| 1 | #include <stdio.h> |
|---|
| 2 | #include <stdlib.h> |
|---|
| 3 | #include <string.h> |
|---|
| 4 | /* #include <malloc.h> */ |
|---|
| 5 | |
|---|
| 6 | #include <sys/types.h> |
|---|
| 7 | #include <netinet/in.h> /* hton ntoh */ |
|---|
| 8 | |
|---|
| 9 | #include "adlocal.h" |
|---|
| 10 | /*#include "arbdb.h"*/ |
|---|
| 11 | #include "arbdbt.h" |
|---|
| 12 | |
|---|
| 13 | static GB_CSTR gb_read_dict_data(GBDATA *gb_dict, long *size) { |
|---|
| 14 | GB_CSTR data = 0; |
|---|
| 15 | if (gb_dict->flags.compressed_data) { |
|---|
| 16 | GB_internal_error("Dictionary is compressed"); |
|---|
| 17 | data = GB_read_bytes(gb_dict); |
|---|
| 18 | } |
|---|
| 19 | else { |
|---|
| 20 | data = GB_read_bytes_pntr(gb_dict); |
|---|
| 21 | } |
|---|
| 22 | *size = GB_read_bytes_count(gb_dict); |
|---|
| 23 | return data; |
|---|
| 24 | } |
|---|
| 25 | |
|---|
| 26 | GB_ERROR gb_load_dictionary_data(GBDATA *gb_main,const char *key, char **dict_data, long *size) { |
|---|
| 27 | /* returns dictionary data (like saved in DB) |
|---|
| 28 | * in a block allocated by gbm_get_mem(.., GBM_DICT_INDEX) |
|---|
| 29 | */ |
|---|
| 30 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
|---|
| 31 | GB_ERROR error = 0; |
|---|
| 32 | |
|---|
| 33 | *dict_data = 0; |
|---|
| 34 | *size = -1; |
|---|
| 35 | gb_main = (GBDATA *)Main->data; |
|---|
| 36 | |
|---|
| 37 | if (key[0] == '@') { |
|---|
| 38 | error = GB_export_error("No dictionaries for system fields"); |
|---|
| 39 | } |
|---|
| 40 | else { |
|---|
| 41 | GBDATA *gb_key_data = Main->gb_key_data; |
|---|
| 42 | GBDATA *gb_name; |
|---|
| 43 | |
|---|
| 44 | GB_push_my_security(gb_main); |
|---|
| 45 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
|---|
| 46 | |
|---|
| 47 | if (gb_name){ |
|---|
| 48 | GBDATA *gb_key = GB_get_father(gb_name); |
|---|
| 49 | GBDATA *gb_dict = GB_entry(gb_key,"@dictionary"); |
|---|
| 50 | if (gb_dict) { |
|---|
| 51 | const char *data = gb_read_dict_data(gb_dict, size); |
|---|
| 52 | char *copy = gbm_get_mem(*size, GBM_DICT_INDEX); |
|---|
| 53 | memcpy(copy, data, *size); |
|---|
| 54 | *dict_data = copy; |
|---|
| 55 | } |
|---|
| 56 | } |
|---|
| 57 | GB_pop_my_security(gb_main); |
|---|
| 58 | } |
|---|
| 59 | return error; |
|---|
| 60 | } |
|---|
| 61 | |
|---|
| 62 | GB_DICTIONARY *gb_create_dict(GBDATA *gb_dict){ |
|---|
| 63 | GB_DICTIONARY *dict = (GB_DICTIONARY *)GB_calloc(sizeof(GB_DICTIONARY),1); |
|---|
| 64 | const char *data; |
|---|
| 65 | GB_NINT *idata; |
|---|
| 66 | long size; |
|---|
| 67 | |
|---|
| 68 | data = gb_read_dict_data(gb_dict, &size); |
|---|
| 69 | GB_write_security_write(gb_dict,7); |
|---|
| 70 | |
|---|
| 71 | idata = (GB_NINT *)data; |
|---|
| 72 | dict->words = ntohl(*idata++); |
|---|
| 73 | dict->textlen = (int)(size - sizeof(GB_NINT)*(1+dict->words*2)); |
|---|
| 74 | |
|---|
| 75 | dict->offsets = idata; |
|---|
| 76 | dict->resort = idata+dict->words; |
|---|
| 77 | dict->text = (unsigned char*)(idata+2*dict->words); |
|---|
| 78 | |
|---|
| 79 | return dict; |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | void delete_gb_dictionary(GB_DICTIONARY *dict){ |
|---|
| 83 | free(dict); |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | void gb_system_key_changed_cb(GBDATA *gbd,int *cl, GB_CB_TYPE type){ |
|---|
| 87 | GBQUARK q = (GBQUARK)(long) cl; |
|---|
| 88 | |
|---|
| 89 | if (type == GB_CB_DELETE){ |
|---|
| 90 | GB_MAIN_TYPE *Main = gb_get_main_during_cb(); |
|---|
| 91 | |
|---|
| 92 | delete_gb_dictionary(Main->keys[q].dictionary); |
|---|
| 93 | Main->keys[q].dictionary = 0; |
|---|
| 94 | Main->keys[q].gb_key = 0; |
|---|
| 95 | }else{ |
|---|
| 96 | gb_load_single_key_data(gbd,q); |
|---|
| 97 | } |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | void gb_system_master_changed_cb(GBDATA *gbd,int *cl, GB_CB_TYPE type){ |
|---|
| 101 | GBQUARK q = (GBQUARK)(long) cl; |
|---|
| 102 | if (type == GB_CB_DELETE){ |
|---|
| 103 | GB_MAIN_TYPE *Main = gb_get_main_during_cb(); |
|---|
| 104 | Main->keys[q].gb_master_ali = 0; |
|---|
| 105 | } |
|---|
| 106 | else { |
|---|
| 107 | gb_load_single_key_data(gbd,q); |
|---|
| 108 | } |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q) { |
|---|
| 112 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
|---|
| 113 | struct gb_key_struct *ks = &Main->keys[q]; |
|---|
| 114 | const char *key = ks->key; |
|---|
| 115 | |
|---|
| 116 | if (!Main->gb_key_data){ |
|---|
| 117 | ks->compression_mask = -1; |
|---|
| 118 | return; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | gb_main = (GBDATA *)Main->data; |
|---|
| 122 | if (key[0] == '@'){ |
|---|
| 123 | ks->compression_mask = 0; |
|---|
| 124 | ks->dictionary = 0; |
|---|
| 125 | ks->gb_key_disabled = 1; |
|---|
| 126 | ks->gb_master_ali = 0; |
|---|
| 127 | } |
|---|
| 128 | else { |
|---|
| 129 | GBDATA *gb_key_data = Main->gb_key_data; |
|---|
| 130 | GBDATA *gb_key,*gb_name,*gb_dict; |
|---|
| 131 | GB_push_my_security(gb_main); |
|---|
| 132 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
|---|
| 133 | if (gb_name){ |
|---|
| 134 | gb_key= GB_get_father(gb_name); |
|---|
| 135 | }else{ |
|---|
| 136 | gb_key = gb_create_container(gb_key_data,"@key"); |
|---|
| 137 | gb_name = gb_create(gb_key,"@name",GB_STRING); |
|---|
| 138 | GB_write_string(gb_name,key); |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | GB_ensure_callback(gb_key,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_key_changed_cb,(int *)q); |
|---|
| 142 | |
|---|
| 143 | if (ks->dictionary) { |
|---|
| 144 | delete_gb_dictionary(ks->dictionary); |
|---|
| 145 | ks->dictionary = 0; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | ks->compression_mask = *GBT_readOrCreate_int(gb_key,"compression_mask",-1); |
|---|
| 149 | gb_dict = GB_entry(gb_key,"@dictionary"); |
|---|
| 150 | ks->dictionary = gb_dict ? gb_create_dict(gb_dict) : 0; |
|---|
| 151 | ks->gb_key = gb_key; |
|---|
| 152 | |
|---|
| 153 | { |
|---|
| 154 | char buffer[256]; |
|---|
| 155 | memset(buffer,0,256); |
|---|
| 156 | sprintf(buffer,"%s/@master_data/@%s",GB_SYSTEM_FOLDER,key); |
|---|
| 157 | ks->gb_master_ali = GB_search(gb_main,buffer,GB_FIND); |
|---|
| 158 | if (ks->gb_master_ali){ |
|---|
| 159 | GB_remove_callback(ks->gb_master_ali,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_master_changed_cb,(int *)q); |
|---|
| 160 | GB_add_callback (ks->gb_master_ali,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_master_changed_cb,(int *)q); |
|---|
| 161 | } |
|---|
| 162 | } |
|---|
| 163 | GB_pop_my_security(gb_main); |
|---|
| 164 | } |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | GB_ERROR gb_save_dictionary_data(GBDATA *gb_main,const char *key,const char *dict, int size) { |
|---|
| 168 | /* if 'dict' is NULL, an existing directory gets deleted */ |
|---|
| 169 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
|---|
| 170 | GB_ERROR error = 0; |
|---|
| 171 | gb_main = (GBDATA *)Main->data; |
|---|
| 172 | if (key[0] == '@') { |
|---|
| 173 | error = GB_export_error("No dictionaries for system fields"); |
|---|
| 174 | } |
|---|
| 175 | else { |
|---|
| 176 | GBDATA *gb_key_data = Main->gb_key_data; |
|---|
| 177 | GBDATA *gb_key,*gb_name,*gb_dict; |
|---|
| 178 | GB_push_my_security(gb_main); |
|---|
| 179 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
|---|
| 180 | if (gb_name){ |
|---|
| 181 | gb_key= GB_get_father(gb_name); |
|---|
| 182 | }else{ |
|---|
| 183 | gb_key = gb_create_container(gb_key_data,"@key"); |
|---|
| 184 | gb_name = gb_create(gb_key,"@name",GB_STRING); |
|---|
| 185 | GB_write_string(gb_name,key); |
|---|
| 186 | } |
|---|
| 187 | if (dict) { |
|---|
| 188 | gb_dict = gb_search(gb_key,"@dictionary",GB_BYTES,1); |
|---|
| 189 | error = GB_write_bytes(gb_dict,dict,size); |
|---|
| 190 | } |
|---|
| 191 | else { |
|---|
| 192 | gb_dict = GB_entry(gb_key, "@dictionary"); |
|---|
| 193 | if (gb_dict) { |
|---|
| 194 | GB_delete(gb_dict); /* delete existing dictionary */ |
|---|
| 195 | } |
|---|
| 196 | } |
|---|
| 197 | GB_pop_my_security(gb_main); |
|---|
| 198 | } |
|---|
| 199 | if (!error){ |
|---|
| 200 | GBQUARK q = gb_key_2_quark(Main,key); |
|---|
| 201 | gb_load_single_key_data(gb_main,q); |
|---|
| 202 | } |
|---|
| 203 | return error; |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | GB_ERROR gb_load_key_data_and_dictionaries(GBDATA *gb_main){ |
|---|
| 207 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
|---|
| 208 | GBDATA *gb_key_data = gb_search(gb_main,GB_SYSTEM_FOLDER "/" GB_SYSTEM_KEY_DATA, GB_CREATE_CONTAINER,1); |
|---|
| 209 | GBDATA *gb_key,*gb_next_key=0; |
|---|
| 210 | int key; |
|---|
| 211 | |
|---|
| 212 | Main->gb_key_data = gb_key_data; |
|---|
| 213 | if (!Main->local_mode) return 0; /* do not create anything at the client side */ |
|---|
| 214 | |
|---|
| 215 | GB_push_my_security(gb_main); |
|---|
| 216 | |
|---|
| 217 | /* First step: search unused keys and delete them */ |
|---|
| 218 | for (gb_key = GB_entry(gb_key_data,"@key"); |
|---|
| 219 | gb_key; |
|---|
| 220 | gb_key = gb_next_key) |
|---|
| 221 | { |
|---|
| 222 | GBDATA *gb_name = GB_entry(gb_key,"@name"); |
|---|
| 223 | const char *name = GB_read_char_pntr(gb_name); |
|---|
| 224 | GBQUARK quark = gb_key_2_quark(Main,name); |
|---|
| 225 | |
|---|
| 226 | gb_next_key = GB_nextEntry(gb_key); |
|---|
| 227 | |
|---|
| 228 | if (quark<=0 || quark >= Main->sizeofkeys || !Main->keys[quark].key){ |
|---|
| 229 | GB_delete(gb_key); /* delete unused key */ |
|---|
| 230 | } |
|---|
| 231 | } |
|---|
| 232 | GB_create_index(gb_key_data, "@name", GB_MIND_CASE, Main->sizeofkeys*2); |
|---|
| 233 | |
|---|
| 234 | gb_key_2_quark(Main,"@name"); |
|---|
| 235 | gb_key_2_quark(Main,"@key"); |
|---|
| 236 | gb_key_2_quark(Main,"@dictionary"); |
|---|
| 237 | gb_key_2_quark(Main,"compression_mask"); |
|---|
| 238 | |
|---|
| 239 | for (key=1;key<Main->sizeofkeys;key++){ |
|---|
| 240 | char *k = Main->keys[key].key; |
|---|
| 241 | if (!k) continue; |
|---|
| 242 | gb_load_single_key_data(gb_main,key); |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | GB_pop_my_security(gb_main); |
|---|
| 247 | return 0; |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | /* gain access to allow repair of broken compression |
|---|
| 251 | * (see NT_fix_dict_compress) |
|---|
| 252 | */ |
|---|
| 253 | |
|---|
| 254 | struct DictData { |
|---|
| 255 | char *data; |
|---|
| 256 | long size; |
|---|
| 257 | }; |
|---|
| 258 | |
|---|
| 259 | struct DictData *GB_get_dictionary(GBDATA *gb_main, const char *key) { |
|---|
| 260 | /* return DictData or |
|---|
| 261 | * NULL if no dictionary or error occurred |
|---|
| 262 | */ |
|---|
| 263 | struct DictData *dd = (struct DictData*)GB_calloc(1, sizeof(*dd)); |
|---|
| 264 | GB_ERROR error = gb_load_dictionary_data(gb_main, key, &dd->data, &dd->size); |
|---|
| 265 | |
|---|
| 266 | if (error || !dd->data) { |
|---|
| 267 | GB_free_dictionary(dd); |
|---|
| 268 | dd = NULL; |
|---|
| 269 | if (error) GB_export_error(error); |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | return dd; |
|---|
| 273 | } |
|---|
| 274 | |
|---|
| 275 | GB_ERROR GB_set_dictionary(GBDATA *gb_main, const char *key, const struct DictData *dd) { |
|---|
| 276 | /* if 'dd' == NULL -> delete dictionary */ |
|---|
| 277 | GB_ERROR error; |
|---|
| 278 | if (dd) { |
|---|
| 279 | error = gb_save_dictionary_data(gb_main, key, dd->data, dd->size); |
|---|
| 280 | } |
|---|
| 281 | else { |
|---|
| 282 | error = gb_save_dictionary_data(gb_main, key, NULL, 0); |
|---|
| 283 | } |
|---|
| 284 | return error; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | void GB_free_dictionary(struct DictData *dd) { |
|---|
| 288 | if (dd) { |
|---|
| 289 | if (dd->data) gbm_free_mem(dd->data, dd->size, GBM_DICT_INDEX); |
|---|
| 290 | free(dd); |
|---|
| 291 | } |
|---|
| 292 | } |
|---|