blob: 8670c053112ee7827a92469d95e049109c999af0 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2000-2003 Intel Corporation
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright notice,
12// this list of conditions and the following disclaimer in the documentation
13// and/or other materials provided with the distribution.
14// * Neither name of Intel Corporation nor the names of its contributors
15// may be used to endorse or promote products derived from this software
16// without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
22// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30///////////////////////////////////////////////////////////////////////////
31
32#include <string.h>
33#include "xmlparser.h"
34
35static const char LESSTHAN = '<';
36static const char GREATERTHAN = '>';
37static const char SLASH = '/';
38static const char EQUALS = '=';
39static const char QUOTE = '\"';
40static const char SINGLEQUOTE = '\'';
41
42static const char *WHITESPACE = "\n\t\r ";
43static const char *COMPLETETAG = "/>";
44static const char *ENDTAG = "</";
45static const char *XMLDECL = "<?xml ";
46static const char *XMLDECL2 = "<?xml?";
47static const char *BEGIN_COMMENT = "<!--";
48static const char *END_COMMENT = "-->";
49static const char *BEGIN_PI = "<?";
50static const char *END_PI = "?>";
51static const char *BEGIN_DOCTYPE = "<!DOCTYPE";
52static const char *CDSTART = "<![CDATA[";
53static const char *CDEND = "]]>";
54static const char *DEC_NUMBERS = "0123456789";
55static const char *HEX_NUMBERS = "0123456789ABCDEFabcdef";
56
57
58typedef struct XmlCharInfo
59{
60 unsigned short l,
61 h;
62} XmlCharInfo;
63
64typedef char utf8char[8];
65
66/*==============================================================================*
67* Letter table contains all characters in XML 1.0 plus ":", "_" and
68* ideographic.
69*
70* This table contains all the characters that an element name can start with.
71* See XML 1.0 (2nd Edition) for more details.
72*
73*===============================================================================*/
74static XmlCharInfo Letter[] =
75{
76 {0x003A, 0x003A}, // character ":"
77 {0x0041, 0x005A},
78 {0x005F, 0x005F}, // character "_"
79 {0x0061, 0x007A}, {0x00C0, 0x00D6}, {0x00D8, 0x00F6}, {0x00F8, 0x00FF},
80 {0x0100, 0x0131}, {0x0134, 0x013E}, {0x0141, 0x0148}, {0x014A, 0x017E},
81 {0x0180, 0x01C3}, {0x01CD, 0x01F0}, {0x01F4, 0x01F5}, {0x01FA, 0x0217},
82 {0x0250, 0x02A8}, {0x02BB, 0x02C1}, {0x0386, 0x0386}, {0x0388, 0x038A},
83 {0x038C, 0x038C}, {0x038E, 0x03A1}, {0x03A3, 0x03CE}, {0x03D0, 0x03D6},
84 {0x03DA, 0x03DA},
85 {0x03DC, 0x03DC}, {0x03DE, 0x03DE}, {0x03E0, 0x03E0}, {0x03E2, 0x03F3},
86 {0x0401, 0x040C}, {0x040E, 0x044F}, {0x0451, 0x045C}, {0x045E, 0x0481},
87 {0x0490, 0x04C4}, {0x04C7, 0x04C8}, {0x04CB, 0x04CC}, {0x04D0, 0x04EB},
88 {0x04EE, 0x04F5}, {0x04F8, 0x04F9}, {0x0531, 0x0556}, {0x0559, 0x0559},
89 {0x0561, 0x0586}, {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x0621, 0x063A},
90 {0x0641, 0x064A}, {0x0671, 0x06B7}, {0x06BA, 0x06BE}, {0x06C0, 0x06CE},
91 {0x06D0, 0x06D3}, {0x06D5, 0x06D5}, {0x06E5, 0x06E6}, {0x0905, 0x0939},
92 {0x093D, 0x093D}, {0x0958, 0x0961}, {0x0985, 0x098C}, {0x098F, 0x0990},
93 {0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9},
94 {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09F0, 0x09F1}, {0x0A05, 0x0A0A},
95 {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, {0x0A32, 0x0A33},
96 {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E},
97 {0x0A72, 0x0A74}, {0x0A85, 0x0A8B}, {0x0A8D, 0x0A8D}, {0x0A8F, 0x0A91},
98 {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9},
99 {0x0ABD, 0x0ABD}, {0x0AE0, 0x0AE0}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10},
100 {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B36, 0x0B39},
101 {0x0B3D, 0x0B3D}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B85, 0x0B8A},
102 {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C},
103 {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB5},
104 {0x0BB7, 0x0BB9}, {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28},
105 {0x0C2A, 0x0C33}, {0x0C35, 0x0C39}, {0x0C60, 0x0C61}, {0x0C85, 0x0C8C},
106 {0x0C8E, 0x0C90}, {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
107 {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, {0x0D05, 0x0D0C}, {0x0D0E, 0x0D10},
108 {0x0D12, 0x0D28}, {0x0D2A, 0x0D39}, {0x0D60, 0x0D61}, {0x0E01, 0x0E2E},
109 {0x0E30, 0x0E30}, {0x0E32, 0x0E33}, {0x0E40, 0x0E45}, {0x0E81, 0x0E82},
110 {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, {0x0E8D, 0x0E8D},
111 {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5},
112 {0x0EA7, 0x0EA7}, {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EAE}, {0x0EB0, 0x0EB0},
113 {0x0EB2, 0x0EB3}, {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0F40, 0x0F47},
114 {0x0F49, 0x0F69}, {0x10A0, 0x10C5}, {0x10D0, 0x10F6}, {0x1100, 0x1100},
115 {0x1102, 0x1103}, {0x1105, 0x1107}, {0x1109, 0x1109}, {0x110B, 0x110C},
116 {0x110E, 0x1112}, {0x113C, 0x113C}, {0x113E, 0x113E}, {0x1140, 0x1140},
117 {0x114C, 0x114C}, {0x114E, 0x114E}, {0x1150, 0x1150}, {0x1154, 0x1155},
118 {0x1159, 0x1159}, {0x115F, 0x1161}, {0x1163, 0x1163}, {0x1165, 0x1165},
119 {0x1167, 0x1167}, {0x1169, 0x1169}, {0x116D, 0x116E}, {0x1172, 0x1173},
120 {0x1175, 0x1175}, {0x119E, 0x119E}, {0x11A8, 0x11A8}, {0x11AB, 0x11AB},
121 {0x11AE, 0x11AF}, {0x11B7, 0x11B8}, {0x11BA, 0x11BA}, {0x11BC, 0x11C2},
122 {0x11EB, 0x11EB}, {0x11F0, 0x11F0}, {0x11F9, 0x11F9}, {0x1E00, 0x1E9B},
123 {0x1EA0, 0x1EF9}, {0x1F00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
124 {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
125 {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC},
126 {0x1FBE, 0x1FBE}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3},
127 {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC},
128 {0x2126, 0x2126}, {0x212A, 0x212B}, {0x212E, 0x212E}, {0x2180, 0x2182},
129 {0x3007, 0x3007}, {0x3021, 0x3029}, // these two are ideographic
130 {0x3041, 0x3094}, {0x30A1, 0x30FA}, {0x3105, 0x312C},
131 {0x4E00, 0x9FA5}, // ideographic
132 {0xAC00, 0xD7A3}
133};
134
135#define LETTERTABLESIZE (sizeof(Letter)/sizeof(Letter[0]))
136
137/*==============================================================================*
138* NameChar table contains
139* CombiningChar, Extender, Digit, '-', '.', less '_', ':'
140* NameChar ::= Digit | '-' | '.' | CombiningChar | Extender
141* See XML 1.0 2nd Edition
142*
143*===============================================================================*/
144static XmlCharInfo NameChar[] =
145{
146 {0x002D, 0x002D}, // character "-"
147 {0x002E, 0x002E}, // character "."
148 {0x0030, 0x0039}, // digit
149 {0x00B7, 0x00B7}, {0x02D0, 0x02D0}, {0x02D1, 0x02D1}, // extended
150 {0x0300, 0x0345}, {0x0360, 0x0361},
151 {0x0387, 0x0387}, // extended
152 {0x0483, 0x0486}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
153 {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C4},
154 {0x0640, 0x0640}, // extended
155 {0x064B, 0x0652},
156 {0x0660, 0x0669}, // digit
157 {0x0670, 0x0670},
158 {0x06D6, 0x06DC}, {0x06DD, 0x06DF}, {0x06E0, 0x06E4}, {0x06E7, 0x06E8},
159 {0x06EA, 0x06ED},
160 {0x06F0, 0x06F9}, // digit
161 {0x0901, 0x0903}, {0x093C, 0x093C},
162 {0x093E, 0x094C}, {0x094D, 0x094D}, {0x0951, 0x0954}, {0x0962, 0x0963},
163 {0x0966, 0x096F}, // digit
164 {0x0981, 0x0983}, {0x09BC, 0x09BC}, {0x09BE, 0x09BE},
165 {0x09BF, 0x09BF}, {0x09C0, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CD},
166 {0x09D7, 0x09D7}, {0x09E2, 0x09E3},
167 {0x09E6, 0x09EF}, // digit
168 {0x0A02, 0x0A02},
169 {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A3E}, {0x0A3F, 0x0A3F}, {0x0A40, 0x0A42},
170 {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
171 {0x0A66, 0x0A6F}, // digit
172 {0x0A70, 0x0A71},
173 {0x0A81, 0x0A83}, {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9},
174 {0x0ACB, 0x0ACD},
175 {0x0AE6, 0x0AEF}, // digit
176 {0x0B01, 0x0B03}, {0x0B3C, 0x0B3C},
177 {0x0B3E, 0x0B43}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57},
178 {0x0B66, 0x0B6F}, // digit
179 {0x0B82, 0x0B83}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8},
180 {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7},
181 {0x0BE7, 0x0BEF}, // digit
182 {0x0C01, 0x0C03},
183 {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
184 {0x0C66, 0x0C6F}, // digit
185 {0x0C82, 0x0C83}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8},
186 {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6},
187 {0x0CE6, 0x0CEF}, // digit
188 {0x0D02, 0x0D03},
189 {0x0D3E, 0x0D43}, {0x0D46, 0x0D48}, {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57},
190 {0x0D66, 0x0D6F}, // digit
191 {0x0E31, 0x0E31}, {0x0E34, 0x0E3A},
192 {0x0E46, 0x0E46}, // extended
193 {0x0E47, 0x0E4E},
194 {0x0E50, 0x0E59}, // digit
195 {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9},
196 {0x0EBB, 0x0EBC},
197 {0x0EC6, 0x0EC6}, // extended
198 {0x0EC8, 0x0ECD},
199 {0x0ED0, 0x0ED9}, // digit
200 {0x0F18, 0x0F19},
201 {0x0F20, 0x0F29}, // digit
202 {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
203 {0x0F39, 0x0F39}, {0x0F3E, 0x0F3E}, {0x0F3F, 0x0F3F}, {0x0F71, 0x0F84},
204 {0x0F86, 0x0F8B}, {0x0F90, 0x0F95}, {0x0F97, 0x0F97}, {0x0F99, 0x0FAD},
205 {0x0FB1, 0x0FB7}, {0x0FB9, 0x0FB9}, {0x20D0, 0x20DC}, {0x20E1, 0x20E1},
206 {0x3005, 0x3005}, // extended
207 {0x302A, 0x302F},
208 {0x3031, 0x3035}, // extended
209 {0x3099, 0x3099}, {0x309A, 0x309A}, // combining char
210 {0x309D, 0x309E}, {0x30FC, 0x30FE} // extended
211};
212
213#define NAMECHARTABLESIZE (sizeof(NameChar)/sizeof(NameChar[0]))
214
215static int XMLStrncasecmp(const char * s1, const char * s2, size_t n)
216{
217 if (!s1 || !s2)
218 {
219 return -1;
220 }
221#ifdef WIN32
222
223 if (n == 0)
224 return 0;
225
226 while (n-- != 0 && tolower(*s1) == tolower(*s2))
227 {
228 if (n == 0 || *s1 == '\0' || *s2 == '\0')
229 break;
230 s1++;
231 s2++;
232 }
233
234 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
235#else
236 return strncasecmp(s1, s2, n);
237#endif
238}
239
240
241
242// functions used in this file
243static void XMLParserFree(
244 Pool * pool,
245 XMLParser * myParser );
246static int XMLParserSkipDocType( char **pstr );
247static int XMLParserSkipProlog( XMLParser * xmlParser );
248static int XMLParserSkipMisc( XMLParser * xmlParser );
249static void XMLParserFreeElementStackItem(
250 Pool * pool,
251 XmlElementStack * pItem );
252static void XMLParserFreeNsURI(
253 Pool * pool,
254 XmlNameSpaceURI * pNsURI );
255
256static int XMLParserGetNextNode(
257 Pool * pool,
258 XMLParser * myParser,
259 XmlNode * newNode,
260 BOOL * isEnd );
261static int XMLParserGetNextToken(
262 Pool * pool,
263 XMLParser * myParser );
264static int XMLParserXmlNamespace(
265 Pool * pool,
266 XMLParser * myParser,
267 XmlNode * newNode );
268static BOOL XMLParserElementPrefixDefined( XMLParser * myParser,
269 XmlNode * newNode,
270 char **nsURI );
271static int XMLParserSetElementNamespace(
272 Pool * pool,
273 XmlElement * newElement,
274 char *nsURI );
275static int XMLParserParseDocument(
276 Pool * pool,
277
278 XmlDocument ** retDoc,
279 XMLParser * domParser );
280static BOOL XMLParserHasDefaultNamespace( XMLParser * xmlParser,
281 XmlNode * newNode,
282 char **nsURI );
283static int XMLParserGetChar( IN char *src,
284 INOUT int *cLen );
285
286/*==============================================================================*
287* XMLParserIsCharInTable
288* will determine whether character c is in the table of tbl
289* (either Letter table or NameChar table)
290*
291*===============================================================================*/
292static BOOL
293XMLParserIsCharInTable( IN int c,
294 IN XmlCharInfo * tbl,
295 IN int sz )
296{
297 int t = 0,
298 b = sz,
299 m;
300
301 while ( t <= b )
302 {
303 m = ( t + b ) / 2;
304 if ( c < tbl[m].l )
305 {
306 b = m - 1;
307 }
308 else if ( c > tbl[m].h )
309 {
310 t = m + 1;
311 }
312 else
313 {
314 return TRUE;
315 }
316 }
317 return FALSE;
318}
319
320/*==============================================================================*
321* XMLParserIsXmlChar
322* see XML 1.0 (2nd Edition) 2.2.
323* Internal to parser only
324*
325*===============================================================================*/
326static BOOL
327XMLParserIsXmlChar( IN int c )
328{
329 return ( c == 0x9 || c == 0xA || c == 0xD ||
330 ( c >= 0x20 && c <= 0xD7FF ) ||
331 ( c >= 0xE000 && c <= 0xFFFD ) ||
332 ( c >= 0x10000 && c <= 0x10FFFF ) );
333}
334
335/*==============================================================================*
336* XMLParserIsNameChar
337* check whether c (int) is in LetterTable or NameCharTable
338* Internal to parser only.
339*
340*===============================================================================*/
341static BOOL
342XMLParserIsNameChar( IN int c,
343 IN BOOL bNameChar )
344{
345 if ( XMLParserIsCharInTable( c, Letter, LETTERTABLESIZE ) )
346 {
347 return TRUE;
348 }
349
350 if ( bNameChar
351 && XMLParserIsCharInTable( c, NameChar, NAMECHARTABLESIZE ) )
352 {
353 return TRUE;
354 }
355 return FALSE;
356}
357
358/*==============================================================================*
359* XmlParserIsValidXmlName
360* Check to see whether name is a valid xml name.
361* External function.
362*
363*===============================================================================*/
364BOOL
365XmlParserIsValidXmlName( const char * name )
366{
367 char *pstr = NULL;
368 int i = 0,
369 nameLen = 0;
370
371 assert( name != NULL );
372
373 nameLen = strlen( name );
374
375 pstr = (char *)name;
376 if ( XMLParserIsNameChar( *pstr, FALSE ) == TRUE )
377 {
378 for ( i = 1; i < nameLen; i++ )
379 {
380 if ( XMLParserIsNameChar( *( pstr + 1 ), TRUE ) == FALSE ) //illegal char
381 {
382 return FALSE;
383 }
384 }
385 }
386
387 return TRUE;
388}
389
390/*==============================================================================*
391* XMLParserIntToUTF8:
392* Encoding a character to its UTF-8 character string, and return its length
393* internal function.
394*
395*===============================================================================*/
396static int
397XMLParserIntToUTF8( IN int c,
398 IN utf8char s )
399{
400 if ( c < 0 )
401 {
402 return 0;
403 }
404
405 if ( c <= 127 )
406 {
407 s[0] = c;
408 s[1] = 0;
409 return 1;
410 }
411 else if ( c <= 0x07FF ) // 0x0080 < c <= 0x07FF
412 {
413 s[0] = 0xC0 | ( c >> 6 );
414 s[1] = 0x80 | ( c & 0x3f );
415 s[2] = 0;
416 return 2;
417 }
418 else if ( c <= 0xFFFF ) // 0x0800 < c <= 0xFFFF
419 {
420 s[0] = 0xE0 | ( c >> 12 );
421 s[1] = 0x80 | ( ( c >> 6 ) & 0x3f );
422 s[2] = 0x80 | ( c & 0x3f );
423 s[3] = 0;
424 return 3;
425 }
426 else if ( c <= 0x1FFFFF ) // 0x10000 < c <= 0x1FFFFF
427 {
428 s[0] = 0xF0 | ( c >> 18 );
429 s[1] = 0x80 | ( ( c >> 12 ) & 0x3f );
430 s[2] = 0x80 | ( ( c >> 6 ) & 0x3f );
431 s[3] = 0x80 | ( c & 0x3f );
432 s[4] = 0;
433 return 4;
434 }
435 else if ( c <= 0x3FFFFFF ) // 0x200000 < c <= 3FFFFFF
436 {
437 s[0] = 0xF8 | ( c >> 24 );
438 s[1] = 0x80 | ( ( c >> 18 ) & 0x3f );
439 s[2] = 0x80 | ( ( c >> 12 ) & 0x3f );
440 s[3] = 0x80 | ( ( c >> 6 ) & 0x3f );
441 s[4] = 0x80 | ( c & 0x3f );
442 s[5] = 0;
443 return 5;
444 }
445#if 1
446 else // 0x4000000 < c <= 7FFFFFFF
447 {
448 s[0] = 0xFC | ( c >> 30 );
449 s[1] = 0x80 | ( ( c >> 24 ) & 0x3f );
450 s[2] = 0x80 | ( ( c >> 18 ) & 0x3f );
451 s[3] = 0x80 | ( ( c >> 12 ) & 0x3f );
452 s[4] = 0x80 | ( ( c >> 6 ) & 0x3f );
453 s[5] = 0x80 | ( c & 0x3f );
454 s[6] = 0;
455 return 6;
456 }
457
458#else
459 else if ( c <= 0x7FFFFFFF ) // 0x4000000 < c <= 7FFFFFFF
460 {
461 s[0] = 0xFC | ( c >> 30 );
462 s[1] = 0x80 | ( ( c >> 24 ) & 0x3f );
463 s[2] = 0x80 | ( ( c >> 18 ) & 0x3f );
464 s[3] = 0x80 | ( ( c >> 12 ) & 0x3f );
465 s[4] = 0x80 | ( ( c >> 6 ) & 0x3f );
466 s[5] = 0x80 | ( c & 0x3f );
467 s[6] = 0;
468 return 6;
469 }
470 else // illegal
471 {
472 return 0;
473 }
474#endif
475}
476
477/*==============================================================================*
478* Parser_UTF8ToInt
479* In UTF-8, characters are encoded using sequences of 1 to 6 octets.
480* This functions will return a UTF-8 character value and its octets number.
481* Internal to parser only.
482* Internal to parser only
483*
484*===============================================================================*/
485static int
486Parser_UTF8ToInt( IN char *ss,
487 OUT int *len )
488{
489
490 unsigned char *s = ( unsigned char * )ss;
491 int c = *s;
492
493 if ( c <= 127 ) // if c<=127, c is just the character.
494 {
495 *len = 1;
496 return c;
497 }
498 else if ( ( c & 0xE0 ) == 0xC0 && ( s[1] & 0xc0 ) == 0x80 ) // a sequence of 110xxxxx and 10xxxxxx?
499 {
500 *len = 2;
501 return ( ( ( c & 0x1f ) << 6 ) | ( s[1] & 0x3f ) );
502 }
503 else if ( ( c & 0xF0 ) == 0xE0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 ) // a sequence of 1110xxxx,10xxxxxx and 10xxxxxx ?
504 {
505 *len = 3;
506 return ( ( ( c & 0xf ) << 12 ) | ( ( s[1] & 0x3f ) << 6 ) |
507 ( s[2] & 0x3f ) );
508 }
509 else if ( ( c & 0xf8 ) == 0xf0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 ) // a sequence of 11110xxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
510 {
511 *len = 4;
512 return ( ( ( c & 0x7 ) << 18 ) | ( ( s[1] & 0x3f ) << 12 ) |
513 ( ( s[2] & 0x3f ) << 6 ) | ( s[3] & 0x3f ) );
514 }
515 else if ( ( c & 0xfc ) == 0xf8 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 ) // a sequence of 111110xx,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx ?
516 {
517 *len = 5;
518 return ( ( ( c & 0x3 ) << 24 ) | ( ( s[1] & 0x3f ) << 18 ) |
519 ( ( s[2] & 0x3f ) << 12 ) | ( ( s[3] & 0x3f ) << 6 ) |
520 ( s[4] & 0x3f ) );
521 }
522 else if ( ( c & 0xfe ) == 0xfc && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 && ( s[5] & 0xc0 ) == 0x80 ) // a sequence of 1111110x,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
523 {
524 *len = 6;
525 return ( ( ( c & 0x1 ) << 30 ) | ( ( s[1] & 0x3f ) << 24 ) |
526 ( ( s[2] & 0x3f ) << 18 ) | ( ( s[3] & 0x3f ) << 12 ) |
527 ( ( s[4] & 0x3f ) << 6 ) | ( s[5] & 0x3f ) );
528 }
529 else // none of above, error
530 {
531 *len = 0;
532 return -1;
533 }
534}
535
536/*==============================================================================*
537* ParserInit
538* Initializes a xml parser.
539* Internal to parser only
540*
541*===============================================================================*/
542static XMLParser *
543
544
545#ifdef USE_CWMP_MEMORY_POOL
546ParserInit( Pool * pool )
547
548#else
549ParserInit( )
550#endif
551
552{
553 XMLParser *newParser = NULL;
554
555 newParser = ( XMLParser * ) PMALLOC( sizeof( XMLParser ) );
556 if ( newParser == NULL )
557 {
558 return NULL;
559 }
560
561 memset( newParser, 0, sizeof( XMLParser ) );
562
563 XmlBufferInit( &( newParser->tokenBuf ) );
564 XmlBufferInit( &( newParser->lastElem ) );
565
566 return newParser;
567}
568
569/*================================================================
570* XMLParserIsValidEndElement
571* check if a new node->nodeName matches top of element stack.
572* Internal to parser only.
573*
574*=================================================================*/
575static int
576XMLParserIsValidEndElement( XMLParser * xmlParser,
577 XmlNode * newNode )
578{
579 return ( strcmp( xmlParser->pCurElement->element, newNode->nodeName )
580 == 0 );
581}
582
583/*===============================================================
584* Parser_pushElement
585* push a new element onto element stack
586* Internal to parser only.
587*
588*=================================================================*/
589static int
590#ifdef USE_CWMP_MEMORY_POOL
591Parser_pushElement(Pool * pool, XMLParser * xmlParser,
592#else
593Parser_pushElement( XMLParser * xmlParser,
594#endif
595
596
597 XmlNode * newElement )
598{
599
600 XmlElementStack *pCurElement = NULL;
601 XmlElementStack *pNewStackElement = NULL;
602
603// assert( newElement );
604 if ( newElement != NULL )
605 {
606 // push new element
607 pNewStackElement =
608 ( XmlElementStack * ) PMALLOC( sizeof( XmlElementStack ) );
609 if ( pNewStackElement == NULL )
610 {
611 return XML_INSUFFICIENT_MEMORY;
612 }
613
614 memset( pNewStackElement, 0, sizeof( XmlElementStack ) );
615 // the element member includes both prefix and name
616
617 pNewStackElement->element = PSTRDUP( newElement->nodeName );
618 if ( pNewStackElement->element == NULL )
619 {
620 PFREE( pNewStackElement );
621 return XML_INSUFFICIENT_MEMORY;
622 }
623
624 if ( newElement->prefix != 0 )
625 {
626 pNewStackElement->prefix = PSTRDUP( newElement->prefix );
627 if ( pNewStackElement->prefix == NULL )
628 {
629 XMLParserFreeElementStackItem(
630#ifdef USE_CWMP_MEMORY_POOL
631 pool ,
632#endif
633 pNewStackElement );
634 PFREE( pNewStackElement );
635 return XML_INSUFFICIENT_MEMORY;
636 }
637 }
638
639 if ( newElement->namespaceURI != 0 )
640 {
641 pNewStackElement->namespaceUri =
642 PSTRDUP( newElement->namespaceURI );
643 if ( pNewStackElement->namespaceUri == NULL )
644 {
645 XMLParserFreeElementStackItem(
646#ifdef USE_CWMP_MEMORY_POOL
647 pool ,
648#endif
649 pNewStackElement );
650 PFREE( pNewStackElement );
651 return XML_INSUFFICIENT_MEMORY;
652 }
653 }
654
655 pCurElement = xmlParser->pCurElement;
656
657 // insert the new element into the top of the stack
658 pNewStackElement->nextElement = pCurElement;
659 xmlParser->pCurElement = pNewStackElement;
660
661 }
662
663 return XML_OK;
664}
665
666/*================================================================
667* ParserPopElement
668* Remove element from element stack.
669* Internal to parser only.
670*
671*=================================================================*/
672static void
673ParserPopElement(
674 Pool * pool,
675 XMLParser * xmlParser )
676{
677 XmlElementStack *pCur = NULL;
678 XmlNameSpaceURI *pnsUri = NULL,
679 *pNextNS = NULL;
680
681 pCur = xmlParser->pCurElement;
682 if ( pCur != NULL )
683 {
684 xmlParser->pCurElement = pCur->nextElement;
685
686 XMLParserFreeElementStackItem(
687#ifdef USE_CWMP_MEMORY_POOL
688 pool ,
689#endif
690 pCur );
691
692 pnsUri = pCur->pNsURI;
693 while ( pnsUri != NULL )
694 {
695 pNextNS = pnsUri->nextNsURI;
696
697 XMLParserFreeNsURI(
698#ifdef USE_CWMP_MEMORY_POOL
699 pool ,
700#endif
701 pnsUri );
702 PFREE( pnsUri );
703 pnsUri = pNextNS;
704 }
705
706 PFREE( pCur );
707 }
708
709}
710
711
712
713static char* check_file(char * filepath)
714{
715#if 0
716 char type[6] = {0};
717
718 if(strncmp(filepath,".xml",4) == 0 )
719 {
720 return NULL;
721 }
722
723 strncpy(type,filepath+(strlen(filepath))-4, 4);
724
725// cwmp_log_info("file type is :%s", type);
726
727 if( strncmp(type, ".xml", 4) == 0)
728 {
729 return filepath;
730 }
731
732 return NULL;
733#endif
734
735 if(strncmp(filepath, "./", 2) == 0 || strncmp(filepath, "../", 3) == 0)
736 {
737 return NULL;
738 }
739
740 return filepath;
741}
742
743/*================================================================
744* ParserReadFileOrBuffer
745* read a xml file or buffer contents into xml parser.
746* Internal to parser only.
747*
748*=================================================================*/
749static int
750
751#ifdef USE_CWMP_MEMORY_POOL
752ParserReadFileOrBuffer(Pool * pool, XMLParser * xmlParser,
753#else
754ParserReadFileOrBuffer( XMLParser * xmlParser,
755#endif
756 IN char *xmlFileName,
757 IN BOOL file )
758{
759 int fileSize = 0;
760 int bytesRead = 0;
761 FILE *xmlFilePtr = NULL;
762
763 char *pxmlFileName = NULL;
764
765 if ( file )
766 {
767 pxmlFileName = check_file(xmlFileName);
768 if(NULL == pxmlFileName)
769 {
770// cwmp_log_error("%s not xml file", xmlFileName);
771 return XML_NO_SUCH_FILE;
772 }
773
774 xmlFilePtr = fopen( pxmlFileName, "rb" );
775 if ( xmlFilePtr == NULL )
776 {
777 return XML_NO_SUCH_FILE;
778 }
779 else
780 {
781 fseek( xmlFilePtr, 0, SEEK_END );
782 fileSize = ftell( xmlFilePtr );
783 if ( fileSize <= 0 )
784 {
785 fclose( xmlFilePtr );
786 return XML_SYNTAX_ERR;
787 }
788
789 xmlParser->dataBuffer = ( char * )PMALLOC( fileSize + 1 );
790 if ( xmlParser->dataBuffer == NULL )
791 {
792 fclose( xmlFilePtr );
793 return XML_INSUFFICIENT_MEMORY;
794 }
795
796 fseek( xmlFilePtr, 0, SEEK_SET );
797 bytesRead =
798 fread( xmlParser->dataBuffer, 1, fileSize, xmlFilePtr );
799 xmlParser->dataBuffer[bytesRead] = '\0'; // append null
800 fclose( xmlFilePtr );
801 }
802 }
803 else
804 {
805 xmlParser->dataBuffer = PSTRDUP( xmlFileName );
806 if ( xmlParser->dataBuffer == NULL )
807 {
808 return XML_INSUFFICIENT_MEMORY;
809 }
810 }
811
812 return XML_OK;
813}
814
815/*================================================================
816* XmlParserLoadDocument
817* parses a xml file and return the DOM tree.
818* Internal to parser only
819*
820*=================================================================*/
821int
822XmlParserLoadDocument(
823 Pool * pool,
824 OUT XmlDocument ** retDoc,
825 IN char *xmlFileName,
826 IN BOOL file )
827{
828 int rc = XML_OK;
829 XMLParser *xmlParser = NULL;
830
831 xmlParser = ParserInit(
832#ifdef USE_CWMP_MEMORY_POOL
833 pool
834#endif
835
836 );
837 if ( xmlParser == NULL )
838 {
839 return XML_INSUFFICIENT_MEMORY;
840 }
841
842 rc = ParserReadFileOrBuffer(
843#ifdef USE_CWMP_MEMORY_POOL
844 pool ,
845#endif
846 xmlParser, xmlFileName, file );
847 if ( rc != XML_OK )
848 {
849 XMLParserFree(
850#ifdef USE_CWMP_MEMORY_POOL
851 pool ,
852#endif
853 xmlParser );
854 return rc;
855 }
856
857 xmlParser->curPtr = xmlParser->dataBuffer;
858 rc = XMLParserParseDocument(
859#ifdef USE_CWMP_MEMORY_POOL
860 pool ,
861#endif
862
863 retDoc, xmlParser );
864 return rc;
865
866}
867
868/*================================================================
869* isTopLevelElement
870* decides whether we have top level element already.
871* Internal to parser only.
872*
873*=================================================================*/
874static int
875isTopLevelElement( XMLParser * xmlParser )
876{
877 assert( xmlParser );
878 return ( xmlParser->pCurElement == NULL );
879}
880
881/*================================================================
882* isDuplicateAttribute
883* Decide whether the new attribute is the same as an
884* existing one.
885* Internal to parser only.
886*
887*=================================================================*/
888static int
889isDuplicateAttribute( XMLParser * xmlParser,
890 XmlNode * newAttrNode )
891{
892 XmlNode * elementNode = NULL;
893 XmlNode * attrNode = NULL;
894
895 elementNode = xmlParser->currentNodePtr;
896 attrNode = elementNode->firstAttr;
897 while ( attrNode != NULL )
898 {
899 if ( strcmp( attrNode->nodeName, newAttrNode->nodeName ) == 0 )
900 {
901 return TRUE;
902 }
903
904 attrNode = attrNode->nextSibling;
905 }
906
907 return FALSE;
908}
909
910/*================================================================
911* XMLParserProcessAttributeName
912* processes the attribute name.
913* Internal to parser only.
914*
915*=================================================================*/
916static int
917XMLParserProcessAttributeName(
918 Pool * pool,
919 XmlDocument * rootDoc,
920 XMLParser * xmlParser,
921 XmlNode * newNode )
922{
923 XmlAttribute *attr = NULL;
924 int rc = XML_OK;
925
926 if ( isDuplicateAttribute( xmlParser, newNode ) == TRUE )
927 {
928 return XML_SYNTAX_ERR;
929 }
930
931 rc = XmlDocCreateAttributeEx(
932#ifdef USE_CWMP_MEMORY_POOL
933 pool ,
934#endif
935 rootDoc, newNode->nodeName,
936 &attr );
937 if ( rc != XML_OK )
938 {
939 return rc;
940 }
941
942 rc = XmlNodeSetNodeProperties(
943#ifdef USE_CWMP_MEMORY_POOL
944 pool ,
945#endif
946 ( XmlNode * ) attr, newNode );
947 if ( rc != XML_OK )
948 {
949 return rc;
950 }
951
952 rc = XmlElementSetAttributeNode(
953
954 ( XmlElement * ) xmlParser->currentNodePtr, attr, NULL );
955 return rc;
956}
957
958/*================================================================
959* ParserProcessElementName
960* Processes element name
961* Internal to parser only.
962*
963*=================================================================*/
964static int
965ParserProcessElementName(
966 Pool * pool,
967
968 XmlDocument * rootDoc,
969 XMLParser * xmlParser,
970 XmlNode * newNode )
971{
972 XmlElement *newElement = NULL;
973 char *nsURI = NULL;
974 int rc = XML_OK;
975
976 if ( xmlParser->bHasTopLevel == TRUE )
977 {
978 if ( isTopLevelElement( xmlParser ) == TRUE )
979 {
980 return XML_SYNTAX_ERR;
981 }
982 }
983 else
984 {
985 xmlParser->bHasTopLevel = TRUE;
986 }
987
988 xmlParser->savePtr = xmlParser->curPtr;
989 rc = XmlDocCreateElementEx(
990#ifdef USE_CWMP_MEMORY_POOL
991 pool ,
992#endif
993 rootDoc, newNode->nodeName,
994 &newElement );
995 if ( rc != XML_OK )
996 {
997 return rc;
998 }
999
1000 rc = XmlNodeSetNodeProperties(
1001#ifdef USE_CWMP_MEMORY_POOL
1002 pool ,
1003#endif
1004 ( XmlNode * ) newElement, newNode );
1005 if ( rc != XML_OK )
1006 {
1007 XmlElementFree(
1008#ifdef USE_CWMP_MEMORY_POOL
1009 pool ,
1010#endif
1011 newElement );
1012 return rc;
1013 }
1014
1015 if ( newNode->prefix != NULL ) // element has namespace prefix
1016 {
1017 if ( XMLParserElementPrefixDefined( xmlParser, newNode, &nsURI ) !=
1018 TRUE )
1019 {
1020 // read next node to see whether it includes namespace definition
1021 xmlParser->pNeedPrefixNode = ( XmlNode * ) newElement;
1022 }
1023 else // fill in the namespace
1024 {
1025 XMLParserSetElementNamespace(
1026#ifdef USE_CWMP_MEMORY_POOL
1027 pool ,
1028#endif
1029 newElement, nsURI );
1030 }
1031 }
1032 else // does element has default namespace
1033 {
1034 // the node may have default namespace definition
1035 if ( XMLParserHasDefaultNamespace( xmlParser, newNode, &nsURI ) ==
1036 TRUE )
1037 {
1038 XMLParserSetElementNamespace(
1039#ifdef USE_CWMP_MEMORY_POOL
1040 pool ,
1041#endif
1042 newElement, nsURI );
1043 }
1044 else if ( xmlParser->state == E_ATTRIBUTE )
1045 {
1046 // the default namespace maybe defined later
1047 xmlParser->pNeedPrefixNode = ( XmlNode * ) newElement;
1048 }
1049 }
1050
1051 rc = XmlNodeAppendChild( xmlParser->currentNodePtr,
1052 ( XmlNode * ) newElement );
1053 if ( rc != XML_OK )
1054 {
1055 XmlElementFree(
1056#ifdef USE_CWMP_MEMORY_POOL
1057 pool ,
1058#endif
1059 newElement );
1060 return rc;
1061 }
1062
1063 xmlParser->currentNodePtr = ( XmlNode * ) newElement;
1064
1065 // push element to stack
1066 rc = Parser_pushElement(
1067#ifdef USE_CWMP_MEMORY_POOL
1068 pool ,
1069#endif
1070
1071 xmlParser, ( XmlNode * ) newElement );
1072 return rc;
1073}
1074
1075/*================================================================
1076* ParserETagVerification
1077* Verifies endof element tag is the same as the openning
1078* element tag.
1079* Internal to parser only.
1080*
1081*=================================================================*/
1082static int
1083ParserETagVerification(
1084 Pool * pool,
1085 XMLParser * xmlParser,
1086 XmlNode * newNode )
1087{
1088
1089 assert( newNode->nodeName );
1090 assert( xmlParser->currentNodePtr );
1091
1092 if ( newNode->nodeType == XML_ELEMENT_NODE )
1093 {
1094 if ( XMLParserIsValidEndElement( xmlParser, newNode ) == TRUE )
1095 {
1096 ParserPopElement(
1097#ifdef USE_CWMP_MEMORY_POOL
1098 pool ,
1099#endif
1100 xmlParser );
1101 }
1102 else // syntax error
1103 {
1104 return XML_SYNTAX_ERR;
1105 }
1106 }
1107
1108 if ( strcmp( newNode->nodeName, xmlParser->currentNodePtr->nodeName ) ==
1109 0 )
1110 {
1111 xmlParser->currentNodePtr = xmlParser->currentNodePtr->parentNode;
1112 }
1113 else
1114 {
1115 return XML_SYNTAX_ERR;
1116 }
1117
1118 return XML_OK;
1119
1120}
1121
1122/*================================================================
1123* XmlParserFreeNodeContent
1124* XFREEs a node contents
1125* Internal to parser only.
1126*
1127*=================================================================*/
1128void
1129XmlParserFreeNodeContent(
1130 Pool * pool,
1131 XmlNode * nodeptr )
1132{
1133
1134 if ( nodeptr == NULL )
1135 {
1136 return;
1137 }
1138
1139 if ( nodeptr->nodeName != NULL )
1140 {
1141 PFREE( nodeptr->nodeName );
1142 }
1143
1144 if ( nodeptr->nodeValue != NULL )
1145 {
1146 PFREE( nodeptr->nodeValue );
1147 }
1148
1149 if ( nodeptr->namespaceURI != NULL )
1150 {
1151 PFREE( nodeptr->namespaceURI );
1152 }
1153
1154 if ( nodeptr->prefix != NULL )
1155 {
1156 PFREE( nodeptr->prefix );
1157 }
1158
1159 if ( nodeptr->localName != NULL )
1160 {
1161 PFREE( nodeptr->localName );
1162 }
1163
1164}
1165
1166/*================================================================
1167* XMLParserParseDocument
1168* Parses the xml file and returns the DOM document tree.
1169* External function.
1170*
1171*=================================================================*/
1172static int
1173XMLParserParseDocument(
1174 Pool * pool,
1175 OUT XmlDocument ** retDoc,
1176 XMLParser * xmlParser )
1177{
1178
1179 XmlDocument *gRootDoc = NULL;
1180 XmlNode newNode;
1181 BOOL bETag = FALSE;
1182 XmlNode * tempNode = NULL;
1183 int rc = XML_OK;
1184 XmlCDATASection *cdataSecNode = NULL;
1185
1186 XmlNodeInit( &newNode );
1187
1188 rc = XmlDocCreateDocumentEx(
1189#ifdef USE_CWMP_MEMORY_POOL
1190 pool ,
1191#endif
1192
1193 &gRootDoc );
1194 if ( rc != XML_OK )
1195 {
1196 goto ErrorHandler;
1197 }
1198
1199 xmlParser->currentNodePtr = ( XmlNode * ) gRootDoc;
1200
1201 rc = XMLParserSkipProlog( xmlParser );
1202 if ( rc != XML_OK )
1203 {
1204 goto ErrorHandler;
1205 }
1206
1207 while ( bETag == FALSE )
1208 {
1209 // clear the newNode contents
1210 XmlNodeInit( &newNode );
1211
1212 if ( XMLParserGetNextNode(
1213#ifdef USE_CWMP_MEMORY_POOL
1214 pool ,
1215#endif
1216 xmlParser, &newNode, &bETag ) ==
1217 XML_OK )
1218 {
1219 if ( bETag == FALSE )
1220 {
1221 switch ( newNode.nodeType )
1222 {
1223 case XML_ELEMENT_NODE:
1224 rc = ParserProcessElementName(
1225#ifdef USE_CWMP_MEMORY_POOL
1226 pool ,
1227#endif
1228 gRootDoc,
1229 xmlParser,
1230 &newNode );
1231 if ( rc != XML_OK )
1232 {
1233 goto ErrorHandler;
1234 }
1235 break;
1236
1237 case XML_TEXT_NODE:
1238 rc = XmlDocCreateTextNodeEx(
1239#ifdef USE_CWMP_MEMORY_POOL
1240 pool ,
1241#endif
1242
1243 gRootDoc,
1244 newNode.
1245 nodeValue,
1246 &tempNode );
1247 if ( rc != XML_OK )
1248 {
1249 goto ErrorHandler;
1250 }
1251
1252 rc = XmlNodeAppendChild( xmlParser->
1253 currentNodePtr,
1254 tempNode );
1255 if ( rc != XML_OK )
1256 {
1257 goto ErrorHandler;
1258 }
1259
1260 break;
1261
1262 case XML_CDATA_SECTION_NODE:
1263 rc = XmlDocCreateCDATASectionEx(
1264#ifdef USE_CWMP_MEMORY_POOL
1265 pool ,
1266#endif
1267
1268 gRootDoc,
1269 newNode.
1270 nodeValue,
1271 &cdataSecNode );
1272 if ( rc != XML_OK )
1273 {
1274 goto ErrorHandler;
1275 }
1276
1277 rc = XmlNodeAppendChild( xmlParser->
1278 currentNodePtr,
1279 &( cdataSecNode->node ) );
1280 if ( rc != XML_OK )
1281 {
1282 goto ErrorHandler;
1283 }
1284 break;
1285
1286 case XML_ATTRIBUTE_NODE:
1287 rc = XMLParserProcessAttributeName(
1288#ifdef USE_CWMP_MEMORY_POOL
1289 pool ,
1290#endif
1291 gRootDoc,
1292 xmlParser,
1293 &newNode );
1294 if ( rc != XML_OK )
1295 {
1296 goto ErrorHandler;
1297 }
1298 break;
1299
1300 default:
1301 break;
1302 }
1303 }
1304 else // ETag==TRUE, endof element tag.
1305 {
1306 rc = ParserETagVerification(
1307#ifdef USE_CWMP_MEMORY_POOL
1308 pool ,
1309#endif
1310 xmlParser, &newNode );
1311 if ( rc != XML_OK )
1312 {
1313 goto ErrorHandler;
1314 }
1315 xmlParser->state = E_CONTENT;
1316 }
1317
1318 // reset bETag flag
1319 bETag = FALSE;
1320
1321 }
1322 else if ( bETag == TRUE ) // file is done
1323 {
1324 break;
1325 }
1326 else
1327 {
1328 rc = XML_FAILED;
1329 goto ErrorHandler;
1330 }
1331 XmlParserFreeNodeContent(
1332#ifdef USE_CWMP_MEMORY_POOL
1333 pool ,
1334#endif
1335 &newNode );
1336
1337 }
1338
1339 if ( xmlParser->pCurElement != NULL )
1340 {
1341 rc = XML_SYNTAX_ERR;
1342 goto ErrorHandler;
1343 }
1344
1345 *retDoc = ( XmlDocument * ) gRootDoc;
1346 XMLParserFree(
1347#ifdef USE_CWMP_MEMORY_POOL
1348 pool ,
1349#endif
1350 xmlParser );
1351 return rc;
1352
1353ErrorHandler:
1354 XmlParserFreeNodeContent(
1355#ifdef USE_CWMP_MEMORY_POOL
1356 pool ,
1357#endif
1358 &newNode );
1359 XmlDocumentFree(
1360
1361#ifdef USE_CWMP_MEMORY_POOL
1362 pool ,
1363#endif
1364 gRootDoc );
1365 XMLParserFree(
1366#ifdef USE_CWMP_MEMORY_POOL
1367 pool ,
1368#endif
1369 xmlParser );
1370 return rc;
1371
1372}
1373
1374/*==============================================================================*
1375* XMLParserSetLastElem
1376* set the last element to be the given string.
1377* Internal to parser only.
1378*
1379*===============================================================================*/
1380static int
1381XMLParserSetLastElem(
1382 Pool * pool,
1383
1384 XMLParser * xmlParser,
1385 IN const char *s )
1386{
1387 int rc;
1388
1389 if ( ( xmlParser == NULL ) || ( s == NULL ) )
1390 {
1391 return XML_FAILED;
1392 }
1393
1394 rc = XmlBufferAssignString(
1395#ifdef USE_CWMP_MEMORY_POOL
1396 pool ,
1397#endif
1398
1399 &( xmlParser->lastElem ), s );
1400 return rc;
1401}
1402
1403/*==============================================================================*
1404*
1405* ParserClearTokenBuf
1406* clear token buffer.
1407* Internal to parser only.
1408*
1409*===============================================================================*/
1410static void
1411ParserClearTokenBuf(
1412 Pool * pool,
1413 XMLParser * xmlParser )
1414{
1415 XmlBufferDestroy(
1416#ifdef USE_CWMP_MEMORY_POOL
1417 pool ,
1418#endif
1419 &( xmlParser->tokenBuf ) );
1420}
1421
1422/*==============================================================================*
1423*
1424* ParserAppendTokBufStr
1425* Appends string s to token buffer
1426* Internal to parser only.
1427*
1428*===============================================================================*/
1429static int
1430ParserAppendTokBufStr(
1431 Pool * pool,
1432
1433 XMLParser * xmlParser,
1434 IN const char *s )
1435{
1436 int rc = XML_OK;
1437
1438 if ( s != NULL )
1439 {
1440 rc = XmlBufferAppendString(
1441#ifdef USE_CWMP_MEMORY_POOL
1442 pool ,
1443#endif
1444
1445 &( xmlParser->tokenBuf ), s );
1446 }
1447
1448 return rc;
1449}
1450
1451/*==============================================================================*
1452*
1453* ParserAppendTokBufChar
1454* Appends c to token buffer.
1455* Internal to parser only.
1456*
1457*===============================================================================*/
1458static int
1459ParserAppendTokBufChar(
1460 Pool * pool,
1461 XMLParser * xmlParser,
1462 IN char c )
1463{
1464 int rc;
1465
1466 rc = XmlBufferAppend(
1467#ifdef USE_CWMP_MEMORY_POOL
1468 pool ,
1469#endif
1470
1471 &( xmlParser->tokenBuf ), &c );
1472 return rc;
1473}
1474
1475/*==============================================================================*
1476*
1477* XMLParserSkipWhiteSpaces
1478* skip white spaces
1479* Internal to parser only
1480*
1481*===============================================================================*/
1482static void
1483XMLParserSkipWhiteSpaces( XMLParser * xmlParser )
1484{
1485 while ( ( *( xmlParser->curPtr ) != 0 ) &&
1486 ( strchr( WHITESPACE, *( xmlParser->curPtr ) ) != NULL ) )
1487 {
1488 xmlParser->curPtr++;
1489 }
1490
1491}
1492
1493/*==============================================================================*
1494* XMLParserGetChar
1495* returns next char value and its length
1496* Internal to parser only
1497*
1498*===============================================================================*/
1499static int
1500XMLParserGetChar( IN char *src,
1501 INOUT int *cLen )
1502{
1503 char *pnum;
1504 int sum;
1505 char c;
1506 int i;
1507
1508 if ( src == NULL || cLen == NULL )
1509 {
1510 return -1;
1511 }
1512
1513 *cLen = 0;
1514
1515 if ( *src != '&' )
1516 {
1517 if ( *src > 0 && XMLParserIsXmlChar( *src ) )
1518 {
1519 *cLen = 1;
1520 return *src;
1521 }
1522
1523 i = Parser_UTF8ToInt( src, cLen );
1524 if ( !XMLParserIsXmlChar( i ) )
1525 {
1526 return -1;
1527 }
1528 return i;
1529 }
1530 else if ( XMLStrncasecmp( src, QUOT, strlen( QUOT ) ) == 0 )
1531 {
1532 *cLen = strlen( QUOT );
1533 return '"';
1534 }
1535 else if ( XMLStrncasecmp( src, LT, strlen( LT ) ) == 0 )
1536 {
1537 *cLen = strlen( LT );
1538 return '<';
1539 }
1540 else if ( XMLStrncasecmp( src, GT, strlen( GT ) ) == 0 )
1541 {
1542 *cLen = strlen( GT );
1543 return '>';
1544 }
1545 else if ( XMLStrncasecmp( src, APOS, strlen( APOS ) ) == 0 )
1546 {
1547 *cLen = strlen( APOS );
1548 return '\'';
1549 }
1550 else if ( XMLStrncasecmp( src, AMP, strlen( AMP ) ) == 0 )
1551 {
1552 *cLen = strlen( AMP );
1553 return '&';
1554 }
1555 else if ( XMLStrncasecmp( src, ESC_HEX, strlen( ESC_HEX ) ) == 0 ) // Read in escape characters of type &#xnn where nn is a hexadecimal value
1556 {
1557 pnum = src + strlen( ESC_HEX );
1558 sum = 0;
1559 while ( strchr( HEX_NUMBERS, *pnum ) != 0 )
1560 {
1561 c = *pnum;
1562 if ( c <= '9' )
1563 {
1564 sum = sum * 16 + ( c - '0' );
1565 }
1566 else if ( c <= 'F' )
1567 {
1568 sum = sum * 16 + ( c - 'A' + 10 );
1569 }
1570 else
1571 {
1572 sum = sum * 16 + ( c - 'a' + 10 );
1573 }
1574
1575 pnum++;
1576 }
1577
1578 if ( ( pnum == src ) || *pnum != ';' || !XMLParserIsXmlChar( sum ) )
1579 {
1580 return -1;
1581 }
1582
1583 *cLen = pnum - src + 1;
1584 return sum;
1585
1586 }
1587 else if ( XMLStrncasecmp( src, ESC_DEC, strlen( ESC_DEC ) ) == 0 )
1588 {
1589 // Read in escape characters of type &#nn where nn is a decimal value
1590 pnum = src + strlen( ESC_DEC );
1591 sum = 0;
1592 while ( strchr( DEC_NUMBERS, *pnum ) != 0 )
1593 {
1594 sum = sum * 10 + ( *pnum - '0' );
1595 pnum++;
1596 }
1597
1598 if ( ( pnum == src ) || *pnum != ';' || !XMLParserIsXmlChar( sum ) )
1599 {
1600 return -1;
1601 }
1602
1603 *cLen = pnum - src + 1;
1604 return sum;
1605 }
1606
1607 return -1;
1608}
1609
1610/*==============================================================================*
1611* XMLParserCopyToken
1612* copy string in src into xml parser token buffer
1613* Internal to parser only.
1614*
1615*===============================================================================*/
1616static int
1617XMLParserCopyToken(
1618 Pool * pool,
1619
1620 XMLParser * xmlParser,
1621 IN char *src,
1622 IN int len )
1623{
1624 int i,
1625 c,
1626 cl;
1627 char *psrc,
1628 *pend;
1629 utf8char uch;
1630
1631 if ( !src || len <= 0 )
1632 {
1633 return XML_FAILED;
1634 }
1635
1636 psrc = src;
1637 pend = src + len;
1638
1639 while ( psrc < pend )
1640 {
1641 if ( ( c = XMLParserGetChar( psrc, &cl ) ) <= 0 )
1642 {
1643 return XML_FAILED;
1644 }
1645
1646 if ( cl == 1 )
1647 {
1648 ParserAppendTokBufChar(
1649#ifdef USE_CWMP_MEMORY_POOL
1650 pool ,
1651#endif
1652
1653 xmlParser, ( char )c );
1654 psrc++;
1655 }
1656 else
1657 {
1658
1659 i = XMLParserIntToUTF8( c, uch );
1660 if ( i == 0 )
1661 {
1662 return XML_FAILED;
1663 }
1664
1665 ParserAppendTokBufStr(
1666#ifdef USE_CWMP_MEMORY_POOL
1667 pool ,
1668#endif
1669 xmlParser, uch );
1670 psrc += cl;
1671 }
1672 }
1673
1674 if ( psrc > pend )
1675 {
1676 return XML_FAILED;
1677 }
1678 else
1679 {
1680 return XML_OK; // success
1681 }
1682
1683}
1684
1685/*==============================================================================*
1686*
1687* XMLParserSkipString
1688* Skips all characters in the string until it finds the skip key.
1689* Then it skips the skip key and returns.
1690* Internal to parser only
1691*
1692*===============================================================================*/
1693static int
1694XMLParserSkipString( INOUT char **pstrSrc,
1695 IN const char *strSkipKey )
1696{
1697 if ( !( *pstrSrc ) || !strSkipKey )
1698 {
1699 return XML_FAILED;
1700 }
1701
1702 while ( ( **pstrSrc )
1703 && strncmp( *pstrSrc, strSkipKey,
1704 strlen( strSkipKey ) ) != 0 )
1705 {
1706 ( *pstrSrc )++;
1707 }
1708
1709 if ( **pstrSrc == '\0' )
1710 {
1711 return XML_SYNTAX_ERR;
1712 }
1713 *pstrSrc = *pstrSrc + strlen( strSkipKey );
1714
1715 return XML_OK; //success
1716}
1717
1718/*==============================================================================*
1719*
1720* Function:
1721* Returns:
1722*
1723*
1724*===============================================================================*/
1725static int
1726XMLParserSkipPI( INOUT char **pSrc )
1727{
1728 char *pEnd = NULL;
1729
1730// assert( *pSrc );
1731 if ( *pSrc == NULL )
1732 {
1733 return XML_FAILED;
1734 }
1735
1736 if ( ( XMLStrncasecmp( *pSrc, ( char * )XMLDECL, strlen( XMLDECL ) ) == 0 ) || ( XMLStrncasecmp( *pSrc, ( char * )XMLDECL2, strlen( XMLDECL2 ) ) == 0 ) ) // not allowed
1737 {
1738 return XML_SYNTAX_ERR;
1739 }
1740
1741 if ( XMLStrncasecmp( *pSrc, ( char * )BEGIN_PI, strlen( BEGIN_PI ) ) == 0 )
1742 {
1743 pEnd = strstr( *pSrc, END_PI );
1744 if ( ( pEnd != NULL ) && ( pEnd != *pSrc ) )
1745 {
1746 *pSrc = pEnd + strlen( BEGIN_PI );
1747 }
1748 else
1749 {
1750 return XML_SYNTAX_ERR;
1751 }
1752 }
1753
1754 return XML_OK;
1755}
1756
1757/*==============================================================================*
1758* XMLParserSkipXMLDecl:
1759* skips XML declarations.
1760* Internal only to parser.
1761*
1762*===============================================================================*/
1763static int
1764XMLParserSkipXMLDecl( INOUT XMLParser * xmlParser )
1765{
1766 int rc = XML_FAILED;
1767
1768// assert( xmlParser );
1769 if ( xmlParser == NULL )
1770 {
1771 return rc;
1772 }
1773
1774 rc = XMLParserSkipString( &( xmlParser->curPtr ), END_PI );
1775 XMLParserSkipWhiteSpaces( xmlParser );
1776 return rc;
1777
1778}
1779
1780/*==============================================================================*
1781* XMLParserSkipProlog
1782* skip prolog
1783* Internal to parser only.
1784*
1785*===============================================================================*/
1786static int
1787XMLParserSkipProlog( INOUT XMLParser * xmlParser )
1788{
1789 int rc = XML_OK;
1790
1791// assert( xmlParser != NULL );
1792 if ( xmlParser == NULL )
1793 {
1794 return XML_FAILED;
1795 }
1796
1797 XMLParserSkipWhiteSpaces( xmlParser );
1798
1799 if ( strncmp( xmlParser->curPtr, ( char * )XMLDECL, strlen( XMLDECL ) ) == 0 ) // <?xml
1800 {
1801 rc = XMLParserSkipXMLDecl( xmlParser );
1802 if ( rc != XML_OK )
1803 {
1804 return rc;
1805 }
1806 }
1807
1808 rc = XMLParserSkipMisc( xmlParser );
1809 if ( ( rc == XML_OK ) && strncmp( xmlParser->curPtr, ( char * )BEGIN_DOCTYPE, strlen( BEGIN_DOCTYPE ) ) == 0 ) // <! DOCTYPE
1810 {
1811 xmlParser->curPtr++;
1812 rc = XMLParserSkipDocType( &( xmlParser->curPtr ) );
1813 }
1814
1815 if ( rc == XML_OK )
1816 {
1817 rc = XMLParserSkipMisc( xmlParser );
1818 }
1819
1820 return rc;
1821}
1822
1823/*==============================================================================*
1824*
1825* Function:
1826* Returns:
1827* Skips all characters in the string until it finds the skip key.
1828* Then it skips the skip key and returns.
1829*
1830*===============================================================================*/
1831static int
1832XMLParserSkipComment( INOUT char **pstrSrc )
1833{
1834 char *pStrFound = NULL;
1835
1836// assert( ( *pstrSrc ) != NULL );
1837 if ( *pstrSrc == NULL )
1838 {
1839 return XML_FAILED;
1840 }
1841
1842 pStrFound = strstr( *pstrSrc, END_COMMENT );
1843 if ( ( pStrFound != NULL ) && ( pStrFound != *pstrSrc ) &&
1844 ( *( pStrFound - 1 ) != '-' ) )
1845 {
1846 *pstrSrc = pStrFound + strlen( END_COMMENT );
1847 }
1848 else
1849 {
1850 return XML_SYNTAX_ERR;
1851 }
1852
1853 return XML_OK;
1854}
1855
1856/*==============================================================================*
1857* XMLParserSkipDocType
1858* skips document type declaration
1859*
1860*===============================================================================*/
1861static int
1862XMLParserSkipDocType( INOUT char **pstr )
1863{
1864 char *pCur = *pstr;
1865 char *pNext = NULL; // default there is no nested <
1866 int num = 1;
1867
1868// assert( ( *pstr ) != NULL );
1869 if ( *pstr == NULL )
1870 {
1871 return XML_FAILED;
1872 }
1873
1874 while ( ( pCur != NULL ) && ( num != 0 ) && ( *pCur != 0 ) )
1875 {
1876 if ( *pCur == '<' )
1877 {
1878 num++;
1879 }
1880 else if ( *pCur == '>' )
1881 {
1882 num--;
1883 }
1884 else if ( *pCur == '"' )
1885 {
1886 pNext = strchr( pCur + 1, '"' );
1887 if ( pNext == NULL )
1888 {
1889 return XML_SYNTAX_ERR;
1890 }
1891
1892 pCur = pNext;
1893 }
1894
1895 pCur++;
1896 }
1897
1898 if ( num == 0 )
1899 {
1900 *pstr = pCur;
1901 return XML_OK;
1902 }
1903 else
1904 {
1905 return XML_SYNTAX_ERR;
1906 }
1907}
1908
1909/*==============================================================================*
1910*
1911* XMLParserSkipMisc:
1912* skip comment, PI and white space
1913*
1914*
1915*===============================================================================*/
1916static int
1917XMLParserSkipMisc( XMLParser * xmlParser )
1918{
1919 int rc = XML_OK;
1920 int done = FALSE;
1921
1922 while ( ( done == FALSE ) && ( rc == XML_OK ) )
1923 {
1924 if ( XMLStrncasecmp( xmlParser->curPtr, ( char * )BEGIN_COMMENT, strlen( BEGIN_COMMENT ) ) == 0 ) // <!--
1925 {
1926 rc = XMLParserSkipComment( &( xmlParser->curPtr ) );
1927
1928 }
1929 else if ( ( XMLStrncasecmp( xmlParser->curPtr, ( char * )XMLDECL, strlen( XMLDECL ) ) == 0 ) || ( XMLStrncasecmp( xmlParser->curPtr, ( char * )XMLDECL2, strlen( XMLDECL2 ) ) == 0 ) ) // <?xml or <?xml?
1930 {
1931 rc = XML_SYNTAX_ERR;
1932 }
1933 else if ( XMLStrncasecmp( xmlParser->curPtr, ( char * )BEGIN_PI, strlen( BEGIN_PI ) ) == 0 ) // <?
1934 {
1935 rc = XMLParserSkipString( &( xmlParser->curPtr ), END_PI );
1936 }
1937 else
1938 {
1939 done = TRUE;
1940 }
1941
1942 XMLParserSkipWhiteSpaces( xmlParser );
1943 }
1944
1945 return rc;
1946}
1947
1948/*==============================================================================*
1949*
1950* XMLParserGetNextToken
1951* return the length of next token in tokenBuff
1952*
1953*
1954*===============================================================================*/
1955static int
1956XMLParserGetNextToken(
1957 Pool * pool,
1958 XMLParser * xmlParser )
1959{
1960 int tokenLength = 0;
1961 int temp,
1962 tlen;
1963 int rc;
1964
1965 ParserClearTokenBuf(
1966#ifdef USE_CWMP_MEMORY_POOL
1967 pool ,
1968#endif
1969 xmlParser );
1970
1971 if ( *( xmlParser->curPtr ) == '\0' )
1972 {
1973 return 0;
1974 }
1975 // skip XML instructions
1976 rc = XMLParserSkipMisc( xmlParser );
1977 if ( rc != XML_OK )
1978 {
1979 return 0;
1980 }
1981 // Attribute value logic must come first, since all text untokenized until end-quote
1982 if ( *( xmlParser->curPtr ) == QUOTE )
1983 {
1984 tokenLength = 1;
1985 }
1986 else if ( *( xmlParser->curPtr ) == SINGLEQUOTE )
1987 {
1988 tokenLength = 1;
1989 }
1990 else if ( *( xmlParser->curPtr ) == LESSTHAN ) // Check for start tags
1991 {
1992 temp = Parser_UTF8ToInt( xmlParser->curPtr + 1, &tlen );
1993 if ( temp == '/' )
1994 {
1995 tokenLength = 2; // token is '</' end tag
1996 }
1997 else if ( XMLParserIsNameChar( temp, FALSE ) == TRUE )
1998 {
1999 tokenLength = 1; // '<' found, so return '<' token
2000 }
2001 else
2002 {
2003 return 0; //error
2004 }
2005 }
2006 else if ( *( xmlParser->curPtr ) == EQUALS ) // Check for '=' token, return it as a token
2007 {
2008 tokenLength = 1;
2009 }
2010 else if ( *( xmlParser->curPtr ) == SLASH )
2011 {
2012 if ( *( xmlParser->curPtr + 1 ) == GREATERTHAN ) // token '/>' found
2013 {
2014 tokenLength = 2;
2015 xmlParser->savePtr = xmlParser->curPtr; // fix
2016 }
2017 }
2018 else if ( *( xmlParser->curPtr ) == GREATERTHAN ) // > found, so return it as a token
2019 {
2020 tokenLength = 1;
2021 }
2022 else if ( XMLParserIsNameChar( Parser_UTF8ToInt( xmlParser->curPtr, &tlen ), FALSE ) ) // Check for name tokens, name found, so find out how long it is
2023 {
2024 int iIndex = tlen;
2025
2026 while ( XMLParserIsNameChar
2027 ( Parser_UTF8ToInt( xmlParser->curPtr + iIndex, &tlen ),
2028 TRUE ) )
2029 {
2030 iIndex += tlen;
2031 }
2032 tokenLength = iIndex;
2033 }
2034 else
2035 {
2036 return 0;
2037 }
2038
2039 // Copy the token to the return string
2040 if ( XMLParserCopyToken(
2041#ifdef USE_CWMP_MEMORY_POOL
2042 pool ,
2043#endif
2044 xmlParser, xmlParser->curPtr, tokenLength ) !=
2045 XML_OK )
2046 {
2047 return 0;
2048 }
2049
2050 xmlParser->curPtr += tokenLength;
2051 return tokenLength;
2052}
2053
2054/*==============================================================================*
2055*
2056* XMLParserGetNameSpace
2057* return the namespce as defined as prefix.
2058* Internal to parser only
2059*
2060*===============================================================================*/
2061static char *
2062XMLParserGetNameSpace( XMLParser * xmlParser,
2063 IN char *prefix )
2064{
2065 XmlElementStack *pCur;
2066 XmlNameSpaceURI *pNsUri;
2067
2068 pCur = xmlParser->pCurElement;
2069 if ( strcmp( pCur->prefix, prefix ) != 0 )
2070 {
2071 pNsUri = pCur->pNsURI;
2072 while ( pNsUri != NULL )
2073 {
2074 if ( strcmp( pNsUri->prefix, prefix ) == 0 )
2075 {
2076 return pNsUri->nsURI;
2077 }
2078 pNsUri = pNsUri->nextNsURI;
2079 }
2080 }
2081 else
2082 {
2083 return pCur->namespaceUri;
2084 }
2085
2086 return NULL;
2087
2088}
2089
2090/*==============================================================================*
2091*
2092* ParserAddNamespace
2093* Add a namespace definition
2094* Internal to parser only
2095*
2096*===============================================================================*/
2097static int
2098ParserAddNamespace(
2099 Pool * pool,
2100 XMLParser * xmlParser )
2101{
2102 XmlNode * pNode;
2103 XmlElementStack *pCur;
2104 char *namespaceUri;
2105
2106 pNode = xmlParser->pNeedPrefixNode;
2107 pCur = xmlParser->pCurElement;
2108
2109 if ( pNode->prefix == NULL ) // element does not have prefix
2110 {
2111 if ( strcmp( pNode->nodeName, pCur->element ) != 0 )
2112 {
2113 return XML_FAILED;
2114 }
2115 if ( pCur->namespaceUri != NULL )
2116 {
2117 // it would be wrong that pNode->namespace != NULL.
2118 assert( pNode->namespaceURI == NULL );
2119
2120 pNode->namespaceURI = PSTRDUP( pCur->namespaceUri );
2121 if ( pNode->namespaceURI == NULL )
2122 {
2123 return XML_INSUFFICIENT_MEMORY;
2124 }
2125 }
2126
2127 xmlParser->pNeedPrefixNode = NULL;
2128
2129 }
2130 else
2131 {
2132 if ( ( strcmp( pNode->nodeName, pCur->element ) != 0 ) &&
2133 ( strcmp( pNode->prefix, pCur->prefix ) != 0 ) )
2134 {
2135 return XML_FAILED;
2136 }
2137
2138 namespaceUri = XMLParserGetNameSpace( xmlParser, pCur->prefix );
2139 if ( namespaceUri != NULL )
2140 {
2141 pNode->namespaceURI = PSTRDUP( namespaceUri );
2142 if ( pNode->namespaceURI == NULL )
2143 {
2144 return XML_INSUFFICIENT_MEMORY;
2145 }
2146
2147 xmlParser->pNeedPrefixNode = NULL;
2148 }
2149 }
2150 return XML_OK;
2151}
2152
2153/*==============================================================================*
2154*
2155* XmlParserSetNodePrefixAndLocalName
2156* set the node prefix and localName as defined by the nodeName
2157* in the form of ns:name
2158* Internal to parser only.
2159*
2160*===============================================================================*/
2161int
2162#ifdef USE_CWMP_MEMORY_POOL
2163XmlParserSetNodePrefixAndLocalName(Pool * pool, XmlNode * node )
2164#else
2165XmlParserSetNodePrefixAndLocalName( XmlNode * node )
2166#endif
2167
2168{
2169
2170 char *pStrPrefix = NULL;
2171 char *pLocalName;
2172 int nPrefix;
2173
2174// assert( node != NULL );
2175 if ( node == NULL )
2176 {
2177 return XML_FAILED;
2178 }
2179
2180 pStrPrefix = strchr( node->nodeName, ':' );
2181 if ( pStrPrefix == NULL )
2182 {
2183 node->prefix = NULL;
2184 node->localName = PSTRDUP( node->nodeName );
2185 if ( node->localName == NULL )
2186 {
2187 return XML_INSUFFICIENT_MEMORY;
2188 }
2189
2190 }
2191 else // fill in the local name and prefix
2192 {
2193
2194 pLocalName = ( char * )pStrPrefix + 1;
2195 nPrefix = pStrPrefix - node->nodeName;
2196 node->prefix = PMALLOC( nPrefix + 1 );
2197 if ( node->prefix == NULL )
2198 {
2199 return XML_INSUFFICIENT_MEMORY;
2200 }
2201
2202 memset( node->prefix, 0, nPrefix + 1 );
2203 strncpy( node->prefix, node->nodeName, nPrefix );
2204
2205 node->localName = PSTRDUP( pLocalName );
2206 if ( node->localName == NULL )
2207 {
2208 PFREE( node->prefix );
2209 node->prefix = NULL; //no need to PFREE really, main loop will XFREEs it
2210 //when return code is not success
2211 return XML_INSUFFICIENT_MEMORY;
2212 }
2213 }
2214
2215 return XML_OK;
2216}
2217
2218/*==============================================================================*
2219*
2220* XMLParserXmlNamespace
2221* add namespace definition.
2222* internal to parser only.
2223*
2224*===============================================================================*/
2225static int
2226#ifdef USE_CWMP_MEMORY_POOL
2227XMLParserXmlNamespace(Pool * pool, XMLParser * xmlParser,
2228#else
2229XMLParserXmlNamespace( XMLParser * xmlParser,
2230#endif
2231
2232 XmlNode * newNode )
2233{
2234
2235
2236 XmlElementStack *pCur = NULL;
2237 XmlNameSpaceURI *pNewNs = NULL;
2238 XmlNameSpaceURI *pNs = NULL;
2239 XmlNameSpaceURI *pPrevNs = NULL;
2240 int rc;
2241
2242 // if the newNode contains a namespace definition
2243 assert( newNode->nodeName != NULL );
2244
2245
2246 if(NULL == xmlParser)
2247 {
2248 return XML_FAILED;
2249 }
2250
2251 pCur = xmlParser->pCurElement;
2252
2253 if ( strcmp( newNode->nodeName, "xmlns" ) == 0 ) // default namespace def.
2254 {
2255 if(pCur == NULL)
2256 {
2257 return XML_FAILED;
2258 }
2259
2260 if (pCur->namespaceUri != NULL )
2261 {
2262 PFREE( pCur->namespaceUri );
2263 }
2264
2265#if 1 /* Jerry Lu Modified@Sep,14,2005 for fix PSTRDUP(NULL) cause Segment Fault */
2266 if (newNode->nodeValue==NULL)
2267 pCur->namespaceUri = PSTRDUP("");
2268 else
2269#endif
2270 pCur->namespaceUri = XmlStrduptrim(
2271#ifdef USE_CWMP_MEMORY_POOL
2272 pool ,
2273#endif
2274 newNode->nodeValue );
2275
2276 if ( pCur->namespaceUri == NULL )
2277 {
2278 return XML_INSUFFICIENT_MEMORY;
2279 }
2280
2281 }
2282 else if ( strncmp( newNode->nodeName, "xmlns:", strlen( "xmlns:" ) ) == 0 ) // namespace definition
2283 {
2284 rc = XmlParserSetNodePrefixAndLocalName(
2285#ifdef USE_CWMP_MEMORY_POOL
2286 pool ,
2287#endif
2288 newNode );
2289 if ( rc != XML_OK )
2290 {
2291 return rc;
2292 }
2293
2294 assert( newNode->localName != NULL );
2295
2296 if ( pCur == NULL )
2297 {
2298 return XML_FAILED;
2299 }
2300
2301 if ( ( pCur->prefix != NULL )
2302 && ( strcmp( pCur->prefix, newNode->localName ) == 0 ) )
2303 {
2304 pCur->namespaceUri = XmlStrduptrim(
2305#ifdef USE_CWMP_MEMORY_POOL
2306 pool ,
2307#endif
2308 newNode->nodeValue );
2309 if ( pCur->namespaceUri == NULL )
2310 {
2311 return XML_INSUFFICIENT_MEMORY;
2312 }
2313 }
2314 else
2315 {
2316
2317 pPrevNs = pCur->pNsURI;
2318 pNs = pPrevNs;
2319 while ( pNs != NULL )
2320 {
2321 if ( ( pNs->prefix != NULL ) &&
2322 ( strcmp( pNs->prefix, newNode->localName ) == 0 ) )
2323 {
2324 break; // replace namespace definition
2325 }
2326 else
2327 {
2328 pPrevNs = pNs;
2329 pNs = pNs->nextNsURI;
2330 }
2331 }
2332
2333 if ( pNs == NULL ) // a new definition
2334 {
2335 pNewNs =
2336 ( XmlNameSpaceURI * )
2337 PMALLOC( sizeof( XmlNameSpaceURI ) );
2338 if ( pNewNs == NULL )
2339 {
2340 return XML_INSUFFICIENT_MEMORY;
2341 }
2342 memset( pNewNs, 0, sizeof( XmlNameSpaceURI ) );
2343
2344 pNewNs->prefix = PSTRDUP( newNode->localName );
2345 if ( pNewNs->prefix == NULL )
2346 {
2347 PFREE( pNewNs );
2348 return XML_INSUFFICIENT_MEMORY;
2349 }
2350
2351 pNewNs->nsURI = XmlStrduptrim(
2352#ifdef USE_CWMP_MEMORY_POOL
2353 pool ,
2354#endif
2355 newNode->nodeValue );
2356 if ( pNewNs->nsURI == NULL )
2357 {
2358 XMLParserFreeNsURI(
2359#ifdef USE_CWMP_MEMORY_POOL
2360 pool ,
2361#endif
2362 pNewNs );
2363 PFREE( pNewNs );
2364 return XML_INSUFFICIENT_MEMORY;
2365 }
2366
2367 if ( pCur->pNsURI == NULL )
2368 {
2369 pCur->pNsURI = pNewNs;
2370 }
2371 else
2372 {
2373 pPrevNs->nextNsURI = pNewNs;
2374 }
2375 }
2376 else // udpate the namespace
2377 {
2378 if ( pNs->nsURI != NULL )
2379 {
2380 PFREE( pNs->nsURI );
2381 }
2382
2383 pNs->nsURI = XmlStrduptrim(
2384#ifdef USE_CWMP_MEMORY_POOL
2385 pool ,
2386#endif
2387 newNode->nodeValue );
2388 if ( pNs->nsURI == NULL )
2389 {
2390 return XML_INSUFFICIENT_MEMORY;
2391 }
2392 }
2393 }
2394 }
2395
2396 if ( pCur == NULL )
2397 {
2398 return XML_FAILED;
2399 }
2400
2401
2402 if (xmlParser->pNeedPrefixNode != NULL )
2403 {
2404 rc = ParserAddNamespace(
2405#ifdef USE_CWMP_MEMORY_POOL
2406 pool ,
2407#endif
2408 xmlParser );
2409 return rc;
2410 }
2411 else
2412 {
2413 return XML_OK;
2414 }
2415
2416}
2417
2418/*==============================================================================*
2419*
2420* ParserProcessSTag:
2421* Processes the STag as defined by XML spec.
2422* Internal to parser only.
2423*
2424*===============================================================================*/
2425static int
2426ParserProcessSTag(
2427 Pool * pool,
2428 XMLParser * xmlParser,
2429 XmlNode * node )
2430{
2431 char *pCurToken = NULL;
2432 int rc;
2433
2434 if ( XMLParserGetNextToken(
2435#ifdef USE_CWMP_MEMORY_POOL
2436 pool ,
2437#endif
2438 xmlParser ) == 0 )
2439 {
2440 return XML_SYNTAX_ERR;
2441 }
2442
2443 pCurToken = ( xmlParser->tokenBuf ).buf;
2444 if ( pCurToken != NULL )
2445 {
2446 node->nodeName = PSTRDUP( pCurToken );
2447 if ( node->nodeName == NULL )
2448 {
2449 return XML_INSUFFICIENT_MEMORY;
2450 }
2451 }
2452 else
2453 {
2454 return XML_SYNTAX_ERR;
2455 }
2456
2457 rc = XMLParserSetLastElem(
2458#ifdef USE_CWMP_MEMORY_POOL
2459 pool ,
2460#endif
2461
2462 xmlParser, node->nodeName );
2463 if ( rc != XML_OK ) // no need to PFREE node->nodeName, main loop will PFREE it
2464 {
2465 return XML_FAILED;
2466 }
2467
2468 rc = XmlParserSetNodePrefixAndLocalName(
2469#ifdef USE_CWMP_MEMORY_POOL
2470 pool ,
2471#endif
2472 node );
2473 if ( rc != XML_OK ) // no need to PFREE node->nodeName, main loop will PFREE it
2474 {
2475 return XML_FAILED;
2476 }
2477
2478 node->nodeValue = NULL;
2479 node->nodeType = XML_ELEMENT_NODE;
2480
2481 xmlParser->savePtr = xmlParser->curPtr;
2482 if ( XMLParserGetNextToken(
2483
2484#ifdef USE_CWMP_MEMORY_POOL
2485 pool ,
2486#endif
2487 xmlParser ) == 0 ) // no need to PFREE node->nodeName, main loop will PFREE it
2488 {
2489 return XML_SYNTAX_ERR;
2490 }
2491
2492 pCurToken = ( xmlParser->tokenBuf ).buf;
2493 // check to see what is the next token
2494 if ( strcmp( pCurToken, "/>" ) == 0 ) // empty element
2495 {
2496 xmlParser->state = E_ELEMENT;
2497 xmlParser->curPtr = xmlParser->savePtr; // backup to />
2498 }
2499 else if ( strcmp( pCurToken, ">" ) == 0 ) // expecting text node
2500 {
2501 xmlParser->state = E_CONTENT;
2502 }
2503 else
2504 {
2505 xmlParser->state = E_ATTRIBUTE;
2506 xmlParser->curPtr = xmlParser->savePtr;
2507 }
2508
2509 return XML_OK;
2510}
2511
2512/*==============================================================================*
2513*
2514* XMLParserHasDefaultNamespace
2515* decide whether the current element has default namespace
2516* Internal to parser only.
2517*
2518*===============================================================================*/
2519static BOOL
2520XMLParserHasDefaultNamespace( XMLParser * xmlParser,
2521 XmlNode * newNode,
2522 IN char **nsURI )
2523{
2524 XmlElementStack *pCur = xmlParser->pCurElement;
2525
2526 while ( pCur != NULL )
2527 {
2528 if ( ( pCur->prefix == NULL ) && ( pCur->namespaceUri != NULL ) )
2529 {
2530 *nsURI = pCur->namespaceUri;
2531 return TRUE;
2532 }
2533 else
2534 {
2535 pCur = pCur->nextElement;
2536 }
2537 }
2538
2539 return FALSE;
2540
2541}
2542
2543/*==============================================================================*
2544*
2545* XMLParserElementPrefixDefined
2546* decides whether element's prefix is already defined.
2547* Internal to parser only.
2548*
2549*===============================================================================*/
2550static BOOL
2551XMLParserElementPrefixDefined( XMLParser * xmlParser,
2552 XmlNode * newNode,
2553 IN char **nsURI )
2554{
2555
2556 XmlElementStack *pCur = xmlParser->pCurElement;
2557 XmlNameSpaceURI *pNsUri;
2558
2559 while ( pCur != NULL )
2560 {
2561 if ( ( pCur->prefix != NULL )
2562 && ( strcmp( pCur->prefix, newNode->prefix ) == 0 ) )
2563 {
2564 *nsURI = pCur->namespaceUri;
2565 return TRUE;
2566 }
2567 else
2568 {
2569 pNsUri = pCur->pNsURI;
2570
2571 while ( pNsUri != NULL )
2572 {
2573 if ( strcmp( pNsUri->prefix, newNode->prefix ) == 0 )
2574 {
2575 *nsURI = pNsUri->nsURI;
2576 return TRUE;
2577 }
2578 else
2579 {
2580 pNsUri = pNsUri->nextNsURI;
2581 }
2582 }
2583 }
2584
2585 pCur = pCur->nextElement;
2586
2587 }
2588
2589 return FALSE;
2590
2591}
2592
2593/*==============================================================================*
2594*
2595* ParserProcessCDSect
2596* Processes CDSection as defined by XML spec.
2597* Internal to parser only.
2598*
2599*===============================================================================*/
2600static int
2601#ifdef USE_CWMP_MEMORY_POOL
2602ParserProcessCDSect(Pool * pool, IN char **pSrc,
2603#else
2604ParserProcessCDSect( IN char **pSrc,
2605#endif
2606
2607 XmlNode * node )
2608{
2609
2610 char *pEnd;
2611 int tokenLength = 0;
2612 char *pCDataStart;
2613
2614 if ( *pSrc == NULL )
2615 {
2616 return XML_FAILED;
2617 }
2618
2619 pCDataStart = *pSrc + strlen( CDSTART );
2620 pEnd = pCDataStart;
2621 while ( ( XMLParserIsXmlChar( *pEnd ) == TRUE ) && ( *pEnd != '0' ) )
2622 {
2623 if ( strncmp( pEnd, CDEND, strlen( CDEND ) ) == 0 )
2624 {
2625 break;
2626 }
2627 else
2628 {
2629 pEnd++;
2630 }
2631 }
2632
2633 if ( ( pEnd - pCDataStart > 0 ) && ( *pEnd != '0' ) )
2634 {
2635 tokenLength = pEnd - pCDataStart;
2636 node->nodeValue = ( char * )PMALLOC( tokenLength + 1 );
2637 if ( node->nodeValue == NULL )
2638 {
2639 return XML_INSUFFICIENT_MEMORY;
2640 }
2641 strncpy( node->nodeValue, pCDataStart, tokenLength );
2642 node->nodeValue[tokenLength] = '\0';
2643
2644 node->nodeName = PSTRDUP( CDATANODENAME );
2645 if ( node->nodeName == NULL )
2646 {
2647 // no need to PFREE node->nodeValue at all, bacause node contents
2648 // will be XFREEd by the main loop.
2649 return XML_INSUFFICIENT_MEMORY;
2650 }
2651
2652 node->nodeType = XML_CDATA_SECTION_NODE;
2653 *pSrc = pEnd + strlen( CDEND );
2654 return XML_OK;
2655 }
2656 else
2657 {
2658 return XML_SYNTAX_ERR;
2659 }
2660
2661}
2662
2663/*==============================================================================*
2664*
2665* XMLParserSetElementNamespace
2666* set element's namespace
2667* Internal to parser only.
2668*
2669*===============================================================================*/
2670static int
2671XMLParserSetElementNamespace(
2672 Pool * pool,
2673 XmlElement * newElement,
2674 IN char *nsURI )
2675{
2676 if ( newElement != NULL )
2677 {
2678 if ( newElement->node.namespaceURI != NULL )
2679 {
2680 return XML_SYNTAX_ERR;
2681 }
2682 else
2683 {
2684 if (nsURI == NULL)
2685 {
2686 return XML_NAMESPACE_ERR;
2687 }
2688 ( newElement->node ).namespaceURI = PSTRDUP( nsURI );
2689 if ( ( newElement->node ).namespaceURI == NULL )
2690 {
2691 return XML_INSUFFICIENT_MEMORY;
2692 }
2693 }
2694 }
2695
2696 return XML_OK;
2697}
2698
2699/*==============================================================================*
2700*
2701* ParserProcessContent
2702* processes the CONTENT as defined in XML spec.
2703* Internal to parser only
2704*
2705*===============================================================================*/
2706static int
2707ParserProcessContent(
2708 Pool * pool,
2709 XMLParser * xmlParser,
2710 XmlNode * node )
2711{
2712 char *pEndContent;
2713 BOOL bReadContent;
2714 int tokenLength;
2715 char *notAllowed = "]]>";
2716 char *pCurToken = NULL;
2717
2718 // save pointer for backup
2719 xmlParser->savePtr = xmlParser->curPtr;
2720 XMLParserSkipWhiteSpaces( xmlParser );
2721
2722 if ( *( xmlParser->curPtr ) == '\0' ) // end of file is reached
2723 {
2724 return XML_OK;
2725 }
2726
2727 pEndContent = xmlParser->curPtr;
2728 if ( *pEndContent == LESSTHAN )
2729 {
2730 if ( strncmp( pEndContent, ( char * )CDSTART, strlen( CDSTART ) ) ==
2731 0 )
2732 {
2733 if ( ParserProcessCDSect(
2734#ifdef USE_CWMP_MEMORY_POOL
2735 pool ,
2736#endif
2737 &pEndContent, node ) !=
2738 XML_OK )
2739 {
2740 return XML_SYNTAX_ERR;
2741 }
2742 else
2743 {
2744 xmlParser->curPtr = pEndContent;
2745 }
2746 }
2747 else
2748 if ( strncmp
2749 ( pEndContent, ( char * )BEGIN_COMMENT,
2750 strlen( BEGIN_COMMENT ) ) == 0 )
2751 {
2752 if ( XMLParserSkipComment( &pEndContent ) != XML_OK )
2753 {
2754 return XML_SYNTAX_ERR;
2755 }
2756 else
2757 {
2758 xmlParser->curPtr = pEndContent;
2759 }
2760 }
2761 else
2762 if ( strncmp
2763 ( pEndContent, ( char * )BEGIN_PI,
2764 strlen( BEGIN_PI ) ) == 0 )
2765 {
2766 if ( XMLParserSkipPI( &pEndContent ) != XML_OK )
2767 {
2768 return XML_SYNTAX_ERR;
2769 }
2770 else
2771 {
2772 xmlParser->curPtr = pEndContent;
2773 }
2774 }
2775 else // empty content
2776 {
2777 xmlParser->state = E_ELEMENT;
2778 }
2779 }
2780 else
2781 {
2782 // backup
2783 xmlParser->curPtr = xmlParser->savePtr;
2784 pEndContent = xmlParser->curPtr;
2785
2786 while ( ( *pEndContent != LESSTHAN ) &&
2787 ( strncmp
2788 ( pEndContent, ( const char * )notAllowed,
2789 strlen( notAllowed ) ) != 0 ) && *pEndContent )
2790 {
2791 pEndContent++;
2792 }
2793
2794 if ( *pEndContent == '\0' )
2795 {
2796 bReadContent = FALSE;
2797 }
2798
2799 if ( strncmp
2800 ( pEndContent, ( const char * )notAllowed,
2801 strlen( notAllowed ) ) == 0 )
2802 {
2803 return XML_SYNTAX_ERR;
2804 }
2805
2806 tokenLength = pEndContent - xmlParser->curPtr;
2807 ParserClearTokenBuf(
2808#ifdef USE_CWMP_MEMORY_POOL
2809 pool ,
2810#endif
2811 xmlParser );
2812
2813 if ( XMLParserCopyToken(
2814#ifdef USE_CWMP_MEMORY_POOL
2815 pool ,
2816#endif
2817 xmlParser, xmlParser->curPtr, tokenLength )
2818 != XML_OK )
2819 {
2820 return XML_SYNTAX_ERR;
2821 }
2822
2823 pCurToken = ( xmlParser->tokenBuf ).buf;
2824 if ( pCurToken != NULL )
2825 {
2826 node->nodeValue = XmlStrduptrim(
2827#ifdef USE_CWMP_MEMORY_POOL
2828 pool ,
2829#endif
2830 pCurToken );
2831 if ( node->nodeValue == NULL )
2832 {
2833 return XML_INSUFFICIENT_MEMORY;
2834 }
2835 }
2836 else
2837 {
2838 return XML_SYNTAX_ERR;
2839 }
2840
2841 node->nodeName = PSTRDUP( TEXTNODENAME );
2842 if ( node->nodeName == NULL )
2843 {
2844 return XML_SYNTAX_ERR;
2845 }
2846 node->nodeType = XML_TEXT_NODE;
2847
2848 // adjust curPtr
2849 xmlParser->curPtr += tokenLength;
2850
2851 }
2852
2853 return XML_OK;
2854}
2855
2856/*==============================================================================*
2857*
2858* ParserProcessETag
2859* process ETag as defined by XML spec.
2860* Internal to parser only.
2861*
2862*===============================================================================*/
2863static int
2864ParserProcessETag(
2865 Pool * pool,
2866 XMLParser * xmlParser,
2867 XmlNode * node,
2868 OUT BOOL * bETag )
2869{
2870 char *pCurToken = NULL;
2871
2872 assert( xmlParser != NULL );
2873 if ( XMLParserGetNextToken(
2874#ifdef USE_CWMP_MEMORY_POOL
2875 pool ,
2876#endif
2877 xmlParser ) == 0 )
2878 {
2879 return XML_SYNTAX_ERR;
2880 }
2881
2882 pCurToken = ( xmlParser->tokenBuf ).buf;
2883 if ( pCurToken == NULL )
2884 {
2885 return XML_SYNTAX_ERR;
2886 }
2887 node->nodeName = PSTRDUP( pCurToken );
2888 if ( node->nodeName == NULL )
2889 {
2890 return XML_INSUFFICIENT_MEMORY;
2891 }
2892
2893 node->nodeValue = NULL;
2894 node->nodeType = XML_ELEMENT_NODE;
2895
2896 XMLParserSkipWhiteSpaces( xmlParser );
2897
2898 // read the >
2899 if ( XMLParserGetNextToken(
2900#ifdef USE_CWMP_MEMORY_POOL
2901 pool ,
2902#endif
2903 xmlParser ) == 0 )
2904 {
2905 return XML_SYNTAX_ERR;
2906 }
2907
2908 pCurToken = ( xmlParser->tokenBuf ).buf;
2909 if ( pCurToken == NULL ) // no need to PFREE node->nodeName, it is XFREEd by main loop
2910 {
2911 return XML_SYNTAX_ERR;
2912 }
2913
2914 if ( strcmp( pCurToken, ">" ) != 0 )
2915 {
2916 return XML_SYNTAX_ERR;
2917 }
2918
2919 *bETag = TRUE;
2920 return XML_OK;
2921}
2922
2923/*==============================================================================*
2924*
2925* XMLParserFreeElementStackItem
2926* XFREEs one ElementStack item.
2927* Internal to parser only.
2928*
2929*===============================================================================*/
2930static void
2931XMLParserFreeElementStackItem(
2932 Pool * pool,
2933 XmlElementStack * pItem )
2934{
2935 assert( pItem != NULL );
2936 if ( pItem->element != NULL )
2937 {
2938 PFREE( pItem->element );
2939 pItem->element = NULL;
2940 }
2941 if ( pItem->namespaceUri != NULL )
2942 {
2943 PFREE( pItem->namespaceUri );
2944 pItem->namespaceUri = NULL;
2945 }
2946 if ( pItem->prefix != NULL )
2947 {
2948 PFREE( pItem->prefix );
2949 pItem->prefix = NULL;
2950 }
2951
2952}
2953
2954/*==============================================================================*
2955*
2956* XMLParserFreeNsURI
2957* XFREEs namespaceURI item.
2958* Internal to parser only.
2959*
2960*===============================================================================*/
2961static void
2962XMLParserFreeNsURI(
2963 Pool * pool,
2964 XmlNameSpaceURI * pNsURI )
2965{
2966 assert( pNsURI != NULL );
2967 if ( pNsURI->nsURI != NULL )
2968 {
2969 PFREE( pNsURI->nsURI );
2970 }
2971 if ( pNsURI->prefix != NULL )
2972 {
2973 PFREE( pNsURI->prefix );
2974 }
2975}
2976
2977/*==============================================================================*
2978*
2979* XMLParserFree
2980* XFREEs all temporary memory allocated by xmlparser.
2981* Internal to parser only
2982*
2983*
2984*===============================================================================*/
2985static void
2986XMLParserFree(
2987 Pool * pool,
2988 XMLParser * xmlParser )
2989{
2990 XmlElementStack *pElement,
2991 *pNextElement;
2992 XmlNameSpaceURI *pNsURI,
2993 *pNextNsURI;
2994
2995 if ( xmlParser == NULL )
2996 {
2997 return;
2998 }
2999
3000 if ( xmlParser->dataBuffer != NULL )
3001 {
3002 PFREE( xmlParser->dataBuffer );
3003 }
3004
3005 XmlBufferDestroy(
3006#ifdef USE_CWMP_MEMORY_POOL
3007 pool ,
3008#endif
3009 &( xmlParser->tokenBuf ) );
3010 XmlBufferDestroy(
3011#ifdef USE_CWMP_MEMORY_POOL
3012 pool ,
3013#endif
3014 &( xmlParser->lastElem ) );
3015
3016 pElement = xmlParser->pCurElement;
3017 while ( pElement != NULL )
3018 {
3019 XMLParserFreeElementStackItem(
3020#ifdef USE_CWMP_MEMORY_POOL
3021 pool ,
3022#endif
3023 pElement );
3024
3025 pNsURI = pElement->pNsURI;
3026 while ( pNsURI != NULL )
3027 {
3028 pNextNsURI = pNsURI->nextNsURI;
3029 XMLParserFreeNsURI(
3030#ifdef USE_CWMP_MEMORY_POOL
3031 pool ,
3032#endif
3033 pNsURI );
3034 PFREE( pNsURI );
3035 pNsURI = pNextNsURI;
3036 }
3037
3038 pNextElement = pElement->nextElement;
3039 PFREE( pElement );
3040 pElement = pNextElement;
3041 }
3042
3043 PFREE( xmlParser );
3044
3045}
3046
3047/*==============================================================================*
3048*
3049* XMLParserParseReference
3050* return XML_OK or not
3051*
3052*
3053*===============================================================================*/
3054static int
3055XMLParserParseReference( IN char *pStr )
3056{
3057 // place holder for future implementation
3058 return XML_OK;
3059}
3060
3061/*==============================================================================*
3062*
3063* XMLParserProcessAttribute
3064* processes attribute.
3065* Internal to parser only.
3066* returns XML_OK or failure
3067*
3068*
3069*===============================================================================*/
3070static int
3071XMLParserProcessAttribute(
3072 Pool * pool,
3073
3074 XMLParser * xmlParser,
3075 XmlNode * node )
3076{
3077
3078 char *strEndQuote = NULL;
3079 int tlen = 0;
3080 char *pCur = NULL;
3081 char *pCurToken = NULL;
3082
3083// assert( xmlParser );
3084 if ( xmlParser == NULL )
3085 {
3086 return XML_FAILED;
3087 }
3088
3089 pCurToken = ( xmlParser->tokenBuf ).buf;
3090 if ( pCurToken == NULL )
3091 {
3092 return XML_SYNTAX_ERR;
3093 }
3094
3095 if ( XMLParserIsNameChar( Parser_UTF8ToInt( pCurToken, &tlen ), FALSE ) ==
3096 FALSE )
3097 {
3098 return XML_SYNTAX_ERR;
3099 }
3100 // copy in the attribute name
3101 node->nodeName = PSTRDUP( pCurToken );
3102 if ( node->nodeName == NULL )
3103 {
3104 return XML_INSUFFICIENT_MEMORY;
3105 }
3106 // read in the "=" sign
3107 if ( XMLParserGetNextToken(
3108#ifdef USE_CWMP_MEMORY_POOL
3109 pool ,
3110#endif
3111 xmlParser ) == 0 )
3112 {
3113 return XML_SYNTAX_ERR;
3114 }
3115
3116 pCurToken = ( xmlParser->tokenBuf ).buf;
3117 if ( *pCurToken != EQUALS )
3118 {
3119 return XML_SYNTAX_ERR;
3120 }
3121 // read in the single quote or double quote
3122 if ( XMLParserGetNextToken(
3123#ifdef USE_CWMP_MEMORY_POOL
3124 pool ,
3125#endif
3126 xmlParser ) == 0 )
3127 {
3128 return XML_SYNTAX_ERR;
3129 }
3130 // pCurToken is either quote or singlequote
3131 pCurToken = ( xmlParser->tokenBuf ).buf;
3132 if ( ( *pCurToken != QUOTE ) && ( *pCurToken != SINGLEQUOTE ) )
3133 {
3134 return XML_SYNTAX_ERR;
3135 }
3136
3137 strEndQuote = strstr( xmlParser->curPtr, pCurToken );
3138 if ( strEndQuote == NULL )
3139 {
3140 return XML_SYNTAX_ERR;
3141 }
3142 // check between curPtr and strEndQuote, whether there are illegal chars.
3143 pCur = xmlParser->curPtr;
3144 while ( pCur < strEndQuote )
3145 {
3146 if ( *pCur == '<' )
3147 {
3148 return XML_SYNTAX_ERR;
3149 }
3150
3151 if ( *pCur == '&' )
3152 {
3153 XMLParserParseReference( ++pCur );
3154 }
3155 pCur++;
3156 }
3157 //clear token buffer
3158 ParserClearTokenBuf(
3159#ifdef USE_CWMP_MEMORY_POOL
3160 pool ,
3161#endif
3162 xmlParser );
3163 if ( strEndQuote != xmlParser->curPtr )
3164 {
3165 if ( XMLParserCopyToken(
3166#ifdef USE_CWMP_MEMORY_POOL
3167 pool ,
3168#endif
3169
3170 xmlParser, xmlParser->curPtr,
3171 strEndQuote - xmlParser->curPtr ) !=
3172 XML_OK )
3173 {
3174 return XML_SYNTAX_ERR;
3175 }
3176 }
3177 // skip the ending quote
3178 xmlParser->curPtr = strEndQuote + 1;
3179
3180 pCurToken = ( xmlParser->tokenBuf ).buf;
3181 if ( pCurToken != NULL ) // attribute has value, like a="c"
3182 {
3183 node->nodeValue = XmlStrduptrim(
3184#ifdef USE_CWMP_MEMORY_POOL
3185 pool ,
3186#endif
3187 pCurToken );
3188 if ( node->nodeValue == NULL )
3189 {
3190 return XML_INSUFFICIENT_MEMORY;
3191 }
3192 }
3193 // if attribute doesn't have value, like a="", fine
3194 node->nodeType = XML_ATTRIBUTE_NODE;
3195
3196 // check whether this is a new namespace definition
3197 if ( XMLParserXmlNamespace(
3198#ifdef USE_CWMP_MEMORY_POOL
3199 pool ,
3200#endif
3201
3202 xmlParser, node ) != XML_OK )
3203 {
3204 return XML_FAILED;
3205 }
3206 // read ahead to see whether we have more attributes
3207 xmlParser->savePtr = xmlParser->curPtr;
3208 if ( XMLParserGetNextToken(
3209#ifdef USE_CWMP_MEMORY_POOL
3210 pool ,
3211#endif
3212
3213 xmlParser ) == 0 )
3214 {
3215 return XML_SYNTAX_ERR;
3216 }
3217
3218 pCurToken = ( xmlParser->tokenBuf ).buf;
3219 if ( strcmp( pCurToken, "<" ) == 0 )
3220 {
3221 return XML_FAILED;
3222 }
3223 else if ( strcmp( pCurToken, ">" ) != 0 ) // more attribute?
3224 {
3225 // backup
3226 xmlParser->curPtr = xmlParser->savePtr;
3227 }
3228 else
3229 {
3230 xmlParser->state = E_CONTENT;
3231 }
3232
3233 return XML_OK;
3234}
3235
3236/*==============================================================================*
3237*
3238* XMLParserGetNextNode
3239* return next node
3240* returns XML_OK or
3241*
3242*
3243*===============================================================================*/
3244static int
3245XMLParserGetNextNode(
3246 Pool * pool,
3247 XMLParser * xmlParser,
3248 OUT XmlNode * node,
3249 OUT BOOL * bETag )
3250{
3251 char *pCurToken = NULL;
3252 char *lastElement = NULL;
3253
3254 // endof file reached?
3255 if (xmlParser == NULL || *( xmlParser->curPtr ) == '\0' )
3256 {
3257 *bETag = TRUE;
3258 return XML_FILE_DONE;
3259 }
3260
3261 if ( xmlParser->state == E_CONTENT )
3262 {
3263 if ( ParserProcessContent(
3264#ifdef USE_CWMP_MEMORY_POOL
3265 pool ,
3266#endif
3267
3268 xmlParser, node ) != XML_OK )
3269 {
3270 return XML_FAILED;
3271 }
3272 }
3273 else
3274 {
3275 XMLParserSkipWhiteSpaces( xmlParser );
3276
3277 if ( ( XMLParserGetNextToken(
3278#ifdef USE_CWMP_MEMORY_POOL
3279 pool ,
3280#endif
3281
3282 xmlParser ) == 0 ) && ( xmlParser->pCurElement == NULL ) && ( *( xmlParser->curPtr ) == '\0' ) ) // comments after the xml doc
3283 {
3284 return XML_OK;
3285 }
3286 else if ( ( xmlParser->tokenBuf ).length == 0 )
3287 {
3288 return XML_SYNTAX_ERR;
3289 }
3290
3291 pCurToken = ( xmlParser->tokenBuf ).buf;
3292 if ( *pCurToken == GREATERTHAN )
3293 {
3294 return XML_OK;
3295 }
3296 else if ( strcmp( pCurToken, ENDTAG ) == 0 ) // we got </, read next element
3297 {
3298 return ParserProcessETag(
3299#ifdef USE_CWMP_MEMORY_POOL
3300 pool ,
3301#endif
3302
3303 xmlParser, node, bETag );
3304 }
3305 else if ( *pCurToken == LESSTHAN )
3306 {
3307 return ParserProcessSTag(
3308#ifdef USE_CWMP_MEMORY_POOL
3309 pool ,
3310#endif
3311 xmlParser, node );
3312 }
3313 else if ( strcmp( pCurToken, COMPLETETAG ) == 0 )
3314 {
3315 lastElement = ( xmlParser->lastElem ).buf;
3316 if ( lastElement == NULL )
3317 {
3318 goto ErrorHandler;
3319 }
3320
3321 node->nodeName = PSTRDUP( lastElement );
3322 if ( node->nodeName == NULL )
3323 {
3324 return XML_INSUFFICIENT_MEMORY;
3325 }
3326 node->nodeType = XML_ELEMENT_NODE;
3327 *bETag = TRUE;
3328
3329 return XML_OK;
3330 }
3331 else if ( xmlParser->state == E_ATTRIBUTE )
3332 {
3333 if ( XMLParserProcessAttribute(
3334#ifdef USE_CWMP_MEMORY_POOL
3335 pool ,
3336#endif
3337 xmlParser, node ) !=
3338 XML_OK )
3339 {
3340 return XML_SYNTAX_ERR;
3341 }
3342 }
3343 else
3344 {
3345 return XML_SYNTAX_ERR;
3346 }
3347 }
3348
3349 return XML_OK;
3350
3351ErrorHandler:
3352
3353 return XML_SYNTAX_ERR;
3354
3355}