check
[oweals/gnunet.git] / src / nat / upnp-minixml.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /*
22  * Code in this file is originally based on the miniupnp library.
23  * Copyright (c) 2005-2009, Thomas BERNARD. All rights reserved.
24  *
25  * Original licence:
26  * 
27  * Redistribution and use in source and binary forms, with or without
28  * modification, are permitted provided that the following conditions are met:
29  * 
30  *   * Redistributions of source code must retain the above copyright notice,
31  *     this list of conditions and the following disclaimer.
32  *   * Redistributions in binary form must reproduce the above copyright notice,
33  *     this list of conditions and the following disclaimer in the documentation
34  *     and/or other materials provided with the distribution.
35  *   * The name of the author may not be used to endorse or promote products
36  *         derived from this software without specific prior written permission.
37  * 
38  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50
51 /**
52  * @file nat/upnp-minixml.c
53  * @brief Simple XML parser used by UPnP
54  *
55  * @author Milan Bouchet-Valat
56  */
57
58 #include "platform.h"
59 #include "gnunet_util_lib.h"
60 #include "upnp-minixml.h"
61
62 /**
63  * Used to parse the argument list.
64  *
65  * @returns GNUNET_OK on success, or GNUNET_SYSERR if the end
66  *   of the xmlbuffer is reached
67  */
68 static int
69 parse_att (struct UPNP_xml_parser_ *p)
70 {
71   const char *att_name;
72   int att_name_len;
73   const char *att_value;
74   int att_value_len;
75   while (p->xml < p->xml_end)
76     {
77       if (*p->xml == '/' || *p->xml == '>')
78         return GNUNET_OK;
79       if (!IS_WHITE_SPACE (*p->xml))
80         {
81           char sep;
82           att_name = p->xml;
83           att_name_len = 0;
84           while (*p->xml != '=' && !IS_WHITE_SPACE (*p->xml))
85             {
86               att_name_len++;
87               p->xml++;
88               if (p->xml >= p->xml_end)
89                 return GNUNET_SYSERR;
90             }
91           while (*(p->xml++) != '=')
92             {
93               if (p->xml >= p->xml_end)
94                 return GNUNET_SYSERR;
95             }
96           while (IS_WHITE_SPACE (*p->xml))
97             {
98               p->xml++;
99               if (p->xml >= p->xml_end)
100                 return GNUNET_SYSERR;
101             }
102           sep = *p->xml;
103           if (sep == '\'' || sep == '\"')
104             {
105               p->xml++;
106               if (p->xml >= p->xml_end)
107                 return GNUNET_SYSERR;
108               att_value = p->xml;
109               att_value_len = 0;
110               while (*p->xml != sep)
111                 {
112                   att_value_len++;
113                   p->xml++;
114                   if (p->xml >= p->xml_end)
115                     return GNUNET_SYSERR;
116                 }
117             }
118           else
119             {
120               att_value = p->xml;
121               att_value_len = 0;
122               while (!IS_WHITE_SPACE (*p->xml)
123                      && *p->xml != '>' && *p->xml != '/')
124                 {
125                   att_value_len++;
126                   p->xml++;
127                   if (p->xml >= p->xml_end)
128                     return GNUNET_SYSERR;
129                 }
130             }
131
132           if (p->att_func)
133             p->att_func (p->cls, att_name, att_name_len, att_value,
134                          att_value_len);
135         }
136       p->xml++;
137     }
138   return GNUNET_SYSERR;
139 }
140
141 /**
142  * Parse the xml stream and call the callback
143  * functions when needed...
144  */
145 void
146 parse_elt (struct UPNP_xml_parser_ *p)
147 {
148   int i;
149   const char *element_name;
150   while (p->xml < (p->xml_end - 1))
151     {
152       /* Element name */
153       if ((p->xml)[0] == '<' && (p->xml)[1] != '?')
154         {
155           i = 0;
156           element_name = ++p->xml;
157           while (!IS_WHITE_SPACE (*p->xml)
158                  && (*p->xml != '>') && (*p->xml != '/'))
159             {
160               i++;
161               p->xml++;
162               if (p->xml >= p->xml_end)
163                 return;
164               /* to ignore namespace : */
165               if (*p->xml == ':')
166                 {
167                   i = 0;
168                   element_name = ++p->xml;
169                 }
170             }
171
172           /* Start of element */
173           if (i > 0)
174             {
175               if (p->start_elt_func)
176                 p->start_elt_func (p->cls, element_name, i);
177               if (parse_att (p) != GNUNET_OK)
178                 return;
179               if (*p->xml != '/')
180                 {
181                   const char *data;
182                   i = 0;
183                   data = ++p->xml;
184                   if (p->xml >= p->xml_end)
185                     return;
186                   while (IS_WHITE_SPACE (*p->xml))
187                     {
188                       p->xml++;
189                       if (p->xml >= p->xml_end)
190                         return;
191                     }
192                   while (*p->xml != '<')
193                     {
194                       i++;
195                       p->xml++;
196                       if (p->xml >= p->xml_end)
197                         return;
198                     }
199                   if (i > 0 && p->data_func)
200                     p->data_func (p->cls, data, i);
201                 }
202             }
203           /* End of element */
204           else if (*p->xml == '/')
205             {
206               i = 0;
207               element_name = ++p->xml;
208               if (p->xml >= p->xml_end)
209                 return;
210               while ((*p->xml != '>'))
211                 {
212                   i++;
213                   p->xml++;
214                   if (p->xml >= p->xml_end)
215                     return;
216                 }
217               if (p->end_elt_func)
218                 p->end_elt_func (p->cls, element_name, i);
219               p->xml++;
220             }
221         }
222       else
223         {
224           p->xml++;
225         }
226     }
227 }
228
229 /**
230  * Parse XML content according to the values stored in the parser struct.
231  * The parser must be initialized before calling this function
232  */
233 void
234 UPNP_parse_xml_ (struct UPNP_xml_parser_ *parser)
235 {
236   parser->xml = parser->xml_start;
237   parser->xml_end = parser->xml_start + parser->xml_size;
238   parse_elt (parser);
239 }