1 /* $Id: upnpreplyparse.c,v 1.11 2011/02/07 16:17:06 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2011 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 if(l>63)
20 l = 63;
21 memcpy(data->curelt, name, l);
22 data->curelt[l] = '\0';
23 }
24
25 static void
NameValueParserGetData(void * d,const char * datas,int l)26 NameValueParserGetData(void * d, const char * datas, int l)
27 {
28 struct NameValueParserData * data = (struct NameValueParserData *)d;
29 struct NameValue * nv;
30 if(strcmp(data->curelt, "NewPortListing") == 0)
31 {
32 /* specific case for NewPortListing which is a XML Document */
33 data->portListing = malloc(l + 1);
34 if(!data->portListing)
35 {
36 /* malloc error */
37 return;
38 }
39 memcpy(data->portListing, datas, l);
40 data->portListing[l] = '\0';
41 data->portListingLength = l;
42 }
43 else
44 {
45 /* standard case. Limited to 63 chars strings */
46 nv = malloc(sizeof(struct NameValue));
47 if(l>63)
48 l = 63;
49 strncpy(nv->name, data->curelt, 64);
50 nv->name[63] = '\0';
51 memcpy(nv->value, datas, l);
52 nv->value[l] = '\0';
53 LIST_INSERT_HEAD( &(data->head), nv, entries);
54 }
55 }
56
57 void
ParseNameValue(const char * buffer,int bufsize,struct NameValueParserData * data)58 ParseNameValue(const char * buffer, int bufsize,
59 struct NameValueParserData * data)
60 {
61 struct xmlparser parser;
62 LIST_INIT(&(data->head));
63 data->portListing = NULL;
64 data->portListingLength = 0;
65 /* init xmlparser object */
66 parser.xmlstart = buffer;
67 parser.xmlsize = bufsize;
68 parser.data = data;
69 parser.starteltfunc = NameValueParserStartElt;
70 parser.endeltfunc = 0;
71 parser.datafunc = NameValueParserGetData;
72 parser.attfunc = 0;
73 parsexml(&parser);
74 }
75
76 void
ClearNameValueList(struct NameValueParserData * pdata)77 ClearNameValueList(struct NameValueParserData * pdata)
78 {
79 struct NameValue * nv;
80 if(pdata->portListing)
81 {
82 free(pdata->portListing);
83 pdata->portListing = NULL;
84 pdata->portListingLength = 0;
85 }
86 while((nv = pdata->head.lh_first) != NULL)
87 {
88 LIST_REMOVE(nv, entries);
89 free(nv);
90 }
91 }
92
93 char *
GetValueFromNameValueList(struct NameValueParserData * pdata,const char * Name)94 GetValueFromNameValueList(struct NameValueParserData * pdata,
95 const char * Name)
96 {
97 struct NameValue * nv;
98 char * p = NULL;
99 for(nv = pdata->head.lh_first;
100 (nv != NULL) && (p == NULL);
101 nv = nv->entries.le_next)
102 {
103 if(strcmp(nv->name, Name) == 0)
104 p = nv->value;
105 }
106 return p;
107 }
108
109 #if 0
110 /* useless now that minixml ignores namespaces by itself */
111 char *
112 GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
113 const char * Name)
114 {
115 struct NameValue * nv;
116 char * p = NULL;
117 char * pname;
118 for(nv = pdata->head.lh_first;
119 (nv != NULL) && (p == NULL);
120 nv = nv->entries.le_next)
121 {
122 pname = strrchr(nv->name, ':');
123 if(pname)
124 pname++;
125 else
126 pname = nv->name;
127 if(strcmp(pname, Name)==0)
128 p = nv->value;
129 }
130 return p;
131 }
132 #endif
133
134 /* debug all-in-one function
135 * do parsing then display to stdout */
136 #ifdef DEBUG
137 void
DisplayNameValueList(char * buffer,int bufsize)138 DisplayNameValueList(char * buffer, int bufsize)
139 {
140 struct NameValueParserData pdata;
141 struct NameValue * nv;
142 ParseNameValue(buffer, bufsize, &pdata);
143 for(nv = pdata.head.lh_first;
144 nv != NULL;
145 nv = nv->entries.le_next)
146 {
147 printf("%s = %s\n", nv->name, nv->value);
148 }
149 ClearNameValueList(&pdata);
150 }
151 #endif
152
153