00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include "config.h"
00021 #endif
00022
00023 #include <stdio.h>
00024 #include "Configuration.h"
00025 #include "htString.h"
00026 #include "ParsedString.h"
00027
00028 #include <stdlib.h>
00029 #include <ctype.h>
00030 #include <locale.h>
00031
00032
00033
00034
00035
00036 Configuration::Configuration()
00037 {
00038 separators = String("=:");
00039 allow_multiple = 0;
00040 }
00041
00042 Configuration::Configuration(const Configuration& other) : Object()
00043 {
00044 separators = other.separators;
00045 allow_multiple = other.allow_multiple;
00046
00047 DictionaryCursor cursor;
00048 const char* key;
00049 for(other.dcGlobalVars.Start_Get(cursor); (key = other.dcGlobalVars.Get_Next(cursor));) {
00050 Add(key, other[key]);
00051 }
00052 }
00053
00054
00055
00056
00057 void Configuration::NameValueSeparators(const String& s)
00058 {
00059 separators = s;
00060 }
00061
00062
00063
00064
00065
00066 void Configuration::Add(const String& str_arg)
00067 {
00068 const char* str = str_arg;
00069 String name, value;
00070
00071 while (str && *str)
00072 {
00073 while (isspace(*str))
00074 str++;
00075 name = 0;
00076 if (!isalpha(*str))
00077 break;
00078
00079
00080
00081 if (!isalnum(*str))
00082 break;
00083 while (isalnum(*str) || *str == '-' || *str == '_')
00084 name << *str++;
00085
00086 name.lowercase();
00087
00088
00089
00090
00091 while (isspace(*str))
00092 str++;
00093 if (!*str)
00094 {
00095
00096
00097
00098 Add(name, "true");
00099 return;
00100 }
00101
00102 if (!strchr((char*)separators, *str))
00103 {
00104
00105
00106
00107
00108 Add(name, "true");
00109 continue;
00110 }
00111
00112
00113
00114
00115 str++;
00116 while (isspace(*str))
00117 str++;
00118 if (!*str)
00119 {
00120
00121
00122
00123 Add(name, "");
00124 break;
00125 }
00126 value = 0;
00127 if (*str == '"')
00128 {
00129
00130
00131
00132
00133 str++;
00134 while (*str && *str != '"')
00135 {
00136 value << *str++;
00137 }
00138 Add(name, value);
00139 if (*str == '"')
00140 str++;
00141 continue;
00142 }
00143 else if (*str == '\'')
00144 {
00145
00146 str++;
00147 while (*str && *str != '\'')
00148 {
00149 value << *str++;
00150 }
00151 Add(name, value);
00152 if (*str == '\'')
00153 str++;
00154 continue;
00155 }
00156 else
00157 {
00158
00159
00160
00161
00162 while (*str && !isspace(*str))
00163 {
00164 value << *str++;
00165 }
00166 Add(name, value);
00167 continue;
00168 }
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177 void Configuration::Add(const String& name, const String& value)
00178 {
00179 String escaped;
00180 const char *s = value.get();
00181 while (*s)
00182 {
00183 if (strchr("$`\\", *s))
00184 escaped << '\\';
00185 escaped << *s++;
00186 }
00187 ParsedString *ps = new ParsedString(escaped);
00188 dcGlobalVars.Add(name, ps);
00189 }
00190
00191
00192
00193
00194
00195
00196 void Configuration::AddParsed(const String& name, const String& value)
00197 {
00198 ParsedString *ps = new ParsedString(value);
00199 if (strcasecmp(name, "locale") == 0)
00200 {
00201 String str(setlocale(LC_ALL, ps->get(dcGlobalVars)));
00202 ps->set(str);
00203
00204
00205
00206
00207
00208
00209 setlocale(LC_TIME, "C");
00210 }
00211 dcGlobalVars.Add(name, ps);
00212 }
00213
00214
00215
00216
00217
00218 int Configuration::Remove(const String& name)
00219 {
00220 return dcGlobalVars.Remove(name);
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 const String Configuration::Find(const String& name) const
00230 {
00231 ParsedString *ps = (ParsedString *) dcGlobalVars[name];
00232 if (ps)
00233 {
00234 return ps->get(dcGlobalVars);
00235 }
00236 else
00237 {
00238 #ifdef DEBUG_CONFIGURATION
00239 fprintf (stderr, "Could not find configuration option %s\n", (const char*)name);
00240 #endif
00241 return 0;
00242 }
00243 }
00244
00245
00246 Object *Configuration::Get_Object(char *name) {
00247 return dcGlobalVars[name];
00248 }
00249
00250
00251
00252
00253 int Configuration::Value(const String& name, int default_value) const
00254 {
00255 return Find(name).as_integer(default_value);
00256 }
00257
00258
00259
00260
00261 double Configuration::Double(const String& name, double default_value) const
00262 {
00263 return Find(name).as_double(default_value);
00264 }
00265
00266
00267
00268
00269
00270 int Configuration::Boolean(const String& name, int default_value) const
00271 {
00272 int value = default_value;
00273 const String s = Find(name);
00274 if (s[0])
00275 {
00276 if (s.nocase_compare("true") == 0 ||
00277 s.nocase_compare("yes") == 0 ||
00278 s.nocase_compare("1") == 0)
00279 value = 1;
00280 else if (s.nocase_compare("false") == 0 ||
00281 s.nocase_compare("no") == 0 ||
00282 s.nocase_compare("0") == 0)
00283 value = 0;
00284 }
00285
00286 return value;
00287 }
00288
00289
00290
00291
00292 const String Configuration::operator[](const String& name) const
00293 {
00294 return Find(name);
00295 }
00296
00297
00298
00299
00300 int Configuration::Read(const String& filename)
00301 {
00302 FILE* in = fopen((const char*)filename, "r");
00303
00304 if(!in) {
00305 fprintf(stderr, "Configuration::Read: cannot open %s for reading : ", (const char*)filename);
00306 perror("");
00307 return NOTOK;
00308 }
00309
00310 #define CONFIG_BUFFER_SIZE (50*1024)
00311
00312
00313
00314
00315 char buffer[CONFIG_BUFFER_SIZE + 1];
00316 char *current;
00317 String line;
00318 String name;
00319 char *value;
00320 int len;
00321 while (fgets(buffer, CONFIG_BUFFER_SIZE, in))
00322 {
00323 line << buffer;
00324 line.chop("\r\n");
00325 if (line.last() == '\\')
00326 {
00327 line.chop(1);
00328 continue;
00329 }
00330
00331 current = line.get();
00332 if (*current == '#' || *current == '\0')
00333 {
00334 line = 0;
00335 continue;
00336 }
00337
00338 name = strtok(current, ": =\t");
00339 value = strtok(0, "\r\n");
00340 if (!value)
00341 value = "";
00342
00343
00344
00345
00346 while (*value == ' ' || *value == '\t')
00347 value++;
00348 len = strlen(value) - 1;
00349
00350
00351
00352 while (value[len] == ' ' || value[len] == '\t')
00353 {
00354 value[len] = '\0';
00355 len--;
00356 }
00357
00358 if (strcasecmp((char*)name, "include") == 0)
00359 {
00360 ParsedString ps(value);
00361 String str(ps.get(dcGlobalVars));
00362 if (str[0] != '/')
00363 {
00364 str = filename;
00365 len = str.lastIndexOf('/') + 1;
00366 if (len > 0)
00367 str.chop(str.length() - len);
00368 else
00369 str = "";
00370 str << ps.get(dcGlobalVars);
00371 }
00372 Read(str);
00373 line = 0;
00374 continue;
00375 }
00376
00377 AddParsed(name, value);
00378 line = 0;
00379 }
00380 fclose(in);
00381 return OK;
00382 }
00383
00384
00385
00386
00387
00388 void Configuration::Defaults(const ConfigDefaults *array)
00389 {
00390 for (int i = 0; array[i].name; i++)
00391 {
00392 AddParsed(array[i].name, array[i].value);
00393 }
00394 }
00395