1/* $Id: upnpreplyparse.c,v 1.12 2012/03/05 19:42:48 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 15static void 16NameValueParserStartElt(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 25static void 26NameValueParserGetData(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 57void 58ParseNameValue(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 76void 77ClearNameValueList(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 93char * 94GetValueFromNameValueList(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 */ 111char * 112GetValueFromNameValueListIgnoreNS(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 137void 138DisplayNameValueList(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