Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/miniupnpc/src/portlistingparse.c
9904 views
1
/* $Id: portlistingparse.c,v 1.12 2025/03/29 17:58:33 nanard Exp $ */
2
/* MiniUPnP project
3
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
4
* (c) 2011-2025 Thomas Bernard
5
* This software is subject to the conditions detailed
6
* in the LICENCE file provided within the distribution */
7
#include <string.h>
8
#include <stdlib.h>
9
#ifdef DEBUG
10
#include <stdio.h>
11
#endif /* DEBUG */
12
#include "portlistingparse.h"
13
#include "minixml.h"
14
15
#if defined(__HAIKU__)
16
/* rename our private function because Haiku already defines a atoui() function */
17
#define atoui atoui2
18
#endif
19
20
/* list of the elements */
21
static const struct {
22
const portMappingElt code;
23
const char * const str;
24
} elements[] = {
25
{ PortMappingEntry, "PortMappingEntry"},
26
{ NewRemoteHost, "NewRemoteHost"},
27
{ NewExternalPort, "NewExternalPort"},
28
{ NewProtocol, "NewProtocol"},
29
{ NewInternalPort, "NewInternalPort"},
30
{ NewInternalClient, "NewInternalClient"},
31
{ NewEnabled, "NewEnabled"},
32
{ NewDescription, "NewDescription"},
33
{ NewLeaseTime, "NewLeaseTime"},
34
{ PortMappingEltNone, NULL}
35
};
36
37
/* Helper function */
38
static UNSIGNED_INTEGER
39
atoui(const char * p, int l)
40
{
41
UNSIGNED_INTEGER r = 0;
42
while(l > 0 && *p)
43
{
44
if(*p >= '0' && *p <= '9')
45
r = r*10 + (*p - '0');
46
else
47
break;
48
p++;
49
l--;
50
}
51
return r;
52
}
53
54
/* Start element handler */
55
static void
56
startelt(void * d, const char * name, int l)
57
{
58
int i;
59
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
60
pdata->curelt = PortMappingEltNone;
61
for(i = 0; elements[i].str; i++)
62
{
63
if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0)
64
{
65
pdata->curelt = elements[i].code;
66
break;
67
}
68
}
69
if(pdata->curelt == PortMappingEntry)
70
{
71
struct PortMapping * pm;
72
pm = calloc(1, sizeof(struct PortMapping));
73
if(pm == NULL)
74
{
75
/* malloc error */
76
#ifdef DEBUG
77
fprintf(stderr, "%s: error allocating memory",
78
"startelt");
79
#endif /* DEBUG */
80
return;
81
}
82
pm->l_next = pdata->l_head; /* insert in list */
83
pdata->l_head = pm;
84
}
85
}
86
87
/* End element handler */
88
static void
89
endelt(void * d, const char * name, int l)
90
{
91
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
92
(void)name;
93
(void)l;
94
pdata->curelt = PortMappingEltNone;
95
}
96
97
/* Data handler */
98
static void
99
data(void * d, const char * data, int l)
100
{
101
struct PortMapping * pm;
102
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
103
pm = pdata->l_head;
104
if(!pm)
105
return;
106
if(l > 63)
107
l = 63;
108
switch(pdata->curelt)
109
{
110
case NewRemoteHost:
111
memcpy(pm->remoteHost, data, l);
112
pm->remoteHost[l] = '\0';
113
break;
114
case NewExternalPort:
115
pm->externalPort = (unsigned short)atoui(data, l);
116
break;
117
case NewProtocol:
118
if(l > 3)
119
l = 3;
120
memcpy(pm->protocol, data, l);
121
pm->protocol[l] = '\0';
122
break;
123
case NewInternalPort:
124
pm->internalPort = (unsigned short)atoui(data, l);
125
break;
126
case NewInternalClient:
127
memcpy(pm->internalClient, data, l);
128
pm->internalClient[l] = '\0';
129
break;
130
case NewEnabled:
131
pm->enabled = (unsigned char)atoui(data, l);
132
break;
133
case NewDescription:
134
memcpy(pm->description, data, l);
135
pm->description[l] = '\0';
136
break;
137
case NewLeaseTime:
138
pm->leaseTime = atoui(data, l);
139
break;
140
default:
141
break;
142
}
143
}
144
145
146
/* Parse the PortMappingList XML document for IGD version 2
147
*/
148
void
149
ParsePortListing(const char * buffer, int bufsize,
150
struct PortMappingParserData * pdata)
151
{
152
struct xmlparser parser;
153
154
memset(pdata, 0, sizeof(struct PortMappingParserData));
155
/* init xmlparser */
156
parser.xmlstart = buffer;
157
parser.xmlsize = bufsize;
158
parser.data = pdata;
159
parser.starteltfunc = startelt;
160
parser.endeltfunc = endelt;
161
parser.datafunc = data;
162
parser.attfunc = 0;
163
parsexml(&parser);
164
}
165
166
void
167
FreePortListing(struct PortMappingParserData * pdata)
168
{
169
struct PortMapping * pm;
170
while((pm = pdata->l_head) != NULL)
171
{
172
/* remove from list */
173
pdata->l_head = pm->l_next;
174
free(pm);
175
}
176
}
177
178
179