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