gwenhywfar 4.0.3
|
00001 /*************************************************************************** 00002 begin : Tue Sep 09 2003 00003 copyright : (C) 2003-2010 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Lesser General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public * 00019 * License along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 * * 00023 ***************************************************************************/ 00024 00025 00026 /* This file is included from db.c */ 00027 00028 00029 00030 int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) { 00031 while(*src) { 00032 unsigned char x; 00033 00034 x=(unsigned char)*src; 00035 if (!( 00036 (x>='A' && x<='Z') || 00037 (x>='a' && x<='z') || 00038 (x>='0' && x<='9') || 00039 x=='%' || 00040 x=='.' || 00041 x==',' || 00042 x=='.' || 00043 x=='_' || 00044 x=='-' || 00045 x=='*' || 00046 x=='?' 00047 )) { 00048 unsigned char c; 00049 00050 GWEN_Buffer_AppendByte(buf, '&'); 00051 c=(((unsigned char)(*src))>>4)&0xf; 00052 if (c>9) 00053 c+=7; 00054 c+='0'; 00055 GWEN_Buffer_AppendByte(buf, c); 00056 c=((unsigned char)(*src))&0xf; 00057 if (c>9) 00058 c+=7; 00059 c+='0'; 00060 GWEN_Buffer_AppendByte(buf, c); 00061 } 00062 else 00063 GWEN_Buffer_AppendByte(buf, *src); 00064 00065 src++; 00066 } /* while */ 00067 00068 return 0; 00069 } 00070 00071 00072 00073 int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) { 00074 while(*src) { 00075 const char *srcBak; 00076 int charHandled; 00077 00078 srcBak=src; 00079 charHandled=0; 00080 if (*src=='&') { 00081 if (strlen(src)>2) { 00082 unsigned char d1, d2; 00083 unsigned char c; 00084 00085 if (isxdigit((int)src[1]) && isxdigit((int)src[2])) { 00086 /* skip '%' */ 00087 src++; 00088 /* read first digit */ 00089 d1=(unsigned char)(toupper(*src)); 00090 00091 /* get second digit */ 00092 src++; 00093 d2=(unsigned char)(toupper(*src)); 00094 /* compute character */ 00095 d1-='0'; 00096 if (d1>9) 00097 d1-=7; 00098 c=(d1<<4)&0xf0; 00099 d2-='0'; 00100 if (d2>9) 00101 d2-=7; 00102 c+=(d2&0xf); 00103 /* store character */ 00104 GWEN_Buffer_AppendByte(buf, (char)c); 00105 charHandled=1; 00106 } 00107 } 00108 } 00109 if (!charHandled) 00110 GWEN_Buffer_AppendByte(buf, *src); 00111 src++; 00112 } /* while */ 00113 00114 return 0; 00115 } 00116 00117 00118 00119 00120 00121 00122 int GWEN_DB_ReadFileAs(GWEN_DB_NODE *db, 00123 const char *fname, 00124 const char *type, 00125 GWEN_DB_NODE *params, 00126 uint32_t dbflags){ 00127 GWEN_SYNCIO *sio; 00128 GWEN_DBIO *dbio; 00129 int rv; 00130 00131 dbio=GWEN_DBIO_GetPlugin(type); 00132 if (!dbio) { 00133 DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type); 00134 return GWEN_ERROR_NOT_SUPPORTED; 00135 } 00136 00137 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting); 00138 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ); 00139 rv=GWEN_SyncIo_Connect(sio); 00140 if (rv<0) { 00141 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00142 GWEN_SyncIo_free(sio); 00143 return rv; 00144 } 00145 00146 rv=GWEN_DBIO_Import(dbio, sio, db, params, dbflags); 00147 if (rv<0) { 00148 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00149 } 00150 GWEN_SyncIo_Disconnect(sio); 00151 GWEN_SyncIo_free(sio); 00152 00153 return rv; 00154 } 00155 00156 00157 00158 int GWEN_DB_WriteFileAs(GWEN_DB_NODE *db, 00159 const char *fname, 00160 const char *type, 00161 GWEN_DB_NODE *params, 00162 uint32_t dbflags){ 00163 int rv; 00164 GWEN_DBIO *dbio; 00165 00166 dbio=GWEN_DBIO_GetPlugin(type); 00167 if (!dbio) { 00168 DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type); 00169 return GWEN_ERROR_NOT_SUPPORTED; 00170 } 00171 00172 rv=GWEN_DBIO_ExportToFile(dbio, fname, db, params, dbflags); 00173 if (rv) { 00174 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00175 return rv; 00176 } 00177 00178 return 0; 00179 } 00180 00181 00182 00183 int GWEN_DB_WriteGroupToIoLayer(GWEN_DB_NODE *node, 00184 GWEN_FAST_BUFFER *fb, 00185 uint32_t dbflags, 00186 int insert) { 00187 GWEN_DB_NODE *n; 00188 GWEN_DB_NODE *cn; 00189 int i; 00190 int err; 00191 int lastWasVar; 00192 00193 lastWasVar=0; 00194 00195 n=GWEN_DB_Node_List_First(node->children); 00196 while(n) { 00197 if (!(n->nodeFlags & GWEN_DB_NODE_FLAGS_VOLATILE)) { 00198 DBG_VERBOUS(GWEN_LOGDOMAIN, "Writing node"); 00199 switch(n->typ) { 00200 case GWEN_DB_NodeType_Group: 00201 if (dbflags & GWEN_DB_FLAGS_WRITE_SUBGROUPS) { 00202 GWEN_BUFFER *tbuf; 00203 00204 if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) { 00205 if (lastWasVar) { 00206 /* only insert newline if the last one before this group was a 00207 * variable */ 00208 GWEN_FASTBUFFER_WRITELINE(fb, err, ""); 00209 if (err<0) { 00210 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00211 return err; 00212 } 00213 } 00214 } 00215 00216 /* indend */ 00217 if (dbflags & GWEN_DB_FLAGS_INDEND) { 00218 for (i=0; i<insert; i++) { 00219 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' '); 00220 if (err<0) { 00221 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00222 return err; 00223 } 00224 } /* for */ 00225 } /* if indend */ 00226 00227 tbuf=GWEN_Buffer_new(0, 128, 0, 1); 00228 err=GWEN_DB_EscapeToBufferTolerant(n->data.dataName, tbuf); 00229 if (err<0) { 00230 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err); 00231 GWEN_Buffer_free(tbuf); 00232 return err; 00233 } 00234 00235 GWEN_FASTBUFFER_WRITEFORCED(fb, err, 00236 GWEN_Buffer_GetStart(tbuf), 00237 GWEN_Buffer_GetUsedBytes(tbuf)); 00238 GWEN_Buffer_free(tbuf); 00239 if (err<0) { 00240 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err); 00241 return err; 00242 } 00243 GWEN_FASTBUFFER_WRITELINE(fb, err, " {"); 00244 if (err<0) { 00245 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00246 return err; 00247 } 00248 err=GWEN_DB_WriteGroupToIoLayer(n, fb, dbflags, insert+2); 00249 if (err<0) 00250 return err; 00251 00252 /* indend */ 00253 if (dbflags & GWEN_DB_FLAGS_INDEND) { 00254 for (i=0; i<insert; i++) { 00255 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' '); 00256 if (err<0) { 00257 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00258 return err; 00259 } 00260 } /* for */ 00261 } /* if indend */ 00262 00263 if (dbflags & GWEN_DB_FLAGS_DETAILED_GROUPS) { 00264 GWEN_FASTBUFFER_WRITEFORCED(fb, err, "} #", -1); 00265 if (err<0) { 00266 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00267 return err; 00268 } 00269 GWEN_FASTBUFFER_WRITELINE(fb, err, n->data.dataName); 00270 if (err<0) { 00271 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00272 return err; 00273 } 00274 } /* if detailed groups */ 00275 else { 00276 GWEN_FASTBUFFER_WRITELINE(fb, err, "}"); 00277 if (err<0) { 00278 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00279 return err; 00280 } 00281 } 00282 if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) { 00283 if (GWEN_DB_Node_List_Next(n)) { 00284 /* only insert newline if something 00285 * is following on the same level */ 00286 GWEN_FASTBUFFER_WRITELINE(fb, err, ""); 00287 if (err<0) { 00288 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00289 return err; 00290 } 00291 } 00292 } 00293 } 00294 lastWasVar=0; 00295 break; 00296 00297 case GWEN_DB_NodeType_Var: 00298 cn=GWEN_DB_Node_List_First(n->children); 00299 if (cn) { 00300 char *typname; 00301 int namewritten; 00302 int values; 00303 00304 typname=0; 00305 namewritten=0; 00306 values=0; 00307 while(cn) { 00308 char numbuffer[32]; 00309 char *binbuffer=NULL; 00310 unsigned int bbsize; 00311 const char *pvalue=NULL; 00312 GWEN_BUFFER *vbuf=NULL; 00313 00314 switch(cn->typ) { 00315 case GWEN_DB_NodeType_ValueChar: 00316 typname="char "; 00317 pvalue=cn->data.dataChar; 00318 if (dbflags & GWEN_DB_FLAGS_ESCAPE_CHARVALUES) { 00319 vbuf=GWEN_Buffer_new(0, strlen(pvalue)+32, 0, 1); 00320 if (GWEN_Text_EscapeToBufferTolerant(pvalue, vbuf)) { 00321 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00322 GWEN_Buffer_free(vbuf); 00323 return 1; 00324 } 00325 pvalue=GWEN_Buffer_GetStart(vbuf); 00326 } 00327 break; 00328 00329 case GWEN_DB_NodeType_ValueInt: 00330 typname="int "; 00331 if (GWEN_Text_NumToString(cn->data.dataInt, 00332 numbuffer, 00333 sizeof(numbuffer)-1, 00334 0)<1) { 00335 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing numeric value"); 00336 return GWEN_ERROR_GENERIC; 00337 } 00338 pvalue=numbuffer; 00339 break; 00340 00341 case GWEN_DB_NodeType_ValueBin: 00342 bbsize=cn->dataSize*2+1; 00343 binbuffer=(char*)GWEN_Memory_malloc(bbsize); 00344 assert(binbuffer); 00345 typname="bin "; 00346 if (!GWEN_Text_ToHex(cn->data.dataBin, 00347 cn->dataSize, 00348 binbuffer, 00349 bbsize)) { 00350 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing binary value"); 00351 return GWEN_ERROR_GENERIC; 00352 } 00353 pvalue=binbuffer; 00354 break; 00355 00356 case GWEN_DB_NodeType_ValuePtr: 00357 DBG_DEBUG(GWEN_LOGDOMAIN, "Not writing ptr type"); 00358 break; 00359 00360 default: 00361 DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled type [%d]", cn->typ); 00362 break; 00363 } 00364 00365 if (pvalue) { 00366 if (!namewritten) { 00367 /* write name */ 00368 /* indend */ 00369 if (dbflags & GWEN_DB_FLAGS_INDEND) { 00370 for (i=0; i<insert; i++) { 00371 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' '); 00372 if (err<0) { 00373 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00374 GWEN_Memory_dealloc(binbuffer); 00375 GWEN_Buffer_free(vbuf); 00376 return 1; 00377 } 00378 } /* for */ 00379 } /* if indend */ 00380 if (!(dbflags & GWEN_DB_FLAGS_OMIT_TYPES)) { 00381 GWEN_FASTBUFFER_WRITEFORCED(fb, err, typname, -1); 00382 if (err<0) { 00383 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00384 GWEN_Memory_dealloc(binbuffer); 00385 GWEN_Buffer_free(vbuf); 00386 return 1; 00387 } 00388 } 00389 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) { 00390 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"'); 00391 if (err<0) { 00392 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00393 GWEN_Memory_dealloc(binbuffer); 00394 GWEN_Buffer_free(vbuf); 00395 return 1; 00396 } 00397 } 00398 GWEN_FASTBUFFER_WRITEFORCED(fb, err, n->data.dataName, -1); 00399 if (err<0) { 00400 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00401 GWEN_Memory_dealloc(binbuffer); 00402 GWEN_Buffer_free(vbuf); 00403 return 1; 00404 } 00405 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) { 00406 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"'); 00407 if (err<0) { 00408 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00409 GWEN_Memory_dealloc(binbuffer); 00410 GWEN_Buffer_free(vbuf); 00411 return 1; 00412 } 00413 } 00414 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ((dbflags & GWEN_DB_FLAGS_USE_COLON)?": ":"="), -1); 00415 if (err<0) { 00416 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00417 GWEN_Memory_dealloc(binbuffer); 00418 GWEN_Buffer_free(vbuf); 00419 return 1; 00420 } 00421 namewritten=1; 00422 } /* if !namewritten */ 00423 00424 if (values) { 00425 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ", ", -1); 00426 if (err<0) { 00427 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00428 GWEN_Memory_dealloc(binbuffer); 00429 GWEN_Buffer_free(vbuf); 00430 return 1; 00431 } 00432 } 00433 values++; 00434 if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) { 00435 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"'); 00436 if (err<0) { 00437 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00438 GWEN_Memory_dealloc(binbuffer); 00439 GWEN_Buffer_free(vbuf); 00440 return 1; 00441 } 00442 } 00443 00444 GWEN_FASTBUFFER_WRITEFORCED(fb, err, pvalue, -1); 00445 if (err<0) { 00446 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00447 GWEN_Memory_dealloc(binbuffer); 00448 GWEN_Buffer_free(vbuf); 00449 return 1; 00450 } 00451 00452 if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) { 00453 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"'); 00454 if (err<0) { 00455 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00456 GWEN_Memory_dealloc(binbuffer); 00457 GWEN_Buffer_free(vbuf); 00458 return 1; 00459 } 00460 } 00461 } /* if pvalue */ 00462 00463 GWEN_Memory_dealloc(binbuffer); 00464 GWEN_Buffer_free(vbuf); 00465 cn=GWEN_DB_Node_List_Next(cn); 00466 } /* while cn */ 00467 00468 if (namewritten) { 00469 GWEN_FASTBUFFER_WRITELINE(fb, err, ""); 00470 if (err<0) { 00471 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00472 return GWEN_ERROR_GENERIC; 00473 } 00474 } 00475 } /* if children */ 00476 lastWasVar=1; 00477 break; 00478 00479 default: 00480 DBG_WARN(GWEN_LOGDOMAIN, "[unhandled node type %d]", n->typ); 00481 } /* switch */ 00482 } /* if not volatile */ 00483 else { 00484 DBG_DEBUG(GWEN_LOGDOMAIN, "Node is volatile, not writing it"); 00485 } 00486 n=GWEN_DB_Node_List_Next(n); 00487 } /* while */ 00488 00489 return 0; 00490 } 00491 00492 00493 00494 int GWEN_DB_WriteToFastBuffer(GWEN_DB_NODE *node, 00495 GWEN_FAST_BUFFER *fb, 00496 uint32_t dbflags) { 00497 int rv; 00498 00499 rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0); 00500 if (rv<0) { 00501 return rv; 00502 } 00503 GWEN_FASTBUFFER_FLUSH(fb, rv); 00504 return rv; 00505 } 00506 00507 00508 00509 int GWEN_DB_WriteToIo(GWEN_DB_NODE *node, 00510 GWEN_SYNCIO *sio, 00511 uint32_t dbflags) { 00512 int rv; 00513 GWEN_FAST_BUFFER *fb; 00514 00515 fb=GWEN_FastBuffer_new(512, sio); 00516 if (dbflags & GWEN_DB_FLAGS_DOSMODE) 00517 GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE); 00518 rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0); 00519 if (rv<0) { 00520 GWEN_FastBuffer_free(fb); 00521 return rv; 00522 } 00523 GWEN_FASTBUFFER_FLUSH(fb, rv); 00524 GWEN_FastBuffer_free(fb); 00525 return rv; 00526 } 00527 00528 00529 00530 int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags){ 00531 int rv; 00532 GWEN_FSLOCK *lck=0; 00533 GWEN_SYNCIO *sio; 00534 00535 /* if locking requested */ 00536 if (dbflags & GWEN_DB_FLAGS_LOCKFILE) { 00537 GWEN_FSLOCK_RESULT res; 00538 00539 lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile); 00540 assert(lck); 00541 res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0); 00542 if (res!=GWEN_FSLock_ResultOk) { 00543 DBG_ERROR(GWEN_LOGDOMAIN, 00544 "Could not apply lock to file \"%s\" (%d)", 00545 fname, res); 00546 GWEN_FSLock_free(lck); 00547 return -1; 00548 } 00549 } 00550 00551 /* open file */ 00552 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateAlways); 00553 if (dbflags & GWEN_DB_FLAGS_APPEND_FILE) 00554 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_APPEND); 00555 GWEN_SyncIo_AddFlags(sio, 00556 GWEN_SYNCIO_FILE_FLAGS_READ | 00557 GWEN_SYNCIO_FILE_FLAGS_WRITE | 00558 GWEN_SYNCIO_FILE_FLAGS_UREAD | 00559 GWEN_SYNCIO_FILE_FLAGS_UWRITE); 00560 rv=GWEN_SyncIo_Connect(sio); 00561 if (rv<0) { 00562 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00563 GWEN_SyncIo_free(sio); 00564 if (lck) { 00565 GWEN_FSLock_Unlock(lck); 00566 GWEN_FSLock_free(lck); 00567 } 00568 return rv; 00569 } 00570 00571 rv=GWEN_DB_WriteToIo(n, sio, dbflags); 00572 if (rv<0) { 00573 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00574 GWEN_SyncIo_Disconnect(sio); 00575 GWEN_SyncIo_free(sio); 00576 if (lck) { 00577 GWEN_FSLock_Unlock(lck); 00578 GWEN_FSLock_free(lck); 00579 } 00580 return rv; 00581 } 00582 00583 rv=GWEN_SyncIo_Disconnect(sio); 00584 if (rv<0) { 00585 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00586 GWEN_SyncIo_free(sio); 00587 if (lck) { 00588 GWEN_FSLock_Unlock(lck); 00589 GWEN_FSLock_free(lck); 00590 } 00591 return rv; 00592 } 00593 GWEN_SyncIo_free(sio); 00594 00595 /* remove lock, if any */ 00596 if (lck) { 00597 GWEN_FSLOCK_RESULT res; 00598 00599 res=GWEN_FSLock_Unlock(lck); 00600 if (res!=GWEN_FSLock_ResultOk) { 00601 DBG_WARN(GWEN_LOGDOMAIN, 00602 "Could not remove lock on file \"%s\" (%d)", 00603 fname, res); 00604 } 00605 GWEN_FSLock_free(lck); 00606 } 00607 00608 return 0; 00609 } 00610 00611 00612 00613 int GWEN_DB__ReadValues(GWEN_DB_NODE *n, 00614 uint32_t dbflags, 00615 const char *typeName, 00616 const char *varName, 00617 uint8_t *p) { 00618 GWEN_DB_NODE_TYPE nodeType=GWEN_DB_NodeType_ValueChar; 00619 GWEN_DB_NODE *dbVar; 00620 GWEN_BUFFER *wbuf; 00621 uint8_t *pDebug; 00622 00623 pDebug=p; 00624 00625 if (typeName==NULL) 00626 typeName="char"; 00627 if (strcasecmp(typeName, "int")==0) 00628 nodeType=GWEN_DB_NodeType_ValueInt; 00629 else if (strcasecmp(typeName, "char")==0) 00630 nodeType=GWEN_DB_NodeType_ValueChar; 00631 else if (strcasecmp(typeName, "bin")==0) 00632 nodeType=GWEN_DB_NodeType_ValueBin; 00633 else { 00634 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown type \"%s\"", typeName); 00635 return GWEN_ERROR_BAD_DATA; 00636 } 00637 00638 dbVar=GWEN_DB_GetNode(n, varName, dbflags | GWEN_PATH_FLAGS_VARIABLE); 00639 if (dbVar==NULL) { 00640 DBG_INFO(GWEN_LOGDOMAIN, "Variable [%s] is not available", varName); 00641 return GWEN_ERROR_GENERIC; 00642 } 00643 00644 wbuf=GWEN_Buffer_new(0, 32, 0, 1); 00645 for (;;) { 00646 int quotes=0; 00647 GWEN_DB_NODE *dbVal=NULL; 00648 const char *v; 00649 00650 while(*p && isspace(*p)) 00651 p++; 00652 if (!*p) { 00653 DBG_INFO(GWEN_LOGDOMAIN, "Missing value"); 00654 GWEN_Buffer_free(wbuf); 00655 return GWEN_ERROR_BAD_DATA; 00656 } 00657 00658 if (*p=='"') { 00659 quotes=1; 00660 p++; 00661 } 00662 00663 while(*p) { 00664 if (*p=='%') { 00665 uint8_t c; 00666 uint8_t cHex; 00667 00668 /* get first nibble */ 00669 p++; 00670 if (!*p) { 00671 DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence"); 00672 GWEN_Buffer_free(wbuf); 00673 return GWEN_ERROR_BAD_DATA; 00674 } 00675 c=toupper(*p)-'0'; 00676 if (c>9) c-=7; 00677 cHex=c<<4; 00678 00679 p++; 00680 if (!*p) { 00681 DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence"); 00682 GWEN_Buffer_free(wbuf); 00683 return GWEN_ERROR_BAD_DATA; 00684 } 00685 c=toupper(*p)-'0'; 00686 if (c>9) c-=7; 00687 cHex|=c; 00688 GWEN_Buffer_AppendByte(wbuf, cHex); 00689 } 00690 else 00691 if (quotes) { 00692 if (*p=='"') { 00693 p++; 00694 break; 00695 } 00696 else 00697 GWEN_Buffer_AppendByte(wbuf, *p); 00698 } 00699 else { 00700 if (*p==',' || *p==';' || *p=='#') 00701 break; 00702 else if (*p=='"') { 00703 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected quotation mark (Line: [%s], parsed: [%s]", 00704 pDebug, GWEN_Buffer_GetStart(wbuf)); 00705 GWEN_Buffer_free(wbuf); 00706 return GWEN_ERROR_BAD_DATA; 00707 } 00708 else 00709 GWEN_Buffer_AppendByte(wbuf, *p); 00710 } 00711 p++; 00712 } 00713 00714 v=GWEN_Buffer_GetStart(wbuf); 00715 if (nodeType==GWEN_DB_NodeType_ValueInt) { 00716 int i; 00717 00718 if (1!=sscanf(v, "%d", &i)) { 00719 DBG_INFO(GWEN_LOGDOMAIN, "Not an integer value [%s]", v); 00720 GWEN_Buffer_free(wbuf); 00721 return GWEN_ERROR_BAD_DATA; 00722 } 00723 dbVal=GWEN_DB_ValueInt_new(i); 00724 } 00725 else if (nodeType==GWEN_DB_NodeType_ValueChar) 00726 dbVal=GWEN_DB_ValueChar_new(v); 00727 else if (nodeType==GWEN_DB_NodeType_ValueBin) { 00728 GWEN_BUFFER *bbuf; 00729 int rv; 00730 00731 bbuf=GWEN_Buffer_new(0, (GWEN_Buffer_GetUsedBytes(wbuf)/2)+1, 0, 1); 00732 rv=GWEN_Text_FromHexBuffer(v, bbuf); 00733 if (rv) { 00734 DBG_INFO(GWEN_LOGDOMAIN, "Bad bin value [%s]", v); 00735 GWEN_Buffer_free(bbuf); 00736 GWEN_Buffer_free(wbuf); 00737 return GWEN_ERROR_BAD_DATA; 00738 } 00739 dbVal=GWEN_DB_ValueBin_new(GWEN_Buffer_GetStart(bbuf), 00740 GWEN_Buffer_GetUsedBytes(bbuf)); 00741 GWEN_Buffer_free(bbuf); 00742 } 00743 else { 00744 /* should never reach this point */ 00745 assert(0); 00746 } 00747 GWEN_DB_Node_Append(dbVar, dbVal); 00748 00749 /* skip blanks if any */ 00750 while(*p && isspace(*p)) 00751 p++; 00752 if (!*p || *p==';' || *p=='#') 00753 break; 00754 else if (*p!=',') { 00755 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected character [%s]", p); 00756 GWEN_Buffer_free(wbuf); 00757 return GWEN_ERROR_BAD_DATA; 00758 } 00759 p++; 00760 GWEN_Buffer_Reset(wbuf); 00761 } 00762 00763 GWEN_Buffer_free(wbuf); 00764 return 0; 00765 } 00766 00767 00768 00769 int GWEN_DB_ReadFromFastBuffer(GWEN_DB_NODE *n, 00770 GWEN_FAST_BUFFER *fb, 00771 uint32_t dbflags) { 00772 GWEN_BUFFER *lbuf; 00773 GWEN_BUFFER *tbuf; 00774 int level=0; 00775 int someLinesRead=0; 00776 00777 lbuf=GWEN_Buffer_new(0, 128, 0, 1); 00778 tbuf=GWEN_Buffer_new(0, 128, 0, 1); 00779 00780 for (;;) { 00781 int rv; 00782 uint8_t *p; 00783 00784 rv=GWEN_FastBuffer_ReadLineToBuffer(fb, lbuf); 00785 if (rv<0) { 00786 if (rv==GWEN_ERROR_EOF) { 00787 if (!someLinesRead && !(dbflags & GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM)){ 00788 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected EOF (%d)", rv); 00789 GWEN_Buffer_free(tbuf); 00790 GWEN_Buffer_free(lbuf); 00791 return rv; 00792 } 00793 break; 00794 } 00795 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00796 GWEN_Buffer_free(tbuf); 00797 GWEN_Buffer_free(lbuf); 00798 return rv; 00799 } 00800 00801 if (GWEN_Buffer_GetUsedBytes(lbuf)==0) { 00802 if (dbflags & GWEN_DB_FLAGS_UNTIL_EMPTY_LINE) { 00803 break; 00804 } 00805 } 00806 else { 00807 someLinesRead=1; 00808 p=(uint8_t*)GWEN_Buffer_GetStart(lbuf); 00809 while(*p && isspace(*p)) 00810 p++; 00811 if (*p) { 00812 uint8_t *p1begin=NULL, *p1end=NULL; 00813 uint8_t *p2begin=NULL, *p2end=NULL; 00814 00815 /* non-empty line */ 00816 if (*p=='}') { 00817 /* found end of current group */ 00818 if (level<1) { 00819 DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket"); 00820 GWEN_Buffer_free(tbuf); 00821 GWEN_Buffer_free(lbuf); 00822 return GWEN_ERROR_BAD_DATA; 00823 } 00824 n=n->parent; 00825 assert(n); /* internal error if parent not found */ 00826 assert(n->typ==GWEN_DB_NodeType_Group); /* internal error if parent is not a group */ 00827 level--; 00828 } 00829 else if (*p=='#') { 00830 /* comment only line */ 00831 } 00832 else { 00833 p1begin=p; 00834 /* read first token */ 00835 while(*p && !isspace(*p) && 00836 *p!='{' && 00837 *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') && 00838 *p!='}' && 00839 *p!=',' && 00840 *p!=';') 00841 p++; 00842 if (!*p) { 00843 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token"); 00844 GWEN_Buffer_Dump(lbuf, 2); 00845 GWEN_Buffer_free(tbuf); 00846 GWEN_Buffer_free(lbuf); 00847 return GWEN_ERROR_BAD_DATA; 00848 } 00849 p1end=p; 00850 00851 /* get to start of 2nd token */ 00852 while(*p && isspace(*p)) 00853 p++; 00854 if (!*p) { 00855 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token"); 00856 GWEN_Buffer_free(tbuf); 00857 GWEN_Buffer_free(lbuf); 00858 return GWEN_ERROR_BAD_DATA; 00859 } 00860 00861 if (*p=='{') { 00862 GWEN_DB_NODE *newGr; 00863 00864 /* found start of group */ 00865 *p1end=0; 00866 rv=GWEN_DB_UnescapeToBufferTolerant((const char*)p1begin, tbuf); 00867 if (rv<0) { 00868 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00869 GWEN_Buffer_free(tbuf); 00870 GWEN_Buffer_free(lbuf); 00871 return rv; 00872 } 00873 newGr=GWEN_DB_GetGroup(n, dbflags, GWEN_Buffer_GetStart(tbuf)); 00874 if (newGr==NULL) { 00875 DBG_INFO(GWEN_LOGDOMAIN, "Could not create group [%s]", GWEN_Buffer_GetStart(tbuf)); 00876 GWEN_Buffer_free(tbuf); 00877 GWEN_Buffer_free(lbuf); 00878 return GWEN_ERROR_GENERIC; 00879 } 00880 GWEN_Buffer_Reset(tbuf); 00881 n=newGr; 00882 level++; 00883 } 00884 else if (*p=='=' || *p==':') { 00885 /* found short variable definition */ 00886 *p1end=0; 00887 p++; 00888 rv=GWEN_DB__ReadValues(n, dbflags, NULL, (const char*)p1begin, p); 00889 if (rv) { 00890 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00891 GWEN_Buffer_free(tbuf); 00892 GWEN_Buffer_free(lbuf); 00893 return rv; 00894 } 00895 } 00896 else if (*p==',' || *p==';') { 00897 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected delimiter found"); 00898 GWEN_Buffer_free(tbuf); 00899 GWEN_Buffer_free(lbuf); 00900 return GWEN_ERROR_BAD_DATA; 00901 } 00902 else { 00903 /* 2nd token, so this should be a standard variable definition */ 00904 p2begin=p; 00905 while(*p && 00906 !isspace(*p) && 00907 *p!='{' && 00908 *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') && 00909 *p!='}' && 00910 *p!=',' && 00911 *p!=';') 00912 p++; 00913 if (!*p) { 00914 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token [%s], [%s]", p1begin, p2begin); 00915 GWEN_Buffer_free(tbuf); 00916 GWEN_Buffer_free(lbuf); 00917 return GWEN_ERROR_BAD_DATA; 00918 } 00919 p2end=p; 00920 if (isspace(*p)) { 00921 while(*p && isspace(*p)) 00922 p++; 00923 if (!*p) { 00924 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token"); 00925 GWEN_Buffer_free(tbuf); 00926 GWEN_Buffer_free(lbuf); 00927 return GWEN_ERROR_BAD_DATA; 00928 } 00929 } 00930 if (*p!='=' && *p!=':') { 00931 DBG_INFO(GWEN_LOGDOMAIN, "Equation mark expected"); 00932 GWEN_Buffer_free(tbuf); 00933 GWEN_Buffer_free(lbuf); 00934 return GWEN_ERROR_BAD_DATA; 00935 } 00936 p++; 00937 00938 *p1end=0; 00939 *p2end=0; 00940 rv=GWEN_DB__ReadValues(n, dbflags, (const char*)p1begin, (const char*)p2begin, p); 00941 if (rv) { 00942 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00943 GWEN_Buffer_free(tbuf); 00944 GWEN_Buffer_free(lbuf); 00945 return rv; 00946 } 00947 } 00948 } 00949 } 00950 } 00951 GWEN_Buffer_Reset(lbuf); 00952 } 00953 00954 if (level) { 00955 DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket (too few)"); 00956 GWEN_Buffer_free(tbuf); 00957 GWEN_Buffer_free(lbuf); 00958 return GWEN_ERROR_BAD_DATA; 00959 } 00960 00961 GWEN_Buffer_free(tbuf); 00962 GWEN_Buffer_free(lbuf); 00963 00964 return 0; 00965 } 00966 00967 00968 00969 int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags) { 00970 GWEN_FAST_BUFFER *fb; 00971 int rv; 00972 00973 /* prepare fast buffer */ 00974 fb=GWEN_FastBuffer_new(1024, sio); 00975 if (dbflags & GWEN_DB_FLAGS_DOSMODE) 00976 GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE); 00977 00978 /* read from it */ 00979 rv=GWEN_DB_ReadFromFastBuffer(n, fb, dbflags); 00980 if (rv<0) { 00981 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00982 GWEN_FastBuffer_free(fb); 00983 return rv; 00984 } 00985 00986 GWEN_FastBuffer_free(fb); 00987 00988 return 0; 00989 } 00990 00991 00992 00993 int GWEN_DB_ReadFile(GWEN_DB_NODE *n, 00994 const char *fname, 00995 uint32_t dbflags) { 00996 GWEN_SYNCIO *sio; 00997 int rv; 00998 00999 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting); 01000 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ); 01001 rv=GWEN_SyncIo_Connect(sio); 01002 if (rv<0) { 01003 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 01004 GWEN_SyncIo_free(sio); 01005 return rv; 01006 } 01007 01008 /* read from it */ 01009 rv=GWEN_DB_ReadFromIo(n, sio, dbflags); 01010 if (rv<0) { 01011 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 01012 GWEN_SyncIo_Disconnect(sio); 01013 GWEN_SyncIo_free(sio); 01014 return rv; 01015 } 01016 01017 GWEN_SyncIo_Disconnect(sio); 01018 GWEN_SyncIo_free(sio); 01019 return 0; 01020 } 01021 01022 01023 01024 int GWEN_DB_ReadFromString(GWEN_DB_NODE *n, 01025 const char *str, 01026 int len, 01027 uint32_t dbflags) { 01028 GWEN_SYNCIO *sio; 01029 int rv; 01030 01031 if (len==0) 01032 len=strlen(str); 01033 01034 sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*) str, len); 01035 rv=GWEN_DB_ReadFromIo(n, sio, dbflags); 01036 if (rv<0) { 01037 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 01038 GWEN_SyncIo_free(sio); 01039 return rv; 01040 } 01041 01042 GWEN_SyncIo_free(sio); 01043 01044 return 0; 01045 } 01046 01047 01048 01049 int GWEN_DB_WriteToBuffer(GWEN_DB_NODE *n, 01050 GWEN_BUFFER *buf, 01051 uint32_t dbflags) { 01052 GWEN_SYNCIO *sio; 01053 int rv; 01054 01055 /* create SyncIO, don't take over buf */ 01056 sio=GWEN_SyncIo_Memory_new(buf, 0); 01057 rv=GWEN_DB_WriteToIo(n, sio, dbflags); 01058 if (rv<0) { 01059 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 01060 GWEN_SyncIo_free(sio); 01061 return rv; 01062 } 01063 01064 GWEN_SyncIo_free(sio); 01065 return 0; 01066 } 01067 01068 01069 01070 01071 01072 01073 01074 01075 01076 01077 01078