upnpreplyparse.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* $Id: upnpreplyparse.c,v 1.20 2017/12/12 11:26:25 nanard Exp $ */
  2. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  3. * MiniUPnP project
  4. * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
  5. * (c) 2006-2017 Thomas Bernard
  6. * This software is subject to the conditions detailed
  7. * in the LICENCE file provided within the distribution */
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include "upnpreplyparse.h"
  12. #include "minixml.h"
  13. static void
  14. NameValueParserStartElt(void * d, const char * name, int l)
  15. {
  16. struct NameValueParserData * data = (struct NameValueParserData *)d;
  17. data->topelt = 1;
  18. if(l>63)
  19. l = 63;
  20. memcpy(data->curelt, name, l);
  21. data->curelt[l] = '\0';
  22. data->cdata = NULL;
  23. data->cdatalen = 0;
  24. }
  25. static void
  26. NameValueParserEndElt(void * d, const char * name, int namelen)
  27. {
  28. struct NameValueParserData * data = (struct NameValueParserData *)d;
  29. struct NameValue * nv;
  30. (void)name;
  31. (void)namelen;
  32. if(!data->topelt)
  33. return;
  34. if(strcmp(data->curelt, "NewPortListing") != 0)
  35. {
  36. int l;
  37. /* standard case. Limited to n chars strings */
  38. l = data->cdatalen;
  39. nv = malloc(sizeof(struct NameValue));
  40. if(nv == NULL)
  41. {
  42. /* malloc error */
  43. #ifdef DEBUG
  44. fprintf(stderr, "%s: error allocating memory",
  45. "NameValueParserEndElt");
  46. #endif /* DEBUG */
  47. return;
  48. }
  49. if(l>=(int)sizeof(nv->value))
  50. l = sizeof(nv->value) - 1;
  51. strncpy(nv->name, data->curelt, 64);
  52. nv->name[63] = '\0';
  53. if(data->cdata != NULL)
  54. {
  55. memcpy(nv->value, data->cdata, l);
  56. nv->value[l] = '\0';
  57. }
  58. else
  59. {
  60. nv->value[0] = '\0';
  61. }
  62. nv->l_next = data->l_head; /* insert in list */
  63. data->l_head = nv;
  64. }
  65. data->cdata = NULL;
  66. data->cdatalen = 0;
  67. data->topelt = 0;
  68. }
  69. static void
  70. NameValueParserGetData(void * d, const char * datas, int l)
  71. {
  72. struct NameValueParserData * data = (struct NameValueParserData *)d;
  73. if(strcmp(data->curelt, "NewPortListing") == 0)
  74. {
  75. /* specific case for NewPortListing which is a XML Document */
  76. data->portListing = malloc(l + 1);
  77. if(!data->portListing)
  78. {
  79. /* malloc error */
  80. #ifdef DEBUG
  81. fprintf(stderr, "%s: error allocating memory",
  82. "NameValueParserGetData");
  83. #endif /* DEBUG */
  84. return;
  85. }
  86. memcpy(data->portListing, datas, l);
  87. data->portListing[l] = '\0';
  88. data->portListingLength = l;
  89. }
  90. else
  91. {
  92. /* standard case. */
  93. data->cdata = datas;
  94. data->cdatalen = l;
  95. }
  96. }
  97. void
  98. ParseNameValue(const char * buffer, int bufsize,
  99. struct NameValueParserData * data)
  100. {
  101. struct xmlparser parser;
  102. memset(data, 0, sizeof(struct NameValueParserData));
  103. /* init xmlparser object */
  104. parser.xmlstart = buffer;
  105. parser.xmlsize = bufsize;
  106. parser.data = data;
  107. parser.starteltfunc = NameValueParserStartElt;
  108. parser.endeltfunc = NameValueParserEndElt;
  109. parser.datafunc = NameValueParserGetData;
  110. parser.attfunc = 0;
  111. parsexml(&parser);
  112. }
  113. void
  114. ClearNameValueList(struct NameValueParserData * pdata)
  115. {
  116. struct NameValue * nv;
  117. if(pdata->portListing)
  118. {
  119. free(pdata->portListing);
  120. pdata->portListing = NULL;
  121. pdata->portListingLength = 0;
  122. }
  123. while((nv = pdata->l_head) != NULL)
  124. {
  125. pdata->l_head = nv->l_next;
  126. free(nv);
  127. }
  128. }
  129. char *
  130. GetValueFromNameValueList(struct NameValueParserData * pdata,
  131. const char * Name)
  132. {
  133. struct NameValue * nv;
  134. char * p = NULL;
  135. for(nv = pdata->l_head;
  136. (nv != NULL) && (p == NULL);
  137. nv = nv->l_next)
  138. {
  139. if(strcmp(nv->name, Name) == 0)
  140. p = nv->value;
  141. }
  142. return p;
  143. }
  144. #if 0
  145. /* useless now that minixml ignores namespaces by itself */
  146. char *
  147. GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
  148. const char * Name)
  149. {
  150. struct NameValue * nv;
  151. char * p = NULL;
  152. char * pname;
  153. for(nv = pdata->head.lh_first;
  154. (nv != NULL) && (p == NULL);
  155. nv = nv->entries.le_next)
  156. {
  157. pname = strrchr(nv->name, ':');
  158. if(pname)
  159. pname++;
  160. else
  161. pname = nv->name;
  162. if(strcmp(pname, Name)==0)
  163. p = nv->value;
  164. }
  165. return p;
  166. }
  167. #endif
  168. /* debug all-in-one function
  169. * do parsing then display to stdout */
  170. #ifdef DEBUG
  171. void
  172. DisplayNameValueList(char * buffer, int bufsize)
  173. {
  174. struct NameValueParserData pdata;
  175. struct NameValue * nv;
  176. ParseNameValue(buffer, bufsize, &pdata);
  177. for(nv = pdata.l_head;
  178. nv != NULL;
  179. nv = nv->l_next)
  180. {
  181. printf("%s = %s\n", nv->name, nv->value);
  182. }
  183. ClearNameValueList(&pdata);
  184. }
  185. #endif /* DEBUG */