00001
00002
00003
00004
00005
00006
00007 #include "wvconfemu.h"
00008 #include "wvstringtable.h"
00009 #include "wvfile.h"
00010 #include "strutils.h"
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 static int parse_wvconf_request(char *request, char *§ion,
00030 char *&entry, char *&value)
00031 {
00032 entry = value = NULL;
00033
00034 section = strchr(request, '[');
00035 if (!section)
00036 return -1;
00037
00038 section++;
00039
00040 entry = strchr(section, ']');
00041 if (!entry)
00042 return -2;
00043
00044 *entry++ = 0;
00045
00046 value = strchr(entry, '=');
00047 if (value)
00048 {
00049 *value++ = 0;
00050 value = trim_string(value);
00051 }
00052
00053 section = trim_string(section);
00054 entry = trim_string(entry);
00055
00056 if (!*section)
00057 return -3;
00058
00059 return 0;
00060 }
00061
00062
00063 static void do_setbool(void* userdata,
00064 WvStringParm section, WvStringParm key,
00065 WvStringParm oldval, WvStringParm newval)
00066 {
00067 bool* b = static_cast<bool*>(userdata);
00068
00069 *b = true;
00070 }
00071
00072
00073 static void do_addname(void* userdata,
00074 WvStringParm section, WvStringParm key,
00075 WvStringParm oldval, WvStringParm newval)
00076 {
00077 (*(WvStringList *)userdata).append(new WvString(key), true);
00078 }
00079
00080
00081 static void do_addfile(void* userdata,
00082 WvStringParm section, WvStringParm key,
00083 WvStringParm oldval, WvStringParm newval)
00084 {
00085 WvFile tmp(WvString("/home/%s/%s", key, *(WvString *)userdata),
00086 O_WRONLY | O_CREAT | O_TRUNC, 0600);
00087 if(tmp.isok())
00088 {
00089 if(!!newval)
00090 tmp.print("%s\n", newval);
00091 else
00092 tmp.print("%s\n", key);
00093 }
00094 }
00095
00096
00097 WvConfigEntryEmu *WvConfigSectionEmu::operator[] (WvStringParm s)
00098 {
00099 WvConfigEntryEmu* entry = entries[s];
00100
00101 if (uniconf[s].exists())
00102 {
00103 if (!entry)
00104 {
00105 entry = new WvConfigEntryEmu(s, uniconf[s].get());
00106 entries.add(entry, true);
00107 }
00108 else
00109 entry->value = uniconf[s].get();
00110 }
00111 else
00112 entry = NULL;
00113
00114 return entry;
00115 }
00116
00117
00118 const char *WvConfigSectionEmu::get(WvStringParm entry, const char *def_val)
00119 {
00120 WvString *value = new WvString(uniconf[entry].get(def_val));
00121 values.add(value, true);
00122 return value->cstr();
00123 }
00124
00125
00126 void WvConfigSectionEmu::set(WvStringParm entry, WvStringParm value)
00127 {
00128 uniconf[entry].set(value);
00129 }
00130
00131
00132 void WvConfigSectionEmu::quick_set(WvStringParm entry, WvStringParm value)
00133 {
00134 uniconf[entry].set(value);
00135 }
00136
00137
00138 bool WvConfigSectionEmu::isempty() const
00139 {
00140 return !uniconf.haschildren();
00141 }
00142
00143
00144 WvConfigSectionEmu::Iter::~Iter()
00145 {
00146 }
00147
00148
00149 void WvConfigSectionEmu::Iter::rewind()
00150 {
00151 iter.rewind();
00152 link.data = entry = NULL;
00153 }
00154
00155
00156 WvLink *WvConfigSectionEmu::Iter::next()
00157 {
00158 if (iter.next())
00159 {
00160 entry = sect[iter->key()];
00161 link.data = static_cast<void*>(entry);
00162 return &link;
00163 }
00164
00165 return NULL;
00166 }
00167
00168
00169 WvLink *WvConfigSectionEmu::Iter::cur()
00170 {
00171 return &link;
00172 }
00173
00174
00175 WvConfigEntryEmu* WvConfigSectionEmu::Iter::ptr() const
00176 {
00177 return entry;
00178 }
00179
00180
00181 void* WvConfigSectionEmu::Iter::vptr() const
00182 {
00183 return link.data;
00184 }
00185
00186
00187 void WvConfEmu::notify(const UniConf &_uni, const UniConfKey &_key)
00188 {
00189 WvList<CallbackInfo>::Iter i(callbacks);
00190 WvString section(_key.first());
00191 WvString key(_key.removefirst());
00192
00193 if (hold)
00194 return;
00195
00196 for (i.rewind(); i.next(); )
00197 {
00198 if (((i->section && !i->section) || !strcasecmp(i->section, section))
00199 && ((i->key && !i->key) || !strcasecmp(i->key, key)))
00200 {
00201 WvString value = uniconf[section][key].get("");
00202 i->callback(i->userdata, section, key, i->last, value);
00203 i->last = value;
00204 }
00205 }
00206 }
00207
00208
00209 WvConfEmu::WvConfEmu(const UniConf& _uniconf):
00210 uniconf(_uniconf), sections(42), hold(false)
00211 {
00212 wvauthd = NULL;
00213 uniconf.add_callback(this,
00214 UniConfCallback(this, &WvConfEmu::notify),
00215 true);
00216 }
00217
00218
00219 void WvConfEmu::zap()
00220 {
00221 uniconf.remove();
00222 }
00223
00224
00225 bool WvConfEmu::isok() const
00226 {
00227 return !uniconf.isnull();
00228 }
00229
00230
00231 void WvConfEmu::load_file(WvStringParm filename)
00232 {
00233 UniConfRoot new_uniconf(WvString("ini:%s", filename));
00234
00235 hold = true;
00236 new_uniconf.copy(uniconf, true);
00237 hold = false;
00238 }
00239
00240
00241 void WvConfEmu::save(WvStringParm filename)
00242 {
00243 UniConfRoot tmp_uniconf(WvString("ini:%s", filename));
00244
00245 uniconf.copy(tmp_uniconf, true);
00246 }
00247
00248
00249 void WvConfEmu::save()
00250 {
00251 uniconf.commit();
00252 }
00253
00254
00255 void WvConfEmu::flush()
00256 {
00257 uniconf.commit();
00258 }
00259
00260
00261 WvConfigSectionEmu *WvConfEmu::operator[] (WvStringParm sect)
00262 {
00263 WvConfigSectionEmu* section = sections[sect];
00264
00265 if (!section && uniconf[sect].exists())
00266 {
00267 section = new WvConfigSectionEmu(uniconf[sect], sect);
00268 sections.add(section, true);
00269 }
00270
00271 return section;
00272 }
00273
00274
00275 void WvConfEmu::add_callback(WvConfCallback callback, void *userdata,
00276 WvStringParm section, WvStringParm key,
00277 void *cookie)
00278 {
00279 WvList<CallbackInfo>::Iter i(callbacks);
00280
00281 if (!callback)
00282 return;
00283
00284 for (i.rewind(); i.next(); )
00285 {
00286 if (i->cookie == cookie
00287 && i->section == section
00288 && i->key == key)
00289 return;
00290 }
00291
00292 callbacks.append(new CallbackInfo(callback, userdata, section, key,
00293 cookie, get(section, key, "")),
00294 true);
00295 }
00296
00297
00298 void WvConfEmu::del_callback(WvStringParm section, WvStringParm key, void *cookie)
00299 {
00300 WvList<CallbackInfo>::Iter i(callbacks);
00301
00302 assert(cookie);
00303
00304 for (i.rewind(); i.next(); )
00305 {
00306 if (i->cookie == cookie
00307 && i->section == section
00308 && i->key == key)
00309 i.xunlink();
00310 }
00311 }
00312
00313
00314 void WvConfEmu::add_setbool(bool *b, WvStringParm _section, WvStringParm _key)
00315 {
00316 add_callback(do_setbool, b, _section, _key, b);
00317 }
00318
00319
00320 void WvConfEmu::add_addname(WvStringList *list, WvStringParm sect, WvStringParm ent)
00321 {
00322 add_callback(do_addname, list, sect, ent, list);
00323 }
00324
00325
00326 void WvConfEmu::del_addname(WvStringList *list,
00327 WvStringParm sect, WvStringParm ent)
00328 {
00329 del_callback(sect, ent, list);
00330 }
00331
00332
00333 void WvConfEmu::add_addfile(WvString *filename,
00334 WvStringParm sect, WvStringParm ent)
00335 {
00336 add_callback(do_addfile, filename, sect, ent, NULL);
00337 }
00338
00339
00340 WvString WvConfEmu::getraw(WvString wvconfstr, int &parse_error)
00341 {
00342 char *section, *entry, *value;
00343 parse_error = parse_wvconf_request(wvconfstr.edit(),
00344 section, entry, value);
00345
00346 if (parse_error)
00347 return WvString();
00348
00349 return get(section, entry, value);
00350 }
00351
00352
00353 int WvConfEmu::getint(WvStringParm section, WvStringParm entry, int def_val)
00354 {
00355 return uniconf[section][entry].getint(def_val);
00356 }
00357
00358
00359 const char *WvConfEmu::get(WvStringParm section, WvStringParm entry,
00360 const char *def_val)
00361 {
00362 WvString *value = new WvString(uniconf[section][entry].get(def_val));
00363 values.add(value, true);
00364 return value->cstr();
00365 }
00366
00367 int WvConfEmu::fuzzy_getint(WvStringList §, WvStringParm entry,
00368 int def_val)
00369 {
00370 WvString def_str(def_val);
00371 return check_for_bool_string(fuzzy_get(sect, entry, def_str));
00372 }
00373
00374
00375 const char *WvConfEmu::fuzzy_get(WvStringList §, WvStringParm entry,
00376 const char *def_val)
00377 {
00378 WvStringList::Iter i(sect);
00379 WvStringTable cache(5);
00380 WvConfigSection *s;
00381
00382 for (i.rewind(); i.next(); )
00383 {
00384 for(s = (*this)[*i];
00385 s && !cache[s->name];
00386 s = (*s)["Inherits"] ? (*this)[(*s)["Inherits"]->value] : NULL)
00387 {
00388 const char *ret = s->get(entry);
00389 if (ret) return ret;
00390 cache.add(&s->name, false);
00391 }
00392 }
00393
00394 return def_val;
00395 }
00396
00397 void WvConfEmu::setraw(WvString wvconfstr, const char *&_value,
00398 int &parse_error)
00399 {
00400 char *section, *entry, *value;
00401 parse_error = parse_wvconf_request(wvconfstr.edit(),
00402 section, entry, value);
00403 if (!parse_error)
00404 {
00405 set(section, entry, value);
00406 _value = get(section, entry, value);
00407 }
00408 else
00409 _value = NULL;
00410 }
00411
00412
00413 void WvConfEmu::setint(WvStringParm section, WvStringParm entry, int value)
00414 {
00415 uniconf[section][entry].setint(value);
00416 }
00417
00418
00419 void WvConfEmu::set(WvStringParm section, WvStringParm entry,
00420 const char *value)
00421 {
00422 uniconf[section][entry].set(value);
00423 }
00424
00425
00426 void WvConfEmu::maybesetint(WvStringParm section, WvStringParm entry,
00427 int value)
00428 {
00429 if (!get(section, entry, NULL))
00430 setint(section, entry, value);
00431 }
00432
00433
00434 void WvConfEmu::maybeset(WvStringParm section, WvStringParm entry,
00435 const char *value)
00436 {
00437 if (get(section, entry, 0) == 0)
00438 set(section, entry, value);
00439 }
00440
00441
00442 void WvConfEmu::delete_section(WvStringParm section)
00443 {
00444 uniconf[section].set(WvString::null);
00445 }
00446
00447
00448 int WvConfEmu::check_for_bool_string(const char *s)
00449 {
00450 if (strcasecmp(s, "off") == 0
00451 || strcasecmp(s, "false") == 0
00452 || strncasecmp(s, "no", 2) == 0)
00453 return (0);
00454
00455 if (strcasecmp(s, "on") == 0
00456 || strcasecmp(s, "true") == 0
00457 || strcasecmp(s, "yes") == 0)
00458 return (1);
00459
00460
00461 return (atoi(s));
00462 }
00463
00464
00465 void WvConfEmu::Iter::rewind()
00466 {
00467 iter.rewind();
00468 link.data = NULL;
00469 }
00470
00471
00472 WvLink *WvConfEmu::Iter::next()
00473 {
00474 if (iter.next())
00475 {
00476 link.data = static_cast<void*>(conf[iter->key()]);
00477 return &link;
00478 }
00479
00480 return NULL;
00481 }
00482
00483
00484 WvConfigSectionEmu* WvConfEmu::Iter::ptr() const
00485 {
00486 return conf[iter->key()];
00487 }
00488