/* * config.cpp -- configuration file parser module * * Copyright (C) 2004 Tony Sin(x) '76 * All rights reserved. * */ /* * GNU GENERAL PUBLIC LICENSE * Version 2, June 1991 * * Copyright (C) 1989, 1991 Free Software Foundation, Inc. * 675 Mass Ave, Cambridge, MA 02139, USA * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* ****************************************************************************** */ /* Configuration file parser */ /* ****************************************************************************** */ #ifdef HAVE_CONFIG_H #ifndef __main_config_h__ #define __main_config_h__ #include "../config.h" #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #endif #include "config.h" cConfig::cConfig() { int i; for (i = ((int) _ip); i < ((int) _badkey); Table[i++] = NULL); } cConfig::cConfig(const char *path) { FILE *fp = fopen(path,"r"); if (fp != NULL) { char line[128]; char key[64]; char value[127]; key_type _key; while (fgets(line,127,fp)) if (!ParseLine(line,key,value) && ((_key = LookupKey(key)) != _badkey)) SetValue(_key,value); fclose(fp); } else { strcpy(ErrStr,"Configuration file does not exist"); throw 0; } } cConfig::~cConfig() { int i; for (i = ((int) _ip); i < ((int) _badkey); i++) if (Table[i] != NULL) delete [] Table[i]; } key_type cConfig::LookupKey(const char *key) const { char *keys[MAX_KEYS] = { "IP", "PORT", "MOUNT", "PASSWORD", "SERVER", "NAME", "GENRE", "DESCRIPTION", "URL", "BITRATE", "PUBLIC", "DUMPFILE", "MP3PATH", "FORMAT", "LOG", "SOURCE", "LOOP", "RECURSIVE", "SHUFFLE", "METAUPDATE", "DATAPORT", "LOGPATH" }; int result; for (result = ((int) _ip); (result < ((int) _badkey)) && (strcmp(key,keys[result])); result++); if (result == _badkey) { strcpy(ErrStr,"Invalid configuration parameter in config file"); throw 0; } else return ((key_type) result); } void cConfig::SetValue(key_type key, const char *value) { if ((value != NULL) && strcmp(value,"")) { if (Table[key] == NULL) Table[key] = new char[strlen(value)+1]; strcpy(Table[key],value); } } char * cConfig::GetValue(key_type key) const { return Table[key]; } int cConfig::ParseLine(const char *buf, char *key, char *value) { int i, idx = 0, err = 0, state = 0; key[0] = '\0'; for (i = 0; (buf[i] && !err); i++) { switch (state) { case 0: if (buf[i] == '#') // initial state err = 1; // signal comment else if (isalpha(buf[i])) { key[idx++] = toupper(buf[i]); // acquire first char of first sequence state = 1; // acquire first sequence state } else if (buf[i] != ' ') // skip initial spaces err = -1; break; case 1: if (buf[i] == ' ') // do not accept more chars state = 2; // on space else if (buf[i] == '=') { key[idx] = '\0'; // on equal, close first sequence, idx = 0; state = 3; // acquire equal state } else if (isalnum(buf[i]) || (buf[i] == '_')) key[idx++] = toupper(buf[i]); // acquire next char of first sequence else err = -1; break; case 2: if (buf[i] == '=') state = 3; // acquire equal state else if (buf[i] != ' ') err = -1; // do not accept anything else but spaces break; case 3: if ((buf[i] != ' ') && !iscntrl(buf[i])) { value[idx++] = buf[i]; state = 4; // acquire second sequence state } break; case 4: if (isalnum(buf[i]) || ispunct(buf[i]) || (buf[i] == ' ')) value[idx++] = buf[i]; // acquire next char of second sequence break; } } if (state == 0) err = 1; value[idx] = '\0'; // close second sequence return err; // signal error code }