gwenhywfar 4.0.3

dbrw.c

Go to the documentation of this file.
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