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