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