gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 begin : Fri Jul 04 2003 00003 copyright : (C) 2003 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 #ifdef HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #define DISABLE_DEBUGLOG 00030 00031 #include <gwenhywfar/gwenhywfarapi.h> 00032 #include <msgengine_p.h> 00033 #include <gwenhywfar/xml.h> 00034 #include <gwenhywfar/text.h> 00035 #include <gwenhywfar/misc.h> 00036 #include <gwenhywfar/path.h> 00037 #include <gwenhywfar/debug.h> 00038 #include <gwenhywfar/buffer.h> 00039 #include <stdlib.h> 00040 #include <assert.h> 00041 #include <string.h> 00042 #include <ctype.h> 00043 00044 00045 GWEN_INHERIT_FUNCTIONS(GWEN_MSGENGINE) 00046 00047 00048 GWEN_MSGENGINE *GWEN_MsgEngine_new(void){ 00049 GWEN_MSGENGINE *e; 00050 00051 GWEN_NEW_OBJECT(GWEN_MSGENGINE, e); 00052 GWEN_INHERIT_INIT(GWEN_MSGENGINE, e); 00053 e->charsToEscape=strdup(GWEN_MSGENGINE_CHARSTOESCAPE); 00054 e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS); 00055 e->globalValues=GWEN_DB_Group_new("globalvalues"); 00056 e->escapeChar='\\'; 00057 00058 e->usage=1; 00059 return e; 00060 } 00061 00062 00063 void GWEN_MsgEngine_free(GWEN_MSGENGINE *e){ 00064 if (e) { 00065 assert(e->usage); 00066 if (--(e->usage)==0) { 00067 GWEN_INHERIT_FINI(GWEN_MSGENGINE, e); 00068 00069 if (e->inheritorData && e->freeDataPtr) 00070 e->freeDataPtr(e); 00071 if (e->ownDefs) 00072 GWEN_XMLNode_free(e->defs); 00073 free(e->charsToEscape); 00074 free(e->delimiters); 00075 GWEN_DB_Group_free(e->globalValues); 00076 if (e->trustInfos) { 00077 /* free trustInfos */ 00078 GWEN_MSGENGINE_TRUSTEDDATA *td, *tdn; 00079 00080 td=e->trustInfos; 00081 while(td) { 00082 tdn=td->next; 00083 GWEN_MsgEngine_TrustedData_free(td); 00084 td=tdn; 00085 } /* while */ 00086 } 00087 GWEN_FREE_OBJECT(e); 00088 } 00089 } 00090 } 00091 00092 00093 00094 void GWEN_MsgEngine_Attach(GWEN_MSGENGINE *e){ 00095 assert(e); 00096 e->usage++; 00097 } 00098 00099 00100 void GWEN_MsgEngine_SetEscapeChar(GWEN_MSGENGINE *e, char c){ 00101 assert(e); 00102 e->escapeChar=c; 00103 } 00104 00105 00106 00107 char GWEN_MsgEngine_GetEscapeChar(GWEN_MSGENGINE *e){ 00108 assert(e); 00109 return e->escapeChar; 00110 } 00111 00112 00113 00114 void GWEN_MsgEngine_SetCharsToEscape(GWEN_MSGENGINE *e, const char *c){ 00115 assert(e); 00116 free(e->charsToEscape); 00117 e->charsToEscape=strdup(c); 00118 } 00119 00120 00121 00122 const char *GWEN_MsgEngine_GetCharsToEscape(GWEN_MSGENGINE *e){ 00123 assert(e); 00124 return e->charsToEscape; 00125 } 00126 00127 00128 00129 void GWEN_MsgEngine_SetDelimiters(GWEN_MSGENGINE *e, const char *s){ 00130 assert(e); 00131 free(e->delimiters); 00132 if (s) 00133 e->delimiters=strdup(s); 00134 else 00135 e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS); 00136 } 00137 00138 00139 00140 const char *GWEN_MsgEngine_GetDelimiters(GWEN_MSGENGINE *e){ 00141 assert(e); 00142 return e->delimiters; 00143 } 00144 00145 00146 00147 void GWEN_MsgEngine_SetMode(GWEN_MSGENGINE *e, const char *mode){ 00148 GWEN_DB_NODE *db; 00149 00150 assert(e); 00151 db=GWEN_MsgEngine__GetGlobalValues(e); 00152 00153 if (mode) 00154 GWEN_DB_SetCharValue(db, 00155 GWEN_DB_FLAGS_OVERWRITE_VARS, 00156 "engine/secmode", 00157 mode); 00158 else 00159 GWEN_DB_DeleteVar(db, "engine/secmode"); 00160 } 00161 00162 00163 const char *GWEN_MsgEngine_GetMode(GWEN_MSGENGINE *e){ 00164 GWEN_DB_NODE *db; 00165 00166 assert(e); 00167 db=GWEN_MsgEngine__GetGlobalValues(e); 00168 return GWEN_DB_GetCharValue(db, "engine/secmode", 0, 0); 00169 } 00170 00171 00172 00173 GWEN_DB_NODE *GWEN_MsgEngine__GetGlobalValues(GWEN_MSGENGINE *e){ 00174 GWEN_DB_NODE *globalValues; 00175 00176 assert(e); 00177 if (e->getGlobalValuesPtr) { 00178 globalValues=e->getGlobalValuesPtr(e); 00179 if (!globalValues) 00180 globalValues=e->globalValues; 00181 } 00182 else { 00183 globalValues=e->globalValues; 00184 } 00185 assert(globalValues); 00186 return globalValues; 00187 } 00188 00189 00190 00191 unsigned int GWEN_MsgEngine_GetProtocolVersion(GWEN_MSGENGINE *e){ 00192 GWEN_DB_NODE *db; 00193 00194 assert(e); 00195 db=GWEN_MsgEngine__GetGlobalValues(e); 00196 return GWEN_DB_GetIntValue(db, "engine/pversion", 0, 0); 00197 } 00198 00199 00200 00201 void GWEN_MsgEngine_SetProtocolVersion(GWEN_MSGENGINE *e, 00202 unsigned int p){ 00203 GWEN_DB_NODE *db; 00204 00205 assert(e); 00206 db=GWEN_MsgEngine__GetGlobalValues(e); 00207 00208 GWEN_DB_SetIntValue(db, 00209 GWEN_DB_FLAGS_OVERWRITE_VARS, 00210 "engine/pversion", 00211 p); 00212 } 00213 00214 00215 00216 GWEN_XMLNODE *GWEN_MsgEngine_GetDefinitions(GWEN_MSGENGINE *e){ 00217 assert(e); 00218 return e->defs; 00219 } 00220 00221 00222 void GWEN_MsgEngine_SetDefinitions(GWEN_MSGENGINE *e, 00223 GWEN_XMLNODE *n, 00224 int take){ 00225 assert(e); 00226 if (e->ownDefs) 00227 GWEN_XMLNode_free(e->defs); 00228 e->defs=n; 00229 e->ownDefs=take; 00230 } 00231 00232 00233 00234 void 00235 GWEN_MsgEngine_SetGetGlobalValuesFunction(GWEN_MSGENGINE *e, 00236 GWEN_MSGENGINE_GETGLOBALVALUES_PTR p){ 00237 assert(e); 00238 e->getGlobalValuesPtr=p; 00239 } 00240 00241 00242 00243 GWEN_MSGENGINE_GETGLOBALVALUES_PTR 00244 GWEN_MsgEngine_GetGetGlobalValuesFunction(GWEN_MSGENGINE *e){ 00245 assert(e); 00246 return e->getGlobalValuesPtr; 00247 } 00248 00249 00250 00251 void GWEN_MsgEngine_SetTypeReadFunction(GWEN_MSGENGINE *e, 00252 GWEN_MSGENGINE_TYPEREAD_PTR p){ 00253 assert(e); 00254 e->typeReadPtr=p; 00255 } 00256 00257 00258 00259 GWEN_MSGENGINE_TYPEREAD_PTR 00260 GWEN_MsgEngine_GetTypeReadFunction(GWEN_MSGENGINE *e){ 00261 assert(e); 00262 return e->typeReadPtr; 00263 } 00264 00265 00266 00267 void GWEN_MsgEngine_SetTypeWriteFunction(GWEN_MSGENGINE *e, 00268 GWEN_MSGENGINE_TYPEWRITE_PTR p){ 00269 assert(e); 00270 e->typeWritePtr=p; 00271 } 00272 00273 00274 00275 GWEN_MSGENGINE_TYPEWRITE_PTR 00276 GWEN_MsgEngine_GetTypeWriteFunction(GWEN_MSGENGINE *e){ 00277 assert(e); 00278 return e->typeWritePtr; 00279 } 00280 00281 00282 00283 void GWEN_MsgEngine_SetTypeCheckFunction(GWEN_MSGENGINE *e, 00284 GWEN_MSGENGINE_TYPECHECK_PTR p){ 00285 assert(e); 00286 e->typeCheckPtr=p; 00287 } 00288 00289 00290 00291 GWEN_MSGENGINE_TYPECHECK_PTR 00292 GWEN_MsgEngine_GetTypeCheckFunction(GWEN_MSGENGINE *e){ 00293 assert(e); 00294 return e->typeCheckPtr; 00295 } 00296 00297 00298 00299 00300 00301 00302 void GWEN_MsgEngine_SetBinTypeReadFunction(GWEN_MSGENGINE *e, 00303 GWEN_MSGENGINE_BINTYPEREAD_PTR p){ 00304 assert(e); 00305 e->binTypeReadPtr=p; 00306 } 00307 00308 00309 00310 GWEN_MSGENGINE_BINTYPEREAD_PTR 00311 GWEN_MsgEngine_GetBinTypeReadFunction(GWEN_MSGENGINE *e){ 00312 assert(e); 00313 return e->binTypeReadPtr; 00314 } 00315 00316 00317 00318 void 00319 GWEN_MsgEngine_SetBinTypeWriteFunction(GWEN_MSGENGINE *e, 00320 GWEN_MSGENGINE_BINTYPEWRITE_PTR p){ 00321 assert(e); 00322 e->binTypeWritePtr=p; 00323 } 00324 00325 00326 00327 GWEN_MSGENGINE_BINTYPEWRITE_PTR 00328 GWEN_MsgEngine_GetBinTypeWriteFunction(GWEN_MSGENGINE *e){ 00329 assert(e); 00330 return e->binTypeWritePtr; 00331 } 00332 00333 00334 00335 void 00336 GWEN_MsgEngine_SetGetCharValueFunction(GWEN_MSGENGINE *e, 00337 GWEN_MSGENGINE_GETCHARVALUE_PTR p){ 00338 assert(e); 00339 e->getCharValuePtr=p; 00340 } 00341 00342 00343 00344 void 00345 GWEN_MsgEngine_SetGetIntValueFunction(GWEN_MSGENGINE *e, 00346 GWEN_MSGENGINE_GETINTVALUE_PTR p){ 00347 assert(e); 00348 e->getIntValuePtr=p; 00349 } 00350 00351 00352 00353 void 00354 GWEN_MsgEngine_SetFreeDataFunction(GWEN_MSGENGINE *e, 00355 GWEN_MSGENGINE_FREEDATA_PTR p){ 00356 assert(e); 00357 DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetFreeDataFunction: Deprecated"); 00358 e->freeDataPtr=p; 00359 } 00360 00361 00362 00363 void *GWEN_MsgEngine_GetInheritorData(const GWEN_MSGENGINE *e){ 00364 assert(e); 00365 return e->inheritorData; 00366 } 00367 00368 00369 00370 void GWEN_MsgEngine_SetInheritorData(GWEN_MSGENGINE *e, void *d){ 00371 assert(e); 00372 DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetInheritorData: Deprecated"); 00373 if (e->inheritorData && e->freeDataPtr) 00374 e->freeDataPtr(e); 00375 e->inheritorData=d; 00376 } 00377 00378 00379 00380 int GWEN_MsgEngine__WriteValue(GWEN_MSGENGINE *e, 00381 GWEN_BUFFER *gbuf, 00382 GWEN_BUFFER *data, 00383 GWEN_XMLNODE *node) { 00384 unsigned int minsize; 00385 unsigned int maxsize; 00386 unsigned int fixSize; 00387 unsigned int startPos; 00388 int filler; 00389 const char *type; 00390 const char *name; 00391 int rv; 00392 00393 /* get some sizes */ 00394 minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); 00395 maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); 00396 fixSize=atoi(GWEN_XMLNode_GetProperty(node, "size","0")); 00397 filler=atoi(GWEN_XMLNode_GetProperty(node, "filler","0")); 00398 type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); 00399 name=GWEN_XMLNode_GetProperty(node, "name","<unnamed>"); 00400 startPos=GWEN_Buffer_GetPos(gbuf); 00401 00402 /* check sizes */ 00403 if (minsize && GWEN_Buffer_GetUsedBytes(data)<minsize) { 00404 DBG_ERROR(GWEN_LOGDOMAIN, "Data too short (minsize is %d)", minsize); 00405 return -1; 00406 } 00407 if (maxsize && GWEN_Buffer_GetUsedBytes(data)>maxsize) { 00408 DBG_ERROR(GWEN_LOGDOMAIN, "Data too long (maxsize is %d)", maxsize); 00409 return -1; 00410 } 00411 00412 rv=1; 00413 if (e->typeWritePtr) { 00414 rv=e->typeWritePtr(e, 00415 gbuf, 00416 data, 00417 node); 00418 } 00419 if (rv==-1) { 00420 DBG_INFO(GWEN_LOGDOMAIN, "External type writing failed"); 00421 return -1; 00422 } 00423 else if (rv==1) { 00424 int i; 00425 00426 /* type not handled externally, so handle it myself */ 00427 if (strcasecmp(type, "bin")==0) { 00428 DBG_DEBUG(GWEN_LOGDOMAIN, "Writing binary data (%d bytes added to %d bytes)", 00429 GWEN_Buffer_GetUsedBytes(data), 00430 GWEN_Buffer_GetUsedBytes(gbuf)); 00431 if (GWEN_Buffer_AllocRoom(gbuf, 10+GWEN_Buffer_GetUsedBytes(data))) { 00432 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00433 return -1; 00434 } 00435 sprintf(GWEN_Buffer_GetPosPointer(gbuf), 00436 "@%d@", 00437 GWEN_Buffer_GetUsedBytes(data)); 00438 00439 00440 i=strlen(GWEN_Buffer_GetPosPointer(gbuf)); 00441 GWEN_Buffer_IncrementPos(gbuf, i); 00442 GWEN_Buffer_AdjustUsedBytes(gbuf); 00443 GWEN_Buffer_AppendBuffer(gbuf, data); 00444 } /* if type is "bin" */ 00445 else if (strcasecmp(type, "num")==0) { 00446 int num; 00447 unsigned int len; 00448 unsigned int lj; 00449 00450 num=atoi(GWEN_Buffer_GetPosPointer(data)); 00451 len=strlen(GWEN_Buffer_GetPosPointer(data)); 00452 00453 if (atoi(GWEN_XMLNode_GetProperty(node, "leftfill","0"))) { 00454 if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) { 00455 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00456 return -1; 00457 } 00458 00459 /* fill left */ 00460 for (lj=0; lj<(maxsize-len); lj++) 00461 GWEN_Buffer_AppendByte(gbuf, '0'); 00462 00463 /* write value */ 00464 for (lj=0; lj<len; lj++) 00465 GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data)); 00466 } 00467 else if (atoi(GWEN_XMLNode_GetProperty(node, "rightfill","0"))) { 00468 if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) { 00469 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00470 return -1; 00471 } 00472 00473 /* write value */ 00474 for (lj=0; lj<len; lj++) 00475 GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data)); 00476 00477 /* fill right */ 00478 for (lj=0; lj<(maxsize-len); lj++) 00479 GWEN_Buffer_AppendByte(gbuf, '0'); 00480 } 00481 else { 00482 if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) { 00483 DBG_ERROR(GWEN_LOGDOMAIN, "Maxsize in XML file is higher than the buffer size"); 00484 return -1; 00485 } 00486 for (lj=0; lj<len; lj++) 00487 GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data)); 00488 } 00489 } /* if type is num */ 00490 else { 00491 /* TODO: Check for valids */ 00492 const char *p; 00493 int lastWasEscape; 00494 unsigned int pcount; 00495 00496 p=GWEN_Buffer_GetPosPointer(data); 00497 pcount=0; 00498 lastWasEscape=0; 00499 while(*p && pcount<GWEN_Buffer_GetUsedBytes(data)) { 00500 int c; 00501 00502 c=(unsigned char)*p; 00503 if (lastWasEscape) { 00504 lastWasEscape=0; 00505 switch(c) { 00506 case 'r': c='\r'; break; 00507 case 'n': c='\n'; break; 00508 case 'f': c='\f'; break; 00509 case 't': c='\t'; break; 00510 default: c=(unsigned char)*p; 00511 } /* switch */ 00512 } 00513 else { 00514 if (*p=='\\') { 00515 lastWasEscape=1; 00516 c=-1; 00517 } 00518 else 00519 c=(unsigned char)*p; 00520 } 00521 if (c!=-1) { 00522 int needsEscape; 00523 00524 needsEscape=0; 00525 if (c==e->escapeChar) 00526 needsEscape=1; 00527 else { 00528 if (e->charsToEscape) 00529 if (strchr(e->charsToEscape, c)) 00530 needsEscape=1; 00531 } 00532 if (needsEscape) { 00533 /* write escape char */ 00534 if (GWEN_Buffer_AppendByte(gbuf, 00535 e->escapeChar)) { 00536 return -1; 00537 } 00538 } 00539 if (GWEN_Buffer_AppendByte(gbuf, c)) { 00540 return -1; 00541 } 00542 } 00543 p++; 00544 pcount++; 00545 } /* while */ 00546 if (pcount<GWEN_Buffer_GetUsedBytes(data)) { 00547 DBG_WARN(GWEN_LOGDOMAIN, "Premature end of string (%d<%d)", 00548 pcount, GWEN_Buffer_GetUsedBytes(data)); 00549 } 00550 if (*p) { 00551 DBG_WARN(GWEN_LOGDOMAIN, 00552 "String for \"%s\" (type %s) is longer than expected " 00553 "(no #0 at pos=%d)", 00554 name, type, 00555 GWEN_Buffer_GetUsedBytes(data)-1); 00556 } 00557 } /* if type is not BIN */ 00558 } /* if type not external */ 00559 else { 00560 DBG_INFO(GWEN_LOGDOMAIN, "Type \"%s\" (for %s) is external (write)", 00561 type, name); 00562 00563 } /* if external type */ 00564 00565 /* fill data */ 00566 if (fixSize) { 00567 uint32_t bs; 00568 unsigned int j; 00569 00570 bs=GWEN_Buffer_GetPos(gbuf)-startPos; 00571 if (bs>fixSize) { 00572 DBG_ERROR(GWEN_LOGDOMAIN, 00573 "Data too long (size is %d, fixed size is %d)", 00574 bs, fixSize); 00575 return -1; 00576 } 00577 00578 for (j=bs; j<fixSize; j++) 00579 GWEN_Buffer_AppendByte(gbuf, (unsigned char)filler); 00580 } 00581 00582 return 0; 00583 } 00584 00585 00586 00587 int GWEN_MsgEngine__IsCharTyp(GWEN_MSGENGINE *e, 00588 const char *type) { 00589 if (e->typeCheckPtr) { 00590 GWEN_DB_NODE_TYPE vt; 00591 00592 vt=e->typeCheckPtr(e, type); 00593 if (vt!=GWEN_DB_NodeType_Unknown) { 00594 if (vt==GWEN_DB_NodeType_ValueChar) 00595 return 1; 00596 } 00597 } 00598 return 00599 (strcasecmp(type, "alpha")==0) || 00600 (strcasecmp(type, "ascii")==0) || 00601 (strcasecmp(type, "an")==0) || 00602 (strcasecmp(type, "float")==0); 00603 } 00604 00605 00606 00607 int GWEN_MsgEngine__IsIntTyp(GWEN_MSGENGINE *e, 00608 const char *type) { 00609 if (e->typeCheckPtr) { 00610 GWEN_DB_NODE_TYPE vt; 00611 00612 vt=e->typeCheckPtr(e, type); 00613 if (vt!=GWEN_DB_NodeType_Unknown) { 00614 if (vt==GWEN_DB_NodeType_ValueInt) 00615 return 1; 00616 } 00617 } 00618 return 00619 (strcasecmp(type, "num")==0); 00620 } 00621 00622 00623 00624 int GWEN_MsgEngine__IsBinTyp(GWEN_MSGENGINE *e, 00625 const char *type) { 00626 if (e->typeCheckPtr) { 00627 GWEN_DB_NODE_TYPE vt; 00628 00629 vt=e->typeCheckPtr(e, type); 00630 if (vt!=GWEN_DB_NodeType_Unknown) { 00631 if (vt==GWEN_DB_NodeType_ValueBin) 00632 return 1; 00633 } 00634 } 00635 return 00636 (strcasecmp(type, "bin")==0); 00637 } 00638 00639 00640 00641 int GWEN_MsgEngine__GetInline(GWEN_MSGENGINE *e, 00642 GWEN_XMLNODE *node, 00643 GWEN_BUFFER *mbuf) { 00644 /* get data from within the XML node */ 00645 GWEN_XMLNODE *n; 00646 const char *type; 00647 00648 00649 type=GWEN_XMLNode_GetProperty(node, "type", "ascii"); 00650 DBG_DEBUG(GWEN_LOGDOMAIN, 00651 "Getting data of type \"%s\" from within XML file", type); 00652 n=GWEN_XMLNode_GetFirstData(node); 00653 if (!n) { 00654 DBG_DEBUG(GWEN_LOGDOMAIN, "No child"); 00655 return 1; 00656 } 00657 00658 if (GWEN_MsgEngine__IsBinTyp(e, type)) { 00659 const char *dp; 00660 unsigned int dplen; 00661 const char *stype; 00662 00663 stype=GWEN_XMLNode_GetProperty(node, "storedAs", type); 00664 if (GWEN_MsgEngine__IsBinTyp(e, stype)) { 00665 dp=GWEN_XMLNode_GetData(n); 00666 dplen=strlen(dp); 00667 if (GWEN_Text_FromHexBuffer(dp, mbuf)) { 00668 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00669 return -1; 00670 } 00671 } /* if stored as bin */ 00672 else { 00673 /* stored as char */ 00674 GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n)); 00675 } 00676 } /* if binType */ 00677 else { 00678 GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n)); 00679 } 00680 00681 return 0; 00682 } 00683 00684 00685 00686 00687 00688 int GWEN_MsgEngine__WriteElement(GWEN_MSGENGINE *e, 00689 GWEN_BUFFER *gbuf, 00690 GWEN_XMLNODE *node, 00691 GWEN_XMLNODE *rnode, 00692 GWEN_DB_NODE *gr, 00693 int loopNr, 00694 int isOptional, 00695 GWEN_XMLNODE_PATH *nodePath) { 00696 const char *name; 00697 const char *type; 00698 unsigned int minsize; 00699 unsigned int maxsize; 00700 char numbuffer[256]; 00701 const char *pdata; 00702 unsigned int datasize; 00703 GWEN_BUFFER *data; 00704 GWEN_BUFFER *tdata; 00705 int handled; 00706 00707 pdata=0; 00708 handled=0; 00709 data=0; 00710 tdata=0; 00711 00712 /* get type */ 00713 type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); 00714 DBG_DEBUG(GWEN_LOGDOMAIN, "Type is \"%s\"", type); 00715 /* get some sizes */ 00716 minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); 00717 maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); 00718 00719 if (e->binTypeWritePtr && 00720 GWEN_MsgEngine__IsBinTyp(e, type) && 00721 atoi(GWEN_XMLNode_GetProperty(node, "writebin", "1"))) { 00722 int rv; 00723 00724 data=GWEN_Buffer_new(0, 00725 64, 00726 0, 00727 1); 00728 00729 rv=e->binTypeWritePtr(e, node, gr, data); 00730 if (rv==-1) { 00731 /* error */ 00732 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 00733 return -1; 00734 } 00735 else if (rv==0) { 00736 handled=1; 00737 } 00738 else if (rv==1) { 00739 GWEN_Buffer_free(data); 00740 data=0; 00741 } 00742 } 00743 00744 if (!handled) { 00745 /* get name */ 00746 name=GWEN_XMLNode_GetProperty(node, "name", 0); 00747 if (!name) { 00748 int rv; 00749 00750 /* get data from within the XML node */ 00751 tdata=GWEN_Buffer_new(0, 32, 0, 1); 00752 GWEN_Buffer_SetStep(tdata, 256); 00753 rv=GWEN_MsgEngine__GetInline(e, node, tdata); 00754 if (rv==0) { 00755 pdata=GWEN_Buffer_GetStart(tdata); 00756 datasize=GWEN_Buffer_GetUsedBytes(tdata); 00757 } 00758 else { 00759 GWEN_Buffer_free(tdata); 00760 tdata=0; 00761 pdata=""; 00762 datasize=0; 00763 } 00764 } /* if (!name) */ 00765 else { 00766 const char *nptr; 00767 00768 DBG_DEBUG(GWEN_LOGDOMAIN, "Name provided (%s), loop is %d", name, loopNr); 00769 nptr=name; 00770 00771 if (gr) { 00772 GWEN_DB_NODE_TYPE vt; 00773 int idata; 00774 00775 /* Variable type of DB takes precedence 00776 */ 00777 vt=GWEN_DB_GetValueTypeByPath(gr, nptr, loopNr); 00778 if (vt==GWEN_DB_NodeType_Unknown) { 00779 if (GWEN_MsgEngine__IsCharTyp(e, type)) 00780 vt=GWEN_DB_NodeType_ValueChar; 00781 else if (GWEN_MsgEngine__IsIntTyp(e, type)) 00782 vt=GWEN_DB_NodeType_ValueInt; 00783 else if (GWEN_MsgEngine__IsBinTyp(e, type)) 00784 vt=GWEN_DB_NodeType_ValueBin; 00785 else { 00786 DBG_INFO(GWEN_LOGDOMAIN, 00787 "Unable to determine parameter " 00788 "type (%s), assuming \"char\" for this matter", type); 00789 vt=GWEN_DB_NodeType_ValueChar; 00790 } 00791 } 00792 00793 /* get the value of the given var from the db */ 00794 switch(vt) { 00795 case GWEN_DB_NodeType_ValueChar: 00796 DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is char", name); 00797 pdata=GWEN_DB_GetCharValue(gr, nptr, loopNr, 0); 00798 if (pdata) { 00799 DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %s", nptr, pdata); 00800 datasize=strlen(pdata); 00801 } 00802 else 00803 datasize=0; 00804 break; 00805 00806 case GWEN_DB_NodeType_ValueInt: 00807 DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is int", name); 00808 if (GWEN_DB_ValueExists(gr, nptr, loopNr)) { 00809 idata=GWEN_DB_GetIntValue(gr, nptr, loopNr, 0); 00810 if (-1==GWEN_Text_NumToString(idata, numbuffer, 00811 sizeof(numbuffer),0)) { 00812 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00813 GWEN_Buffer_free(data); 00814 return -1; 00815 } 00816 DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %d", nptr, idata); 00817 pdata=numbuffer; 00818 datasize=strlen(numbuffer); 00819 } 00820 break; 00821 00822 case GWEN_DB_NodeType_ValueBin: 00823 DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is bin", name); 00824 pdata=GWEN_DB_GetBinValue(gr, nptr, loopNr, 0, 0, &datasize); 00825 break; 00826 00827 default: 00828 DBG_WARN(GWEN_LOGDOMAIN, "Unsupported parameter type (%d)", vt); 00829 break; 00830 } /* switch vt */ 00831 } /* if gr */ 00832 00833 if (!pdata) { 00834 GWEN_XMLNODE_PATH *copyOfNodePath; 00835 00836 copyOfNodePath=GWEN_XMLNode_Path_dup(nodePath); 00837 00838 /* still no data, try to get it from the XML file */ 00839 DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\"", name); 00840 pdata=GWEN_MsgEngine__SearchForValue(e, 00841 node, copyOfNodePath, nptr, 00842 &datasize); 00843 GWEN_XMLNode_Path_free(copyOfNodePath); 00844 if (pdata) { 00845 DBG_DEBUG(GWEN_LOGDOMAIN, "Found value of \"%s\"", name); 00846 } 00847 } 00848 00849 if (!pdata) { 00850 int rv; 00851 00852 /* get data from within the XML node */ 00853 tdata=GWEN_Buffer_new(0, 32, 0, 1); 00854 GWEN_Buffer_SetStep(tdata, 256); 00855 rv=GWEN_MsgEngine__GetInline(e, node, tdata); 00856 if (rv==0) { 00857 pdata=GWEN_Buffer_GetStart(tdata); 00858 datasize=GWEN_Buffer_GetUsedBytes(tdata); 00859 } 00860 else { 00861 GWEN_Buffer_free(tdata); 00862 tdata=0; 00863 } 00864 } 00865 00866 if (pdata==0) { 00867 if (isOptional) { 00868 DBG_INFO(GWEN_LOGDOMAIN, "Value not found, omitting element \"%s[%d]\"", 00869 name, loopNr); 00870 GWEN_Buffer_free(data); 00871 return 1; 00872 } 00873 else { 00874 DBG_ERROR(GWEN_LOGDOMAIN, 00875 "Value for element \"%s[%d]\" (mode \"%s\") not found", 00876 name, loopNr, 00877 GWEN_MsgEngine_GetMode(e)); 00878 GWEN_DB_Dump(gr, 4); 00879 GWEN_Buffer_free(data); 00880 return -1; 00881 } 00882 } 00883 } 00884 00885 if (!data) 00886 data=GWEN_Buffer_new((char*)pdata, 00887 datasize, 00888 datasize, 00889 0 /* dont take ownership*/ ); 00890 } 00891 00892 /* write value */ 00893 if (GWEN_MsgEngine__WriteValue(e, 00894 gbuf, 00895 data, 00896 node)!=0) { 00897 DBG_INFO(GWEN_LOGDOMAIN, "Could not write value"); 00898 GWEN_Buffer_free(data); 00899 GWEN_Buffer_free(tdata); 00900 return -1; 00901 } 00902 GWEN_Buffer_free(data); 00903 GWEN_Buffer_free(tdata); 00904 00905 return 0; 00906 } 00907 00908 00909 00910 GWEN_XMLNODE *GWEN_MsgEngine_FindGroupByProperty(GWEN_MSGENGINE *e, 00911 const char *pname, 00912 int version, 00913 const char *pvalue) { 00914 return GWEN_MsgEngine_FindNodeByProperty(e, "GROUP", pname, version, pvalue); 00915 } 00916 00917 00918 00919 GWEN_XMLNODE *GWEN_MsgEngine_FindNodeByProperty(GWEN_MSGENGINE *e, 00920 const char *t, 00921 const char *pname, 00922 int version, 00923 const char *pvalue) { 00924 GWEN_XMLNODE *n; 00925 const char *p; 00926 int i; 00927 const char *mode; 00928 unsigned int proto; 00929 char buffer[256]; 00930 00931 if ((strlen(t)+4)>sizeof(buffer)) { 00932 DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long."); 00933 return 0; 00934 } 00935 00936 mode=GWEN_MsgEngine_GetMode(e); 00937 proto=GWEN_MsgEngine_GetProtocolVersion(e); 00938 if (!e->defs) { 00939 DBG_INFO(GWEN_LOGDOMAIN, "No definitions available"); 00940 return 0; 00941 } 00942 n=e->defs; 00943 n=GWEN_XMLNode_GetChild(n); 00944 00945 /* find type+"S" */ 00946 strcpy(buffer, t); 00947 strcat(buffer,"S"); 00948 while(n) { 00949 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 00950 p=GWEN_XMLNode_GetData(n); 00951 assert(p); 00952 if (strcasecmp(p, buffer)==0) 00953 break; 00954 } 00955 n=GWEN_XMLNode_Next(n); 00956 } /* while */ 00957 00958 if (!n) { 00959 DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t); 00960 return 0; 00961 } 00962 00963 /* find approppriate group definition */ 00964 if (!mode) 00965 mode=""; 00966 n=GWEN_XMLNode_GetChild(n); 00967 if (!n) { 00968 DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer); 00969 return 0; 00970 } 00971 00972 /* find type+"def" */ 00973 strcpy(buffer, t); 00974 strcat(buffer,"def"); 00975 while(n) { 00976 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 00977 p=GWEN_XMLNode_GetData(n); 00978 assert(p); 00979 if (strcasecmp(p, buffer)==0) { 00980 p=GWEN_XMLNode_GetProperty(n, pname,""); 00981 if (strcasecmp(p, pvalue)==0) { 00982 i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0")); 00983 if (proto==0 || (int)proto==i || i==0) { 00984 i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0")); 00985 if (version==0 || version==i) { 00986 p=GWEN_XMLNode_GetProperty(n, "mode",""); 00987 if (strcasecmp(p, mode)==0 || !*p) { 00988 DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found", 00989 pname, pvalue); 00990 return n; 00991 } 00992 } 00993 } 00994 } 00995 } 00996 } 00997 n=GWEN_XMLNode_Next(n); 00998 } /* while */ 00999 01000 DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found", 01001 pname, 01002 pvalue, 01003 version); 01004 return 0; 01005 } 01006 01007 01008 01009 GWEN_XMLNODE *GWEN_MsgEngine_FindNodeByPropertyStrictProto(GWEN_MSGENGINE *e, 01010 const char *t, 01011 const char *pname, 01012 int version, 01013 const char *pvalue) { 01014 GWEN_XMLNODE *n; 01015 const char *p; 01016 int i; 01017 const char *mode; 01018 unsigned int proto; 01019 char buffer[256]; 01020 01021 if ((strlen(t)+4)>sizeof(buffer)) { 01022 DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long."); 01023 return 0; 01024 } 01025 01026 mode=GWEN_MsgEngine_GetMode(e); 01027 proto=GWEN_MsgEngine_GetProtocolVersion(e); 01028 if (!e->defs) { 01029 DBG_INFO(GWEN_LOGDOMAIN, "No definitions available"); 01030 return 0; 01031 } 01032 n=e->defs; 01033 n=GWEN_XMLNode_GetChild(n); 01034 01035 /* find type+"S" */ 01036 strcpy(buffer, t); 01037 strcat(buffer,"S"); 01038 while(n) { 01039 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 01040 p=GWEN_XMLNode_GetData(n); 01041 assert(p); 01042 if (strcasecmp(p, buffer)==0) 01043 break; 01044 } 01045 n=GWEN_XMLNode_Next(n); 01046 } /* while */ 01047 01048 if (!n) { 01049 DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t); 01050 return 0; 01051 } 01052 01053 /* find approppriate group definition */ 01054 if (!mode) 01055 mode=""; 01056 n=GWEN_XMLNode_GetChild(n); 01057 if (!n) { 01058 DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer); 01059 return 0; 01060 } 01061 01062 /* find type+"def" */ 01063 strcpy(buffer, t); 01064 strcat(buffer,"def"); 01065 while(n) { 01066 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 01067 p=GWEN_XMLNode_GetData(n); 01068 assert(p); 01069 if (strcasecmp(p, buffer)==0) { 01070 p=GWEN_XMLNode_GetProperty(n, pname,""); 01071 if (strcasecmp(p, pvalue)==0) { 01072 i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0")); 01073 if (proto==0 || (int)proto==i) { 01074 i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0")); 01075 if (version==0 || version==i) { 01076 p=GWEN_XMLNode_GetProperty(n, "mode",""); 01077 if (strcasecmp(p, mode)==0 || !*p) { 01078 DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found", 01079 pname, pvalue); 01080 return n; 01081 } 01082 } 01083 } 01084 } 01085 } 01086 } 01087 n=GWEN_XMLNode_Next(n); 01088 } /* while */ 01089 01090 DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found", 01091 pname, 01092 pvalue, 01093 version); 01094 return 0; 01095 } 01096 01097 01098 01099 const char *GWEN_MsgEngine__TransformValue(GWEN_MSGENGINE *e, 01100 const char *pvalue, 01101 GWEN_XMLNODE *node, 01102 GWEN_XMLNODE *dnode, 01103 unsigned int *datasize) { 01104 const char *p; 01105 static char pbuffer[256]; 01106 GWEN_DB_NODE *globalValues; 01107 01108 globalValues=GWEN_MsgEngine__GetGlobalValues(e); 01109 assert(globalValues); 01110 01111 if (pvalue) { 01112 DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming value \"%s\"", pvalue); 01113 /* check whether the value is a property */ 01114 p=pvalue; 01115 while (*p && isspace((int)*p)) 01116 p++; 01117 if (*p=='$' || *p=='+') { 01118 /* global property */ 01119 int incr; 01120 01121 incr=(*p=='+'); 01122 p++; 01123 01124 DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p); 01125 if (incr) { 01126 int z; 01127 01128 z=GWEN_DB_GetIntValue(globalValues, p, 0, 0); 01129 DBG_DEBUG(GWEN_LOGDOMAIN, "Incrementing global property \"%s\" (%d)", 01130 p, z); 01131 if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { 01132 DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); 01133 return 0; 01134 } 01135 01136 z++; 01137 DBG_DEBUG(GWEN_LOGDOMAIN, "Setting global property \"%s\"=%d", p, z); 01138 GWEN_DB_SetIntValue(globalValues, 01139 GWEN_DB_FLAGS_DEFAULT | 01140 GWEN_DB_FLAGS_OVERWRITE_VARS, 01141 p, z); 01142 pvalue=pbuffer; 01143 *datasize=strlen(pvalue); 01144 } 01145 else { 01146 int z; 01147 GWEN_DB_NODE_TYPE vt; 01148 const char *type = "should_be_known"; 01149 /* default value; otherwise the compiler issues a warning */ 01150 01151 DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p); 01152 vt=GWEN_DB_GetVariableType(globalValues, p); 01153 if (vt==GWEN_DB_NodeType_Unknown) { 01154 if (!GWEN_DB_VariableExists(globalValues, p)) { 01155 DBG_ERROR(GWEN_LOGDOMAIN, "Unable to determine type of \"%s\"", p); 01156 return 0; 01157 } 01158 type=GWEN_XMLNode_GetProperty(dnode, "type", "ascii"); 01159 if (GWEN_MsgEngine__IsCharTyp(e, type)) 01160 vt=GWEN_DB_NodeType_ValueChar; 01161 else if (GWEN_MsgEngine__IsIntTyp(e, type)) 01162 vt=GWEN_DB_NodeType_ValueInt; 01163 else if (GWEN_MsgEngine__IsBinTyp(e, type)) 01164 vt=GWEN_DB_NodeType_ValueBin; 01165 else { 01166 DBG_ERROR(GWEN_LOGDOMAIN, 01167 "Unable to determine type of \"%s\" (xml)", p); 01168 return 0; 01169 } 01170 } 01171 01172 switch(vt) { 01173 case GWEN_DB_NodeType_ValueChar: 01174 pvalue=GWEN_DB_GetCharValue(globalValues, p, 0, ""); 01175 *datasize=strlen(pvalue); 01176 break; 01177 01178 case GWEN_DB_NodeType_ValueInt: 01179 z=GWEN_DB_GetIntValue(globalValues, p, 0, 0); 01180 if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { 01181 DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); 01182 return 0; 01183 } 01184 pvalue=pbuffer; 01185 *datasize=strlen(pvalue); 01186 break; 01187 01188 case GWEN_DB_NodeType_ValueBin: 01189 pvalue=GWEN_DB_GetBinValue(globalValues, p, 0, 01190 0,0, 01191 datasize); 01192 break; 01193 01194 default: 01195 DBG_ERROR(GWEN_LOGDOMAIN,"Unknown type %s", type); 01196 return 0; 01197 } /* switch */ 01198 } 01199 DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed"); 01200 } 01201 else if (*p=='%') { 01202 /* local property */ 01203 p++; 01204 01205 DBG_DEBUG(GWEN_LOGDOMAIN, "Getting property \"%s\"", p); 01206 pvalue=GWEN_XMLNode_GetProperty(node, p, 0); 01207 if (pvalue) { 01208 *datasize=strlen(pvalue); 01209 DBG_DEBUG(GWEN_LOGDOMAIN, "Transformed value \"%s\"", pvalue); 01210 } 01211 else 01212 *datasize=0; 01213 } 01214 else if (*p=='?') { 01215 GWEN_DB_NODE_TYPE vt; 01216 int z; 01217 const char *dtype; 01218 01219 /* get type */ 01220 dtype=GWEN_XMLNode_GetProperty(dnode, "type","ASCII"); 01221 01222 /* program variable accessable via callback */ 01223 p++; 01224 DBG_DEBUG(GWEN_LOGDOMAIN, "Getting program variable \"%s\"", p); 01225 01226 pvalue=0; 01227 if (GWEN_MsgEngine__IsCharTyp(e, dtype)) 01228 vt=GWEN_DB_NodeType_ValueChar; 01229 else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) 01230 vt=GWEN_DB_NodeType_ValueInt; 01231 else { 01232 vt=GWEN_DB_NodeType_ValueChar; 01233 } 01234 01235 switch(vt) { 01236 case GWEN_DB_NodeType_ValueChar: 01237 if (e->getCharValuePtr) { 01238 pvalue=e->getCharValuePtr(e, p, 0); 01239 if (pvalue) 01240 *datasize=strlen(pvalue); 01241 } 01242 break; 01243 01244 case GWEN_DB_NodeType_ValueInt: 01245 if (e->getIntValuePtr) { 01246 z=e->getIntValuePtr(e, p, 0); 01247 if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { 01248 DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); 01249 return 0; 01250 } 01251 pvalue=pbuffer; 01252 *datasize=strlen(pvalue); 01253 } 01254 else { 01255 DBG_NOTICE(GWEN_LOGDOMAIN, "Callback for getIntValue not set"); 01256 } 01257 break; 01258 01259 default: 01260 DBG_ERROR(GWEN_LOGDOMAIN,"Unhandled type %s", dtype); 01261 return 0; 01262 } /* switch */ 01263 01264 DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed"); 01265 } 01266 else { 01267 *datasize=strlen(pvalue); 01268 } 01269 } 01270 return pvalue; 01271 } 01272 01273 01274 01275 const char *GWEN_MsgEngine_SearchForProperty(GWEN_XMLNODE *node, 01276 GWEN_XMLNODE *refnode, 01277 const char *name, 01278 int topDown) { 01279 const char *pvalue; 01280 GWEN_XMLNODE *pn; 01281 const char *lastValue; 01282 01283 DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in properties", name); 01284 lastValue=0; 01285 01286 pvalue=GWEN_XMLNode_GetProperty(node, name,0); 01287 if (pvalue) { 01288 if (!topDown) 01289 return pvalue; 01290 DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue); 01291 lastValue=pvalue; 01292 } 01293 01294 pn=refnode; 01295 while(pn) { 01296 pvalue=GWEN_XMLNode_GetProperty(pn, name,0); 01297 if (pvalue) { 01298 if (!topDown) 01299 return pvalue; 01300 DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue); 01301 lastValue=pvalue; 01302 } 01303 pn=GWEN_XMLNode_GetParent(pn); 01304 } /* while */ 01305 return lastValue; 01306 } 01307 01308 01309 01310 int GWEN_MsgEngine_GetHighestTrustLevel(GWEN_XMLNODE *node, 01311 GWEN_XMLNODE *refnode) { 01312 int value; 01313 GWEN_XMLNODE *pn; 01314 int highestTrust; 01315 01316 highestTrust=0; 01317 01318 value=atoi(GWEN_XMLNode_GetProperty(node, "trustlevel","0")); 01319 if (value>highestTrust) 01320 highestTrust=value; 01321 01322 pn=node; 01323 while(pn) { 01324 value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0")); 01325 if (value>highestTrust) 01326 highestTrust=value; 01327 pn=GWEN_XMLNode_GetParent(pn); 01328 } /* while */ 01329 01330 pn=refnode; 01331 while(pn) { 01332 value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0")); 01333 if (value>highestTrust) 01334 highestTrust=value; 01335 pn=GWEN_XMLNode_GetParent(pn); 01336 } /* while */ 01337 return highestTrust; 01338 } 01339 01340 01341 01342 const char *GWEN_MsgEngine__SearchForValue(GWEN_MSGENGINE *e, 01343 GWEN_XMLNODE *node, 01344 GWEN_XMLNODE_PATH *nodePath, 01345 const char *name, 01346 unsigned int *datasize) { 01347 const char *pvalue; 01348 GWEN_XMLNODE *pn; 01349 char *bufferPtr; 01350 int topDown; 01351 const char *lastValue; 01352 unsigned int lastDataSize; 01353 unsigned int ldatasize; 01354 01355 DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in <VALUES>", 01356 name); 01357 if (!node) { 01358 DBG_WARN(GWEN_LOGDOMAIN, "No node !"); 01359 } 01360 topDown=atoi(GWEN_XMLNode_GetProperty(node, "topdown", "0")); 01361 lastValue=0; 01362 lastDataSize=0; 01363 01364 bufferPtr=0; 01365 01366 /*pn=GWEN_XMLNode_GetParent(node);*/ 01367 pn=GWEN_XMLNode_Path_Surface(nodePath); 01368 while(pn) { 01369 const char *ppath; 01370 /* 01371 if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) { 01372 DBG_NOTICE(GWEN_LOGDOMAIN, "Checking node \"%s\"", 01373 GWEN_XMLNode_GetData(pn)); 01374 }*/ 01375 pvalue=GWEN_MsgEngine__findInValues(e, pn, node, name, &ldatasize); 01376 if (pvalue) { 01377 if (!topDown) { 01378 free(bufferPtr); 01379 *datasize=ldatasize; 01380 return pvalue; 01381 } 01382 DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value, but will look further"); 01383 lastValue=pvalue; 01384 lastDataSize=ldatasize; 01385 } 01386 01387 ppath=GWEN_XMLNode_GetProperty(pn, "name", ""); 01388 01389 if (*ppath) { 01390 int i; 01391 char *tmpptr; 01392 01393 if (bufferPtr) { 01394 i=strlen(bufferPtr)+strlen(ppath)+2; 01395 tmpptr=(char*)malloc(i); 01396 assert(tmpptr); 01397 sprintf(tmpptr, "%s/%s", ppath, bufferPtr); 01398 free(bufferPtr); 01399 bufferPtr=tmpptr; 01400 } 01401 else { 01402 i=strlen(ppath)+strlen(name)+2; 01403 tmpptr=(char*)malloc(i); 01404 assert(tmpptr); 01405 sprintf(tmpptr, "%s/%s", ppath, name); 01406 bufferPtr=tmpptr; 01407 } 01408 name=bufferPtr; 01409 } 01410 pn=GWEN_XMLNode_Path_Surface(nodePath); 01411 } /* while */ 01412 01413 free(bufferPtr); 01414 if (!lastValue) 01415 *datasize=0; 01416 else 01417 *datasize=lastDataSize; 01418 return lastValue; 01419 } 01420 01421 01422 01423 const char *GWEN_MsgEngine__findInValues(GWEN_MSGENGINE *e, 01424 GWEN_XMLNODE *node, 01425 GWEN_XMLNODE *dnode, 01426 const char *name, 01427 unsigned int *datasize) { 01428 GWEN_XMLNODE *pn; 01429 01430 DBG_VERBOUS(GWEN_LOGDOMAIN, "Looking for value of \"%s\" in <VALUES>", name); 01431 pn=GWEN_XMLNode_GetChild(node); 01432 01433 while(pn) { 01434 if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) { 01435 GWEN_XMLNODE *n; 01436 const char *p; 01437 01438 p=GWEN_XMLNode_GetData(pn); 01439 assert(p); 01440 DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s", p); 01441 if (strcasecmp(p, "VALUES")==0) { 01442 DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found"); 01443 /* <preset> found, check all values */ 01444 n=GWEN_XMLNode_GetChild(pn); 01445 while(n) { 01446 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 01447 p=GWEN_XMLNode_GetData(n); 01448 assert(p); 01449 if (strcasecmp(p, "VALUE")==0) { 01450 const char *pname; 01451 const char *pvalue; 01452 01453 pname=GWEN_XMLNode_GetProperty(n, "path", 0); 01454 if (pname) { 01455 DBG_DEBUG(GWEN_LOGDOMAIN, "Comparing against \"%s\"", pname); 01456 if (strcasecmp(name, pname)==0) { 01457 GWEN_XMLNODE *dn; 01458 01459 dn=GWEN_XMLNode_GetChild(n); 01460 while (dn) { 01461 if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { 01462 pvalue=GWEN_XMLNode_GetData(dn); 01463 if (pvalue) { 01464 DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming \"%s\"", pvalue); 01465 pvalue=GWEN_MsgEngine__TransformValue(e, 01466 pvalue, 01467 node, 01468 dnode, 01469 datasize); 01470 } 01471 if (pvalue) 01472 return pvalue; 01473 } 01474 dn=GWEN_XMLNode_Next(dn); 01475 } /* while dn */ 01476 } /* if path matches name */ 01477 } /* if path given */ 01478 } /* if VALUE tag */ 01479 } /* if TAG */ 01480 n=GWEN_XMLNode_Next(n); 01481 } /* while */ 01482 break; /* REMOVE this to check multiple groups */ 01483 } /* if <preset> found */ 01484 } /* if tag */ 01485 pn=GWEN_XMLNode_Next(pn); 01486 } /* while node */ 01487 01488 DBG_DEBUG(GWEN_LOGDOMAIN, "No value found for \"%s\" in <VALUES>", name); 01489 return 0; 01490 } 01491 01492 01493 01494 GWEN_XMLNODE *GWEN_MsgEngine__GetGroup(GWEN_MSGENGINE *e, 01495 GWEN_XMLNODE *node, 01496 const char *t, 01497 int version, 01498 const char *pvalue) { 01499 GWEN_XMLNODE *n; 01500 const char *p; 01501 int i; 01502 const char *mode; 01503 unsigned int proto; 01504 char buffer[256]; 01505 01506 if ((strlen(t)+4)>sizeof(buffer)) { 01507 DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long."); 01508 return 0; 01509 } 01510 01511 mode=GWEN_MsgEngine_GetMode(e); 01512 proto=GWEN_MsgEngine_GetProtocolVersion(e); 01513 01514 /* find type+"S" */ 01515 strcpy(buffer, t); 01516 strcat(buffer,"S"); 01517 n=GWEN_XMLNode_FindFirstTag(node, buffer, 0, 0); 01518 if (!n) { 01519 DBG_DEBUG(GWEN_LOGDOMAIN, 01520 "No definitions here for type \"%s\"", t); 01521 return 0; 01522 } 01523 01524 /* find approppriate group definition */ 01525 if (!mode) 01526 mode=""; 01527 n=GWEN_XMLNode_GetFirstTag(n); 01528 if (!n) { 01529 DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer); 01530 return 0; 01531 } 01532 01533 /* find type+"def" */ 01534 strcpy(buffer, t); 01535 strcat(buffer, "def"); 01536 while(n) { 01537 p=GWEN_XMLNode_GetData(n); 01538 assert(p); 01539 if (strcasecmp(p, buffer)==0 || 01540 strcasecmp(p, t)==0) { 01541 p=GWEN_XMLNode_GetProperty(n, "id", ""); 01542 if (strcasecmp(p, pvalue)!=0) 01543 p=GWEN_XMLNode_GetProperty(n, "name", ""); 01544 if (strcasecmp(p, pvalue)==0) { 01545 i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0")); 01546 if (proto==0 || (int)proto==i || i==0) { 01547 i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0")); 01548 if (version==0 || version==i) { 01549 p=GWEN_XMLNode_GetProperty(n, "mode",""); 01550 if (strcasecmp(p, mode)==0 || !*p) { 01551 DBG_DEBUG(GWEN_LOGDOMAIN, 01552 "Group definition for \"%s=%s\" found", 01553 t, pvalue); 01554 return n; 01555 } 01556 } 01557 } 01558 } 01559 } 01560 n=GWEN_XMLNode_GetNextTag(n); 01561 } /* while */ 01562 01563 DBG_DEBUG(GWEN_LOGDOMAIN, 01564 "Group definition for \"%s=%s\"(%d) not found here", 01565 t, 01566 pvalue, 01567 version); 01568 return 0; 01569 } 01570 01571 01572 01573 GWEN_XMLNODE *GWEN_MsgEngine_GetGroup(GWEN_MSGENGINE *e, 01574 GWEN_XMLNODE *node, 01575 const GWEN_XMLNODE_PATH *nodePath, 01576 const char *t, 01577 int version, 01578 const char *pvalue) { 01579 GWEN_XMLNODE *n; 01580 GWEN_XMLNODE *nLast = 0; 01581 GWEN_XMLNODE *nRes = 0; 01582 GWEN_XMLNODE_PATH *pathCopy; 01583 01584 assert(node); 01585 assert(nodePath); 01586 assert(t); 01587 assert(pvalue); 01588 01589 pathCopy=GWEN_XMLNode_Path_dup(nodePath); 01590 n=GWEN_XMLNode_Path_Surface(pathCopy); 01591 /* first try all nodes along the path */ 01592 while(n) { 01593 nLast=n; 01594 nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue); 01595 if (nRes) 01596 break; 01597 n=GWEN_XMLNode_Path_Surface(pathCopy); 01598 } 01599 GWEN_XMLNode_Path_free(pathCopy); 01600 if (nRes) { 01601 /* already found */ 01602 if (nRes==node) { 01603 DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected."); 01604 return 0; 01605 } 01606 return nRes; 01607 } 01608 01609 if (nLast) 01610 n=nLast; 01611 else 01612 n=node; 01613 01614 if (n) { 01615 n=GWEN_XMLNode_GetParent(n); 01616 while(n) { 01617 nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue); 01618 if (nRes) 01619 break; 01620 n=GWEN_XMLNode_GetParent(n); 01621 } 01622 } 01623 01624 /* try root as a last resort */ 01625 if (!nRes && e->defs) 01626 nRes=GWEN_MsgEngine__GetGroup(e, e->defs, t, version, pvalue); 01627 01628 if (!nRes) { 01629 DBG_DEBUG(GWEN_LOGDOMAIN, 01630 "Group definition for \"%s=%s\"(%d) not found", 01631 t, 01632 pvalue, 01633 version); 01634 return 0; 01635 } 01636 if (nRes==node) { 01637 DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected."); 01638 return 0; 01639 } 01640 return nRes; 01641 } 01642 01643 01644 01645 int GWEN_MsgEngine__WriteGroup(GWEN_MSGENGINE *e, 01646 GWEN_BUFFER *gbuf, 01647 GWEN_XMLNODE *node, 01648 GWEN_XMLNODE *rnode, 01649 GWEN_DB_NODE *gr, 01650 int groupIsOptional, 01651 GWEN_XMLNODE_PATH *nodePath) { 01652 GWEN_XMLNODE *n; 01653 const char *p; 01654 char delimiter; 01655 char terminator; 01656 int isFirstElement; 01657 int omittedElements; 01658 int hasEntries; 01659 01660 01661 /* get some settings */ 01662 if (rnode) { 01663 /* get delimiter */ 01664 p=GWEN_XMLNode_GetProperty(rnode, 01665 "delimiter", 01666 GWEN_XMLNode_GetProperty(node, 01667 "delimiter", 01668 "")); 01669 delimiter=*p; 01670 01671 /* get terminating char, if any */ 01672 p=GWEN_XMLNode_GetProperty(rnode, 01673 "terminator", 01674 GWEN_XMLNode_GetProperty(node, 01675 "terminator", 01676 "")); 01677 terminator=*p; 01678 } 01679 else { 01680 /* get delimiter */ 01681 p=GWEN_XMLNode_GetProperty(node, 01682 "delimiter", 01683 ""); 01684 delimiter=*p; 01685 01686 /* get terminating char, if any */ 01687 p=GWEN_XMLNode_GetProperty(node, "terminator",""); 01688 terminator=*p; 01689 } 01690 01691 /* handle all child entries */ 01692 n=GWEN_XMLNode_GetChild(node); 01693 isFirstElement=1; 01694 omittedElements=0; 01695 hasEntries=0; 01696 if (!n) { 01697 DBG_INFO(GWEN_LOGDOMAIN, "No subnodes !"); 01698 } 01699 while(n) { 01700 int t; 01701 unsigned int minnum; 01702 unsigned int maxnum; 01703 int gversion; 01704 const char *addEmptyMode; 01705 unsigned int loopNr; 01706 01707 minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); 01708 maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); 01709 gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); 01710 addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one"); 01711 01712 DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements); 01713 t=GWEN_XMLNode_GetType(n); 01714 if (t==GWEN_XMLNodeTypeTag) { 01715 const char *typ; 01716 01717 typ=GWEN_XMLNode_GetData(n); 01718 if (typ==0) { 01719 DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); 01720 return -1; 01721 } 01722 if (strcasecmp(typ, "ELEM")==0) { 01723 /* element tag found */ 01724 int j; 01725 int rv; 01726 01727 DBG_VERBOUS(GWEN_LOGDOMAIN, "Found an element"); 01728 /* write element as often as needed */ 01729 for (loopNr=0; loopNr<maxnum; loopNr++) { 01730 unsigned int posBeforeElement; 01731 01732 posBeforeElement=GWEN_Buffer_GetPos(gbuf); 01733 01734 /* write delimiter, if needed */ 01735 if (delimiter) { 01736 DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters", 01737 omittedElements); 01738 for (j=0; j<omittedElements; j++) { 01739 if (GWEN_Buffer_AppendByte(gbuf, delimiter)) { 01740 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 01741 return -1; 01742 } 01743 } 01744 if (!isFirstElement) 01745 if (GWEN_Buffer_AppendByte(gbuf, delimiter)) { 01746 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 01747 return -1; 01748 } 01749 } 01750 01751 rv=GWEN_MsgEngine__WriteElement(e, 01752 gbuf, 01753 n, 01754 rnode, 01755 gr, 01756 loopNr, 01757 loopNr>=minnum || 01758 (groupIsOptional && !hasEntries), 01759 nodePath); 01760 if (rv==-1) { 01761 DBG_INFO(GWEN_LOGDOMAIN, "Error writing element"); 01762 DBG_INFO(GWEN_LOGDOMAIN, "Node is:"); 01763 GWEN_XMLNode_Dump(n, 1); 01764 if (gr) { 01765 DBG_INFO(GWEN_LOGDOMAIN, "Data is:"); 01766 GWEN_DB_Dump(gr, 1); 01767 } 01768 return -1; 01769 } 01770 else if (rv==0) { 01771 isFirstElement=0; 01772 omittedElements=0; 01773 hasEntries=1; 01774 DBG_DEBUG(GWEN_LOGDOMAIN, "Element written"); 01775 } 01776 else { 01777 /* element is optional, not found */ 01778 /* restore position */ 01779 GWEN_Buffer_SetPos(gbuf, posBeforeElement); 01780 GWEN_Buffer_Crop(gbuf, 0, posBeforeElement); 01781 01782 if (strcasecmp(addEmptyMode, "max")==0) { 01783 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty"); 01784 omittedElements+=(maxnum-loopNr); 01785 } 01786 else if (strcasecmp(addEmptyMode, "min")==0) { 01787 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty"); 01788 if (loopNr<minnum) 01789 omittedElements+=(minnum-loopNr); 01790 } 01791 else if (strcasecmp(addEmptyMode, "one")==0) { 01792 if (loopNr==0) 01793 omittedElements++; 01794 } 01795 else if (strcasecmp(addEmptyMode, "none")==0) { 01796 } 01797 else { 01798 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"", 01799 addEmptyMode); 01800 return -1; 01801 } 01802 break; 01803 } 01804 } /* for */ 01805 } 01806 else if (strcasecmp(typ, "VALUES")==0) { 01807 } 01808 else if (strcasecmp(typ, "DESCR")==0) { 01809 } 01810 else { 01811 /* group tag found */ 01812 GWEN_XMLNODE *gn; 01813 GWEN_DB_NODE *gcfg; 01814 const char *gname; 01815 const char *gtype; 01816 unsigned int posBeforeGroup; 01817 01818 DBG_VERBOUS(GWEN_LOGDOMAIN, "Found a group"); 01819 01820 gcfg=0; 01821 gtype=GWEN_XMLNode_GetProperty(n, "type",0); 01822 if (!gtype) { 01823 /* no "type" property, so use this group directly */ 01824 DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ); 01825 gtype=""; 01826 gn=n; 01827 } 01828 else { 01829 DBG_VERBOUS(GWEN_LOGDOMAIN, "<%s> tag is of type \"%s\"", typ, gtype); 01830 gn=GWEN_MsgEngine_GetGroup(e, n, nodePath, typ, 01831 gversion, gtype); 01832 if (!gn) { 01833 DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); 01834 return -1; 01835 } 01836 } 01837 01838 gname=NULL; 01839 gcfg=NULL; 01840 if (gr) { 01841 gname=GWEN_XMLNode_GetProperty(n, "name",0); 01842 if (gname) { 01843 DBG_VERBOUS(GWEN_LOGDOMAIN, "Group \"%s\" using special data", gname); 01844 gcfg=GWEN_DB_FindFirstGroup(gr, gname); 01845 } 01846 else { 01847 DBG_DEBUG(GWEN_LOGDOMAIN, "Unnamed group, using basic data"); 01848 /* TODO: check for maxnum==1, since only then the following line makes sense */ 01849 gcfg=gr; 01850 } 01851 } 01852 01853 /* write group as often as needed */ 01854 for (loopNr=0; loopNr<maxnum; loopNr++) { 01855 int rv; 01856 int groupIsEmpty; 01857 01858 groupIsEmpty=0; 01859 posBeforeGroup=GWEN_Buffer_GetPos(gbuf); 01860 01861 /* write delimiter, if needed */ 01862 if (delimiter) { 01863 int j; 01864 01865 DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters", 01866 omittedElements); 01867 for (j=0; j<omittedElements; j++) { 01868 if (GWEN_Buffer_AppendByte(gbuf, delimiter)) { 01869 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 01870 return -1; 01871 } 01872 } 01873 if (!isFirstElement) 01874 if (GWEN_Buffer_AppendByte(gbuf, delimiter)) { 01875 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 01876 return -1; 01877 } 01878 } 01879 01880 /* find next matching group */ 01881 if (gcfg==0) { 01882 DBG_DEBUG(GWEN_LOGDOMAIN, "No group found"); 01883 if (loopNr>=minnum) 01884 groupIsEmpty=1; 01885 } 01886 01887 if (groupIsEmpty) { 01888 /* empty group, flag as such */ 01889 rv=1; 01890 } 01891 else { 01892 int dive; 01893 01894 /* write group */ 01895 if (GWEN_XMLNode_Path_Dive(nodePath, n)) { 01896 DBG_INFO(GWEN_LOGDOMAIN, "Called from here"); 01897 return -1; 01898 } 01899 if (n==gn) 01900 dive=1; 01901 else { 01902 if (GWEN_XMLNode_Path_Dive(nodePath, gn)) { 01903 DBG_INFO(GWEN_LOGDOMAIN, "Called from here"); 01904 return -1; 01905 } 01906 dive=2; 01907 } 01908 rv=GWEN_MsgEngine__WriteGroup(e, 01909 gbuf, 01910 gn, 01911 n, 01912 gcfg, 01913 loopNr>=minnum || groupIsOptional, 01914 nodePath); 01915 GWEN_XMLNode_Path_Surface(nodePath); 01916 if (dive==2) 01917 GWEN_XMLNode_Path_Surface(nodePath); 01918 } 01919 01920 if (rv==-1) { 01921 DBG_INFO(GWEN_LOGDOMAIN, "Could not write group \"%s\"", gtype); 01922 if (gn) { 01923 DBG_INFO(GWEN_LOGDOMAIN, "Node is:"); 01924 GWEN_XMLNode_Dump(gn, 1); 01925 } 01926 if (n) { 01927 DBG_INFO(GWEN_LOGDOMAIN, "Referring node is:"); 01928 GWEN_XMLNode_Dump(n, 1); 01929 } 01930 if (gr) { 01931 DBG_INFO(GWEN_LOGDOMAIN, "Data is:"); 01932 GWEN_DB_Dump(gr, 1); 01933 } 01934 return -1; 01935 } 01936 else if (rv==0) { 01937 isFirstElement=0; 01938 omittedElements=0; 01939 hasEntries=1; 01940 DBG_DEBUG(GWEN_LOGDOMAIN, "Element written"); 01941 } 01942 else { 01943 /* group is optional, not found */ 01944 /* restore position */ 01945 GWEN_Buffer_SetPos(gbuf, posBeforeGroup); 01946 GWEN_Buffer_Crop(gbuf, 0, posBeforeGroup); 01947 01948 if (strcasecmp(addEmptyMode, "max")==0) { 01949 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty"); 01950 omittedElements+=(maxnum-loopNr); 01951 } 01952 else if (strcasecmp(addEmptyMode, "min")==0) { 01953 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty"); 01954 if (loopNr<minnum) 01955 omittedElements+=(minnum-loopNr); 01956 } 01957 else if (strcasecmp(addEmptyMode, "one")==0) { 01958 if (loopNr==0) 01959 omittedElements++; 01960 } 01961 else if (strcasecmp(addEmptyMode, "none")==0) { 01962 } 01963 else { 01964 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"", 01965 addEmptyMode); 01966 return -1; 01967 } 01968 break; 01969 } 01970 01971 /* use next group next time if any */ 01972 if (gcfg && gname) 01973 gcfg=GWEN_DB_FindNextGroup(gcfg, gname); 01974 } /* for */ 01975 } /* if "GROUP" */ 01976 } /* if TAG */ 01977 else if (t==GWEN_XMLNodeTypeData) { 01978 } 01979 else { 01980 DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled node type %d", t); 01981 } 01982 n=GWEN_XMLNode_Next(n); 01983 } /* while */ 01984 01985 /* write terminating character, if any */ 01986 if (terminator) { 01987 if (GWEN_Buffer_AppendByte(gbuf, terminator)) { 01988 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 01989 return -1; 01990 } 01991 } 01992 01993 if (!hasEntries) { 01994 DBG_INFO(GWEN_LOGDOMAIN, "No entries in node"); 01995 } 01996 return hasEntries?0:1; 01997 } 01998 01999 02000 02001 int GWEN_MsgEngine_CreateMessageFromNode(GWEN_MSGENGINE *e, 02002 GWEN_XMLNODE *node, 02003 GWEN_BUFFER *gbuf, 02004 GWEN_DB_NODE *msgData){ 02005 GWEN_XMLNODE_PATH *np; 02006 int rv; 02007 02008 assert(e); 02009 assert(node); 02010 assert(msgData); 02011 02012 np=GWEN_XMLNode_Path_new(); 02013 GWEN_XMLNode_Path_Dive(np, node); 02014 rv=GWEN_MsgEngine__WriteGroup(e, 02015 gbuf, 02016 node, 02017 0, 02018 msgData, 02019 0, 02020 np); 02021 GWEN_XMLNode_Path_free(np); 02022 if (rv){ 02023 const char *p; 02024 02025 p=GWEN_XMLNode_GetData(node); 02026 if (p) { 02027 DBG_INFO(GWEN_LOGDOMAIN, "Error writing group \"%s\"", p); 02028 } 02029 else { 02030 DBG_INFO(GWEN_LOGDOMAIN, "Error writing group"); 02031 } 02032 return -1; 02033 } 02034 02035 return 0; 02036 } 02037 02038 02039 02040 int GWEN_MsgEngine_CreateMessage(GWEN_MSGENGINE *e, 02041 const char *msgName, 02042 int msgVersion, 02043 GWEN_BUFFER *gbuf, 02044 GWEN_DB_NODE *msgData) { 02045 GWEN_XMLNODE *group; 02046 02047 group=GWEN_MsgEngine_FindGroupByProperty(e, "id", msgVersion, msgName); 02048 if (!group) { 02049 DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName); 02050 return -1; 02051 } 02052 return GWEN_MsgEngine_CreateMessageFromNode(e, 02053 group, 02054 gbuf, 02055 msgData); 02056 } 02057 02058 02059 02060 int GWEN_MsgEngine_AddDefinitions(GWEN_MSGENGINE *e, 02061 GWEN_XMLNODE *node) { 02062 GWEN_XMLNODE *nsrc, *ndst; 02063 02064 assert(e); 02065 assert(node); 02066 02067 if (!e->defs) { 02068 e->defs=GWEN_XMLNode_dup(node); 02069 e->ownDefs=1; 02070 return 0; 02071 } 02072 02073 nsrc=GWEN_XMLNode_GetChild(node); 02074 while(nsrc) { 02075 if (GWEN_XMLNode_GetType(nsrc)==GWEN_XMLNodeTypeTag) { 02076 ndst=GWEN_XMLNode_FindNode(e->defs, GWEN_XMLNodeTypeTag, 02077 GWEN_XMLNode_GetData(nsrc)); 02078 if (ndst) { 02079 GWEN_XMLNODE *n; 02080 02081 n=GWEN_XMLNode_GetChild(nsrc); 02082 while (n) { 02083 GWEN_XMLNODE *newNode; 02084 02085 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding node \"%s\"", GWEN_XMLNode_GetData(n)); 02086 newNode=GWEN_XMLNode_dup(n); 02087 GWEN_XMLNode_AddChild(ndst, newNode); 02088 n=GWEN_XMLNode_Next(n); 02089 } /* while n */ 02090 } 02091 else { 02092 GWEN_XMLNODE *newNode; 02093 02094 DBG_DEBUG(GWEN_LOGDOMAIN, "Adding branch \"%s\"", GWEN_XMLNode_GetData(nsrc)); 02095 newNode=GWEN_XMLNode_dup(nsrc); 02096 GWEN_XMLNode_AddChild(e->defs, newNode); 02097 } 02098 } /* if TAG */ 02099 nsrc=GWEN_XMLNode_Next(nsrc); 02100 } /* while */ 02101 02102 return 0; 02103 } 02104 02105 02106 02107 int GWEN_MsgEngine__ShowElement(GWEN_UNUSED GWEN_MSGENGINE *e, 02108 const char *path, 02109 GWEN_XMLNODE *node, 02110 GWEN_STRINGLIST *sl, 02111 uint32_t flags) { 02112 const char *name; 02113 const char *type; 02114 const char *npath; 02115 unsigned int minsize; 02116 unsigned int maxsize; 02117 unsigned int minnum; 02118 unsigned int maxnum; 02119 int j; 02120 int isSet; 02121 char nbuffer[256]; 02122 GWEN_STRINGLISTENTRY *en; 02123 02124 /* get type */ 02125 type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); 02126 02127 /* get some sizes */ 02128 minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); 02129 maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); 02130 minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1")); 02131 maxnum=atoi(GWEN_XMLNode_GetProperty(node, "maxnum","1")); 02132 02133 npath=""; 02134 isSet=0; 02135 02136 /* get name */ 02137 name=GWEN_XMLNode_GetProperty(node, "name", 0); 02138 if (path==0) 02139 path=""; 02140 02141 if (name) { 02142 /* get value of a config variable */ 02143 if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) { 02144 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02145 return -1; 02146 } 02147 if (*path) 02148 sprintf(nbuffer, "%s/%s", path, name); 02149 else 02150 sprintf(nbuffer, "%s", name); 02151 npath=nbuffer; 02152 } 02153 02154 en=GWEN_StringList_FirstEntry(sl); 02155 while(en) { 02156 if (GWEN_StringListEntry_Data(en)) 02157 if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) { 02158 isSet=1; 02159 break; 02160 } 02161 en=GWEN_StringListEntry_Next(en); 02162 } /* while */ 02163 02164 if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET)) 02165 return 0; 02166 02167 fprintf(stdout, " %s", 02168 npath); 02169 j=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(npath); 02170 if (j>0) { 02171 int i; 02172 02173 for (i=0; i<j; i++) 02174 fprintf(stdout, " "); 02175 } 02176 fprintf(stdout, "| %s", type); 02177 j=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(type); 02178 if (j>0) { 02179 int i; 02180 02181 for (i=0; i<j; i++) 02182 fprintf(stdout, " "); 02183 } 02184 fprintf(stdout, "| %4d-%4d", minsize, maxsize); 02185 fprintf(stdout," | %3d ", maxnum); 02186 fprintf(stdout," |"); 02187 if (minnum==0) 02188 fprintf(stdout," optvar"); 02189 if (flags & GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL) 02190 fprintf(stdout," optgrp"); 02191 02192 if (isSet) { 02193 fprintf(stdout," set"); 02194 } 02195 02196 fprintf(stdout,"\n"); 02197 02198 return 0; 02199 } 02200 02201 02202 02203 int GWEN_MsgEngine__ShowGroup(GWEN_MSGENGINE *e, 02204 const char *path, 02205 GWEN_XMLNODE *node, 02206 GWEN_XMLNODE *rnode, 02207 GWEN_STRINGLIST *sl, 02208 uint32_t flags) { 02209 GWEN_XMLNODE *n; 02210 int isFirstElement; 02211 int omittedElements; 02212 int rv; 02213 02214 /* setup data */ 02215 n=GWEN_XMLNode_GetChild(node); 02216 02217 if (path==0) 02218 path=""; 02219 if (*path=='/') 02220 path++; 02221 02222 while(n) { 02223 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 02224 const char *p; 02225 02226 p=GWEN_XMLNode_GetData(n); 02227 assert(p); 02228 DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p); 02229 if (strcasecmp(p, "VALUES")==0) 02230 break; 02231 } /* if tag */ 02232 n=GWEN_XMLNode_Next(n); 02233 } /* while */ 02234 02235 if (n) { 02236 DBG_DEBUG(GWEN_LOGDOMAIN, "<preset> found"); 02237 /* <preset> found, handle all values */ 02238 n=GWEN_XMLNode_GetChild(n); 02239 while(n) { 02240 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 02241 const char *p; 02242 02243 p=GWEN_XMLNode_GetData(n); 02244 assert(p); 02245 if (strcasecmp(p, "VALUE")==0) { 02246 const char *pname; 02247 const char *pvalue; 02248 02249 pname=GWEN_XMLNode_GetProperty(n, "path", 0); 02250 if (pname) { 02251 GWEN_XMLNODE *dn; 02252 02253 /* path found, find data */ 02254 dn=GWEN_XMLNode_GetChild(n); 02255 while (dn) { 02256 if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { 02257 pvalue=GWEN_XMLNode_GetData(dn); 02258 if (pvalue) { 02259 char pbuffer[256]; 02260 02261 /* check whether the value is a property */ 02262 p=pvalue; 02263 while (*p && isspace((int)*p)) 02264 p++; 02265 if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) { 02266 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02267 return -1; 02268 } 02269 if (*path) 02270 sprintf(pbuffer, "%s/%s", path, pname); 02271 else 02272 sprintf(pbuffer, "%s", pname); 02273 GWEN_StringList_AppendString(sl, 02274 pbuffer, 02275 0, 02276 1); 02277 } 02278 break; 02279 } 02280 dn=GWEN_XMLNode_Next(dn); 02281 } /* while dn */ 02282 } /* if path given */ 02283 } /* if VALUE tag */ 02284 } /* if TAG */ 02285 n=GWEN_XMLNode_Next(n); 02286 } /* while */ 02287 } /* if <preset> found */ 02288 02289 /* now handle all child entries */ 02290 n=GWEN_XMLNode_GetChild(node); 02291 isFirstElement=1; 02292 omittedElements=0; 02293 while(n) { 02294 int t; 02295 unsigned int minnum; 02296 unsigned int maxnum; 02297 int gversion; 02298 const char *addEmptyMode; 02299 unsigned int loopNr; 02300 unsigned int lflags; 02301 02302 minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); 02303 maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); 02304 gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); 02305 addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one"); 02306 02307 lflags=flags; 02308 02309 DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements); 02310 t=GWEN_XMLNode_GetType(n); 02311 if (t==GWEN_XMLNodeTypeTag) { 02312 const char *typ; 02313 02314 typ=GWEN_XMLNode_GetData(n); 02315 if (typ==0) { 02316 DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); 02317 return -1; 02318 } 02319 if (strcasecmp(typ, "ELEM")==0) { 02320 /* element tag found */ 02321 02322 /* write element as often as needed */ 02323 rv=GWEN_MsgEngine__ShowElement(e, 02324 path, 02325 n, 02326 sl, 02327 lflags); 02328 if (rv==-1) 02329 return -1; 02330 else { 02331 isFirstElement=0; 02332 omittedElements=0; 02333 } 02334 } 02335 else if (strcasecmp(typ, "VALUES")==0) { 02336 } 02337 else if (strcasecmp(typ, "DESCR")==0) { 02338 } 02339 else { 02340 /* group tag found */ 02341 GWEN_XMLNODE *gn; 02342 const char *gname; 02343 const char *gtype; 02344 02345 if (minnum==0) 02346 lflags|=GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL; 02347 02348 gtype=GWEN_XMLNode_GetProperty(n, "type",0); 02349 if (!gtype) { 02350 /* no "type" property, so use this group directly */ 02351 DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ); 02352 gtype=""; 02353 gn=n; 02354 } 02355 else { 02356 gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype); 02357 if (!gn) { 02358 DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); 02359 return -1; 02360 } 02361 } 02362 02363 /* write group as often as needed */ 02364 for (loopNr=0; loopNr<maxnum; loopNr++) { 02365 /* find group */ 02366 char pbuffer[256]; 02367 const char *npath; 02368 02369 /* get configuration */ 02370 gname=GWEN_XMLNode_GetProperty(n, "name",0); 02371 if (gname) { 02372 if (loopNr==0) { 02373 if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) { 02374 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02375 return -1; 02376 } 02377 sprintf(pbuffer, "%s/%s", path, gname); 02378 npath=pbuffer; 02379 } 02380 else { 02381 /* this is not the first one, so create new name */ 02382 if (strlen(path)+strlen(gname)+10>sizeof(pbuffer)) { 02383 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02384 return -1; 02385 } 02386 if (*path) 02387 sprintf(pbuffer, "%s/%s%d", path, gname, loopNr); 02388 else 02389 sprintf(pbuffer, "%s%d", gname, loopNr); 02390 /* get the value of the given var */ 02391 npath=pbuffer; 02392 } 02393 } /* if name given */ 02394 else 02395 npath=path; 02396 02397 /* write group */ 02398 if (GWEN_MsgEngine__ShowGroup(e, 02399 npath, 02400 gn, 02401 n, 02402 sl, 02403 lflags)) { 02404 DBG_INFO(GWEN_LOGDOMAIN, "Could not show group \"%s\"", gtype); 02405 return -1; 02406 } 02407 } /* for */ 02408 } 02409 } 02410 n=GWEN_XMLNode_Next(n); 02411 } /* while */ 02412 02413 return 0; 02414 } 02415 02416 02417 02418 int GWEN_MsgEngine_ShowMessage(GWEN_MSGENGINE *e, 02419 const char *typ, 02420 const char *msgName, 02421 int msgVersion, 02422 uint32_t flags) { 02423 GWEN_XMLNODE *group; 02424 GWEN_STRINGLIST *sl; 02425 int i, j; 02426 const char *p; 02427 02428 sl=GWEN_StringList_new(); 02429 02430 fprintf(stdout, "Message \"%s\" version %d\n", 02431 msgName, msgVersion); 02432 for (i=0; i<76; i++) 02433 fprintf(stdout, "="); 02434 fprintf(stdout, "\n"); 02435 p=" Variable"; 02436 fprintf(stdout, "%s", p); 02437 i=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(p); 02438 for (j=0; j<i; j++) 02439 fprintf(stdout," "); 02440 02441 fprintf(stdout," |"); 02442 p=" Type"; 02443 fprintf(stdout, "%s", p); 02444 i=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(p); 02445 for (j=0; j<i; j++) 02446 fprintf(stdout," "); 02447 02448 fprintf(stdout," | Size | Num | Flags\n"); 02449 for (i=0; i<76; i++) 02450 fprintf(stdout, "-"); 02451 fprintf(stdout, "\n"); 02452 02453 group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName); 02454 if (!group) { 02455 DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName); 02456 GWEN_StringList_free(sl); 02457 return -1; 02458 } 02459 02460 if (GWEN_MsgEngine__ShowGroup(e, 02461 "", 02462 group, 02463 0, 02464 sl, 02465 flags)) { 02466 DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName); 02467 GWEN_StringList_free(sl); 02468 return -1; 02469 } 02470 02471 GWEN_StringList_free(sl); 02472 02473 return 0; 02474 } 02475 02476 02477 02478 int GWEN_MsgEngine__ListElement(GWEN_UNUSED GWEN_MSGENGINE *e, 02479 const char *path, 02480 GWEN_XMLNODE *node, 02481 GWEN_STRINGLIST *sl, 02482 GWEN_XMLNODE *listNode, 02483 uint32_t flags) { 02484 const char *name; 02485 const char *type; 02486 const char *npath; 02487 int isSet; 02488 char nbuffer[256]; 02489 GWEN_STRINGLISTENTRY *en; 02490 GWEN_XMLNODE *nn; 02491 02492 /* get type */ 02493 type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); 02494 02495 npath=""; 02496 isSet=0; 02497 02498 /* get name */ 02499 name=GWEN_XMLNode_GetProperty(node, "name", 0); 02500 if (path==0) 02501 path=""; 02502 02503 if (name) { 02504 /* get value of a config variable */ 02505 if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) { 02506 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02507 return -1; 02508 } 02509 if (*path) 02510 sprintf(nbuffer, "%s/%s", path, name); 02511 else 02512 sprintf(nbuffer, "%s", name); 02513 npath=nbuffer; 02514 } 02515 02516 en=GWEN_StringList_FirstEntry(sl); 02517 while(en) { 02518 if (GWEN_StringListEntry_Data(en)) 02519 if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) { 02520 isSet=1; 02521 break; 02522 } 02523 en=GWEN_StringListEntry_Next(en); 02524 } /* while */ 02525 02526 if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET)) 02527 return 0; 02528 02529 nn=GWEN_XMLNode_dup(node); 02530 if (isSet) 02531 GWEN_XMLNode_SetProperty(nn, "GWEN_set", "1"); 02532 GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath); 02533 GWEN_XMLNode_AddChild(listNode, nn); 02534 02535 return 0; 02536 } 02537 02538 02539 02540 int GWEN_MsgEngine__ListGroup(GWEN_MSGENGINE *e, 02541 const char *path, 02542 GWEN_XMLNODE *node, 02543 GWEN_XMLNODE *rnode, 02544 GWEN_STRINGLIST *sl, 02545 GWEN_XMLNODE *listNode, 02546 uint32_t flags) { 02547 GWEN_XMLNODE *n; 02548 int rv; 02549 02550 /* setup data */ 02551 n=GWEN_XMLNode_GetChild(node); 02552 02553 if (path==0) 02554 path=""; 02555 if (*path=='/') 02556 path++; 02557 02558 while(n) { 02559 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 02560 const char *p; 02561 02562 p=GWEN_XMLNode_GetData(n); 02563 assert(p); 02564 DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p); 02565 if (strcasecmp(p, "VALUES")==0) 02566 break; 02567 } /* if tag */ 02568 n=GWEN_XMLNode_Next(n); 02569 } /* while */ 02570 02571 if (n) { 02572 DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found"); 02573 /* <values> found, handle all values */ 02574 n=GWEN_XMLNode_GetChild(n); 02575 while(n) { 02576 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 02577 const char *p; 02578 02579 p=GWEN_XMLNode_GetData(n); 02580 assert(p); 02581 if (strcasecmp(p, "VALUE")==0) { 02582 const char *pname; 02583 const char *pvalue; 02584 02585 pname=GWEN_XMLNode_GetProperty(n, "path", 0); 02586 if (pname) { 02587 GWEN_XMLNODE *dn; 02588 02589 /* path found, find data */ 02590 dn=GWEN_XMLNode_GetChild(n); 02591 while (dn) { 02592 if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { 02593 pvalue=GWEN_XMLNode_GetData(dn); 02594 if (pvalue) { 02595 char pbuffer[256]; 02596 02597 /* check whether the value is a property */ 02598 p=pvalue; 02599 while (*p && isspace((int)*p)) 02600 p++; 02601 if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) { 02602 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02603 return -1; 02604 } 02605 if (*path) 02606 sprintf(pbuffer, "%s/%s", path, pname); 02607 else 02608 sprintf(pbuffer, "%s", pname); 02609 DBG_INFO(GWEN_LOGDOMAIN, "Found preset value for %s", pbuffer); 02610 GWEN_StringList_AppendString(sl, 02611 pbuffer, 02612 0, 02613 1); 02614 } 02615 break; 02616 } 02617 dn=GWEN_XMLNode_Next(dn); 02618 } /* while dn */ 02619 } /* if path given */ 02620 } /* if VALUE tag */ 02621 } /* if TAG */ 02622 n=GWEN_XMLNode_Next(n); 02623 } /* while */ 02624 } /* if <values> found */ 02625 02626 /* now handle all child entries */ 02627 n=GWEN_XMLNode_GetChild(node); 02628 while(n) { 02629 int t; 02630 int gversion; 02631 unsigned int lflags; 02632 02633 gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); 02634 lflags=flags; 02635 02636 t=GWEN_XMLNode_GetType(n); 02637 if (t==GWEN_XMLNodeTypeTag) { 02638 const char *typ; 02639 02640 typ=GWEN_XMLNode_GetData(n); 02641 if (typ==0) { 02642 DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); 02643 return -1; 02644 } 02645 if (strcasecmp(typ, "ELEM")==0) { 02646 /* element tag found */ 02647 02648 /* list element */ 02649 rv=GWEN_MsgEngine__ListElement(e, 02650 path, 02651 n, 02652 sl, 02653 listNode, 02654 lflags); 02655 if (rv==-1) 02656 return -1; 02657 } 02658 else if (strcasecmp(typ, "VALUES")==0) { 02659 } 02660 else if (strcasecmp(typ, "DESCR")==0) { 02661 } 02662 else { 02663 /* group tag found */ 02664 GWEN_XMLNODE *gn; 02665 GWEN_XMLNODE *nn; 02666 const char *gname; 02667 const char *gtype; 02668 char pbuffer[256]; 02669 const char *npath; 02670 02671 gtype=GWEN_XMLNode_GetProperty(n, "type",0); 02672 if (!gtype) { 02673 /* no "type" property, so use this group directly */ 02674 DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ); 02675 gtype=""; 02676 gn=n; 02677 } 02678 else { 02679 gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype); 02680 if (!gn) { 02681 DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); 02682 return -1; 02683 } 02684 } 02685 02686 /* get configuration */ 02687 gname=GWEN_XMLNode_GetProperty(n, "name",0); 02688 if (gname) { 02689 if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) { 02690 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 02691 return -1; 02692 } 02693 02694 if (*path) 02695 sprintf(pbuffer, "%s/%s", path, gname); 02696 else 02697 sprintf(pbuffer, "%s", gname); 02698 npath=pbuffer; 02699 } /* if name given */ 02700 else 02701 npath=path; 02702 02703 nn=GWEN_XMLNode_dup(n); 02704 if (gn!=n) 02705 GWEN_XMLNode_CopyProperties(nn, gn, 0); 02706 GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath); 02707 GWEN_XMLNode_AddChild(listNode, nn); 02708 02709 /* write group */ 02710 if (GWEN_MsgEngine__ListGroup(e, 02711 npath, 02712 gn, 02713 n, 02714 sl, 02715 nn, 02716 lflags)) { 02717 DBG_INFO(GWEN_LOGDOMAIN, "Could not list group \"%s\"", gtype); 02718 return -1; 02719 } 02720 } 02721 } 02722 n=GWEN_XMLNode_Next(n); 02723 } /* while */ 02724 02725 return 0; 02726 } 02727 02728 02729 02730 GWEN_XMLNODE *GWEN_MsgEngine_ListMessage(GWEN_MSGENGINE *e, 02731 const char *typ, 02732 const char *msgName, 02733 int msgVersion, 02734 uint32_t flags) { 02735 GWEN_XMLNODE *group; 02736 GWEN_STRINGLIST *sl; 02737 GWEN_XMLNODE *listNode; 02738 02739 group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName); 02740 if (!group) 02741 group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "code", 02742 msgVersion, msgName); 02743 if (!group) { 02744 DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" (version %d) not found\n", 02745 msgName, msgVersion); 02746 return 0; 02747 } 02748 02749 sl=GWEN_StringList_new(); 02750 /* copy group, but remove all children (we only want the properties) */ 02751 listNode=GWEN_XMLNode_dup(group); 02752 GWEN_XMLNode_RemoveChildren(listNode); 02753 02754 if (GWEN_MsgEngine__ListGroup(e, 02755 "", 02756 group, 02757 0, 02758 sl, 02759 listNode, 02760 flags)) { 02761 DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName); 02762 GWEN_StringList_free(sl); 02763 GWEN_XMLNode_free(listNode); 02764 return 0; 02765 } 02766 02767 GWEN_StringList_free(sl); 02768 02769 return listNode; 02770 } 02771 02772 02773 02774 02775 02776 02777 02778 int GWEN_MsgEngine__ReadValue(GWEN_MSGENGINE *e, 02779 GWEN_BUFFER *msgbuf, 02780 GWEN_XMLNODE *node, 02781 GWEN_XMLNODE *rnode, 02782 GWEN_BUFFER *vbuf, 02783 const char *delimiters, 02784 uint32_t flags) { 02785 unsigned int minsize; 02786 unsigned int maxsize; 02787 unsigned int size; 02788 unsigned int minnum; 02789 GWEN_MSGENGINE_TRUSTLEVEL trustLevel; 02790 unsigned int posInMsg; 02791 const char *type; 02792 int rv; 02793 unsigned int realSize; 02794 02795 /* get some sizes */ 02796 posInMsg=GWEN_Buffer_GetPos(msgbuf); 02797 realSize=0; 02798 size=atoi(GWEN_XMLNode_GetProperty(node, "size","0")); 02799 minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); 02800 maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); 02801 minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1")); 02802 type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); 02803 02804 rv=1; 02805 if (e->typeReadPtr) { 02806 rv=e->typeReadPtr(e, 02807 msgbuf, 02808 node, 02809 vbuf, 02810 e->escapeChar, 02811 delimiters); 02812 } 02813 if (rv==-1) { 02814 DBG_INFO(GWEN_LOGDOMAIN, "External type reading failed on type \"%s\"", type); 02815 return -1; 02816 } 02817 else if (rv==1) { 02818 if (strcasecmp(type, "bin")==0) { 02819 if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) { 02820 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (@num@ expected)"); 02821 return -1; 02822 } 02823 else { 02824 char lbuffer[16]; 02825 int c; 02826 char *p; 02827 int l; 02828 02829 p=lbuffer; 02830 c=GWEN_Buffer_ReadByte(msgbuf); 02831 if (c!='@') { 02832 DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); 02833 return -1; 02834 } 02835 02836 c=0; 02837 while(GWEN_Buffer_GetBytesLeft(msgbuf)>0) { 02838 c=GWEN_Buffer_ReadByte(msgbuf); 02839 if (c==-1) { 02840 DBG_ERROR(GWEN_LOGDOMAIN, "\"@\" expected"); 02841 return -1; 02842 } 02843 if (c=='@') 02844 break; 02845 *p=(char)c; 02846 p++; 02847 } /* while */ 02848 *p=0; 02849 if (c!='@') { 02850 DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); 02851 return -1; 02852 } 02853 if (sscanf(lbuffer, "%d", &l)!=1) { 02854 DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format"); 02855 return -1; 02856 } 02857 DBG_DEBUG(GWEN_LOGDOMAIN, "Reading binary: %d bytes from pos %d (msgsize=%d)", 02858 l, 02859 GWEN_Buffer_GetPos(msgbuf), 02860 GWEN_Buffer_GetUsedBytes(msgbuf)); 02861 if (GWEN_Buffer_GetBytesLeft(msgbuf) < (unsigned) l) { 02862 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)"); 02863 return -1; 02864 } 02865 if (GWEN_Buffer_AppendBytes(vbuf, 02866 GWEN_Buffer_GetPosPointer(msgbuf), 02867 l)) { 02868 DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here"); 02869 return -1; 02870 } 02871 GWEN_Buffer_IncrementPos(msgbuf,l); 02872 } 02873 } /* if bin */ 02874 else { 02875 /* type is not bin */ 02876 int lastWasEscape; 02877 int isEscaped; 02878 int br; 02879 02880 isEscaped=0; 02881 lastWasEscape=0; 02882 02883 br=0; 02884 while(GWEN_Buffer_GetBytesLeft(msgbuf) && 02885 (size==0 || br<size)) { 02886 int c; 02887 02888 c=GWEN_Buffer_ReadByte(msgbuf); 02889 if (lastWasEscape) { 02890 lastWasEscape=0; 02891 isEscaped=1; 02892 } 02893 else { 02894 isEscaped=0; 02895 if (c==e->escapeChar) { 02896 lastWasEscape=1; 02897 c=-1; 02898 } 02899 } 02900 if (c!=-1) { 02901 if (!isEscaped && (c && strchr(delimiters, c)!=0)) { 02902 /* delimiter found, step back */ 02903 GWEN_Buffer_DecrementPos(msgbuf,1); 02904 break; 02905 } 02906 else { 02907 if (c=='\\' || iscntrl(c)) { 02908 DBG_WARN(GWEN_LOGDOMAIN, 02909 "Found a bad character (%02x) in type \"%s\", " 02910 "converting to SPACE", 02911 (unsigned int)c, 02912 type); 02913 c=' '; 02914 } 02915 if (GWEN_Buffer_AppendByte(vbuf, c)) { 02916 DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here"); 02917 return -1; 02918 } 02919 br++; 02920 } 02921 } 02922 } /* while */ 02923 } /* if !bin */ 02924 } /* if type not external */ 02925 else { 02926 DBG_DEBUG(GWEN_LOGDOMAIN, "Type \"%s\" is external (read)", type); 02927 } 02928 02929 realSize=GWEN_Buffer_GetUsedBytes(vbuf); 02930 02931 /* check the value */ 02932 if (realSize==0) { 02933 DBG_DEBUG(GWEN_LOGDOMAIN, "Datasize is 0"); 02934 if (minnum==0) { 02935 DBG_DEBUG(GWEN_LOGDOMAIN, "... but thats ok"); 02936 /* value is empty, and that is allowed */ 02937 return 1; 02938 } 02939 else { 02940 DBG_ERROR(GWEN_LOGDOMAIN, "Value missing"); 02941 GWEN_XMLNode_Dump(node, 1); 02942 return -1; 02943 } 02944 } 02945 02946 /* check minimum size */ 02947 if (minsize!=0 && realSize<minsize) { 02948 DBG_INFO(GWEN_LOGDOMAIN, "Value too short (%d<%d).", 02949 realSize, 02950 minsize); 02951 return -1; 02952 } 02953 02954 /* check maximum size */ 02955 if (maxsize!=0 && realSize>maxsize) { 02956 DBG_INFO(GWEN_LOGDOMAIN, "Value too long (%d>%d).", 02957 realSize, maxsize); 02958 return -1; 02959 } 02960 02961 if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) { 02962 /* add trust data to msgEngine */ 02963 const char *descr; 02964 02965 trustLevel=GWEN_MsgEngine_GetHighestTrustLevel(node, rnode); 02966 if (trustLevel) { 02967 unsigned int ustart; 02968 02969 ustart=GWEN_Buffer_GetPos(msgbuf)-realSize; 02970 descr=GWEN_XMLNode_GetProperty(node, "name",0); 02971 if (GWEN_MsgEngine_AddTrustInfo(e, 02972 GWEN_Buffer_GetStart(vbuf), 02973 realSize, 02974 descr, 02975 trustLevel, 02976 ustart)) { 02977 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 02978 return -1; 02979 } 02980 } 02981 } 02982 02983 return 0; 02984 } 02985 02986 02987 02988 int GWEN_MsgEngine__ReadGroup(GWEN_MSGENGINE *e, 02989 GWEN_BUFFER *msgbuf, 02990 GWEN_XMLNODE *node, 02991 GWEN_XMLNODE *rnode, 02992 GWEN_DB_NODE *gr, 02993 const char *delimiters, 02994 uint32_t flags) { 02995 unsigned int minsize; 02996 unsigned int maxsize; 02997 unsigned int minnum; 02998 unsigned int maxnum; 02999 const char *name; 03000 const char *p; 03001 char delimiter; 03002 char terminator; 03003 GWEN_XMLNODE *n; 03004 int abortLoop; 03005 GWEN_BUFFER *delimBuffer=0; 03006 03007 /* get some settings */ 03008 if (rnode) { 03009 /* get delimiter */ 03010 p=GWEN_XMLNode_GetProperty(rnode, 03011 "delimiter", 03012 GWEN_XMLNode_GetProperty(node, 03013 "delimiter", 03014 "")); 03015 delimiter=*p; 03016 03017 /* get terminating char, if any */ 03018 p=GWEN_XMLNode_GetProperty(rnode, 03019 "terminator", 03020 GWEN_XMLNode_GetProperty(node, 03021 "terminator", 03022 "")); 03023 terminator=*p; 03024 } 03025 else { 03026 /* get delimiter */ 03027 p=GWEN_XMLNode_GetProperty(node, 03028 "delimiter", 03029 ""); 03030 delimiter=*p; 03031 03032 /* get terminating char, if any */ 03033 p=GWEN_XMLNode_GetProperty(node, "terminator",""); 03034 terminator=*p; 03035 } 03036 03037 delimBuffer=GWEN_Buffer_new(0, strlen(delimiters)+2, 0, 1); 03038 GWEN_Buffer_AppendString(delimBuffer, delimiters); 03039 if (delimiter) 03040 GWEN_Buffer_AppendByte(delimBuffer, delimiter); 03041 if (terminator) 03042 GWEN_Buffer_AppendByte(delimBuffer, terminator); 03043 03044 DBG_DEBUG(GWEN_LOGDOMAIN, "Delimiters are \"%s\" and \"%c\"", 03045 delimiters, delimiter); 03046 03047 n=GWEN_XMLNode_GetChild(node); 03048 while (n) { 03049 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 03050 const char *type; 03051 03052 if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) 03053 break; 03054 03055 type=GWEN_XMLNode_GetData(n); 03056 03057 /* 03058 DBG_NOTICE(GWEN_LOGDOMAIN, "Reading group from here :"); 03059 GWEN_Text_DumpString(GWEN_Buffer_GetStart(msgbuf)+ 03060 GWEN_Buffer_GetPos(msgbuf), 03061 GWEN_Buffer_GetUsedBytes(msgbuf)- 03062 GWEN_Buffer_GetPos(msgbuf), 03063 stderr, 3); 03064 */ 03065 if (strcasecmp(type, "ELEM")==0) { 03066 unsigned int loopNr; 03067 03068 /* get some sizes */ 03069 minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize","0")); 03070 maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize","0")); 03071 minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); 03072 maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); 03073 name=GWEN_XMLNode_GetProperty(n, "name", 0); 03074 03075 loopNr=0; 03076 abortLoop=0; 03077 while((maxnum==0 || loopNr<maxnum) && !abortLoop) { 03078 int c; 03079 03080 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %s", name); 03081 if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) 03082 break; 03083 c=GWEN_Buffer_PeekByte(msgbuf); 03084 if (c==-1) { 03085 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here"); 03086 GWEN_Buffer_free(delimBuffer); 03087 return -1; 03088 } 03089 03090 DBG_VERBOUS(GWEN_LOGDOMAIN, 03091 "Checking delimiter at pos %x " 03092 "(whether \"%c\" is in \"%s\")", 03093 GWEN_Buffer_GetPos(msgbuf), 03094 c, GWEN_Buffer_GetStart(delimBuffer)); 03095 if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) { 03096 abortLoop=1; 03097 DBG_VERBOUS(GWEN_LOGDOMAIN, 03098 "Found delimiter (\"%c\" is in \"%s\")", 03099 c, GWEN_Buffer_GetStart(delimBuffer)); 03100 } /* if delimiter found */ 03101 else { 03102 /* current char is not a delimiter */ 03103 if (name==0) { 03104 DBG_VERBOUS(GWEN_LOGDOMAIN, "no name"); 03105 } 03106 else { 03107 /* name is given */ 03108 int rv; 03109 const char *dtype; 03110 GWEN_BUFFER *vbuf; 03111 03112 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading value from pos %x", 03113 GWEN_Buffer_GetPos(msgbuf)); 03114 vbuf=GWEN_Buffer_new(0, 03115 GWEN_MSGENGINE_MAX_VALUE_LEN, 03116 0,0); 03117 /* 03118 DBG_ERROR(GWEN_LOGDOMAIN, "Reading value from here:\n"); 03119 GWEN_Text_DumpString(GWEN_Buffer_GetPosPointer(msgbuf), 03120 GWEN_Buffer_GetBytesLeft(msgbuf), 03121 stderr, 1);*/ 03122 03123 rv=GWEN_MsgEngine__ReadValue(e, 03124 msgbuf, 03125 n, 03126 rnode, 03127 vbuf, 03128 GWEN_Buffer_GetStart(delimBuffer), 03129 //":+'", 03130 flags); 03131 if (rv==1) { 03132 DBG_INFO(GWEN_LOGDOMAIN, "Empty value"); 03133 } 03134 else if (rv==-1) { 03135 DBG_INFO(GWEN_LOGDOMAIN, "Error parsing node \"%s\" (%s)", 03136 name, 03137 type); 03138 GWEN_Buffer_free(vbuf); 03139 GWEN_Buffer_free(delimBuffer); 03140 return -1; 03141 } 03142 03143 GWEN_Buffer_Rewind(vbuf); 03144 03145 /* special handling for binary data */ 03146 dtype=GWEN_XMLNode_GetProperty(n, "type", ""); 03147 if (GWEN_MsgEngine__IsBinTyp(e, dtype)) { 03148 if (atoi(GWEN_XMLNode_GetProperty(n, "readbin", "1")) && 03149 e->binTypeReadPtr) { 03150 rv=e->binTypeReadPtr(e, n, gr, vbuf); 03151 } 03152 else 03153 rv=1; 03154 if (rv==-1) { 03155 DBG_INFO(GWEN_LOGDOMAIN, "Called from here"); 03156 GWEN_Buffer_free(vbuf); 03157 GWEN_Buffer_free(delimBuffer); 03158 return -1; 03159 } 03160 else if (rv==1) { 03161 /* bin type not handled, so handle it myself */ 03162 if (GWEN_DB_SetBinValue(gr, 03163 GWEN_DB_FLAGS_DEFAULT, 03164 name, 03165 GWEN_Buffer_GetStart(vbuf), 03166 GWEN_Buffer_GetUsedBytes(vbuf))) { 03167 DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name); 03168 GWEN_Buffer_free(vbuf); 03169 GWEN_Buffer_free(delimBuffer); 03170 return -1; 03171 } 03172 } 03173 } /* if type is bin */ 03174 else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) { 03175 int z; 03176 03177 if (1!=sscanf(GWEN_Buffer_GetStart(vbuf), "%d", &z)) { 03178 DBG_INFO(GWEN_LOGDOMAIN, "Value for \"%s\" is not an integer", 03179 name); 03180 GWEN_Buffer_free(delimBuffer); 03181 return -1; 03182 } 03183 if (GWEN_DB_SetIntValue(gr, 03184 GWEN_DB_FLAGS_DEFAULT, 03185 name, z)) { 03186 DBG_INFO(GWEN_LOGDOMAIN, "Could not set int value for \"%s\"", name); 03187 GWEN_Buffer_free(delimBuffer); 03188 return -1; 03189 } 03190 } /* if type is int */ 03191 else { 03192 DBG_DEBUG(GWEN_LOGDOMAIN, "Value is \"%s\"", 03193 GWEN_Buffer_GetStart(vbuf)); 03194 if (GWEN_DB_SetCharValue(gr, 03195 GWEN_DB_FLAGS_DEFAULT, 03196 name, 03197 GWEN_Buffer_GetStart(vbuf))){ 03198 DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name); 03199 GWEN_Buffer_free(delimBuffer); 03200 return -1; 03201 } 03202 } /* if !bin */ 03203 03204 GWEN_Buffer_free(vbuf); 03205 } /* if name is given */ 03206 } /* if current char is not a delimiter */ 03207 03208 if (GWEN_Buffer_GetBytesLeft(msgbuf)) { 03209 if (delimiter) { 03210 if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) { 03211 GWEN_Buffer_IncrementPos(msgbuf,1); 03212 } 03213 } 03214 } 03215 loopNr++; 03216 } /* while */ 03217 if (loopNr<minnum) { 03218 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few ELEM repeats)"); 03219 GWEN_XMLNode_Dump(n, 2); 03220 GWEN_Buffer_free(delimBuffer); 03221 return -1; 03222 } 03223 n=GWEN_XMLNode_Next(n); 03224 } /* if ELEM */ 03225 else if (strcasecmp(type, "VALUES")==0) { 03226 n=GWEN_XMLNode_Next(n); 03227 } 03228 else if (strcasecmp(type, "DESCR")==0) { 03229 n=GWEN_XMLNode_Next(n); 03230 } 03231 else { 03232 /* group tag found */ 03233 GWEN_XMLNODE *gn; 03234 GWEN_DB_NODE *gcfg; 03235 const char *gname; 03236 const char *gtype; 03237 unsigned int gversion; 03238 unsigned int loopNr; 03239 03240 minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); 03241 maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); 03242 gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); 03243 gtype=GWEN_XMLNode_GetProperty(n, "type",0); 03244 if (!gtype) { 03245 /* no "type" property, so use this group directly */ 03246 DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", type); 03247 gtype=""; 03248 gn=n; 03249 } 03250 else { 03251 gn=GWEN_MsgEngine_FindNodeByProperty(e, type, "id", 03252 gversion, gtype); 03253 if (!gn) { 03254 DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", type); 03255 GWEN_Buffer_free(delimBuffer); 03256 return -1; 03257 } 03258 } 03259 03260 /* get configuration */ 03261 loopNr=0; 03262 abortLoop=0; 03263 while((maxnum==0 || loopNr<maxnum) && !abortLoop) { 03264 int c; 03265 03266 DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group type %s", gtype); 03267 if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) 03268 break; 03269 c=GWEN_Buffer_PeekByte(msgbuf); 03270 if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) { 03271 abortLoop=1; 03272 } 03273 else { 03274 gname=GWEN_XMLNode_GetProperty(n, "name",0); 03275 if (gname) { 03276 DBG_DEBUG(GWEN_LOGDOMAIN, "Creating group \"%s\"", gname); 03277 gcfg=GWEN_DB_GetGroup(gr, 03278 GWEN_PATH_FLAGS_CREATE_GROUP, 03279 gname); 03280 if (!gcfg) { 03281 DBG_ERROR(GWEN_LOGDOMAIN, "Could not select group \"%s\"", 03282 gname); 03283 GWEN_Buffer_free(delimBuffer); 03284 return -1; 03285 } 03286 DBG_DEBUG(GWEN_LOGDOMAIN, "Created group \"%s\"", gname); 03287 } /* if name given */ 03288 else 03289 gcfg=gr; 03290 03291 /* read group */ 03292 DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group \"%s\"", gname); 03293 if (GWEN_MsgEngine__ReadGroup(e, 03294 msgbuf, 03295 gn, 03296 n, 03297 gcfg, 03298 GWEN_Buffer_GetStart(delimBuffer), 03299 flags)) { 03300 DBG_INFO(GWEN_LOGDOMAIN, "Could not read group \"%s\"", gtype); 03301 GWEN_Buffer_free(delimBuffer); 03302 return -1; 03303 } 03304 } 03305 if (GWEN_Buffer_GetBytesLeft(msgbuf)) { 03306 if (delimiter) { 03307 if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) { 03308 GWEN_Buffer_IncrementPos(msgbuf, 1); 03309 } 03310 } 03311 } 03312 loopNr++; 03313 } /* while */ 03314 if (loopNr<minnum) { 03315 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few group repeats)"); 03316 GWEN_Buffer_free(delimBuffer); 03317 return -1; 03318 } 03319 n=GWEN_XMLNode_Next(n); 03320 } /* if GROUP */ 03321 } /* if TAG */ 03322 else { 03323 n=GWEN_XMLNode_Next(n); 03324 } 03325 } /* while */ 03326 03327 /* check whether there still are nodes which have not been read */ 03328 while(n) { 03329 if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { 03330 if (strcasecmp(GWEN_XMLNode_GetData(n), "ELEM")==0 || 03331 strcasecmp(GWEN_XMLNode_GetData(n), "GROUP")==0) { 03332 unsigned int i; 03333 03334 i=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1")); 03335 if (i) { 03336 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (still tags to parse)"); 03337 GWEN_XMLNode_Dump(n, 2); 03338 GWEN_Buffer_free(delimBuffer); 03339 return -1; 03340 } 03341 } 03342 } 03343 n=GWEN_XMLNode_Next(n); 03344 } 03345 03346 03347 if (terminator) { 03348 /* skip terminator */ 03349 if (GWEN_Buffer_GetBytesLeft(msgbuf)) { 03350 if (GWEN_Buffer_PeekByte(msgbuf)==terminator) { 03351 GWEN_Buffer_IncrementPos(msgbuf, 1); 03352 } 03353 else { 03354 DBG_ERROR(GWEN_LOGDOMAIN, 03355 "Terminating character missing (pos=%d [%x]) " 03356 "expecting \"%c\", got \"%c\")", 03357 GWEN_Buffer_GetPos(msgbuf), 03358 GWEN_Buffer_GetPos(msgbuf), 03359 terminator, 03360 GWEN_Buffer_PeekByte(msgbuf)); 03361 GWEN_XMLNode_Dump(node, 1); 03362 GWEN_Buffer_free(delimBuffer); 03363 return -1; 03364 } 03365 } 03366 else { 03367 DBG_ERROR(GWEN_LOGDOMAIN, "Terminating character missing"); 03368 GWEN_Buffer_free(delimBuffer); 03369 return -1; 03370 } 03371 } 03372 03373 GWEN_Buffer_free(delimBuffer); 03374 return 0; 03375 } 03376 03377 03378 03379 int GWEN_MsgEngine_ParseMessage(GWEN_MSGENGINE *e, 03380 GWEN_XMLNODE *group, 03381 GWEN_BUFFER *msgbuf, 03382 GWEN_DB_NODE *msgData, 03383 uint32_t flags){ 03384 03385 if (GWEN_MsgEngine__ReadGroup(e, 03386 msgbuf, 03387 group, 03388 0, 03389 msgData, 03390 e->delimiters, 03391 flags)) { 03392 DBG_INFO(GWEN_LOGDOMAIN, "Error reading group"); 03393 return -1; 03394 } 03395 03396 return 0; 03397 } 03398 03399 03400 03401 int GWEN_MsgEngine_SetValue(GWEN_MSGENGINE *e, 03402 const char *path, 03403 const char *value){ 03404 GWEN_DB_NODE *globalValues; 03405 03406 assert(e); 03407 globalValues=GWEN_MsgEngine__GetGlobalValues(e); 03408 assert(globalValues); 03409 return GWEN_DB_SetCharValue(globalValues, 03410 GWEN_DB_FLAGS_DEFAULT | 03411 GWEN_DB_FLAGS_OVERWRITE_VARS, 03412 path, value); 03413 } 03414 03415 03416 03417 int GWEN_MsgEngine_SetIntValue(GWEN_MSGENGINE *e, 03418 const char *path, 03419 int value){ 03420 GWEN_DB_NODE *globalValues; 03421 03422 assert(e); 03423 globalValues=GWEN_MsgEngine__GetGlobalValues(e); 03424 assert(globalValues); 03425 return GWEN_DB_SetIntValue(globalValues, 03426 GWEN_DB_FLAGS_DEFAULT | 03427 GWEN_DB_FLAGS_OVERWRITE_VARS, 03428 path, value); 03429 } 03430 03431 03432 03433 const char *GWEN_MsgEngine_GetValue(GWEN_MSGENGINE *e, 03434 const char *path, 03435 const char *defValue){ 03436 GWEN_DB_NODE *globalValues; 03437 03438 assert(e); 03439 globalValues=GWEN_MsgEngine__GetGlobalValues(e); 03440 assert(globalValues); 03441 return GWEN_DB_GetCharValue(globalValues, 03442 path, 0, defValue); 03443 } 03444 03445 03446 03447 int GWEN_MsgEngine_GetIntValue(GWEN_MSGENGINE *e, 03448 const char *path, 03449 int defValue){ 03450 GWEN_DB_NODE *globalValues; 03451 03452 assert(e); 03453 globalValues=GWEN_MsgEngine__GetGlobalValues(e); 03454 assert(globalValues); 03455 return GWEN_DB_GetIntValue(globalValues, 03456 path, 0, defValue); 03457 } 03458 03459 03460 03461 /* --------------------------------------------------------------- FUNCTION */ 03462 int GWEN_MsgEngine_SkipSegment(GWEN_UNUSED GWEN_MSGENGINE *e, 03463 GWEN_BUFFER *msgbuf, 03464 unsigned char escapeChar, 03465 unsigned char delimiter) { 03466 int esc; 03467 03468 esc=0; 03469 while(GWEN_Buffer_GetBytesLeft(msgbuf)) { 03470 if (esc) { 03471 esc=0; 03472 } 03473 else { 03474 int i; 03475 unsigned char c; 03476 03477 i=GWEN_Buffer_ReadByte(msgbuf); 03478 if (i==-1) { 03479 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 03480 return 0; 03481 } 03482 c=(unsigned int)i; 03483 if (c==escapeChar) { /* escape */ 03484 esc=1; 03485 } 03486 else if (c=='@') { 03487 /* skip binary data */ 03488 char lbuffer[16]; 03489 char *p; 03490 int l; 03491 int nc; 03492 03493 p=lbuffer; 03494 while(1) { 03495 nc=GWEN_Buffer_ReadByte(msgbuf); 03496 if (nc==-1) { 03497 DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); 03498 return -1; 03499 } 03500 if (nc=='@') 03501 break; 03502 *p=nc; 03503 p++; 03504 } /* while */ 03505 *p=0; 03506 if (sscanf(lbuffer, "%d", &l)!=1) { 03507 DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format"); 03508 return -1; 03509 } 03510 if (GWEN_Buffer_GetUsedBytes(msgbuf)-GWEN_Buffer_GetPos(msgbuf) 03511 < (unsigned) l) { 03512 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)"); 03513 return -1; 03514 } 03515 GWEN_Buffer_IncrementPos(msgbuf, l); 03516 } 03517 else if (c==delimiter) {/* segment-end */ 03518 return 0; 03519 break; 03520 } 03521 } 03522 } /* while */ 03523 03524 DBG_ERROR(GWEN_LOGDOMAIN, "End of segment not found"); 03525 return -1; 03526 } 03527 03528 03529 03530 /* --------------------------------------------------------------- FUNCTION */ 03531 int GWEN_MsgEngine_ReadMessage(GWEN_MSGENGINE *e, 03532 const char *gtype, 03533 GWEN_BUFFER *mbuf, 03534 GWEN_DB_NODE *gr, 03535 uint32_t flags) { 03536 unsigned int segments; 03537 03538 segments=0; 03539 03540 while(GWEN_Buffer_GetBytesLeft(mbuf)) { 03541 GWEN_XMLNODE *node; 03542 unsigned int posBak; 03543 const char *p; 03544 GWEN_DB_NODE *tmpdb; 03545 int segVer; 03546 03547 /* find head segment description */ 03548 tmpdb=GWEN_DB_Group_new("tmpdb"); 03549 node=GWEN_MsgEngine_FindGroupByProperty(e, 03550 "id", 03551 0, 03552 "SegHead"); 03553 if (node==0) { 03554 DBG_ERROR(GWEN_LOGDOMAIN, "Segment description not found"); 03555 GWEN_DB_Group_free(tmpdb); 03556 return -1; 03557 } 03558 03559 /* parse head segment */ 03560 posBak=GWEN_Buffer_GetPos(mbuf); 03561 if (GWEN_MsgEngine_ParseMessage(e, 03562 node, 03563 mbuf, 03564 tmpdb, 03565 flags)) { 03566 DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment head"); 03567 GWEN_DB_Group_free(tmpdb); 03568 return -1; 03569 } 03570 03571 /* get segment code */ 03572 segVer=GWEN_DB_GetIntValue(tmpdb, 03573 "version", 03574 0, 03575 0); 03576 p=GWEN_DB_GetCharValue(tmpdb, 03577 "code", 03578 0, 03579 0); 03580 if (!p) { 03581 DBG_ERROR(GWEN_LOGDOMAIN, "No segment code for %s ? This seems to be a bad msg...", 03582 gtype); 03583 GWEN_Buffer_SetPos(mbuf, posBak); 03584 DBG_ERROR(GWEN_LOGDOMAIN, "Full message (pos=%04x)", posBak); 03585 GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf), 03586 GWEN_Buffer_GetUsedBytes(mbuf), 03587 1); 03588 GWEN_DB_Dump(tmpdb, 1); 03589 GWEN_DB_Group_free(tmpdb); 03590 return -1; 03591 } 03592 03593 /* try to find corresponding XML node */ 03594 node=GWEN_MsgEngine_FindNodeByProperty(e, 03595 gtype, 03596 "code", 03597 segVer, 03598 p); 03599 if (node==0) { 03600 unsigned int ustart; 03601 03602 ustart=GWEN_Buffer_GetPos(mbuf); 03603 ustart++; /* skip delimiter */ 03604 03605 /* node not found, skip it */ 03606 DBG_NOTICE(GWEN_LOGDOMAIN, 03607 "Unknown segment \"%s\" (Segnum=%d, version=%d, ref=%d)", 03608 p, 03609 GWEN_DB_GetIntValue(tmpdb, "seq", 0, -1), 03610 GWEN_DB_GetIntValue(tmpdb, "version", 0, -1), 03611 GWEN_DB_GetIntValue(tmpdb, "ref", 0, -1)); 03612 if (GWEN_MsgEngine_SkipSegment(e, mbuf, '?', '\'')) { 03613 DBG_ERROR(GWEN_LOGDOMAIN, "Error skipping segment \"%s\"", p); 03614 GWEN_DB_Group_free(tmpdb); 03615 return -1; 03616 } 03617 if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) { 03618 unsigned int usize; 03619 03620 usize=GWEN_Buffer_GetPos(mbuf)-ustart-1; 03621 #if 0 03622 GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+ustart, 03623 usize, 03624 stderr, 1); 03625 #endif 03626 if (GWEN_MsgEngine_AddTrustInfo(e, 03627 GWEN_Buffer_GetStart(mbuf)+ustart, 03628 usize, 03629 p, 03630 GWEN_MsgEngineTrustLevelHigh, 03631 ustart)) { 03632 DBG_INFO(GWEN_LOGDOMAIN, "called from here"); 03633 GWEN_DB_Group_free(tmpdb); 03634 return -1; 03635 } 03636 } /* if trustInfo handling wanted */ 03637 } 03638 else { 03639 /* ok, node available, get the corresponding description and parse 03640 * the segment */ 03641 const char *id; 03642 GWEN_DB_NODE *storegrp; 03643 unsigned int startPos; 03644 03645 /* restore start position, since the segment head is part of a full 03646 * description, so we need to restart reading from the very begin */ 03647 GWEN_Buffer_SetPos(mbuf, posBak); 03648 03649 /* create group in DB for this segment */ 03650 id=GWEN_XMLNode_GetProperty(node, "id", p); 03651 storegrp=GWEN_DB_GetGroup(gr, 03652 GWEN_PATH_FLAGS_CREATE_GROUP, 03653 id); 03654 assert(storegrp); 03655 03656 /* store the start position of this segment within the DB */ 03657 startPos=GWEN_Buffer_GetPos(mbuf); 03658 GWEN_DB_SetIntValue(storegrp, 03659 GWEN_DB_FLAGS_OVERWRITE_VARS, 03660 "segment/pos", 03661 startPos); 03662 03663 /* parse the segment */ 03664 if (GWEN_MsgEngine_ParseMessage(e, 03665 node, 03666 mbuf, 03667 storegrp, 03668 flags)) { 03669 DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment \"%s\" at %d (%x)", 03670 p, 03671 GWEN_Buffer_GetPos(mbuf)-startPos, 03672 GWEN_Buffer_GetPos(mbuf)-startPos); 03673 GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+startPos, 03674 GWEN_Buffer_GetUsedBytes(mbuf)-startPos, 03675 1); 03676 DBG_ERROR(GWEN_LOGDOMAIN, "Stored data so far:"); 03677 GWEN_DB_Dump(storegrp, 2); 03678 GWEN_DB_Group_free(tmpdb); 03679 return -1; 03680 } 03681 03682 /* store segment size within DB */ 03683 GWEN_DB_SetIntValue(storegrp, 03684 GWEN_DB_FLAGS_OVERWRITE_VARS, 03685 "segment/length", 03686 GWEN_Buffer_GetPos(mbuf)-startPos); 03687 segments++; 03688 } 03689 GWEN_DB_Group_free(tmpdb); 03690 } /* while */ 03691 03692 /* done */ 03693 if (segments) { 03694 DBG_DEBUG(GWEN_LOGDOMAIN, "Parsed %d segments", segments); 03695 return 0; 03696 } 03697 else { 03698 DBG_INFO(GWEN_LOGDOMAIN, "No segments parsed."); 03699 return 1; 03700 } 03701 } 03702 03703 03704 03705 03706 03707 03708 03709 03710 GWEN_MSGENGINE_TRUSTEDDATA* 03711 GWEN_MsgEngine_TrustedData_new(const char *data, 03712 unsigned int size, 03713 const char *description, 03714 GWEN_MSGENGINE_TRUSTLEVEL trustLevel){ 03715 GWEN_MSGENGINE_TRUSTEDDATA *td; 03716 03717 assert(data); 03718 assert(size); 03719 GWEN_NEW_OBJECT(GWEN_MSGENGINE_TRUSTEDDATA, td); 03720 td->data=(char*)malloc(size); 03721 assert(td->data); 03722 memmove(td->data, data, size); 03723 if (description) 03724 td->description=strdup(description); 03725 td->trustLevel=trustLevel; 03726 td->size=size; 03727 return td; 03728 } 03729 03730 03731 03732 void GWEN_MsgEngine_TrustedData_free(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03733 if (td) { 03734 free(td->data); 03735 free(td->description); 03736 free(td->replacement); 03737 GWEN_FREE_OBJECT(td); 03738 } 03739 } 03740 03741 03742 03743 GWEN_MSGENGINE_TRUSTEDDATA* 03744 GWEN_MsgEngine_TrustedData_GetNext(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03745 assert(td); 03746 return td->next; 03747 } 03748 03749 03750 03751 const char* 03752 GWEN_MsgEngine_TrustedData_GetData(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03753 assert(td); 03754 return td->data; 03755 } 03756 03757 03758 03759 unsigned int 03760 GWEN_MsgEngine_TrustedData_GetSize(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03761 assert(td); 03762 return td->size; 03763 } 03764 03765 03766 03767 const char* 03768 GWEN_MsgEngine_TrustedData_GetDescription(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03769 assert(td); 03770 return td->description; 03771 } 03772 03773 03774 03775 GWEN_MSGENGINE_TRUSTLEVEL 03776 GWEN_MsgEngine_TrustedData_GetTrustLevel(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03777 assert(td); 03778 return td->trustLevel; 03779 } 03780 03781 03782 03783 const char* 03784 GWEN_MsgEngine_TrustedData_GetReplacement(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03785 assert(td); 03786 return td->replacement; 03787 } 03788 03789 03790 03791 int GWEN_MsgEngine_TrustedData_AddPos(GWEN_MSGENGINE_TRUSTEDDATA *td, 03792 unsigned int pos){ 03793 assert(td); 03794 if (td->posCount>=GWEN_MSGENGINE_TRUSTEDDATA_MAXPOS) 03795 return -1; 03796 td->positions[td->posCount++]=pos; 03797 return 0; 03798 } 03799 03800 03801 03802 int GWEN_MsgEngine_TrustedData_GetFirstPos(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03803 assert(td); 03804 td->posPointer=0; 03805 return GWEN_MsgEngine_TrustedData_GetNextPos(td); 03806 } 03807 03808 03809 03810 int GWEN_MsgEngine_TrustedData_GetNextPos(GWEN_MSGENGINE_TRUSTEDDATA *td){ 03811 assert(td); 03812 if (td->posPointer>=td->posCount) 03813 return -1; 03814 return td->positions[td->posPointer++]; 03815 } 03816 03817 03818 03819 int 03820 GWEN_MsgEngine_TrustedData_CreateReplacements(GWEN_MSGENGINE_TRUSTEDDATA 03821 *td){ 03822 unsigned int nextNr; 03823 GWEN_MSGENGINE_TRUSTEDDATA *ntd; 03824 unsigned int count; 03825 03826 assert(td); 03827 count=0; 03828 ntd=td; 03829 while(ntd) { 03830 count++; 03831 ntd=ntd->next; 03832 } 03833 03834 if (count<0x10) 03835 nextNr=0x01; 03836 else 03837 nextNr=0x11; 03838 03839 ntd=td; 03840 while(ntd) { 03841 unsigned int i; 03842 char numbuffer[32]; 03843 char *rp; 03844 GWEN_MSGENGINE_TRUSTEDDATA *std; 03845 int match; 03846 03847 /* check whether the same data already exists */ 03848 std=td; 03849 match=0; 03850 while(std && std!=ntd) { 03851 03852 match=1; 03853 if (std->size==ntd->size) { 03854 for (i=0; i<td->size; i++) { 03855 if (std->data[i]!=ntd->data[i]) { 03856 match=0; 03857 break; 03858 } 03859 } /* for */ 03860 } 03861 else 03862 match=0; 03863 03864 if (match) 03865 break; 03866 std=std->next; 03867 } /* while */ 03868 03869 if (match) { 03870 /* copy the found match */ 03871 rp=strdup(std->replacement); 03872 } 03873 else { 03874 /* this is a new one */ 03875 rp=(char*)malloc(ntd->size+1); 03876 assert(rp); 03877 03878 if (ntd->size==1) { 03879 if (count>=0x10) 03880 nextNr+=0x10; 03881 } 03882 sprintf(numbuffer, "%02X", nextNr++); 03883 for (i=0; i<ntd->size; i++) { 03884 if (count<0x10) 03885 rp[i]=numbuffer[1]; 03886 else 03887 rp[i]=numbuffer[1-(i&1)]; 03888 } /* for */ 03889 rp[i]=0; 03890 } 03891 /* 03892 DBG_DEBUG(GWEN_LOGDOMAIN, "Replacement: \"%s\" for \"%s\" (%d)", rp, 03893 ntd->description, 03894 ntd->size); 03895 */ 03896 free(ntd->replacement); 03897 ntd->replacement=rp; 03898 03899 ntd=ntd->next; 03900 } /* while */ 03901 return 0; 03902 } 03903 03904 03905 03906 GWEN_MSGENGINE_TRUSTEDDATA *GWEN_MsgEngine_TakeTrustInfo(GWEN_MSGENGINE *e){ 03907 GWEN_MSGENGINE_TRUSTEDDATA *td; 03908 03909 assert(e); 03910 td=e->trustInfos; 03911 e->trustInfos=0; 03912 return td; 03913 } 03914 03915 03916 03917 03918 int GWEN_MsgEngine_AddTrustInfo(GWEN_MSGENGINE *e, 03919 const char *data, 03920 unsigned int size, 03921 const char *description, 03922 GWEN_MSGENGINE_TRUSTLEVEL trustLevel, 03923 unsigned int pos) { 03924 GWEN_MSGENGINE_TRUSTEDDATA *td; 03925 int match; 03926 03927 assert(e); 03928 assert(data); 03929 assert(size); 03930 03931 if (!description) 03932 description=""; 03933 03934 td=e->trustInfos; 03935 while(td) { 03936 unsigned int i; 03937 03938 /* compare data */ 03939 if (td->size==size && 03940 *description && 03941 *(td->description) && 03942 trustLevel==td->trustLevel && 03943 strcasecmp(description, td->description)==0) { 03944 match=1; 03945 for (i=0; i<td->size; i++) { 03946 if (td->data[i]!=data[i]) { 03947 match=0; 03948 break; 03949 } 03950 } /* for */ 03951 } 03952 else 03953 match=0; 03954 03955 if (match) 03956 break; 03957 td=td->next; 03958 } /* while */ 03959 03960 if (!td) { 03961 DBG_INFO(GWEN_LOGDOMAIN, "Creating new trustInfo for \"%s\" (%d)", 03962 description, size); 03963 td=GWEN_MsgEngine_TrustedData_new(data, 03964 size, 03965 description, 03966 trustLevel); 03967 GWEN_LIST_ADD(GWEN_MSGENGINE_TRUSTEDDATA, td, &(e->trustInfos)); 03968 } 03969 else { 03970 DBG_INFO(GWEN_LOGDOMAIN, "Reusing trustInfo for \"%s\" (%d)", 03971 description, size); 03972 } 03973 GWEN_MsgEngine_TrustedData_AddPos(td, pos); 03974 return 0; 03975 } 03976 03977 03978