00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00024 #include <stdio.h>
00025 #include <unistd.h>
00026
00027 #define LIBXML_SCHEMAS_ENABLED
00028 #include <libxml/xmlschemas.h>
00029
00030 #include "ermanifest.h"
00031
00032
00033 #define DEFAULT_ENCODING "utf-8"
00034 #define INT_MAX_BUF 15
00035 #define BOOL_MAX_BUF 6
00036
00037 #define _DEBUG 0
00038
00039 #if (_DEBUG)
00040 #define TRACE(x, args...) fprintf(stderr, "(ERM_TRACE)" __FILE__ ":%d,%s() " x "\n", __LINE__, __func__ , ##args)
00041 #else
00042 #define TRACE(x...) do {} while(0)
00043 #endif
00044
00045
00056 xmlChar *ConvertInput(const char *in, const char *encoding)
00057 {
00058 xmlChar *out;
00059 int ret;
00060 int size;
00061 int out_size;
00062 int temp;
00063 xmlCharEncodingHandlerPtr handler;
00064
00065 if (in == 0)
00066 return 0;
00067
00068 handler = xmlFindCharEncodingHandler(encoding);
00069
00070 if (!handler)
00071 {
00072 TRACE("ConvertInput: no encoding handler found for '%s'\n", encoding ? encoding : "");
00073 return 0;
00074 }
00075
00076 size = (int)strlen(in) + 1;
00077 out_size = size * 2 - 1;
00078 out = (unsigned char *)xmlMalloc((size_t) out_size);
00079
00080 if (out != 0)
00081 {
00082 temp = size - 1;
00083 ret = handler->input(out, &out_size, (const xmlChar *)in, &temp);
00084 if ((ret < 0) || (temp - size + 1))
00085 {
00086 if (ret < 0)
00087 {
00088 TRACE("ConvertInput: conversion wasn't successful.\n");
00089 }
00090 else
00091 {
00092 TRACE("ConvertInput: conversion wasn't successful. converted: %i octets.\n", temp);
00093 }
00094
00095 xmlFree(out);
00096 out = 0;
00097 }
00098 else
00099 {
00100 out = (unsigned char *)xmlRealloc(out, out_size + 1);
00101 out[out_size] = 0;
00102 }
00103 }
00104 else
00105 {
00106 TRACE("ConvertInput: no mem\n");
00107 }
00108
00109 return out;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 xmlXPathObjectPtr LocateTo(const char *express, const erManifest *pCtx)
00121 {
00122 xmlXPathObjectPtr xpathObj;
00123
00124 xpathObj = xmlXPathEvalExpression(BAD_CAST express, pCtx->pPathCtx);
00125 if (xpathObj == NULL)
00126 {
00127 TRACE("LocateTo failed! Express %s\n", express);
00128 return NULL;
00129 }
00130 if (xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr <= 0)
00131 {
00132 TRACE("LocateTo failed! no or empty xmlNodeSet");
00133 xmlXPathFreeObject(xpathObj);
00134 return NULL;
00135 }
00136
00137 return xpathObj;
00138 }
00139
00140 xmlNodePtr ermXmlGetChildNode(xmlNodePtr parent, const char* childName)
00141 {
00142 xmlNodePtr cur = NULL;
00143
00144
00145
00146
00147 if (parent && childName && childName[0] != '\0')
00148 {
00149 cur = parent->children;
00150 while (cur != NULL)
00151 {
00152 if ( xmlStrcmp(cur->name, (const xmlChar*)childName) == 0 )
00153 {
00154
00155 break;
00156 }
00157 cur = cur->next;
00158 }
00159 }
00160 return cur;
00161 }
00162
00163 xmlNodeSetPtr ermXmlGetChildNodeSet(xmlNodePtr parent, const char* childName)
00164 {
00165 int i;
00166
00167 xmlNodeSetPtr nodeSet = NULL;
00168 xmlNodePtr cur = NULL;
00169
00170
00171
00172
00173
00174 nodeSet = xmlMalloc( sizeof(xmlNodeSet) );
00175 if (nodeSet == NULL) { return NULL; }
00176 nodeSet->nodeNr = 0;
00177 nodeSet->nodeMax = 10;
00178 nodeSet->nodeTab = xmlMalloc(10 * sizeof(xmlNode));
00179 if (nodeSet->nodeTab == NULL) { return NULL; }
00180
00181 if (parent && childName && childName[0] != '\0')
00182 {
00183 cur = parent->children;
00184 while (cur != NULL)
00185 {
00186 if ( xmlStrcmp(cur->name, (const xmlChar*)childName) == 0 )
00187 {
00188
00189
00190
00191 if (nodeSet->nodeNr >= nodeSet->nodeMax)
00192 {
00193 i = 2 * nodeSet->nodeMax;
00194 nodeSet->nodeMax = i;
00195 nodeSet->nodeTab = xmlRealloc(nodeSet->nodeTab, i * sizeof(xmlNode));
00196 if (nodeSet->nodeTab == NULL) { return NULL; }
00197 }
00198
00199
00200 nodeSet->nodeTab[ nodeSet->nodeNr ] = cur;
00201 nodeSet->nodeNr++;
00202 }
00203 cur = cur->next;
00204 }
00205 }
00206 return nodeSet;
00207 }
00208
00209 xmlNodePtr ermXmlGetChildNodeWithAttr(xmlNodePtr parent, const char* nodeName, const char* attrName, const char* attrValue)
00210 {
00211 xmlNodePtr cur = NULL;
00212 xmlNodePtr ret = NULL;
00213 xmlChar *attr;
00214
00215
00216
00217
00218 if (parent && nodeName && nodeName[0] != '\0')
00219 {
00220 cur = parent->children;
00221 while (cur != NULL && ret == NULL)
00222 {
00223 if (xmlStrcmp(cur->name, (const xmlChar *)nodeName) == 0)
00224 {
00225 attr = xmlGetProp(cur, attrName);
00226 if (attr)
00227 {
00228 if (attrValue == NULL
00229 || xmlStrcmp(attr, (const xmlChar *)attrValue) == 0)
00230 {
00231
00232 ret = cur;
00233 }
00234 xmlFree(attr);
00235 }
00236 }
00237 cur = cur->next;
00238 }
00239 }
00240 return ret;
00241 }
00242
00243 xmlNodePtr ermXmlGetChildNodeWithoutAttr(xmlNodePtr parent, const char* nodeName, const char* attrName)
00244 {
00245 xmlNodePtr cur = NULL;
00246 xmlNodePtr ret = NULL;
00247 xmlChar* attr;
00248
00249
00250
00251
00252 if (parent && nodeName && nodeName[0] != '\0')
00253 {
00254 cur = parent->children;
00255 while (cur != NULL && ret == NULL)
00256 {
00257 if ( xmlStrcmp(cur->name, (const xmlChar*)nodeName) == 0 )
00258 {
00259 attr = xmlGetProp(cur, attrName);
00260 if (attr == NULL)
00261 {
00262
00263 ret = cur;
00264 }
00265 else
00266 {
00267 xmlFree(attr);
00268 }
00269 }
00270 cur = cur->next;
00271 }
00272 }
00273 return ret;
00274 }
00275
00276 int ermXmlExist(const erManifest *pCtx, const char *express)
00277 {
00278 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00279 if (NULL == xpathObj)
00280 return RET_ERR;
00281
00282 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00283
00284 if (nodes && nodes->nodeNr > 0 && nodes->nodeTab[0])
00285 {
00286 xmlXPathFreeObject(xpathObj);
00287 return RET_OK;
00288 }
00289 xmlXPathFreeObject(xpathObj);
00290 return RET_ERR;
00291 }
00292
00293
00294
00295 int ermXmlOpenFile(const char *szFileName, erManifest *pCtx)
00296 {
00297 pCtx->pDoc = NULL;
00298 pCtx->pPathCtx = NULL;
00299 pCtx->szFileName = NULL;
00300
00301 if (NULL == szFileName)
00302 {
00303 TRACE("szFileName pointer is empty!\n");
00304 return RET_ERR;
00305 }
00306
00307 if (0 >= strlen(szFileName))
00308 {
00309 TRACE("length of szFileName is zero!\n");
00310 return RET_ERR;
00311 }
00312
00313 pCtx->pDoc = xmlParseFile(szFileName);
00314 if (NULL == pCtx->pDoc)
00315 return RET_ERR;
00316
00317 pCtx->pPathCtx = xmlXPathNewContext(pCtx->pDoc);
00318 if (NULL == pCtx->pPathCtx)
00319 {
00320 xmlFreeDoc(pCtx->pDoc);
00321 pCtx->pDoc = NULL;
00322 return RET_ERR;
00323 }
00324
00325 pCtx->szFileName = strdup(szFileName);
00326 return RET_OK;
00327 }
00328
00329
00330 int ermXmlOpenManifest(const char *szContainerName, erManifest *pCtx)
00331 {
00332 int ret;
00333 char *xpath;
00334 char buf[100];
00335
00336 if (NULL == szContainerName)
00337 {
00338 TRACE("szContainerName pointer is empty!\n");
00339 return RET_ERR;
00340 }
00341
00342 int n = strlen(szContainerName);
00343 if (0 >= n)
00344 {
00345 TRACE("length of szFileContainer is zero!\n");
00346 return RET_ERR;
00347 }
00348
00349 char *szFileName = alloca(n + 1 + strlen(MANIFEST_FILENAME) + 1);
00350 if (NULL == szFileName)
00351 {
00352 TRACE("alloca failedi!\n");
00353 return RET_ERR;
00354 }
00355 sprintf(szFileName, "%s/" MANIFEST_FILENAME, szContainerName);
00356
00357 ret = ermXmlOpenFile(szFileName, pCtx);
00358 if (ret == RET_OK)
00359 {
00360
00361
00362
00363 xpath = "/package/metadata/dc-metadata/Date";
00364 if ( ermXmlGetString(pCtx, xpath, buf, sizeof(buf)) == RET_OK
00365 && buf[0] == '\0' )
00366 {
00367 ermXmlRemoveNode(pCtx, xpath);
00368 }
00369
00370
00371 xpath = "/package/metadata/dc-metadata/Identifier";
00372 if ( ermXmlGetString(pCtx, xpath, buf, sizeof(buf)) == RET_OK
00373 && buf[0] == '\0' )
00374 {
00375 ermXmlRemoveNode(pCtx, xpath);
00376 }
00377
00378
00379 xpath = "/package/metadata/dc-metadata/Type";
00380 if ( ermXmlGetString(pCtx, xpath, buf, sizeof(buf)) == RET_OK
00381 && buf[0] == '\0' )
00382 {
00383 ermXmlRemoveNode(pCtx, xpath);
00384 }
00385
00386
00387 xpath = "/package/metadata/dc-metadata/Format";
00388 ermXmlRemoveNode(pCtx, xpath);
00389
00390
00391 xpath = "/package/metadata/dc-metadata/Language";
00392 ermXmlRemoveNode(pCtx, xpath);
00393 }
00394
00395 return ret;
00396 }
00397
00398
00399 int ermXmlValidateManifest(erManifest *pCtx)
00400 {
00401 int retVal = RET_ERR;
00402
00403 xmlSchemaParserCtxtPtr parserCtxtPtr = NULL;
00404 xmlSchemaValidCtxtPtr validCtxPtr = NULL;
00405 xmlSchemaPtr schema = NULL;
00406
00407 int result;
00408
00409 if (NULL == pCtx->pDoc)
00410 {
00411 TRACE("pCtx->pDoc pointer is empty!\n");
00412 return retVal;
00413 }
00414
00415
00416 parserCtxtPtr = xmlSchemaNewParserCtxt(MANIFEST_SCHEMA_FILE);
00417 if (parserCtxtPtr)
00418 {
00419 schema = xmlSchemaParse(parserCtxtPtr);
00420 if (schema)
00421 {
00422 validCtxPtr = xmlSchemaNewValidCtxt(schema);
00423 if (validCtxPtr)
00424 {
00425 if (xmlSchemaIsValid(validCtxPtr))
00426 {
00427
00428 result = xmlSchemaValidateDoc(validCtxPtr, pCtx->pDoc);
00429 TRACE("ValidateDoc returns [%d] (0 == OK)\n", result);
00430 if (result == 0)
00431 {
00432 retVal = RET_OK;
00433 }
00434 }
00435 xmlSchemaFreeValidCtxt(validCtxPtr);
00436 }
00437 xmlSchemaFree(schema);
00438 }
00439 }
00440 xmlSchemaFreeParserCtxt(parserCtxtPtr);
00441
00442 return retVal;
00443 }
00444
00445
00446
00447 int ermXmlCreateHandleOnly(erManifest *pCtx)
00448 {
00449 pCtx->pDoc = NULL;
00450 pCtx->pPathCtx = NULL;
00451 pCtx->szFileName = NULL;
00452
00453 pCtx->pDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
00454 if (NULL == pCtx->pDoc)
00455 return RET_ERR;
00456
00457 pCtx->pPathCtx = xmlXPathNewContext(pCtx->pDoc);
00458 if (NULL == pCtx->pPathCtx)
00459 {
00460 xmlFreeDoc(pCtx->pDoc);
00461 return RET_ERR;
00462 }
00463
00464 return RET_OK;
00465 }
00466
00467
00468 int ermXmlCreateFile(const char *szFileName, erManifest *pCtx)
00469 {
00470 if (NULL == szFileName)
00471 {
00472 TRACE("szFileName pointer is empty!\n");
00473 return RET_ERR;
00474 }
00475
00476 if (0 >= strlen(szFileName))
00477 {
00478 TRACE("length of szFileName is zero!\n");
00479 return RET_ERR;
00480 }
00481
00482 int iRet = ermXmlCreateHandleOnly(pCtx);
00483 if (RET_OK == iRet)
00484 {
00485 iRet = ermXmlSaveAs(pCtx, szFileName);
00486 }
00487 if (RET_OK != iRet)
00488 {
00489 ermXmlClose(pCtx);
00490 }
00491 return iRet;
00492 }
00493
00494
00495 int ermXmlCreateManifest(const char *szContainerName, erManifest *pCtx)
00496 {
00497 if (NULL == szContainerName)
00498 {
00499 TRACE("szContainerName pointer is empty!\n");
00500 return RET_ERR;
00501 }
00502
00503 int n = strlen(szContainerName);
00504 if (0 >= n)
00505 {
00506 TRACE("length of szFileContainer is zero!\n");
00507 return RET_ERR;
00508 }
00509
00510 char *szFileName = alloca(n + 1 + strlen(MANIFEST_FILENAME) + 1);
00511 if (NULL == szFileName)
00512 {
00513 TRACE("alloca failed!\n");
00514 return RET_ERR;
00515 }
00516 sprintf(szFileName, "%s/" MANIFEST_FILENAME, szContainerName);
00517
00518 return ermXmlCreateFile(szFileName, pCtx);
00519 }
00520
00521 int ermXmlParseBuffer(const char* xmlString, const char* szFileName, erManifest *pCtx)
00522 {
00523 pCtx->pDoc = NULL;
00524 pCtx->pPathCtx = NULL;
00525 pCtx->szFileName = NULL;
00526
00527 if (NULL == xmlString)
00528 {
00529 TRACE("xmlString pointer is empty!\n");
00530 return RET_ERR;
00531 }
00532
00533 if (NULL == szFileName)
00534 {
00535 TRACE("szFileName pointer is empty!\n");
00536 return RET_ERR;
00537 }
00538
00539 if (0 >= strlen(szFileName))
00540 {
00541 TRACE("length of szFileName is zero!\n");
00542 return RET_ERR;
00543 }
00544
00545 pCtx->pDoc = xmlParseMemory(xmlString, strlen(xmlString));
00546 if (NULL == pCtx->pDoc)
00547 {
00548 TRACE("xmlParseMemory failed!\n");
00549 return RET_ERR;
00550 }
00551
00552 pCtx->pPathCtx = xmlXPathNewContext(pCtx->pDoc);
00553 if (NULL == pCtx->pPathCtx)
00554 {
00555 TRACE("xmlXPathNewContext failed!\n");
00556 xmlFreeDoc(pCtx->pDoc);
00557 pCtx->pDoc = NULL;
00558 return RET_ERR;
00559 }
00560
00561 pCtx->szFileName = strdup(szFileName);
00562 return RET_OK;
00563 }
00564
00565
00566 const char *ermXmlGetFileName(const erManifest *pCtx)
00567 {
00568 return pCtx->szFileName;
00569 }
00570
00571 int ermXmlGetNodeNr(const erManifest *pCtx, const char *express, int *number)
00572 {
00573 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00574 if (NULL == xpathObj)
00575 return RET_ERR;
00576
00577
00578 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00579 if (nodes)
00580 {
00581 *number = nodes->nodeNr;
00582 xmlXPathFreeObject(xpathObj);
00583 return RET_OK;
00584 }
00585 xmlXPathFreeObject(xpathObj);
00586 return RET_ERR;
00587 }
00588
00589 int ermXmlGetString(const erManifest *pCtx, const char *express, char *pRet, const int length)
00590 {
00591 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00592 if (NULL == xpathObj)
00593 return RET_ERR;
00594
00595
00596 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00597
00598 if (nodes && nodes->nodeNr > 0 && nodes->nodeTab[0] && nodes->nodeTab[0]->children)
00599 {
00600
00601 xmlChar *content = xmlNodeGetContent(nodes->nodeTab[0]->children);
00602
00603 strncpy(pRet, content, length - 1);
00604 pRet[length - 1] = '\0';
00605 xmlXPathFreeObject(xpathObj);
00606
00607 xmlFree(content);
00608 return RET_OK;
00609 }
00610 else if (nodes && nodes->nodeNr > 0 && nodes->nodeTab[0])
00611 {
00612 pRet[0] = '\0';
00613 xmlXPathFreeObject(xpathObj);
00614 return RET_OK;
00615 }
00616
00617 TRACE("No nodes found!");
00618 xmlXPathFreeObject(xpathObj);
00619 return RET_ERR;
00620 }
00621
00622 const char *ermXmlGetStringBuffer(const erManifest *pCtx, const char *express, int *length)
00623 {
00624 *length = 0;
00625 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00626 if (NULL == xpathObj)
00627 return NULL;
00628
00629
00630 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00631
00632 if (nodes && nodes->nodeNr > 0 && nodes->nodeTab[0] && nodes->nodeTab[0]->children)
00633 {
00634 xmlChar *content = xmlNodeGetContent(&nodes->nodeTab[0]->children[0]);
00635 *length = xmlStrlen(content);
00636 xmlXPathFreeObject(xpathObj);
00637 return (const char *)content;
00638 }
00639
00640 TRACE("No nodes found!\n");
00641 xmlXPathFreeObject(xpathObj);
00642 return NULL;
00643 }
00644
00645 void ermXmlFreeStringBuffer(const char *ptr)
00646 {
00647 if (NULL == ptr)
00648 {
00649 TRACE("Attempt to free null pointer!\n");
00650 return;
00651 }
00652 xmlFree((xmlChar *) ptr);
00653 }
00654
00655 int ermXmlGetInt(const erManifest *pCtx, const char *express, int *pRet)
00656 {
00657
00658 char tmp[INT_MAX_BUF] = { 0 };
00659
00660 if (RET_ERR == ermXmlGetString(pCtx, express, tmp, INT_MAX_BUF))
00661 return RET_ERR;
00662
00663 if (1 == sscanf(tmp, "%d", pRet))
00664 return RET_OK;
00665 return RET_ERR;
00666 }
00667
00668 int ermXmlGetBoolean(const erManifest *pCtx, const char *express, int *pRet)
00669 {
00670
00671 char tmp[BOOL_MAX_BUF] = { 0 };
00672
00673 if (RET_ERR == ermXmlGetString(pCtx, express, tmp, BOOL_MAX_BUF))
00674 return RET_ERR;
00675
00676 if (0 == strcmp(tmp, "false"))
00677 {
00678 *pRet = 0;
00679 return RET_OK;
00680 }
00681 if (0 == strcmp(tmp, "true"))
00682 {
00683 *pRet = 1;
00684 return RET_OK;
00685 }
00686 return RET_ERR;
00687 }
00688
00689 int ermXmlGetAttributeString(const erManifest *pCtx, const char *express,
00690 const char *attrName, char *pRet, const int length)
00691 {
00692 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00693 if (NULL == xpathObj)
00694 return RET_ERR;
00695
00696
00697 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00698
00699 if (nodes && nodes->nodeNr && nodes->nodeTab[0])
00700 {
00701 xmlChar *pSrc = xmlGetProp(nodes->nodeTab[0], attrName);
00702 strncpy(pRet, pSrc, length - 1);
00703 pRet[length - 1] = '\0';
00704 xmlXPathFreeObject(xpathObj);
00705
00706
00707 xmlFree(pSrc);
00708 return RET_OK;
00709 }
00710
00711 xmlXPathFreeObject(xpathObj);
00712 return RET_ERR;
00713 }
00714
00715 const char *ermXmlGetAttributeStringBuffer(const erManifest *pCtx, const char *express, const char *attrName, int *length)
00716 {
00717 *length = 0;
00718 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00719 if (NULL == xpathObj)
00720 return NULL;
00721
00722
00723 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00724 if (nodes && nodes->nodeNr && nodes->nodeTab[0])
00725 {
00726 xmlChar *pSrc = xmlGetProp(nodes->nodeTab[0], attrName);
00727 xmlXPathFreeObject(xpathObj);
00728 *length = xmlStrlen(pSrc);
00729 return pSrc;
00730 }
00731
00732 xmlXPathFreeObject(xpathObj);
00733 return NULL;
00734 }
00735
00736 int ermXmlGetAttributeInt(const erManifest *pCtx, const char *express, const char *attrName, int *pRet)
00737 {
00738 char tmp[INT_MAX_BUF] = { 0 };
00739 if (RET_OK != ermXmlGetAttributeString(pCtx, express, attrName, tmp, INT_MAX_BUF))
00740 return RET_ERR;
00741 if (1 == sscanf(tmp, "%d", pRet))
00742 return RET_OK;
00743 return RET_ERR;
00744 }
00745
00746
00747 int ermXmlSetString(erManifest *pCtx, const char *express, const char *pData)
00748 {
00749 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00750 if (NULL == xpathObj)
00751 return RET_ERR;
00752
00753 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00754
00755
00756 xmlChar *xmlString = xmlEncodeSpecialChars(pCtx->pDoc, (xmlChar *) pData);
00757
00758 if (nodes && nodes->nodeTab[0])
00759 {
00760 xmlNodeSetContent(nodes->nodeTab[0], xmlString);
00761 xmlFree(xmlString);
00762
00763
00764 if (nodes->nodeTab[0]->type != XML_NAMESPACE_DECL)
00765 nodes->nodeTab[0] = NULL;
00766 xmlXPathFreeObject(xpathObj);
00767 return RET_OK;
00768 }
00769 xmlXPathFreeObject(xpathObj);
00770 return RET_ERR;
00771 }
00772
00773 int ermXmlSetInt(erManifest *pCtx, const char *express, const int data)
00774 {
00775 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00776 if (NULL == xpathObj)
00777 return RET_ERR;
00778
00779 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00780
00781 if (nodes && nodes->nodeTab[0])
00782 {
00783 char tmp[INT_MAX_BUF] = { 0 };
00784 snprintf(tmp, INT_MAX_BUF, "%d", data);
00785 xmlNodeSetContent(nodes->nodeTab[0], tmp);
00786
00787 if (nodes->nodeTab[0]->type != XML_NAMESPACE_DECL)
00788 nodes->nodeTab[0] = NULL;
00789 xmlXPathFreeObject(xpathObj);
00790 return RET_OK;
00791 }
00792 xmlXPathFreeObject(xpathObj);
00793 return RET_ERR;
00794 }
00795
00796 int ermXmlSetBoolean(erManifest *pCtx, const char *express, const int data)
00797 {
00798 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00799 if (NULL == xpathObj)
00800 return RET_ERR;
00801 if (0 != data && 1 != data)
00802 return RET_ERR;
00803
00804 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00805
00806 if (nodes && nodes->nodeTab[0])
00807 {
00808 const char *tmp = data ? "true" : "false";
00809 xmlNodeSetContent(nodes->nodeTab[0], tmp);
00810
00811 if (nodes->nodeTab[0]->type != XML_NAMESPACE_DECL)
00812 nodes->nodeTab[0] = NULL;
00813 xmlXPathFreeObject(xpathObj);
00814 return RET_OK;
00815 }
00816 xmlXPathFreeObject(xpathObj);
00817 return RET_ERR;
00818 }
00819
00820
00821
00822 int ermXmlSetAttributeString(const erManifest *pCtx, const char *express,
00823 const char *attrName, const char *pSrc, const int length)
00824 {
00825 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00826 if (NULL == xpathObj)
00827 return RET_ERR;
00828
00829 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00830
00831 if (nodes && nodes->nodeNr && nodes->nodeTab[0])
00832 {
00833 xmlSetProp(nodes->nodeTab[0], attrName, BAD_CAST pSrc);
00834 xmlXPathFreeObject(xpathObj);
00835 return RET_OK;
00836 }
00837 xmlXPathFreeObject(xpathObj);
00838 return RET_ERR;
00839 }
00840
00841
00842 int ermXmlSetAttributeInt(erManifest *pCtx, const char *express, const char *attrName, const int data)
00843 {
00844 char tmp[INT_MAX_BUF] = { 0 };
00845 snprintf(tmp, INT_MAX_BUF, "%d", data);
00846 return ermXmlSetAttributeString(pCtx, express, attrName, tmp, INT_MAX_BUF);
00847 }
00848
00849
00850 int ermXmlNewString(const erManifest *pCtx, const char *parentExpress, const char *name, const char *content)
00851 {
00852 xmlXPathObjectPtr xpathObj = LocateTo(parentExpress, pCtx);
00853 if (NULL == xpathObj)
00854 return RET_ERR;
00855
00856 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00857
00858
00859 xmlChar *xmlString = xmlEncodeSpecialChars(pCtx->pDoc, (xmlChar *) content);
00860
00861 if (nodes && nodes->nodeTab[0])
00862 {
00863 xmlNewChild(nodes->nodeTab[0],
00864 NULL, BAD_CAST name,
00865 xmlString);
00866 xmlFree(xmlString);
00867 xmlXPathFreeObject(xpathObj);
00868 return RET_OK;
00869 }
00870 xmlXPathFreeObject(xpathObj);
00871 return RET_ERR;
00872 }
00873
00874 int ermXmlNewInt(erManifest *pCtx, const char *parentExpress, const char *name, const int content)
00875 {
00876 char tmp[INT_MAX_BUF] = { 0 };
00877 snprintf(tmp, INT_MAX_BUF, "%d", content);
00878 return ermXmlNewString(pCtx, parentExpress, name, tmp);
00879 }
00880
00881 int ermXmlNewBoolean(erManifest *pCtx, const char *parentExpress, const char *name, const int content)
00882 {
00883 if (0 != content && 1 != content)
00884 return RET_ERR;
00885
00886 const char *tmp = content ? "true" : "false";
00887 return ermXmlNewString(pCtx, parentExpress, name, tmp);
00888 }
00889
00890
00891 int ermXmlRemoveNode(erManifest *pCtx, const char *express)
00892 {
00893 xmlXPathObjectPtr xpathObj = LocateTo(express, pCtx);
00894 if (NULL == xpathObj)
00895 return RET_ERR;
00896
00897 xmlNodeSetPtr nodes = xpathObj->nodesetval;
00898
00899 if (nodes && nodes->nodeTab[0])
00900 {
00901 xmlUnlinkNode(nodes->nodeTab[0]);
00902 xmlFreeNode(nodes->nodeTab[0]);
00903 xmlXPathFreeObject(xpathObj);
00904 return RET_OK;
00905 }
00906 xmlXPathFreeObject(xpathObj);
00907 return RET_ERR;
00908 }
00909
00910
00911
00912 int ermXmlSave(erManifest *pCtx)
00913 {
00914 if (NULL == pCtx->szFileName)
00915 {
00916 TRACE("pCtx->szFileName pointer is empty!\n");
00917 return RET_ERR;
00918 }
00919 if (0 >= strlen(pCtx->szFileName))
00920 {
00921 TRACE("length of pCtx->szFileName is zero!\n");
00922 return RET_ERR;
00923 }
00924
00925 int n = xmlSaveFileEnc(pCtx->szFileName, pCtx->pDoc, DEFAULT_ENCODING);
00926 sync();
00927 return (n >= 0) ? RET_OK : RET_ERR;
00928 }
00929
00930
00931 int ermXmlSaveAs(erManifest *pCtx, const char *szFileName)
00932 {
00933 if (NULL == szFileName)
00934 {
00935 TRACE("szFileName pointer is empty!\n");
00936 return RET_ERR;
00937 }
00938
00939 if (0 >= strlen(szFileName))
00940 {
00941 TRACE("length of szFileName is zero!\n");
00942 return RET_ERR;
00943 }
00944
00945 if (pCtx->szFileName)
00946 {
00947 free(pCtx->szFileName);
00948 }
00949 pCtx->szFileName = strdup(szFileName);
00950
00951 int iRet = ermXmlSave(pCtx);
00952 return iRet;
00953 }
00954
00955
00956 int ermXmlSaveAndClose(erManifest *pCtx)
00957 {
00958 int iRet = ermXmlSave(pCtx);
00959 ermXmlClose(pCtx);
00960 return iRet;
00961 }
00962
00963
00964 int ermXmlClose(erManifest *pCtx)
00965 {
00966 if (pCtx->pDoc)
00967 {
00968 xmlFreeDoc(pCtx->pDoc);
00969 pCtx->pDoc = NULL;
00970 }
00971 if (pCtx->pPathCtx)
00972 {
00973 xmlXPathFreeContext(pCtx->pPathCtx);
00974 pCtx->pPathCtx = NULL;
00975 }
00976 if (pCtx->szFileName)
00977 {
00978 free(pCtx->szFileName);
00979 pCtx->szFileName = NULL;
00980 }
00981 return RET_OK;
00982 }
00983
00984
00985 typedef struct
00986 {
00987 char *name;
00988 char *value;
00989 } pairs_t;
00990
00991 typedef enum
00992 {
00993 with_none_t,
00994 with_index_t,
00995 with_attr_t,
00996 with_child_t
00997 } with_type_t;
00998
00999 typedef struct
01000 {
01001 char *xpath;
01002 char *name;
01003
01004 with_type_t type;
01005 union
01006 {
01007 pairs_t pairs;
01008 int index;
01009 } u;
01010 } a_step_t;
01011
01012 static a_step_t *newAStep(void)
01013 {
01014 a_step_t *theStep = (a_step_t *) malloc(sizeof(a_step_t));
01015 if (theStep)
01016 {
01017 memset(theStep, 0, sizeof(a_step_t));
01018 }
01019 return theStep;
01020 }
01021
01022 static void freeAStep(a_step_t * theStep)
01023 {
01024 if (theStep)
01025 {
01026 if (theStep->xpath)
01027 {
01028 free(theStep->xpath);
01029 theStep->xpath = NULL;
01030 }
01031
01032 if (theStep->name)
01033 {
01034 free(theStep->name);
01035 theStep->name = NULL;
01036 }
01037
01038 if ((theStep->type == with_attr_t) || (theStep->type == with_child_t))
01039 {
01040 if (theStep->u.pairs.name)
01041 {
01042 free(theStep->u.pairs.name);
01043 theStep->u.pairs.name = NULL;
01044 }
01045
01046 if (theStep->u.pairs.value)
01047 {
01048 free(theStep->u.pairs.value);
01049 theStep->u.pairs.value = NULL;
01050 }
01051 }
01052
01053 free(theStep);
01054 }
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064 static void calcDelimiterPositions(char *curSlashPos, char *nextSlashPos,
01065 char **beginBracketPos, char **atPos, char **equalPos, char **endBracketPos)
01066 {
01067 char *cp = NULL;
01068
01069 cp = curSlashPos + 1;
01070 while (cp < nextSlashPos)
01071 {
01072 switch (*cp)
01073 {
01074 case '[':
01075 *beginBracketPos = cp;
01076 break;
01077 case ']':
01078 *endBracketPos = cp;
01079 break;
01080 case '@':
01081 *atPos = cp;
01082 break;
01083 case '=':
01084 *equalPos = cp;
01085 break;
01086 default:
01087 break;
01088 }
01089 cp++;
01090 }
01091 }
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 static void getNameAndValue(char *beginPos, char *equalPos, char *endPos, char **name, char **value)
01103 {
01104 char *szName = NULL, *szValue = NULL;
01105 int nNameLen, nValueLen;
01106
01107 nNameLen = equalPos - beginPos;
01108 nValueLen = endPos - equalPos - 2;
01109
01110 szName = (char *)malloc(nNameLen + 1);
01111 szValue = (char *)malloc(nValueLen + 1);
01112
01113 if (szName)
01114 {
01115 strncpy(szName, beginPos, nNameLen);
01116 szName[nNameLen] = '\0';
01117 }
01118
01119 if (szValue)
01120 {
01121 strncpy(szValue, equalPos + 2, nValueLen);
01122 szValue[nValueLen] = '\0';
01123 }
01124
01125 *name = szName;
01126 *value = szValue;
01127 }
01128
01129
01130
01131
01132
01133
01134 static void getIndex(const char *begin, const char *end, int *index)
01135 {
01136 char *pBuffer = NULL;
01137 int nLen;
01138
01139 *index = 0;
01140
01141 nLen = end - begin + 1;
01142 pBuffer = malloc(nLen + 1);
01143 if (pBuffer)
01144 {
01145 strncpy(pBuffer, begin, nLen);
01146 pBuffer[nLen] = '\0';
01147 *index = atoi(pBuffer);
01148 free(pBuffer);
01149 pBuffer = NULL;
01150 }
01151 }
01152
01153 static int lexicalizeAStep(char *express, char *curSlashPos, a_step_t * data)
01154 {
01155 char *nextSlashPos = NULL;
01156 char *beginBracketPos = NULL, *endBracketPos = NULL;
01157 char *atPos = NULL, *equalPos = NULL;
01158 int nLen = 0;
01159
01160 nextSlashPos = strchr(curSlashPos + 1, '/');
01161
01162 if (NULL == nextSlashPos)
01163 {
01164 nextSlashPos = (express + strlen(express));
01165 }
01166
01167
01168 calcDelimiterPositions(curSlashPos, nextSlashPos, &beginBracketPos, &atPos, &equalPos, &endBracketPos);
01169
01170
01171 nLen = curSlashPos - express;
01172 data->xpath = malloc(nLen + 1);
01173 if (NULL == data->xpath)
01174 {
01175 return RET_ERR;
01176 }
01177 snprintf(data->xpath, nLen + 1, "%s", express);
01178
01179 if (beginBracketPos && endBracketPos)
01180 {
01181
01182 nLen = beginBracketPos - (curSlashPos + 1);
01183 data->name = malloc(nLen + 1);
01184 if (NULL == data->name)
01185 {
01186 return RET_ERR;
01187 }
01188 snprintf(data->name, nLen + 1, "%s", curSlashPos + 1);
01189
01190 if (atPos)
01191 {
01192
01193 data->type = with_attr_t;
01194 getNameAndValue(atPos + 1, equalPos, endBracketPos - 1, &data->u.pairs.name, &data->u.pairs.value);
01195 }
01196 else if (equalPos)
01197 {
01198
01199 data->type = with_child_t;
01200 getNameAndValue(beginBracketPos + 1, equalPos, endBracketPos - 1,
01201 &data->u.pairs.name, &data->u.pairs.value);
01202 }
01203 else
01204 {
01205
01206 data->type = with_index_t;
01207 getIndex(beginBracketPos + 1, endBracketPos - 1, &data->u.index);
01208 }
01209 }
01210 else
01211 {
01212
01213 data->type = with_none_t;
01214 nLen = nextSlashPos - (curSlashPos + 1);
01215
01216 data->name = malloc(nLen + 1);
01217 if (NULL == data->name)
01218 {
01219 return RET_ERR;
01220 }
01221 snprintf(data->name, nLen + 1, "%s", curSlashPos + 1);
01222 }
01223
01224 return (nextSlashPos - curSlashPos);
01225 }
01226
01227 #define BUF_LEN 1024
01228 static int checkAStep(const erManifest *pCtx, char *express, char *curSlashPos)
01229 {
01230 a_step_t *data = NULL;
01231 char xpath[BUF_LEN + 1];
01232 int nChars, nLen, nRet;
01233
01234 data = newAStep();
01235 nChars = lexicalizeAStep(express, curSlashPos, data);
01236 if (RET_ERR == nChars)
01237 {
01238 freeAStep(data);
01239 data = NULL;
01240 return RET_ERR;
01241 }
01242
01243 switch (data->type)
01244 {
01245 case with_attr_t:
01246
01247 snprintf(xpath, BUF_LEN, "%s/%s[@%s=\"%s\"]",
01248 data->xpath, data->name, data->u.pairs.name, data->u.pairs.value);
01249 if (RET_ERR == ermXmlExist(pCtx, xpath))
01250 {
01251 if (strlen(data->xpath))
01252 {
01253 nRet = ermXmlNewString(pCtx, data->xpath, data->name, "");
01254 }
01255 else
01256 {
01257
01258 nRet = ermXmlNewString(pCtx, "/", data->name, "");
01259 }
01260
01261 if (RET_ERR == nRet)
01262 {
01263 freeAStep(data);
01264 data = NULL;
01265 return RET_ERR;
01266 }
01267
01268 snprintf(xpath, BUF_LEN, "%s/%s[last()]", data->xpath, data->name);
01269 nRet =
01270 ermXmlSetAttributeString(pCtx, xpath, data->u.pairs.name,
01271 data->u.pairs.value, strlen(data->u.pairs.value));
01272 if (RET_ERR == nRet)
01273 {
01274 freeAStep(data);
01275 data = NULL;
01276 return RET_ERR;
01277 }
01278 }
01279 break;
01280 case with_child_t:
01281
01282 nLen = snprintf(xpath, BUF_LEN, "%s/%s[%s=\"%s\"]",
01283 data->xpath, data->name, data->u.pairs.name, data->u.pairs.value);
01284 if (RET_ERR == ermXmlExist(pCtx, xpath))
01285 {
01286 if (strlen(data->xpath))
01287 {
01288 nRet = ermXmlNewString(pCtx, data->xpath, data->name, "");
01289 }
01290 else
01291 {
01292
01293 nRet = ermXmlNewString(pCtx, "/", data->name, "");
01294 }
01295
01296 if (RET_ERR == nRet)
01297 {
01298 freeAStep(data);
01299 data = NULL;
01300 return RET_ERR;
01301 }
01302
01303 nLen = snprintf(xpath, BUF_LEN, "%s/%s[last()]", data->xpath, data->name);
01304 nRet = ermXmlNewString(pCtx, xpath, data->u.pairs.name, data->u.pairs.value);
01305 if (RET_ERR == nRet)
01306 {
01307 freeAStep(data);
01308 data = NULL;
01309 return RET_ERR;
01310 }
01311 }
01312 break;
01313 case with_index_t:
01314
01315 nLen = snprintf(xpath, BUF_LEN, "%s/%s[%d]", data->xpath, data->name, data->u.index);
01316 if (RET_ERR == ermXmlExist(pCtx, xpath))
01317 {
01318 int nNodes = 0;
01319
01320 nLen = snprintf(xpath, BUF_LEN, "%s/%s", data->xpath, data->name);
01321 nRet = ermXmlGetNodeNr(pCtx, xpath, &nNodes);
01322 while (nNodes < data->u.index)
01323 {
01324 if (strlen(data->xpath))
01325 {
01326 nRet = ermXmlNewString(pCtx, data->xpath, data->name, "");
01327 }
01328 else
01329 {
01330
01331 nRet = ermXmlNewString(pCtx, "/", data->name, "");
01332 }
01333
01334 if (RET_ERR == nRet)
01335 {
01336 freeAStep(data);
01337 data = NULL;
01338 return RET_ERR;
01339 }
01340 nNodes++;
01341 }
01342 }
01343 break;
01344 case with_none_t:
01345 default:
01346
01347 nLen = snprintf(xpath, BUF_LEN, "%s/%s", data->xpath, data->name);
01348 if (RET_ERR == ermXmlExist(pCtx, xpath))
01349 {
01350 if (strlen(data->xpath))
01351 {
01352 nRet = ermXmlNewString(pCtx, data->xpath, data->name, "");
01353 }
01354 else
01355 {
01356
01357 nRet = ermXmlNewString(pCtx, "/", data->name, "");
01358 }
01359
01360 if (RET_ERR == nRet)
01361 {
01362 freeAStep(data);
01363 data = NULL;
01364 return RET_ERR;
01365 }
01366 }
01367 break;
01368 }
01369
01370 freeAStep(data);
01371 data = NULL;
01372
01373 return nChars;
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 int ermXmlCheckXpath(erManifest * pCtx, char *express)
01392 {
01393 int i, nChars;
01394
01395 if ((NULL == pCtx) || (NULL == express))
01396 {
01397 return RET_ERR;
01398 }
01399
01400 if (RET_OK == ermXmlExist(pCtx, express))
01401 {
01402 return RET_OK;
01403 }
01404
01405 i = 0;
01406 while (express[i])
01407 {
01408 nChars = checkAStep(pCtx, express, express + i);
01409 if (RET_ERR == nChars)
01410 {
01411 return RET_ERR;
01412 }
01413 i += nChars;
01414 }
01415
01416 return RET_OK;
01417 }