added new self-made config parser with new config style
authorpk910 <philipp@zoelle1.de>
Sun, 6 Nov 2011 07:55:58 +0000 (08:55 +0100)
committerpk910 <philipp@zoelle1.de>
Sun, 6 Nov 2011 08:23:52 +0000 (09:23 +0100)
.gitignore
INSTALL
Makefile.am
neonserv.example.conf [new file with mode: 0644]
neonserv.example.ini [deleted file]
src/ConfigParser.c [new file with mode: 0644]
src/ConfigParser.h [new file with mode: 0644]
src/main.c

index ed4e2b541ca599db011dd48e0455717f30b36421..2dee84763659cf9c41cf830344bf2bb2e52dbbe1 100644 (file)
@@ -1,5 +1,6 @@
 mysqlConfig.h
 neonserv.ini
 mysqlConfig.h
 neonserv.ini
+neonserv.conf
 src/version.c
 src/version.php
 src/.deps
 src/version.c
 src/version.php
 src/.deps
diff --git a/INSTALL b/INSTALL
index 6ac9d235434e7bfe31a2302452ba8ca28c589fa5..dc48fed7f73de93fbe31f6d16f8aa7b46a418049 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -17,8 +17,8 @@ Quick Install:
 $ ./autogen.sh
 $ ./configure
 $ make
 $ ./autogen.sh
 $ ./configure
 $ make
-$ ${EDITOR} neonserv.ini
-    NOTE: You may want to copy neonserv.example.ini to neonserv.ini and
+$ ${EDITOR} neonserv.conf
+    NOTE: You may want to copy neonserv.example.conf to neonserv.conf and
     edit that.
 $ ./neonserv
 
     edit that.
 $ ./neonserv
 
@@ -50,7 +50,7 @@ Compiling:
   6) You may now either type "make install" to install it to your
      installation path, or work from your build directory, either is fine.
 
   6) You may now either type "make install" to install it to your
      installation path, or work from your build directory, either is fine.
 
-  7) Copy neonserv.example.ini to neonserv.ini and edit the mysql information.
+  7) Copy neonserv.example.conf to neonserv.conf and edit the mysql information.
 
  10) Once you have NeonServ for the first time, it will create the neccesary
      tables in your database. Take a look into `bots` to edit Bot settings like
 
  10) Once you have NeonServ for the first time, it will create the neccesary
      tables in your database. Take a look into `bots` to edit Bot settings like
index 0c8c81d881ac0dea81a06e65b88bc46f97316caf..89c9ff02821d1bebc6a9cd439d33d16ed54a3b76 100644 (file)
@@ -115,7 +115,7 @@ neonserv_SOURCES = src/version.c \
       src/cmd_neonserv_noregister.c \
       src/cmd_global_staff.c \
       src/cmd_funcmds.c \
       src/cmd_neonserv_noregister.c \
       src/cmd_global_staff.c \
       src/cmd_funcmds.c \
-      src/lib/ini.c
+      src/ConfigParser.c
 
 neonserv_LDADD = $(MYSQL_LIBS) $(WINSOCK_LIBS)
 
 
 neonserv_LDADD = $(MYSQL_LIBS) $(WINSOCK_LIBS)
 
@@ -125,10 +125,10 @@ install-exec-local:
        $(INSTALL) -m 644 $(srcdir)/database.sql $(prefix)
        $(INSTALL) -m 644 $(srcdir)/database.upgrade.sql $(prefix)
        $(INSTALL) -m 644 $(srcdir)/database.defaults.sql $(prefix)
        $(INSTALL) -m 644 $(srcdir)/database.sql $(prefix)
        $(INSTALL) -m 644 $(srcdir)/database.upgrade.sql $(prefix)
        $(INSTALL) -m 644 $(srcdir)/database.defaults.sql $(prefix)
-       $(INSTALL) -m 600 $(srcdir)/neonserv.example.ini $(prefix)
+       $(INSTALL) -m 600 $(srcdir)/neonserv.example.conf $(prefix)
        $(INSTALL) -m 744 $(srcdir)/language.php $(prefix)
        @echo
        @echo NeonServ-$(VERSION) has been installed to $(prefix)
        $(INSTALL) -m 744 $(srcdir)/language.php $(prefix)
        @echo
        @echo NeonServ-$(VERSION) has been installed to $(prefix)
-       @echo Edit the neonserv.example.ini and save it as neonserv.ini before you start!
+       @echo Edit the neonserv.example.conf and save it as neonserv.conf before you start!
        @echo You should use an own database for this Bot - table names are NOT prefixed!
        @echo
        @echo You should use an own database for this Bot - table names are NOT prefixed!
        @echo
diff --git a/neonserv.example.conf b/neonserv.example.conf
new file mode 100644 (file)
index 0000000..99775ae
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+  NeonServ example configuration
+*/
+
+"MySQL" {
+    "host" = "127.0.0.1 ";
+    "port" = 3306;
+    "user" = "neonserv";
+    "pass" = "password";
+    "base" = "neonserv";
+};
\ No newline at end of file
diff --git a/neonserv.example.ini b/neonserv.example.ini
deleted file mode 100644 (file)
index 997d5ce..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-[MySQL]
-host = 127.0.0.1 
-port = 3306
-user = neonserv 
-pass = password 
-base = neonserv 
diff --git a/src/ConfigParser.c b/src/ConfigParser.c
new file mode 100644 (file)
index 0000000..775e062
--- /dev/null
@@ -0,0 +1,316 @@
+/* ConfigParser.c - NeonServ v5.2
+ * Copyright (C) 2011  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#include "ConfigParser.h"
+
+#define ENTRYTYPE_BLOCK   1
+#define ENTRYTYPE_STRING  2
+#define ENTRYTYPE_INTEGER 3
+
+struct ConfigEntry {
+    char *name;
+    int type;
+    void *value;
+    struct ConfigEntry *next;
+};
+
+static struct ConfigEntry *root_entry = NULL;
+
+static char *parse_config_recursive(struct ConfigEntry *centry, char *buffer, int root_element);
+static void free_entry_rekursiv(struct ConfigEntry *centry, int is_root_entry);
+
+int loadConfig(const char *filename) {
+    FILE *f;
+    f = fopen(filename, "rb");
+    if(!f) return 0;
+    
+    // obtain file size:
+    long lSize;
+    fseek (f, 0, SEEK_END);
+    lSize = ftell(f);
+    rewind(f);
+    
+    // allocate memory to contain the whole file:
+    char *buffer = (char*) malloc (sizeof(char)*lSize + 1);
+    if (buffer == NULL) return 0;
+    
+    // copy the file into the buffer:
+    size_t result = fread (buffer, 1, lSize, f);
+    if (result != lSize) return 0;
+    buffer[lSize] = '\0';
+    
+    // now parse the config file...
+    if(root_entry) {
+        free_loaded_config();
+    }
+    root_entry = malloc(sizeof(*root_entry));
+    if (!root_entry) return 0;
+    parse_config_recursive(root_entry, buffer, 1);
+    
+    // free the buffer...
+    free(buffer);
+    return 1;
+}
+
+#define PARSER_FLAG_ESCAPED    0x01
+#define PARSER_FLAG_BLOCK      0x02
+#define PARSER_FLAG_STRING     0x04
+#define PARSER_FLAG_EXPECT_END 0x08
+#define PARSER_FLAG_NEXTCHAR   0x10
+#define PARSER_FLAG_INTEGER    0x20
+#define PARSER_FLAG_EOBN       0x40 /* End of Block name */
+#define PARSER_FLAG_COMMAND    0x80
+static char *parse_config_recursive(struct ConfigEntry *centry, char *buffer, int root_element) {
+    int flags = 0;
+    int type = (root_element ? ENTRYTYPE_BLOCK : 0);
+    char cbuf[1024];
+    int cbufpos = 0;
+    struct ConfigEntry *sub_entrys = NULL;
+    while(*buffer) {
+        if(flags & PARSER_FLAG_NEXTCHAR) {
+            buffer++;
+            if(*buffer == '\0')
+                break;
+        }
+        flags |= PARSER_FLAG_NEXTCHAR;
+        if(flags & PARSER_FLAG_EOBN) {
+            flags &= ~(PARSER_FLAG_EOBN | PARSER_FLAG_NEXTCHAR);
+            struct ConfigEntry *new_entry = malloc(sizeof(*new_entry));
+            if (!new_entry) return buffer;
+            new_entry->name = strdup(cbuf);
+            buffer = parse_config_recursive(new_entry, buffer, 0);
+            if(sub_entrys)
+                new_entry->next = sub_entrys;
+            else
+                new_entry->next = NULL;
+            sub_entrys = new_entry;
+            centry->value = sub_entrys;
+        }
+        if(flags & PARSER_FLAG_ESCAPED) {
+            cbuf[cbufpos++] = *buffer;
+            flags &= ~PARSER_FLAG_ESCAPED;
+            continue;
+        }
+        if(flags & PARSER_FLAG_EXPECT_END) {
+            if(*buffer == ';') {
+                centry->type = type;
+                return (buffer+1);
+            }
+            continue;
+        }
+        if(flags & PARSER_FLAG_STRING) {
+            if(*buffer == '"') {
+                cbuf[cbufpos] = '\0';
+                flags &= ~PARSER_FLAG_STRING;
+                if(type == ENTRYTYPE_STRING) {
+                    flags |= PARSER_FLAG_EXPECT_END;
+                    centry->value = strdup(cbuf);
+                } else if(type == ENTRYTYPE_BLOCK) {
+                    flags |= PARSER_FLAG_EOBN;
+                }
+            } else if(*buffer == '\\')
+                flags |= PARSER_FLAG_ESCAPED;
+            else
+                cbuf[cbufpos++] = *buffer;
+            continue;
+        }
+        if(flags & PARSER_FLAG_INTEGER) {
+            if(!isdigit(*buffer)) {
+                cbuf[cbufpos] = '\0';
+                flags &= ~PARSER_FLAG_INTEGER;
+                if(type == ENTRYTYPE_INTEGER) {
+                    flags |= PARSER_FLAG_EXPECT_END;
+                    int *intbuf = malloc(sizeof(int));
+                    *intbuf = atoi(cbuf);
+                    centry->value = intbuf;
+                }
+                if(*buffer == ';') {
+                    centry->type = type;
+                    return (buffer+1);
+                }
+            } else
+                cbuf[cbufpos++] = *buffer;
+            continue;
+        }
+        if(flags & PARSER_FLAG_COMMAND) {
+            int found_command = 0;
+            switch(*buffer) {
+                case '/':
+                    buffer = strstr(buffer, "\n");
+                    found_command = 1;
+                    break;
+                case '*':
+                    //simple search for the next */
+                    buffer = strstr(buffer, "*/")+1;
+                    found_command = 1;
+            }
+            flags &= ~PARSER_FLAG_COMMAND;
+            if(found_command)
+                continue;
+        }
+        switch(*buffer) {
+            case '\\':
+                flags |= PARSER_FLAG_ESCAPED;
+                break;
+            case '/':
+                if(!(flags & PARSER_FLAG_STRING)) {
+                    flags |= PARSER_FLAG_COMMAND;
+                }
+                break;
+            case '{':
+                flags |= PARSER_FLAG_BLOCK;
+                type = ENTRYTYPE_BLOCK;
+                break;
+            case '}':
+                if(flags & PARSER_FLAG_BLOCK)
+                    flags &= ~PARSER_FLAG_BLOCK;
+                flags |= PARSER_FLAG_EXPECT_END;
+                break;
+            case '"':
+                flags |= PARSER_FLAG_STRING;
+                if(!type)
+                    type = ENTRYTYPE_STRING;
+                cbufpos = 0;
+                break;
+            case ';':
+                centry->type = type;
+                return (buffer+1);
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                if(!type)
+                    type = ENTRYTYPE_INTEGER;
+                flags |= PARSER_FLAG_INTEGER;
+                cbufpos = 0;
+                cbuf[cbufpos++] = *buffer;
+                break;
+            default:
+                break;
+        }
+    }
+    centry->type = type;
+    return buffer; //end of the buffer
+}
+
+int get_int_field(char *field_path) {
+    struct ConfigEntry *centry = root_entry;
+    char *a, *b = field_path;
+    struct ConfigEntry *subentry;
+    while((a = strstr(b, ".")) && centry) {
+        if(centry->type == ENTRYTYPE_BLOCK) {
+            int found = 0;
+            for(subentry = centry->value; subentry; subentry = subentry->next) {
+                if(!stricmplen(subentry->name, b, a-b)) {
+                    centry = subentry;
+                    found = 1;
+                    break;
+                }
+            }
+            if(!found)
+                return 0;
+        } else
+            return 0;
+        b = a+1;
+    }
+    if(centry->type == ENTRYTYPE_BLOCK) {
+        int found = 0;
+        for(subentry = centry->value; subentry; subentry = subentry->next) {
+            if(!stricmp(subentry->name, b)) {
+                centry = subentry;
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            return 0;
+    } else
+        return 0;
+    if(centry->type == ENTRYTYPE_INTEGER)
+        return ((int *)centry->value)[0];
+    else
+        return 0;
+}
+
+char *get_string_field(char *field_path) {
+    struct ConfigEntry *centry = root_entry;
+    char *a, *b = field_path;
+    struct ConfigEntry *subentry;
+    while((a = strstr(b, ".")) && centry) {
+        if(centry->type == ENTRYTYPE_BLOCK) {
+            int found = 0;
+            for(subentry = centry->value; subentry; subentry = subentry->next) {
+                if(!stricmplen(subentry->name, b, a-b)) {
+                    centry = subentry;
+                    found = 1;
+                    break;
+                }
+            }
+            if(!found)
+                return NULL;
+        } else
+            return NULL;
+        b = a+1;
+    }
+    if(centry->type == ENTRYTYPE_BLOCK) {
+        int found = 0;
+        for(subentry = centry->value; subentry; subentry = subentry->next) {
+            if(!stricmp(subentry->name, b)) {
+                centry = subentry;
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            return NULL;
+    } else
+        return NULL;
+    if(centry->type == ENTRYTYPE_STRING)
+        return centry->value;
+    else
+        return NULL;
+}
+
+void free_loaded_config() {
+    if(root_entry) {
+        free_entry_rekursiv(root_entry, 1);
+        root_entry = NULL;
+    }
+}
+
+static void free_entry_rekursiv(struct ConfigEntry *centry, int is_root_entry) {
+    if(centry->type == ENTRYTYPE_BLOCK) {
+        struct ConfigEntry *subentry, *nextentry;
+        for(subentry = centry->value; subentry; subentry = nextentry) {
+            nextentry = subentry->next;
+            free_entry_rekursiv(subentry, 0);
+        }
+    } else if(centry->type == ENTRYTYPE_STRING) {
+        free(centry->value);
+    } else if(centry->type == ENTRYTYPE_INTEGER) {
+        free(centry->value);
+    }
+    if(!is_root_entry)
+        free(centry->name);
+    free(centry);
+}
diff --git a/src/ConfigParser.h b/src/ConfigParser.h
new file mode 100644 (file)
index 0000000..1657765
--- /dev/null
@@ -0,0 +1,27 @@
+/* ConfigParser.h - NeonServ v5.2
+ * Copyright (C) 2011  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef _ConfigParser_h
+#define _ConfigParser_h
+#include "main.h"
+
+int loadConfig(const char *filename);
+int get_int_field(char *field_path);
+char *get_string_field(char *field_path);
+void free_loaded_config();
+
+#endif
\ No newline at end of file
index d6258a7598e5fce77fdb7b4116f27c68a681d30b..183ebaedb3e1e205215b51ed0a8c7395d9beb91d 100644 (file)
@@ -34,7 +34,7 @@
 #include "IRCQueue.h"
 #include "DBHelper.h"
 #include "commands.h"
 #include "IRCQueue.h"
 #include "DBHelper.h"
 #include "commands.h"
-#include "lib/ini.h"
+#include "ConfigParser.h"
 
 time_t start_time;
 
 
 time_t start_time;
 
@@ -53,40 +53,34 @@ void cleanup() {
 }
 
 static int load_mysql_config() {
 }
 
 static int load_mysql_config() {
-    char mysql_host[MAXLEN], mysql_port_str[MAXLEN], mysql_user[MAXLEN], mysql_pass[MAXLEN], mysql_base[MAXLEN];
+    char *mysql_host, *mysql_user, *mysql_pass, *mysql_base;
     int mysql_serverport;
     int mysql_serverport;
-    if(loadINI("neonserv.ini") == FILE_SUCCESS) {
-        mysql_host[0] = '\0';
-        ReadString("MySQL", "host", mysql_host);
-        if(!*mysql_host) {
-            perror("invalid neonserv.ini: missing MySQL host");
+    if(loadConfig("neonserv.conf")) {
+        mysql_host = get_string_field("MySQL.host");
+        if(!mysql_host) {
+            perror("invalid neonserv.conf: missing MySQL.host");
             return 0;
         }
             return 0;
         }
-        mysql_port_str[0] = '\0';
-        ReadString("MySQL", "port", mysql_port_str);
-        mysql_serverport = atoi(mysql_port_str);
+        mysql_serverport = get_int_field("MySQL.port");
         if(!mysql_serverport)
             mysql_serverport = 3306;
         if(!mysql_serverport)
             mysql_serverport = 3306;
-        mysql_user[0] = '\0';
-        ReadString("MySQL", "user", mysql_user);
-        if(!*mysql_user) {
-            perror("invalid neonserv.ini: missing MySQL user");
+        mysql_user = get_string_field("MySQL.user");
+        if(!mysql_user) {
+            perror("invalid neonserv.conf: missing MySQL.user");
             return 0;
         }
             return 0;
         }
-        mysql_pass[0] = '\0';
-        ReadString("MySQL", "pass", mysql_pass);
-        if(!*mysql_pass) {
-            perror("invalid neonserv.ini: missing MySQL pass");
+        mysql_pass = get_string_field("MySQL.pass");
+        if(!mysql_pass) {
+            perror("invalid neonserv.conf: missing MySQL.pass");
             return 0;
         }
             return 0;
         }
-        mysql_base[0] = '\0';
-        ReadString("MySQL", "base", mysql_base);
-        if(!*mysql_base) {
-            perror("invalid neonserv.ini: missing MySQL base");
+        mysql_base = get_string_field("MySQL.base");
+        if(!mysql_base) {
+            perror("invalid neonserv.conf: missing MySQL base");
             return 0;
         }
     } else {
             return 0;
         }
     } else {
-        perror("Unable to load neonserv.ini");
+        perror("Unable to load neonserv.conf");
         return 0;
     }
     init_mysql(mysql_host, mysql_serverport, mysql_user, mysql_pass, mysql_base);
         return 0;
     }
     init_mysql(mysql_host, mysql_serverport, mysql_user, mysql_pass, mysql_base);