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