00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00028 #include "dnxXml.h"
00029
00030 #include "dnxProtocol.h"
00031 #include "dnxError.h"
00032 #include "dnxDebug.h"
00033 #include "dnxLogging.h"
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <errno.h>
00039 #include <syslog.h>
00040 #include <assert.h>
00041
00042 #define DNX_XML_MIN_HEADER 32
00043
00046
00047
00048
00049
00060 static int dnxXmlEscapeStr(char * outstr, char * instr, int maxbuf)
00061 {
00062 int i,op;
00063 int ret = DNX_OK;
00064
00065 for (i = 0, op = 0; i < strlen(instr) && i < maxbuf && ret == DNX_OK; i++)
00066 {
00067 switch(instr[i])
00068 {
00069 case 38:
00070 if (op + 5 < maxbuf)
00071 {
00072 memcpy(outstr + op, "&", 5);
00073 op += 5;
00074 }
00075 else
00076 ret = DNX_ERR_CAPACITY;
00077 break;
00078 case 60:
00079 if (op + 4 < maxbuf)
00080 {
00081 memcpy(outstr + op, "<", 4);
00082 op += 4;
00083 }
00084 else
00085 ret = DNX_ERR_CAPACITY;
00086 break;
00087 case 62:
00088 if (op + 4 < maxbuf)
00089 {
00090 memcpy(outstr + op, ">", 4);
00091 op += 4;
00092 }
00093 else ret = DNX_ERR_CAPACITY;
00094 break;
00095 case 34:
00096 if (op + 6 < maxbuf)
00097 {
00098 memcpy(outstr + op, "&qout;", 6);
00099 op += 6;
00100 }
00101 else
00102 ret = DNX_ERR_CAPACITY;
00103 break;
00104 case 39:
00105 if (op + 6 < maxbuf)
00106 {
00107 memcpy(outstr + op, "'", 6);
00108 op += 6;
00109 }
00110 else
00111 ret = DNX_ERR_CAPACITY;
00112 break;
00113 default:
00114 if (op + 1 < maxbuf)
00115 {
00116 outstr[op] = instr[i];
00117 op++;
00118 }
00119 else
00120 ret = DNX_ERR_CAPACITY;
00121 break;
00122 }
00123 }
00124 if (i >= maxbuf)
00125 ret = DNX_ERR_CAPACITY;
00126 if (ret != DNX_ERR_CAPACITY)
00127 outstr[op] = 0;
00128 return ret;
00129 }
00130
00131
00132
00143 static int dnxXmlUnescapeStr(char * outstr, char * instr, int maxbuf)
00144 {
00145 int i, op;
00146 int ret = DNX_OK;
00147 char * temp;
00148 int tempnum;
00149
00150 for (i = 0, op = 0; i < strlen(instr) && i < maxbuf && ret == DNX_OK; i++, op++)
00151 {
00152 if (instr[i] == 38)
00153 {
00154 if (strncmp(instr + i, "&", 5) == 0)
00155 {
00156 outstr[op] = '&';
00157 i += 4;
00158 }
00159 else if (strncmp(instr + i, "<", 4) == 0)
00160 {
00161 outstr[op] = '<';
00162 i += 3;
00163 }
00164 else if (strncmp(instr + i, ">", 4) == 0)
00165 {
00166 outstr[op] = '>';
00167 i+=3;
00168 }
00169 else if (strncmp(instr + i, "&qout;", 6) == 0)
00170 {
00171 outstr[op] = 34;
00172 i+=5;
00173 }
00174 else if (strncmp(instr + i, "'", 6) == 0)
00175 {
00176 outstr[op] = 39;
00177 i+=5;
00178 }
00179 else if ((temp = memchr(instr + i, ';', maxbuf-i)) != 0)
00180 {
00181 if (instr[i+1] == '#')
00182 {
00183 errno = 0;
00184 tempnum = strtol(instr + i, 0, 0);
00185 if (errno == ERANGE || tempnum < 0 || tempnum > 255)
00186 {
00187 ret = DNX_ERR_SYNTAX;
00188 dnxDebug(2, "dnxXmlUnescapeStr: invalid unescape #, "
00189 "instr=%s, i=%d, num=%d", instr, i, tempnum);
00190 }
00191 else
00192 outstr[op]=(int)tempnum;
00193 i = temp-instr;
00194 }
00195 else
00196 {
00197 ret = DNX_ERR_SYNTAX;
00198 dnxDebug(2, "dnxXmlUnescapeStr: unsupported xml escape "
00199 "sequence, instr=%s, i=%d", instr, i);
00200 }
00201 }
00202 else
00203 {
00204 ret = DNX_ERR_SYNTAX;
00205 dnxDebug(2, "dnxXmlUnescapeStr: inappropriate escape "
00206 "sequence, instr=%s, i=%d", instr, i);
00207 }
00208 }
00209 else
00210 outstr[op]=instr[i];
00211 }
00212 if (i >= maxbuf)
00213 ret = DNX_ERR_CAPACITY;
00214 if (ret != DNX_ERR_CAPACITY)
00215 outstr[op] = 0;
00216 return ret;
00217 }
00218
00219
00220
00231 static int dnxXmlToString(DnxXmlType xType, void * xData, char * buf, int size)
00232 {
00233 int ret = DNX_OK;
00234
00235 assert(xData && buf && size > 0);
00236
00237 *buf = 0;
00238
00239 switch (xType)
00240 {
00241 case DNX_XML_SHORT:
00242 snprintf(buf, size, "%hd", *((short *)xData));
00243 break;
00244
00245 case DNX_XML_USHORT:
00246 snprintf(buf, size, "%hu", *((unsigned short *)xData));
00247 break;
00248
00249 case DNX_XML_INT:
00250 snprintf(buf, size, "%d", *((int *)xData));
00251 break;
00252
00253 case DNX_XML_UINT:
00254 snprintf(buf, size, "%u", *((unsigned int *)xData));
00255 break;
00256
00257 case DNX_XML_LONG:
00258 snprintf(buf, size, "%ld", *((long *)xData));
00259 break;
00260
00261 case DNX_XML_ULONG:
00262 snprintf(buf, size, "%lu", *((unsigned long *)xData));
00263 break;
00264
00265 case DNX_XML_STR_UNESCAPED:
00266 assert(strlen((char *)xData) < size);
00267 strncpy(buf, (char *)xData, size);
00268 buf[size - 1] = 0;
00269 break;
00270
00271 case DNX_XML_STR:
00272 assert(strlen((char *)xData) < size);
00273 ret = dnxXmlEscapeStr(buf, (char *)xData, size);
00274 buf[size - 1] = 0;
00275 break;
00276
00277 case DNX_XML_XID:
00278 snprintf(buf, size, "%u-%lu-%lu", ((DnxXID *)xData)->objType,
00279 ((DnxXID *)xData)->objSerial, ((DnxXID *)xData)->objSlot);
00280 break;
00281
00282 default:
00283 ret = DNX_ERR_INVALID;
00284 }
00285 return ret;
00286 }
00287
00288
00289
00302 static int dnxXmlGetTagValue(DnxXmlBuf * xbuf, char * xTag, DnxXmlType xType,
00303 char * buf, int size)
00304 {
00305 char * cp, * ep, * value;
00306 int len, ret = DNX_OK;
00307
00308 assert(xbuf && xTag && buf && size);
00309
00310
00311 cp = xbuf->buf;
00312 while ((cp = strchr(cp, '<')) != 0)
00313 {
00314 cp++;
00315
00316 if (*cp == '/')
00317 continue;
00318
00319
00320 if ((ep = strchr(cp, '>')) == 0)
00321 {
00322 ret = DNX_ERR_SYNTAX;
00323 break;
00324 }
00325
00326
00327 if (strncmp(cp, xTag, (ep-cp)))
00328 {
00329 cp = ep+1;
00330 continue;
00331 }
00332
00333 value = cp = ep + 1;
00334
00335 end_tag:
00336
00337
00338 if ((ep = strchr(cp, '<')) == 0)
00339 {
00340 ret = DNX_ERR_SYNTAX;
00341 break;
00342 }
00343
00344 len = ep - value;
00345
00346
00347 if (*(cp = ep + 1) != '/')
00348 goto end_tag;
00349 cp++;
00350
00351
00352 if ((ep = strchr(cp, '>')) == 0)
00353 {
00354 ret = DNX_ERR_SYNTAX;
00355 break;
00356 }
00357
00358
00359 if (strncmp(cp, xTag, ep - cp))
00360 goto end_tag;
00361
00362
00363 if (len >= size)
00364 len = size - 1;
00365
00366
00367 if (len > 0)
00368 memcpy(buf, value, len);
00369 buf[len] = 0;
00370
00371 break;
00372 }
00373 return ret;
00374 }
00375
00376
00377
00378
00379
00387 int dnxXmlOpen(DnxXmlBuf * xbuf, char * tag)
00388 {
00389 assert(xbuf && tag);
00390
00391
00392 xbuf->size = sprintf(xbuf->buf, "<dnxMessage><Request>%s</Request>", tag);
00393
00394 return DNX_OK;
00395 }
00396
00397
00398
00409 int dnxXmlAdd(DnxXmlBuf * xbuf, char * xTag, DnxXmlType xType, void * xData)
00410 {
00411 char buf[DNX_MAX_MSG];
00412 int len, ret;
00413
00414 assert(xbuf && xbuf->size >= DNX_XML_MIN_HEADER && xTag);
00415
00416
00417 *buf = 0;
00418 if (xData && (ret = dnxXmlToString(xType, xData, buf, sizeof buf)) != DNX_OK)
00419 return ret;
00420
00421
00422 if ((len = xbuf->size + strlen(xTag) * 2 + strlen(buf) + 5) >= DNX_MAX_MSG)
00423 return DNX_ERR_CAPACITY;
00424
00425
00426 xbuf->size += sprintf(xbuf->buf + xbuf->size, "<%s>%s</%s>", xTag, buf, xTag);
00427
00428 return DNX_OK;
00429 }
00430
00431
00432
00447 int dnxXmlGet(DnxXmlBuf * xbuf, char * xTag, DnxXmlType xType, void * xData)
00448 {
00449 char buf[DNX_MAX_MSG];
00450 char * cp, * ep, * lastchar;
00451 unsigned long unum;
00452 long num;
00453 int ret = DNX_OK;
00454 char * temp = NULL;
00455
00456
00457 if ((ret = dnxXmlGetTagValue(xbuf, xTag, xType, buf, sizeof buf)) != DNX_OK)
00458 return ret;
00459
00460
00461 switch (xType)
00462 {
00463 case DNX_XML_SHORT:
00464 errno = 0;
00465 num = strtol(buf, &lastchar, 0);
00466 if (errno == ERANGE || *lastchar)
00467 ret = DNX_ERR_SYNTAX;
00468 else
00469 *(short *)xData = (short)num;
00470 break;
00471
00472 case DNX_XML_USHORT:
00473 errno = 0;
00474 unum = strtoul(buf, &lastchar, 0);
00475 if (errno == ERANGE || *lastchar)
00476 ret = DNX_ERR_SYNTAX;
00477 else
00478 *(unsigned short *)xData = (unsigned short)unum;
00479 break;
00480
00481 case DNX_XML_INT:
00482 errno = 0;
00483 num = strtol(buf, &lastchar, 0);
00484 if (errno == ERANGE || *lastchar)
00485 ret = DNX_ERR_SYNTAX;
00486 else
00487 *(int *)xData = (int)num;
00488 break;
00489
00490 case DNX_XML_UINT:
00491 errno = 0;
00492 unum = strtoul(buf, &lastchar, 0);
00493 if (errno == ERANGE || *lastchar)
00494 ret = DNX_ERR_SYNTAX;
00495 else
00496 *(unsigned int *)xData = (unsigned int)unum;
00497 break;
00498
00499 case DNX_XML_LONG:
00500 errno = 0;
00501 num = strtol(buf, &lastchar, 0);
00502 if (errno == ERANGE || *lastchar)
00503 ret = DNX_ERR_SYNTAX;
00504 else
00505 *(long *)xData = (long)num;
00506 break;
00507
00508 case DNX_XML_ULONG:
00509 errno = 0;
00510 unum = strtoul(buf, &lastchar, 0);
00511 if (errno == ERANGE || *lastchar)
00512 ret = DNX_ERR_SYNTAX;
00513 else
00514 *(unsigned long *)xData = (unsigned long)unum;
00515 break;
00516
00517 case DNX_XML_STR_UNESCAPED:
00518 if ((*((char **)xData) = xstrdup(buf)) == 0)
00519 ret = DNX_ERR_MEMORY;
00520 break;
00521
00522 case DNX_XML_STR:
00523 if ((temp = xstrdup(buf)) == 0)
00524 {
00525 ret = DNX_ERR_MEMORY;
00526 }else{
00527 ret = dnxXmlUnescapeStr(temp, buf, sizeof buf);
00528 *(char **)xData = temp;
00529 }
00530 break;
00531
00532 case DNX_XML_XID:
00533
00534
00535 if ((cp = strchr(buf, '-')) == 0)
00536 {
00537 ret = DNX_ERR_SYNTAX;
00538 break;
00539 }
00540 *cp++ = 0;
00541
00542 if ((ep = strchr(cp, '-')) == 0)
00543 {
00544 ret = DNX_ERR_SYNTAX;
00545 break;
00546 }
00547 *ep++ = 0;
00548
00549
00550 errno = 0;
00551 unum = strtoul(buf, &lastchar, 0);
00552 if (errno == ERANGE || *lastchar)
00553 {
00554 ret = DNX_ERR_SYNTAX;
00555 break;
00556 }
00557 ((DnxXID *)xData)->objType = (DnxObjType)unum;
00558
00559
00560 errno = 0;
00561 unum = strtoul(cp, &lastchar, 0);
00562 if (errno == ERANGE || *lastchar)
00563 {
00564 ret = DNX_ERR_SYNTAX;
00565 break;
00566 }
00567 ((DnxXID *)xData)->objSerial = (unsigned long)unum;
00568
00569
00570 errno = 0;
00571 unum = strtoul(ep, &lastchar, 0);
00572 if (errno == ERANGE || *lastchar)
00573 {
00574 ret = DNX_ERR_SYNTAX;
00575 break;
00576 }
00577 ((DnxXID *)xData)->objSlot = (unsigned long)unum;
00578 break;
00579
00580 default:
00581 ret = DNX_ERR_INVALID;
00582 }
00583 return ret;
00584 }
00585
00586
00587
00596 int dnxXmlCmpStr(DnxXmlBuf * xbuf, char * xTag, char * cmpstr)
00597 {
00598 char buf[DNX_MAX_MSG];
00599 int ret;
00600
00601 if ((ret = dnxXmlGetTagValue(xbuf,
00602 xTag, DNX_XML_STR, buf, sizeof buf)) != DNX_OK)
00603 return ret;
00604
00605 return strcmp(cmpstr, buf) == 0 ? DNX_OK : DNX_ERR_SYNTAX;
00606 }
00607
00608
00609
00616 int dnxXmlClose(DnxXmlBuf * xbuf)
00617 {
00618 assert(xbuf && xbuf->size >= 0);
00619
00620 if (xbuf->size > DNX_MAX_MSG)
00621 return DNX_ERR_CAPACITY;
00622
00623
00624 strcat(xbuf->buf, "</dnxMessage>");
00625 xbuf->size = strlen(xbuf->buf);
00626
00627 return DNX_OK;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 #ifdef DNX_XML_TEST
00646
00647 #include "utesthelp.h"
00648
00649 static verbose;
00650
00651 IMPLEMENT_DNX_SYSLOG(verbose);
00652 IMPLEMENT_DNX_DEBUG(verbose);
00653
00654 int main(int argc, char ** argv)
00655 {
00656 static int lens[] = {35, 54, 74, 90, 107, 126, 146, 174, 204, 217};
00657 static char * testbuf =
00658 "<dnxMessage>"
00659 "<Request>Test</Request>"
00660 "<Short>-100</Short>"
00661 "<UShort>100</UShort>"
00662 "<Int>-1000</Int>"
00663 "<UInt>1000</UInt>"
00664 "<Long>-10000</Long>"
00665 "<ULong>10000</ULong>"
00666 "<String>test string</String>"
00667 "<XID>6-12345678-87654321</XID>"
00668 "</dnxMessage>";
00669
00670 DnxXmlBuf xbuf;
00671
00672 short xshort = -100;
00673 unsigned short xushort = 100;
00674 int xint = -1000;
00675 unsigned int xuint = 1000;
00676 long xlong = -10000;
00677 unsigned long xulong = 10000;
00678 char * xstring = "test string";
00679 DnxXID xid;
00680
00681 xid.objType = DNX_OBJ_MANAGER;
00682 xid.objSerial = 12345678;
00683 xid.objSlot = 87654321;
00684
00685 verbose = argc > 1 ? 1 : 0;
00686
00687 CHECK_ZERO(dnxXmlOpen(&xbuf, "Test"));
00688 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[0]) == 0);
00689
00690 CHECK_ZERO(dnxXmlAdd(&xbuf, "Short", DNX_XML_SHORT, &xshort));
00691 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[1]) == 0);
00692
00693 CHECK_ZERO(dnxXmlAdd(&xbuf, "UShort", DNX_XML_USHORT, &xushort));
00694 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[2]) == 0);
00695
00696 CHECK_ZERO(dnxXmlAdd(&xbuf, "Int", DNX_XML_INT, &xint));
00697 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[3]) == 0);
00698
00699 CHECK_ZERO(dnxXmlAdd(&xbuf, "UInt", DNX_XML_UINT, &xuint));
00700 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[4]) == 0);
00701
00702 CHECK_ZERO(dnxXmlAdd(&xbuf, "Long", DNX_XML_LONG, &xlong));
00703 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[5]) == 0);
00704
00705 CHECK_ZERO(dnxXmlAdd(&xbuf, "ULong", DNX_XML_ULONG, &xulong));
00706 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[6]) == 0);
00707
00708 CHECK_ZERO(dnxXmlAdd(&xbuf, "String", DNX_XML_STR, xstring));
00709 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[7]) == 0);
00710
00711 CHECK_ZERO(dnxXmlAdd(&xbuf, "XID", DNX_XML_XID, &xid));
00712 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[8]) == 0);
00713
00714 CHECK_ZERO(dnxXmlClose(&xbuf));
00715 CHECK_TRUE(memcmp(xbuf.buf, testbuf, lens[9]) == 0);
00716
00717 CHECK_ZERO(dnxXmlGet(&xbuf, "Short", DNX_XML_SHORT, &xshort));
00718 CHECK_TRUE(xshort == -100);
00719
00720 CHECK_ZERO(dnxXmlGet(&xbuf, "UShort", DNX_XML_USHORT, &xushort));
00721 CHECK_TRUE(xushort == 100);
00722
00723 CHECK_ZERO(dnxXmlGet(&xbuf, "Int", DNX_XML_INT, &xint));
00724 CHECK_TRUE(xint == -1000);
00725
00726 CHECK_ZERO(dnxXmlGet(&xbuf, "UInt", DNX_XML_UINT, &xuint));
00727 CHECK_TRUE(xuint == 1000);
00728
00729 CHECK_ZERO(dnxXmlGet(&xbuf, "Long", DNX_XML_LONG, &xlong));
00730 CHECK_TRUE(xlong == -10000);
00731
00732 CHECK_ZERO(dnxXmlGet(&xbuf, "ULong", DNX_XML_ULONG, &xulong));
00733 CHECK_TRUE(xulong == 10000);
00734
00735 CHECK_ZERO(dnxXmlGet(&xbuf, "String", DNX_XML_STR, &xstring));
00736 CHECK_TRUE(strcmp(xstring, "test string") == 0);
00737
00738
00739 xfree(xstring);
00740
00741 CHECK_ZERO(dnxXmlGet(&xbuf, "XID", DNX_XML_XID, &xid));
00742 CHECK_TRUE(xid.objType == DNX_OBJ_MANAGER);
00743 CHECK_TRUE(xid.objSerial == 12345678);
00744 CHECK_TRUE(xid.objSlot == 87654321);
00745
00746 #ifdef DEBUG_HEAP
00747 CHECK_ZERO(dnxCheckHeap());
00748 #endif
00749
00750 return 0;
00751 }
00752
00753 #endif
00754
00755
00756