Path: blob/master/thirdparty/miniupnpc/src/upnpreplyparse.c
9904 views
/* $Id: upnpreplyparse.c,v 1.22 2025/02/08 23:12:26 nanard Exp $ */1/* vim: tabstop=4 shiftwidth=4 noexpandtab2* MiniUPnP project3* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/4* (c) 2006-2025 Thomas Bernard5* This software is subject to the conditions detailed6* in the LICENCE file provided within the distribution */78#include <stdlib.h>9#include <string.h>10#include <stdio.h>1112#include "upnpreplyparse.h"13#include "minixml.h"1415struct NameValue {16/*! \brief pointer to the next element */17struct NameValue * l_next;18/*! \brief name */19char name[64];20#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L21/* C99 flexible array member */22/*! \brief character value */23char value[];24#elif defined(__GNUC__)25char value[0];26#else27/* Fallback to a hack */28char value[1];29#endif30};3132static void33NameValueParserStartElt(void * d, const char * name, int l)34{35struct NameValueParserData * data = (struct NameValueParserData *)d;36data->topelt = 1;37if(l>63)38l = 63;39memcpy(data->curelt, name, l);40data->curelt[l] = '\0';41data->cdata = NULL;42data->cdatalen = 0;43}4445static void46NameValueParserEndElt(void * d, const char * name, int namelen)47{48struct NameValueParserData * data = (struct NameValueParserData *)d;49struct NameValue * nv;50(void)name;51(void)namelen;52if(!data->topelt)53return;54if(strcmp(data->curelt, "NewPortListing") != 0)55{56int l;57/* standard case. Limited to n chars strings */58l = data->cdatalen;59nv = malloc(sizeof(struct NameValue) + l + 1);60if(nv == NULL)61{62/* malloc error */63#ifdef DEBUG64fprintf(stderr, "%s: error allocating memory",65"NameValueParserEndElt");66#endif /* DEBUG */67return;68}69strncpy(nv->name, data->curelt, 64);70nv->name[63] = '\0';71if(data->cdata != NULL)72{73memcpy(nv->value, data->cdata, l);74nv->value[l] = '\0';75}76else77{78nv->value[0] = '\0';79}80nv->l_next = data->l_head; /* insert in list */81data->l_head = nv;82}83data->cdata = NULL;84data->cdatalen = 0;85data->topelt = 0;86}8788static void89NameValueParserGetData(void * d, const char * datas, int l)90{91struct NameValueParserData * data = (struct NameValueParserData *)d;92if(strcmp(data->curelt, "NewPortListing") == 0)93{94/* specific case for NewPortListing which is a XML Document */95free(data->portListing);96data->portListing = malloc(l + 1);97if(!data->portListing)98{99/* malloc error */100#ifdef DEBUG101fprintf(stderr, "%s: error allocating memory",102"NameValueParserGetData");103#endif /* DEBUG */104return;105}106memcpy(data->portListing, datas, l);107data->portListing[l] = '\0';108data->portListingLength = l;109}110else111{112/* standard case. */113data->cdata = datas;114data->cdatalen = l;115}116}117118void119ParseNameValue(const char * buffer, int bufsize,120struct NameValueParserData * data)121{122struct xmlparser parser;123memset(data, 0, sizeof(struct NameValueParserData));124/* init xmlparser object */125parser.xmlstart = buffer;126parser.xmlsize = bufsize;127parser.data = data;128parser.starteltfunc = NameValueParserStartElt;129parser.endeltfunc = NameValueParserEndElt;130parser.datafunc = NameValueParserGetData;131parser.attfunc = 0;132parsexml(&parser);133}134135void136ClearNameValueList(struct NameValueParserData * pdata)137{138struct NameValue * nv;139if(pdata->portListing)140{141free(pdata->portListing);142pdata->portListing = NULL;143pdata->portListingLength = 0;144}145while((nv = pdata->l_head) != NULL)146{147pdata->l_head = nv->l_next;148free(nv);149}150}151152char *153GetValueFromNameValueList(struct NameValueParserData * pdata,154const char * name)155{156struct NameValue * nv;157char * p = NULL;158for(nv = pdata->l_head;159(nv != NULL) && (p == NULL);160nv = nv->l_next)161{162if(strcmp(nv->name, name) == 0)163p = nv->value;164}165return p;166}167168/* debug all-in-one function169* do parsing then display to stdout */170#ifdef DEBUG171void172DisplayNameValueList(char * buffer, int bufsize)173{174struct NameValueParserData pdata;175struct NameValue * nv;176ParseNameValue(buffer, bufsize, &pdata);177for(nv = pdata.l_head;178nv != NULL;179nv = nv->l_next)180{181printf("%s = %s\n", nv->name, nv->value);182}183ClearNameValueList(&pdata);184}185#endif /* DEBUG */186187188189