Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htreg.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htreg.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <errno.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 
00025 #include "defreg.h"
00026 #include "htatom.h"
00027 #include "htctrl.h"
00028 #include "htdialog.h"
00029 #include "htio.h"
00030 #include "htiobox.h"
00031 #include "htreg.h"
00032 #include "log.h"
00033 #include "snprintf.h"
00034 #include "store.h"
00035 #include "tools.h"
00036 
00037 ht_registry *registry;
00038 
00039 #define ATOM_HT_REGISTRY                                MAGICD("REG\x00")
00040 #define ATOM_HT_REGISTRY_NODE                   MAGICD("REG\x01")
00041 #define ATOM_HT_REGISTRY_DATA_STREE     MAGICD("REG\x02")
00042 #define ATOM_HT_REGISTRY_DATA_DWORD     MAGICD("REG\x03")
00043 #define ATOM_HT_REGISTRY_DATA_RAW               MAGICD("REG\x04")
00044 #define ATOM_HT_REGISTRY_DATA_STRING    MAGICD("REG\x05")
00045 #define ATOM_HT_REGISTRY_NODE_TYPE_DESC MAGICD("REG\x10")
00046 #define ATOM_HT_CREATE_EMPTY_SUBDIR     MAGICD("REG\x20")
00047 #define ATOM_HT_CREATE_EMPTY_SYMLINK    MAGICD("REG\x21")
00048 #define ATOM_HT_CREATE_EMPTY_DWORD              MAGICD("REG\x22")
00049 #define ATOM_HT_CREATE_EMPTY_STRING     MAGICD("REG\x23")
00050 #define ATOM_HT_CREATE_EMPTY_RAW                MAGICD("REG\x24")
00051 
00052 /*
00053  *      CLASS ht_registry_data
00054  */
00055 
00056 bool ht_registry_data::editdialog(const char *keyname)
00057 {
00058         return false;
00059 }
00060 
00061 void ht_registry_data::strvalue(char *buf32bytes)
00062 {
00063         strcpy(buf32bytes, "<unknown>");
00064 }
00065 
00066 /*
00067  *      CLASS ht_registry_data_stree
00068  */
00069 
00070 ht_registry_data_stree::ht_registry_data_stree(ht_stree *t)
00071 {
00072         tree = t;
00073 }
00074 
00075 ht_registry_data_stree::~ht_registry_data_stree()
00076 {
00077         if (tree) {
00078                 tree->destroy();
00079                 delete tree;
00080         }
00081 }
00082 
00083 int ht_registry_data_stree::load(ht_object_stream *f)
00084 {
00085         if (!(tree = (ht_stree*)f->getObject("tree"))) return 1;
00086         return f->get_error();
00087 }
00088 
00089 OBJECT_ID ht_registry_data_stree::object_id() const
00090 {
00091         return ATOM_HT_REGISTRY_DATA_STREE;
00092 }
00093 
00094 void ht_registry_data_stree::store(ht_object_stream *f)
00095 {
00096         f->putObject(tree, "tree");
00097 }
00098 
00099 void ht_registry_data_stree::strvalue(char *buf32bytes)
00100 {
00101         *buf32bytes = 0;
00102 }
00103 
00104 /*
00105  *      CLASS ht_registry_data_dword
00106  */
00107 
00108 ht_registry_data_dword::ht_registry_data_dword(dword v)
00109 {
00110         value = v;
00111 }
00112 
00113 bool ht_registry_data_dword::editdialog(const char *keyname)
00114 {
00115 // FIXME: use eval instead of strtol
00116         char result[32];
00117         ht_snprintf(result, sizeof result, "%d", value);
00118         if (inputbox("edit dword", "number", result, sizeof result, 0)==button_ok) {
00119                 char *r;
00120                 int i = (int)strtol(result, &r, 10);
00121                 if (*r == 0) {
00122                         value = i;
00123                         return true;
00124                 }
00125         }
00126         return false;
00127 }
00128 
00129 int ht_registry_data_dword::load(ht_object_stream *f)
00130 {
00131         value = f->getIntHex(4, "dword");
00132         return f->get_error();
00133 }
00134 
00135 OBJECT_ID ht_registry_data_dword::object_id() const
00136 {
00137         return ATOM_HT_REGISTRY_DATA_DWORD;
00138 }
00139 
00140 void ht_registry_data_dword::store(ht_object_stream *f)
00141 {
00142         f->putIntHex(value, 4, "dword");
00143 }
00144 
00145 void ht_registry_data_dword::strvalue(char *buf32bytes)
00146 {
00147         ht_snprintf(buf32bytes, 32, "%d", value);
00148 }
00149 
00150 /*
00151  *      CLASS ht_registry_data_raw
00152  */
00153 
00154 ht_registry_data_raw::ht_registry_data_raw(const void *v, UINT s)
00155 {
00156         size = s;
00157         if (size) {
00158                 value = malloc(s);
00159                 memmove(value, v, s);
00160         } else {
00161                 value = 0;
00162         }
00163 }
00164 
00165 ht_registry_data_raw::~ht_registry_data_raw()
00166 {
00167         if (value) free(value);
00168 }
00169 
00170 bool ht_registry_data_raw::editdialog(const char *keyname)
00171 {
00172         bool r = false;
00173         bounds b;
00174         b.w = 50;
00175         b.h = 15;
00176         b.x = (screen->size.w-b.w)/2;
00177         b.y = (screen->size.h-b.h)/2;
00178         
00179         ht_dialog *d = new ht_dialog();
00180         d->init(&b, "edit data_raw", FS_TITLE | FS_KILLER);
00181         
00182         if (d->run(false)) {
00183                 r = true;
00184         }
00185         
00186         d->done();
00187         delete d;
00188         return r;
00189 }
00190 
00191 int ht_registry_data_raw::load(ht_object_stream *f)
00192 {
00193         size = f->getIntDec(4, "size");
00194         value = f->getBinary(size, NULL);
00195         return f->get_error();
00196 }
00197 
00198 OBJECT_ID ht_registry_data_raw::object_id() const
00199 {
00200         return ATOM_HT_REGISTRY_DATA_RAW;
00201 }
00202 
00203 void ht_registry_data_raw::store(ht_object_stream *f)
00204 {
00205         f->putIntDec(size, 4, "size");
00206         f->putBinary(value, size, NULL);
00207 }
00208 
00209 void ht_registry_data_raw::strvalue(char *buf32bytes)
00210 {
00211         strcpy(buf32bytes, "raw");
00212 }
00213 
00214 /*
00215  *      CLASS ht_registry_data_string
00216  */
00217 
00218 ht_registry_data_string::ht_registry_data_string(const char *s)
00219 {
00220         value = ht_strdup(s);
00221 }
00222 
00223 ht_registry_data_string::~ht_registry_data_string()
00224 {
00225         if (value) free(value);
00226 }
00227 
00228 bool ht_registry_data_string::editdialog(const char *keyname)
00229 {
00230         char res[256];
00231         strncpy(res, value, 255);
00232         res[255] = 0;
00233         if (inputbox("edit string", "string", res, 256, 0)) {
00234                 if (value) delete value;
00235                 value = strdup(res);
00236                 return true;
00237         }
00238         return false;
00239 }
00240 
00241 int ht_registry_data_string::load(ht_object_stream *f)
00242 {
00243         value = f->getString("string");
00244         return f->get_error();
00245 }
00246 
00247 OBJECT_ID ht_registry_data_string::object_id() const
00248 {
00249         return ATOM_HT_REGISTRY_DATA_STRING;
00250 }
00251 
00252 void ht_registry_data_string::store(ht_object_stream *f)
00253 {
00254         f->putString(value, "string");
00255 }
00256 
00257 void ht_registry_data_string::strvalue(char *buf32bytes)
00258 {
00259         strncpy(buf32bytes, value, 31);
00260         buf32bytes[31] = 0;
00261 }
00262 
00263 /*
00264  *      CLASS ht_registry_node
00265  */
00266 
00267 void ht_registry_node::init(ht_registry_node_type Type)
00268 {
00269         type = Type;
00270         data = NULL;
00271 }
00272 
00273 void ht_registry_node::done()
00274 {
00275         if (data) {
00276                 data->done();
00277                 delete data;
00278         }
00279 }
00280 
00281 int ht_registry_node::load(ht_object_stream *f)
00282 {
00283         type = f->getIntHex(4, "type");
00284         if (!(data = (ht_registry_data*)f->getObject(NULL))) return 1;
00285         return f->get_error();
00286 }
00287 
00288 void ht_registry_node::store(ht_object_stream *f)
00289 {
00290         f->putIntHex(type, 4, "type");
00291         f->putObject(data, NULL);
00292 }
00293 
00294 OBJECT_ID ht_registry_node::object_id() const
00295 {
00296         return ATOM_HT_REGISTRY_NODE;
00297 }
00298 
00299 /*
00300  *      create_empty_*
00301  */
00302 
00303 ht_registry_data *create_empty_symlink()
00304 {
00305         return new ht_registry_data_string("");
00306 }
00307 
00308 ht_registry_data *create_empty_dword()
00309 {
00310         return new ht_registry_data_dword();
00311 }
00312 
00313 ht_registry_data *create_empty_string()
00314 {
00315         return new ht_registry_data_string("");
00316 }
00317 
00318 ht_registry_data *create_empty_raw()
00319 {
00320         return new ht_registry_data_raw();
00321 }
00322 
00323 /*
00324  *      CLASS ht_registry
00325  */
00326 
00327 int ht_registry_node_type_desc::load(ht_object_stream *f)
00328 {
00329         type = f->getIntDec(4, "type");
00330         HT_ATOM a = f->getIntHex(4, NULL);
00331         void *p = find_atom(a);
00332         create_empty_registry_data=(create_empty_registry_data_func)p;
00333         return f->get_error();
00334 }
00335 
00336 OBJECT_ID ht_registry_node_type_desc::object_id() const
00337 {
00338         return ATOM_HT_REGISTRY_NODE_TYPE_DESC;
00339 }
00340 
00341 void ht_registry_node_type_desc::store(ht_object_stream *f)
00342 {
00343         f->putIntDec(type, 4, "type");
00344         HT_ATOM a = find_atom_rev((void*)create_empty_registry_data);
00345         f->putIntHex(a, 4, NULL);
00346 }
00347 
00348 
00349 void ht_registry::init()
00350 {
00351 // build registry root
00352         root=new ht_registry_node();
00353 
00354         root->init(RNT_SUBDIR);
00355 
00356         ht_stree *s=new ht_stree();
00357         s->init(compare_keys_string);
00358 
00359         root->data=new ht_registry_data_stree(s);
00360 
00361 // build node_types tree
00362         node_types=new ht_stree();
00363         node_types->init(compare_keys_string);
00364 
00365         struct bla {
00366                 char *identifier;
00367                 ht_registry_node_type type;
00368                 create_empty_registry_data_func create_empty_registry_data;
00369         };
00370         bla b[]=
00371         {
00372                 {"subdir", RNT_SUBDIR, NULL},
00373                 {"symlink", RNT_SYMLINK, create_empty_symlink},
00374                 {"dword", RNT_DWORD, create_empty_dword},
00375                 {"string", RNT_STRING, create_empty_string},
00376                 {"raw", RNT_RAW, create_empty_raw}
00377         };
00378 
00379         for (UINT i=0; i<sizeof (b) / sizeof b[0]; i++) {
00380                 ht_registry_node_type_desc *d=new ht_registry_node_type_desc();
00381                 d->type = b[i].type;
00382                 d->create_empty_registry_data = b[i].create_empty_registry_data;
00383                 node_types->insert(new ht_data_string(b[i].identifier), d);
00384         }
00385 }
00386 
00387 void ht_registry::done()
00388 {
00389         node_types->destroy();
00390         delete node_types;
00391 
00392         root->done();
00393         delete root;
00394 }
00395 
00396 int ht_registry::create_node(const char *key, ht_registry_node_type type)
00397 {
00398         const char *name;
00399         ht_registry_node *m;
00400         if (!splitfind(key, &name, &m)) return EINVAL;
00401 
00402         if (!valid_nodename(name)) return EINVAL;
00403 
00404         ht_registry_node_type_desc *d = get_node_type_desc(type, NULL);
00405         if (d && d->create_empty_registry_data) {
00406                 ht_registry_data *data = d->create_empty_registry_data();
00407 
00408                 ht_registry_node *n=new ht_registry_node();
00409                 n->init(type);
00410                 n->data=data;
00411 
00412                 return ((ht_registry_data_stree*)m->data)->tree->insert(new ht_data_string(name), n) ? 0 : EEXIST;
00413         }
00414 
00415         return ENOSYS;
00416 }
00417 
00418 int ht_registry::create_subdir(const char *key)
00419 {
00420         const char *name;
00421         ht_registry_node *m;
00422         if (!splitfind(key, &name, &m)) return EINVAL;
00423 
00424         if (!valid_nodename(name)) return EINVAL;
00425 
00426         ht_stree *s=new ht_stree();
00427         s->init(compare_keys_string);
00428 
00429         ht_registry_node *n=new ht_registry_node();
00430         n->init(RNT_SUBDIR);
00431         n->data=new ht_registry_data_stree(s);
00432 
00433         return ((ht_registry_data_stree*)m->data)->tree->insert(new ht_data_string(name), n) ? 0 : EEXIST;
00434 }
00435 
00436 int ht_registry::delete_node(const char *key)
00437 {
00438         ht_tree *dir;
00439         ht_registry_node *n=find_entry_i(&dir, key, 0);
00440         if (!n) return ENOENT;
00441         const char *s=strrchr(key, '/');
00442         if (s) s++; else s=key;
00443         ht_data_string ss(s);
00444         return dir->del(&ss) ? 0 : ENOENT;
00445 }
00446 
00447 void ht_registry::debug_dump()
00448 {
00449 #if 0
00450 //      FILE *f=fopen("", "");
00451         debug_dump_i(stderr, ((ht_registry_data_stree*)root->data)->tree, 0);
00452 //      fclose(f);
00453 #endif
00454 }
00455 
00456 void ht_registry::debug_dump_i(FILE *f, ht_tree *t, int ident)
00457 {
00458 #if 0
00459         ht_data_string *key=NULL;
00460         ht_registry_node *n;
00461         while ((key=(ht_data_string*)t->enum_next((Object**)&n, key))) {
00462                 for (int i=0; i<ident; i++) fprintf(f, "     ");
00463                 fprintf(f, "%s ", key->value);
00464                 switch (n->type) {
00465                         case RNT_DWORD:
00466                                 fprintf(f, "= (dword) %08d (%08x)\n", ((ht_data_dword*)n->data)->value, ((ht_data_dword*)n->data)->value);
00467                                 break;
00468                         case RNT_STRING:
00469                                 fprintf(f, "= (string) \"%s\"\n", ((ht_data_string*)n->data)->value);
00470                                 break;
00471                         case RNT_SYMLINK:
00472                                 fprintf(f, "=> \"%s\"\n", ((ht_data_string*)n->data)->value);
00473                                 break;
00474                         case RNT_SUBDIR:
00475                                 fprintf(f, "{\n");
00476                                 debug_dump_i(f, ((ht_registry_data_stree*)n->data)->tree, ident+1);
00477                                 for (int i=0; i<ident; i++) fprintf(f, "     ");
00478                                 fprintf(f, "}\n");
00479                                 break;
00480                         case RNT_RAW:
00481                                 fprintf(f, "= (raw) nyi!\n");
00482                                 break;
00483                         default: {
00484                                 char *name=lookup_node_type_name(n->type);
00485                                 if (!name) name="?";
00486                                 fprintf(f, "= ('%s'=%d)\n", name, n->type);
00487                                 break;
00488                         }
00489                 }
00490         }
00491 #endif
00492 }
00493 
00494 const char *ht_registry::enum_next(ht_registry_data **data, ht_registry_node_type *type, const char *dir, const char *prevkey)
00495 {
00496         ht_tree *t;
00497         rec_depth = 0;
00498         ht_registry_node *n = find_entry_i(0, dir, 1);
00499         if (n) {
00500                 if (n->type != RNT_SUBDIR) return NULL;
00501                 t = ((ht_registry_data_stree*)n->data)->tree;
00502 
00503                 ht_data_string ok(prevkey);
00504                 ht_data_string *k;
00505                 ht_registry_node *d;
00506                 if ((k = (ht_data_string*)t->enum_next((Object**)&d, prevkey ? &ok : NULL))) {
00507                         *data = d->data;
00508                         *type = d->type;
00509                         return k->value;
00510                 }
00511         }
00512         return NULL;
00513 }
00514 
00515 const char *ht_registry::enum_prev(ht_registry_data **data, ht_registry_node_type *type, const char *dir, const char *nextkey)
00516 {
00517         ht_tree *t;
00518         rec_depth = 0;
00519         ht_registry_node *n = find_entry_i(0, dir, 1);
00520         if (n) {
00521                 if (n->type != RNT_SUBDIR) return NULL;
00522                 t = ((ht_registry_data_stree*)n->data)->tree;
00523 
00524                 ht_data_string ok(nextkey);
00525                 ht_data_string *k;
00526                 ht_registry_node *d;
00527                 if ((k = (ht_data_string*)t->enum_prev((Object**)&d, nextkey ? &ok : NULL))) {
00528                         *data = d->data;
00529                         *type = d->type;
00530                         return k->value;
00531                 }
00532         }
00533         return NULL;
00534 }
00535 
00536 bool ht_registry::find_any_entry(const char *key, ht_registry_data **data, ht_registry_node_type *type)
00537 {
00538         rec_depth=0;
00539         ht_registry_node *n=find_entry_i(0, key, 1);
00540         if (n) {
00541                 *data=n->data;
00542                 *type=n->type;
00543                 return true;
00544         }
00545         return false;
00546 }
00547 
00548 bool ht_registry::find_data_entry(const char *key, ht_registry_data **data, ht_registry_node_type *type, bool follow_symlinks)
00549 {
00550         rec_depth=0;
00551         ht_registry_node *n=find_entry_i(0, key, follow_symlinks);
00552         if (n) {
00553                 if (n->type==RNT_SUBDIR) return false;
00554                 *data=n->data;
00555                 *type=n->type;
00556                 return true;
00557         }
00558         return false;
00559 }
00560 
00561 ht_registry_node *ht_registry::find_entry_i(ht_tree **rdir, const char *key, bool follow_symlinks)
00562 {
00563         ht_registry_node *dir=root;
00564         char *s;
00565         char t[256]; /* FIXME: possible buffer overflow */
00566         if (key[0]=='/') key++;
00567         while (1) {
00568                 s=strchr(key, '/');
00569                 if (s) {
00570                         strncpy(t, key, s-key);
00571                         t[s-key]=0;
00572                         dir=find_entry_get_subdir(((ht_registry_data_stree*)dir->data)->tree, t);
00573                         if (!dir) break;
00574                         key=s+1;
00575                 } else {
00576                         ht_registry_node *n;
00577                         if (*key==0) {
00578                                 n=dir;
00579                         } else {
00580                                 n=find_entry_get_data(((ht_registry_data_stree*)dir->data)->tree, key, follow_symlinks);
00581                         }
00582                         if (rdir) *rdir=((ht_registry_data_stree*)dir->data)->tree;
00583                         return n;
00584                 }
00585         }
00586         return 0;
00587 }
00588 
00589 ht_registry_node *ht_registry::find_entry_get_node(ht_tree *dir, const char *nodename)
00590 {
00591         if (nodename) {
00592                 ht_data_string keystr(nodename);
00593                 ht_registry_node *n=(ht_registry_node*)dir->get(&keystr);
00594                 return n;
00595         }
00596         return NULL;
00597 }
00598 
00599 ht_registry_node *ht_registry::find_entry_get_subdir(ht_tree *dir, const char *nodename)
00600 {
00601         ht_registry_node *n=find_entry_get_node(dir, nodename);
00602 start:
00603         if (!n) return 0;
00604         switch (n->type) {
00605                 case RNT_SYMLINK: {
00606                         rec_depth++;
00607                         if (rec_depth>MAX_SYMLINK_REC_DEPTH) return 0;
00608                         char *sl=((ht_registry_data_string*)n->data)->value;
00609                         if (sl[0]=='/') {
00610                                 n=find_entry_i(0, sl, 1);
00611                                 goto start;
00612                         } else {
00613                                 return find_entry_get_subdir(dir, sl);
00614                         }
00615                 }
00616                 case RNT_SUBDIR:
00617                         return n;
00618         }
00619         return 0;
00620 }
00621 
00622 ht_registry_node *ht_registry::find_entry_get_data(ht_tree *dir, const char *nodename, bool follow_symlinks)
00623 {
00624         ht_registry_node *n=find_entry_get_node(dir, nodename);
00625 start:
00626         if (!n) return 0;
00627         if ((follow_symlinks) && (n->type==RNT_SYMLINK)) {
00628                 rec_depth++;
00629                 if (rec_depth>MAX_SYMLINK_REC_DEPTH) return 0;
00630                 char *sl=((ht_registry_data_string*)n->data)->value;
00631                 if (sl[0]=='/') {
00632                         n=find_entry_i(0, sl, 1);
00633                         goto start;
00634                 } else {
00635                         return find_entry_get_data(dir, sl, follow_symlinks);
00636                 }
00637         }
00638         return n;
00639 }
00640 
00641 ht_registry_node_type ht_registry::have_node_type(const char *identifier, create_empty_registry_data_func create_empty_registry_data)
00642 {
00643         ht_registry_node_type t=lookup_node_type(identifier);
00644         if (!t) t=register_node_type(identifier, create_empty_registry_data);
00645         return t;
00646 }
00647 
00648 int ht_registry::load(ht_object_stream *f)
00649 {
00650         if (!(node_types=(ht_stree*)f->getObject("types"))) return 1;
00651         if (!(root=(ht_registry_node*)f->getObject("root"))) return 1;
00652         return f->get_error();
00653 }
00654 
00655 ht_registry_node_type_desc *ht_registry::get_node_type_desc(ht_registry_node_type t, char **identifier)
00656 {
00657         ht_data_string *key=NULL;
00658         ht_registry_node_type_desc *data;
00659         while ((key=(ht_data_string*)node_types->enum_next((Object**)&data, key))) {
00660                 if (t==data->type) {
00661                         if (identifier) *identifier = key->value;
00662                         return data;
00663                 }
00664         }
00665         return NULL;
00666 }
00667 
00668 ht_registry_node_type ht_registry::lookup_node_type(const char *identifier)
00669 {
00670         ht_data_string s(identifier);
00671         ht_registry_node_type_desc *d=(ht_registry_node_type_desc*)node_types->get(&s);
00672         return d ? d->type : 0;
00673 }
00674 
00675 OBJECT_ID ht_registry::object_id() const
00676 {
00677         return ATOM_HT_REGISTRY;
00678 }
00679 
00680 ht_registry_node_type ht_registry::register_node_type(const char *identifier, create_empty_registry_data_func create_empty_registry_data)
00681 {
00682 //      ht_registry_node_type t = RNT_USER;
00683         ht_registry_node_type t = 0;
00684         ht_data_string *key;
00685         ht_registry_node_type_desc *data;
00686         bool found = false; 
00687         while (!found) {
00688                 t++;
00689                 found = true;
00690                 key = NULL;
00691                 while ((key=(ht_data_string*)node_types->enum_next((Object**)&data, key))) {
00692                         if (t == data->type) {
00693                                 found = false;
00694                                 break;
00695                         }
00696                 }
00697         }
00698 
00699         ht_registry_node_type_desc *v = new ht_registry_node_type_desc();
00700         v->type = t;
00701         v->create_empty_registry_data = create_empty_registry_data;
00702         bool b = node_types->insert(new ht_data_string(identifier), v);
00703         if (b) return t;
00704         return RNT_INVALID;
00705 }
00706 
00707 int ht_registry::set_dword(const char *key, dword d)
00708 {
00709         return set_node(key, RNT_DWORD, new ht_registry_data_dword(d));
00710 }
00711 
00712 int ht_registry::set_raw(const char *key, const void *data, UINT size)
00713 {
00714         return set_node(key, RNT_RAW, new ht_registry_data_raw(data, size));
00715 }
00716 
00717 int ht_registry::set_node(const char *key, ht_registry_node_type type, ht_registry_data *data)
00718 {
00719         ht_registry_node *n = find_entry_i(0, key, 0);
00720         if (!n) return ENOENT;
00721 
00722         if (n->type == type) {
00723                 if (n->data) {
00724                         n->data->done();
00725                         delete n->data;
00726                 }
00727                 n->data = data;
00728                 return 0;
00729         }
00730         return EPERM;
00731 }
00732 
00733 int ht_registry::set_string(const char *key, const char *string)
00734 {
00735         return set_node(key, RNT_STRING, new ht_registry_data_string(string));
00736 }
00737 
00738 int ht_registry::set_symlink(const char *key, const char *dest)
00739 {
00740         return set_node(key, RNT_SYMLINK, new ht_registry_data_string(dest));
00741 }
00742 
00743 bool ht_registry::splitfind(const char *key, const char **name, ht_registry_node **node)
00744 {
00745         char dir[256]; /* FIXME: possible buffer overflow */
00746         const char *n=strrchr(key, '/');
00747         if (n) {
00748                 strncpy(dir, key, n-key);
00749                 dir[n-key]=0;
00750                 n++;
00751         } else {
00752                 dir[0]=0;
00753                 n=key;
00754         }
00755 
00756         ht_registry_node *m=find_entry_i(0, dir, 1);
00757         if (!m) return 0;
00758         if (m->type!=RNT_SUBDIR) return 0;
00759         *node=m;
00760         *name=n;
00761         return 1;
00762 }
00763 
00764 void ht_registry::store(ht_object_stream *f)
00765 {
00766         f->putObject(node_types, "types");
00767         f->putObject(root, "root");
00768 }
00769 
00770 unsigned char valid_nodename_chars[256/8]=
00771 {
00772 /* 00, 08, 10, 18 */
00773         0, 0, 0, 0,
00774 /* 20, 28, 30, 38 */
00775 /* space '-' 0-9 '&' ':' '.' */
00776         BITMAP(1, 0, 0, 0, 0, 0, 1, 0), BITMAP(0, 0, 0, 0, 0, 1, 1, 0),
00777         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 0, 0, 0, 0, 0),
00778 /* 40, 48, 50, 58 */
00779 /* A-Z '_' */
00780         BITMAP(0, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 1, 1, 1, 1, 1),
00781         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 0, 0, 0, 0, 1),
00782 /* 60, 68, 70, 78 */
00783 /* a-z */
00784         BITMAP(0, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 1, 1, 1, 1, 1),
00785         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 0, 0, 0, 0, 0),
00786 /* 80, 88, 90, 98 */
00787         0, 0, 0, 0,
00788 /* a0, a8, b0, b8 */
00789         0, 0, 0, 0,
00790 /* c0, c8, d0, d8 */
00791         0, 0, 0, 0,
00792 /* e0, e8, f0, f8 */
00793         0, 0, 0, 0
00794 };
00795 
00796 unsigned char valid_nodename_chars_first[256/8]=
00797 {
00798 /* 00, 08, 10, 18 */
00799         0, 0, 0, 0,
00800 /* 20, 28, 30, 38 */
00801 /* '.' '-' 0-9 */
00802         BITMAP(0, 0, 0, 0, 0, 0, 1, 0), BITMAP(0, 0, 0, 0, 0, 1, 1, 0),
00803         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 0, 0, 0, 0, 0, 0),
00804 /* 40, 48, 50, 58 */
00805 /* A-Z '_' */
00806         BITMAP(0, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 1, 1, 1, 1, 1),
00807         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 0, 0, 0, 0, 1),
00808 /* 60, 68, 70, 78 */
00809 /* a-z */
00810         BITMAP(0, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 1, 1, 1, 1, 1),
00811         BITMAP(1, 1, 1, 1, 1, 1, 1, 1), BITMAP(1, 1, 1, 0, 0, 0, 0, 0),
00812 /* 80, 88, 90, 98 */
00813         0, 0, 0, 0,
00814 /* a0, a8, b0, b8 */
00815         0, 0, 0, 0,
00816 /* c0, c8, d0, d8 */
00817         0, 0, 0, 0,
00818 /* e0, e8, f0, f8 */
00819         0, 0, 0, 0
00820 };
00821 
00822 bool valid_char(unsigned char *bitmap, char c)
00823 {
00824         int o=c/8;
00825         int p=c%8;
00826         return BITBIT(bitmap[o], p);
00827 }
00828 
00829 bool ht_registry::valid_nodename(const char *nodename)
00830 {
00831         if ((strcmp(nodename, "..")==0) || (strcmp(nodename, ".")==0)) {
00832                 return false;
00833         }
00834         if (!valid_char(valid_nodename_chars_first, *nodename)) return false;
00835         nodename++;
00836         while (*nodename) {
00837                 if (!valid_char(valid_nodename_chars, *nodename)) return false;
00838                 nodename++;
00839         }
00840         return true;
00841 }
00842 
00843 dword get_config_dword(char *ident)
00844 {
00845         char e[HT_NAME_MAX], *ee = e;
00846         strcpy(ee, "/config/"); ee += strlen(ee);
00847         strncpy(ee, ident, sizeof (e) - (ee-e));
00848         ht_registry_data *d;
00849         ht_registry_node_type t;
00850         if (registry->find_data_entry(e, &d, &t, true)) {
00851                 if (t == RNT_DWORD) {
00852                         ht_registry_data_dword *s = (ht_registry_data_dword *)d;
00853                         return s->value;
00854                 } else {
00855                         char *q = "?";
00856                         registry->get_node_type_desc(t, &q);
00857                         LOG_EX(LOG_ERROR, "registry key '%s' not of type %s, but: %s", e, "dword", q);
00858                 }
00859         } else LOG_EX(LOG_ERROR, "registry key '%s' not found", e);
00860         return 0;
00861 }
00862 
00863 char *get_config_string(char *ident)
00864 {
00865         char e[HT_NAME_MAX], *ee = e;
00866         strcpy(ee, "/config/"); ee += strlen(ee);
00867         strncpy(ee, ident, sizeof (e) - (ee-e));
00868         ht_registry_data *d;
00869         ht_registry_node_type t;
00870         if (registry->find_data_entry(e, &d, &t, true)) {
00871                 if (t == RNT_STRING) {
00872                         ht_registry_data_string *s = (ht_registry_data_string *)d;
00873                         return ht_strdup(s->value);
00874                 } else {
00875                         char *q = "?";
00876                         registry->get_node_type_desc(t, &q);
00877                         LOG_EX(LOG_ERROR, "registry key '%s' not of type %s, but: %s", e, "string", q);
00878                 }
00879         } else LOG_EX(LOG_ERROR, "registry key '%s' not found", e);
00880         return NULL;
00881 }
00882 
00883 BUILDER(ATOM_HT_REGISTRY, ht_registry);
00884 BUILDER(ATOM_HT_REGISTRY_NODE, ht_registry_node);
00885 BUILDER(ATOM_HT_REGISTRY_DATA_STREE, ht_registry_data_stree);
00886 BUILDER(ATOM_HT_REGISTRY_DATA_DWORD, ht_registry_data_dword);
00887 BUILDER(ATOM_HT_REGISTRY_DATA_RAW, ht_registry_data_raw);
00888 BUILDER(ATOM_HT_REGISTRY_DATA_STRING, ht_registry_data_string);
00889 BUILDER(ATOM_HT_REGISTRY_NODE_TYPE_DESC, ht_registry_node_type_desc);
00890         
00891 /*
00892  *      INIT
00893  */
00894 
00895 bool init_registry()
00896 {
00897         REGISTER(ATOM_HT_REGISTRY, ht_registry);
00898         REGISTER(ATOM_HT_REGISTRY_NODE, ht_registry_node);
00899         REGISTER(ATOM_HT_REGISTRY_DATA_STREE, ht_registry_data_stree);
00900         REGISTER(ATOM_HT_REGISTRY_DATA_DWORD, ht_registry_data_dword);
00901         REGISTER(ATOM_HT_REGISTRY_DATA_RAW, ht_registry_data_raw);
00902         REGISTER(ATOM_HT_REGISTRY_DATA_STRING, ht_registry_data_string);
00903         REGISTER(ATOM_HT_REGISTRY_NODE_TYPE_DESC, ht_registry_node_type_desc);
00904 //      register_atom(ATOM_HT_CREATE_EMPTY_SUBDIR, (void*));
00905         register_atom(ATOM_HT_CREATE_EMPTY_SYMLINK, (void*)create_empty_symlink);
00906         register_atom(ATOM_HT_CREATE_EMPTY_DWORD, (void*)create_empty_dword);
00907         register_atom(ATOM_HT_CREATE_EMPTY_STRING, (void*)create_empty_string);
00908         register_atom(ATOM_HT_CREATE_EMPTY_RAW, (void*)create_empty_raw);
00909 
00910 /*
00911  *      load default registry
00912  */
00913         ht_memmap_file *f = new ht_memmap_file();
00914         f->init((unsigned char*)default_reg, sizeof default_reg);
00915 
00916         ht_object_stream_bin *o = new ht_object_stream_bin();
00917         o->init(f);
00918 
00919         registry = (ht_registry*)o->getObject(NULL);
00920 
00921         o->done();
00922         delete o;
00923 
00924         f->done();
00925         delete f;
00926 
00927         return true;
00928 }
00929 
00930 /*
00931  *      DONE
00932  */
00933 
00934 void done_registry()
00935 {
00936         UNREGISTER(ATOM_HT_REGISTRY, ht_registry);
00937         UNREGISTER(ATOM_HT_REGISTRY_NODE, ht_registry_node);
00938         UNREGISTER(ATOM_HT_REGISTRY_DATA_STREE, ht_registry_data_stree);
00939         UNREGISTER(ATOM_HT_REGISTRY_DATA_DWORD, ht_registry_data_dword);
00940         UNREGISTER(ATOM_HT_REGISTRY_DATA_RAW, ht_registry_data_raw);
00941         UNREGISTER(ATOM_HT_REGISTRY_DATA_STRING, ht_registry_data_string);
00942         UNREGISTER(ATOM_HT_REGISTRY_NODE_TYPE_DESC, ht_registry_node_type_desc);
00943 //      unregister_atom(ATOM_HT_CREATE_EMPTY_SUBDIR);
00944         unregister_atom(ATOM_HT_CREATE_EMPTY_SYMLINK);
00945         unregister_atom(ATOM_HT_CREATE_EMPTY_DWORD);
00946         unregister_atom(ATOM_HT_CREATE_EMPTY_STRING);
00947         unregister_atom(ATOM_HT_CREATE_EMPTY_RAW);
00948         
00949         registry->done();
00950         delete registry;
00951 }
00952 

Generated on Fri May 7 21:15:37 2004 by doxygen 1.3.5