1 /*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (c) 2012 France Telecom All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * - Neither name of Intel Corporation nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ******************************************************************************/
32
33
34 /*!
35 * \file
36 */
37
38 #include "autoconfig.h"
39
40 #include "ixmlparser.h"
41
42
43 #include "ixmldebug.h"
44
45
46 #include <assert.h>
47 #include <stddef.h> /* for ptrdiff_t */
48 #include <stdio.h>
49 #include <stdlib.h> /* for free(), malloc() */
50 #include <string.h>
51
52
53 #ifdef _WIN32
54 #define strncasecmp strnicmp
55 #endif
56
57
58 static char g_error_char = '\0';
59 #ifdef IXML_HAVE_SCRIPTSUPPORT
60 static IXML_BeforeFreeNode_t Before_Free_callback;
61 #endif
62
63
64 static const char LESSTHAN = '<';
65 static const char GREATERTHAN = '>';
66 static const char SLASH = '/';
67 static const char EQUALS = '=';
68 static const char QUOTE = '\"';
69 static const char SINGLEQUOTE = '\'';
70
71
72 static const char *WHITESPACE = "\n\t\r ";
73 static const char *COMPLETETAG = "/>";
74 static const char *ENDTAG = "</";
75 static const char *XMLDECL = "<?xml ";
76 static const char *XMLDECL2 = "<?xml?";
77 static const char *BEGIN_COMMENT = "<!--";
78 static const char *END_COMMENT = "-->";
79 static const char *BEGIN_PI = "<?";
80 static const char *END_PI = "?>";
81 static const char *BEGIN_DOCTYPE = "<!DOCTYPE";
82 static const char *CDSTART = "<![CDATA[";
83 static const char *CDEND = "]]>";
84 static const char *DEC_NUMBERS = "0123456789";
85 static const char *HEX_NUMBERS = "0123456789ABCDEFabcdef";
86
87
88 typedef struct char_info {
89 unsigned short l;
90 unsigned short h;
91 } char_info_t;
92
93
94 typedef char utf8char[8];
95
96
97 /*!
98 * \brief The letter table contains all characters in XML 1.0 plus ":", "_" and
99 * ideographic.
100 *
101 * This table contains all the characters that an element name can start with.
102 * See XML 1.0 (2nd Edition) for more details.
103 */
104 static char_info_t Letter[] = {
105 {0x003A, 0x003A}, /* character ":" */
106 {0x0041, 0x005A},
107 {0x005F, 0x005F}, /* character "_" */
108 {0x0061, 0x007A}, {0x00C0, 0x00D6}, {0x00D8, 0x00F6}, {0x00F8, 0x00FF},
109 {0x0100, 0x0131}, {0x0134, 0x013E}, {0x0141, 0x0148}, {0x014A, 0x017E},
110 {0x0180, 0x01C3}, {0x01CD, 0x01F0}, {0x01F4, 0x01F5}, {0x01FA, 0x0217},
111 {0x0250, 0x02A8}, {0x02BB, 0x02C1}, {0x0386, 0x0386}, {0x0388, 0x038A},
112 {0x038C, 0x038C}, {0x038E, 0x03A1}, {0x03A3, 0x03CE}, {0x03D0, 0x03D6},
113 {0x03DA, 0x03DA},
114 {0x03DC, 0x03DC}, {0x03DE, 0x03DE}, {0x03E0, 0x03E0}, {0x03E2, 0x03F3},
115 {0x0401, 0x040C}, {0x040E, 0x044F}, {0x0451, 0x045C}, {0x045E, 0x0481},
116 {0x0490, 0x04C4}, {0x04C7, 0x04C8}, {0x04CB, 0x04CC}, {0x04D0, 0x04EB},
117 {0x04EE, 0x04F5}, {0x04F8, 0x04F9}, {0x0531, 0x0556}, {0x0559, 0x0559},
118 {0x0561, 0x0586}, {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x0621, 0x063A},
119 {0x0641, 0x064A}, {0x0671, 0x06B7}, {0x06BA, 0x06BE}, {0x06C0, 0x06CE},
120 {0x06D0, 0x06D3}, {0x06D5, 0x06D5}, {0x06E5, 0x06E6}, {0x0905, 0x0939},
121 {0x093D, 0x093D}, {0x0958, 0x0961}, {0x0985, 0x098C}, {0x098F, 0x0990},
122 {0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9},
123 {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09F0, 0x09F1}, {0x0A05, 0x0A0A},
124 {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33},
125 {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
126 {0x0A72, 0x0A74}, {0x0A85, 0x0A8B}, {0x0A8D, 0x0A8D}, {0x0A8F, 0x0A91},
127 {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9},
128 {0x0ABD, 0x0ABD}, {0x0AE0, 0x0AE0}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10},
129 {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B36, 0x0B39},
130 {0x0B3D, 0x0B3D}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B85, 0x0B8A},
131 {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C},
132 {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB5},
133 {0x0BB7, 0x0BB9}, {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28},
134 {0x0C2A, 0x0C33}, {0x0C35, 0x0C39}, {0x0C60, 0x0C61}, {0x0C85, 0x0C8C},
135 {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
136 {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, {0x0D05, 0x0D0C}, {0x0D0E, 0x0D10},
137 {0x0D12, 0x0D28}, {0x0D2A, 0x0D39}, {0x0D60, 0x0D61}, {0x0E01, 0x0E2E},
138 {0x0E30, 0x0E30}, {0x0E32, 0x0E33}, {0x0E40, 0x0E45}, {0x0E81, 0x0E82},
139 {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, {0x0E8D, 0x0E8D},
140 {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5},
141 {0x0EA7, 0x0EA7}, {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EAE}, {0x0EB0, 0x0EB0},
142 {0x0EB2, 0x0EB3}, {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0F40, 0x0F47},
143 {0x0F49, 0x0F69}, {0x10A0, 0x10C5}, {0x10D0, 0x10F6}, {0x1100, 0x1100},
144 {0x1102, 0x1103}, {0x1105, 0x1107}, {0x1109, 0x1109}, {0x110B, 0x110C},
145 {0x110E, 0x1112}, {0x113C, 0x113C}, {0x113E, 0x113E}, {0x1140, 0x1140},
146 {0x114C, 0x114C}, {0x114E, 0x114E}, {0x1150, 0x1150}, {0x1154, 0x1155},
147 {0x1159, 0x1159}, {0x115F, 0x1161}, {0x1163, 0x1163}, {0x1165, 0x1165},
148 {0x1167, 0x1167}, {0x1169, 0x1169}, {0x116D, 0x116E}, {0x1172, 0x1173},
149 {0x1175, 0x1175}, {0x119E, 0x119E}, {0x11A8, 0x11A8}, {0x11AB, 0x11AB},
150 {0x11AE, 0x11AF}, {0x11B7, 0x11B8}, {0x11BA, 0x11BA}, {0x11BC, 0x11C2},
151 {0x11EB, 0x11EB}, {0x11F0, 0x11F0}, {0x11F9, 0x11F9}, {0x1E00, 0x1E9B},
152 {0x1EA0, 0x1EF9}, {0x1F00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
153 {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
154 {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC},
155 {0x1FBE, 0x1FBE}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3},
156 {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC},
157 {0x2126, 0x2126}, {0x212A, 0x212B}, {0x212E, 0x212E}, {0x2180, 0x2182},
158 {0x3007, 0x3007}, {0x3021, 0x3029}, /* these two are ideographic */
159 {0x3041, 0x3094}, {0x30A1, 0x30FA}, {0x3105, 0x312C},
160 {0x4E00, 0x9FA5}, /* ideographic */
161 {0xAC00, 0xD7A3}
162 };
163
164
165 /*!
166 * \brief The size of the letter table array.
167 */
168 #define LETTERTABLESIZE (sizeof(Letter)/sizeof(Letter[0]))
169
170
171 /*!
172 * \brief The NameChar table contains CombiningChar, Extender, Digit,
173 * '-', '.', less '_', ':'
174 *
175 * NameChar ::= Digit | '-' | '.' | CombiningChar | Extender
176 * See XML 1.0 2nd Edition
177 */
178 static char_info_t NameChar[] = {
179 {0x002D, 0x002D}, /* character "-" */
180 {0x002E, 0x002E}, /* character "." */
181 {0x0030, 0x0039}, /* digit */
182 {0x00B7, 0x00B7}, {0x02D0, 0x02D0}, {0x02D1, 0x02D1}, /* extended */
183 {0x0300, 0x0345}, {0x0360, 0x0361},
184 {0x0387, 0x0387}, /* extended */
185 {0x0483, 0x0486}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
186 {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C4},
187 {0x0640, 0x0640}, /* extended */
188 {0x064B, 0x0652},
189 {0x0660, 0x0669}, /* digit */
190 {0x0670, 0x0670},
191 {0x06D6, 0x06DC}, {0x06DD, 0x06DF}, {0x06E0, 0x06E4}, {0x06E7, 0x06E8},
192 {0x06EA, 0x06ED},
193 {0x06F0, 0x06F9}, /* digit */
194 {0x0901, 0x0903}, {0x093C, 0x093C},
195 {0x093E, 0x094C}, {0x094D, 0x094D}, {0x0951, 0x0954}, {0x0962, 0x0963},
196 {0x0966, 0x096F}, /* digit */
197 {0x0981, 0x0983}, {0x09BC, 0x09BC}, {0x09BE, 0x09BE},
198 {0x09BF, 0x09BF}, {0x09C0, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CD},
199 {0x09D7, 0x09D7}, {0x09E2, 0x09E3},
200 {0x09E6, 0x09EF}, /* digit */
201 {0x0A02, 0x0A02},
202 {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A3E}, {0x0A3F, 0x0A3F}, {0x0A40, 0x0A42},
203 {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
204 {0x0A66, 0x0A6F}, /* digit */
205 {0x0A70, 0x0A71},
206 {0x0A81, 0x0A83}, {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9},
207 {0x0ACB, 0x0ACD},
208 {0x0AE6, 0x0AEF}, /* digit */
209 {0x0B01, 0x0B03}, {0x0B3C, 0x0B3C},
210 {0x0B3E, 0x0B43}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57},
211 {0x0B66, 0x0B6F}, /* digit */
212 {0x0B82, 0x0B83}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8},
213 {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7},
214 {0x0BE7, 0x0BEF}, /* digit */
215 {0x0C01, 0x0C03},
216 {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
217 {0x0C66, 0x0C6F}, /* digit */
218 {0x0C82, 0x0C83}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8},
219 {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6},
220 {0x0CE6, 0x0CEF}, /* digit */
221 {0x0D02, 0x0D03},
222 {0x0D3E, 0x0D43}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57},
223 {0x0D66, 0x0D6F}, /* digit */
224 {0x0E31, 0x0E31}, {0x0E34, 0x0E3A},
225 {0x0E46, 0x0E46}, /* extended */
226 {0x0E47, 0x0E4E},
227 {0x0E50, 0x0E59}, /* digit */
228 {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9},
229 {0x0EBB, 0x0EBC},
230 {0x0EC6, 0x0EC6}, /* extended */
231 {0x0EC8, 0x0ECD},
232 {0x0ED0, 0x0ED9}, /* digit */
233 {0x0F18, 0x0F19},
234 {0x0F20, 0x0F29}, /* digit */
235 {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
236 {0x0F39, 0x0F39}, {0x0F3E, 0x0F3E}, {0x0F3F, 0x0F3F}, {0x0F71, 0x0F84},
237 {0x0F86, 0x0F8B}, {0x0F90, 0x0F95}, {0x0F97, 0x0F97}, {0x0F99, 0x0FAD},
238 {0x0FB1, 0x0FB7}, {0x0FB9, 0x0FB9}, {0x20D0, 0x20DC}, {0x20E1, 0x20E1},
239 {0x3005, 0x3005}, /* extended */
240 {0x302A, 0x302F},
241 {0x3031, 0x3035}, /* extended */
242 {0x3099, 0x3099}, {0x309A, 0x309A}, /* combining char */
243 {0x309D, 0x309E}, {0x30FC, 0x30FE} /* extended */
244 };
245
246
247 /*!
248 * \brief The name char table array size.
249 */
250 #define NAMECHARTABLESIZE (sizeof(NameChar)/sizeof(NameChar[0]))
251
252
253 /*!
254 * \brief Frees one ElementStack item.
255 */
Parser_freeElementStackItem(IXML_ElementStack * pItem)256 static void Parser_freeElementStackItem(
257 /*! [in] The element stack item to free. */
258 IXML_ElementStack *pItem)
259 {
260 assert( pItem != NULL );
261 if( pItem->element != NULL ) {
262 free( pItem->element );
263 pItem->element = NULL;
264 }
265 if( pItem->namespaceUri != NULL ) {
266 free( pItem->namespaceUri );
267 pItem->namespaceUri = NULL;
268 }
269 if( pItem->prefix != NULL ) {
270 free( pItem->prefix );
271 pItem->prefix = NULL;
272 }
273 }
274
275
276 /*!
277 * \brief Frees namespaceURI item.
278 */
Parser_freeNsURI(IXML_NamespaceURI * pNsURI)279 static void Parser_freeNsURI(
280 /*! [in] The name space URI item to free. */
281 IXML_NamespaceURI *pNsURI)
282 {
283 assert( pNsURI != NULL );
284 if( pNsURI->nsURI != NULL ) {
285 free( pNsURI->nsURI );
286 }
287 if( pNsURI->prefix != NULL ) {
288 free( pNsURI->prefix );
289 }
290 }
291
292
293 /*!
294 * \brief Frees all temporary memory allocated by xmlparser.
295 */
Parser_free(Parser * xmlParser)296 static void Parser_free(
297 /*! [in] The XML parser. */
298 Parser *xmlParser)
299 {
300 IXML_ElementStack *pElement;
301 IXML_ElementStack *pNextElement;
302 IXML_NamespaceURI *pNsURI;
303 IXML_NamespaceURI *pNextNsURI;
304
305 if( xmlParser == NULL ) {
306 return;
307 }
308
309 if( xmlParser->dataBuffer != NULL ) {
310 free( xmlParser->dataBuffer );
311 }
312
313 ixml_membuf_destroy( &( xmlParser->tokenBuf ) );
314 ixml_membuf_destroy( &( xmlParser->lastElem ) );
315
316 pElement = xmlParser->pCurElement;
317 while( pElement != NULL ) {
318 Parser_freeElementStackItem( pElement );
319
320 pNsURI = pElement->pNsURI;
321 while( pNsURI != NULL ) {
322 pNextNsURI = pNsURI->nextNsURI;
323 Parser_freeNsURI( pNsURI );
324 free( pNsURI );
325 pNsURI = pNextNsURI;
326 }
327
328 pNextElement = pElement->nextElement;
329 free( pElement );
330 pElement = pNextElement;
331 }
332
333 free( xmlParser );
334 }
335
336
337 /*!
338 * \brief Skips document type declaration
339 */
Parser_skipDocType(char ** pstr)340 static int Parser_skipDocType(
341 /*! [in,out] The pointer to the skipped point. */
342 char **pstr)
343 {
344 char *pCur = *pstr;
345 /* default there is no nested < */
346 char *pNext = NULL;
347 int num = 1;
348
349 assert( ( *pstr ) != NULL );
350 if( *pstr == NULL ) {
351 return IXML_FAILED;
352 }
353
354 while( ( pCur != NULL ) && ( num != 0 ) && ( *pCur != 0 ) ) {
355 if( *pCur == '<' ) {
356 num++;
357 } else if( *pCur == '>' ) {
358 num--;
359 } else if( *pCur == '"' ) {
360 pNext = strchr( pCur + 1, '"' );
361 if( pNext == NULL ) {
362 return IXML_SYNTAX_ERR;
363 }
364
365 pCur = pNext;
366 }
367
368 pCur++;
369 }
370
371 if( num == 0 ) {
372 *pstr = pCur;
373 return IXML_SUCCESS;
374 } else {
375 return IXML_SYNTAX_ERR;
376 }
377 }
378
379
380 /*!
381 * \brief Skips all characters in the string until it finds the skip key.
382 * Then it skips the skip key and returns.
383 */
Parser_skipString(char ** pstrSrc,const char * strSkipKey)384 static int Parser_skipString(
385 /*! [in,out] The pointer to the skipped point. */
386 char **pstrSrc,
387 /*! [in] The skip key. */
388 const char *strSkipKey)
389 {
390 if( !( *pstrSrc ) || !strSkipKey ) {
391 return IXML_FAILED;
392 }
393
394 while( ( **pstrSrc )
395 && strncmp( *pstrSrc, strSkipKey,
396 strlen( strSkipKey ) ) != 0 ) {
397 ( *pstrSrc )++;
398 }
399
400 if( **pstrSrc == '\0' ) {
401 return IXML_SYNTAX_ERR;
402 }
403 *pstrSrc = *pstrSrc + strlen( strSkipKey );
404
405 return IXML_SUCCESS;
406 }
407
408
409 /*!
410 * \brief Skip white spaces.
411 */
Parser_skipWhiteSpaces(Parser * xmlParser)412 static void Parser_skipWhiteSpaces(
413 /*! [in] The XML parser. */
414 Parser *xmlParser)
415 {
416 while( ( *( xmlParser->curPtr ) != 0 ) &&
417 ( strchr( WHITESPACE, ( int ) *( xmlParser->curPtr ) ) != NULL ) ) {
418 xmlParser->curPtr++;
419 }
420 }
421
422
423 /*!
424 * \brief Skips XML declarations.
425 */
Parser_skipXMLDecl(Parser * xmlParser)426 static int Parser_skipXMLDecl(
427 /*! [in,out] The XML parser. */
428 Parser *xmlParser)
429 {
430 int rc = IXML_FAILED;
431
432 assert( xmlParser );
433 if( xmlParser == NULL ) {
434 return rc;
435 }
436
437 rc = Parser_skipString( &( xmlParser->curPtr ), END_PI );
438 Parser_skipWhiteSpaces( xmlParser );
439 return rc;
440 }
441
442
443 /*!
444 * \brief Skips all characters in the string until it finds the skip key.
445 * Then it skips the skip key and returns.
446 */
Parser_skipComment(char ** pstrSrc)447 static int Parser_skipComment(
448 /*! [in,out] The pointer to the skipped point. */
449 char **pstrSrc)
450 {
451 char *pStrFound = NULL;
452
453 assert( ( *pstrSrc ) != NULL );
454 if( *pstrSrc == NULL ) {
455 return IXML_FAILED;
456 }
457
458 pStrFound = strstr( *pstrSrc, END_COMMENT );
459 if( ( pStrFound != NULL ) && ( pStrFound != *pstrSrc ) &&
460 ( *( pStrFound - 1 ) != '-' ) ) {
461 *pstrSrc = pStrFound + strlen( END_COMMENT );
462 } else {
463 return IXML_SYNTAX_ERR;
464 }
465
466 return IXML_SUCCESS;
467 }
468
469
470 /*!
471 * \brief Skip comment, PI and white space.
472 */
Parser_skipMisc(Parser * xmlParser)473 static int Parser_skipMisc(
474 /*! [in] The XML parser. */
475 Parser *xmlParser)
476 {
477 int rc = IXML_SUCCESS;
478 int done = 0;
479
480 while( ( done == 0 ) && ( rc == IXML_SUCCESS ) ) {
481 if( strncasecmp( xmlParser->curPtr, ( char * )BEGIN_COMMENT, strlen( BEGIN_COMMENT ) ) == 0 ) {
482 /* <!-- */
483 rc = Parser_skipComment( &( xmlParser->curPtr ) );
484
485 } else if (strncasecmp(xmlParser->curPtr, (char *)XMLDECL , strlen(XMLDECL )) == 0 ||
486 strncasecmp(xmlParser->curPtr, (char *)XMLDECL2, strlen(XMLDECL2)) == 0) {
487 /* <?xml or <?xml? */
488 rc = IXML_SYNTAX_ERR;
489 } else if (strncasecmp(xmlParser->curPtr, (char *)BEGIN_PI, strlen(BEGIN_PI)) == 0) {
490 /* <? */
491 rc = Parser_skipString(&xmlParser->curPtr, END_PI);
492 } else {
493 done = 1;
494 }
495 Parser_skipWhiteSpaces(xmlParser);
496 }
497
498 return rc;
499 }
500
501
502 /*!
503 * \brief Skip prolog.
504 */
Parser_skipProlog(Parser * xmlParser)505 static int Parser_skipProlog(
506 /*! [in,out] The XML parser. */
507 Parser *xmlParser)
508 {
509 int rc = IXML_SUCCESS;
510
511 assert( xmlParser != NULL );
512 if( xmlParser == NULL ) {
513 return IXML_FAILED;
514 }
515
516 Parser_skipWhiteSpaces( xmlParser );
517
518 if( strncmp( xmlParser->curPtr, ( char * )XMLDECL, strlen( XMLDECL ) ) == 0 ) {
519 /* <?xml */
520 rc = Parser_skipXMLDecl( xmlParser );
521 if( rc != IXML_SUCCESS ) {
522 return rc;
523 }
524 }
525
526 rc = Parser_skipMisc( xmlParser );
527 if( ( rc == IXML_SUCCESS ) &&
528 strncmp( xmlParser->curPtr, ( char * )BEGIN_DOCTYPE, strlen( BEGIN_DOCTYPE ) ) == 0 ) {
529 /* <! DOCTYPE */
530 xmlParser->curPtr++;
531 rc = Parser_skipDocType( &( xmlParser->curPtr ) );
532 }
533
534 if( rc == IXML_SUCCESS ) {
535 rc = Parser_skipMisc( xmlParser );
536 }
537
538 return rc;
539 }
540
541
542 /*!
543 * \brief Set the last element to be the given string.
544 */
Parser_setLastElem(Parser * xmlParser,const char * s)545 static int Parser_setLastElem(
546 /*! [in] The XML parser. */
547 Parser *xmlParser,
548 /*! [in] The string to copy from. */
549 const char *s)
550 {
551 int rc;
552
553 if( ( xmlParser == NULL ) || ( s == NULL ) ) {
554 return IXML_FAILED;
555 }
556
557 rc = ixml_membuf_assign_str( &( xmlParser->lastElem ), s );
558 return rc;
559 }
560
561
562 /*!
563 * \brief Clear token buffer.
564 */
Parser_clearTokenBuf(Parser * xmlParser)565 static void Parser_clearTokenBuf(
566 /*! [in] The XML parser. */
567 Parser *xmlParser)
568 {
569 ixml_membuf_destroy( &( xmlParser->tokenBuf ) );
570 }
571
572
573 /*!
574 * \brief In UTF-8, characters are encoded using sequences of 1 to 6 octets.
575 * This functions will return a UTF-8 character value and its octets number.
576 *
577 * \return The UTF-8 character converted to an int (32 bits).
578 */
Parser_UTF8ToInt(const char * ss,ptrdiff_t * len)579 static int Parser_UTF8ToInt(
580 /*! [in] The pointer to the character to encode. */
581 const char *ss,
582 /*! [out] The number of octets of the UTF-8 encoding of this character. */
583 ptrdiff_t *len)
584 {
585 const unsigned char *s = (const unsigned char *)ss;
586 int c = *s;
587
588 if (c <= 127) {
589 /* if c<=127, c is just the character. */
590 *len = 1;
591 return c;
592 } else if ((c & 0xE0) == 0xC0 &&
593 (s[1] & 0xc0) == 0x80) {
594 /* a sequence of 110xxxxx and 10xxxxxx? */
595 *len = 2;
596 return ((c & 0x1f) << 6) |
597 (s[1] & 0x3f);
598 } else if ((c & 0xF0) == 0xE0 &&
599 (s[1] & 0xc0) == 0x80 &&
600 (s[2] & 0xc0) == 0x80) {
601 /* a sequence of 1110xxxx,10xxxxxx and 10xxxxxx ? */
602 *len = 3;
603 return ((c & 0x0f) << 12) |
604 ((s[1] & 0x3f) << 6) |
605 (s[2] & 0x3f);
606 } else if ((c & 0xf8) == 0xf0 &&
607 (s[1] & 0xc0) == 0x80 &&
608 (s[2] & 0xc0) == 0x80 &&
609 (s[3] & 0xc0) == 0x80) {
610 /* a sequence of 11110xxx,10xxxxxx,10xxxxxx and 10xxxxxx ? */
611 *len = 4;
612 return ((c & 0x07) << 18) |
613 ((s[1] & 0x3f) << 12) |
614 ((s[2] & 0x3f) << 6) |
615 (s[3] & 0x3f);
616 } else if ((c & 0xfc) == 0xf8 &&
617 (s[1] & 0xc0) == 0x80 &&
618 (s[2] & 0xc0) == 0x80 &&
619 (s[3] & 0xc0) == 0x80 &&
620 (s[4] & 0xc0) == 0x80) {
621 /* a sequence of 111110xx,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx ? */
622 *len = 5;
623 return ((c & 0x03) << 24) |
624 ((s[1] & 0x3f) << 18) |
625 ((s[2] & 0x3f) << 12) |
626 ((s[3] & 0x3f) << 6) |
627 (s[4] & 0x3f);
628 } else if ((c & 0xfe) == 0xfc &&
629 (s[1] & 0xc0) == 0x80 &&
630 (s[2] & 0xc0) == 0x80 &&
631 (s[3] & 0xc0) == 0x80 &&
632 (s[4] & 0xc0) == 0x80 &&
633 (s[5] & 0xc0) == 0x80) {
634 /* a sequence of 1111110x,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx and 10xxxxxx ? */
635 *len = 6;
636 return ((c & 0x01) << 30) |
637 ((s[1] & 0x3f) << 24) |
638 ((s[2] & 0x3f) << 18) |
639 ((s[3] & 0x3f) << 12) |
640 ((s[4] & 0x3f) << 6) |
641 (s[5] & 0x3f);
642 } else {
643 /* none of above, error */
644 int ret = 0;
645 int line = __LINE__;
646 if (g_error_char) {
647 *len = 1;
648 ret = g_error_char;
649 } else {
650 *len = 0;
651 ret = -1;
652 }
653 IxmlPrintf(__FILE__, line, "Parser_UTF8ToInt", "Error %d\n", ret);
654 return ret;
655 }
656 }
657
658
659 /*!
660 * \brief Will determine whether character c is in the table of tbl (either
661 * Letter table or NameChar table).
662 *
663 * \return 1 or 0.
664 */
Parser_isCharInTable(int c,char_info_t * tbl,int sz)665 static int Parser_isCharInTable(
666 /*! [in] Character to check. */
667 int c,
668 /*! [in] Table to use. */
669 char_info_t *tbl,
670 /*! [in] Size of the table. */
671 int sz)
672 {
673 int t = 0;
674 int b = sz - 1;
675 int m;
676
677 while (t <= b) {
678 m = ( t + b ) / 2;
679 if (c < tbl[m].l) {
680 b = m - 1;
681 } else if (c > tbl[m].h) {
682 t = m + 1;
683 } else {
684 return 1;
685 }
686 }
687
688 return 0;
689 }
690
691
692 /*!
693 * \brief Check whether c (int) is in LetterTable or NameCharTable.
694 */
Parser_isNameChar(int c,int bNameChar)695 static int Parser_isNameChar(
696 /*! [in] The character to check. */
697 int c,
698 /*! [in] 1 if you also want to check in the NameChar table. */
699 int bNameChar)
700 {
701 if (Parser_isCharInTable(c, Letter, (int)LETTERTABLESIZE)) {
702 return 1;
703 }
704
705 if (bNameChar &&
706 Parser_isCharInTable(c, NameChar, (int)NAMECHARTABLESIZE)) {
707 return 1;
708 }
709
710 return 0;
711 }
712
713
714 /*!
715 * \brief see XML 1.0 (2nd Edition) 2.2.
716 */
Parser_isXmlChar(int c)717 static int Parser_isXmlChar(
718 /*! [in] The character to check. */
719 int c)
720 {
721 return
722 c == 0x9 || c == 0xA || c == 0xD ||
723 (c >= 0x20 && c <= 0xD7FF) ||
724 (c >= 0xE000 && c <= 0xFFFD) ||
725 (c >= 0x10000 && c <= 0x10FFFF);
726 }
727
728
729 /*!
730 * \brief Returns next char value and its length.
731 */
Parser_getChar(const char * src,ptrdiff_t * cLen)732 static int Parser_getChar(
733 /*! [in] . */
734 const char *src,
735 /*! [in,out] . */
736 ptrdiff_t *cLen)
737 {
738 int ret = -1;
739 int line = 0;
740 const char *pnum;
741 int sum;
742 char c;
743 int i;
744
745 if( src == NULL || cLen == NULL ) {
746 line = __LINE__;
747 ret = -1;
748 goto ExitFunction;
749 }
750
751 *cLen = 0;
752 if (*src != '&') {
753 if (*src > 0 && Parser_isXmlChar((int)*src)) {
754 *cLen = 1;
755 ret = *src;
756 goto ExitFunction;
757 }
758
759 i = Parser_UTF8ToInt(src, cLen);
760 if (!Parser_isXmlChar(i)) {
761 line = __LINE__;
762 ret = g_error_char ? g_error_char : -1;
763 goto ExitFunction;
764 }
765
766 line = __LINE__;
767 ret = i;
768 goto ExitFunction;
769 } else if (strncasecmp(src, QUOT, strlen(QUOT)) == 0) {
770 *cLen = (int)strlen(QUOT);
771 ret = '"';
772 goto ExitFunction;
773 } else if (strncasecmp(src, LT, strlen(LT)) == 0) {
774 *cLen = (int)strlen(LT);
775 ret = '<';
776 goto ExitFunction;
777 } else if (strncasecmp(src, GT, strlen(GT)) == 0) {
778 *cLen = (int)strlen(GT);
779 ret = '>';
780 goto ExitFunction;
781 } else if (strncasecmp(src, APOS, strlen(APOS)) == 0) {
782 *cLen = (int)strlen(APOS);
783 ret = '\'';
784 goto ExitFunction;
785 } else if (strncasecmp(src, AMP, strlen(AMP)) == 0) {
786 *cLen = (int)strlen(AMP);
787 ret = '&';
788 goto ExitFunction;
789 } else if (strncasecmp(src, ESC_HEX, strlen(ESC_HEX)) == 0) {
790 /* Read in escape characters of type &#xnn where nn is a hexadecimal value */
791 pnum = src + strlen( ESC_HEX );
792 sum = 0;
793 while (strchr(HEX_NUMBERS, (int)*pnum) != 0) {
794 c = *pnum;
795 if (c <= '9') {
796 sum = sum * 16 + ( c - '0' );
797 } else if( c <= 'F' ) {
798 sum = sum * 16 + ( c - 'A' + 10 );
799 } else {
800 sum = sum * 16 + ( c - 'a' + 10 );
801 }
802 pnum++;
803 }
804 if (pnum == src || *pnum != ';' || !Parser_isXmlChar(sum)) {
805 line = __LINE__;
806 goto fail_entity;
807 }
808 *cLen = pnum - src + 1;
809 ret = sum;
810 goto ExitFunction;
811 } else if (strncasecmp(src, ESC_DEC, strlen(ESC_DEC)) == 0) {
812 /* Read in escape characters of type &#nn where nn is a decimal value */
813 pnum = src + strlen(ESC_DEC);
814 sum = 0;
815 while (strchr(DEC_NUMBERS, (int)*pnum) != 0) {
816 sum = sum * 10 + ( *pnum - '0' );
817 pnum++;
818 }
819 if( ( pnum == src ) || *pnum != ';' || !Parser_isXmlChar( sum ) ) {
820 line = __LINE__;
821 goto fail_entity;
822 }
823 *cLen = pnum - src + 1;
824 ret = sum;
825 goto ExitFunction;
826 }
827
828 fail_entity:
829 if (g_error_char) {
830 *cLen = 1;
831 ret = '&';
832 goto ExitFunction;
833 }
834 ret = -1;
835
836 ExitFunction:
837 if (ret == -1 || (g_error_char && ret == g_error_char)) {
838 IxmlPrintf(__FILE__, line, "Parser_getChar", "Error %d\n", ret);
839 }
840
841 return ret;
842 }
843
844
845 /*!
846 * \brief Appends c to token buffer.
847 */
Parser_appendTokBufChar(Parser * xmlParser,char c)848 static int Parser_appendTokBufChar(
849 /*! [in] The XML parser. */
850 Parser *xmlParser,
851 /*! [in] The character to append. */
852 char c)
853 {
854 int rc;
855
856 rc = ixml_membuf_append( &( xmlParser->tokenBuf ), &c );
857 return rc;
858 }
859
860
861 /*!
862 * \brief Encodes a character to its UTF-8 character string, and return its length.
863 *
864 * \return The length of the encoded string in bytes.
865 */
Parser_intToUTF8(int c,utf8char s)866 static int Parser_intToUTF8(
867 /*! [in] The character to encode. */
868 int c,
869 /*! [out] The resultant UTF-8 encoded string. */
870 utf8char s)
871 {
872 if (c < 0)
873 return 0;
874
875 if (c <= 127) {
876 s[0] = (char)c;
877 s[1] = (char)0;
878 return 1;
879 } else if (c <= 0x07FF) {
880 /* 0x0080 < c <= 0x07FF */
881 s[0] = (char)(0xC0 | (c >> 6 ) );
882 s[1] = (char)(0x80 | ( c & 0x3f));
883 s[2] = (char)0;
884 return 2;
885 } else if (c <= 0xFFFF) {
886 /* 0x0800 < c <= 0xFFFF */
887 s[0] = (char)(0xE0 | (c >> 12) );
888 s[1] = (char)(0x80 | ((c >> 6 ) & 0x3f));
889 s[2] = (char)(0x80 | ( c & 0x3f));
890 s[3] = (char)0;
891 return 3;
892 } else if (c <= 0x1FFFFF) {
893 /* 0x10000 < c <= 0x1FFFFF */
894 s[0] = (char)(0xF0 | (c >> 18) );
895 s[1] = (char)(0x80 | ((c >> 12) & 0x3f));
896 s[2] = (char)(0x80 | ((c >> 6 ) & 0x3f));
897 s[3] = (char)(0x80 | ( c & 0x3f));
898 s[4] = (char)0;
899 return 4;
900 } else if (c <= 0x3FFFFFF) {
901 /* 0x200000 < c <= 3FFFFFF */
902 s[0] = (char)(0xF8 | (c >> 24) );
903 s[1] = (char)(0x80 | ((c >> 18) & 0x3f));
904 s[2] = (char)(0x80 | ((c >> 12) & 0x3f));
905 s[3] = (char)(0x80 | ((c >> 6 ) & 0x3f));
906 s[4] = (char)(0x80 | ( c & 0x3f));
907 s[5] = (char)0;
908 return 5;
909 } else if (c <= 0x7FFFFFFF) {
910 /* 0x4000000 < c <= 7FFFFFFF */
911 s[0] = (char)(0xFC | (c >> 30) );
912 s[1] = (char)(0x80 | ((c >> 24) & 0x3f));
913 s[2] = (char)(0x80 | ((c >> 18) & 0x3f));
914 s[3] = (char)(0x80 | ((c >> 12) & 0x3f));
915 s[4] = (char)(0x80 | ((c >> 6 ) & 0x3f));
916 s[5] = (char)(0x80 | ( c & 0x3f));
917 s[6] = (char)0;
918 return 6;
919 } else {
920 /* illegal */
921 return 0;
922 }
923 }
924
925
926 /*!
927 * \brief Appends string s to token buffer.
928 */
Parser_appendTokBufStr(Parser * xmlParser,const char * s)929 static int Parser_appendTokBufStr(
930 /*! [in] The XML parser. */
931 Parser *xmlParser,
932 /*! [in] The string to append. */
933 const char *s)
934 {
935 int rc = IXML_SUCCESS;
936
937 if( s != NULL ) {
938 rc = ixml_membuf_append_str( &( xmlParser->tokenBuf ), s );
939 }
940
941 return rc;
942 }
943
944
945 /*!
946 * \brief Copy string in src into xml parser token buffer
947 */
Parser_copyToken(Parser * xmlParser,const char * src,ptrdiff_t len)948 static int Parser_copyToken(
949 /*! [in] The XML parser. */
950 Parser *xmlParser,
951 /*! [in] The string to copy from. */
952 const char *src,
953 /*! [in] The lenght to copy. */
954 ptrdiff_t len)
955 {
956 int ret = IXML_SUCCESS;
957 int line = 0;
958 int i;
959 int c;
960 ptrdiff_t cl;
961 const char *psrc;
962 const char *pend;
963 utf8char uch;
964
965 if (!src || len <= 0) {
966 line = __LINE__;
967 ret = IXML_FAILED;
968 goto ExitFunction;
969 }
970
971 psrc = src;
972 pend = src + len;
973
974 while (psrc < pend) {
975 c = Parser_getChar(psrc, &cl);
976 if (c <= 0) {
977 line = __LINE__;
978 ret = IXML_FAILED;
979 goto ExitFunction;
980 }
981
982 if (cl == 1) {
983 Parser_appendTokBufChar(xmlParser, (char)c);
984 psrc++;
985 } else {
986 i = Parser_intToUTF8(c, uch);
987 if (i == 0) {
988 line = __LINE__;
989 ret = IXML_FAILED;
990 goto ExitFunction;
991 }
992 Parser_appendTokBufStr(xmlParser, uch);
993 psrc += cl;
994 }
995 }
996
997 if (psrc > pend) {
998 line = __LINE__;
999 ret = IXML_FAILED;
1000 goto ExitFunction;
1001 }
1002
1003 ExitFunction:
1004 if (ret != IXML_SUCCESS) {
1005 IxmlPrintf(__FILE__, line, "Parser_copyToken", "Error %d\n", ret);
1006 }
1007
1008 return ret;
1009 }
1010
1011
1012 /*!
1013 * \brief Return the length of next token in tokenBuff.
1014 */
Parser_getNextToken(Parser * xmlParser)1015 static ptrdiff_t Parser_getNextToken(
1016 /*! [in] The XML parser. */
1017 Parser *xmlParser)
1018 {
1019 ptrdiff_t tokenLength = 0;
1020 int temp;
1021 ptrdiff_t tlen;
1022 int rc;
1023
1024 Parser_clearTokenBuf( xmlParser );
1025
1026 if( *( xmlParser->curPtr ) == '\0' ) {
1027 return 0;
1028 }
1029 /* skip XML instructions */
1030 rc = Parser_skipMisc( xmlParser );
1031 if( rc != IXML_SUCCESS ) {
1032 return 0;
1033 }
1034 /* Attribute value logic must come first, since all text untokenized until
1035 * end-quote */
1036 if( *( xmlParser->curPtr ) == QUOTE ) {
1037 tokenLength = 1;
1038 } else if( *( xmlParser->curPtr ) == SINGLEQUOTE ) {
1039 tokenLength = 1;
1040 } else if( *( xmlParser->curPtr ) == LESSTHAN ) {
1041 /* Check for start tags */
1042 temp = Parser_UTF8ToInt( xmlParser->curPtr + 1, &tlen );
1043 if( temp == '/' ) {
1044 /* token is '</' end tag */
1045 tokenLength = 2;
1046 } else if( Parser_isNameChar( temp, 0 ) ) {
1047 /* '<' found, so return '<' token */
1048 tokenLength = 1;
1049 } else {
1050 /* error */
1051 return 0;
1052 }
1053 } else if( *( xmlParser->curPtr ) == EQUALS ) {
1054 /* Check for '=' token, return it as a token */
1055 tokenLength = 1;
1056 } else if( *( xmlParser->curPtr ) == SLASH ) {
1057 if( *( xmlParser->curPtr + 1 ) == GREATERTHAN ) {
1058 /* token '/>' found */
1059 tokenLength = 2;
1060 /* fix */
1061 xmlParser->savePtr = xmlParser->curPtr;
1062 }
1063 } else if( *( xmlParser->curPtr ) == GREATERTHAN ) {
1064 /* > found, so return it as a token */
1065 tokenLength = 1;
1066 } else if( Parser_isNameChar( Parser_UTF8ToInt( xmlParser->curPtr, &tlen ), 0 ) ) {
1067 /* Check for name tokens, name found, so find out how long it is */
1068 ptrdiff_t iIndex = tlen;
1069
1070 while( Parser_isNameChar
1071 ( Parser_UTF8ToInt( xmlParser->curPtr + iIndex, &tlen ),
1072 1 ) ) {
1073 iIndex += tlen;
1074 }
1075 tokenLength = iIndex;
1076 } else {
1077 return 0;
1078 }
1079
1080 /* Copy the token to the return string */
1081 if( Parser_copyToken( xmlParser, xmlParser->curPtr, tokenLength ) !=
1082 IXML_SUCCESS ) {
1083 return 0;
1084 }
1085
1086 xmlParser->curPtr += tokenLength;
1087 return tokenLength;
1088 }
1089
1090
1091 /*!
1092 * \brief Version of strdup() that handles NULL input.
1093 *
1094 * \return The same as strdup().
1095 */
safe_strdup(const char * s)1096 static char *safe_strdup(
1097 /*! [in] String to be duplicated. */
1098 const char *s)
1099 {
1100 assert(s != NULL);
1101
1102 if (s == NULL) {
1103 return strdup((const char*)"");
1104 }
1105 return strdup(s);
1106 }
1107
1108
1109 /*!
1110 * \brief Processes the STag as defined by XML spec.
1111 */
Parser_processSTag(Parser * xmlParser,IXML_Node * node)1112 static int Parser_processSTag(
1113 /*! [in] The XML parser. */
1114 Parser *xmlParser,
1115 /*! [in] The Node to process. */
1116 IXML_Node *node)
1117 {
1118 char *pCurToken = NULL;
1119 int rc;
1120
1121 if( Parser_getNextToken( xmlParser ) == 0 ) {
1122 return IXML_SYNTAX_ERR;
1123 }
1124
1125 pCurToken = ( xmlParser->tokenBuf ).buf;
1126 if( pCurToken != NULL ) {
1127 node->nodeName = safe_strdup( pCurToken );
1128 if( node->nodeName == NULL ) {
1129 return IXML_INSUFFICIENT_MEMORY;
1130 }
1131 } else {
1132 return IXML_SYNTAX_ERR;
1133 }
1134
1135 rc = Parser_setLastElem( xmlParser, node->nodeName );
1136 if( rc != IXML_SUCCESS ) {
1137 /* no need to free node->nodeName, main loop will free it */
1138 return IXML_FAILED;
1139 }
1140
1141 rc = Parser_setNodePrefixAndLocalName( node );
1142 if( rc != IXML_SUCCESS ) {
1143 /* no need to free node->nodeName, main loop will free it */
1144 return IXML_FAILED;
1145 }
1146
1147 node->nodeValue = NULL;
1148 node->nodeType = eELEMENT_NODE;
1149
1150 xmlParser->savePtr = xmlParser->curPtr;
1151 if( Parser_getNextToken( xmlParser ) == 0 ) {
1152 /* no need to free node->nodeName, main loop will free it */
1153 return IXML_SYNTAX_ERR;
1154 }
1155
1156 pCurToken = ( xmlParser->tokenBuf ).buf;
1157 /* check to see what is the next token */
1158 if( strcmp( pCurToken, "/>" ) == 0 )
1159 {
1160 /* empty element */
1161 xmlParser->state = eELEMENT;
1162 /* backup to /> */
1163 xmlParser->curPtr = xmlParser->savePtr;
1164 } else if( strcmp( pCurToken, ">" ) == 0 )
1165 {
1166 /* expecting text node */
1167 xmlParser->state = eCONTENT;
1168 } else {
1169 xmlParser->state = eATTRIBUTE;
1170 xmlParser->curPtr = xmlParser->savePtr;
1171 }
1172
1173 return IXML_SUCCESS;
1174 }
1175
1176
1177 /*!
1178 * \brief
1179 */
Parser_skipPI(char ** pSrc)1180 static int Parser_skipPI(
1181 /*! [in,out] The pointer to the skipped point. */
1182 char **pSrc)
1183 {
1184 char *pEnd = NULL;
1185
1186 assert( *pSrc );
1187 if( *pSrc == NULL ) {
1188 return IXML_FAILED;
1189 }
1190
1191 if ((strncasecmp(*pSrc, (char *)XMLDECL , strlen(XMLDECL )) == 0) ||
1192 (strncasecmp(*pSrc, (char *)XMLDECL2, strlen(XMLDECL2)) == 0)) {
1193 /* not allowed */
1194 return IXML_SYNTAX_ERR;
1195 }
1196
1197 if (strncasecmp(*pSrc, (char *)BEGIN_PI, strlen(BEGIN_PI)) == 0) {
1198 pEnd = strstr( *pSrc, END_PI );
1199 if( ( pEnd != NULL ) && ( pEnd != *pSrc ) ) {
1200 *pSrc = pEnd + strlen( BEGIN_PI );
1201 } else {
1202 return IXML_SYNTAX_ERR;
1203 }
1204 }
1205
1206 return IXML_SUCCESS;
1207 }
1208
1209
1210 /*!
1211 * \brief Processes CDSection as defined by XML spec.
1212 *
1213 * \return
1214 */
Parser_processCDSect(char ** pSrc,IXML_Node * node)1215 static int Parser_processCDSect(
1216 /*! [in] . */
1217 char **pSrc,
1218 /*! [in] The Node to process. */
1219 IXML_Node *node)
1220 {
1221 char *pEnd;
1222 size_t tokenLength = (size_t)0;
1223 char *pCDataStart;
1224
1225 if( *pSrc == NULL ) {
1226 return IXML_FAILED;
1227 }
1228
1229 pCDataStart = *pSrc + strlen( CDSTART );
1230 pEnd = pCDataStart;
1231 while( ( Parser_isXmlChar( (int)*pEnd ) ) && ( *pEnd != '\0' ) ) {
1232 if( strncmp( pEnd, CDEND, strlen( CDEND ) ) == 0 ) {
1233 break;
1234 } else {
1235 pEnd++;
1236 }
1237 }
1238
1239 if( ( pEnd - pCDataStart > 0 ) && ( *pEnd != '\0' ) ) {
1240 tokenLength = (size_t)pEnd - (size_t)pCDataStart;
1241 node->nodeValue = (char *)malloc(tokenLength + (size_t)1);
1242 if( node->nodeValue == NULL ) {
1243 return IXML_INSUFFICIENT_MEMORY;
1244 }
1245 strncpy(node->nodeValue, pCDataStart, tokenLength);
1246 node->nodeValue[tokenLength] = '\0';
1247
1248 node->nodeName = safe_strdup( CDATANODENAME );
1249 if( node->nodeName == NULL ) {
1250 /* no need to free node->nodeValue at all, bacause node contents
1251 * will be freed by the main loop. */
1252 return IXML_INSUFFICIENT_MEMORY;
1253 }
1254
1255 node->nodeType = eCDATA_SECTION_NODE;
1256 *pSrc = pEnd + strlen( CDEND );
1257 return IXML_SUCCESS;
1258 } else {
1259 return IXML_SYNTAX_ERR;
1260 }
1261 }
1262
1263
1264 /*!
1265 * \brief Processes the CONTENT as defined in XML spec.
1266 */
Parser_processContent(Parser * xmlParser,IXML_Node * node)1267 static int Parser_processContent(
1268 /*! [in] The XML parser. */
1269 Parser *xmlParser,
1270 /*! [in] The Node to process. */
1271 IXML_Node *node)
1272 {
1273 int ret = IXML_SUCCESS;
1274 int line = 0;
1275 char *pEndContent;
1276 ptrdiff_t tokenLength;
1277 const char *notAllowed = "]]>";
1278 char *pCurToken = NULL;
1279
1280 /* save pointer for backup */
1281 xmlParser->savePtr = xmlParser->curPtr;
1282 Parser_skipWhiteSpaces( xmlParser );
1283
1284 if (*(xmlParser->curPtr) == '\0' ) {
1285 /* end of file is reached */
1286 ret = IXML_SUCCESS;
1287 goto ExitFunction;
1288 }
1289
1290 pEndContent = xmlParser->curPtr;
1291 if (*pEndContent == LESSTHAN) {
1292 if (strncmp(pEndContent, (char *)CDSTART, strlen(CDSTART)) == 0) {
1293 if (Parser_processCDSect(&pEndContent, node) != IXML_SUCCESS) {
1294 line = __LINE__;
1295 ret = IXML_SYNTAX_ERR;
1296 goto ExitFunction;
1297 } else {
1298 xmlParser->curPtr = pEndContent;
1299 }
1300 } else if(strncmp(pEndContent, (char *)BEGIN_COMMENT, strlen(BEGIN_COMMENT)) == 0) {
1301 if (Parser_skipComment(&pEndContent) != IXML_SUCCESS) {
1302 line = __LINE__;
1303 ret = IXML_SYNTAX_ERR;
1304 goto ExitFunction;
1305 } else {
1306 xmlParser->curPtr = pEndContent;
1307 }
1308 } else if(strncmp(pEndContent, (char *)BEGIN_PI, strlen(BEGIN_PI)) == 0) {
1309 if (Parser_skipPI(&pEndContent) != IXML_SUCCESS) {
1310 line = __LINE__;
1311 ret = IXML_SYNTAX_ERR;
1312 goto ExitFunction;
1313 } else {
1314 xmlParser->curPtr = pEndContent;
1315 }
1316 } else {
1317 /* empty content */
1318 xmlParser->state = eELEMENT;
1319 }
1320 } else {
1321 /* backup */
1322 xmlParser->curPtr = xmlParser->savePtr;
1323 pEndContent = xmlParser->curPtr;
1324
1325 while ((*pEndContent != LESSTHAN) &&
1326 ( strncmp(pEndContent, (const char *)notAllowed, strlen(notAllowed)) != 0) &&
1327 *pEndContent) {
1328 pEndContent++;
1329 }
1330
1331 if (strncmp(pEndContent, (const char *)notAllowed, strlen(notAllowed)) == 0) {
1332 line = __LINE__;
1333 ret = IXML_SYNTAX_ERR;
1334 goto ExitFunction;
1335 }
1336
1337 tokenLength = pEndContent - xmlParser->curPtr;
1338 Parser_clearTokenBuf( xmlParser );
1339
1340 if (Parser_copyToken(xmlParser, xmlParser->curPtr, tokenLength) != IXML_SUCCESS) {
1341 line = __LINE__;
1342 ret = IXML_SYNTAX_ERR;
1343 goto ExitFunction;
1344 }
1345
1346 pCurToken = (xmlParser->tokenBuf).buf;
1347 if (pCurToken != NULL) {
1348 node->nodeValue = safe_strdup(pCurToken);
1349 if (node->nodeValue == NULL) {
1350 line = __LINE__;
1351 ret = IXML_INSUFFICIENT_MEMORY;
1352 goto ExitFunction;
1353 }
1354 } else {
1355 line = __LINE__;
1356 ret = IXML_SYNTAX_ERR;
1357 goto ExitFunction;
1358 }
1359
1360 node->nodeName = safe_strdup( TEXTNODENAME );
1361 if (node->nodeName == NULL) {
1362 line = __LINE__;
1363 ret = IXML_SYNTAX_ERR;
1364 goto ExitFunction;
1365 }
1366 node->nodeType = eTEXT_NODE;
1367
1368 /* adjust curPtr */
1369 xmlParser->curPtr += tokenLength;
1370 }
1371
1372 ExitFunction:
1373 if (ret != IXML_SUCCESS) {
1374 IxmlPrintf(__FILE__, line, "Parser_processContent", "Error %d\n", ret);
1375 }
1376
1377 return ret;
1378 }
1379
1380
1381 /*!
1382 * \brief Process ETag as defined by XML spec.
1383 */
Parser_processETag(Parser * xmlParser,IXML_Node * node,int * bETag)1384 static int Parser_processETag(
1385 /*! [in] The XML parser. */
1386 Parser *xmlParser,
1387 /*! [in] The Node to process. */
1388 IXML_Node *node,
1389 /*! [out] . */
1390 int *bETag)
1391 {
1392 int ret = IXML_SUCCESS;
1393 int line = 0;
1394 char *pCurToken = NULL;
1395
1396 assert( xmlParser != NULL );
1397 if( Parser_getNextToken( xmlParser ) == 0 ) {
1398 line = __LINE__;
1399 ret = IXML_SYNTAX_ERR;
1400 goto ExitFunction;
1401 }
1402
1403 pCurToken = ( xmlParser->tokenBuf ).buf;
1404 if( pCurToken == NULL ) {
1405 line = __LINE__;
1406 ret = IXML_SYNTAX_ERR;
1407 goto ExitFunction;
1408 }
1409 node->nodeName = safe_strdup( pCurToken );
1410 if( node->nodeName == NULL ) {
1411 line = __LINE__;
1412 ret = IXML_INSUFFICIENT_MEMORY;
1413 goto ExitFunction;
1414 }
1415
1416 node->nodeValue = NULL;
1417 node->nodeType = eELEMENT_NODE;
1418
1419 Parser_skipWhiteSpaces( xmlParser );
1420
1421 /* read the > */
1422 if( Parser_getNextToken( xmlParser ) == 0 ) {
1423 line = __LINE__;
1424 ret = IXML_SYNTAX_ERR;
1425 goto ExitFunction;
1426 }
1427
1428 pCurToken = ( xmlParser->tokenBuf ).buf;
1429 if( pCurToken == NULL ) {
1430 /* no need to free node->nodeName, it is freed by main loop */
1431 line = __LINE__;
1432 ret = IXML_SYNTAX_ERR;
1433 goto ExitFunction;
1434 }
1435
1436 if( strcmp( pCurToken, ">" ) != 0 ) {
1437 line = __LINE__;
1438 ret = IXML_SYNTAX_ERR;
1439 goto ExitFunction;
1440 }
1441
1442 *bETag = 1;
1443
1444 ExitFunction:
1445 if (ret != IXML_SUCCESS) {
1446 IxmlPrintf(__FILE__, line, "Parser_processETag", "Error %d\n", ret);
1447 }
1448
1449 return ret;
1450 }
1451
1452
1453 /*!
1454 * \brief Unimplemented function.
1455 *
1456 * \return IXML_SUCCESS.
1457 */
1458 #if 0
1459 static int Parser_parseReference(
1460 /*! [in] Currently unused. */
1461 char *pStr)
1462 {
1463 /* place holder for future implementation */
1464 return IXML_SUCCESS;
1465 pStr = pStr;
1466 }
1467 #endif
1468
1469
1470 /*!
1471 * \brief Return the namespce as defined as prefix.
1472 */
Parser_getNameSpace(Parser * xmlParser,const char * prefix)1473 static char *Parser_getNameSpace(
1474 /*! [in] The XML parser. */
1475 Parser *xmlParser,
1476 /*! [in] The prefix. */
1477 const char *prefix)
1478 {
1479 IXML_ElementStack *pCur;
1480 IXML_NamespaceURI *pNsUri;
1481
1482 pCur = xmlParser->pCurElement;
1483 if( strcmp( pCur->prefix, prefix ) != 0 ) {
1484 pNsUri = pCur->pNsURI;
1485 while( pNsUri != NULL ) {
1486 if( strcmp( pNsUri->prefix, prefix ) == 0 ) {
1487 return pNsUri->nsURI;
1488 }
1489 pNsUri = pNsUri->nextNsURI;
1490 }
1491 } else {
1492 return pCur->namespaceUri;
1493 }
1494
1495 return NULL;
1496
1497 }
1498
1499
1500 /*!
1501 * \brief Add a namespace definition.
1502 */
Parser_addNamespace(Parser * xmlParser)1503 static int Parser_addNamespace(
1504 /*! [in] The XML parser. */
1505 Parser *xmlParser)
1506 {
1507 IXML_Node *pNode;
1508 IXML_ElementStack *pCur;
1509 const char *namespaceUri;
1510
1511 pNode = xmlParser->pNeedPrefixNode;
1512 pCur = xmlParser->pCurElement;
1513 if (!pNode->prefix) {
1514 /* element does not have prefix */
1515 if (strcmp(pNode->nodeName, pCur->element) != 0)
1516 return IXML_FAILED;
1517 if (pCur->namespaceUri) {
1518 /* it would be wrong that pNode->namespace != NULL. */
1519 assert(pNode->namespaceURI == NULL);
1520 pNode->namespaceURI = safe_strdup(pCur->namespaceUri);
1521 if (!pNode->namespaceURI)
1522 return IXML_INSUFFICIENT_MEMORY;
1523 }
1524 xmlParser->pNeedPrefixNode = NULL;
1525 } else {
1526 if (!pCur->prefix ||
1527 ((strcmp(pNode->nodeName, pCur->element) != 0) &&
1528 (strcmp(pNode->prefix, pCur->prefix) != 0)))
1529 return IXML_FAILED;
1530 namespaceUri = Parser_getNameSpace(xmlParser, pCur->prefix);
1531 if (namespaceUri) {
1532 pNode->namespaceURI = safe_strdup(namespaceUri);
1533 if (!pNode->namespaceURI)
1534 return IXML_INSUFFICIENT_MEMORY;
1535 xmlParser->pNeedPrefixNode = NULL;
1536 }
1537 }
1538
1539 return IXML_SUCCESS;
1540 }
1541
1542
1543 /*!
1544 * \brief Add namespace definition.
1545 */
Parser_xmlNamespace(Parser * xmlParser,IXML_Node * newNode)1546 static int Parser_xmlNamespace(
1547 /*! [in] The XML parser. */
1548 Parser *xmlParser,
1549 /*! [in] The Node to process. */
1550 IXML_Node *newNode)
1551 {
1552 IXML_ElementStack *pCur = xmlParser->pCurElement;
1553 IXML_NamespaceURI *pNewNs = NULL;
1554 IXML_NamespaceURI *pNs = NULL;
1555 IXML_NamespaceURI *pPrevNs = NULL;
1556 int ret = IXML_SUCCESS;
1557 int line = 0;
1558
1559 /* if the newNode contains a namespace definition */
1560 assert(newNode->nodeName != NULL);
1561
1562 if (strcmp(newNode->nodeName, "xmlns") == 0) {
1563 /* default namespace def. */
1564 if (pCur->namespaceUri != NULL) {
1565 free(pCur->namespaceUri);
1566 }
1567 pCur->namespaceUri = safe_strdup(newNode->nodeValue);
1568 if (pCur->namespaceUri == NULL) {
1569 ret = IXML_INSUFFICIENT_MEMORY;
1570 line = __LINE__;
1571 goto ExitFunction;
1572 }
1573 } else if (strncmp(newNode->nodeName, "xmlns:", strlen("xmlns:")) == 0) {
1574 /* namespace definition */
1575 ret = Parser_setNodePrefixAndLocalName(newNode);
1576 if (ret != IXML_SUCCESS) {
1577 line = __LINE__;
1578 goto ExitFunction;
1579 }
1580
1581 assert(newNode->localName != NULL);
1582
1583 if (pCur == NULL) {
1584 ret = IXML_FAILED;
1585 line = __LINE__;
1586 goto ExitFunction;
1587 }
1588 if (pCur->prefix != NULL &&
1589 strcmp(pCur->prefix, newNode->localName) == 0) {
1590 if (pCur->namespaceUri != NULL) {
1591 free(pCur->namespaceUri);
1592 }
1593 pCur->namespaceUri = safe_strdup(newNode->nodeValue);
1594 if (pCur->namespaceUri == NULL) {
1595 ret = IXML_INSUFFICIENT_MEMORY;
1596 line = __LINE__;
1597 goto ExitFunction;
1598 }
1599 } else {
1600 pPrevNs = pCur->pNsURI;
1601 pNs = pPrevNs;
1602 while (pNs != NULL) {
1603 if (pNs->prefix != NULL &&
1604 strcmp(pNs->prefix, newNode->localName) == 0) {
1605 /* replace namespace definition */
1606 break;
1607 } else {
1608 pPrevNs = pNs;
1609 pNs = pNs->nextNsURI;
1610 }
1611 }
1612 if (pNs == NULL) {
1613 /* a new definition */
1614 pNewNs = (IXML_NamespaceURI *)
1615 malloc(sizeof (IXML_NamespaceURI));
1616 if (pNewNs == NULL) {
1617 ret = IXML_INSUFFICIENT_MEMORY;
1618 line = __LINE__;
1619 goto ExitFunction;
1620 }
1621 memset(pNewNs, 0, sizeof (IXML_NamespaceURI));
1622 pNewNs->prefix = safe_strdup(newNode->localName);
1623 if (pNewNs->prefix == NULL) {
1624 free(pNewNs);
1625 ret = IXML_INSUFFICIENT_MEMORY;
1626 line = __LINE__;
1627 goto ExitFunction;
1628 }
1629 pNewNs->nsURI = safe_strdup(newNode->nodeValue);
1630 if (pNewNs->nsURI == NULL) {
1631 Parser_freeNsURI(pNewNs);
1632 free(pNewNs);
1633 ret = IXML_INSUFFICIENT_MEMORY;
1634 line = __LINE__;
1635 goto ExitFunction;
1636 }
1637 if (pCur->pNsURI == NULL) {
1638 pCur->pNsURI = pNewNs;
1639 } else {
1640 pPrevNs->nextNsURI = pNewNs;
1641 }
1642 } else {
1643 /* udpate the namespace */
1644 if (pNs->nsURI != NULL) {
1645 free(pNs->nsURI);
1646 }
1647 pNs->nsURI = safe_strdup(newNode->nodeValue);
1648 if (pNs->nsURI == NULL) {
1649 ret = IXML_INSUFFICIENT_MEMORY;
1650 line = __LINE__;
1651 goto ExitFunction;
1652 }
1653 }
1654 }
1655 }
1656 if (xmlParser->pNeedPrefixNode != NULL) {
1657 ret = Parser_addNamespace(xmlParser);
1658 line = __LINE__;
1659 goto ExitFunction;
1660 }
1661
1662 ExitFunction:
1663 if (ret != IXML_SUCCESS && ret != IXML_FILE_DONE) {
1664 IxmlPrintf(__FILE__, line, "Parser_xmlNamespace", "Error %d\n", ret);
1665 }
1666
1667 return ret;
1668 }
1669
1670
1671 /*!
1672 * \brief Processes attribute.
1673 *
1674 * \return IXML_SUCCESS or failure code.
1675 */
Parser_processAttribute(Parser * xmlParser,IXML_Node * node)1676 static int Parser_processAttribute(
1677 /*! [in] The XML parser. */
1678 Parser *xmlParser,
1679 /*! [in] The Node to process. */
1680 IXML_Node *node)
1681 {
1682 int ret = IXML_SUCCESS;
1683 int line = 0;
1684 ptrdiff_t tlen = 0;
1685 char *strEndQuote = NULL;
1686 char *pCur = NULL;
1687 char *pCurToken = NULL;
1688
1689 assert(xmlParser);
1690
1691 if (xmlParser == NULL) {
1692 ret = IXML_FAILED;
1693 line = __LINE__;
1694 goto ExitFunction;
1695 }
1696 pCurToken = xmlParser->tokenBuf.buf;
1697 if (pCurToken == NULL) {
1698 ret = IXML_SYNTAX_ERR;
1699 line = __LINE__;
1700 goto ExitFunction;
1701 }
1702 if (Parser_isNameChar(Parser_UTF8ToInt(pCurToken, &tlen), 0) == 0) {
1703 ret = IXML_SYNTAX_ERR;
1704 line = __LINE__;
1705 goto ExitFunction;
1706 }
1707 /* copy in the attribute name */
1708 node->nodeName = safe_strdup(pCurToken);
1709 if (node->nodeName == NULL) {
1710 ret = IXML_INSUFFICIENT_MEMORY;
1711 line = __LINE__;
1712 goto ExitFunction;
1713 }
1714 /* read in the "=" sign */
1715 if (Parser_getNextToken(xmlParser) == 0) {
1716 ret = IXML_SYNTAX_ERR;
1717 line = __LINE__;
1718 goto ExitFunction;
1719 }
1720
1721 pCurToken = xmlParser->tokenBuf.buf;
1722 if (*pCurToken != EQUALS) {
1723 ret = IXML_SYNTAX_ERR;
1724 line = __LINE__;
1725 goto ExitFunction;
1726 }
1727 /* read in the single quote or double quote */
1728 if (Parser_getNextToken(xmlParser) == 0) {
1729 ret = IXML_SYNTAX_ERR;
1730 line = __LINE__;
1731 goto ExitFunction;
1732 }
1733 /* pCurToken is either quote or single quote */
1734 pCurToken = ( xmlParser->tokenBuf ).buf;
1735 if (*pCurToken != QUOTE && *pCurToken != SINGLEQUOTE) {
1736 ret = IXML_SYNTAX_ERR;
1737 line = __LINE__;
1738 goto ExitFunction;
1739 }
1740 strEndQuote = strstr(xmlParser->curPtr, pCurToken);
1741 if (strEndQuote == NULL) {
1742 ret = IXML_SYNTAX_ERR;
1743 line = __LINE__;
1744 goto ExitFunction;
1745 }
1746 /* check between curPtr and strEndQuote,
1747 * whether there are illegal chars. */
1748 pCur = xmlParser->curPtr;
1749 while (pCur < strEndQuote) {
1750 if (*pCur == '<') {
1751 ret = IXML_SYNTAX_ERR;
1752 line = __LINE__;
1753 goto ExitFunction;
1754 }
1755 /*if (*pCur == '&') {
1756 Parser_parseReference(++pCur);
1757 }*/
1758 pCur++;
1759 }
1760 /* clear token buffer */
1761 Parser_clearTokenBuf(xmlParser);
1762 if (strEndQuote != xmlParser->curPtr) {
1763 ret = Parser_copyToken(
1764 xmlParser,
1765 xmlParser->curPtr,
1766 strEndQuote - xmlParser->curPtr);
1767 if(ret != IXML_SUCCESS) {
1768 ret = IXML_SYNTAX_ERR;
1769 line = __LINE__;
1770 goto ExitFunction;
1771 }
1772 }
1773 /* skip the ending quote */
1774 xmlParser->curPtr = strEndQuote + 1;
1775 pCurToken = xmlParser->tokenBuf.buf;
1776 if (pCurToken != NULL) {
1777 /* attribute has value, like a="c" */
1778 node->nodeValue = safe_strdup(pCurToken);
1779 if (node->nodeValue == NULL) {
1780 ret = IXML_INSUFFICIENT_MEMORY;
1781 line = __LINE__;
1782 goto ExitFunction;
1783 }
1784 } else {
1785 /* if attribute doesn't have value, like a=""
1786 * somewhere on other places is this copied */
1787 node->nodeValue = malloc(sizeof (char));
1788 *(node->nodeValue) = '\0';
1789 }
1790 node->nodeType = eATTRIBUTE_NODE;
1791
1792 /* check whether this is a new namespace definition */
1793 ret = Parser_xmlNamespace(xmlParser, node);
1794 if (ret != IXML_SUCCESS) {
1795 line = __LINE__;
1796 goto ExitFunction;
1797 }
1798 /* read ahead to see whether we have more attributes */
1799 xmlParser->savePtr = xmlParser->curPtr;
1800 if (Parser_getNextToken(xmlParser) == 0) {
1801 ret = IXML_SYNTAX_ERR;
1802 line = __LINE__;
1803 goto ExitFunction;
1804 }
1805
1806 pCurToken = xmlParser->tokenBuf.buf;
1807 if (strcmp(pCurToken, "<") == 0) {
1808 ret = IXML_FAILED;
1809 line = __LINE__;
1810 goto ExitFunction;
1811 } else if(strcmp(pCurToken, ">") != 0) {
1812 /* more attribute? */
1813 /* backup */
1814 xmlParser->curPtr = xmlParser->savePtr;
1815 } else {
1816 xmlParser->state = eCONTENT;
1817 }
1818
1819 ExitFunction:
1820 if (ret != IXML_SUCCESS && ret != IXML_FILE_DONE) {
1821 IxmlPrintf(__FILE__, line, "Parser_processAttribute", "Error %d\n", ret);
1822 }
1823
1824 return ret;
1825 }
1826
1827
1828 /*!
1829 * \brief Get the next node.
1830 *
1831 * \return IXML_SUCCESS and the next node or IXML_FILE_DONE or an error.
1832 */
Parser_getNextNode(Parser * xmlParser,IXML_Node * node,int * bETag)1833 static int Parser_getNextNode(
1834 /*! [in] The XML parser. */
1835 Parser *xmlParser,
1836 /*! [out] The XML parser. */
1837 IXML_Node *node,
1838 /*! [out] The XML parser. */
1839 int *bETag)
1840 {
1841 char *pCurToken = NULL;
1842 char *lastElement = NULL;
1843 int ret = IXML_SUCCESS;
1844 int line = 0;
1845 ptrdiff_t tokenLen = 0;
1846
1847 /* endof file reached? */
1848 if (*(xmlParser->curPtr) == '\0') {
1849 *bETag = 1;
1850 line = __LINE__;
1851 ret = IXML_FILE_DONE;
1852 goto ExitFunction;
1853 }
1854
1855 switch (xmlParser->state) {
1856 case eCONTENT:
1857 line = __LINE__;
1858 ret = Parser_processContent(xmlParser, node);
1859 goto ExitFunction;
1860 default:
1861 Parser_skipWhiteSpaces(xmlParser);
1862 tokenLen = Parser_getNextToken(xmlParser);
1863 if (tokenLen == 0 &&
1864 xmlParser->pCurElement == NULL &&
1865 *(xmlParser->curPtr) == '\0') {
1866 /* comments after the xml doc */
1867 line = __LINE__;
1868 ret = IXML_SUCCESS;
1869 goto ExitFunction;
1870 } else if ((xmlParser->tokenBuf).length == (size_t)0) {
1871 line = __LINE__;
1872 ret = IXML_SYNTAX_ERR;
1873 goto ExitFunction;
1874 }
1875
1876 pCurToken = (xmlParser->tokenBuf).buf;
1877 if (*pCurToken == GREATERTHAN) {
1878 line = __LINE__;
1879 ret = IXML_SUCCESS;
1880 goto ExitFunction;
1881 } else if (strcmp(pCurToken, ENDTAG) == 0) {
1882 /* we got </, read next element */
1883 line = __LINE__;
1884 ret = Parser_processETag(xmlParser, node, bETag);
1885 goto ExitFunction;
1886 } else if (*pCurToken == LESSTHAN) {
1887 line = __LINE__;
1888 ret = Parser_processSTag(xmlParser, node);
1889 goto ExitFunction;
1890 } else if (strcmp(pCurToken, COMPLETETAG) == 0) {
1891 lastElement = (xmlParser->lastElem).buf;
1892 if (lastElement == NULL) {
1893 line = __LINE__;
1894 ret = IXML_SYNTAX_ERR;
1895 goto ExitFunction;
1896 }
1897
1898 node->nodeName = safe_strdup(lastElement);
1899 if (node->nodeName == NULL) {
1900 line = __LINE__;
1901 ret = IXML_INSUFFICIENT_MEMORY;
1902 goto ExitFunction;
1903 }
1904 node->nodeType = eELEMENT_NODE;
1905 *bETag = 1;
1906
1907 line = __LINE__;
1908 ret = IXML_SUCCESS;
1909 goto ExitFunction;
1910 } else if (xmlParser->pCurElement != NULL) {
1911 switch (xmlParser->state) {
1912 case eATTRIBUTE:
1913 if (Parser_processAttribute(xmlParser, node) != IXML_SUCCESS) {
1914 line = __LINE__;
1915 ret = IXML_SYNTAX_ERR;
1916 goto ExitFunction;
1917 }
1918 break;
1919 default:
1920 line = __LINE__;
1921 ret = IXML_SYNTAX_ERR;
1922 goto ExitFunction;
1923 }
1924 } else {
1925 line = __LINE__;
1926 ret = IXML_SYNTAX_ERR;
1927 goto ExitFunction;
1928 }
1929 }
1930
1931 ExitFunction:
1932 if (ret != IXML_SUCCESS && ret != IXML_FILE_DONE) {
1933 IxmlPrintf(__FILE__, line, "Parser_getNextNode", "Error %d\n", ret);
1934 }
1935
1936 return ret;
1937 }
1938
1939
1940 /*!
1941 * \brief Decides whether element's prefix is already defined.
1942 */
Parser_ElementPrefixDefined(Parser * xmlParser,IXML_Node * newNode,char ** nsURI)1943 static int Parser_ElementPrefixDefined(
1944 /*! [in] The XML parser. */
1945 Parser *xmlParser,
1946 /*! [in] The Node to process. */
1947 IXML_Node *newNode,
1948 /*! [in,out] The name space URI. */
1949 char **nsURI )
1950 {
1951 IXML_ElementStack *pCur = xmlParser->pCurElement;
1952 IXML_NamespaceURI *pNsUri;
1953
1954 while( pCur != NULL ) {
1955 if( ( pCur->prefix != NULL )
1956 && ( strcmp( pCur->prefix, newNode->prefix ) == 0 ) ) {
1957 *nsURI = pCur->namespaceUri;
1958 return 1;
1959 } else {
1960 pNsUri = pCur->pNsURI;
1961
1962 while( pNsUri != NULL ) {
1963 if( strcmp( pNsUri->prefix, newNode->prefix ) == 0 ) {
1964 *nsURI = pNsUri->nsURI;
1965 return 1;
1966 } else {
1967 pNsUri = pNsUri->nextNsURI;
1968 }
1969 }
1970 }
1971
1972 pCur = pCur->nextElement;
1973
1974 }
1975
1976 return 0;
1977 }
1978
1979
1980 /*!
1981 * \brief Set element's namespace.
1982 */
Parser_setElementNamespace(IXML_Element * newElement,const char * nsURI)1983 static int Parser_setElementNamespace(
1984 /*! [in] The Element Node to process. */
1985 IXML_Element *newElement,
1986 /*! [in] The name space string. */
1987 const char *nsURI)
1988 {
1989 if( newElement != NULL ) {
1990 if( newElement->n.namespaceURI != NULL ) {
1991 return IXML_SYNTAX_ERR;
1992 } else {
1993 ( newElement->n ).namespaceURI = safe_strdup( nsURI );
1994 if( ( newElement->n ).namespaceURI == NULL ) {
1995 return IXML_INSUFFICIENT_MEMORY;
1996 }
1997 }
1998 }
1999
2000 return IXML_SUCCESS;
2001 }
2002
2003
2004 /*!
2005 * \brief Reports whether the new attribute is the same as an existing one.
2006 *
2007 * \return 1 if the new attribute is the same as an existing one.
2008 */
isDuplicateAttribute(Parser * xmlParser,IXML_Node * newAttrNode)2009 static int isDuplicateAttribute(
2010 /*! [in] The XML parser. */
2011 Parser *xmlParser,
2012 /*! [in] The node attribute to compare. */
2013 IXML_Node *newAttrNode)
2014 {
2015 IXML_Node *elementNode = NULL;
2016 IXML_Node *attrNode = NULL;
2017
2018 elementNode = xmlParser->currentNodePtr;
2019 attrNode = elementNode->firstAttr;
2020 while( attrNode != NULL ) {
2021 if( strcmp( attrNode->nodeName, newAttrNode->nodeName ) == 0 ) {
2022 return 1;
2023 }
2024
2025 attrNode = attrNode->nextSibling;
2026 }
2027
2028 return 0;
2029 }
2030
2031
2032 /*!
2033 * \brief Processes the attribute name.
2034 *
2035 * \return IXML_SUCCESS if successful, otherwise or an error code.
2036 */
Parser_processAttributeName(IXML_Document * rootDoc,Parser * xmlParser,IXML_Node * newNode)2037 static int Parser_processAttributeName(
2038 /*! [in] The XML document. */
2039 IXML_Document *rootDoc,
2040 /*! [in] The XML parser. */
2041 Parser *xmlParser,
2042 /*! [in] The Node to process. */
2043 IXML_Node *newNode)
2044 {
2045 IXML_Attr *attr = NULL;
2046 int rc = IXML_SUCCESS;
2047
2048 if( isDuplicateAttribute( xmlParser, newNode ) ) {
2049 return IXML_SYNTAX_ERR;
2050 }
2051
2052 rc = ixmlDocument_createAttributeEx( rootDoc, newNode->nodeName, &attr );
2053 if( rc != IXML_SUCCESS ) {
2054 return rc;
2055 }
2056
2057 rc = ixmlNode_setNodeProperties( ( IXML_Node * ) attr, newNode );
2058 if( rc != IXML_SUCCESS ) {
2059 ixmlAttr_free( attr );
2060 return rc;
2061 }
2062
2063 rc = ixmlElement_setAttributeNode(
2064 (IXML_Element *)xmlParser->currentNodePtr, attr, NULL );
2065 if( rc != IXML_SUCCESS ) {
2066 ixmlAttr_free( attr );
2067 }
2068 return rc;
2069 }
2070
2071
2072 /*!
2073 * \brief Push a new element onto element stack.
2074 *
2075 * \return
2076 */
Parser_pushElement(Parser * xmlParser,IXML_Node * newElement)2077 static int Parser_pushElement(
2078 /*! [in] The XML parser. */
2079 Parser *xmlParser,
2080 /*! [in] The element node to push. */
2081 IXML_Node *newElement)
2082 {
2083 IXML_ElementStack *pCurElement = NULL;
2084 IXML_ElementStack *pNewStackElement = NULL;
2085
2086 assert( newElement );
2087 if( newElement != NULL ) {
2088 /* push new element */
2089 pNewStackElement =
2090 ( IXML_ElementStack * ) malloc( sizeof( IXML_ElementStack ) );
2091 if( pNewStackElement == NULL ) {
2092 return IXML_INSUFFICIENT_MEMORY;
2093 }
2094
2095 memset( pNewStackElement, 0, sizeof( IXML_ElementStack ) );
2096 /* the element member includes both prefix and name */
2097
2098 pNewStackElement->element = safe_strdup( newElement->nodeName );
2099 if( pNewStackElement->element == NULL ) {
2100 free( pNewStackElement );
2101 return IXML_INSUFFICIENT_MEMORY;
2102 }
2103
2104 if( newElement->prefix != 0 ) {
2105 pNewStackElement->prefix = safe_strdup( newElement->prefix );
2106 if( pNewStackElement->prefix == NULL ) {
2107 Parser_freeElementStackItem( pNewStackElement );
2108 free( pNewStackElement );
2109 return IXML_INSUFFICIENT_MEMORY;
2110 }
2111 }
2112
2113 if( newElement->namespaceURI != 0 ) {
2114 pNewStackElement->namespaceUri =
2115 safe_strdup( newElement->namespaceURI );
2116 if( pNewStackElement->namespaceUri == NULL ) {
2117 Parser_freeElementStackItem( pNewStackElement );
2118 free( pNewStackElement );
2119 return IXML_INSUFFICIENT_MEMORY;
2120 }
2121 }
2122
2123 pCurElement = xmlParser->pCurElement;
2124
2125 /* insert the new element into the top of the stack */
2126 pNewStackElement->nextElement = pCurElement;
2127 xmlParser->pCurElement = pNewStackElement;
2128
2129 }
2130
2131 return IXML_SUCCESS;
2132 }
2133
2134
2135 /*!
2136 * \brief Reports whether there is a top level element in the parser.
2137 *
2138 * \return 1 if there is a top level element in the parser.
2139 */
isTopLevelElement(Parser * xmlParser)2140 static int isTopLevelElement(
2141 /*! [in] The XML parser. */
2142 Parser *xmlParser)
2143 {
2144 assert(xmlParser);
2145 return xmlParser->pCurElement == NULL;
2146 }
2147
2148
2149 /*!
2150 * \brief Decide whether the current element has default namespace
2151 */
Parser_hasDefaultNamespace(Parser * xmlParser,char ** nsURI)2152 static int Parser_hasDefaultNamespace(
2153 /*! [in] The XML parser. */
2154 Parser *xmlParser,
2155 /*! [in,out] The name space URI. */
2156 char **nsURI )
2157 {
2158 IXML_ElementStack *pCur = xmlParser->pCurElement;
2159
2160 while( pCur != NULL ) {
2161 if( ( pCur->prefix == NULL ) && ( pCur->namespaceUri != NULL ) ) {
2162 *nsURI = pCur->namespaceUri;
2163 return 1;
2164 } else {
2165 pCur = pCur->nextElement;
2166 }
2167 }
2168
2169 return 0;
2170 }
2171
2172
2173 /*!
2174 * \brief Processes element name.
2175 *
2176 * \return IXML_SUCCESS if successful, otherwise or an error code.
2177 */
Parser_processElementName(IXML_Document * rootDoc,Parser * xmlParser,IXML_Node * newNode)2178 static int Parser_processElementName(
2179 /*! [in] The XML document. */
2180 IXML_Document *rootDoc,
2181 /*! [in] The XML parser. */
2182 Parser *xmlParser,
2183 /*! [in] The Node to process. */
2184 IXML_Node *newNode )
2185 {
2186 IXML_Element *newElement = NULL;
2187 char *nsURI = NULL;
2188 int rc = IXML_SUCCESS;
2189
2190 if( xmlParser->bHasTopLevel ) {
2191 if( isTopLevelElement( xmlParser ) ) {
2192 return IXML_SYNTAX_ERR;
2193 }
2194 } else {
2195 xmlParser->bHasTopLevel = 1;
2196 }
2197
2198 xmlParser->savePtr = xmlParser->curPtr;
2199 rc = ixmlDocument_createElementEx( rootDoc, newNode->nodeName, &newElement );
2200 if( rc != IXML_SUCCESS ) {
2201 return rc;
2202 }
2203
2204 rc = ixmlNode_setNodeProperties( ( IXML_Node * ) newElement, newNode );
2205 if( rc != IXML_SUCCESS ) {
2206 ixmlElement_free( newElement );
2207 return rc;
2208 }
2209
2210 if (newNode->prefix) {
2211 /* element has namespace prefix */
2212 if (!Parser_ElementPrefixDefined(xmlParser, newNode, &nsURI)) {
2213 /* read next node to see whether it includes namespace definition */
2214 xmlParser->pNeedPrefixNode = (IXML_Node *)newElement;
2215 } else {
2216 /* fill in the namespace */
2217 Parser_setElementNamespace( newElement, nsURI );
2218 }
2219 } else {
2220 /* does element has default namespace */
2221 /* the node may have default namespace definition */
2222 if (Parser_hasDefaultNamespace(xmlParser, &nsURI)) {
2223 Parser_setElementNamespace(newElement, nsURI);
2224 } else {
2225 switch (xmlParser->state) {
2226 case eATTRIBUTE:
2227 /* the default namespace maybe defined later */
2228 xmlParser->pNeedPrefixNode = (IXML_Node *)newElement;
2229 break;
2230 default:
2231 break;
2232 }
2233 }
2234 }
2235
2236 rc = ixmlNode_appendChild(xmlParser->currentNodePtr, (IXML_Node *)newElement);
2237 if (rc != IXML_SUCCESS) {
2238 ixmlElement_free(newElement);
2239 return rc;
2240 }
2241
2242 xmlParser->currentNodePtr = ( IXML_Node * ) newElement;
2243
2244 /* push element to stack */
2245 rc = Parser_pushElement( xmlParser, ( IXML_Node * ) newElement );
2246 return rc;
2247 }
2248
2249
2250 /*!
2251 * \brief Check if a new node->nodeName matches top of element stack.
2252 *
2253 * \return 1 if matches.
2254 */
Parser_isValidEndElement(Parser * xmlParser,IXML_Node * newNode)2255 static int Parser_isValidEndElement(
2256 /*! [in] The XML parser. */
2257 Parser *xmlParser,
2258 /*! [in] The node. */
2259 IXML_Node *newNode)
2260 {
2261 assert(xmlParser);
2262
2263 if (xmlParser->pCurElement == NULL) {
2264 return 0;
2265 }
2266
2267 assert(xmlParser->pCurElement->element);
2268 assert(newNode);
2269 assert(newNode->nodeName);
2270 return strcmp(xmlParser->pCurElement->element, newNode->nodeName) == 0;
2271 }
2272
2273
2274 /*!
2275 * \brief Remove element from element stack.
2276 */
Parser_popElement(Parser * xmlParser)2277 static void Parser_popElement(
2278 /*! [in] The XML parser. */
2279 Parser *xmlParser)
2280 {
2281 IXML_ElementStack *pCur = NULL;
2282 IXML_NamespaceURI *pnsUri = NULL;
2283 IXML_NamespaceURI *pNextNS = NULL;
2284
2285 pCur = xmlParser->pCurElement;
2286 if (pCur != NULL) {
2287 xmlParser->pCurElement = pCur->nextElement;
2288 Parser_freeElementStackItem(pCur);
2289 pnsUri = pCur->pNsURI;
2290 while (pnsUri != NULL) {
2291 pNextNS = pnsUri->nextNsURI;
2292 Parser_freeNsURI(pnsUri);
2293 free(pnsUri);
2294 pnsUri = pNextNS;
2295 }
2296 free(pCur);
2297 }
2298 }
2299
2300
2301 /*!
2302 * \brief Verifies endof element tag is the same as the openning element tag.
2303 */
Parser_eTagVerification(Parser * xmlParser,IXML_Node * newNode)2304 static int Parser_eTagVerification(
2305 /*! [in] The XML parser. */
2306 Parser *xmlParser,
2307 /*! [in] The Node to process. */
2308 IXML_Node *newNode)
2309 {
2310 assert( newNode->nodeName );
2311 assert( xmlParser->currentNodePtr );
2312
2313 switch( newNode->nodeType ) {
2314 case eELEMENT_NODE:
2315 if( Parser_isValidEndElement( xmlParser, newNode ) ) {
2316 Parser_popElement( xmlParser );
2317 } else {
2318 /* syntax error */
2319 return IXML_SYNTAX_ERR;
2320 }
2321 break;
2322 default:
2323 break;
2324 }
2325
2326 if( strcmp( newNode->nodeName, xmlParser->currentNodePtr->nodeName ) ==
2327 0 ) {
2328 xmlParser->currentNodePtr = xmlParser->currentNodePtr->parentNode;
2329 } else {
2330 return IXML_SYNTAX_ERR;
2331 }
2332
2333 return IXML_SUCCESS;
2334 }
2335
2336
2337 /*!
2338 * \brief Parses the xml file and returns the DOM document tree.
2339 *
2340 * \return
2341 */
Parser_parseDocument(IXML_Document ** retDoc,Parser * xmlParser)2342 static int Parser_parseDocument(
2343 /*! [out] The XML document. */
2344 IXML_Document **retDoc,
2345 /*! [in] The XML parser. */
2346 Parser *xmlParser)
2347 {
2348 IXML_Document *gRootDoc = NULL;
2349 IXML_Node newNode;
2350 int bETag = 0;
2351 IXML_Node *tempNode = NULL;
2352 int rc = IXML_SUCCESS;
2353 IXML_CDATASection *cdataSecNode = NULL;
2354
2355 /* It is important that the node gets initialized here, otherwise things
2356 * can go wrong on the error handler. */
2357 ixmlNode_init( &newNode );
2358
2359 rc = ixmlDocument_createDocumentEx( &gRootDoc );
2360 if( rc != IXML_SUCCESS ) {
2361 goto ErrorHandler;
2362 }
2363
2364 xmlParser->currentNodePtr = ( IXML_Node * ) gRootDoc;
2365
2366 rc = Parser_skipProlog( xmlParser );
2367 if( rc != IXML_SUCCESS ) {
2368 goto ErrorHandler;
2369 }
2370
2371 while( bETag == 0 ) {
2372 /* clear the newNode contents. Redundant on the first iteration,
2373 * but nonetheless, necessary due to the possible calls to
2374 * ErrorHandler above. Currently, this is just a memset to zero. */
2375 ixmlNode_init( &newNode );
2376
2377 if( Parser_getNextNode( xmlParser, &newNode, &bETag ) ==
2378 IXML_SUCCESS ) {
2379 if( bETag == 0 ) {
2380 switch ( newNode.nodeType ) {
2381 case eELEMENT_NODE:
2382 rc = Parser_processElementName( gRootDoc,
2383 xmlParser,
2384 &newNode );
2385 if( rc != IXML_SUCCESS ) {
2386 goto ErrorHandler;
2387 }
2388 break;
2389
2390 case eTEXT_NODE:
2391 rc = ixmlDocument_createTextNodeEx( gRootDoc,
2392 newNode.
2393 nodeValue,
2394 &tempNode );
2395 if( rc != IXML_SUCCESS ) {
2396 goto ErrorHandler;
2397 }
2398
2399 rc = ixmlNode_appendChild( xmlParser->
2400 currentNodePtr,
2401 tempNode );
2402 if( rc != IXML_SUCCESS ) {
2403 goto ErrorHandler;
2404 }
2405
2406 break;
2407
2408 case eCDATA_SECTION_NODE:
2409 rc = ixmlDocument_createCDATASectionEx( gRootDoc,
2410 newNode.
2411 nodeValue,
2412 &cdataSecNode );
2413 if( rc != IXML_SUCCESS ) {
2414 goto ErrorHandler;
2415 }
2416
2417 rc = ixmlNode_appendChild( xmlParser->
2418 currentNodePtr,
2419 &( cdataSecNode->n ) );
2420 if( rc != IXML_SUCCESS ) {
2421 goto ErrorHandler;
2422 }
2423 break;
2424
2425 case eATTRIBUTE_NODE:
2426 rc = Parser_processAttributeName( gRootDoc,
2427 xmlParser,
2428 &newNode );
2429 if( rc != IXML_SUCCESS ) {
2430 goto ErrorHandler;
2431 }
2432 break;
2433
2434 default:
2435 break;
2436 }
2437 } else {
2438 /* ETag==1, endof element tag. */
2439 rc = Parser_eTagVerification( xmlParser, &newNode );
2440 if( rc != IXML_SUCCESS ) {
2441 goto ErrorHandler;
2442 }
2443 xmlParser->state = eCONTENT;
2444 }
2445
2446 /* reset bETag flag */
2447 bETag = 0;
2448
2449 } else if( bETag ) {
2450 /* file is done */
2451 break;
2452 } else {
2453 rc = IXML_FAILED;
2454 goto ErrorHandler;
2455 }
2456 Parser_freeNodeContent( &newNode );
2457
2458 }
2459
2460 if( xmlParser->pCurElement != NULL ) {
2461 rc = IXML_SYNTAX_ERR;
2462 goto ErrorHandler;
2463 }
2464
2465 *retDoc = ( IXML_Document * ) gRootDoc;
2466 Parser_free( xmlParser );
2467 return rc;
2468
2469 ErrorHandler:
2470 Parser_freeNodeContent( &newNode );
2471 ixmlDocument_free( gRootDoc );
2472 Parser_free( xmlParser );
2473 return rc;
2474 }
2475
2476
Parser_isValidXmlName(const DOMString name)2477 int Parser_isValidXmlName(const DOMString name)
2478 {
2479 const char *pstr = NULL;
2480 size_t i = (size_t)0;
2481 size_t nameLen = (size_t)0;
2482
2483 assert(name != NULL);
2484
2485 nameLen = strlen(name);
2486 pstr = name;
2487 if (Parser_isNameChar((int)*pstr, 0)) {
2488 for (i = (size_t)1; i < nameLen; ++i) {
2489 if (Parser_isNameChar((int)*(pstr + i), 1) == 0) {
2490 /* illegal char */
2491 return 0;
2492 }
2493 }
2494 }
2495
2496 return 1;
2497 }
2498
2499
Parser_setErrorChar(char c)2500 void Parser_setErrorChar(char c)
2501 {
2502 g_error_char = c;
2503 }
2504
2505 #ifdef IXML_HAVE_SCRIPTSUPPORT
Parser_setBeforeFree(IXML_BeforeFreeNode_t hndlr)2506 void Parser_setBeforeFree(IXML_BeforeFreeNode_t hndlr)
2507 {
2508 Before_Free_callback = hndlr;
2509 }
2510
Parser_getBeforeFree()2511 IXML_BeforeFreeNode_t Parser_getBeforeFree()
2512 {
2513 return Before_Free_callback;
2514 }
2515 #endif
2516
2517 /*!
2518 * \brief Initializes a xml parser.
2519 *
2520 * \return The parser object or \b NULL if there is not enough memory.
2521 */
Parser_init()2522 static Parser *Parser_init()
2523 {
2524 Parser *newParser = NULL;
2525
2526 newParser = (Parser *)malloc(sizeof (Parser));
2527 if (newParser == NULL) {
2528 return NULL;
2529 }
2530
2531 memset(newParser, 0, sizeof (Parser));
2532 ixml_membuf_init(&(newParser->tokenBuf));
2533 ixml_membuf_init(&(newParser->lastElem));
2534
2535 return newParser;
2536 }
2537
2538
2539 /*!
2540 * \brief Read a xml file or buffer contents into xml parser.
2541 */
Parser_readFileOrBuffer(Parser * xmlParser,const char * xmlFileName,int file)2542 static int Parser_readFileOrBuffer(
2543 /*! [in] The XML parser. */
2544 Parser *xmlParser,
2545 /*! [in] The file name or the buffer to copy, according to the
2546 * parameter "file". */
2547 const char *xmlFileName,
2548 /*! [in] 1 if you want to read from a file, 0 if xmlFileName is
2549 * the buffer to copy to the parser. */
2550 int file)
2551 {
2552 long fileSize = 0;
2553 size_t bytesRead = (size_t)0;
2554 FILE *xmlFilePtr = NULL;
2555
2556 if( file ) {
2557 xmlFilePtr = fopen( xmlFileName, "rb" );
2558 if( xmlFilePtr == NULL ) {
2559 return IXML_NO_SUCH_FILE;
2560 } else {
2561 fseek( xmlFilePtr, 0, SEEK_END );
2562 fileSize = ftell( xmlFilePtr );
2563 if( fileSize <= 0 ) {
2564 fclose( xmlFilePtr );
2565 return IXML_SYNTAX_ERR;
2566 }
2567
2568 xmlParser->dataBuffer = (char *)malloc((size_t)fileSize + (size_t)1);
2569 if( xmlParser->dataBuffer == NULL ) {
2570 fclose( xmlFilePtr );
2571 return IXML_INSUFFICIENT_MEMORY;
2572 }
2573
2574 fseek( xmlFilePtr, 0, SEEK_SET );
2575 bytesRead =
2576 fread(xmlParser->dataBuffer, (size_t)1, (size_t)fileSize, xmlFilePtr);
2577 /* append null */
2578 xmlParser->dataBuffer[bytesRead] = '\0';
2579 fclose( xmlFilePtr );
2580 }
2581 } else {
2582 xmlParser->dataBuffer = safe_strdup( xmlFileName );
2583 if( xmlParser->dataBuffer == NULL ) {
2584 return IXML_INSUFFICIENT_MEMORY;
2585 }
2586 }
2587
2588 return IXML_SUCCESS;
2589 }
2590
2591
2592 /*!
2593 * \brief Parses a xml file and return the DOM tree.
2594 */
Parser_LoadDocument(IXML_Document ** retDoc,const char * xmlFileName,int file)2595 int Parser_LoadDocument(
2596 /*! [out] The output document tree. */
2597 IXML_Document **retDoc,
2598 /*! [in] The file name or the buffer to copy, according to the
2599 * parameter "file". */
2600 const char *xmlFileName,
2601 /*! [in] 1 if you want to read from a file, 0 if xmlFileName is
2602 * the buffer to copy to the parser. */
2603 int file)
2604 {
2605 int rc = IXML_SUCCESS;
2606 Parser *xmlParser = NULL;
2607
2608 xmlParser = Parser_init();
2609 if( xmlParser == NULL ) {
2610 return IXML_INSUFFICIENT_MEMORY;
2611 }
2612
2613 rc = Parser_readFileOrBuffer( xmlParser, xmlFileName, file );
2614 if( rc != IXML_SUCCESS ) {
2615 Parser_free( xmlParser );
2616 return rc;
2617 }
2618
2619 xmlParser->curPtr = xmlParser->dataBuffer;
2620 rc = Parser_parseDocument( retDoc, xmlParser );
2621 return rc;
2622
2623 }
2624
2625
Parser_freeNodeContent(IXML_Node * nodeptr)2626 void Parser_freeNodeContent(IXML_Node *nodeptr)
2627 {
2628 if( nodeptr == NULL ) {
2629 return;
2630 }
2631
2632 if( nodeptr->nodeName != NULL ) {
2633 free( nodeptr->nodeName );
2634 }
2635
2636 if( nodeptr->nodeValue != NULL ) {
2637 free( nodeptr->nodeValue );
2638 }
2639
2640 if( nodeptr->namespaceURI != NULL ) {
2641 free( nodeptr->namespaceURI );
2642 }
2643
2644 if( nodeptr->prefix != NULL ) {
2645 free( nodeptr->prefix );
2646 }
2647
2648 if( nodeptr->localName != NULL ) {
2649 free( nodeptr->localName );
2650 }
2651 }
2652
2653
2654 /*!
2655 * \brief Set the node prefix and localName as defined by the nodeName in the
2656 * form of ns:name.
2657 */
Parser_setNodePrefixAndLocalName(IXML_Node * node)2658 int Parser_setNodePrefixAndLocalName(
2659 /*! [in,out] The Node to process. */
2660 IXML_Node *node)
2661 {
2662 char *pStrPrefix = NULL;
2663 char *pLocalName;
2664 ptrdiff_t nPrefix;
2665
2666 assert( node != NULL );
2667 if( node == NULL ) {
2668 return IXML_FAILED;
2669 }
2670
2671 pStrPrefix = strchr( node->nodeName, ':' );
2672 if( pStrPrefix == NULL ) {
2673 node->prefix = NULL;
2674 node->localName = safe_strdup( node->nodeName );
2675 if( node->localName == NULL ) {
2676 return IXML_INSUFFICIENT_MEMORY;
2677 }
2678
2679 } else {
2680 /* fill in the local name and prefix */
2681 pLocalName = ( char * )pStrPrefix + 1;
2682 nPrefix = pStrPrefix - node->nodeName;
2683 node->prefix = malloc((size_t)nPrefix + (size_t)1);
2684 if (!node->prefix) {
2685 return IXML_INSUFFICIENT_MEMORY;
2686 }
2687
2688 memset(node->prefix, 0, (size_t)nPrefix + (size_t)1);
2689 strncpy(node->prefix, node->nodeName, (size_t)nPrefix);
2690
2691 node->localName = safe_strdup( pLocalName );
2692 if( node->localName == NULL ) {
2693 free( node->prefix );
2694 /* no need to free really, main loop will frees it
2695 * when return code is not success */
2696 node->prefix = NULL;
2697 return IXML_INSUFFICIENT_MEMORY;
2698 }
2699 }
2700
2701 return IXML_SUCCESS;
2702 }
2703
2704