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
+neonserv.conf
 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
-$ ${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
 
@@ -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.
 
-  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
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/lib/ini.c
+      src/ConfigParser.c
 
 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 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)
-       @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
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 "lib/ini.h"
+#include "ConfigParser.h"
 
 time_t start_time;
 
@@ -53,40 +53,34 @@ void cleanup() {
 }
 
 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;
-    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;
         }
-        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;
-        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;
         }
-        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;
         }
-        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 {
-        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);