1 /* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2013 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
15 static void
NameValueParserStartElt(void * d,const char * name,int l)16 NameValueParserStartElt(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
28 static void
NameValueParserEndElt(void * d,const char * name,int l)29 NameValueParserEndElt(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 LIST_INSERT_HEAD( &(data->head), nv, entries);
57 }
58 data->cdata = NULL;
59 data->cdatalen = 0;
60 data->topelt = 0;
61 }
62
63 static void
NameValueParserGetData(void * d,const char * datas,int l)64 NameValueParserGetData(void * d, const char * datas, int l)
65 {
66 struct NameValueParserData * data = (struct NameValueParserData *)d;
67 if(strcmp(data->curelt, "NewPortListing") == 0)
68 {
69 /* specific case for NewPortListing which is a XML Document */
70 data->portListing = malloc(l + 1);
71 if(!data->portListing)
72 {
73 /* malloc error */
74 return;
75 }
76 memcpy(data->portListing, datas, l);
77 data->portListing[l] = '\0';
78 data->portListingLength = l;
79 }
80 else
81 {
82 /* standard case. */
83 data->cdata = datas;
84 data->cdatalen = l;
85 }
86 }
87
88 void
ParseNameValue(const char * buffer,int bufsize,struct NameValueParserData * data)89 ParseNameValue(const char * buffer, int bufsize,
90 struct NameValueParserData * data)
91 {
92 struct xmlparser parser;
93 LIST_INIT(&(data->head));
94 data->portListing = NULL;
95 data->portListingLength = 0;
96 /* init xmlparser object */
97 parser.xmlstart = buffer;
98 parser.xmlsize = bufsize;
99 parser.data = data;
100 parser.starteltfunc = NameValueParserStartElt;
101 parser.endeltfunc = NameValueParserEndElt;
102 parser.datafunc = NameValueParserGetData;
103 parser.attfunc = 0;
104 parsexml(&parser);
105 }
106
107 void
ClearNameValueList(struct NameValueParserData * pdata)108 ClearNameValueList(struct NameValueParserData * pdata)
109 {
110 struct NameValue * nv;
111 if(pdata->portListing)
112 {
113 free(pdata->portListing);
114 pdata->portListing = NULL;
115 pdata->portListingLength = 0;
116 }
117 while((nv = pdata->head.lh_first) != NULL)
118 {
119 LIST_REMOVE(nv, entries);
120 free(nv);
121 }
122 }
123
124 char *
GetValueFromNameValueList(struct NameValueParserData * pdata,const char * Name)125 GetValueFromNameValueList(struct NameValueParserData * pdata,
126 const char * Name)
127 {
128 struct NameValue * nv;
129 char * p = NULL;
130 for(nv = pdata->head.lh_first;
131 (nv != NULL) && (p == NULL);
132 nv = nv->entries.le_next)
133 {
134 if(strcmp(nv->name, Name) == 0)
135 p = nv->value;
136 }
137 return p;
138 }
139
140 #if 0
141 /* useless now that minixml ignores namespaces by itself */
142 char *
143 GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
144 const char * Name)
145 {
146 struct NameValue * nv;
147 char * p = NULL;
148 char * pname;
149 for(nv = pdata->head.lh_first;
150 (nv != NULL) && (p == NULL);
151 nv = nv->entries.le_next)
152 {
153 pname = strrchr(nv->name, ':');
154 if(pname)
155 pname++;
156 else
157 pname = nv->name;
158 if(strcmp(pname, Name)==0)
159 p = nv->value;
160 }
161 return p;
162 }
163 #endif
164
165 /* debug all-in-one function
166 * do parsing then display to stdout */
167 #ifdef DEBUG
168 void
DisplayNameValueList(char * buffer,int bufsize)169 DisplayNameValueList(char * buffer, int bufsize)
170 {
171 struct NameValueParserData pdata;
172 struct NameValue * nv;
173 ParseNameValue(buffer, bufsize, &pdata);
174 for(nv = pdata.head.lh_first;
175 nv != NULL;
176 nv = nv->entries.le_next)
177 {
178 printf("%s = %s\n", nv->name, nv->value);
179 }
180 ClearNameValueList(&pdata);
181 }
182 #endif
183
184