--- /dev/null
+/* 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);
+}
#include "IRCQueue.h"
#include "DBHelper.h"
#include "commands.h"
-#include "lib/ini.h"
+#include "ConfigParser.h"
time_t start_time;
}
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);