|
1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd |
|
2 See the file COPYING for copying permission. |
|
3 */ |
|
4 |
|
5 #include <stddef.h> |
|
6 #include <string.h> /* memset(), memcpy() */ |
|
7 #include <assert.h> |
|
8 |
|
9 #define XML_BUILDING_EXPAT 1 |
|
10 |
|
11 #ifdef COMPILED_FROM_DSP |
|
12 #include "winconfig.h" |
|
13 #elif defined(MACOS_CLASSIC) |
|
14 #include "macconfig.h" |
|
15 #elif defined(__amigaos4__) |
|
16 #include "amigaconfig.h" |
|
17 #elif defined(HAVE_EXPAT_CONFIG_H) |
|
18 #include <expat_config.h> |
|
19 #endif /* ndef COMPILED_FROM_DSP */ |
|
20 |
|
21 #include "expat.h" |
|
22 |
|
23 #ifdef XML_UNICODE |
|
24 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX |
|
25 #define XmlConvert XmlUtf16Convert |
|
26 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding |
|
27 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS |
|
28 #define XmlEncode XmlUtf16Encode |
|
29 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) |
|
30 typedef unsigned short ICHAR; |
|
31 #else |
|
32 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX |
|
33 #define XmlConvert XmlUtf8Convert |
|
34 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding |
|
35 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS |
|
36 #define XmlEncode XmlUtf8Encode |
|
37 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8) |
|
38 typedef char ICHAR; |
|
39 #endif |
|
40 |
|
41 |
|
42 #ifndef XML_NS |
|
43 |
|
44 #define XmlInitEncodingNS XmlInitEncoding |
|
45 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding |
|
46 #undef XmlGetInternalEncodingNS |
|
47 #define XmlGetInternalEncodingNS XmlGetInternalEncoding |
|
48 #define XmlParseXmlDeclNS XmlParseXmlDecl |
|
49 |
|
50 #endif |
|
51 |
|
52 /* BEGIN MOZILLA CHANGE (typedef XML_Char to char16_t) */ |
|
53 #if 0 |
|
54 |
|
55 #ifdef XML_UNICODE |
|
56 |
|
57 #ifdef XML_UNICODE_WCHAR_T |
|
58 #define XML_T(x) (const wchar_t)x |
|
59 #define XML_L(x) L ## x |
|
60 #else |
|
61 #define XML_T(x) (const unsigned short)x |
|
62 #define XML_L(x) x |
|
63 #endif |
|
64 |
|
65 #else |
|
66 |
|
67 #define XML_T(x) x |
|
68 #define XML_L(x) x |
|
69 |
|
70 #endif |
|
71 |
|
72 #endif |
|
73 /* END MOZILLA CHANGE */ |
|
74 |
|
75 /* Round up n to be a multiple of sz, where sz is a power of 2. */ |
|
76 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) |
|
77 |
|
78 /* Handle the case where memmove() doesn't exist. */ |
|
79 #ifndef HAVE_MEMMOVE |
|
80 #ifdef HAVE_BCOPY |
|
81 #define memmove(d,s,l) bcopy((s),(d),(l)) |
|
82 #else |
|
83 #error memmove does not exist on this platform, nor is a substitute available |
|
84 #endif /* HAVE_BCOPY */ |
|
85 #endif /* HAVE_MEMMOVE */ |
|
86 |
|
87 #include "internal.h" |
|
88 #include "xmltok.h" |
|
89 #include "xmlrole.h" |
|
90 |
|
91 typedef const XML_Char *KEY; |
|
92 |
|
93 typedef struct { |
|
94 KEY name; |
|
95 } NAMED; |
|
96 |
|
97 typedef struct { |
|
98 NAMED **v; |
|
99 unsigned char power; |
|
100 size_t size; |
|
101 size_t used; |
|
102 const XML_Memory_Handling_Suite *mem; |
|
103 } HASH_TABLE; |
|
104 |
|
105 /* Basic character hash algorithm, taken from Python's string hash: |
|
106 h = h * 1000003 ^ character, the constant being a prime number. |
|
107 |
|
108 */ |
|
109 #ifdef XML_UNICODE |
|
110 #define CHAR_HASH(h, c) \ |
|
111 (((h) * 0xF4243) ^ (unsigned short)(c)) |
|
112 #else |
|
113 #define CHAR_HASH(h, c) \ |
|
114 (((h) * 0xF4243) ^ (unsigned char)(c)) |
|
115 #endif |
|
116 |
|
117 /* For probing (after a collision) we need a step size relative prime |
|
118 to the hash table size, which is a power of 2. We use double-hashing, |
|
119 since we can calculate a second hash value cheaply by taking those bits |
|
120 of the first hash value that were discarded (masked out) when the table |
|
121 index was calculated: index = hash & mask, where mask = table->size - 1. |
|
122 We limit the maximum step size to table->size / 4 (mask >> 2) and make |
|
123 it odd, since odd numbers are always relative prime to a power of 2. |
|
124 */ |
|
125 #define SECOND_HASH(hash, mask, power) \ |
|
126 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2)) |
|
127 #define PROBE_STEP(hash, mask, power) \ |
|
128 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) |
|
129 |
|
130 typedef struct { |
|
131 NAMED **p; |
|
132 NAMED **end; |
|
133 } HASH_TABLE_ITER; |
|
134 |
|
135 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ |
|
136 #define INIT_DATA_BUF_SIZE 1024 |
|
137 #define INIT_ATTS_SIZE 16 |
|
138 #define INIT_ATTS_VERSION 0xFFFFFFFF |
|
139 #define INIT_BLOCK_SIZE 1024 |
|
140 #define INIT_BUFFER_SIZE 1024 |
|
141 |
|
142 #define EXPAND_SPARE 24 |
|
143 |
|
144 typedef struct binding { |
|
145 struct prefix *prefix; |
|
146 struct binding *nextTagBinding; |
|
147 struct binding *prevPrefixBinding; |
|
148 const struct attribute_id *attId; |
|
149 XML_Char *uri; |
|
150 int uriLen; |
|
151 int uriAlloc; |
|
152 } BINDING; |
|
153 |
|
154 typedef struct prefix { |
|
155 const XML_Char *name; |
|
156 BINDING *binding; |
|
157 } PREFIX; |
|
158 |
|
159 typedef struct { |
|
160 const XML_Char *str; |
|
161 const XML_Char *localPart; |
|
162 const XML_Char *prefix; |
|
163 int strLen; |
|
164 int uriLen; |
|
165 int prefixLen; |
|
166 } TAG_NAME; |
|
167 |
|
168 /* TAG represents an open element. |
|
169 The name of the element is stored in both the document and API |
|
170 encodings. The memory buffer 'buf' is a separately-allocated |
|
171 memory area which stores the name. During the XML_Parse()/ |
|
172 XMLParseBuffer() when the element is open, the memory for the 'raw' |
|
173 version of the name (in the document encoding) is shared with the |
|
174 document buffer. If the element is open across calls to |
|
175 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to |
|
176 contain the 'raw' name as well. |
|
177 |
|
178 A parser re-uses these structures, maintaining a list of allocated |
|
179 TAG objects in a free list. |
|
180 */ |
|
181 typedef struct tag { |
|
182 struct tag *parent; /* parent of this element */ |
|
183 const char *rawName; /* tagName in the original encoding */ |
|
184 int rawNameLength; |
|
185 TAG_NAME name; /* tagName in the API encoding */ |
|
186 char *buf; /* buffer for name components */ |
|
187 char *bufEnd; /* end of the buffer */ |
|
188 BINDING *bindings; |
|
189 } TAG; |
|
190 |
|
191 typedef struct { |
|
192 const XML_Char *name; |
|
193 const XML_Char *textPtr; |
|
194 int textLen; /* length in XML_Chars */ |
|
195 int processed; /* # of processed bytes - when suspended */ |
|
196 const XML_Char *systemId; |
|
197 const XML_Char *base; |
|
198 const XML_Char *publicId; |
|
199 const XML_Char *notation; |
|
200 XML_Bool open; |
|
201 XML_Bool is_param; |
|
202 XML_Bool is_internal; /* true if declared in internal subset outside PE */ |
|
203 } ENTITY; |
|
204 |
|
205 typedef struct { |
|
206 enum XML_Content_Type type; |
|
207 enum XML_Content_Quant quant; |
|
208 const XML_Char * name; |
|
209 int firstchild; |
|
210 int lastchild; |
|
211 int childcnt; |
|
212 int nextsib; |
|
213 } CONTENT_SCAFFOLD; |
|
214 |
|
215 #define INIT_SCAFFOLD_ELEMENTS 32 |
|
216 |
|
217 typedef struct block { |
|
218 struct block *next; |
|
219 int size; |
|
220 XML_Char s[1]; |
|
221 } BLOCK; |
|
222 |
|
223 typedef struct { |
|
224 BLOCK *blocks; |
|
225 BLOCK *freeBlocks; |
|
226 const XML_Char *end; |
|
227 XML_Char *ptr; |
|
228 XML_Char *start; |
|
229 const XML_Memory_Handling_Suite *mem; |
|
230 } STRING_POOL; |
|
231 |
|
232 /* The XML_Char before the name is used to determine whether |
|
233 an attribute has been specified. */ |
|
234 typedef struct attribute_id { |
|
235 XML_Char *name; |
|
236 PREFIX *prefix; |
|
237 XML_Bool maybeTokenized; |
|
238 XML_Bool xmlns; |
|
239 } ATTRIBUTE_ID; |
|
240 |
|
241 typedef struct { |
|
242 const ATTRIBUTE_ID *id; |
|
243 XML_Bool isCdata; |
|
244 const XML_Char *value; |
|
245 } DEFAULT_ATTRIBUTE; |
|
246 |
|
247 typedef struct { |
|
248 unsigned long version; |
|
249 unsigned long hash; |
|
250 const XML_Char *uriName; |
|
251 } NS_ATT; |
|
252 |
|
253 typedef struct { |
|
254 const XML_Char *name; |
|
255 PREFIX *prefix; |
|
256 const ATTRIBUTE_ID *idAtt; |
|
257 int nDefaultAtts; |
|
258 int allocDefaultAtts; |
|
259 DEFAULT_ATTRIBUTE *defaultAtts; |
|
260 } ELEMENT_TYPE; |
|
261 |
|
262 typedef struct { |
|
263 HASH_TABLE generalEntities; |
|
264 HASH_TABLE elementTypes; |
|
265 HASH_TABLE attributeIds; |
|
266 HASH_TABLE prefixes; |
|
267 STRING_POOL pool; |
|
268 STRING_POOL entityValuePool; |
|
269 /* false once a parameter entity reference has been skipped */ |
|
270 XML_Bool keepProcessing; |
|
271 /* true once an internal or external PE reference has been encountered; |
|
272 this includes the reference to an external subset */ |
|
273 XML_Bool hasParamEntityRefs; |
|
274 XML_Bool standalone; |
|
275 #ifdef XML_DTD |
|
276 /* indicates if external PE has been read */ |
|
277 XML_Bool paramEntityRead; |
|
278 HASH_TABLE paramEntities; |
|
279 #endif /* XML_DTD */ |
|
280 PREFIX defaultPrefix; |
|
281 /* === scaffolding for building content model === */ |
|
282 XML_Bool in_eldecl; |
|
283 CONTENT_SCAFFOLD *scaffold; |
|
284 unsigned contentStringLen; |
|
285 unsigned scaffSize; |
|
286 unsigned scaffCount; |
|
287 int scaffLevel; |
|
288 int *scaffIndex; |
|
289 } DTD; |
|
290 |
|
291 typedef struct open_internal_entity { |
|
292 const char *internalEventPtr; |
|
293 const char *internalEventEndPtr; |
|
294 struct open_internal_entity *next; |
|
295 ENTITY *entity; |
|
296 int startTagLevel; |
|
297 XML_Bool betweenDecl; /* WFC: PE Between Declarations */ |
|
298 } OPEN_INTERNAL_ENTITY; |
|
299 |
|
300 typedef enum XML_Error PTRCALL Processor(XML_Parser parser, |
|
301 const char *start, |
|
302 const char *end, |
|
303 const char **endPtr); |
|
304 |
|
305 static Processor prologProcessor; |
|
306 static Processor prologInitProcessor; |
|
307 static Processor contentProcessor; |
|
308 static Processor cdataSectionProcessor; |
|
309 #ifdef XML_DTD |
|
310 static Processor ignoreSectionProcessor; |
|
311 static Processor externalParEntProcessor; |
|
312 static Processor externalParEntInitProcessor; |
|
313 static Processor entityValueProcessor; |
|
314 static Processor entityValueInitProcessor; |
|
315 #endif /* XML_DTD */ |
|
316 static Processor epilogProcessor; |
|
317 static Processor errorProcessor; |
|
318 static Processor externalEntityInitProcessor; |
|
319 static Processor externalEntityInitProcessor2; |
|
320 static Processor externalEntityInitProcessor3; |
|
321 static Processor externalEntityContentProcessor; |
|
322 static Processor internalEntityProcessor; |
|
323 |
|
324 static enum XML_Error |
|
325 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); |
|
326 static enum XML_Error |
|
327 processXmlDecl(XML_Parser parser, int isGeneralTextEntity, |
|
328 const char *s, const char *next); |
|
329 static enum XML_Error |
|
330 initializeEncoding(XML_Parser parser); |
|
331 static enum XML_Error |
|
332 doProlog(XML_Parser parser, const ENCODING *enc, const char *s, |
|
333 const char *end, int tok, const char *next, const char **nextPtr, |
|
334 XML_Bool haveMore); |
|
335 static enum XML_Error |
|
336 processInternalEntity(XML_Parser parser, ENTITY *entity, |
|
337 XML_Bool betweenDecl); |
|
338 static enum XML_Error |
|
339 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, |
|
340 const char *start, const char *end, const char **endPtr, |
|
341 XML_Bool haveMore); |
|
342 static enum XML_Error |
|
343 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, |
|
344 const char *end, const char **nextPtr, XML_Bool haveMore); |
|
345 #ifdef XML_DTD |
|
346 static enum XML_Error |
|
347 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, |
|
348 const char *end, const char **nextPtr, XML_Bool haveMore); |
|
349 #endif /* XML_DTD */ |
|
350 |
|
351 static enum XML_Error |
|
352 storeAtts(XML_Parser parser, const ENCODING *, const char *s, |
|
353 TAG_NAME *tagNamePtr, BINDING **bindingsPtr); |
|
354 static enum XML_Error |
|
355 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, |
|
356 const XML_Char *uri, BINDING **bindingsPtr); |
|
357 static int |
|
358 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, |
|
359 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser); |
|
360 static enum XML_Error |
|
361 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, |
|
362 const char *, const char *, STRING_POOL *); |
|
363 static enum XML_Error |
|
364 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, |
|
365 const char *, const char *, STRING_POOL *); |
|
366 static ATTRIBUTE_ID * |
|
367 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, |
|
368 const char *end); |
|
369 static int |
|
370 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); |
|
371 static enum XML_Error |
|
372 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, |
|
373 const char *end); |
|
374 static int |
|
375 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, |
|
376 const char *start, const char *end); |
|
377 static int |
|
378 reportComment(XML_Parser parser, const ENCODING *enc, const char *start, |
|
379 const char *end); |
|
380 static void |
|
381 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, |
|
382 const char *end); |
|
383 |
|
384 static const XML_Char * getContext(XML_Parser parser); |
|
385 static XML_Bool |
|
386 setContext(XML_Parser parser, const XML_Char *context); |
|
387 |
|
388 static void FASTCALL normalizePublicId(XML_Char *s); |
|
389 |
|
390 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms); |
|
391 /* do not call if parentParser != NULL */ |
|
392 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); |
|
393 static void |
|
394 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); |
|
395 static int |
|
396 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); |
|
397 static int |
|
398 copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); |
|
399 |
|
400 static NAMED * |
|
401 lookup(HASH_TABLE *table, KEY name, size_t createSize); |
|
402 static void FASTCALL |
|
403 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); |
|
404 static void FASTCALL hashTableClear(HASH_TABLE *); |
|
405 static void FASTCALL hashTableDestroy(HASH_TABLE *); |
|
406 static void FASTCALL |
|
407 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); |
|
408 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *); |
|
409 |
|
410 static void FASTCALL |
|
411 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms); |
|
412 static void FASTCALL poolClear(STRING_POOL *); |
|
413 static void FASTCALL poolDestroy(STRING_POOL *); |
|
414 static XML_Char * |
|
415 poolAppend(STRING_POOL *pool, const ENCODING *enc, |
|
416 const char *ptr, const char *end); |
|
417 static XML_Char * |
|
418 poolStoreString(STRING_POOL *pool, const ENCODING *enc, |
|
419 const char *ptr, const char *end); |
|
420 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); |
|
421 static const XML_Char * FASTCALL |
|
422 poolCopyString(STRING_POOL *pool, const XML_Char *s); |
|
423 static const XML_Char * |
|
424 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); |
|
425 static const XML_Char * FASTCALL |
|
426 poolAppendString(STRING_POOL *pool, const XML_Char *s); |
|
427 |
|
428 static int FASTCALL nextScaffoldPart(XML_Parser parser); |
|
429 static XML_Content * build_model(XML_Parser parser); |
|
430 static ELEMENT_TYPE * |
|
431 getElementType(XML_Parser parser, const ENCODING *enc, |
|
432 const char *ptr, const char *end); |
|
433 |
|
434 static XML_Parser |
|
435 parserCreate(const XML_Char *encodingName, |
|
436 const XML_Memory_Handling_Suite *memsuite, |
|
437 const XML_Char *nameSep, |
|
438 DTD *dtd); |
|
439 static void |
|
440 parserInit(XML_Parser parser, const XML_Char *encodingName); |
|
441 |
|
442 #define poolStart(pool) ((pool)->start) |
|
443 #define poolEnd(pool) ((pool)->ptr) |
|
444 #define poolLength(pool) ((pool)->ptr - (pool)->start) |
|
445 #define poolChop(pool) ((void)--(pool->ptr)) |
|
446 #define poolLastChar(pool) (((pool)->ptr)[-1]) |
|
447 #define poolDiscard(pool) ((pool)->ptr = (pool)->start) |
|
448 #define poolFinish(pool) ((pool)->start = (pool)->ptr) |
|
449 #define poolAppendChar(pool, c) \ |
|
450 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ |
|
451 ? 0 \ |
|
452 : ((*((pool)->ptr)++ = c), 1)) |
|
453 |
|
454 struct XML_ParserStruct { |
|
455 /* The first member must be userData so that the XML_GetUserData |
|
456 macro works. */ |
|
457 void *m_userData; |
|
458 void *m_handlerArg; |
|
459 char *m_buffer; |
|
460 const XML_Memory_Handling_Suite m_mem; |
|
461 /* first character to be parsed */ |
|
462 const char *m_bufferPtr; |
|
463 /* past last character to be parsed */ |
|
464 char *m_bufferEnd; |
|
465 /* allocated end of buffer */ |
|
466 const char *m_bufferLim; |
|
467 XML_Index m_parseEndByteIndex; |
|
468 const char *m_parseEndPtr; |
|
469 XML_Char *m_dataBuf; |
|
470 XML_Char *m_dataBufEnd; |
|
471 XML_StartElementHandler m_startElementHandler; |
|
472 XML_EndElementHandler m_endElementHandler; |
|
473 XML_CharacterDataHandler m_characterDataHandler; |
|
474 XML_ProcessingInstructionHandler m_processingInstructionHandler; |
|
475 XML_CommentHandler m_commentHandler; |
|
476 XML_StartCdataSectionHandler m_startCdataSectionHandler; |
|
477 XML_EndCdataSectionHandler m_endCdataSectionHandler; |
|
478 XML_DefaultHandler m_defaultHandler; |
|
479 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; |
|
480 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; |
|
481 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; |
|
482 XML_NotationDeclHandler m_notationDeclHandler; |
|
483 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; |
|
484 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; |
|
485 XML_NotStandaloneHandler m_notStandaloneHandler; |
|
486 XML_ExternalEntityRefHandler m_externalEntityRefHandler; |
|
487 XML_Parser m_externalEntityRefHandlerArg; |
|
488 XML_SkippedEntityHandler m_skippedEntityHandler; |
|
489 XML_UnknownEncodingHandler m_unknownEncodingHandler; |
|
490 XML_ElementDeclHandler m_elementDeclHandler; |
|
491 XML_AttlistDeclHandler m_attlistDeclHandler; |
|
492 XML_EntityDeclHandler m_entityDeclHandler; |
|
493 XML_XmlDeclHandler m_xmlDeclHandler; |
|
494 const ENCODING *m_encoding; |
|
495 INIT_ENCODING m_initEncoding; |
|
496 const ENCODING *m_internalEncoding; |
|
497 const XML_Char *m_protocolEncodingName; |
|
498 XML_Bool m_ns; |
|
499 XML_Bool m_ns_triplets; |
|
500 void *m_unknownEncodingMem; |
|
501 void *m_unknownEncodingData; |
|
502 void *m_unknownEncodingHandlerData; |
|
503 void (XMLCALL *m_unknownEncodingRelease)(void *); |
|
504 PROLOG_STATE m_prologState; |
|
505 Processor *m_processor; |
|
506 enum XML_Error m_errorCode; |
|
507 const char *m_eventPtr; |
|
508 const char *m_eventEndPtr; |
|
509 const char *m_positionPtr; |
|
510 OPEN_INTERNAL_ENTITY *m_openInternalEntities; |
|
511 OPEN_INTERNAL_ENTITY *m_freeInternalEntities; |
|
512 XML_Bool m_defaultExpandInternalEntities; |
|
513 int m_tagLevel; |
|
514 ENTITY *m_declEntity; |
|
515 const XML_Char *m_doctypeName; |
|
516 const XML_Char *m_doctypeSysid; |
|
517 const XML_Char *m_doctypePubid; |
|
518 const XML_Char *m_declAttributeType; |
|
519 const XML_Char *m_declNotationName; |
|
520 const XML_Char *m_declNotationPublicId; |
|
521 ELEMENT_TYPE *m_declElementType; |
|
522 ATTRIBUTE_ID *m_declAttributeId; |
|
523 XML_Bool m_declAttributeIsCdata; |
|
524 XML_Bool m_declAttributeIsId; |
|
525 DTD *m_dtd; |
|
526 const XML_Char *m_curBase; |
|
527 TAG *m_tagStack; |
|
528 TAG *m_freeTagList; |
|
529 BINDING *m_inheritedBindings; |
|
530 BINDING *m_freeBindingList; |
|
531 int m_attsSize; |
|
532 int m_nSpecifiedAtts; |
|
533 int m_idAttIndex; |
|
534 ATTRIBUTE *m_atts; |
|
535 NS_ATT *m_nsAtts; |
|
536 unsigned long m_nsAttsVersion; |
|
537 unsigned char m_nsAttsPower; |
|
538 POSITION m_position; |
|
539 STRING_POOL m_tempPool; |
|
540 STRING_POOL m_temp2Pool; |
|
541 char *m_groupConnector; |
|
542 unsigned int m_groupSize; |
|
543 XML_Char m_namespaceSeparator; |
|
544 XML_Parser m_parentParser; |
|
545 XML_ParsingStatus m_parsingStatus; |
|
546 #ifdef XML_DTD |
|
547 XML_Bool m_isParamEntity; |
|
548 XML_Bool m_useForeignDTD; |
|
549 enum XML_ParamEntityParsing m_paramEntityParsing; |
|
550 #endif |
|
551 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */ |
|
552 const XML_Char* m_mismatch; |
|
553 /* END MOZILLA CHANGE */ |
|
554 }; |
|
555 |
|
556 #define MALLOC(s) (parser->m_mem.malloc_fcn((s))) |
|
557 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s))) |
|
558 #define FREE(p) (parser->m_mem.free_fcn((p))) |
|
559 |
|
560 #define userData (parser->m_userData) |
|
561 #define handlerArg (parser->m_handlerArg) |
|
562 #define startElementHandler (parser->m_startElementHandler) |
|
563 #define endElementHandler (parser->m_endElementHandler) |
|
564 #define characterDataHandler (parser->m_characterDataHandler) |
|
565 #define processingInstructionHandler \ |
|
566 (parser->m_processingInstructionHandler) |
|
567 #define commentHandler (parser->m_commentHandler) |
|
568 #define startCdataSectionHandler \ |
|
569 (parser->m_startCdataSectionHandler) |
|
570 #define endCdataSectionHandler (parser->m_endCdataSectionHandler) |
|
571 #define defaultHandler (parser->m_defaultHandler) |
|
572 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler) |
|
573 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler) |
|
574 #define unparsedEntityDeclHandler \ |
|
575 (parser->m_unparsedEntityDeclHandler) |
|
576 #define notationDeclHandler (parser->m_notationDeclHandler) |
|
577 #define startNamespaceDeclHandler \ |
|
578 (parser->m_startNamespaceDeclHandler) |
|
579 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler) |
|
580 #define notStandaloneHandler (parser->m_notStandaloneHandler) |
|
581 #define externalEntityRefHandler \ |
|
582 (parser->m_externalEntityRefHandler) |
|
583 #define externalEntityRefHandlerArg \ |
|
584 (parser->m_externalEntityRefHandlerArg) |
|
585 #define internalEntityRefHandler \ |
|
586 (parser->m_internalEntityRefHandler) |
|
587 #define skippedEntityHandler (parser->m_skippedEntityHandler) |
|
588 #define unknownEncodingHandler (parser->m_unknownEncodingHandler) |
|
589 #define elementDeclHandler (parser->m_elementDeclHandler) |
|
590 #define attlistDeclHandler (parser->m_attlistDeclHandler) |
|
591 #define entityDeclHandler (parser->m_entityDeclHandler) |
|
592 #define xmlDeclHandler (parser->m_xmlDeclHandler) |
|
593 #define encoding (parser->m_encoding) |
|
594 #define initEncoding (parser->m_initEncoding) |
|
595 #define internalEncoding (parser->m_internalEncoding) |
|
596 #define unknownEncodingMem (parser->m_unknownEncodingMem) |
|
597 #define unknownEncodingData (parser->m_unknownEncodingData) |
|
598 #define unknownEncodingHandlerData \ |
|
599 (parser->m_unknownEncodingHandlerData) |
|
600 #define unknownEncodingRelease (parser->m_unknownEncodingRelease) |
|
601 #define protocolEncodingName (parser->m_protocolEncodingName) |
|
602 #define ns (parser->m_ns) |
|
603 #define ns_triplets (parser->m_ns_triplets) |
|
604 #define prologState (parser->m_prologState) |
|
605 #define processor (parser->m_processor) |
|
606 #define errorCode (parser->m_errorCode) |
|
607 #define eventPtr (parser->m_eventPtr) |
|
608 #define eventEndPtr (parser->m_eventEndPtr) |
|
609 #define positionPtr (parser->m_positionPtr) |
|
610 #define position (parser->m_position) |
|
611 #define openInternalEntities (parser->m_openInternalEntities) |
|
612 #define freeInternalEntities (parser->m_freeInternalEntities) |
|
613 #define defaultExpandInternalEntities \ |
|
614 (parser->m_defaultExpandInternalEntities) |
|
615 #define tagLevel (parser->m_tagLevel) |
|
616 #define buffer (parser->m_buffer) |
|
617 #define bufferPtr (parser->m_bufferPtr) |
|
618 #define bufferEnd (parser->m_bufferEnd) |
|
619 #define parseEndByteIndex (parser->m_parseEndByteIndex) |
|
620 #define parseEndPtr (parser->m_parseEndPtr) |
|
621 #define bufferLim (parser->m_bufferLim) |
|
622 #define dataBuf (parser->m_dataBuf) |
|
623 #define dataBufEnd (parser->m_dataBufEnd) |
|
624 #define _dtd (parser->m_dtd) |
|
625 #define curBase (parser->m_curBase) |
|
626 #define declEntity (parser->m_declEntity) |
|
627 #define doctypeName (parser->m_doctypeName) |
|
628 #define doctypeSysid (parser->m_doctypeSysid) |
|
629 #define doctypePubid (parser->m_doctypePubid) |
|
630 #define declAttributeType (parser->m_declAttributeType) |
|
631 #define declNotationName (parser->m_declNotationName) |
|
632 #define declNotationPublicId (parser->m_declNotationPublicId) |
|
633 #define declElementType (parser->m_declElementType) |
|
634 #define declAttributeId (parser->m_declAttributeId) |
|
635 #define declAttributeIsCdata (parser->m_declAttributeIsCdata) |
|
636 #define declAttributeIsId (parser->m_declAttributeIsId) |
|
637 #define freeTagList (parser->m_freeTagList) |
|
638 #define freeBindingList (parser->m_freeBindingList) |
|
639 #define inheritedBindings (parser->m_inheritedBindings) |
|
640 #define tagStack (parser->m_tagStack) |
|
641 #define atts (parser->m_atts) |
|
642 #define attsSize (parser->m_attsSize) |
|
643 #define nSpecifiedAtts (parser->m_nSpecifiedAtts) |
|
644 #define idAttIndex (parser->m_idAttIndex) |
|
645 #define nsAtts (parser->m_nsAtts) |
|
646 #define nsAttsVersion (parser->m_nsAttsVersion) |
|
647 #define nsAttsPower (parser->m_nsAttsPower) |
|
648 #define tempPool (parser->m_tempPool) |
|
649 #define temp2Pool (parser->m_temp2Pool) |
|
650 #define groupConnector (parser->m_groupConnector) |
|
651 #define groupSize (parser->m_groupSize) |
|
652 #define namespaceSeparator (parser->m_namespaceSeparator) |
|
653 #define parentParser (parser->m_parentParser) |
|
654 #define ps_parsing (parser->m_parsingStatus.parsing) |
|
655 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer) |
|
656 #ifdef XML_DTD |
|
657 #define isParamEntity (parser->m_isParamEntity) |
|
658 #define useForeignDTD (parser->m_useForeignDTD) |
|
659 #define paramEntityParsing (parser->m_paramEntityParsing) |
|
660 #endif /* XML_DTD */ |
|
661 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */ |
|
662 #define mismatch (parser->m_mismatch) |
|
663 /* END MOZILLA CHANGE */ |
|
664 |
|
665 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
666 #if 0 |
|
667 XML_Parser XMLCALL |
|
668 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) |
|
669 { |
|
670 XML_Char tmp[2]; |
|
671 *tmp = nsSep; |
|
672 return XML_ParserCreate_MM(encodingName, NULL, tmp); |
|
673 } |
|
674 #endif |
|
675 /* END MOZILLA CHANGE */ |
|
676 |
|
677 static const XML_Char implicitContext[] = { |
|
678 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/', |
|
679 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', |
|
680 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', |
|
681 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' |
|
682 }; |
|
683 |
|
684 XML_Parser XMLCALL |
|
685 XML_ParserCreate_MM(const XML_Char *encodingName, |
|
686 const XML_Memory_Handling_Suite *memsuite, |
|
687 const XML_Char *nameSep) |
|
688 { |
|
689 XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); |
|
690 if (parser != NULL && ns) { |
|
691 /* implicit context only set for root parser, since child |
|
692 parsers (i.e. external entity parsers) will inherit it |
|
693 */ |
|
694 if (!setContext(parser, implicitContext)) { |
|
695 XML_ParserFree(parser); |
|
696 return NULL; |
|
697 } |
|
698 } |
|
699 return parser; |
|
700 } |
|
701 |
|
702 static XML_Parser |
|
703 parserCreate(const XML_Char *encodingName, |
|
704 const XML_Memory_Handling_Suite *memsuite, |
|
705 const XML_Char *nameSep, |
|
706 DTD *dtd) |
|
707 { |
|
708 XML_Parser parser; |
|
709 |
|
710 if (memsuite) { |
|
711 XML_Memory_Handling_Suite *mtemp; |
|
712 parser = (XML_Parser) |
|
713 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); |
|
714 if (parser != NULL) { |
|
715 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); |
|
716 mtemp->malloc_fcn = memsuite->malloc_fcn; |
|
717 mtemp->realloc_fcn = memsuite->realloc_fcn; |
|
718 mtemp->free_fcn = memsuite->free_fcn; |
|
719 } |
|
720 } |
|
721 else { |
|
722 XML_Memory_Handling_Suite *mtemp; |
|
723 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); |
|
724 if (parser != NULL) { |
|
725 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); |
|
726 mtemp->malloc_fcn = malloc; |
|
727 mtemp->realloc_fcn = realloc; |
|
728 mtemp->free_fcn = free; |
|
729 } |
|
730 } |
|
731 |
|
732 if (!parser) |
|
733 return parser; |
|
734 |
|
735 buffer = NULL; |
|
736 bufferLim = NULL; |
|
737 |
|
738 attsSize = INIT_ATTS_SIZE; |
|
739 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); |
|
740 if (atts == NULL) { |
|
741 FREE(parser); |
|
742 return NULL; |
|
743 } |
|
744 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); |
|
745 if (dataBuf == NULL) { |
|
746 FREE(atts); |
|
747 FREE(parser); |
|
748 return NULL; |
|
749 } |
|
750 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; |
|
751 |
|
752 if (dtd) |
|
753 _dtd = dtd; |
|
754 else { |
|
755 _dtd = dtdCreate(&parser->m_mem); |
|
756 if (_dtd == NULL) { |
|
757 FREE(dataBuf); |
|
758 FREE(atts); |
|
759 FREE(parser); |
|
760 return NULL; |
|
761 } |
|
762 } |
|
763 |
|
764 freeBindingList = NULL; |
|
765 freeTagList = NULL; |
|
766 freeInternalEntities = NULL; |
|
767 |
|
768 groupSize = 0; |
|
769 groupConnector = NULL; |
|
770 |
|
771 unknownEncodingHandler = NULL; |
|
772 unknownEncodingHandlerData = NULL; |
|
773 |
|
774 namespaceSeparator = '!'; |
|
775 ns = XML_FALSE; |
|
776 ns_triplets = XML_FALSE; |
|
777 |
|
778 nsAtts = NULL; |
|
779 nsAttsVersion = 0; |
|
780 nsAttsPower = 0; |
|
781 |
|
782 poolInit(&tempPool, &(parser->m_mem)); |
|
783 poolInit(&temp2Pool, &(parser->m_mem)); |
|
784 parserInit(parser, encodingName); |
|
785 |
|
786 if (encodingName && !protocolEncodingName) { |
|
787 XML_ParserFree(parser); |
|
788 return NULL; |
|
789 } |
|
790 |
|
791 if (nameSep) { |
|
792 ns = XML_TRUE; |
|
793 internalEncoding = XmlGetInternalEncodingNS(); |
|
794 namespaceSeparator = *nameSep; |
|
795 } |
|
796 else { |
|
797 internalEncoding = XmlGetInternalEncoding(); |
|
798 } |
|
799 |
|
800 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */ |
|
801 mismatch = NULL; |
|
802 /* END MOZILLA CHANGE */ |
|
803 |
|
804 return parser; |
|
805 } |
|
806 |
|
807 static void |
|
808 parserInit(XML_Parser parser, const XML_Char *encodingName) |
|
809 { |
|
810 processor = prologInitProcessor; |
|
811 XmlPrologStateInit(&prologState); |
|
812 protocolEncodingName = (encodingName != NULL |
|
813 ? poolCopyString(&tempPool, encodingName) |
|
814 : NULL); |
|
815 curBase = NULL; |
|
816 XmlInitEncoding(&initEncoding, &encoding, 0); |
|
817 userData = NULL; |
|
818 handlerArg = NULL; |
|
819 startElementHandler = NULL; |
|
820 endElementHandler = NULL; |
|
821 characterDataHandler = NULL; |
|
822 processingInstructionHandler = NULL; |
|
823 commentHandler = NULL; |
|
824 startCdataSectionHandler = NULL; |
|
825 endCdataSectionHandler = NULL; |
|
826 defaultHandler = NULL; |
|
827 startDoctypeDeclHandler = NULL; |
|
828 endDoctypeDeclHandler = NULL; |
|
829 unparsedEntityDeclHandler = NULL; |
|
830 notationDeclHandler = NULL; |
|
831 startNamespaceDeclHandler = NULL; |
|
832 endNamespaceDeclHandler = NULL; |
|
833 notStandaloneHandler = NULL; |
|
834 externalEntityRefHandler = NULL; |
|
835 externalEntityRefHandlerArg = parser; |
|
836 skippedEntityHandler = NULL; |
|
837 elementDeclHandler = NULL; |
|
838 attlistDeclHandler = NULL; |
|
839 entityDeclHandler = NULL; |
|
840 xmlDeclHandler = NULL; |
|
841 bufferPtr = buffer; |
|
842 bufferEnd = buffer; |
|
843 parseEndByteIndex = 0; |
|
844 parseEndPtr = NULL; |
|
845 declElementType = NULL; |
|
846 declAttributeId = NULL; |
|
847 declEntity = NULL; |
|
848 doctypeName = NULL; |
|
849 doctypeSysid = NULL; |
|
850 doctypePubid = NULL; |
|
851 declAttributeType = NULL; |
|
852 declNotationName = NULL; |
|
853 declNotationPublicId = NULL; |
|
854 declAttributeIsCdata = XML_FALSE; |
|
855 declAttributeIsId = XML_FALSE; |
|
856 memset(&position, 0, sizeof(POSITION)); |
|
857 errorCode = XML_ERROR_NONE; |
|
858 eventPtr = NULL; |
|
859 eventEndPtr = NULL; |
|
860 positionPtr = NULL; |
|
861 openInternalEntities = NULL; |
|
862 defaultExpandInternalEntities = XML_TRUE; |
|
863 tagLevel = 0; |
|
864 tagStack = NULL; |
|
865 inheritedBindings = NULL; |
|
866 nSpecifiedAtts = 0; |
|
867 unknownEncodingMem = NULL; |
|
868 unknownEncodingRelease = NULL; |
|
869 unknownEncodingData = NULL; |
|
870 parentParser = NULL; |
|
871 ps_parsing = XML_INITIALIZED; |
|
872 #ifdef XML_DTD |
|
873 isParamEntity = XML_FALSE; |
|
874 useForeignDTD = XML_FALSE; |
|
875 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; |
|
876 #endif |
|
877 } |
|
878 |
|
879 /* moves list of bindings to freeBindingList */ |
|
880 static void FASTCALL |
|
881 moveToFreeBindingList(XML_Parser parser, BINDING *bindings) |
|
882 { |
|
883 while (bindings) { |
|
884 BINDING *b = bindings; |
|
885 bindings = bindings->nextTagBinding; |
|
886 b->nextTagBinding = freeBindingList; |
|
887 freeBindingList = b; |
|
888 } |
|
889 } |
|
890 |
|
891 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
892 #if 0 |
|
893 XML_Bool XMLCALL |
|
894 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) |
|
895 { |
|
896 TAG *tStk; |
|
897 OPEN_INTERNAL_ENTITY *openEntityList; |
|
898 if (parentParser) |
|
899 return XML_FALSE; |
|
900 /* move tagStack to freeTagList */ |
|
901 tStk = tagStack; |
|
902 while (tStk) { |
|
903 TAG *tag = tStk; |
|
904 tStk = tStk->parent; |
|
905 tag->parent = freeTagList; |
|
906 moveToFreeBindingList(parser, tag->bindings); |
|
907 tag->bindings = NULL; |
|
908 freeTagList = tag; |
|
909 } |
|
910 /* move openInternalEntities to freeInternalEntities */ |
|
911 openEntityList = openInternalEntities; |
|
912 while (openEntityList) { |
|
913 OPEN_INTERNAL_ENTITY *openEntity = openEntityList; |
|
914 openEntityList = openEntity->next; |
|
915 openEntity->next = freeInternalEntities; |
|
916 freeInternalEntities = openEntity; |
|
917 } |
|
918 moveToFreeBindingList(parser, inheritedBindings); |
|
919 FREE(unknownEncodingMem); |
|
920 if (unknownEncodingRelease) |
|
921 unknownEncodingRelease(unknownEncodingData); |
|
922 poolClear(&tempPool); |
|
923 poolClear(&temp2Pool); |
|
924 parserInit(parser, encodingName); |
|
925 dtdReset(_dtd, &parser->m_mem); |
|
926 return setContext(parser, implicitContext); |
|
927 } |
|
928 |
|
929 enum XML_Status XMLCALL |
|
930 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) |
|
931 { |
|
932 /* Block after XML_Parse()/XML_ParseBuffer() has been called. |
|
933 XXX There's no way for the caller to determine which of the |
|
934 XXX possible error cases caused the XML_STATUS_ERROR return. |
|
935 */ |
|
936 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) |
|
937 return XML_STATUS_ERROR; |
|
938 if (encodingName == NULL) |
|
939 protocolEncodingName = NULL; |
|
940 else { |
|
941 protocolEncodingName = poolCopyString(&tempPool, encodingName); |
|
942 if (!protocolEncodingName) |
|
943 return XML_STATUS_ERROR; |
|
944 } |
|
945 return XML_STATUS_OK; |
|
946 } |
|
947 #endif |
|
948 /* END MOZILLA CHANGE */ |
|
949 |
|
950 XML_Parser XMLCALL |
|
951 XML_ExternalEntityParserCreate(XML_Parser oldParser, |
|
952 const XML_Char *context, |
|
953 const XML_Char *encodingName) |
|
954 { |
|
955 XML_Parser parser = oldParser; |
|
956 DTD *newDtd = NULL; |
|
957 DTD *oldDtd = _dtd; |
|
958 XML_StartElementHandler oldStartElementHandler = startElementHandler; |
|
959 XML_EndElementHandler oldEndElementHandler = endElementHandler; |
|
960 XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; |
|
961 XML_ProcessingInstructionHandler oldProcessingInstructionHandler |
|
962 = processingInstructionHandler; |
|
963 XML_CommentHandler oldCommentHandler = commentHandler; |
|
964 XML_StartCdataSectionHandler oldStartCdataSectionHandler |
|
965 = startCdataSectionHandler; |
|
966 XML_EndCdataSectionHandler oldEndCdataSectionHandler |
|
967 = endCdataSectionHandler; |
|
968 XML_DefaultHandler oldDefaultHandler = defaultHandler; |
|
969 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler |
|
970 = unparsedEntityDeclHandler; |
|
971 XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; |
|
972 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler |
|
973 = startNamespaceDeclHandler; |
|
974 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler |
|
975 = endNamespaceDeclHandler; |
|
976 XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; |
|
977 XML_ExternalEntityRefHandler oldExternalEntityRefHandler |
|
978 = externalEntityRefHandler; |
|
979 XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; |
|
980 XML_UnknownEncodingHandler oldUnknownEncodingHandler |
|
981 = unknownEncodingHandler; |
|
982 XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; |
|
983 XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; |
|
984 XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; |
|
985 XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; |
|
986 ELEMENT_TYPE * oldDeclElementType = declElementType; |
|
987 |
|
988 void *oldUserData = userData; |
|
989 void *oldHandlerArg = handlerArg; |
|
990 XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; |
|
991 XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; |
|
992 #ifdef XML_DTD |
|
993 enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; |
|
994 int oldInEntityValue = prologState.inEntityValue; |
|
995 #endif |
|
996 XML_Bool oldns_triplets = ns_triplets; |
|
997 |
|
998 #ifdef XML_DTD |
|
999 if (!context) |
|
1000 newDtd = oldDtd; |
|
1001 #endif /* XML_DTD */ |
|
1002 |
|
1003 /* Note that the magical uses of the pre-processor to make field |
|
1004 access look more like C++ require that `parser' be overwritten |
|
1005 here. This makes this function more painful to follow than it |
|
1006 would be otherwise. |
|
1007 */ |
|
1008 if (ns) { |
|
1009 XML_Char tmp[2]; |
|
1010 *tmp = namespaceSeparator; |
|
1011 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); |
|
1012 } |
|
1013 else { |
|
1014 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); |
|
1015 } |
|
1016 |
|
1017 if (!parser) |
|
1018 return NULL; |
|
1019 |
|
1020 startElementHandler = oldStartElementHandler; |
|
1021 endElementHandler = oldEndElementHandler; |
|
1022 characterDataHandler = oldCharacterDataHandler; |
|
1023 processingInstructionHandler = oldProcessingInstructionHandler; |
|
1024 commentHandler = oldCommentHandler; |
|
1025 startCdataSectionHandler = oldStartCdataSectionHandler; |
|
1026 endCdataSectionHandler = oldEndCdataSectionHandler; |
|
1027 defaultHandler = oldDefaultHandler; |
|
1028 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; |
|
1029 notationDeclHandler = oldNotationDeclHandler; |
|
1030 startNamespaceDeclHandler = oldStartNamespaceDeclHandler; |
|
1031 endNamespaceDeclHandler = oldEndNamespaceDeclHandler; |
|
1032 notStandaloneHandler = oldNotStandaloneHandler; |
|
1033 externalEntityRefHandler = oldExternalEntityRefHandler; |
|
1034 skippedEntityHandler = oldSkippedEntityHandler; |
|
1035 unknownEncodingHandler = oldUnknownEncodingHandler; |
|
1036 elementDeclHandler = oldElementDeclHandler; |
|
1037 attlistDeclHandler = oldAttlistDeclHandler; |
|
1038 entityDeclHandler = oldEntityDeclHandler; |
|
1039 xmlDeclHandler = oldXmlDeclHandler; |
|
1040 declElementType = oldDeclElementType; |
|
1041 userData = oldUserData; |
|
1042 if (oldUserData == oldHandlerArg) |
|
1043 handlerArg = userData; |
|
1044 else |
|
1045 handlerArg = parser; |
|
1046 if (oldExternalEntityRefHandlerArg != oldParser) |
|
1047 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; |
|
1048 defaultExpandInternalEntities = oldDefaultExpandInternalEntities; |
|
1049 ns_triplets = oldns_triplets; |
|
1050 parentParser = oldParser; |
|
1051 #ifdef XML_DTD |
|
1052 paramEntityParsing = oldParamEntityParsing; |
|
1053 prologState.inEntityValue = oldInEntityValue; |
|
1054 if (context) { |
|
1055 #endif /* XML_DTD */ |
|
1056 if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) |
|
1057 || !setContext(parser, context)) { |
|
1058 XML_ParserFree(parser); |
|
1059 return NULL; |
|
1060 } |
|
1061 processor = externalEntityInitProcessor; |
|
1062 #ifdef XML_DTD |
|
1063 } |
|
1064 else { |
|
1065 /* The DTD instance referenced by _dtd is shared between the document's |
|
1066 root parser and external PE parsers, therefore one does not need to |
|
1067 call setContext. In addition, one also *must* not call setContext, |
|
1068 because this would overwrite existing prefix->binding pointers in |
|
1069 _dtd with ones that get destroyed with the external PE parser. |
|
1070 This would leave those prefixes with dangling pointers. |
|
1071 */ |
|
1072 isParamEntity = XML_TRUE; |
|
1073 XmlPrologStateInitExternalEntity(&prologState); |
|
1074 processor = externalParEntInitProcessor; |
|
1075 } |
|
1076 #endif /* XML_DTD */ |
|
1077 return parser; |
|
1078 } |
|
1079 |
|
1080 static void FASTCALL |
|
1081 destroyBindings(BINDING *bindings, XML_Parser parser) |
|
1082 { |
|
1083 for (;;) { |
|
1084 BINDING *b = bindings; |
|
1085 if (!b) |
|
1086 break; |
|
1087 bindings = b->nextTagBinding; |
|
1088 FREE(b->uri); |
|
1089 FREE(b); |
|
1090 } |
|
1091 } |
|
1092 |
|
1093 void XMLCALL |
|
1094 XML_ParserFree(XML_Parser parser) |
|
1095 { |
|
1096 TAG *tagList; |
|
1097 OPEN_INTERNAL_ENTITY *entityList; |
|
1098 if (parser == NULL) |
|
1099 return; |
|
1100 /* free tagStack and freeTagList */ |
|
1101 tagList = tagStack; |
|
1102 for (;;) { |
|
1103 TAG *p; |
|
1104 if (tagList == NULL) { |
|
1105 if (freeTagList == NULL) |
|
1106 break; |
|
1107 tagList = freeTagList; |
|
1108 freeTagList = NULL; |
|
1109 } |
|
1110 p = tagList; |
|
1111 tagList = tagList->parent; |
|
1112 FREE(p->buf); |
|
1113 destroyBindings(p->bindings, parser); |
|
1114 FREE(p); |
|
1115 } |
|
1116 /* free openInternalEntities and freeInternalEntities */ |
|
1117 entityList = openInternalEntities; |
|
1118 for (;;) { |
|
1119 OPEN_INTERNAL_ENTITY *openEntity; |
|
1120 if (entityList == NULL) { |
|
1121 if (freeInternalEntities == NULL) |
|
1122 break; |
|
1123 entityList = freeInternalEntities; |
|
1124 freeInternalEntities = NULL; |
|
1125 } |
|
1126 openEntity = entityList; |
|
1127 entityList = entityList->next; |
|
1128 FREE(openEntity); |
|
1129 } |
|
1130 |
|
1131 destroyBindings(freeBindingList, parser); |
|
1132 destroyBindings(inheritedBindings, parser); |
|
1133 poolDestroy(&tempPool); |
|
1134 poolDestroy(&temp2Pool); |
|
1135 #ifdef XML_DTD |
|
1136 /* external parameter entity parsers share the DTD structure |
|
1137 parser->m_dtd with the root parser, so we must not destroy it |
|
1138 */ |
|
1139 if (!isParamEntity && _dtd) |
|
1140 #else |
|
1141 if (_dtd) |
|
1142 #endif /* XML_DTD */ |
|
1143 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); |
|
1144 FREE((void *)atts); |
|
1145 FREE(groupConnector); |
|
1146 FREE(buffer); |
|
1147 FREE(dataBuf); |
|
1148 FREE(nsAtts); |
|
1149 FREE(unknownEncodingMem); |
|
1150 if (unknownEncodingRelease) |
|
1151 unknownEncodingRelease(unknownEncodingData); |
|
1152 FREE(parser); |
|
1153 } |
|
1154 |
|
1155 void XMLCALL |
|
1156 XML_UseParserAsHandlerArg(XML_Parser parser) |
|
1157 { |
|
1158 handlerArg = parser; |
|
1159 } |
|
1160 |
|
1161 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1162 #if 0 |
|
1163 enum XML_Error XMLCALL |
|
1164 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) |
|
1165 { |
|
1166 #ifdef XML_DTD |
|
1167 /* block after XML_Parse()/XML_ParseBuffer() has been called */ |
|
1168 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) |
|
1169 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; |
|
1170 useForeignDTD = useDTD; |
|
1171 return XML_ERROR_NONE; |
|
1172 #else |
|
1173 return XML_ERROR_FEATURE_REQUIRES_XML_DTD; |
|
1174 #endif |
|
1175 } |
|
1176 #endif |
|
1177 /* END MOZILLA CHANGE */ |
|
1178 |
|
1179 void XMLCALL |
|
1180 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) |
|
1181 { |
|
1182 /* block after XML_Parse()/XML_ParseBuffer() has been called */ |
|
1183 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) |
|
1184 return; |
|
1185 ns_triplets = do_nst ? XML_TRUE : XML_FALSE; |
|
1186 } |
|
1187 |
|
1188 void XMLCALL |
|
1189 XML_SetUserData(XML_Parser parser, void *p) |
|
1190 { |
|
1191 if (handlerArg == userData) |
|
1192 handlerArg = userData = p; |
|
1193 else |
|
1194 userData = p; |
|
1195 } |
|
1196 |
|
1197 enum XML_Status XMLCALL |
|
1198 XML_SetBase(XML_Parser parser, const XML_Char *p) |
|
1199 { |
|
1200 if (p) { |
|
1201 p = poolCopyString(&_dtd->pool, p); |
|
1202 if (!p) |
|
1203 return XML_STATUS_ERROR; |
|
1204 curBase = p; |
|
1205 } |
|
1206 else |
|
1207 curBase = NULL; |
|
1208 return XML_STATUS_OK; |
|
1209 } |
|
1210 |
|
1211 const XML_Char * XMLCALL |
|
1212 XML_GetBase(XML_Parser parser) |
|
1213 { |
|
1214 return curBase; |
|
1215 } |
|
1216 |
|
1217 int XMLCALL |
|
1218 XML_GetSpecifiedAttributeCount(XML_Parser parser) |
|
1219 { |
|
1220 return nSpecifiedAtts; |
|
1221 } |
|
1222 |
|
1223 int XMLCALL |
|
1224 XML_GetIdAttributeIndex(XML_Parser parser) |
|
1225 { |
|
1226 return idAttIndex; |
|
1227 } |
|
1228 |
|
1229 void XMLCALL |
|
1230 XML_SetElementHandler(XML_Parser parser, |
|
1231 XML_StartElementHandler start, |
|
1232 XML_EndElementHandler end) |
|
1233 { |
|
1234 startElementHandler = start; |
|
1235 endElementHandler = end; |
|
1236 } |
|
1237 |
|
1238 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1239 #if 0 |
|
1240 void XMLCALL |
|
1241 XML_SetStartElementHandler(XML_Parser parser, |
|
1242 XML_StartElementHandler start) { |
|
1243 startElementHandler = start; |
|
1244 } |
|
1245 |
|
1246 void XMLCALL |
|
1247 XML_SetEndElementHandler(XML_Parser parser, |
|
1248 XML_EndElementHandler end) { |
|
1249 endElementHandler = end; |
|
1250 } |
|
1251 #endif |
|
1252 /* END MOZILLA CHANGE */ |
|
1253 |
|
1254 void XMLCALL |
|
1255 XML_SetCharacterDataHandler(XML_Parser parser, |
|
1256 XML_CharacterDataHandler handler) |
|
1257 { |
|
1258 characterDataHandler = handler; |
|
1259 } |
|
1260 |
|
1261 void XMLCALL |
|
1262 XML_SetProcessingInstructionHandler(XML_Parser parser, |
|
1263 XML_ProcessingInstructionHandler handler) |
|
1264 { |
|
1265 processingInstructionHandler = handler; |
|
1266 } |
|
1267 |
|
1268 void XMLCALL |
|
1269 XML_SetCommentHandler(XML_Parser parser, |
|
1270 XML_CommentHandler handler) |
|
1271 { |
|
1272 commentHandler = handler; |
|
1273 } |
|
1274 |
|
1275 void XMLCALL |
|
1276 XML_SetCdataSectionHandler(XML_Parser parser, |
|
1277 XML_StartCdataSectionHandler start, |
|
1278 XML_EndCdataSectionHandler end) |
|
1279 { |
|
1280 startCdataSectionHandler = start; |
|
1281 endCdataSectionHandler = end; |
|
1282 } |
|
1283 |
|
1284 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1285 #if 0 |
|
1286 void XMLCALL |
|
1287 XML_SetStartCdataSectionHandler(XML_Parser parser, |
|
1288 XML_StartCdataSectionHandler start) { |
|
1289 startCdataSectionHandler = start; |
|
1290 } |
|
1291 |
|
1292 void XMLCALL |
|
1293 XML_SetEndCdataSectionHandler(XML_Parser parser, |
|
1294 XML_EndCdataSectionHandler end) { |
|
1295 endCdataSectionHandler = end; |
|
1296 } |
|
1297 |
|
1298 void XMLCALL |
|
1299 XML_SetDefaultHandler(XML_Parser parser, |
|
1300 XML_DefaultHandler handler) |
|
1301 { |
|
1302 defaultHandler = handler; |
|
1303 defaultExpandInternalEntities = XML_FALSE; |
|
1304 } |
|
1305 #endif |
|
1306 /* END MOZILLA CHANGE */ |
|
1307 |
|
1308 void XMLCALL |
|
1309 XML_SetDefaultHandlerExpand(XML_Parser parser, |
|
1310 XML_DefaultHandler handler) |
|
1311 { |
|
1312 defaultHandler = handler; |
|
1313 defaultExpandInternalEntities = XML_TRUE; |
|
1314 } |
|
1315 |
|
1316 void XMLCALL |
|
1317 XML_SetDoctypeDeclHandler(XML_Parser parser, |
|
1318 XML_StartDoctypeDeclHandler start, |
|
1319 XML_EndDoctypeDeclHandler end) |
|
1320 { |
|
1321 startDoctypeDeclHandler = start; |
|
1322 endDoctypeDeclHandler = end; |
|
1323 } |
|
1324 |
|
1325 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1326 #if 0 |
|
1327 void XMLCALL |
|
1328 XML_SetStartDoctypeDeclHandler(XML_Parser parser, |
|
1329 XML_StartDoctypeDeclHandler start) { |
|
1330 startDoctypeDeclHandler = start; |
|
1331 } |
|
1332 |
|
1333 void XMLCALL |
|
1334 XML_SetEndDoctypeDeclHandler(XML_Parser parser, |
|
1335 XML_EndDoctypeDeclHandler end) { |
|
1336 endDoctypeDeclHandler = end; |
|
1337 } |
|
1338 #endif |
|
1339 /* END MOZILLA CHANGE */ |
|
1340 |
|
1341 void XMLCALL |
|
1342 XML_SetUnparsedEntityDeclHandler(XML_Parser parser, |
|
1343 XML_UnparsedEntityDeclHandler handler) |
|
1344 { |
|
1345 unparsedEntityDeclHandler = handler; |
|
1346 } |
|
1347 |
|
1348 void XMLCALL |
|
1349 XML_SetNotationDeclHandler(XML_Parser parser, |
|
1350 XML_NotationDeclHandler handler) |
|
1351 { |
|
1352 notationDeclHandler = handler; |
|
1353 } |
|
1354 |
|
1355 void XMLCALL |
|
1356 XML_SetNamespaceDeclHandler(XML_Parser parser, |
|
1357 XML_StartNamespaceDeclHandler start, |
|
1358 XML_EndNamespaceDeclHandler end) |
|
1359 { |
|
1360 startNamespaceDeclHandler = start; |
|
1361 endNamespaceDeclHandler = end; |
|
1362 } |
|
1363 |
|
1364 |
|
1365 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1366 #if 0 |
|
1367 void XMLCALL |
|
1368 XML_SetStartNamespaceDeclHandler(XML_Parser parser, |
|
1369 XML_StartNamespaceDeclHandler start) { |
|
1370 startNamespaceDeclHandler = start; |
|
1371 } |
|
1372 |
|
1373 void XMLCALL |
|
1374 XML_SetEndNamespaceDeclHandler(XML_Parser parser, |
|
1375 XML_EndNamespaceDeclHandler end) { |
|
1376 endNamespaceDeclHandler = end; |
|
1377 } |
|
1378 |
|
1379 void XMLCALL |
|
1380 XML_SetNotStandaloneHandler(XML_Parser parser, |
|
1381 XML_NotStandaloneHandler handler) |
|
1382 { |
|
1383 notStandaloneHandler = handler; |
|
1384 } |
|
1385 #endif |
|
1386 /* END MOZILLA CHANGE */ |
|
1387 |
|
1388 void XMLCALL |
|
1389 XML_SetExternalEntityRefHandler(XML_Parser parser, |
|
1390 XML_ExternalEntityRefHandler handler) |
|
1391 { |
|
1392 externalEntityRefHandler = handler; |
|
1393 } |
|
1394 |
|
1395 void XMLCALL |
|
1396 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) |
|
1397 { |
|
1398 if (arg) |
|
1399 externalEntityRefHandlerArg = (XML_Parser)arg; |
|
1400 else |
|
1401 externalEntityRefHandlerArg = parser; |
|
1402 } |
|
1403 |
|
1404 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1405 #if 0 |
|
1406 void XMLCALL |
|
1407 XML_SetSkippedEntityHandler(XML_Parser parser, |
|
1408 XML_SkippedEntityHandler handler) |
|
1409 { |
|
1410 skippedEntityHandler = handler; |
|
1411 } |
|
1412 |
|
1413 void XMLCALL |
|
1414 XML_SetUnknownEncodingHandler(XML_Parser parser, |
|
1415 XML_UnknownEncodingHandler handler, |
|
1416 void *data) |
|
1417 { |
|
1418 unknownEncodingHandler = handler; |
|
1419 unknownEncodingHandlerData = data; |
|
1420 } |
|
1421 |
|
1422 void XMLCALL |
|
1423 XML_SetElementDeclHandler(XML_Parser parser, |
|
1424 XML_ElementDeclHandler eldecl) |
|
1425 { |
|
1426 elementDeclHandler = eldecl; |
|
1427 } |
|
1428 |
|
1429 void XMLCALL |
|
1430 XML_SetAttlistDeclHandler(XML_Parser parser, |
|
1431 XML_AttlistDeclHandler attdecl) |
|
1432 { |
|
1433 attlistDeclHandler = attdecl; |
|
1434 } |
|
1435 |
|
1436 void XMLCALL |
|
1437 XML_SetEntityDeclHandler(XML_Parser parser, |
|
1438 XML_EntityDeclHandler handler) |
|
1439 { |
|
1440 entityDeclHandler = handler; |
|
1441 } |
|
1442 #endif |
|
1443 /* END MOZILLA CHANGE */ |
|
1444 |
|
1445 void XMLCALL |
|
1446 XML_SetXmlDeclHandler(XML_Parser parser, |
|
1447 XML_XmlDeclHandler handler) { |
|
1448 xmlDeclHandler = handler; |
|
1449 } |
|
1450 |
|
1451 int XMLCALL |
|
1452 XML_SetParamEntityParsing(XML_Parser parser, |
|
1453 enum XML_ParamEntityParsing peParsing) |
|
1454 { |
|
1455 /* block after XML_Parse()/XML_ParseBuffer() has been called */ |
|
1456 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) |
|
1457 return 0; |
|
1458 #ifdef XML_DTD |
|
1459 paramEntityParsing = peParsing; |
|
1460 return 1; |
|
1461 #else |
|
1462 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; |
|
1463 #endif |
|
1464 } |
|
1465 |
|
1466 enum XML_Status XMLCALL |
|
1467 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) |
|
1468 { |
|
1469 switch (ps_parsing) { |
|
1470 case XML_SUSPENDED: |
|
1471 errorCode = XML_ERROR_SUSPENDED; |
|
1472 return XML_STATUS_ERROR; |
|
1473 case XML_FINISHED: |
|
1474 errorCode = XML_ERROR_FINISHED; |
|
1475 return XML_STATUS_ERROR; |
|
1476 default: |
|
1477 ps_parsing = XML_PARSING; |
|
1478 } |
|
1479 |
|
1480 if (len == 0) { |
|
1481 ps_finalBuffer = (XML_Bool)isFinal; |
|
1482 if (!isFinal) |
|
1483 return XML_STATUS_OK; |
|
1484 positionPtr = bufferPtr; |
|
1485 parseEndPtr = bufferEnd; |
|
1486 |
|
1487 /* If data are left over from last buffer, and we now know that these |
|
1488 data are the final chunk of input, then we have to check them again |
|
1489 to detect errors based on that fact. |
|
1490 */ |
|
1491 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); |
|
1492 |
|
1493 if (errorCode == XML_ERROR_NONE) { |
|
1494 switch (ps_parsing) { |
|
1495 case XML_SUSPENDED: |
|
1496 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); |
|
1497 positionPtr = bufferPtr; |
|
1498 return XML_STATUS_SUSPENDED; |
|
1499 case XML_INITIALIZED: |
|
1500 case XML_PARSING: |
|
1501 ps_parsing = XML_FINISHED; |
|
1502 /* fall through */ |
|
1503 default: |
|
1504 return XML_STATUS_OK; |
|
1505 } |
|
1506 } |
|
1507 eventEndPtr = eventPtr; |
|
1508 processor = errorProcessor; |
|
1509 return XML_STATUS_ERROR; |
|
1510 } |
|
1511 #ifndef XML_CONTEXT_BYTES |
|
1512 else if (bufferPtr == bufferEnd) { |
|
1513 const char *end; |
|
1514 int nLeftOver; |
|
1515 /* BEGIN MOZILLA CHANGE (|result| has type XML_Status, not XML_Error) */ |
|
1516 enum XML_Status result; |
|
1517 /* END MOZILLA CHANGE */ |
|
1518 parseEndByteIndex += len; |
|
1519 positionPtr = s; |
|
1520 ps_finalBuffer = (XML_Bool)isFinal; |
|
1521 |
|
1522 errorCode = processor(parser, s, parseEndPtr = s + len, &end); |
|
1523 |
|
1524 if (errorCode != XML_ERROR_NONE) { |
|
1525 eventEndPtr = eventPtr; |
|
1526 processor = errorProcessor; |
|
1527 return XML_STATUS_ERROR; |
|
1528 } |
|
1529 else { |
|
1530 switch (ps_parsing) { |
|
1531 case XML_SUSPENDED: |
|
1532 result = XML_STATUS_SUSPENDED; |
|
1533 break; |
|
1534 case XML_INITIALIZED: |
|
1535 case XML_PARSING: |
|
1536 /* BEGIN MOZILLA CHANGE (always initialize result) */ |
|
1537 #if 0 |
|
1538 result = XML_STATUS_OK; |
|
1539 if (isFinal) { |
|
1540 ps_parsing = XML_FINISHED; |
|
1541 return result; |
|
1542 } |
|
1543 #else |
|
1544 if (isFinal) { |
|
1545 ps_parsing = XML_FINISHED; |
|
1546 return XML_STATUS_OK; |
|
1547 } |
|
1548 /* fall through */ |
|
1549 default: |
|
1550 result = XML_STATUS_OK; |
|
1551 #endif |
|
1552 /* END MOZILLA CHANGE */ |
|
1553 } |
|
1554 } |
|
1555 |
|
1556 XmlUpdatePosition(encoding, positionPtr, end, &position); |
|
1557 nLeftOver = s + len - end; |
|
1558 if (nLeftOver) { |
|
1559 if (buffer == NULL || nLeftOver > bufferLim - buffer) { |
|
1560 /* FIXME avoid integer overflow */ |
|
1561 char *temp; |
|
1562 temp = (buffer == NULL |
|
1563 ? (char *)MALLOC(len * 2) |
|
1564 : (char *)REALLOC(buffer, len * 2)); |
|
1565 if (temp == NULL) { |
|
1566 errorCode = XML_ERROR_NO_MEMORY; |
|
1567 return XML_STATUS_ERROR; |
|
1568 } |
|
1569 buffer = temp; |
|
1570 if (!buffer) { |
|
1571 errorCode = XML_ERROR_NO_MEMORY; |
|
1572 eventPtr = eventEndPtr = NULL; |
|
1573 processor = errorProcessor; |
|
1574 return XML_STATUS_ERROR; |
|
1575 } |
|
1576 bufferLim = buffer + len * 2; |
|
1577 } |
|
1578 memcpy(buffer, end, nLeftOver); |
|
1579 } |
|
1580 bufferPtr = buffer; |
|
1581 bufferEnd = buffer + nLeftOver; |
|
1582 positionPtr = bufferPtr; |
|
1583 parseEndPtr = bufferEnd; |
|
1584 eventPtr = bufferPtr; |
|
1585 eventEndPtr = bufferPtr; |
|
1586 return result; |
|
1587 } |
|
1588 #endif /* not defined XML_CONTEXT_BYTES */ |
|
1589 else { |
|
1590 void *buff = XML_GetBuffer(parser, len); |
|
1591 if (buff == NULL) |
|
1592 return XML_STATUS_ERROR; |
|
1593 else { |
|
1594 memcpy(buff, s, len); |
|
1595 return XML_ParseBuffer(parser, len, isFinal); |
|
1596 } |
|
1597 } |
|
1598 } |
|
1599 |
|
1600 enum XML_Status XMLCALL |
|
1601 XML_ParseBuffer(XML_Parser parser, int len, int isFinal) |
|
1602 { |
|
1603 const char *start; |
|
1604 enum XML_Status result = XML_STATUS_OK; |
|
1605 |
|
1606 switch (ps_parsing) { |
|
1607 case XML_SUSPENDED: |
|
1608 errorCode = XML_ERROR_SUSPENDED; |
|
1609 return XML_STATUS_ERROR; |
|
1610 case XML_FINISHED: |
|
1611 errorCode = XML_ERROR_FINISHED; |
|
1612 return XML_STATUS_ERROR; |
|
1613 default: |
|
1614 ps_parsing = XML_PARSING; |
|
1615 } |
|
1616 |
|
1617 start = bufferPtr; |
|
1618 positionPtr = start; |
|
1619 bufferEnd += len; |
|
1620 parseEndPtr = bufferEnd; |
|
1621 parseEndByteIndex += len; |
|
1622 ps_finalBuffer = (XML_Bool)isFinal; |
|
1623 |
|
1624 errorCode = processor(parser, start, parseEndPtr, &bufferPtr); |
|
1625 |
|
1626 if (errorCode != XML_ERROR_NONE) { |
|
1627 eventEndPtr = eventPtr; |
|
1628 processor = errorProcessor; |
|
1629 return XML_STATUS_ERROR; |
|
1630 } |
|
1631 else { |
|
1632 switch (ps_parsing) { |
|
1633 case XML_SUSPENDED: |
|
1634 result = XML_STATUS_SUSPENDED; |
|
1635 break; |
|
1636 case XML_INITIALIZED: |
|
1637 case XML_PARSING: |
|
1638 if (isFinal) { |
|
1639 ps_parsing = XML_FINISHED; |
|
1640 return result; |
|
1641 } |
|
1642 default: ; /* should not happen */ |
|
1643 } |
|
1644 } |
|
1645 |
|
1646 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); |
|
1647 positionPtr = bufferPtr; |
|
1648 return result; |
|
1649 } |
|
1650 |
|
1651 void * XMLCALL |
|
1652 XML_GetBuffer(XML_Parser parser, int len) |
|
1653 { |
|
1654 switch (ps_parsing) { |
|
1655 case XML_SUSPENDED: |
|
1656 errorCode = XML_ERROR_SUSPENDED; |
|
1657 return NULL; |
|
1658 case XML_FINISHED: |
|
1659 errorCode = XML_ERROR_FINISHED; |
|
1660 return NULL; |
|
1661 default: ; |
|
1662 } |
|
1663 |
|
1664 if (len > bufferLim - bufferEnd) { |
|
1665 /* FIXME avoid integer overflow */ |
|
1666 int neededSize = len + (int)(bufferEnd - bufferPtr); |
|
1667 #ifdef XML_CONTEXT_BYTES |
|
1668 int keep = (int)(bufferPtr - buffer); |
|
1669 |
|
1670 if (keep > XML_CONTEXT_BYTES) |
|
1671 keep = XML_CONTEXT_BYTES; |
|
1672 neededSize += keep; |
|
1673 #endif /* defined XML_CONTEXT_BYTES */ |
|
1674 if (neededSize <= bufferLim - buffer) { |
|
1675 #ifdef XML_CONTEXT_BYTES |
|
1676 if (keep < bufferPtr - buffer) { |
|
1677 int offset = (int)(bufferPtr - buffer) - keep; |
|
1678 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); |
|
1679 bufferEnd -= offset; |
|
1680 bufferPtr -= offset; |
|
1681 } |
|
1682 #else |
|
1683 memmove(buffer, bufferPtr, bufferEnd - bufferPtr); |
|
1684 bufferEnd = buffer + (bufferEnd - bufferPtr); |
|
1685 bufferPtr = buffer; |
|
1686 #endif /* not defined XML_CONTEXT_BYTES */ |
|
1687 } |
|
1688 else { |
|
1689 char *newBuf; |
|
1690 int bufferSize = (int)(bufferLim - bufferPtr); |
|
1691 if (bufferSize == 0) |
|
1692 bufferSize = INIT_BUFFER_SIZE; |
|
1693 do { |
|
1694 bufferSize *= 2; |
|
1695 } while (bufferSize < neededSize); |
|
1696 newBuf = (char *)MALLOC(bufferSize); |
|
1697 if (newBuf == 0) { |
|
1698 errorCode = XML_ERROR_NO_MEMORY; |
|
1699 return NULL; |
|
1700 } |
|
1701 bufferLim = newBuf + bufferSize; |
|
1702 #ifdef XML_CONTEXT_BYTES |
|
1703 if (bufferPtr) { |
|
1704 int keep = (int)(bufferPtr - buffer); |
|
1705 if (keep > XML_CONTEXT_BYTES) |
|
1706 keep = XML_CONTEXT_BYTES; |
|
1707 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); |
|
1708 FREE(buffer); |
|
1709 buffer = newBuf; |
|
1710 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; |
|
1711 bufferPtr = buffer + keep; |
|
1712 } |
|
1713 else { |
|
1714 bufferEnd = newBuf + (bufferEnd - bufferPtr); |
|
1715 bufferPtr = buffer = newBuf; |
|
1716 } |
|
1717 #else |
|
1718 if (bufferPtr) { |
|
1719 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); |
|
1720 FREE(buffer); |
|
1721 } |
|
1722 bufferEnd = newBuf + (bufferEnd - bufferPtr); |
|
1723 bufferPtr = buffer = newBuf; |
|
1724 #endif /* not defined XML_CONTEXT_BYTES */ |
|
1725 } |
|
1726 } |
|
1727 return bufferEnd; |
|
1728 } |
|
1729 |
|
1730 enum XML_Status XMLCALL |
|
1731 XML_StopParser(XML_Parser parser, XML_Bool resumable) |
|
1732 { |
|
1733 switch (ps_parsing) { |
|
1734 case XML_SUSPENDED: |
|
1735 if (resumable) { |
|
1736 errorCode = XML_ERROR_SUSPENDED; |
|
1737 return XML_STATUS_ERROR; |
|
1738 } |
|
1739 ps_parsing = XML_FINISHED; |
|
1740 break; |
|
1741 case XML_FINISHED: |
|
1742 errorCode = XML_ERROR_FINISHED; |
|
1743 return XML_STATUS_ERROR; |
|
1744 default: |
|
1745 if (resumable) { |
|
1746 #ifdef XML_DTD |
|
1747 if (isParamEntity) { |
|
1748 errorCode = XML_ERROR_SUSPEND_PE; |
|
1749 return XML_STATUS_ERROR; |
|
1750 } |
|
1751 #endif |
|
1752 ps_parsing = XML_SUSPENDED; |
|
1753 } |
|
1754 else |
|
1755 ps_parsing = XML_FINISHED; |
|
1756 } |
|
1757 return XML_STATUS_OK; |
|
1758 } |
|
1759 |
|
1760 enum XML_Status XMLCALL |
|
1761 XML_ResumeParser(XML_Parser parser) |
|
1762 { |
|
1763 enum XML_Status result = XML_STATUS_OK; |
|
1764 |
|
1765 if (ps_parsing != XML_SUSPENDED) { |
|
1766 errorCode = XML_ERROR_NOT_SUSPENDED; |
|
1767 return XML_STATUS_ERROR; |
|
1768 } |
|
1769 ps_parsing = XML_PARSING; |
|
1770 |
|
1771 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); |
|
1772 |
|
1773 if (errorCode != XML_ERROR_NONE) { |
|
1774 eventEndPtr = eventPtr; |
|
1775 processor = errorProcessor; |
|
1776 return XML_STATUS_ERROR; |
|
1777 } |
|
1778 else { |
|
1779 switch (ps_parsing) { |
|
1780 case XML_SUSPENDED: |
|
1781 result = XML_STATUS_SUSPENDED; |
|
1782 break; |
|
1783 case XML_INITIALIZED: |
|
1784 case XML_PARSING: |
|
1785 if (ps_finalBuffer) { |
|
1786 ps_parsing = XML_FINISHED; |
|
1787 return result; |
|
1788 } |
|
1789 default: ; |
|
1790 } |
|
1791 } |
|
1792 |
|
1793 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); |
|
1794 positionPtr = bufferPtr; |
|
1795 /* BEGIN MOZILLA CHANGE (always set eventPtr/eventEndPtr) */ |
|
1796 eventPtr = bufferPtr; |
|
1797 eventEndPtr = bufferPtr; |
|
1798 /* END MOZILLA CHANGE */ |
|
1799 return result; |
|
1800 } |
|
1801 |
|
1802 void XMLCALL |
|
1803 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) |
|
1804 { |
|
1805 assert(status != NULL); |
|
1806 *status = parser->m_parsingStatus; |
|
1807 } |
|
1808 |
|
1809 enum XML_Error XMLCALL |
|
1810 XML_GetErrorCode(XML_Parser parser) |
|
1811 { |
|
1812 return errorCode; |
|
1813 } |
|
1814 |
|
1815 XML_Index XMLCALL |
|
1816 XML_GetCurrentByteIndex(XML_Parser parser) |
|
1817 { |
|
1818 if (eventPtr) |
|
1819 return parseEndByteIndex - (parseEndPtr - eventPtr); |
|
1820 /* BEGIN MOZILLA CHANGE (fix XML_GetCurrentByteIndex) */ |
|
1821 #if 0 |
|
1822 return -1; |
|
1823 #else |
|
1824 return parseEndByteIndex; |
|
1825 #endif |
|
1826 /* END MOZILLA CHANGE */ |
|
1827 } |
|
1828 |
|
1829 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1830 #if 0 |
|
1831 int XMLCALL |
|
1832 XML_GetCurrentByteCount(XML_Parser parser) |
|
1833 { |
|
1834 if (eventEndPtr && eventPtr) |
|
1835 return (int)(eventEndPtr - eventPtr); |
|
1836 return 0; |
|
1837 } |
|
1838 |
|
1839 const char * XMLCALL |
|
1840 XML_GetInputContext(XML_Parser parser, int *offset, int *size) |
|
1841 { |
|
1842 #ifdef XML_CONTEXT_BYTES |
|
1843 if (eventPtr && buffer) { |
|
1844 *offset = (int)(eventPtr - buffer); |
|
1845 *size = (int)(bufferEnd - buffer); |
|
1846 return buffer; |
|
1847 } |
|
1848 #endif /* defined XML_CONTEXT_BYTES */ |
|
1849 return (char *) 0; |
|
1850 } |
|
1851 #endif |
|
1852 /* END MOZILLA CHANGE */ |
|
1853 |
|
1854 XML_Size XMLCALL |
|
1855 XML_GetCurrentLineNumber(XML_Parser parser) |
|
1856 { |
|
1857 if (eventPtr && eventPtr >= positionPtr) { |
|
1858 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); |
|
1859 positionPtr = eventPtr; |
|
1860 } |
|
1861 return position.lineNumber + 1; |
|
1862 } |
|
1863 |
|
1864 XML_Size XMLCALL |
|
1865 XML_GetCurrentColumnNumber(XML_Parser parser) |
|
1866 { |
|
1867 if (eventPtr && eventPtr >= positionPtr) { |
|
1868 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); |
|
1869 positionPtr = eventPtr; |
|
1870 } |
|
1871 return position.columnNumber; |
|
1872 } |
|
1873 |
|
1874 /* BEGIN MOZILLA CHANGE (unused API) */ |
|
1875 #if 0 |
|
1876 void XMLCALL |
|
1877 XML_FreeContentModel(XML_Parser parser, XML_Content *model) |
|
1878 { |
|
1879 FREE(model); |
|
1880 } |
|
1881 |
|
1882 void * XMLCALL |
|
1883 XML_MemMalloc(XML_Parser parser, size_t size) |
|
1884 { |
|
1885 return MALLOC(size); |
|
1886 } |
|
1887 |
|
1888 void * XMLCALL |
|
1889 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) |
|
1890 { |
|
1891 return REALLOC(ptr, size); |
|
1892 } |
|
1893 |
|
1894 void XMLCALL |
|
1895 XML_MemFree(XML_Parser parser, void *ptr) |
|
1896 { |
|
1897 FREE(ptr); |
|
1898 } |
|
1899 |
|
1900 void XMLCALL |
|
1901 XML_DefaultCurrent(XML_Parser parser) |
|
1902 { |
|
1903 if (defaultHandler) { |
|
1904 if (openInternalEntities) |
|
1905 reportDefault(parser, |
|
1906 internalEncoding, |
|
1907 openInternalEntities->internalEventPtr, |
|
1908 openInternalEntities->internalEventEndPtr); |
|
1909 else |
|
1910 reportDefault(parser, encoding, eventPtr, eventEndPtr); |
|
1911 } |
|
1912 } |
|
1913 |
|
1914 const XML_LChar * XMLCALL |
|
1915 XML_ExpatVersion(void) { |
|
1916 |
|
1917 /* V1 is used to string-ize the version number. However, it would |
|
1918 string-ize the actual version macro *names* unless we get them |
|
1919 substituted before being passed to V1. CPP is defined to expand |
|
1920 a macro, then rescan for more expansions. Thus, we use V2 to expand |
|
1921 the version macros, then CPP will expand the resulting V1() macro |
|
1922 with the correct numerals. */ |
|
1923 /* ### I'm assuming cpp is portable in this respect... */ |
|
1924 |
|
1925 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c) |
|
1926 #define V2(a,b,c) XML_L("expat_")V1(a,b,c) |
|
1927 |
|
1928 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); |
|
1929 |
|
1930 #undef V1 |
|
1931 #undef V2 |
|
1932 } |
|
1933 |
|
1934 XML_Expat_Version XMLCALL |
|
1935 XML_ExpatVersionInfo(void) |
|
1936 { |
|
1937 XML_Expat_Version version; |
|
1938 |
|
1939 version.major = XML_MAJOR_VERSION; |
|
1940 version.minor = XML_MINOR_VERSION; |
|
1941 version.micro = XML_MICRO_VERSION; |
|
1942 |
|
1943 return version; |
|
1944 } |
|
1945 |
|
1946 const XML_Feature * XMLCALL |
|
1947 XML_GetFeatureList(void) |
|
1948 { |
|
1949 static const XML_Feature features[] = { |
|
1950 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), |
|
1951 sizeof(XML_Char)}, |
|
1952 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), |
|
1953 sizeof(XML_LChar)}, |
|
1954 #ifdef XML_UNICODE |
|
1955 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, |
|
1956 #endif |
|
1957 #ifdef XML_UNICODE_WCHAR_T |
|
1958 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, |
|
1959 #endif |
|
1960 #ifdef XML_DTD |
|
1961 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, |
|
1962 #endif |
|
1963 #ifdef XML_CONTEXT_BYTES |
|
1964 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), |
|
1965 XML_CONTEXT_BYTES}, |
|
1966 #endif |
|
1967 #ifdef XML_MIN_SIZE |
|
1968 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, |
|
1969 #endif |
|
1970 #ifdef XML_NS |
|
1971 {XML_FEATURE_NS, XML_L("XML_NS"), 0}, |
|
1972 #endif |
|
1973 {XML_FEATURE_END, NULL, 0} |
|
1974 }; |
|
1975 |
|
1976 return features; |
|
1977 } |
|
1978 #endif |
|
1979 /* END MOZILLA CHANGE */ |
|
1980 |
|
1981 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */ |
|
1982 const XML_Char * XMLCALL |
|
1983 MOZ_XML_GetMismatchedTag(XML_Parser parser) |
|
1984 { |
|
1985 return mismatch; |
|
1986 } |
|
1987 /* END MOZILLA CHANGE */ |
|
1988 |
|
1989 /* Initially tag->rawName always points into the parse buffer; |
|
1990 for those TAG instances opened while the current parse buffer was |
|
1991 processed, and not yet closed, we need to store tag->rawName in a more |
|
1992 permanent location, since the parse buffer is about to be discarded. |
|
1993 */ |
|
1994 static XML_Bool |
|
1995 storeRawNames(XML_Parser parser) |
|
1996 { |
|
1997 TAG *tag = tagStack; |
|
1998 while (tag) { |
|
1999 int bufSize; |
|
2000 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); |
|
2001 char *rawNameBuf = tag->buf + nameLen; |
|
2002 /* Stop if already stored. Since tagStack is a stack, we can stop |
|
2003 at the first entry that has already been copied; everything |
|
2004 below it in the stack is already been accounted for in a |
|
2005 previous call to this function. |
|
2006 */ |
|
2007 if (tag->rawName == rawNameBuf) |
|
2008 break; |
|
2009 /* For re-use purposes we need to ensure that the |
|
2010 size of tag->buf is a multiple of sizeof(XML_Char). |
|
2011 */ |
|
2012 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); |
|
2013 if (bufSize > tag->bufEnd - tag->buf) { |
|
2014 char *temp = (char *)REALLOC(tag->buf, bufSize); |
|
2015 if (temp == NULL) |
|
2016 return XML_FALSE; |
|
2017 /* if tag->name.str points to tag->buf (only when namespace |
|
2018 processing is off) then we have to update it |
|
2019 */ |
|
2020 if (tag->name.str == (XML_Char *)tag->buf) |
|
2021 tag->name.str = (XML_Char *)temp; |
|
2022 /* if tag->name.localPart is set (when namespace processing is on) |
|
2023 then update it as well, since it will always point into tag->buf |
|
2024 */ |
|
2025 if (tag->name.localPart) |
|
2026 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - |
|
2027 (XML_Char *)tag->buf); |
|
2028 tag->buf = temp; |
|
2029 tag->bufEnd = temp + bufSize; |
|
2030 rawNameBuf = temp + nameLen; |
|
2031 } |
|
2032 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); |
|
2033 tag->rawName = rawNameBuf; |
|
2034 tag = tag->parent; |
|
2035 } |
|
2036 return XML_TRUE; |
|
2037 } |
|
2038 |
|
2039 static enum XML_Error PTRCALL |
|
2040 contentProcessor(XML_Parser parser, |
|
2041 const char *start, |
|
2042 const char *end, |
|
2043 const char **endPtr) |
|
2044 { |
|
2045 enum XML_Error result = doContent(parser, 0, encoding, start, end, |
|
2046 endPtr, (XML_Bool)!ps_finalBuffer); |
|
2047 if (result == XML_ERROR_NONE) { |
|
2048 if (!storeRawNames(parser)) |
|
2049 return XML_ERROR_NO_MEMORY; |
|
2050 } |
|
2051 return result; |
|
2052 } |
|
2053 |
|
2054 static enum XML_Error PTRCALL |
|
2055 externalEntityInitProcessor(XML_Parser parser, |
|
2056 const char *start, |
|
2057 const char *end, |
|
2058 const char **endPtr) |
|
2059 { |
|
2060 enum XML_Error result = initializeEncoding(parser); |
|
2061 if (result != XML_ERROR_NONE) |
|
2062 return result; |
|
2063 processor = externalEntityInitProcessor2; |
|
2064 return externalEntityInitProcessor2(parser, start, end, endPtr); |
|
2065 } |
|
2066 |
|
2067 static enum XML_Error PTRCALL |
|
2068 externalEntityInitProcessor2(XML_Parser parser, |
|
2069 const char *start, |
|
2070 const char *end, |
|
2071 const char **endPtr) |
|
2072 { |
|
2073 const char *next = start; /* XmlContentTok doesn't always set the last arg */ |
|
2074 int tok = XmlContentTok(encoding, start, end, &next); |
|
2075 switch (tok) { |
|
2076 case XML_TOK_BOM: |
|
2077 /* If we are at the end of the buffer, this would cause the next stage, |
|
2078 i.e. externalEntityInitProcessor3, to pass control directly to |
|
2079 doContent (by detecting XML_TOK_NONE) without processing any xml text |
|
2080 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. |
|
2081 */ |
|
2082 if (next == end && !ps_finalBuffer) { |
|
2083 *endPtr = next; |
|
2084 return XML_ERROR_NONE; |
|
2085 } |
|
2086 start = next; |
|
2087 break; |
|
2088 case XML_TOK_PARTIAL: |
|
2089 if (!ps_finalBuffer) { |
|
2090 *endPtr = start; |
|
2091 return XML_ERROR_NONE; |
|
2092 } |
|
2093 eventPtr = start; |
|
2094 return XML_ERROR_UNCLOSED_TOKEN; |
|
2095 case XML_TOK_PARTIAL_CHAR: |
|
2096 if (!ps_finalBuffer) { |
|
2097 *endPtr = start; |
|
2098 return XML_ERROR_NONE; |
|
2099 } |
|
2100 eventPtr = start; |
|
2101 return XML_ERROR_PARTIAL_CHAR; |
|
2102 } |
|
2103 processor = externalEntityInitProcessor3; |
|
2104 return externalEntityInitProcessor3(parser, start, end, endPtr); |
|
2105 } |
|
2106 |
|
2107 static enum XML_Error PTRCALL |
|
2108 externalEntityInitProcessor3(XML_Parser parser, |
|
2109 const char *start, |
|
2110 const char *end, |
|
2111 const char **endPtr) |
|
2112 { |
|
2113 int tok; |
|
2114 const char *next = start; /* XmlContentTok doesn't always set the last arg */ |
|
2115 eventPtr = start; |
|
2116 tok = XmlContentTok(encoding, start, end, &next); |
|
2117 eventEndPtr = next; |
|
2118 |
|
2119 switch (tok) { |
|
2120 case XML_TOK_XML_DECL: |
|
2121 { |
|
2122 enum XML_Error result; |
|
2123 result = processXmlDecl(parser, 1, start, next); |
|
2124 if (result != XML_ERROR_NONE) |
|
2125 return result; |
|
2126 switch (ps_parsing) { |
|
2127 case XML_SUSPENDED: |
|
2128 *endPtr = next; |
|
2129 return XML_ERROR_NONE; |
|
2130 case XML_FINISHED: |
|
2131 return XML_ERROR_ABORTED; |
|
2132 default: |
|
2133 start = next; |
|
2134 } |
|
2135 } |
|
2136 break; |
|
2137 case XML_TOK_PARTIAL: |
|
2138 if (!ps_finalBuffer) { |
|
2139 *endPtr = start; |
|
2140 return XML_ERROR_NONE; |
|
2141 } |
|
2142 return XML_ERROR_UNCLOSED_TOKEN; |
|
2143 case XML_TOK_PARTIAL_CHAR: |
|
2144 if (!ps_finalBuffer) { |
|
2145 *endPtr = start; |
|
2146 return XML_ERROR_NONE; |
|
2147 } |
|
2148 return XML_ERROR_PARTIAL_CHAR; |
|
2149 } |
|
2150 processor = externalEntityContentProcessor; |
|
2151 tagLevel = 1; |
|
2152 return externalEntityContentProcessor(parser, start, end, endPtr); |
|
2153 } |
|
2154 |
|
2155 static enum XML_Error PTRCALL |
|
2156 externalEntityContentProcessor(XML_Parser parser, |
|
2157 const char *start, |
|
2158 const char *end, |
|
2159 const char **endPtr) |
|
2160 { |
|
2161 enum XML_Error result = doContent(parser, 1, encoding, start, end, |
|
2162 endPtr, (XML_Bool)!ps_finalBuffer); |
|
2163 if (result == XML_ERROR_NONE) { |
|
2164 if (!storeRawNames(parser)) |
|
2165 return XML_ERROR_NO_MEMORY; |
|
2166 } |
|
2167 return result; |
|
2168 } |
|
2169 |
|
2170 static enum XML_Error |
|
2171 doContent(XML_Parser parser, |
|
2172 int startTagLevel, |
|
2173 const ENCODING *enc, |
|
2174 const char *s, |
|
2175 const char *end, |
|
2176 const char **nextPtr, |
|
2177 XML_Bool haveMore) |
|
2178 { |
|
2179 /* save one level of indirection */ |
|
2180 DTD * const dtd = _dtd; |
|
2181 |
|
2182 const char **eventPP; |
|
2183 const char **eventEndPP; |
|
2184 if (enc == encoding) { |
|
2185 eventPP = &eventPtr; |
|
2186 eventEndPP = &eventEndPtr; |
|
2187 } |
|
2188 else { |
|
2189 eventPP = &(openInternalEntities->internalEventPtr); |
|
2190 eventEndPP = &(openInternalEntities->internalEventEndPtr); |
|
2191 } |
|
2192 *eventPP = s; |
|
2193 |
|
2194 for (;;) { |
|
2195 const char *next = s; /* XmlContentTok doesn't always set the last arg */ |
|
2196 int tok = XmlContentTok(enc, s, end, &next); |
|
2197 *eventEndPP = next; |
|
2198 switch (tok) { |
|
2199 case XML_TOK_TRAILING_CR: |
|
2200 if (haveMore) { |
|
2201 *nextPtr = s; |
|
2202 return XML_ERROR_NONE; |
|
2203 } |
|
2204 *eventEndPP = end; |
|
2205 if (characterDataHandler) { |
|
2206 XML_Char c = 0xA; |
|
2207 characterDataHandler(handlerArg, &c, 1); |
|
2208 } |
|
2209 else if (defaultHandler) |
|
2210 reportDefault(parser, enc, s, end); |
|
2211 /* We are at the end of the final buffer, should we check for |
|
2212 XML_SUSPENDED, XML_FINISHED? |
|
2213 */ |
|
2214 if (startTagLevel == 0) |
|
2215 return XML_ERROR_NO_ELEMENTS; |
|
2216 if (tagLevel != startTagLevel) |
|
2217 return XML_ERROR_ASYNC_ENTITY; |
|
2218 *nextPtr = end; |
|
2219 return XML_ERROR_NONE; |
|
2220 case XML_TOK_NONE: |
|
2221 if (haveMore) { |
|
2222 *nextPtr = s; |
|
2223 return XML_ERROR_NONE; |
|
2224 } |
|
2225 if (startTagLevel > 0) { |
|
2226 if (tagLevel != startTagLevel) |
|
2227 return XML_ERROR_ASYNC_ENTITY; |
|
2228 *nextPtr = s; |
|
2229 return XML_ERROR_NONE; |
|
2230 } |
|
2231 return XML_ERROR_NO_ELEMENTS; |
|
2232 case XML_TOK_INVALID: |
|
2233 *eventPP = next; |
|
2234 return XML_ERROR_INVALID_TOKEN; |
|
2235 case XML_TOK_PARTIAL: |
|
2236 if (haveMore) { |
|
2237 *nextPtr = s; |
|
2238 return XML_ERROR_NONE; |
|
2239 } |
|
2240 return XML_ERROR_UNCLOSED_TOKEN; |
|
2241 case XML_TOK_PARTIAL_CHAR: |
|
2242 if (haveMore) { |
|
2243 *nextPtr = s; |
|
2244 return XML_ERROR_NONE; |
|
2245 } |
|
2246 return XML_ERROR_PARTIAL_CHAR; |
|
2247 case XML_TOK_ENTITY_REF: |
|
2248 { |
|
2249 const XML_Char *name; |
|
2250 ENTITY *entity; |
|
2251 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, |
|
2252 s + enc->minBytesPerChar, |
|
2253 next - enc->minBytesPerChar); |
|
2254 if (ch) { |
|
2255 if (characterDataHandler) |
|
2256 characterDataHandler(handlerArg, &ch, 1); |
|
2257 else if (defaultHandler) |
|
2258 reportDefault(parser, enc, s, next); |
|
2259 break; |
|
2260 } |
|
2261 name = poolStoreString(&dtd->pool, enc, |
|
2262 s + enc->minBytesPerChar, |
|
2263 next - enc->minBytesPerChar); |
|
2264 if (!name) |
|
2265 return XML_ERROR_NO_MEMORY; |
|
2266 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); |
|
2267 poolDiscard(&dtd->pool); |
|
2268 /* First, determine if a check for an existing declaration is needed; |
|
2269 if yes, check that the entity exists, and that it is internal, |
|
2270 otherwise call the skipped entity or default handler. |
|
2271 */ |
|
2272 if (!dtd->hasParamEntityRefs || dtd->standalone) { |
|
2273 if (!entity) |
|
2274 return XML_ERROR_UNDEFINED_ENTITY; |
|
2275 else if (!entity->is_internal) |
|
2276 return XML_ERROR_ENTITY_DECLARED_IN_PE; |
|
2277 } |
|
2278 else if (!entity) { |
|
2279 if (skippedEntityHandler) |
|
2280 skippedEntityHandler(handlerArg, name, 0); |
|
2281 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */ |
|
2282 #if 0 |
|
2283 else if (defaultHandler) |
|
2284 reportDefault(parser, enc, s, next); |
|
2285 break; |
|
2286 #else |
|
2287 return XML_ERROR_UNDEFINED_ENTITY; |
|
2288 #endif |
|
2289 /* END MOZILLA CHANGE */ |
|
2290 } |
|
2291 if (entity->open) |
|
2292 return XML_ERROR_RECURSIVE_ENTITY_REF; |
|
2293 if (entity->notation) |
|
2294 return XML_ERROR_BINARY_ENTITY_REF; |
|
2295 if (entity->textPtr) { |
|
2296 enum XML_Error result; |
|
2297 if (!defaultExpandInternalEntities) { |
|
2298 if (skippedEntityHandler) |
|
2299 skippedEntityHandler(handlerArg, entity->name, 0); |
|
2300 else if (defaultHandler) |
|
2301 reportDefault(parser, enc, s, next); |
|
2302 break; |
|
2303 } |
|
2304 result = processInternalEntity(parser, entity, XML_FALSE); |
|
2305 if (result != XML_ERROR_NONE) |
|
2306 return result; |
|
2307 } |
|
2308 else if (externalEntityRefHandler) { |
|
2309 const XML_Char *context; |
|
2310 entity->open = XML_TRUE; |
|
2311 context = getContext(parser); |
|
2312 entity->open = XML_FALSE; |
|
2313 if (!context) |
|
2314 return XML_ERROR_NO_MEMORY; |
|
2315 if (!externalEntityRefHandler(externalEntityRefHandlerArg, |
|
2316 context, |
|
2317 entity->base, |
|
2318 entity->systemId, |
|
2319 entity->publicId)) |
|
2320 return XML_ERROR_EXTERNAL_ENTITY_HANDLING; |
|
2321 poolDiscard(&tempPool); |
|
2322 } |
|
2323 else if (defaultHandler) |
|
2324 reportDefault(parser, enc, s, next); |
|
2325 break; |
|
2326 } |
|
2327 case XML_TOK_START_TAG_NO_ATTS: |
|
2328 /* fall through */ |
|
2329 case XML_TOK_START_TAG_WITH_ATTS: |
|
2330 { |
|
2331 TAG *tag; |
|
2332 enum XML_Error result; |
|
2333 XML_Char *toPtr; |
|
2334 if (freeTagList) { |
|
2335 tag = freeTagList; |
|
2336 freeTagList = freeTagList->parent; |
|
2337 } |
|
2338 else { |
|
2339 tag = (TAG *)MALLOC(sizeof(TAG)); |
|
2340 if (!tag) |
|
2341 return XML_ERROR_NO_MEMORY; |
|
2342 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); |
|
2343 if (!tag->buf) { |
|
2344 FREE(tag); |
|
2345 return XML_ERROR_NO_MEMORY; |
|
2346 } |
|
2347 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; |
|
2348 } |
|
2349 tag->bindings = NULL; |
|
2350 tag->parent = tagStack; |
|
2351 tagStack = tag; |
|
2352 tag->name.localPart = NULL; |
|
2353 tag->name.prefix = NULL; |
|
2354 tag->rawName = s + enc->minBytesPerChar; |
|
2355 tag->rawNameLength = XmlNameLength(enc, tag->rawName); |
|
2356 ++tagLevel; |
|
2357 { |
|
2358 const char *rawNameEnd = tag->rawName + tag->rawNameLength; |
|
2359 const char *fromPtr = tag->rawName; |
|
2360 toPtr = (XML_Char *)tag->buf; |
|
2361 for (;;) { |
|
2362 int bufSize; |
|
2363 int convLen; |
|
2364 XmlConvert(enc, |
|
2365 &fromPtr, rawNameEnd, |
|
2366 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); |
|
2367 convLen = (int)(toPtr - (XML_Char *)tag->buf); |
|
2368 if (fromPtr == rawNameEnd) { |
|
2369 tag->name.strLen = convLen; |
|
2370 break; |
|
2371 } |
|
2372 bufSize = (int)(tag->bufEnd - tag->buf) << 1; |
|
2373 { |
|
2374 char *temp = (char *)REALLOC(tag->buf, bufSize); |
|
2375 if (temp == NULL) |
|
2376 return XML_ERROR_NO_MEMORY; |
|
2377 tag->buf = temp; |
|
2378 tag->bufEnd = temp + bufSize; |
|
2379 toPtr = (XML_Char *)temp + convLen; |
|
2380 } |
|
2381 } |
|
2382 } |
|
2383 tag->name.str = (XML_Char *)tag->buf; |
|
2384 *toPtr = XML_T('\0'); |
|
2385 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); |
|
2386 if (result) |
|
2387 return result; |
|
2388 if (startElementHandler) |
|
2389 startElementHandler(handlerArg, tag->name.str, |
|
2390 (const XML_Char **)atts); |
|
2391 else if (defaultHandler) |
|
2392 reportDefault(parser, enc, s, next); |
|
2393 poolClear(&tempPool); |
|
2394 break; |
|
2395 } |
|
2396 case XML_TOK_EMPTY_ELEMENT_NO_ATTS: |
|
2397 /* fall through */ |
|
2398 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: |
|
2399 { |
|
2400 const char *rawName = s + enc->minBytesPerChar; |
|
2401 enum XML_Error result; |
|
2402 BINDING *bindings = NULL; |
|
2403 XML_Bool noElmHandlers = XML_TRUE; |
|
2404 TAG_NAME name; |
|
2405 name.str = poolStoreString(&tempPool, enc, rawName, |
|
2406 rawName + XmlNameLength(enc, rawName)); |
|
2407 if (!name.str) |
|
2408 return XML_ERROR_NO_MEMORY; |
|
2409 poolFinish(&tempPool); |
|
2410 result = storeAtts(parser, enc, s, &name, &bindings); |
|
2411 if (result) |
|
2412 return result; |
|
2413 poolFinish(&tempPool); |
|
2414 if (startElementHandler) { |
|
2415 startElementHandler(handlerArg, name.str, (const XML_Char **)atts); |
|
2416 noElmHandlers = XML_FALSE; |
|
2417 } |
|
2418 if (endElementHandler) { |
|
2419 if (startElementHandler) |
|
2420 *eventPP = *eventEndPP; |
|
2421 endElementHandler(handlerArg, name.str); |
|
2422 noElmHandlers = XML_FALSE; |
|
2423 } |
|
2424 if (noElmHandlers && defaultHandler) |
|
2425 reportDefault(parser, enc, s, next); |
|
2426 poolClear(&tempPool); |
|
2427 while (bindings) { |
|
2428 BINDING *b = bindings; |
|
2429 if (endNamespaceDeclHandler) |
|
2430 endNamespaceDeclHandler(handlerArg, b->prefix->name); |
|
2431 bindings = bindings->nextTagBinding; |
|
2432 b->nextTagBinding = freeBindingList; |
|
2433 freeBindingList = b; |
|
2434 b->prefix->binding = b->prevPrefixBinding; |
|
2435 } |
|
2436 } |
|
2437 if (tagLevel == 0) |
|
2438 return epilogProcessor(parser, next, end, nextPtr); |
|
2439 break; |
|
2440 case XML_TOK_END_TAG: |
|
2441 if (tagLevel == startTagLevel) |
|
2442 return XML_ERROR_ASYNC_ENTITY; |
|
2443 else { |
|
2444 int len; |
|
2445 const char *rawName; |
|
2446 TAG *tag = tagStack; |
|
2447 tagStack = tag->parent; |
|
2448 tag->parent = freeTagList; |
|
2449 freeTagList = tag; |
|
2450 rawName = s + enc->minBytesPerChar*2; |
|
2451 len = XmlNameLength(enc, rawName); |
|
2452 if (len != tag->rawNameLength |
|
2453 || memcmp(tag->rawName, rawName, len) != 0) { |
|
2454 /* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */ |
|
2455 /* This code is copied from the |if (endElementHandler)| block below */ |
|
2456 const XML_Char *localPart; |
|
2457 const XML_Char *prefix; |
|
2458 XML_Char *uri; |
|
2459 localPart = tag->name.localPart; |
|
2460 if (ns && localPart) { |
|
2461 /* localPart and prefix may have been overwritten in |
|
2462 tag->name.str, since this points to the binding->uri |
|
2463 buffer which gets re-used; so we have to add them again |
|
2464 */ |
|
2465 uri = (XML_Char *)tag->name.str + tag->name.uriLen; |
|
2466 /* don't need to check for space - already done in storeAtts() */ |
|
2467 while (*localPart) *uri++ = *localPart++; |
|
2468 prefix = (XML_Char *)tag->name.prefix; |
|
2469 if (ns_triplets && prefix) { |
|
2470 *uri++ = namespaceSeparator; |
|
2471 while (*prefix) *uri++ = *prefix++; |
|
2472 } |
|
2473 *uri = XML_T('\0'); |
|
2474 } |
|
2475 mismatch = tag->name.str; |
|
2476 /* END MOZILLA CHANGE */ |
|
2477 *eventPP = rawName; |
|
2478 return XML_ERROR_TAG_MISMATCH; |
|
2479 } |
|
2480 --tagLevel; |
|
2481 if (endElementHandler) { |
|
2482 const XML_Char *localPart; |
|
2483 const XML_Char *prefix; |
|
2484 XML_Char *uri; |
|
2485 localPart = tag->name.localPart; |
|
2486 if (ns && localPart) { |
|
2487 /* localPart and prefix may have been overwritten in |
|
2488 tag->name.str, since this points to the binding->uri |
|
2489 buffer which gets re-used; so we have to add them again |
|
2490 */ |
|
2491 uri = (XML_Char *)tag->name.str + tag->name.uriLen; |
|
2492 /* don't need to check for space - already done in storeAtts() */ |
|
2493 while (*localPart) *uri++ = *localPart++; |
|
2494 prefix = (XML_Char *)tag->name.prefix; |
|
2495 if (ns_triplets && prefix) { |
|
2496 *uri++ = namespaceSeparator; |
|
2497 while (*prefix) *uri++ = *prefix++; |
|
2498 } |
|
2499 *uri = XML_T('\0'); |
|
2500 } |
|
2501 endElementHandler(handlerArg, tag->name.str); |
|
2502 } |
|
2503 else if (defaultHandler) |
|
2504 reportDefault(parser, enc, s, next); |
|
2505 while (tag->bindings) { |
|
2506 BINDING *b = tag->bindings; |
|
2507 if (endNamespaceDeclHandler) |
|
2508 endNamespaceDeclHandler(handlerArg, b->prefix->name); |
|
2509 tag->bindings = tag->bindings->nextTagBinding; |
|
2510 b->nextTagBinding = freeBindingList; |
|
2511 freeBindingList = b; |
|
2512 b->prefix->binding = b->prevPrefixBinding; |
|
2513 } |
|
2514 if (tagLevel == 0) |
|
2515 return epilogProcessor(parser, next, end, nextPtr); |
|
2516 } |
|
2517 break; |
|
2518 case XML_TOK_CHAR_REF: |
|
2519 { |
|
2520 int n = XmlCharRefNumber(enc, s); |
|
2521 if (n < 0) |
|
2522 return XML_ERROR_BAD_CHAR_REF; |
|
2523 if (characterDataHandler) { |
|
2524 XML_Char buf[XML_ENCODE_MAX]; |
|
2525 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); |
|
2526 } |
|
2527 else if (defaultHandler) |
|
2528 reportDefault(parser, enc, s, next); |
|
2529 } |
|
2530 break; |
|
2531 case XML_TOK_XML_DECL: |
|
2532 return XML_ERROR_MISPLACED_XML_PI; |
|
2533 case XML_TOK_DATA_NEWLINE: |
|
2534 if (characterDataHandler) { |
|
2535 XML_Char c = 0xA; |
|
2536 characterDataHandler(handlerArg, &c, 1); |
|
2537 } |
|
2538 else if (defaultHandler) |
|
2539 reportDefault(parser, enc, s, next); |
|
2540 break; |
|
2541 case XML_TOK_CDATA_SECT_OPEN: |
|
2542 { |
|
2543 enum XML_Error result; |
|
2544 if (startCdataSectionHandler) |
|
2545 startCdataSectionHandler(handlerArg); |
|
2546 #if 0 |
|
2547 /* Suppose you doing a transformation on a document that involves |
|
2548 changing only the character data. You set up a defaultHandler |
|
2549 and a characterDataHandler. The defaultHandler simply copies |
|
2550 characters through. The characterDataHandler does the |
|
2551 transformation and writes the characters out escaping them as |
|
2552 necessary. This case will fail to work if we leave out the |
|
2553 following two lines (because & and < inside CDATA sections will |
|
2554 be incorrectly escaped). |
|
2555 |
|
2556 However, now we have a start/endCdataSectionHandler, so it seems |
|
2557 easier to let the user deal with this. |
|
2558 */ |
|
2559 else if (characterDataHandler) |
|
2560 characterDataHandler(handlerArg, dataBuf, 0); |
|
2561 #endif |
|
2562 else if (defaultHandler) |
|
2563 reportDefault(parser, enc, s, next); |
|
2564 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); |
|
2565 if (result != XML_ERROR_NONE) |
|
2566 return result; |
|
2567 else if (!next) { |
|
2568 processor = cdataSectionProcessor; |
|
2569 return result; |
|
2570 } |
|
2571 } |
|
2572 break; |
|
2573 case XML_TOK_TRAILING_RSQB: |
|
2574 if (haveMore) { |
|
2575 *nextPtr = s; |
|
2576 return XML_ERROR_NONE; |
|
2577 } |
|
2578 if (characterDataHandler) { |
|
2579 if (MUST_CONVERT(enc, s)) { |
|
2580 ICHAR *dataPtr = (ICHAR *)dataBuf; |
|
2581 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); |
|
2582 characterDataHandler(handlerArg, dataBuf, |
|
2583 (int)(dataPtr - (ICHAR *)dataBuf)); |
|
2584 } |
|
2585 else |
|
2586 characterDataHandler(handlerArg, |
|
2587 (XML_Char *)s, |
|
2588 (int)((XML_Char *)end - (XML_Char *)s)); |
|
2589 } |
|
2590 else if (defaultHandler) |
|
2591 reportDefault(parser, enc, s, end); |
|
2592 /* We are at the end of the final buffer, should we check for |
|
2593 XML_SUSPENDED, XML_FINISHED? |
|
2594 */ |
|
2595 if (startTagLevel == 0) { |
|
2596 *eventPP = end; |
|
2597 return XML_ERROR_NO_ELEMENTS; |
|
2598 } |
|
2599 if (tagLevel != startTagLevel) { |
|
2600 *eventPP = end; |
|
2601 return XML_ERROR_ASYNC_ENTITY; |
|
2602 } |
|
2603 *nextPtr = end; |
|
2604 return XML_ERROR_NONE; |
|
2605 case XML_TOK_DATA_CHARS: |
|
2606 if (characterDataHandler) { |
|
2607 if (MUST_CONVERT(enc, s)) { |
|
2608 for (;;) { |
|
2609 ICHAR *dataPtr = (ICHAR *)dataBuf; |
|
2610 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); |
|
2611 *eventEndPP = s; |
|
2612 characterDataHandler(handlerArg, dataBuf, |
|
2613 (int)(dataPtr - (ICHAR *)dataBuf)); |
|
2614 if (s == next) |
|
2615 break; |
|
2616 *eventPP = s; |
|
2617 } |
|
2618 } |
|
2619 else |
|
2620 characterDataHandler(handlerArg, |
|
2621 (XML_Char *)s, |
|
2622 (int)((XML_Char *)next - (XML_Char *)s)); |
|
2623 } |
|
2624 else if (defaultHandler) |
|
2625 reportDefault(parser, enc, s, next); |
|
2626 break; |
|
2627 case XML_TOK_PI: |
|
2628 if (!reportProcessingInstruction(parser, enc, s, next)) |
|
2629 return XML_ERROR_NO_MEMORY; |
|
2630 break; |
|
2631 case XML_TOK_COMMENT: |
|
2632 if (!reportComment(parser, enc, s, next)) |
|
2633 return XML_ERROR_NO_MEMORY; |
|
2634 break; |
|
2635 default: |
|
2636 if (defaultHandler) |
|
2637 reportDefault(parser, enc, s, next); |
|
2638 break; |
|
2639 } |
|
2640 *eventPP = s = next; |
|
2641 switch (ps_parsing) { |
|
2642 case XML_SUSPENDED: |
|
2643 *nextPtr = next; |
|
2644 return XML_ERROR_NONE; |
|
2645 case XML_FINISHED: |
|
2646 return XML_ERROR_ABORTED; |
|
2647 default: ; |
|
2648 } |
|
2649 } |
|
2650 /* not reached */ |
|
2651 } |
|
2652 |
|
2653 /* Precondition: all arguments must be non-NULL; |
|
2654 Purpose: |
|
2655 - normalize attributes |
|
2656 - check attributes for well-formedness |
|
2657 - generate namespace aware attribute names (URI, prefix) |
|
2658 - build list of attributes for startElementHandler |
|
2659 - default attributes |
|
2660 - process namespace declarations (check and report them) |
|
2661 - generate namespace aware element name (URI, prefix) |
|
2662 */ |
|
2663 static enum XML_Error |
|
2664 storeAtts(XML_Parser parser, const ENCODING *enc, |
|
2665 const char *attStr, TAG_NAME *tagNamePtr, |
|
2666 BINDING **bindingsPtr) |
|
2667 { |
|
2668 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
2669 ELEMENT_TYPE *elementType; |
|
2670 int nDefaultAtts; |
|
2671 const XML_Char **appAtts; /* the attribute list for the application */ |
|
2672 int attIndex = 0; |
|
2673 int prefixLen; |
|
2674 int i; |
|
2675 int n; |
|
2676 XML_Char *uri; |
|
2677 int nPrefixes = 0; |
|
2678 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2679 int nXMLNSDeclarations = 0; |
|
2680 /* END MOZILLA CHANGE */ |
|
2681 BINDING *binding; |
|
2682 const XML_Char *localPart; |
|
2683 |
|
2684 /* lookup the element type name */ |
|
2685 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); |
|
2686 if (!elementType) { |
|
2687 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); |
|
2688 if (!name) |
|
2689 return XML_ERROR_NO_MEMORY; |
|
2690 elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, |
|
2691 sizeof(ELEMENT_TYPE)); |
|
2692 if (!elementType) |
|
2693 return XML_ERROR_NO_MEMORY; |
|
2694 if (ns && !setElementTypePrefix(parser, elementType)) |
|
2695 return XML_ERROR_NO_MEMORY; |
|
2696 } |
|
2697 nDefaultAtts = elementType->nDefaultAtts; |
|
2698 |
|
2699 /* get the attributes from the tokenizer */ |
|
2700 n = XmlGetAttributes(enc, attStr, attsSize, atts); |
|
2701 if (n + nDefaultAtts > attsSize) { |
|
2702 int oldAttsSize = attsSize; |
|
2703 ATTRIBUTE *temp; |
|
2704 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; |
|
2705 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); |
|
2706 if (temp == NULL) |
|
2707 return XML_ERROR_NO_MEMORY; |
|
2708 atts = temp; |
|
2709 if (n > oldAttsSize) |
|
2710 XmlGetAttributes(enc, attStr, n, atts); |
|
2711 } |
|
2712 |
|
2713 appAtts = (const XML_Char **)atts; |
|
2714 for (i = 0; i < n; i++) { |
|
2715 /* add the name and value to the attribute list */ |
|
2716 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, |
|
2717 atts[i].name |
|
2718 + XmlNameLength(enc, atts[i].name)); |
|
2719 if (!attId) |
|
2720 return XML_ERROR_NO_MEMORY; |
|
2721 /* Detect duplicate attributes by their QNames. This does not work when |
|
2722 namespace processing is turned on and different prefixes for the same |
|
2723 namespace are used. For this case we have a check further down. |
|
2724 */ |
|
2725 if ((attId->name)[-1]) { |
|
2726 if (enc == encoding) |
|
2727 eventPtr = atts[i].name; |
|
2728 return XML_ERROR_DUPLICATE_ATTRIBUTE; |
|
2729 } |
|
2730 (attId->name)[-1] = 1; |
|
2731 appAtts[attIndex++] = attId->name; |
|
2732 if (!atts[i].normalized) { |
|
2733 enum XML_Error result; |
|
2734 XML_Bool isCdata = XML_TRUE; |
|
2735 |
|
2736 /* figure out whether declared as other than CDATA */ |
|
2737 if (attId->maybeTokenized) { |
|
2738 int j; |
|
2739 for (j = 0; j < nDefaultAtts; j++) { |
|
2740 if (attId == elementType->defaultAtts[j].id) { |
|
2741 isCdata = elementType->defaultAtts[j].isCdata; |
|
2742 break; |
|
2743 } |
|
2744 } |
|
2745 } |
|
2746 |
|
2747 /* normalize the attribute value */ |
|
2748 result = storeAttributeValue(parser, enc, isCdata, |
|
2749 atts[i].valuePtr, atts[i].valueEnd, |
|
2750 &tempPool); |
|
2751 if (result) |
|
2752 return result; |
|
2753 appAtts[attIndex] = poolStart(&tempPool); |
|
2754 poolFinish(&tempPool); |
|
2755 } |
|
2756 else { |
|
2757 /* the value did not need normalizing */ |
|
2758 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, |
|
2759 atts[i].valueEnd); |
|
2760 if (appAtts[attIndex] == 0) |
|
2761 return XML_ERROR_NO_MEMORY; |
|
2762 poolFinish(&tempPool); |
|
2763 } |
|
2764 /* handle prefixed attribute names */ |
|
2765 if (attId->prefix) { |
|
2766 if (attId->xmlns) { |
|
2767 /* deal with namespace declarations here */ |
|
2768 enum XML_Error result = addBinding(parser, attId->prefix, attId, |
|
2769 appAtts[attIndex], bindingsPtr); |
|
2770 if (result) |
|
2771 return result; |
|
2772 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2773 #if 0 |
|
2774 --attIndex; |
|
2775 #else |
|
2776 attIndex++; |
|
2777 nXMLNSDeclarations++; |
|
2778 (attId->name)[-1] = 3; |
|
2779 #endif |
|
2780 /* END MOZILLA CHANGE */ |
|
2781 } |
|
2782 else { |
|
2783 /* deal with other prefixed names later */ |
|
2784 attIndex++; |
|
2785 nPrefixes++; |
|
2786 (attId->name)[-1] = 2; |
|
2787 } |
|
2788 } |
|
2789 else |
|
2790 attIndex++; |
|
2791 } |
|
2792 |
|
2793 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ |
|
2794 nSpecifiedAtts = attIndex; |
|
2795 if (elementType->idAtt && (elementType->idAtt->name)[-1]) { |
|
2796 for (i = 0; i < attIndex; i += 2) |
|
2797 if (appAtts[i] == elementType->idAtt->name) { |
|
2798 idAttIndex = i; |
|
2799 break; |
|
2800 } |
|
2801 } |
|
2802 else |
|
2803 idAttIndex = -1; |
|
2804 |
|
2805 /* do attribute defaulting */ |
|
2806 for (i = 0; i < nDefaultAtts; i++) { |
|
2807 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; |
|
2808 if (!(da->id->name)[-1] && da->value) { |
|
2809 if (da->id->prefix) { |
|
2810 if (da->id->xmlns) { |
|
2811 enum XML_Error result = addBinding(parser, da->id->prefix, da->id, |
|
2812 da->value, bindingsPtr); |
|
2813 if (result) |
|
2814 return result; |
|
2815 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2816 (da->id->name)[-1] = 3; |
|
2817 nXMLNSDeclarations++; |
|
2818 appAtts[attIndex++] = da->id->name; |
|
2819 appAtts[attIndex++] = da->value; |
|
2820 /* END MOZILLA CHANGE */ |
|
2821 } |
|
2822 else { |
|
2823 (da->id->name)[-1] = 2; |
|
2824 nPrefixes++; |
|
2825 appAtts[attIndex++] = da->id->name; |
|
2826 appAtts[attIndex++] = da->value; |
|
2827 } |
|
2828 } |
|
2829 else { |
|
2830 (da->id->name)[-1] = 1; |
|
2831 appAtts[attIndex++] = da->id->name; |
|
2832 appAtts[attIndex++] = da->value; |
|
2833 } |
|
2834 } |
|
2835 } |
|
2836 appAtts[attIndex] = 0; |
|
2837 |
|
2838 /* expand prefixed attribute names, check for duplicates, |
|
2839 and clear flags that say whether attributes were specified */ |
|
2840 i = 0; |
|
2841 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2842 #if 0 |
|
2843 if (nPrefixes) { |
|
2844 #else |
|
2845 if (nPrefixes || nXMLNSDeclarations) { |
|
2846 #endif |
|
2847 /* END MOZILLA CHANGE */ |
|
2848 int j; /* hash table index */ |
|
2849 unsigned long version = nsAttsVersion; |
|
2850 int nsAttsSize = (int)1 << nsAttsPower; |
|
2851 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2852 if (nPrefixes) { |
|
2853 /* END MOZILLA CHANGE */ |
|
2854 /* size of hash table must be at least 2 * (# of prefixed attributes) */ |
|
2855 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */ |
|
2856 NS_ATT *temp; |
|
2857 /* hash table size must also be a power of 2 and >= 8 */ |
|
2858 while (nPrefixes >> nsAttsPower++); |
|
2859 if (nsAttsPower < 3) |
|
2860 nsAttsPower = 3; |
|
2861 nsAttsSize = (int)1 << nsAttsPower; |
|
2862 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT)); |
|
2863 if (!temp) |
|
2864 return XML_ERROR_NO_MEMORY; |
|
2865 nsAtts = temp; |
|
2866 version = 0; /* force re-initialization of nsAtts hash table */ |
|
2867 } |
|
2868 /* using a version flag saves us from initializing nsAtts every time */ |
|
2869 if (!version) { /* initialize version flags when version wraps around */ |
|
2870 version = INIT_ATTS_VERSION; |
|
2871 for (j = nsAttsSize; j != 0; ) |
|
2872 nsAtts[--j].version = version; |
|
2873 } |
|
2874 nsAttsVersion = --version; |
|
2875 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2876 } |
|
2877 /* END MOZILLA CHANGE */ |
|
2878 |
|
2879 /* expand prefixed names and check for duplicates */ |
|
2880 for (; i < attIndex; i += 2) { |
|
2881 const XML_Char *s = appAtts[i]; |
|
2882 if (s[-1] == 2) { /* prefixed */ |
|
2883 ATTRIBUTE_ID *id; |
|
2884 const BINDING *b; |
|
2885 unsigned long uriHash = 0; |
|
2886 ((XML_Char *)s)[-1] = 0; /* clear flag */ |
|
2887 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0); |
|
2888 b = id->prefix->binding; |
|
2889 if (!b) |
|
2890 return XML_ERROR_UNBOUND_PREFIX; |
|
2891 |
|
2892 /* as we expand the name we also calculate its hash value */ |
|
2893 for (j = 0; j < b->uriLen; j++) { |
|
2894 const XML_Char c = b->uri[j]; |
|
2895 if (!poolAppendChar(&tempPool, c)) |
|
2896 return XML_ERROR_NO_MEMORY; |
|
2897 uriHash = CHAR_HASH(uriHash, c); |
|
2898 } |
|
2899 while (*s++ != XML_T(':')) |
|
2900 ; |
|
2901 do { /* copies null terminator */ |
|
2902 const XML_Char c = *s; |
|
2903 if (!poolAppendChar(&tempPool, *s)) |
|
2904 return XML_ERROR_NO_MEMORY; |
|
2905 uriHash = CHAR_HASH(uriHash, c); |
|
2906 } while (*s++); |
|
2907 |
|
2908 { /* Check hash table for duplicate of expanded name (uriName). |
|
2909 Derived from code in lookup(HASH_TABLE *table, ...). |
|
2910 */ |
|
2911 unsigned char step = 0; |
|
2912 unsigned long mask = nsAttsSize - 1; |
|
2913 j = uriHash & mask; /* index into hash table */ |
|
2914 while (nsAtts[j].version == version) { |
|
2915 /* for speed we compare stored hash values first */ |
|
2916 if (uriHash == nsAtts[j].hash) { |
|
2917 const XML_Char *s1 = poolStart(&tempPool); |
|
2918 const XML_Char *s2 = nsAtts[j].uriName; |
|
2919 /* s1 is null terminated, but not s2 */ |
|
2920 for (; *s1 == *s2 && *s1 != 0; s1++, s2++); |
|
2921 if (*s1 == 0) |
|
2922 return XML_ERROR_DUPLICATE_ATTRIBUTE; |
|
2923 } |
|
2924 if (!step) |
|
2925 step = PROBE_STEP(uriHash, mask, nsAttsPower); |
|
2926 j < step ? (j += nsAttsSize - step) : (j -= step); |
|
2927 } |
|
2928 } |
|
2929 |
|
2930 if (ns_triplets) { /* append namespace separator and prefix */ |
|
2931 tempPool.ptr[-1] = namespaceSeparator; |
|
2932 s = b->prefix->name; |
|
2933 do { |
|
2934 if (!poolAppendChar(&tempPool, *s)) |
|
2935 return XML_ERROR_NO_MEMORY; |
|
2936 } while (*s++); |
|
2937 } |
|
2938 |
|
2939 /* store expanded name in attribute list */ |
|
2940 s = poolStart(&tempPool); |
|
2941 poolFinish(&tempPool); |
|
2942 appAtts[i] = s; |
|
2943 |
|
2944 /* fill empty slot with new version, uriName and hash value */ |
|
2945 nsAtts[j].version = version; |
|
2946 nsAtts[j].hash = uriHash; |
|
2947 nsAtts[j].uriName = s; |
|
2948 |
|
2949 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2950 #if 0 |
|
2951 if (!--nPrefixes) |
|
2952 #else |
|
2953 if (!--nPrefixes && !nXMLNSDeclarations) { |
|
2954 #endif |
|
2955 /* END MOZILLA CHANGE */ |
|
2956 i += 2; |
|
2957 break; |
|
2958 } |
|
2959 } |
|
2960 /* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */ |
|
2961 else if (s[-1] == 3) { /* xmlns attribute */ |
|
2962 static const XML_Char xmlnsNamespace[] = { |
|
2963 'h', 't', 't', 'p', ':', '/', '/', |
|
2964 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', |
|
2965 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0' |
|
2966 }; |
|
2967 static const XML_Char xmlnsPrefix[] = { |
|
2968 'x', 'm', 'l', 'n', 's', '\0' |
|
2969 }; |
|
2970 XML_Bool appendXMLNS = XML_TRUE; |
|
2971 |
|
2972 ((XML_Char *)s)[-1] = 0; /* clear flag */ |
|
2973 if (!poolAppendString(&tempPool, xmlnsNamespace) |
|
2974 || !poolAppendChar(&tempPool, namespaceSeparator)) |
|
2975 return XML_ERROR_NO_MEMORY; |
|
2976 s += sizeof(xmlnsPrefix) / sizeof(xmlnsPrefix[0]) - 1; |
|
2977 if (*s == XML_T(':')) { |
|
2978 ++s; |
|
2979 do { /* copies null terminator */ |
|
2980 if (!poolAppendChar(&tempPool, *s)) |
|
2981 return XML_ERROR_NO_MEMORY; |
|
2982 } while (*s++); |
|
2983 if (ns_triplets) { /* append namespace separator and prefix */ |
|
2984 tempPool.ptr[-1] = namespaceSeparator; |
|
2985 if (!poolAppendString(&tempPool, xmlnsPrefix) |
|
2986 || !poolAppendChar(&tempPool, '\0')) |
|
2987 return XML_ERROR_NO_MEMORY; |
|
2988 } |
|
2989 } |
|
2990 else { |
|
2991 /* xlmns attribute without a prefix. */ |
|
2992 if (!poolAppendString(&tempPool, xmlnsPrefix) |
|
2993 || !poolAppendChar(&tempPool, '\0')) |
|
2994 return XML_ERROR_NO_MEMORY; |
|
2995 } |
|
2996 |
|
2997 /* store expanded name in attribute list */ |
|
2998 s = poolStart(&tempPool); |
|
2999 poolFinish(&tempPool); |
|
3000 appAtts[i] = s; |
|
3001 |
|
3002 if (!--nXMLNSDeclarations && !nPrefixes) { |
|
3003 i += 2; |
|
3004 break; |
|
3005 } |
|
3006 } |
|
3007 /* END MOZILLA CHANGE */ |
|
3008 else /* not prefixed */ |
|
3009 ((XML_Char *)s)[-1] = 0; /* clear flag */ |
|
3010 } |
|
3011 } |
|
3012 /* clear flags for the remaining attributes */ |
|
3013 for (; i < attIndex; i += 2) |
|
3014 ((XML_Char *)(appAtts[i]))[-1] = 0; |
|
3015 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) |
|
3016 binding->attId->name[-1] = 0; |
|
3017 |
|
3018 if (!ns) |
|
3019 return XML_ERROR_NONE; |
|
3020 |
|
3021 /* expand the element type name */ |
|
3022 if (elementType->prefix) { |
|
3023 binding = elementType->prefix->binding; |
|
3024 if (!binding) |
|
3025 return XML_ERROR_UNBOUND_PREFIX; |
|
3026 localPart = tagNamePtr->str; |
|
3027 while (*localPart++ != XML_T(':')) |
|
3028 ; |
|
3029 } |
|
3030 else if (dtd->defaultPrefix.binding) { |
|
3031 binding = dtd->defaultPrefix.binding; |
|
3032 localPart = tagNamePtr->str; |
|
3033 } |
|
3034 else |
|
3035 return XML_ERROR_NONE; |
|
3036 prefixLen = 0; |
|
3037 if (ns_triplets && binding->prefix->name) { |
|
3038 for (; binding->prefix->name[prefixLen++];) |
|
3039 ; /* prefixLen includes null terminator */ |
|
3040 } |
|
3041 tagNamePtr->localPart = localPart; |
|
3042 tagNamePtr->uriLen = binding->uriLen; |
|
3043 tagNamePtr->prefix = binding->prefix->name; |
|
3044 tagNamePtr->prefixLen = prefixLen; |
|
3045 for (i = 0; localPart[i++];) |
|
3046 ; /* i includes null terminator */ |
|
3047 n = i + binding->uriLen + prefixLen; |
|
3048 if (n > binding->uriAlloc) { |
|
3049 TAG *p; |
|
3050 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); |
|
3051 if (!uri) |
|
3052 return XML_ERROR_NO_MEMORY; |
|
3053 binding->uriAlloc = n + EXPAND_SPARE; |
|
3054 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); |
|
3055 for (p = tagStack; p; p = p->parent) |
|
3056 if (p->name.str == binding->uri) |
|
3057 p->name.str = uri; |
|
3058 FREE(binding->uri); |
|
3059 binding->uri = uri; |
|
3060 } |
|
3061 /* if namespaceSeparator != '\0' then uri includes it already */ |
|
3062 uri = binding->uri + binding->uriLen; |
|
3063 memcpy(uri, localPart, i * sizeof(XML_Char)); |
|
3064 /* we always have a namespace separator between localPart and prefix */ |
|
3065 if (prefixLen) { |
|
3066 uri += i - 1; |
|
3067 *uri = namespaceSeparator; /* replace null terminator */ |
|
3068 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); |
|
3069 } |
|
3070 tagNamePtr->str = binding->uri; |
|
3071 return XML_ERROR_NONE; |
|
3072 } |
|
3073 |
|
3074 /* addBinding() overwrites the value of prefix->binding without checking. |
|
3075 Therefore one must keep track of the old value outside of addBinding(). |
|
3076 */ |
|
3077 static enum XML_Error |
|
3078 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, |
|
3079 const XML_Char *uri, BINDING **bindingsPtr) |
|
3080 { |
|
3081 static const XML_Char xmlNamespace[] = { |
|
3082 'h', 't', 't', 'p', ':', '/', '/', |
|
3083 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', |
|
3084 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', |
|
3085 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' |
|
3086 }; |
|
3087 static const int xmlLen = |
|
3088 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1; |
|
3089 static const XML_Char xmlnsNamespace[] = { |
|
3090 'h', 't', 't', 'p', ':', '/', '/', |
|
3091 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', |
|
3092 '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0' |
|
3093 }; |
|
3094 static const int xmlnsLen = |
|
3095 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1; |
|
3096 |
|
3097 XML_Bool mustBeXML = XML_FALSE; |
|
3098 XML_Bool isXML = XML_TRUE; |
|
3099 XML_Bool isXMLNS = XML_TRUE; |
|
3100 |
|
3101 BINDING *b; |
|
3102 int len; |
|
3103 |
|
3104 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ |
|
3105 if (*uri == XML_T('\0') && prefix->name) |
|
3106 return XML_ERROR_UNDECLARING_PREFIX; |
|
3107 |
|
3108 if (prefix->name |
|
3109 && prefix->name[0] == XML_T('x') |
|
3110 && prefix->name[1] == XML_T('m') |
|
3111 && prefix->name[2] == XML_T('l')) { |
|
3112 |
|
3113 /* Not allowed to bind xmlns */ |
|
3114 if (prefix->name[3] == XML_T('n') |
|
3115 && prefix->name[4] == XML_T('s') |
|
3116 && prefix->name[5] == XML_T('\0')) |
|
3117 return XML_ERROR_RESERVED_PREFIX_XMLNS; |
|
3118 |
|
3119 if (prefix->name[3] == XML_T('\0')) |
|
3120 mustBeXML = XML_TRUE; |
|
3121 } |
|
3122 |
|
3123 for (len = 0; uri[len]; len++) { |
|
3124 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len])) |
|
3125 isXML = XML_FALSE; |
|
3126 |
|
3127 if (!mustBeXML && isXMLNS |
|
3128 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) |
|
3129 isXMLNS = XML_FALSE; |
|
3130 } |
|
3131 isXML = isXML && len == xmlLen; |
|
3132 isXMLNS = isXMLNS && len == xmlnsLen; |
|
3133 |
|
3134 if (mustBeXML != isXML) |
|
3135 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML |
|
3136 : XML_ERROR_RESERVED_NAMESPACE_URI; |
|
3137 |
|
3138 if (isXMLNS) |
|
3139 return XML_ERROR_RESERVED_NAMESPACE_URI; |
|
3140 |
|
3141 if (namespaceSeparator) |
|
3142 len++; |
|
3143 if (freeBindingList) { |
|
3144 b = freeBindingList; |
|
3145 if (len > b->uriAlloc) { |
|
3146 XML_Char *temp = (XML_Char *)REALLOC(b->uri, |
|
3147 sizeof(XML_Char) * (len + EXPAND_SPARE)); |
|
3148 if (temp == NULL) |
|
3149 return XML_ERROR_NO_MEMORY; |
|
3150 b->uri = temp; |
|
3151 b->uriAlloc = len + EXPAND_SPARE; |
|
3152 } |
|
3153 freeBindingList = b->nextTagBinding; |
|
3154 } |
|
3155 else { |
|
3156 b = (BINDING *)MALLOC(sizeof(BINDING)); |
|
3157 if (!b) |
|
3158 return XML_ERROR_NO_MEMORY; |
|
3159 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); |
|
3160 if (!b->uri) { |
|
3161 FREE(b); |
|
3162 return XML_ERROR_NO_MEMORY; |
|
3163 } |
|
3164 b->uriAlloc = len + EXPAND_SPARE; |
|
3165 } |
|
3166 b->uriLen = len; |
|
3167 memcpy(b->uri, uri, len * sizeof(XML_Char)); |
|
3168 if (namespaceSeparator) |
|
3169 b->uri[len - 1] = namespaceSeparator; |
|
3170 b->prefix = prefix; |
|
3171 b->attId = attId; |
|
3172 b->prevPrefixBinding = prefix->binding; |
|
3173 /* NULL binding when default namespace undeclared */ |
|
3174 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) |
|
3175 prefix->binding = NULL; |
|
3176 else |
|
3177 prefix->binding = b; |
|
3178 b->nextTagBinding = *bindingsPtr; |
|
3179 *bindingsPtr = b; |
|
3180 /* if attId == NULL then we are not starting a namespace scope */ |
|
3181 if (attId && startNamespaceDeclHandler) |
|
3182 startNamespaceDeclHandler(handlerArg, prefix->name, |
|
3183 prefix->binding ? uri : 0); |
|
3184 return XML_ERROR_NONE; |
|
3185 } |
|
3186 |
|
3187 /* The idea here is to avoid using stack for each CDATA section when |
|
3188 the whole file is parsed with one call. |
|
3189 */ |
|
3190 static enum XML_Error PTRCALL |
|
3191 cdataSectionProcessor(XML_Parser parser, |
|
3192 const char *start, |
|
3193 const char *end, |
|
3194 const char **endPtr) |
|
3195 { |
|
3196 enum XML_Error result = doCdataSection(parser, encoding, &start, end, |
|
3197 endPtr, (XML_Bool)!ps_finalBuffer); |
|
3198 if (result != XML_ERROR_NONE) |
|
3199 return result; |
|
3200 if (start) { |
|
3201 if (parentParser) { /* we are parsing an external entity */ |
|
3202 processor = externalEntityContentProcessor; |
|
3203 return externalEntityContentProcessor(parser, start, end, endPtr); |
|
3204 } |
|
3205 else { |
|
3206 processor = contentProcessor; |
|
3207 return contentProcessor(parser, start, end, endPtr); |
|
3208 } |
|
3209 } |
|
3210 return result; |
|
3211 } |
|
3212 |
|
3213 /* startPtr gets set to non-null if the section is closed, and to null if |
|
3214 the section is not yet closed. |
|
3215 */ |
|
3216 static enum XML_Error |
|
3217 doCdataSection(XML_Parser parser, |
|
3218 const ENCODING *enc, |
|
3219 const char **startPtr, |
|
3220 const char *end, |
|
3221 const char **nextPtr, |
|
3222 XML_Bool haveMore) |
|
3223 { |
|
3224 const char *s = *startPtr; |
|
3225 const char **eventPP; |
|
3226 const char **eventEndPP; |
|
3227 if (enc == encoding) { |
|
3228 eventPP = &eventPtr; |
|
3229 *eventPP = s; |
|
3230 eventEndPP = &eventEndPtr; |
|
3231 } |
|
3232 else { |
|
3233 eventPP = &(openInternalEntities->internalEventPtr); |
|
3234 eventEndPP = &(openInternalEntities->internalEventEndPtr); |
|
3235 } |
|
3236 *eventPP = s; |
|
3237 *startPtr = NULL; |
|
3238 |
|
3239 for (;;) { |
|
3240 const char *next; |
|
3241 int tok = XmlCdataSectionTok(enc, s, end, &next); |
|
3242 *eventEndPP = next; |
|
3243 switch (tok) { |
|
3244 case XML_TOK_CDATA_SECT_CLOSE: |
|
3245 if (endCdataSectionHandler) |
|
3246 endCdataSectionHandler(handlerArg); |
|
3247 #if 0 |
|
3248 /* see comment under XML_TOK_CDATA_SECT_OPEN */ |
|
3249 else if (characterDataHandler) |
|
3250 characterDataHandler(handlerArg, dataBuf, 0); |
|
3251 #endif |
|
3252 else if (defaultHandler) |
|
3253 reportDefault(parser, enc, s, next); |
|
3254 *startPtr = next; |
|
3255 *nextPtr = next; |
|
3256 if (ps_parsing == XML_FINISHED) |
|
3257 return XML_ERROR_ABORTED; |
|
3258 else |
|
3259 return XML_ERROR_NONE; |
|
3260 case XML_TOK_DATA_NEWLINE: |
|
3261 if (characterDataHandler) { |
|
3262 XML_Char c = 0xA; |
|
3263 characterDataHandler(handlerArg, &c, 1); |
|
3264 } |
|
3265 else if (defaultHandler) |
|
3266 reportDefault(parser, enc, s, next); |
|
3267 break; |
|
3268 case XML_TOK_DATA_CHARS: |
|
3269 if (characterDataHandler) { |
|
3270 if (MUST_CONVERT(enc, s)) { |
|
3271 for (;;) { |
|
3272 ICHAR *dataPtr = (ICHAR *)dataBuf; |
|
3273 XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); |
|
3274 *eventEndPP = next; |
|
3275 characterDataHandler(handlerArg, dataBuf, |
|
3276 (int)(dataPtr - (ICHAR *)dataBuf)); |
|
3277 if (s == next) |
|
3278 break; |
|
3279 *eventPP = s; |
|
3280 } |
|
3281 } |
|
3282 else |
|
3283 characterDataHandler(handlerArg, |
|
3284 (XML_Char *)s, |
|
3285 (int)((XML_Char *)next - (XML_Char *)s)); |
|
3286 } |
|
3287 else if (defaultHandler) |
|
3288 reportDefault(parser, enc, s, next); |
|
3289 break; |
|
3290 case XML_TOK_INVALID: |
|
3291 *eventPP = next; |
|
3292 return XML_ERROR_INVALID_TOKEN; |
|
3293 case XML_TOK_PARTIAL_CHAR: |
|
3294 if (haveMore) { |
|
3295 *nextPtr = s; |
|
3296 return XML_ERROR_NONE; |
|
3297 } |
|
3298 return XML_ERROR_PARTIAL_CHAR; |
|
3299 case XML_TOK_PARTIAL: |
|
3300 case XML_TOK_NONE: |
|
3301 if (haveMore) { |
|
3302 *nextPtr = s; |
|
3303 return XML_ERROR_NONE; |
|
3304 } |
|
3305 return XML_ERROR_UNCLOSED_CDATA_SECTION; |
|
3306 default: |
|
3307 *eventPP = next; |
|
3308 return XML_ERROR_UNEXPECTED_STATE; |
|
3309 } |
|
3310 |
|
3311 *eventPP = s = next; |
|
3312 switch (ps_parsing) { |
|
3313 case XML_SUSPENDED: |
|
3314 *nextPtr = next; |
|
3315 return XML_ERROR_NONE; |
|
3316 case XML_FINISHED: |
|
3317 return XML_ERROR_ABORTED; |
|
3318 default: ; |
|
3319 } |
|
3320 } |
|
3321 /* not reached */ |
|
3322 } |
|
3323 |
|
3324 #ifdef XML_DTD |
|
3325 |
|
3326 /* The idea here is to avoid using stack for each IGNORE section when |
|
3327 the whole file is parsed with one call. |
|
3328 */ |
|
3329 static enum XML_Error PTRCALL |
|
3330 ignoreSectionProcessor(XML_Parser parser, |
|
3331 const char *start, |
|
3332 const char *end, |
|
3333 const char **endPtr) |
|
3334 { |
|
3335 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, |
|
3336 endPtr, (XML_Bool)!ps_finalBuffer); |
|
3337 if (result != XML_ERROR_NONE) |
|
3338 return result; |
|
3339 if (start) { |
|
3340 processor = prologProcessor; |
|
3341 return prologProcessor(parser, start, end, endPtr); |
|
3342 } |
|
3343 return result; |
|
3344 } |
|
3345 |
|
3346 /* startPtr gets set to non-null is the section is closed, and to null |
|
3347 if the section is not yet closed. |
|
3348 */ |
|
3349 static enum XML_Error |
|
3350 doIgnoreSection(XML_Parser parser, |
|
3351 const ENCODING *enc, |
|
3352 const char **startPtr, |
|
3353 const char *end, |
|
3354 const char **nextPtr, |
|
3355 XML_Bool haveMore) |
|
3356 { |
|
3357 const char *next; |
|
3358 int tok; |
|
3359 const char *s = *startPtr; |
|
3360 const char **eventPP; |
|
3361 const char **eventEndPP; |
|
3362 if (enc == encoding) { |
|
3363 eventPP = &eventPtr; |
|
3364 *eventPP = s; |
|
3365 eventEndPP = &eventEndPtr; |
|
3366 } |
|
3367 else { |
|
3368 eventPP = &(openInternalEntities->internalEventPtr); |
|
3369 eventEndPP = &(openInternalEntities->internalEventEndPtr); |
|
3370 } |
|
3371 *eventPP = s; |
|
3372 *startPtr = NULL; |
|
3373 tok = XmlIgnoreSectionTok(enc, s, end, &next); |
|
3374 *eventEndPP = next; |
|
3375 switch (tok) { |
|
3376 case XML_TOK_IGNORE_SECT: |
|
3377 if (defaultHandler) |
|
3378 reportDefault(parser, enc, s, next); |
|
3379 *startPtr = next; |
|
3380 *nextPtr = next; |
|
3381 if (ps_parsing == XML_FINISHED) |
|
3382 return XML_ERROR_ABORTED; |
|
3383 else |
|
3384 return XML_ERROR_NONE; |
|
3385 case XML_TOK_INVALID: |
|
3386 *eventPP = next; |
|
3387 return XML_ERROR_INVALID_TOKEN; |
|
3388 case XML_TOK_PARTIAL_CHAR: |
|
3389 if (haveMore) { |
|
3390 *nextPtr = s; |
|
3391 return XML_ERROR_NONE; |
|
3392 } |
|
3393 return XML_ERROR_PARTIAL_CHAR; |
|
3394 case XML_TOK_PARTIAL: |
|
3395 case XML_TOK_NONE: |
|
3396 if (haveMore) { |
|
3397 *nextPtr = s; |
|
3398 return XML_ERROR_NONE; |
|
3399 } |
|
3400 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ |
|
3401 default: |
|
3402 *eventPP = next; |
|
3403 return XML_ERROR_UNEXPECTED_STATE; |
|
3404 } |
|
3405 /* not reached */ |
|
3406 } |
|
3407 |
|
3408 #endif /* XML_DTD */ |
|
3409 |
|
3410 static enum XML_Error |
|
3411 initializeEncoding(XML_Parser parser) |
|
3412 { |
|
3413 const char *s; |
|
3414 #ifdef XML_UNICODE |
|
3415 char encodingBuf[128]; |
|
3416 if (!protocolEncodingName) |
|
3417 s = NULL; |
|
3418 else { |
|
3419 int i; |
|
3420 for (i = 0; protocolEncodingName[i]; i++) { |
|
3421 if (i == sizeof(encodingBuf) - 1 |
|
3422 || (protocolEncodingName[i] & ~0x7f) != 0) { |
|
3423 encodingBuf[0] = '\0'; |
|
3424 break; |
|
3425 } |
|
3426 encodingBuf[i] = (char)protocolEncodingName[i]; |
|
3427 } |
|
3428 encodingBuf[i] = '\0'; |
|
3429 s = encodingBuf; |
|
3430 } |
|
3431 #else |
|
3432 s = protocolEncodingName; |
|
3433 #endif |
|
3434 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) |
|
3435 return XML_ERROR_NONE; |
|
3436 return handleUnknownEncoding(parser, protocolEncodingName); |
|
3437 } |
|
3438 |
|
3439 static enum XML_Error |
|
3440 processXmlDecl(XML_Parser parser, int isGeneralTextEntity, |
|
3441 const char *s, const char *next) |
|
3442 { |
|
3443 const char *encodingName = NULL; |
|
3444 const XML_Char *storedEncName = NULL; |
|
3445 const ENCODING *newEncoding = NULL; |
|
3446 const char *version = NULL; |
|
3447 const char *versionend; |
|
3448 const XML_Char *storedversion = NULL; |
|
3449 int standalone = -1; |
|
3450 if (!(ns |
|
3451 ? XmlParseXmlDeclNS |
|
3452 : XmlParseXmlDecl)(isGeneralTextEntity, |
|
3453 encoding, |
|
3454 s, |
|
3455 next, |
|
3456 &eventPtr, |
|
3457 &version, |
|
3458 &versionend, |
|
3459 &encodingName, |
|
3460 &newEncoding, |
|
3461 &standalone)) { |
|
3462 if (isGeneralTextEntity) |
|
3463 return XML_ERROR_TEXT_DECL; |
|
3464 else |
|
3465 return XML_ERROR_XML_DECL; |
|
3466 } |
|
3467 if (!isGeneralTextEntity && standalone == 1) { |
|
3468 _dtd->standalone = XML_TRUE; |
|
3469 #ifdef XML_DTD |
|
3470 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) |
|
3471 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; |
|
3472 #endif /* XML_DTD */ |
|
3473 } |
|
3474 if (xmlDeclHandler) { |
|
3475 if (encodingName != NULL) { |
|
3476 storedEncName = poolStoreString(&temp2Pool, |
|
3477 encoding, |
|
3478 encodingName, |
|
3479 encodingName |
|
3480 + XmlNameLength(encoding, encodingName)); |
|
3481 if (!storedEncName) |
|
3482 return XML_ERROR_NO_MEMORY; |
|
3483 poolFinish(&temp2Pool); |
|
3484 } |
|
3485 if (version) { |
|
3486 storedversion = poolStoreString(&temp2Pool, |
|
3487 encoding, |
|
3488 version, |
|
3489 versionend - encoding->minBytesPerChar); |
|
3490 if (!storedversion) |
|
3491 return XML_ERROR_NO_MEMORY; |
|
3492 } |
|
3493 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); |
|
3494 } |
|
3495 else if (defaultHandler) |
|
3496 reportDefault(parser, encoding, s, next); |
|
3497 if (protocolEncodingName == NULL) { |
|
3498 if (newEncoding) { |
|
3499 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { |
|
3500 eventPtr = encodingName; |
|
3501 return XML_ERROR_INCORRECT_ENCODING; |
|
3502 } |
|
3503 encoding = newEncoding; |
|
3504 } |
|
3505 else if (encodingName) { |
|
3506 enum XML_Error result; |
|
3507 if (!storedEncName) { |
|
3508 storedEncName = poolStoreString( |
|
3509 &temp2Pool, encoding, encodingName, |
|
3510 encodingName + XmlNameLength(encoding, encodingName)); |
|
3511 if (!storedEncName) |
|
3512 return XML_ERROR_NO_MEMORY; |
|
3513 } |
|
3514 result = handleUnknownEncoding(parser, storedEncName); |
|
3515 poolClear(&temp2Pool); |
|
3516 if (result == XML_ERROR_UNKNOWN_ENCODING) |
|
3517 eventPtr = encodingName; |
|
3518 return result; |
|
3519 } |
|
3520 } |
|
3521 |
|
3522 if (storedEncName || storedversion) |
|
3523 poolClear(&temp2Pool); |
|
3524 |
|
3525 return XML_ERROR_NONE; |
|
3526 } |
|
3527 |
|
3528 static enum XML_Error |
|
3529 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) |
|
3530 { |
|
3531 if (unknownEncodingHandler) { |
|
3532 XML_Encoding info; |
|
3533 int i; |
|
3534 for (i = 0; i < 256; i++) |
|
3535 info.map[i] = -1; |
|
3536 info.convert = NULL; |
|
3537 info.data = NULL; |
|
3538 info.release = NULL; |
|
3539 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, |
|
3540 &info)) { |
|
3541 ENCODING *enc; |
|
3542 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); |
|
3543 if (!unknownEncodingMem) { |
|
3544 if (info.release) |
|
3545 info.release(info.data); |
|
3546 return XML_ERROR_NO_MEMORY; |
|
3547 } |
|
3548 enc = (ns |
|
3549 ? XmlInitUnknownEncodingNS |
|
3550 : XmlInitUnknownEncoding)(unknownEncodingMem, |
|
3551 info.map, |
|
3552 info.convert, |
|
3553 info.data); |
|
3554 if (enc) { |
|
3555 unknownEncodingData = info.data; |
|
3556 unknownEncodingRelease = info.release; |
|
3557 encoding = enc; |
|
3558 return XML_ERROR_NONE; |
|
3559 } |
|
3560 } |
|
3561 if (info.release != NULL) |
|
3562 info.release(info.data); |
|
3563 } |
|
3564 return XML_ERROR_UNKNOWN_ENCODING; |
|
3565 } |
|
3566 |
|
3567 static enum XML_Error PTRCALL |
|
3568 prologInitProcessor(XML_Parser parser, |
|
3569 const char *s, |
|
3570 const char *end, |
|
3571 const char **nextPtr) |
|
3572 { |
|
3573 enum XML_Error result = initializeEncoding(parser); |
|
3574 if (result != XML_ERROR_NONE) |
|
3575 return result; |
|
3576 processor = prologProcessor; |
|
3577 return prologProcessor(parser, s, end, nextPtr); |
|
3578 } |
|
3579 |
|
3580 #ifdef XML_DTD |
|
3581 |
|
3582 static enum XML_Error PTRCALL |
|
3583 externalParEntInitProcessor(XML_Parser parser, |
|
3584 const char *s, |
|
3585 const char *end, |
|
3586 const char **nextPtr) |
|
3587 { |
|
3588 enum XML_Error result = initializeEncoding(parser); |
|
3589 if (result != XML_ERROR_NONE) |
|
3590 return result; |
|
3591 |
|
3592 /* we know now that XML_Parse(Buffer) has been called, |
|
3593 so we consider the external parameter entity read */ |
|
3594 _dtd->paramEntityRead = XML_TRUE; |
|
3595 |
|
3596 if (prologState.inEntityValue) { |
|
3597 processor = entityValueInitProcessor; |
|
3598 return entityValueInitProcessor(parser, s, end, nextPtr); |
|
3599 } |
|
3600 else { |
|
3601 processor = externalParEntProcessor; |
|
3602 return externalParEntProcessor(parser, s, end, nextPtr); |
|
3603 } |
|
3604 } |
|
3605 |
|
3606 static enum XML_Error PTRCALL |
|
3607 entityValueInitProcessor(XML_Parser parser, |
|
3608 const char *s, |
|
3609 const char *end, |
|
3610 const char **nextPtr) |
|
3611 { |
|
3612 int tok; |
|
3613 const char *start = s; |
|
3614 const char *next = start; |
|
3615 eventPtr = start; |
|
3616 |
|
3617 for (;;) { |
|
3618 tok = XmlPrologTok(encoding, start, end, &next); |
|
3619 eventEndPtr = next; |
|
3620 if (tok <= 0) { |
|
3621 if (!ps_finalBuffer && tok != XML_TOK_INVALID) { |
|
3622 *nextPtr = s; |
|
3623 return XML_ERROR_NONE; |
|
3624 } |
|
3625 switch (tok) { |
|
3626 case XML_TOK_INVALID: |
|
3627 return XML_ERROR_INVALID_TOKEN; |
|
3628 case XML_TOK_PARTIAL: |
|
3629 return XML_ERROR_UNCLOSED_TOKEN; |
|
3630 case XML_TOK_PARTIAL_CHAR: |
|
3631 return XML_ERROR_PARTIAL_CHAR; |
|
3632 case XML_TOK_NONE: /* start == end */ |
|
3633 default: |
|
3634 break; |
|
3635 } |
|
3636 /* found end of entity value - can store it now */ |
|
3637 return storeEntityValue(parser, encoding, s, end); |
|
3638 } |
|
3639 else if (tok == XML_TOK_XML_DECL) { |
|
3640 enum XML_Error result; |
|
3641 result = processXmlDecl(parser, 0, start, next); |
|
3642 if (result != XML_ERROR_NONE) |
|
3643 return result; |
|
3644 switch (ps_parsing) { |
|
3645 case XML_SUSPENDED: |
|
3646 *nextPtr = next; |
|
3647 return XML_ERROR_NONE; |
|
3648 case XML_FINISHED: |
|
3649 return XML_ERROR_ABORTED; |
|
3650 default: |
|
3651 *nextPtr = next; |
|
3652 } |
|
3653 /* stop scanning for text declaration - we found one */ |
|
3654 processor = entityValueProcessor; |
|
3655 return entityValueProcessor(parser, next, end, nextPtr); |
|
3656 } |
|
3657 /* If we are at the end of the buffer, this would cause XmlPrologTok to |
|
3658 return XML_TOK_NONE on the next call, which would then cause the |
|
3659 function to exit with *nextPtr set to s - that is what we want for other |
|
3660 tokens, but not for the BOM - we would rather like to skip it; |
|
3661 then, when this routine is entered the next time, XmlPrologTok will |
|
3662 return XML_TOK_INVALID, since the BOM is still in the buffer |
|
3663 */ |
|
3664 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) { |
|
3665 *nextPtr = next; |
|
3666 return XML_ERROR_NONE; |
|
3667 } |
|
3668 start = next; |
|
3669 eventPtr = start; |
|
3670 } |
|
3671 } |
|
3672 |
|
3673 static enum XML_Error PTRCALL |
|
3674 externalParEntProcessor(XML_Parser parser, |
|
3675 const char *s, |
|
3676 const char *end, |
|
3677 const char **nextPtr) |
|
3678 { |
|
3679 const char *next = s; |
|
3680 int tok; |
|
3681 |
|
3682 tok = XmlPrologTok(encoding, s, end, &next); |
|
3683 if (tok <= 0) { |
|
3684 if (!ps_finalBuffer && tok != XML_TOK_INVALID) { |
|
3685 *nextPtr = s; |
|
3686 return XML_ERROR_NONE; |
|
3687 } |
|
3688 switch (tok) { |
|
3689 case XML_TOK_INVALID: |
|
3690 return XML_ERROR_INVALID_TOKEN; |
|
3691 case XML_TOK_PARTIAL: |
|
3692 return XML_ERROR_UNCLOSED_TOKEN; |
|
3693 case XML_TOK_PARTIAL_CHAR: |
|
3694 return XML_ERROR_PARTIAL_CHAR; |
|
3695 case XML_TOK_NONE: /* start == end */ |
|
3696 default: |
|
3697 break; |
|
3698 } |
|
3699 } |
|
3700 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. |
|
3701 However, when parsing an external subset, doProlog will not accept a BOM |
|
3702 as valid, and report a syntax error, so we have to skip the BOM |
|
3703 */ |
|
3704 else if (tok == XML_TOK_BOM) { |
|
3705 s = next; |
|
3706 tok = XmlPrologTok(encoding, s, end, &next); |
|
3707 } |
|
3708 |
|
3709 processor = prologProcessor; |
|
3710 return doProlog(parser, encoding, s, end, tok, next, |
|
3711 nextPtr, (XML_Bool)!ps_finalBuffer); |
|
3712 } |
|
3713 |
|
3714 static enum XML_Error PTRCALL |
|
3715 entityValueProcessor(XML_Parser parser, |
|
3716 const char *s, |
|
3717 const char *end, |
|
3718 const char **nextPtr) |
|
3719 { |
|
3720 const char *start = s; |
|
3721 const char *next = s; |
|
3722 const ENCODING *enc = encoding; |
|
3723 int tok; |
|
3724 |
|
3725 for (;;) { |
|
3726 tok = XmlPrologTok(enc, start, end, &next); |
|
3727 if (tok <= 0) { |
|
3728 if (!ps_finalBuffer && tok != XML_TOK_INVALID) { |
|
3729 *nextPtr = s; |
|
3730 return XML_ERROR_NONE; |
|
3731 } |
|
3732 switch (tok) { |
|
3733 case XML_TOK_INVALID: |
|
3734 return XML_ERROR_INVALID_TOKEN; |
|
3735 case XML_TOK_PARTIAL: |
|
3736 return XML_ERROR_UNCLOSED_TOKEN; |
|
3737 case XML_TOK_PARTIAL_CHAR: |
|
3738 return XML_ERROR_PARTIAL_CHAR; |
|
3739 case XML_TOK_NONE: /* start == end */ |
|
3740 default: |
|
3741 break; |
|
3742 } |
|
3743 /* found end of entity value - can store it now */ |
|
3744 return storeEntityValue(parser, enc, s, end); |
|
3745 } |
|
3746 start = next; |
|
3747 } |
|
3748 } |
|
3749 |
|
3750 #endif /* XML_DTD */ |
|
3751 |
|
3752 static enum XML_Error PTRCALL |
|
3753 prologProcessor(XML_Parser parser, |
|
3754 const char *s, |
|
3755 const char *end, |
|
3756 const char **nextPtr) |
|
3757 { |
|
3758 const char *next = s; |
|
3759 int tok = XmlPrologTok(encoding, s, end, &next); |
|
3760 return doProlog(parser, encoding, s, end, tok, next, |
|
3761 nextPtr, (XML_Bool)!ps_finalBuffer); |
|
3762 } |
|
3763 |
|
3764 static enum XML_Error |
|
3765 doProlog(XML_Parser parser, |
|
3766 const ENCODING *enc, |
|
3767 const char *s, |
|
3768 const char *end, |
|
3769 int tok, |
|
3770 const char *next, |
|
3771 const char **nextPtr, |
|
3772 XML_Bool haveMore) |
|
3773 { |
|
3774 #ifdef XML_DTD |
|
3775 static const XML_Char externalSubsetName[] = { '#' , '\0' }; |
|
3776 #endif /* XML_DTD */ |
|
3777 static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' }; |
|
3778 static const XML_Char atypeID[] = { 'I', 'D', '\0' }; |
|
3779 static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' }; |
|
3780 static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' }; |
|
3781 static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' }; |
|
3782 static const XML_Char atypeENTITIES[] = |
|
3783 { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' }; |
|
3784 static const XML_Char atypeNMTOKEN[] = { |
|
3785 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' }; |
|
3786 static const XML_Char atypeNMTOKENS[] = { |
|
3787 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' }; |
|
3788 static const XML_Char notationPrefix[] = { |
|
3789 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' }; |
|
3790 static const XML_Char enumValueSep[] = { '|', '\0' }; |
|
3791 static const XML_Char enumValueStart[] = { '(', '\0' }; |
|
3792 |
|
3793 /* save one level of indirection */ |
|
3794 DTD * const dtd = _dtd; |
|
3795 |
|
3796 const char **eventPP; |
|
3797 const char **eventEndPP; |
|
3798 enum XML_Content_Quant quant; |
|
3799 |
|
3800 if (enc == encoding) { |
|
3801 eventPP = &eventPtr; |
|
3802 eventEndPP = &eventEndPtr; |
|
3803 } |
|
3804 else { |
|
3805 eventPP = &(openInternalEntities->internalEventPtr); |
|
3806 eventEndPP = &(openInternalEntities->internalEventEndPtr); |
|
3807 } |
|
3808 |
|
3809 for (;;) { |
|
3810 int role; |
|
3811 XML_Bool handleDefault = XML_TRUE; |
|
3812 *eventPP = s; |
|
3813 *eventEndPP = next; |
|
3814 if (tok <= 0) { |
|
3815 if (haveMore && tok != XML_TOK_INVALID) { |
|
3816 *nextPtr = s; |
|
3817 return XML_ERROR_NONE; |
|
3818 } |
|
3819 switch (tok) { |
|
3820 case XML_TOK_INVALID: |
|
3821 *eventPP = next; |
|
3822 return XML_ERROR_INVALID_TOKEN; |
|
3823 case XML_TOK_PARTIAL: |
|
3824 return XML_ERROR_UNCLOSED_TOKEN; |
|
3825 case XML_TOK_PARTIAL_CHAR: |
|
3826 return XML_ERROR_PARTIAL_CHAR; |
|
3827 case XML_TOK_NONE: |
|
3828 #ifdef XML_DTD |
|
3829 /* for internal PE NOT referenced between declarations */ |
|
3830 if (enc != encoding && !openInternalEntities->betweenDecl) { |
|
3831 *nextPtr = s; |
|
3832 return XML_ERROR_NONE; |
|
3833 } |
|
3834 /* WFC: PE Between Declarations - must check that PE contains |
|
3835 complete markup, not only for external PEs, but also for |
|
3836 internal PEs if the reference occurs between declarations. |
|
3837 */ |
|
3838 if (isParamEntity || enc != encoding) { |
|
3839 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) |
|
3840 == XML_ROLE_ERROR) |
|
3841 return XML_ERROR_INCOMPLETE_PE; |
|
3842 *nextPtr = s; |
|
3843 return XML_ERROR_NONE; |
|
3844 } |
|
3845 #endif /* XML_DTD */ |
|
3846 return XML_ERROR_NO_ELEMENTS; |
|
3847 default: |
|
3848 tok = -tok; |
|
3849 next = end; |
|
3850 break; |
|
3851 } |
|
3852 } |
|
3853 role = XmlTokenRole(&prologState, tok, s, next, enc); |
|
3854 switch (role) { |
|
3855 case XML_ROLE_XML_DECL: |
|
3856 { |
|
3857 enum XML_Error result = processXmlDecl(parser, 0, s, next); |
|
3858 if (result != XML_ERROR_NONE) |
|
3859 return result; |
|
3860 enc = encoding; |
|
3861 handleDefault = XML_FALSE; |
|
3862 } |
|
3863 break; |
|
3864 case XML_ROLE_DOCTYPE_NAME: |
|
3865 if (startDoctypeDeclHandler) { |
|
3866 doctypeName = poolStoreString(&tempPool, enc, s, next); |
|
3867 if (!doctypeName) |
|
3868 return XML_ERROR_NO_MEMORY; |
|
3869 poolFinish(&tempPool); |
|
3870 doctypePubid = NULL; |
|
3871 handleDefault = XML_FALSE; |
|
3872 } |
|
3873 doctypeSysid = NULL; /* always initialize to NULL */ |
|
3874 break; |
|
3875 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: |
|
3876 if (startDoctypeDeclHandler) { |
|
3877 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, |
|
3878 doctypePubid, 1); |
|
3879 doctypeName = NULL; |
|
3880 poolClear(&tempPool); |
|
3881 handleDefault = XML_FALSE; |
|
3882 } |
|
3883 break; |
|
3884 #ifdef XML_DTD |
|
3885 case XML_ROLE_TEXT_DECL: |
|
3886 { |
|
3887 enum XML_Error result = processXmlDecl(parser, 1, s, next); |
|
3888 if (result != XML_ERROR_NONE) |
|
3889 return result; |
|
3890 enc = encoding; |
|
3891 handleDefault = XML_FALSE; |
|
3892 } |
|
3893 break; |
|
3894 #endif /* XML_DTD */ |
|
3895 case XML_ROLE_DOCTYPE_PUBLIC_ID: |
|
3896 #ifdef XML_DTD |
|
3897 useForeignDTD = XML_FALSE; |
|
3898 declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
|
3899 externalSubsetName, |
|
3900 sizeof(ENTITY)); |
|
3901 if (!declEntity) |
|
3902 return XML_ERROR_NO_MEMORY; |
|
3903 #endif /* XML_DTD */ |
|
3904 dtd->hasParamEntityRefs = XML_TRUE; |
|
3905 if (startDoctypeDeclHandler) { |
|
3906 if (!XmlIsPublicId(enc, s, next, eventPP)) |
|
3907 return XML_ERROR_PUBLICID; |
|
3908 doctypePubid = poolStoreString(&tempPool, enc, |
|
3909 s + enc->minBytesPerChar, |
|
3910 next - enc->minBytesPerChar); |
|
3911 if (!doctypePubid) |
|
3912 return XML_ERROR_NO_MEMORY; |
|
3913 normalizePublicId((XML_Char *)doctypePubid); |
|
3914 poolFinish(&tempPool); |
|
3915 handleDefault = XML_FALSE; |
|
3916 goto alreadyChecked; |
|
3917 } |
|
3918 /* fall through */ |
|
3919 case XML_ROLE_ENTITY_PUBLIC_ID: |
|
3920 if (!XmlIsPublicId(enc, s, next, eventPP)) |
|
3921 return XML_ERROR_PUBLICID; |
|
3922 alreadyChecked: |
|
3923 if (dtd->keepProcessing && declEntity) { |
|
3924 XML_Char *tem = poolStoreString(&dtd->pool, |
|
3925 enc, |
|
3926 s + enc->minBytesPerChar, |
|
3927 next - enc->minBytesPerChar); |
|
3928 if (!tem) |
|
3929 return XML_ERROR_NO_MEMORY; |
|
3930 normalizePublicId(tem); |
|
3931 declEntity->publicId = tem; |
|
3932 poolFinish(&dtd->pool); |
|
3933 if (entityDeclHandler) |
|
3934 handleDefault = XML_FALSE; |
|
3935 } |
|
3936 break; |
|
3937 case XML_ROLE_DOCTYPE_CLOSE: |
|
3938 if (doctypeName) { |
|
3939 startDoctypeDeclHandler(handlerArg, doctypeName, |
|
3940 doctypeSysid, doctypePubid, 0); |
|
3941 poolClear(&tempPool); |
|
3942 handleDefault = XML_FALSE; |
|
3943 } |
|
3944 /* doctypeSysid will be non-NULL in the case of a previous |
|
3945 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler |
|
3946 was not set, indicating an external subset |
|
3947 */ |
|
3948 #ifdef XML_DTD |
|
3949 if (doctypeSysid || useForeignDTD) { |
|
3950 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; |
|
3951 dtd->hasParamEntityRefs = XML_TRUE; |
|
3952 if (paramEntityParsing && externalEntityRefHandler) { |
|
3953 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, |
|
3954 externalSubsetName, |
|
3955 sizeof(ENTITY)); |
|
3956 if (!entity) |
|
3957 return XML_ERROR_NO_MEMORY; |
|
3958 if (useForeignDTD) |
|
3959 entity->base = curBase; |
|
3960 dtd->paramEntityRead = XML_FALSE; |
|
3961 if (!externalEntityRefHandler(externalEntityRefHandlerArg, |
|
3962 0, |
|
3963 entity->base, |
|
3964 entity->systemId, |
|
3965 entity->publicId)) |
|
3966 return XML_ERROR_EXTERNAL_ENTITY_HANDLING; |
|
3967 if (dtd->paramEntityRead) { |
|
3968 if (!dtd->standalone && |
|
3969 notStandaloneHandler && |
|
3970 !notStandaloneHandler(handlerArg)) |
|
3971 return XML_ERROR_NOT_STANDALONE; |
|
3972 } |
|
3973 /* if we didn't read the foreign DTD then this means that there |
|
3974 is no external subset and we must reset dtd->hasParamEntityRefs |
|
3975 */ |
|
3976 else if (!doctypeSysid) |
|
3977 dtd->hasParamEntityRefs = hadParamEntityRefs; |
|
3978 /* end of DTD - no need to update dtd->keepProcessing */ |
|
3979 } |
|
3980 useForeignDTD = XML_FALSE; |
|
3981 } |
|
3982 #endif /* XML_DTD */ |
|
3983 if (endDoctypeDeclHandler) { |
|
3984 endDoctypeDeclHandler(handlerArg); |
|
3985 handleDefault = XML_FALSE; |
|
3986 } |
|
3987 break; |
|
3988 case XML_ROLE_INSTANCE_START: |
|
3989 #ifdef XML_DTD |
|
3990 /* if there is no DOCTYPE declaration then now is the |
|
3991 last chance to read the foreign DTD |
|
3992 */ |
|
3993 if (useForeignDTD) { |
|
3994 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; |
|
3995 dtd->hasParamEntityRefs = XML_TRUE; |
|
3996 if (paramEntityParsing && externalEntityRefHandler) { |
|
3997 ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, |
|
3998 externalSubsetName, |
|
3999 sizeof(ENTITY)); |
|
4000 if (!entity) |
|
4001 return XML_ERROR_NO_MEMORY; |
|
4002 entity->base = curBase; |
|
4003 dtd->paramEntityRead = XML_FALSE; |
|
4004 if (!externalEntityRefHandler(externalEntityRefHandlerArg, |
|
4005 0, |
|
4006 entity->base, |
|
4007 entity->systemId, |
|
4008 entity->publicId)) |
|
4009 return XML_ERROR_EXTERNAL_ENTITY_HANDLING; |
|
4010 if (dtd->paramEntityRead) { |
|
4011 if (!dtd->standalone && |
|
4012 notStandaloneHandler && |
|
4013 !notStandaloneHandler(handlerArg)) |
|
4014 return XML_ERROR_NOT_STANDALONE; |
|
4015 } |
|
4016 /* if we didn't read the foreign DTD then this means that there |
|
4017 is no external subset and we must reset dtd->hasParamEntityRefs |
|
4018 */ |
|
4019 else |
|
4020 dtd->hasParamEntityRefs = hadParamEntityRefs; |
|
4021 /* end of DTD - no need to update dtd->keepProcessing */ |
|
4022 } |
|
4023 } |
|
4024 #endif /* XML_DTD */ |
|
4025 processor = contentProcessor; |
|
4026 return contentProcessor(parser, s, end, nextPtr); |
|
4027 case XML_ROLE_ATTLIST_ELEMENT_NAME: |
|
4028 declElementType = getElementType(parser, enc, s, next); |
|
4029 if (!declElementType) |
|
4030 return XML_ERROR_NO_MEMORY; |
|
4031 goto checkAttListDeclHandler; |
|
4032 case XML_ROLE_ATTRIBUTE_NAME: |
|
4033 declAttributeId = getAttributeId(parser, enc, s, next); |
|
4034 if (!declAttributeId) |
|
4035 return XML_ERROR_NO_MEMORY; |
|
4036 declAttributeIsCdata = XML_FALSE; |
|
4037 declAttributeType = NULL; |
|
4038 declAttributeIsId = XML_FALSE; |
|
4039 goto checkAttListDeclHandler; |
|
4040 case XML_ROLE_ATTRIBUTE_TYPE_CDATA: |
|
4041 declAttributeIsCdata = XML_TRUE; |
|
4042 declAttributeType = atypeCDATA; |
|
4043 goto checkAttListDeclHandler; |
|
4044 case XML_ROLE_ATTRIBUTE_TYPE_ID: |
|
4045 declAttributeIsId = XML_TRUE; |
|
4046 declAttributeType = atypeID; |
|
4047 goto checkAttListDeclHandler; |
|
4048 case XML_ROLE_ATTRIBUTE_TYPE_IDREF: |
|
4049 declAttributeType = atypeIDREF; |
|
4050 goto checkAttListDeclHandler; |
|
4051 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: |
|
4052 declAttributeType = atypeIDREFS; |
|
4053 goto checkAttListDeclHandler; |
|
4054 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: |
|
4055 declAttributeType = atypeENTITY; |
|
4056 goto checkAttListDeclHandler; |
|
4057 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: |
|
4058 declAttributeType = atypeENTITIES; |
|
4059 goto checkAttListDeclHandler; |
|
4060 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: |
|
4061 declAttributeType = atypeNMTOKEN; |
|
4062 goto checkAttListDeclHandler; |
|
4063 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: |
|
4064 declAttributeType = atypeNMTOKENS; |
|
4065 checkAttListDeclHandler: |
|
4066 if (dtd->keepProcessing && attlistDeclHandler) |
|
4067 handleDefault = XML_FALSE; |
|
4068 break; |
|
4069 case XML_ROLE_ATTRIBUTE_ENUM_VALUE: |
|
4070 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: |
|
4071 if (dtd->keepProcessing && attlistDeclHandler) { |
|
4072 const XML_Char *prefix; |
|
4073 if (declAttributeType) { |
|
4074 prefix = enumValueSep; |
|
4075 } |
|
4076 else { |
|
4077 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE |
|
4078 ? notationPrefix |
|
4079 : enumValueStart); |
|
4080 } |
|
4081 if (!poolAppendString(&tempPool, prefix)) |
|
4082 return XML_ERROR_NO_MEMORY; |
|
4083 if (!poolAppend(&tempPool, enc, s, next)) |
|
4084 return XML_ERROR_NO_MEMORY; |
|
4085 declAttributeType = tempPool.start; |
|
4086 handleDefault = XML_FALSE; |
|
4087 } |
|
4088 break; |
|
4089 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: |
|
4090 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: |
|
4091 if (dtd->keepProcessing) { |
|
4092 if (!defineAttribute(declElementType, declAttributeId, |
|
4093 declAttributeIsCdata, declAttributeIsId, |
|
4094 0, parser)) |
|
4095 return XML_ERROR_NO_MEMORY; |
|
4096 if (attlistDeclHandler && declAttributeType) { |
|
4097 if (*declAttributeType == XML_T('(') |
|
4098 || (*declAttributeType == XML_T('N') |
|
4099 && declAttributeType[1] == XML_T('O'))) { |
|
4100 /* Enumerated or Notation type */ |
|
4101 if (!poolAppendChar(&tempPool, XML_T(')')) |
|
4102 || !poolAppendChar(&tempPool, XML_T('\0'))) |
|
4103 return XML_ERROR_NO_MEMORY; |
|
4104 declAttributeType = tempPool.start; |
|
4105 poolFinish(&tempPool); |
|
4106 } |
|
4107 *eventEndPP = s; |
|
4108 attlistDeclHandler(handlerArg, declElementType->name, |
|
4109 declAttributeId->name, declAttributeType, |
|
4110 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); |
|
4111 poolClear(&tempPool); |
|
4112 handleDefault = XML_FALSE; |
|
4113 } |
|
4114 } |
|
4115 break; |
|
4116 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: |
|
4117 case XML_ROLE_FIXED_ATTRIBUTE_VALUE: |
|
4118 if (dtd->keepProcessing) { |
|
4119 const XML_Char *attVal; |
|
4120 enum XML_Error result = |
|
4121 storeAttributeValue(parser, enc, declAttributeIsCdata, |
|
4122 s + enc->minBytesPerChar, |
|
4123 next - enc->minBytesPerChar, |
|
4124 &dtd->pool); |
|
4125 if (result) |
|
4126 return result; |
|
4127 attVal = poolStart(&dtd->pool); |
|
4128 poolFinish(&dtd->pool); |
|
4129 /* ID attributes aren't allowed to have a default */ |
|
4130 if (!defineAttribute(declElementType, declAttributeId, |
|
4131 declAttributeIsCdata, XML_FALSE, attVal, parser)) |
|
4132 return XML_ERROR_NO_MEMORY; |
|
4133 if (attlistDeclHandler && declAttributeType) { |
|
4134 if (*declAttributeType == XML_T('(') |
|
4135 || (*declAttributeType == XML_T('N') |
|
4136 && declAttributeType[1] == XML_T('O'))) { |
|
4137 /* Enumerated or Notation type */ |
|
4138 if (!poolAppendChar(&tempPool, XML_T(')')) |
|
4139 || !poolAppendChar(&tempPool, XML_T('\0'))) |
|
4140 return XML_ERROR_NO_MEMORY; |
|
4141 declAttributeType = tempPool.start; |
|
4142 poolFinish(&tempPool); |
|
4143 } |
|
4144 *eventEndPP = s; |
|
4145 attlistDeclHandler(handlerArg, declElementType->name, |
|
4146 declAttributeId->name, declAttributeType, |
|
4147 attVal, |
|
4148 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); |
|
4149 poolClear(&tempPool); |
|
4150 handleDefault = XML_FALSE; |
|
4151 } |
|
4152 } |
|
4153 break; |
|
4154 case XML_ROLE_ENTITY_VALUE: |
|
4155 if (dtd->keepProcessing) { |
|
4156 enum XML_Error result = storeEntityValue(parser, enc, |
|
4157 s + enc->minBytesPerChar, |
|
4158 next - enc->minBytesPerChar); |
|
4159 if (declEntity) { |
|
4160 declEntity->textPtr = poolStart(&dtd->entityValuePool); |
|
4161 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool)); |
|
4162 poolFinish(&dtd->entityValuePool); |
|
4163 if (entityDeclHandler) { |
|
4164 *eventEndPP = s; |
|
4165 entityDeclHandler(handlerArg, |
|
4166 declEntity->name, |
|
4167 declEntity->is_param, |
|
4168 declEntity->textPtr, |
|
4169 declEntity->textLen, |
|
4170 curBase, 0, 0, 0); |
|
4171 handleDefault = XML_FALSE; |
|
4172 } |
|
4173 } |
|
4174 else |
|
4175 poolDiscard(&dtd->entityValuePool); |
|
4176 if (result != XML_ERROR_NONE) |
|
4177 return result; |
|
4178 } |
|
4179 break; |
|
4180 case XML_ROLE_DOCTYPE_SYSTEM_ID: |
|
4181 #ifdef XML_DTD |
|
4182 useForeignDTD = XML_FALSE; |
|
4183 #endif /* XML_DTD */ |
|
4184 dtd->hasParamEntityRefs = XML_TRUE; |
|
4185 if (startDoctypeDeclHandler) { |
|
4186 doctypeSysid = poolStoreString(&tempPool, enc, |
|
4187 s + enc->minBytesPerChar, |
|
4188 next - enc->minBytesPerChar); |
|
4189 if (doctypeSysid == NULL) |
|
4190 return XML_ERROR_NO_MEMORY; |
|
4191 poolFinish(&tempPool); |
|
4192 handleDefault = XML_FALSE; |
|
4193 } |
|
4194 #ifdef XML_DTD |
|
4195 else |
|
4196 /* use externalSubsetName to make doctypeSysid non-NULL |
|
4197 for the case where no startDoctypeDeclHandler is set */ |
|
4198 doctypeSysid = externalSubsetName; |
|
4199 #endif /* XML_DTD */ |
|
4200 if (!dtd->standalone |
|
4201 #ifdef XML_DTD |
|
4202 && !paramEntityParsing |
|
4203 #endif /* XML_DTD */ |
|
4204 && notStandaloneHandler |
|
4205 && !notStandaloneHandler(handlerArg)) |
|
4206 return XML_ERROR_NOT_STANDALONE; |
|
4207 #ifndef XML_DTD |
|
4208 break; |
|
4209 #else /* XML_DTD */ |
|
4210 if (!declEntity) { |
|
4211 declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
|
4212 externalSubsetName, |
|
4213 sizeof(ENTITY)); |
|
4214 if (!declEntity) |
|
4215 return XML_ERROR_NO_MEMORY; |
|
4216 declEntity->publicId = NULL; |
|
4217 } |
|
4218 /* fall through */ |
|
4219 #endif /* XML_DTD */ |
|
4220 case XML_ROLE_ENTITY_SYSTEM_ID: |
|
4221 if (dtd->keepProcessing && declEntity) { |
|
4222 declEntity->systemId = poolStoreString(&dtd->pool, enc, |
|
4223 s + enc->minBytesPerChar, |
|
4224 next - enc->minBytesPerChar); |
|
4225 if (!declEntity->systemId) |
|
4226 return XML_ERROR_NO_MEMORY; |
|
4227 declEntity->base = curBase; |
|
4228 poolFinish(&dtd->pool); |
|
4229 if (entityDeclHandler) |
|
4230 handleDefault = XML_FALSE; |
|
4231 } |
|
4232 break; |
|
4233 case XML_ROLE_ENTITY_COMPLETE: |
|
4234 if (dtd->keepProcessing && declEntity && entityDeclHandler) { |
|
4235 *eventEndPP = s; |
|
4236 entityDeclHandler(handlerArg, |
|
4237 declEntity->name, |
|
4238 declEntity->is_param, |
|
4239 0,0, |
|
4240 declEntity->base, |
|
4241 declEntity->systemId, |
|
4242 declEntity->publicId, |
|
4243 0); |
|
4244 handleDefault = XML_FALSE; |
|
4245 } |
|
4246 break; |
|
4247 case XML_ROLE_ENTITY_NOTATION_NAME: |
|
4248 if (dtd->keepProcessing && declEntity) { |
|
4249 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); |
|
4250 if (!declEntity->notation) |
|
4251 return XML_ERROR_NO_MEMORY; |
|
4252 poolFinish(&dtd->pool); |
|
4253 if (unparsedEntityDeclHandler) { |
|
4254 *eventEndPP = s; |
|
4255 unparsedEntityDeclHandler(handlerArg, |
|
4256 declEntity->name, |
|
4257 declEntity->base, |
|
4258 declEntity->systemId, |
|
4259 declEntity->publicId, |
|
4260 declEntity->notation); |
|
4261 handleDefault = XML_FALSE; |
|
4262 } |
|
4263 else if (entityDeclHandler) { |
|
4264 *eventEndPP = s; |
|
4265 entityDeclHandler(handlerArg, |
|
4266 declEntity->name, |
|
4267 0,0,0, |
|
4268 declEntity->base, |
|
4269 declEntity->systemId, |
|
4270 declEntity->publicId, |
|
4271 declEntity->notation); |
|
4272 handleDefault = XML_FALSE; |
|
4273 } |
|
4274 } |
|
4275 break; |
|
4276 case XML_ROLE_GENERAL_ENTITY_NAME: |
|
4277 { |
|
4278 if (XmlPredefinedEntityName(enc, s, next)) { |
|
4279 declEntity = NULL; |
|
4280 break; |
|
4281 } |
|
4282 if (dtd->keepProcessing) { |
|
4283 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); |
|
4284 if (!name) |
|
4285 return XML_ERROR_NO_MEMORY; |
|
4286 declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, |
|
4287 sizeof(ENTITY)); |
|
4288 if (!declEntity) |
|
4289 return XML_ERROR_NO_MEMORY; |
|
4290 if (declEntity->name != name) { |
|
4291 poolDiscard(&dtd->pool); |
|
4292 declEntity = NULL; |
|
4293 } |
|
4294 else { |
|
4295 poolFinish(&dtd->pool); |
|
4296 declEntity->publicId = NULL; |
|
4297 declEntity->is_param = XML_FALSE; |
|
4298 /* if we have a parent parser or are reading an internal parameter |
|
4299 entity, then the entity declaration is not considered "internal" |
|
4300 */ |
|
4301 declEntity->is_internal = !(parentParser || openInternalEntities); |
|
4302 if (entityDeclHandler) |
|
4303 handleDefault = XML_FALSE; |
|
4304 } |
|
4305 } |
|
4306 else { |
|
4307 poolDiscard(&dtd->pool); |
|
4308 declEntity = NULL; |
|
4309 } |
|
4310 } |
|
4311 break; |
|
4312 case XML_ROLE_PARAM_ENTITY_NAME: |
|
4313 #ifdef XML_DTD |
|
4314 if (dtd->keepProcessing) { |
|
4315 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); |
|
4316 if (!name) |
|
4317 return XML_ERROR_NO_MEMORY; |
|
4318 declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
|
4319 name, sizeof(ENTITY)); |
|
4320 if (!declEntity) |
|
4321 return XML_ERROR_NO_MEMORY; |
|
4322 if (declEntity->name != name) { |
|
4323 poolDiscard(&dtd->pool); |
|
4324 declEntity = NULL; |
|
4325 } |
|
4326 else { |
|
4327 poolFinish(&dtd->pool); |
|
4328 declEntity->publicId = NULL; |
|
4329 declEntity->is_param = XML_TRUE; |
|
4330 /* if we have a parent parser or are reading an internal parameter |
|
4331 entity, then the entity declaration is not considered "internal" |
|
4332 */ |
|
4333 declEntity->is_internal = !(parentParser || openInternalEntities); |
|
4334 if (entityDeclHandler) |
|
4335 handleDefault = XML_FALSE; |
|
4336 } |
|
4337 } |
|
4338 else { |
|
4339 poolDiscard(&dtd->pool); |
|
4340 declEntity = NULL; |
|
4341 } |
|
4342 #else /* not XML_DTD */ |
|
4343 declEntity = NULL; |
|
4344 #endif /* XML_DTD */ |
|
4345 break; |
|
4346 case XML_ROLE_NOTATION_NAME: |
|
4347 declNotationPublicId = NULL; |
|
4348 declNotationName = NULL; |
|
4349 if (notationDeclHandler) { |
|
4350 declNotationName = poolStoreString(&tempPool, enc, s, next); |
|
4351 if (!declNotationName) |
|
4352 return XML_ERROR_NO_MEMORY; |
|
4353 poolFinish(&tempPool); |
|
4354 handleDefault = XML_FALSE; |
|
4355 } |
|
4356 break; |
|
4357 case XML_ROLE_NOTATION_PUBLIC_ID: |
|
4358 if (!XmlIsPublicId(enc, s, next, eventPP)) |
|
4359 return XML_ERROR_PUBLICID; |
|
4360 if (declNotationName) { /* means notationDeclHandler != NULL */ |
|
4361 XML_Char *tem = poolStoreString(&tempPool, |
|
4362 enc, |
|
4363 s + enc->minBytesPerChar, |
|
4364 next - enc->minBytesPerChar); |
|
4365 if (!tem) |
|
4366 return XML_ERROR_NO_MEMORY; |
|
4367 normalizePublicId(tem); |
|
4368 declNotationPublicId = tem; |
|
4369 poolFinish(&tempPool); |
|
4370 handleDefault = XML_FALSE; |
|
4371 } |
|
4372 break; |
|
4373 case XML_ROLE_NOTATION_SYSTEM_ID: |
|
4374 if (declNotationName && notationDeclHandler) { |
|
4375 const XML_Char *systemId |
|
4376 = poolStoreString(&tempPool, enc, |
|
4377 s + enc->minBytesPerChar, |
|
4378 next - enc->minBytesPerChar); |
|
4379 if (!systemId) |
|
4380 return XML_ERROR_NO_MEMORY; |
|
4381 *eventEndPP = s; |
|
4382 notationDeclHandler(handlerArg, |
|
4383 declNotationName, |
|
4384 curBase, |
|
4385 systemId, |
|
4386 declNotationPublicId); |
|
4387 handleDefault = XML_FALSE; |
|
4388 } |
|
4389 poolClear(&tempPool); |
|
4390 break; |
|
4391 case XML_ROLE_NOTATION_NO_SYSTEM_ID: |
|
4392 if (declNotationPublicId && notationDeclHandler) { |
|
4393 *eventEndPP = s; |
|
4394 notationDeclHandler(handlerArg, |
|
4395 declNotationName, |
|
4396 curBase, |
|
4397 0, |
|
4398 declNotationPublicId); |
|
4399 handleDefault = XML_FALSE; |
|
4400 } |
|
4401 poolClear(&tempPool); |
|
4402 break; |
|
4403 case XML_ROLE_ERROR: |
|
4404 switch (tok) { |
|
4405 case XML_TOK_PARAM_ENTITY_REF: |
|
4406 /* PE references in internal subset are |
|
4407 not allowed within declarations. */ |
|
4408 return XML_ERROR_PARAM_ENTITY_REF; |
|
4409 case XML_TOK_XML_DECL: |
|
4410 return XML_ERROR_MISPLACED_XML_PI; |
|
4411 default: |
|
4412 return XML_ERROR_SYNTAX; |
|
4413 } |
|
4414 #ifdef XML_DTD |
|
4415 case XML_ROLE_IGNORE_SECT: |
|
4416 { |
|
4417 enum XML_Error result; |
|
4418 if (defaultHandler) |
|
4419 reportDefault(parser, enc, s, next); |
|
4420 handleDefault = XML_FALSE; |
|
4421 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); |
|
4422 if (result != XML_ERROR_NONE) |
|
4423 return result; |
|
4424 else if (!next) { |
|
4425 processor = ignoreSectionProcessor; |
|
4426 return result; |
|
4427 } |
|
4428 } |
|
4429 break; |
|
4430 #endif /* XML_DTD */ |
|
4431 case XML_ROLE_GROUP_OPEN: |
|
4432 if (prologState.level >= groupSize) { |
|
4433 if (groupSize) { |
|
4434 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); |
|
4435 if (temp == NULL) |
|
4436 return XML_ERROR_NO_MEMORY; |
|
4437 groupConnector = temp; |
|
4438 if (dtd->scaffIndex) { |
|
4439 int *temp = (int *)REALLOC(dtd->scaffIndex, |
|
4440 groupSize * sizeof(int)); |
|
4441 if (temp == NULL) |
|
4442 return XML_ERROR_NO_MEMORY; |
|
4443 dtd->scaffIndex = temp; |
|
4444 } |
|
4445 } |
|
4446 else { |
|
4447 groupConnector = (char *)MALLOC(groupSize = 32); |
|
4448 if (!groupConnector) |
|
4449 return XML_ERROR_NO_MEMORY; |
|
4450 } |
|
4451 } |
|
4452 groupConnector[prologState.level] = 0; |
|
4453 if (dtd->in_eldecl) { |
|
4454 int myindex = nextScaffoldPart(parser); |
|
4455 if (myindex < 0) |
|
4456 return XML_ERROR_NO_MEMORY; |
|
4457 dtd->scaffIndex[dtd->scaffLevel] = myindex; |
|
4458 dtd->scaffLevel++; |
|
4459 dtd->scaffold[myindex].type = XML_CTYPE_SEQ; |
|
4460 if (elementDeclHandler) |
|
4461 handleDefault = XML_FALSE; |
|
4462 } |
|
4463 break; |
|
4464 case XML_ROLE_GROUP_SEQUENCE: |
|
4465 if (groupConnector[prologState.level] == '|') |
|
4466 return XML_ERROR_SYNTAX; |
|
4467 groupConnector[prologState.level] = ','; |
|
4468 if (dtd->in_eldecl && elementDeclHandler) |
|
4469 handleDefault = XML_FALSE; |
|
4470 break; |
|
4471 case XML_ROLE_GROUP_CHOICE: |
|
4472 if (groupConnector[prologState.level] == ',') |
|
4473 return XML_ERROR_SYNTAX; |
|
4474 if (dtd->in_eldecl |
|
4475 && !groupConnector[prologState.level] |
|
4476 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type |
|
4477 != XML_CTYPE_MIXED) |
|
4478 ) { |
|
4479 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type |
|
4480 = XML_CTYPE_CHOICE; |
|
4481 if (elementDeclHandler) |
|
4482 handleDefault = XML_FALSE; |
|
4483 } |
|
4484 groupConnector[prologState.level] = '|'; |
|
4485 break; |
|
4486 case XML_ROLE_PARAM_ENTITY_REF: |
|
4487 #ifdef XML_DTD |
|
4488 case XML_ROLE_INNER_PARAM_ENTITY_REF: |
|
4489 dtd->hasParamEntityRefs = XML_TRUE; |
|
4490 if (!paramEntityParsing) |
|
4491 dtd->keepProcessing = dtd->standalone; |
|
4492 else { |
|
4493 const XML_Char *name; |
|
4494 ENTITY *entity; |
|
4495 name = poolStoreString(&dtd->pool, enc, |
|
4496 s + enc->minBytesPerChar, |
|
4497 next - enc->minBytesPerChar); |
|
4498 if (!name) |
|
4499 return XML_ERROR_NO_MEMORY; |
|
4500 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); |
|
4501 poolDiscard(&dtd->pool); |
|
4502 /* first, determine if a check for an existing declaration is needed; |
|
4503 if yes, check that the entity exists, and that it is internal, |
|
4504 otherwise call the skipped entity handler |
|
4505 */ |
|
4506 if (prologState.documentEntity && |
|
4507 (dtd->standalone |
|
4508 ? !openInternalEntities |
|
4509 : !dtd->hasParamEntityRefs)) { |
|
4510 if (!entity) |
|
4511 return XML_ERROR_UNDEFINED_ENTITY; |
|
4512 else if (!entity->is_internal) |
|
4513 return XML_ERROR_ENTITY_DECLARED_IN_PE; |
|
4514 } |
|
4515 else if (!entity) { |
|
4516 dtd->keepProcessing = dtd->standalone; |
|
4517 /* cannot report skipped entities in declarations */ |
|
4518 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) { |
|
4519 skippedEntityHandler(handlerArg, name, 1); |
|
4520 handleDefault = XML_FALSE; |
|
4521 } |
|
4522 break; |
|
4523 } |
|
4524 if (entity->open) |
|
4525 return XML_ERROR_RECURSIVE_ENTITY_REF; |
|
4526 if (entity->textPtr) { |
|
4527 enum XML_Error result; |
|
4528 XML_Bool betweenDecl = |
|
4529 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); |
|
4530 result = processInternalEntity(parser, entity, betweenDecl); |
|
4531 if (result != XML_ERROR_NONE) |
|
4532 return result; |
|
4533 handleDefault = XML_FALSE; |
|
4534 break; |
|
4535 } |
|
4536 if (externalEntityRefHandler) { |
|
4537 dtd->paramEntityRead = XML_FALSE; |
|
4538 entity->open = XML_TRUE; |
|
4539 if (!externalEntityRefHandler(externalEntityRefHandlerArg, |
|
4540 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=191482) */ |
|
4541 #if 0 |
|
4542 0, |
|
4543 #else |
|
4544 entity->name, |
|
4545 #endif |
|
4546 /* END MOZILLA CHANGE */ |
|
4547 entity->base, |
|
4548 entity->systemId, |
|
4549 entity->publicId)) { |
|
4550 entity->open = XML_FALSE; |
|
4551 return XML_ERROR_EXTERNAL_ENTITY_HANDLING; |
|
4552 } |
|
4553 entity->open = XML_FALSE; |
|
4554 handleDefault = XML_FALSE; |
|
4555 if (!dtd->paramEntityRead) { |
|
4556 dtd->keepProcessing = dtd->standalone; |
|
4557 break; |
|
4558 } |
|
4559 } |
|
4560 else { |
|
4561 dtd->keepProcessing = dtd->standalone; |
|
4562 break; |
|
4563 } |
|
4564 } |
|
4565 #endif /* XML_DTD */ |
|
4566 if (!dtd->standalone && |
|
4567 notStandaloneHandler && |
|
4568 !notStandaloneHandler(handlerArg)) |
|
4569 return XML_ERROR_NOT_STANDALONE; |
|
4570 break; |
|
4571 |
|
4572 /* Element declaration stuff */ |
|
4573 |
|
4574 case XML_ROLE_ELEMENT_NAME: |
|
4575 if (elementDeclHandler) { |
|
4576 declElementType = getElementType(parser, enc, s, next); |
|
4577 if (!declElementType) |
|
4578 return XML_ERROR_NO_MEMORY; |
|
4579 dtd->scaffLevel = 0; |
|
4580 dtd->scaffCount = 0; |
|
4581 dtd->in_eldecl = XML_TRUE; |
|
4582 handleDefault = XML_FALSE; |
|
4583 } |
|
4584 break; |
|
4585 |
|
4586 case XML_ROLE_CONTENT_ANY: |
|
4587 case XML_ROLE_CONTENT_EMPTY: |
|
4588 if (dtd->in_eldecl) { |
|
4589 if (elementDeclHandler) { |
|
4590 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); |
|
4591 if (!content) |
|
4592 return XML_ERROR_NO_MEMORY; |
|
4593 content->quant = XML_CQUANT_NONE; |
|
4594 content->name = NULL; |
|
4595 content->numchildren = 0; |
|
4596 content->children = NULL; |
|
4597 content->type = ((role == XML_ROLE_CONTENT_ANY) ? |
|
4598 XML_CTYPE_ANY : |
|
4599 XML_CTYPE_EMPTY); |
|
4600 *eventEndPP = s; |
|
4601 elementDeclHandler(handlerArg, declElementType->name, content); |
|
4602 handleDefault = XML_FALSE; |
|
4603 } |
|
4604 dtd->in_eldecl = XML_FALSE; |
|
4605 } |
|
4606 break; |
|
4607 |
|
4608 case XML_ROLE_CONTENT_PCDATA: |
|
4609 if (dtd->in_eldecl) { |
|
4610 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type |
|
4611 = XML_CTYPE_MIXED; |
|
4612 if (elementDeclHandler) |
|
4613 handleDefault = XML_FALSE; |
|
4614 } |
|
4615 break; |
|
4616 |
|
4617 case XML_ROLE_CONTENT_ELEMENT: |
|
4618 quant = XML_CQUANT_NONE; |
|
4619 goto elementContent; |
|
4620 case XML_ROLE_CONTENT_ELEMENT_OPT: |
|
4621 quant = XML_CQUANT_OPT; |
|
4622 goto elementContent; |
|
4623 case XML_ROLE_CONTENT_ELEMENT_REP: |
|
4624 quant = XML_CQUANT_REP; |
|
4625 goto elementContent; |
|
4626 case XML_ROLE_CONTENT_ELEMENT_PLUS: |
|
4627 quant = XML_CQUANT_PLUS; |
|
4628 elementContent: |
|
4629 if (dtd->in_eldecl) { |
|
4630 ELEMENT_TYPE *el; |
|
4631 const XML_Char *name; |
|
4632 int nameLen; |
|
4633 const char *nxt = (quant == XML_CQUANT_NONE |
|
4634 ? next |
|
4635 : next - enc->minBytesPerChar); |
|
4636 int myindex = nextScaffoldPart(parser); |
|
4637 if (myindex < 0) |
|
4638 return XML_ERROR_NO_MEMORY; |
|
4639 dtd->scaffold[myindex].type = XML_CTYPE_NAME; |
|
4640 dtd->scaffold[myindex].quant = quant; |
|
4641 el = getElementType(parser, enc, s, nxt); |
|
4642 if (!el) |
|
4643 return XML_ERROR_NO_MEMORY; |
|
4644 name = el->name; |
|
4645 dtd->scaffold[myindex].name = name; |
|
4646 nameLen = 0; |
|
4647 for (; name[nameLen++]; ); |
|
4648 dtd->contentStringLen += nameLen; |
|
4649 if (elementDeclHandler) |
|
4650 handleDefault = XML_FALSE; |
|
4651 } |
|
4652 break; |
|
4653 |
|
4654 case XML_ROLE_GROUP_CLOSE: |
|
4655 quant = XML_CQUANT_NONE; |
|
4656 goto closeGroup; |
|
4657 case XML_ROLE_GROUP_CLOSE_OPT: |
|
4658 quant = XML_CQUANT_OPT; |
|
4659 goto closeGroup; |
|
4660 case XML_ROLE_GROUP_CLOSE_REP: |
|
4661 quant = XML_CQUANT_REP; |
|
4662 goto closeGroup; |
|
4663 case XML_ROLE_GROUP_CLOSE_PLUS: |
|
4664 quant = XML_CQUANT_PLUS; |
|
4665 closeGroup: |
|
4666 if (dtd->in_eldecl) { |
|
4667 if (elementDeclHandler) |
|
4668 handleDefault = XML_FALSE; |
|
4669 dtd->scaffLevel--; |
|
4670 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; |
|
4671 if (dtd->scaffLevel == 0) { |
|
4672 if (!handleDefault) { |
|
4673 XML_Content *model = build_model(parser); |
|
4674 if (!model) |
|
4675 return XML_ERROR_NO_MEMORY; |
|
4676 *eventEndPP = s; |
|
4677 elementDeclHandler(handlerArg, declElementType->name, model); |
|
4678 } |
|
4679 dtd->in_eldecl = XML_FALSE; |
|
4680 dtd->contentStringLen = 0; |
|
4681 } |
|
4682 } |
|
4683 break; |
|
4684 /* End element declaration stuff */ |
|
4685 |
|
4686 case XML_ROLE_PI: |
|
4687 if (!reportProcessingInstruction(parser, enc, s, next)) |
|
4688 return XML_ERROR_NO_MEMORY; |
|
4689 handleDefault = XML_FALSE; |
|
4690 break; |
|
4691 case XML_ROLE_COMMENT: |
|
4692 if (!reportComment(parser, enc, s, next)) |
|
4693 return XML_ERROR_NO_MEMORY; |
|
4694 handleDefault = XML_FALSE; |
|
4695 break; |
|
4696 case XML_ROLE_NONE: |
|
4697 switch (tok) { |
|
4698 case XML_TOK_BOM: |
|
4699 handleDefault = XML_FALSE; |
|
4700 break; |
|
4701 } |
|
4702 break; |
|
4703 case XML_ROLE_DOCTYPE_NONE: |
|
4704 if (startDoctypeDeclHandler) |
|
4705 handleDefault = XML_FALSE; |
|
4706 break; |
|
4707 case XML_ROLE_ENTITY_NONE: |
|
4708 if (dtd->keepProcessing && entityDeclHandler) |
|
4709 handleDefault = XML_FALSE; |
|
4710 break; |
|
4711 case XML_ROLE_NOTATION_NONE: |
|
4712 if (notationDeclHandler) |
|
4713 handleDefault = XML_FALSE; |
|
4714 break; |
|
4715 case XML_ROLE_ATTLIST_NONE: |
|
4716 if (dtd->keepProcessing && attlistDeclHandler) |
|
4717 handleDefault = XML_FALSE; |
|
4718 break; |
|
4719 case XML_ROLE_ELEMENT_NONE: |
|
4720 if (elementDeclHandler) |
|
4721 handleDefault = XML_FALSE; |
|
4722 break; |
|
4723 } /* end of big switch */ |
|
4724 |
|
4725 if (handleDefault && defaultHandler) |
|
4726 reportDefault(parser, enc, s, next); |
|
4727 |
|
4728 switch (ps_parsing) { |
|
4729 case XML_SUSPENDED: |
|
4730 *nextPtr = next; |
|
4731 return XML_ERROR_NONE; |
|
4732 case XML_FINISHED: |
|
4733 return XML_ERROR_ABORTED; |
|
4734 default: |
|
4735 s = next; |
|
4736 tok = XmlPrologTok(enc, s, end, &next); |
|
4737 } |
|
4738 } |
|
4739 /* not reached */ |
|
4740 } |
|
4741 |
|
4742 static enum XML_Error PTRCALL |
|
4743 epilogProcessor(XML_Parser parser, |
|
4744 const char *s, |
|
4745 const char *end, |
|
4746 const char **nextPtr) |
|
4747 { |
|
4748 processor = epilogProcessor; |
|
4749 eventPtr = s; |
|
4750 for (;;) { |
|
4751 const char *next = NULL; |
|
4752 int tok = XmlPrologTok(encoding, s, end, &next); |
|
4753 eventEndPtr = next; |
|
4754 switch (tok) { |
|
4755 /* report partial linebreak - it might be the last token */ |
|
4756 case -XML_TOK_PROLOG_S: |
|
4757 if (defaultHandler) { |
|
4758 reportDefault(parser, encoding, s, next); |
|
4759 if (ps_parsing == XML_FINISHED) |
|
4760 return XML_ERROR_ABORTED; |
|
4761 } |
|
4762 *nextPtr = next; |
|
4763 return XML_ERROR_NONE; |
|
4764 case XML_TOK_NONE: |
|
4765 *nextPtr = s; |
|
4766 return XML_ERROR_NONE; |
|
4767 case XML_TOK_PROLOG_S: |
|
4768 if (defaultHandler) |
|
4769 reportDefault(parser, encoding, s, next); |
|
4770 break; |
|
4771 case XML_TOK_PI: |
|
4772 if (!reportProcessingInstruction(parser, encoding, s, next)) |
|
4773 return XML_ERROR_NO_MEMORY; |
|
4774 break; |
|
4775 case XML_TOK_COMMENT: |
|
4776 if (!reportComment(parser, encoding, s, next)) |
|
4777 return XML_ERROR_NO_MEMORY; |
|
4778 break; |
|
4779 case XML_TOK_INVALID: |
|
4780 eventPtr = next; |
|
4781 return XML_ERROR_INVALID_TOKEN; |
|
4782 case XML_TOK_PARTIAL: |
|
4783 if (!ps_finalBuffer) { |
|
4784 *nextPtr = s; |
|
4785 return XML_ERROR_NONE; |
|
4786 } |
|
4787 return XML_ERROR_UNCLOSED_TOKEN; |
|
4788 case XML_TOK_PARTIAL_CHAR: |
|
4789 if (!ps_finalBuffer) { |
|
4790 *nextPtr = s; |
|
4791 return XML_ERROR_NONE; |
|
4792 } |
|
4793 return XML_ERROR_PARTIAL_CHAR; |
|
4794 default: |
|
4795 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; |
|
4796 } |
|
4797 eventPtr = s = next; |
|
4798 switch (ps_parsing) { |
|
4799 case XML_SUSPENDED: |
|
4800 *nextPtr = next; |
|
4801 return XML_ERROR_NONE; |
|
4802 case XML_FINISHED: |
|
4803 return XML_ERROR_ABORTED; |
|
4804 default: ; |
|
4805 } |
|
4806 } |
|
4807 } |
|
4808 |
|
4809 static enum XML_Error |
|
4810 processInternalEntity(XML_Parser parser, ENTITY *entity, |
|
4811 XML_Bool betweenDecl) |
|
4812 { |
|
4813 const char *textStart, *textEnd; |
|
4814 const char *next; |
|
4815 enum XML_Error result; |
|
4816 OPEN_INTERNAL_ENTITY *openEntity; |
|
4817 |
|
4818 if (freeInternalEntities) { |
|
4819 openEntity = freeInternalEntities; |
|
4820 freeInternalEntities = openEntity->next; |
|
4821 } |
|
4822 else { |
|
4823 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); |
|
4824 if (!openEntity) |
|
4825 return XML_ERROR_NO_MEMORY; |
|
4826 } |
|
4827 entity->open = XML_TRUE; |
|
4828 entity->processed = 0; |
|
4829 openEntity->next = openInternalEntities; |
|
4830 openInternalEntities = openEntity; |
|
4831 openEntity->entity = entity; |
|
4832 openEntity->startTagLevel = tagLevel; |
|
4833 openEntity->betweenDecl = betweenDecl; |
|
4834 openEntity->internalEventPtr = NULL; |
|
4835 openEntity->internalEventEndPtr = NULL; |
|
4836 textStart = (char *)entity->textPtr; |
|
4837 textEnd = (char *)(entity->textPtr + entity->textLen); |
|
4838 |
|
4839 #ifdef XML_DTD |
|
4840 if (entity->is_param) { |
|
4841 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); |
|
4842 result = doProlog(parser, internalEncoding, textStart, textEnd, tok, |
|
4843 next, &next, XML_FALSE); |
|
4844 } |
|
4845 else |
|
4846 #endif /* XML_DTD */ |
|
4847 result = doContent(parser, tagLevel, internalEncoding, textStart, |
|
4848 textEnd, &next, XML_FALSE); |
|
4849 |
|
4850 if (result == XML_ERROR_NONE) { |
|
4851 if (textEnd != next && ps_parsing == XML_SUSPENDED) { |
|
4852 entity->processed = (int)(next - textStart); |
|
4853 processor = internalEntityProcessor; |
|
4854 } |
|
4855 else { |
|
4856 entity->open = XML_FALSE; |
|
4857 openInternalEntities = openEntity->next; |
|
4858 /* put openEntity back in list of free instances */ |
|
4859 openEntity->next = freeInternalEntities; |
|
4860 freeInternalEntities = openEntity; |
|
4861 } |
|
4862 } |
|
4863 return result; |
|
4864 } |
|
4865 |
|
4866 static enum XML_Error PTRCALL |
|
4867 internalEntityProcessor(XML_Parser parser, |
|
4868 const char *s, |
|
4869 const char *end, |
|
4870 const char **nextPtr) |
|
4871 { |
|
4872 ENTITY *entity; |
|
4873 const char *textStart, *textEnd; |
|
4874 const char *next; |
|
4875 enum XML_Error result; |
|
4876 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; |
|
4877 if (!openEntity) |
|
4878 return XML_ERROR_UNEXPECTED_STATE; |
|
4879 |
|
4880 entity = openEntity->entity; |
|
4881 textStart = ((char *)entity->textPtr) + entity->processed; |
|
4882 textEnd = (char *)(entity->textPtr + entity->textLen); |
|
4883 |
|
4884 #ifdef XML_DTD |
|
4885 if (entity->is_param) { |
|
4886 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); |
|
4887 result = doProlog(parser, internalEncoding, textStart, textEnd, tok, |
|
4888 next, &next, XML_FALSE); |
|
4889 } |
|
4890 else |
|
4891 #endif /* XML_DTD */ |
|
4892 result = doContent(parser, openEntity->startTagLevel, internalEncoding, |
|
4893 textStart, textEnd, &next, XML_FALSE); |
|
4894 |
|
4895 if (result != XML_ERROR_NONE) |
|
4896 return result; |
|
4897 else if (textEnd != next && ps_parsing == XML_SUSPENDED) { |
|
4898 entity->processed = (int)(next - (char *)entity->textPtr); |
|
4899 return result; |
|
4900 } |
|
4901 else { |
|
4902 entity->open = XML_FALSE; |
|
4903 openInternalEntities = openEntity->next; |
|
4904 /* put openEntity back in list of free instances */ |
|
4905 openEntity->next = freeInternalEntities; |
|
4906 freeInternalEntities = openEntity; |
|
4907 } |
|
4908 |
|
4909 #ifdef XML_DTD |
|
4910 if (entity->is_param) { |
|
4911 int tok; |
|
4912 processor = prologProcessor; |
|
4913 tok = XmlPrologTok(encoding, s, end, &next); |
|
4914 return doProlog(parser, encoding, s, end, tok, next, nextPtr, |
|
4915 (XML_Bool)!ps_finalBuffer); |
|
4916 } |
|
4917 else |
|
4918 #endif /* XML_DTD */ |
|
4919 { |
|
4920 processor = contentProcessor; |
|
4921 /* see externalEntityContentProcessor vs contentProcessor */ |
|
4922 return doContent(parser, parentParser ? 1 : 0, encoding, s, end, |
|
4923 nextPtr, (XML_Bool)!ps_finalBuffer); |
|
4924 } |
|
4925 } |
|
4926 |
|
4927 static enum XML_Error PTRCALL |
|
4928 errorProcessor(XML_Parser parser, |
|
4929 const char *s, |
|
4930 const char *end, |
|
4931 const char **nextPtr) |
|
4932 { |
|
4933 return errorCode; |
|
4934 } |
|
4935 |
|
4936 static enum XML_Error |
|
4937 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, |
|
4938 const char *ptr, const char *end, |
|
4939 STRING_POOL *pool) |
|
4940 { |
|
4941 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, |
|
4942 end, pool); |
|
4943 if (result) |
|
4944 return result; |
|
4945 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) |
|
4946 poolChop(pool); |
|
4947 if (!poolAppendChar(pool, XML_T('\0'))) |
|
4948 return XML_ERROR_NO_MEMORY; |
|
4949 return XML_ERROR_NONE; |
|
4950 } |
|
4951 |
|
4952 static enum XML_Error |
|
4953 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, |
|
4954 const char *ptr, const char *end, |
|
4955 STRING_POOL *pool) |
|
4956 { |
|
4957 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
4958 for (;;) { |
|
4959 const char *next; |
|
4960 int tok = XmlAttributeValueTok(enc, ptr, end, &next); |
|
4961 switch (tok) { |
|
4962 case XML_TOK_NONE: |
|
4963 return XML_ERROR_NONE; |
|
4964 case XML_TOK_INVALID: |
|
4965 if (enc == encoding) |
|
4966 eventPtr = next; |
|
4967 return XML_ERROR_INVALID_TOKEN; |
|
4968 case XML_TOK_PARTIAL: |
|
4969 if (enc == encoding) |
|
4970 eventPtr = ptr; |
|
4971 return XML_ERROR_INVALID_TOKEN; |
|
4972 case XML_TOK_CHAR_REF: |
|
4973 { |
|
4974 XML_Char buf[XML_ENCODE_MAX]; |
|
4975 int i; |
|
4976 int n = XmlCharRefNumber(enc, ptr); |
|
4977 if (n < 0) { |
|
4978 if (enc == encoding) |
|
4979 eventPtr = ptr; |
|
4980 return XML_ERROR_BAD_CHAR_REF; |
|
4981 } |
|
4982 if (!isCdata |
|
4983 && n == 0x20 /* space */ |
|
4984 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) |
|
4985 break; |
|
4986 n = XmlEncode(n, (ICHAR *)buf); |
|
4987 if (!n) { |
|
4988 if (enc == encoding) |
|
4989 eventPtr = ptr; |
|
4990 return XML_ERROR_BAD_CHAR_REF; |
|
4991 } |
|
4992 for (i = 0; i < n; i++) { |
|
4993 if (!poolAppendChar(pool, buf[i])) |
|
4994 return XML_ERROR_NO_MEMORY; |
|
4995 } |
|
4996 } |
|
4997 break; |
|
4998 case XML_TOK_DATA_CHARS: |
|
4999 if (!poolAppend(pool, enc, ptr, next)) |
|
5000 return XML_ERROR_NO_MEMORY; |
|
5001 break; |
|
5002 case XML_TOK_TRAILING_CR: |
|
5003 next = ptr + enc->minBytesPerChar; |
|
5004 /* fall through */ |
|
5005 case XML_TOK_ATTRIBUTE_VALUE_S: |
|
5006 case XML_TOK_DATA_NEWLINE: |
|
5007 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) |
|
5008 break; |
|
5009 if (!poolAppendChar(pool, 0x20)) |
|
5010 return XML_ERROR_NO_MEMORY; |
|
5011 break; |
|
5012 case XML_TOK_ENTITY_REF: |
|
5013 { |
|
5014 const XML_Char *name; |
|
5015 ENTITY *entity; |
|
5016 char checkEntityDecl; |
|
5017 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, |
|
5018 ptr + enc->minBytesPerChar, |
|
5019 next - enc->minBytesPerChar); |
|
5020 if (ch) { |
|
5021 if (!poolAppendChar(pool, ch)) |
|
5022 return XML_ERROR_NO_MEMORY; |
|
5023 break; |
|
5024 } |
|
5025 name = poolStoreString(&temp2Pool, enc, |
|
5026 ptr + enc->minBytesPerChar, |
|
5027 next - enc->minBytesPerChar); |
|
5028 if (!name) |
|
5029 return XML_ERROR_NO_MEMORY; |
|
5030 entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); |
|
5031 poolDiscard(&temp2Pool); |
|
5032 /* First, determine if a check for an existing declaration is needed; |
|
5033 if yes, check that the entity exists, and that it is internal. |
|
5034 */ |
|
5035 if (pool == &dtd->pool) /* are we called from prolog? */ |
|
5036 checkEntityDecl = |
|
5037 #ifdef XML_DTD |
|
5038 prologState.documentEntity && |
|
5039 #endif /* XML_DTD */ |
|
5040 (dtd->standalone |
|
5041 ? !openInternalEntities |
|
5042 : !dtd->hasParamEntityRefs); |
|
5043 else /* if (pool == &tempPool): we are called from content */ |
|
5044 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; |
|
5045 if (checkEntityDecl) { |
|
5046 if (!entity) |
|
5047 return XML_ERROR_UNDEFINED_ENTITY; |
|
5048 else if (!entity->is_internal) |
|
5049 return XML_ERROR_ENTITY_DECLARED_IN_PE; |
|
5050 } |
|
5051 else if (!entity) { |
|
5052 /* Cannot report skipped entity here - see comments on |
|
5053 skippedEntityHandler. |
|
5054 if (skippedEntityHandler) |
|
5055 skippedEntityHandler(handlerArg, name, 0); |
|
5056 */ |
|
5057 /* Cannot call the default handler because this would be |
|
5058 out of sync with the call to the startElementHandler. |
|
5059 if ((pool == &tempPool) && defaultHandler) |
|
5060 reportDefault(parser, enc, ptr, next); |
|
5061 */ |
|
5062 /* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */ |
|
5063 #if 0 |
|
5064 break; |
|
5065 #else |
|
5066 return XML_ERROR_UNDEFINED_ENTITY; |
|
5067 #endif |
|
5068 /* END MOZILLA CHANGE */ |
|
5069 } |
|
5070 if (entity->open) { |
|
5071 if (enc == encoding) |
|
5072 eventPtr = ptr; |
|
5073 return XML_ERROR_RECURSIVE_ENTITY_REF; |
|
5074 } |
|
5075 if (entity->notation) { |
|
5076 if (enc == encoding) |
|
5077 eventPtr = ptr; |
|
5078 return XML_ERROR_BINARY_ENTITY_REF; |
|
5079 } |
|
5080 if (!entity->textPtr) { |
|
5081 if (enc == encoding) |
|
5082 eventPtr = ptr; |
|
5083 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; |
|
5084 } |
|
5085 else { |
|
5086 enum XML_Error result; |
|
5087 const XML_Char *textEnd = entity->textPtr + entity->textLen; |
|
5088 entity->open = XML_TRUE; |
|
5089 result = appendAttributeValue(parser, internalEncoding, isCdata, |
|
5090 (char *)entity->textPtr, |
|
5091 (char *)textEnd, pool); |
|
5092 entity->open = XML_FALSE; |
|
5093 if (result) |
|
5094 return result; |
|
5095 } |
|
5096 } |
|
5097 break; |
|
5098 default: |
|
5099 if (enc == encoding) |
|
5100 eventPtr = ptr; |
|
5101 return XML_ERROR_UNEXPECTED_STATE; |
|
5102 } |
|
5103 ptr = next; |
|
5104 } |
|
5105 /* not reached */ |
|
5106 } |
|
5107 |
|
5108 static enum XML_Error |
|
5109 storeEntityValue(XML_Parser parser, |
|
5110 const ENCODING *enc, |
|
5111 const char *entityTextPtr, |
|
5112 const char *entityTextEnd) |
|
5113 { |
|
5114 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
5115 STRING_POOL *pool = &(dtd->entityValuePool); |
|
5116 enum XML_Error result = XML_ERROR_NONE; |
|
5117 #ifdef XML_DTD |
|
5118 int oldInEntityValue = prologState.inEntityValue; |
|
5119 prologState.inEntityValue = 1; |
|
5120 #endif /* XML_DTD */ |
|
5121 /* never return Null for the value argument in EntityDeclHandler, |
|
5122 since this would indicate an external entity; therefore we |
|
5123 have to make sure that entityValuePool.start is not null */ |
|
5124 if (!pool->blocks) { |
|
5125 if (!poolGrow(pool)) |
|
5126 return XML_ERROR_NO_MEMORY; |
|
5127 } |
|
5128 |
|
5129 for (;;) { |
|
5130 const char *next; |
|
5131 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); |
|
5132 switch (tok) { |
|
5133 case XML_TOK_PARAM_ENTITY_REF: |
|
5134 #ifdef XML_DTD |
|
5135 if (isParamEntity || enc != encoding) { |
|
5136 const XML_Char *name; |
|
5137 ENTITY *entity; |
|
5138 name = poolStoreString(&tempPool, enc, |
|
5139 entityTextPtr + enc->minBytesPerChar, |
|
5140 next - enc->minBytesPerChar); |
|
5141 if (!name) { |
|
5142 result = XML_ERROR_NO_MEMORY; |
|
5143 goto endEntityValue; |
|
5144 } |
|
5145 entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); |
|
5146 poolDiscard(&tempPool); |
|
5147 if (!entity) { |
|
5148 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ |
|
5149 /* cannot report skipped entity here - see comments on |
|
5150 skippedEntityHandler |
|
5151 if (skippedEntityHandler) |
|
5152 skippedEntityHandler(handlerArg, name, 0); |
|
5153 */ |
|
5154 dtd->keepProcessing = dtd->standalone; |
|
5155 goto endEntityValue; |
|
5156 } |
|
5157 if (entity->open) { |
|
5158 if (enc == encoding) |
|
5159 eventPtr = entityTextPtr; |
|
5160 result = XML_ERROR_RECURSIVE_ENTITY_REF; |
|
5161 goto endEntityValue; |
|
5162 } |
|
5163 if (entity->systemId) { |
|
5164 if (externalEntityRefHandler) { |
|
5165 dtd->paramEntityRead = XML_FALSE; |
|
5166 entity->open = XML_TRUE; |
|
5167 if (!externalEntityRefHandler(externalEntityRefHandlerArg, |
|
5168 0, |
|
5169 entity->base, |
|
5170 entity->systemId, |
|
5171 entity->publicId)) { |
|
5172 entity->open = XML_FALSE; |
|
5173 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; |
|
5174 goto endEntityValue; |
|
5175 } |
|
5176 entity->open = XML_FALSE; |
|
5177 if (!dtd->paramEntityRead) |
|
5178 dtd->keepProcessing = dtd->standalone; |
|
5179 } |
|
5180 else |
|
5181 dtd->keepProcessing = dtd->standalone; |
|
5182 } |
|
5183 else { |
|
5184 entity->open = XML_TRUE; |
|
5185 result = storeEntityValue(parser, |
|
5186 internalEncoding, |
|
5187 (char *)entity->textPtr, |
|
5188 (char *)(entity->textPtr |
|
5189 + entity->textLen)); |
|
5190 entity->open = XML_FALSE; |
|
5191 if (result) |
|
5192 goto endEntityValue; |
|
5193 } |
|
5194 break; |
|
5195 } |
|
5196 #endif /* XML_DTD */ |
|
5197 /* In the internal subset, PE references are not legal |
|
5198 within markup declarations, e.g entity values in this case. */ |
|
5199 eventPtr = entityTextPtr; |
|
5200 result = XML_ERROR_PARAM_ENTITY_REF; |
|
5201 goto endEntityValue; |
|
5202 case XML_TOK_NONE: |
|
5203 result = XML_ERROR_NONE; |
|
5204 goto endEntityValue; |
|
5205 case XML_TOK_ENTITY_REF: |
|
5206 case XML_TOK_DATA_CHARS: |
|
5207 if (!poolAppend(pool, enc, entityTextPtr, next)) { |
|
5208 result = XML_ERROR_NO_MEMORY; |
|
5209 goto endEntityValue; |
|
5210 } |
|
5211 break; |
|
5212 case XML_TOK_TRAILING_CR: |
|
5213 next = entityTextPtr + enc->minBytesPerChar; |
|
5214 /* fall through */ |
|
5215 case XML_TOK_DATA_NEWLINE: |
|
5216 if (pool->end == pool->ptr && !poolGrow(pool)) { |
|
5217 result = XML_ERROR_NO_MEMORY; |
|
5218 goto endEntityValue; |
|
5219 } |
|
5220 *(pool->ptr)++ = 0xA; |
|
5221 break; |
|
5222 case XML_TOK_CHAR_REF: |
|
5223 { |
|
5224 XML_Char buf[XML_ENCODE_MAX]; |
|
5225 int i; |
|
5226 int n = XmlCharRefNumber(enc, entityTextPtr); |
|
5227 if (n < 0) { |
|
5228 if (enc == encoding) |
|
5229 eventPtr = entityTextPtr; |
|
5230 result = XML_ERROR_BAD_CHAR_REF; |
|
5231 goto endEntityValue; |
|
5232 } |
|
5233 n = XmlEncode(n, (ICHAR *)buf); |
|
5234 if (!n) { |
|
5235 if (enc == encoding) |
|
5236 eventPtr = entityTextPtr; |
|
5237 result = XML_ERROR_BAD_CHAR_REF; |
|
5238 goto endEntityValue; |
|
5239 } |
|
5240 for (i = 0; i < n; i++) { |
|
5241 if (pool->end == pool->ptr && !poolGrow(pool)) { |
|
5242 result = XML_ERROR_NO_MEMORY; |
|
5243 goto endEntityValue; |
|
5244 } |
|
5245 *(pool->ptr)++ = buf[i]; |
|
5246 } |
|
5247 } |
|
5248 break; |
|
5249 case XML_TOK_PARTIAL: |
|
5250 if (enc == encoding) |
|
5251 eventPtr = entityTextPtr; |
|
5252 result = XML_ERROR_INVALID_TOKEN; |
|
5253 goto endEntityValue; |
|
5254 case XML_TOK_INVALID: |
|
5255 if (enc == encoding) |
|
5256 eventPtr = next; |
|
5257 result = XML_ERROR_INVALID_TOKEN; |
|
5258 goto endEntityValue; |
|
5259 default: |
|
5260 if (enc == encoding) |
|
5261 eventPtr = entityTextPtr; |
|
5262 result = XML_ERROR_UNEXPECTED_STATE; |
|
5263 goto endEntityValue; |
|
5264 } |
|
5265 entityTextPtr = next; |
|
5266 } |
|
5267 endEntityValue: |
|
5268 #ifdef XML_DTD |
|
5269 prologState.inEntityValue = oldInEntityValue; |
|
5270 #endif /* XML_DTD */ |
|
5271 return result; |
|
5272 } |
|
5273 |
|
5274 static void FASTCALL |
|
5275 normalizeLines(XML_Char *s) |
|
5276 { |
|
5277 XML_Char *p; |
|
5278 for (;; s++) { |
|
5279 if (*s == XML_T('\0')) |
|
5280 return; |
|
5281 if (*s == 0xD) |
|
5282 break; |
|
5283 } |
|
5284 p = s; |
|
5285 do { |
|
5286 if (*s == 0xD) { |
|
5287 *p++ = 0xA; |
|
5288 if (*++s == 0xA) |
|
5289 s++; |
|
5290 } |
|
5291 else |
|
5292 *p++ = *s++; |
|
5293 } while (*s); |
|
5294 *p = XML_T('\0'); |
|
5295 } |
|
5296 |
|
5297 static int |
|
5298 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, |
|
5299 const char *start, const char *end) |
|
5300 { |
|
5301 const XML_Char *target; |
|
5302 XML_Char *data; |
|
5303 const char *tem; |
|
5304 if (!processingInstructionHandler) { |
|
5305 if (defaultHandler) |
|
5306 reportDefault(parser, enc, start, end); |
|
5307 return 1; |
|
5308 } |
|
5309 start += enc->minBytesPerChar * 2; |
|
5310 tem = start + XmlNameLength(enc, start); |
|
5311 target = poolStoreString(&tempPool, enc, start, tem); |
|
5312 if (!target) |
|
5313 return 0; |
|
5314 poolFinish(&tempPool); |
|
5315 data = poolStoreString(&tempPool, enc, |
|
5316 XmlSkipS(enc, tem), |
|
5317 end - enc->minBytesPerChar*2); |
|
5318 if (!data) |
|
5319 return 0; |
|
5320 normalizeLines(data); |
|
5321 processingInstructionHandler(handlerArg, target, data); |
|
5322 poolClear(&tempPool); |
|
5323 return 1; |
|
5324 } |
|
5325 |
|
5326 static int |
|
5327 reportComment(XML_Parser parser, const ENCODING *enc, |
|
5328 const char *start, const char *end) |
|
5329 { |
|
5330 XML_Char *data; |
|
5331 if (!commentHandler) { |
|
5332 if (defaultHandler) |
|
5333 reportDefault(parser, enc, start, end); |
|
5334 return 1; |
|
5335 } |
|
5336 data = poolStoreString(&tempPool, |
|
5337 enc, |
|
5338 start + enc->minBytesPerChar * 4, |
|
5339 end - enc->minBytesPerChar * 3); |
|
5340 if (!data) |
|
5341 return 0; |
|
5342 normalizeLines(data); |
|
5343 commentHandler(handlerArg, data); |
|
5344 poolClear(&tempPool); |
|
5345 return 1; |
|
5346 } |
|
5347 |
|
5348 static void |
|
5349 reportDefault(XML_Parser parser, const ENCODING *enc, |
|
5350 const char *s, const char *end) |
|
5351 { |
|
5352 if (MUST_CONVERT(enc, s)) { |
|
5353 const char **eventPP; |
|
5354 const char **eventEndPP; |
|
5355 if (enc == encoding) { |
|
5356 eventPP = &eventPtr; |
|
5357 eventEndPP = &eventEndPtr; |
|
5358 } |
|
5359 else { |
|
5360 eventPP = &(openInternalEntities->internalEventPtr); |
|
5361 eventEndPP = &(openInternalEntities->internalEventEndPtr); |
|
5362 } |
|
5363 do { |
|
5364 ICHAR *dataPtr = (ICHAR *)dataBuf; |
|
5365 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); |
|
5366 *eventEndPP = s; |
|
5367 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf)); |
|
5368 *eventPP = s; |
|
5369 } while (s != end); |
|
5370 } |
|
5371 else |
|
5372 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s)); |
|
5373 } |
|
5374 |
|
5375 |
|
5376 static int |
|
5377 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, |
|
5378 XML_Bool isId, const XML_Char *value, XML_Parser parser) |
|
5379 { |
|
5380 DEFAULT_ATTRIBUTE *att; |
|
5381 if (value || isId) { |
|
5382 /* The handling of default attributes gets messed up if we have |
|
5383 a default which duplicates a non-default. */ |
|
5384 int i; |
|
5385 for (i = 0; i < type->nDefaultAtts; i++) |
|
5386 if (attId == type->defaultAtts[i].id) |
|
5387 return 1; |
|
5388 if (isId && !type->idAtt && !attId->xmlns) |
|
5389 type->idAtt = attId; |
|
5390 } |
|
5391 if (type->nDefaultAtts == type->allocDefaultAtts) { |
|
5392 if (type->allocDefaultAtts == 0) { |
|
5393 type->allocDefaultAtts = 8; |
|
5394 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts |
|
5395 * sizeof(DEFAULT_ATTRIBUTE)); |
|
5396 if (!type->defaultAtts) |
|
5397 return 0; |
|
5398 } |
|
5399 else { |
|
5400 DEFAULT_ATTRIBUTE *temp; |
|
5401 int count = type->allocDefaultAtts * 2; |
|
5402 temp = (DEFAULT_ATTRIBUTE *) |
|
5403 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); |
|
5404 if (temp == NULL) |
|
5405 return 0; |
|
5406 type->allocDefaultAtts = count; |
|
5407 type->defaultAtts = temp; |
|
5408 } |
|
5409 } |
|
5410 att = type->defaultAtts + type->nDefaultAtts; |
|
5411 att->id = attId; |
|
5412 att->value = value; |
|
5413 att->isCdata = isCdata; |
|
5414 if (!isCdata) |
|
5415 attId->maybeTokenized = XML_TRUE; |
|
5416 type->nDefaultAtts += 1; |
|
5417 return 1; |
|
5418 } |
|
5419 |
|
5420 static int |
|
5421 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) |
|
5422 { |
|
5423 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
5424 const XML_Char *name; |
|
5425 for (name = elementType->name; *name; name++) { |
|
5426 if (*name == XML_T(':')) { |
|
5427 PREFIX *prefix; |
|
5428 const XML_Char *s; |
|
5429 for (s = elementType->name; s != name; s++) { |
|
5430 if (!poolAppendChar(&dtd->pool, *s)) |
|
5431 return 0; |
|
5432 } |
|
5433 if (!poolAppendChar(&dtd->pool, XML_T('\0'))) |
|
5434 return 0; |
|
5435 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), |
|
5436 sizeof(PREFIX)); |
|
5437 if (!prefix) |
|
5438 return 0; |
|
5439 if (prefix->name == poolStart(&dtd->pool)) |
|
5440 poolFinish(&dtd->pool); |
|
5441 else |
|
5442 poolDiscard(&dtd->pool); |
|
5443 elementType->prefix = prefix; |
|
5444 |
|
5445 } |
|
5446 } |
|
5447 return 1; |
|
5448 } |
|
5449 |
|
5450 static ATTRIBUTE_ID * |
|
5451 getAttributeId(XML_Parser parser, const ENCODING *enc, |
|
5452 const char *start, const char *end) |
|
5453 { |
|
5454 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
5455 ATTRIBUTE_ID *id; |
|
5456 const XML_Char *name; |
|
5457 if (!poolAppendChar(&dtd->pool, XML_T('\0'))) |
|
5458 return NULL; |
|
5459 name = poolStoreString(&dtd->pool, enc, start, end); |
|
5460 if (!name) |
|
5461 return NULL; |
|
5462 /* skip quotation mark - its storage will be re-used (like in name[-1]) */ |
|
5463 ++name; |
|
5464 id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); |
|
5465 if (!id) |
|
5466 return NULL; |
|
5467 if (id->name != name) |
|
5468 poolDiscard(&dtd->pool); |
|
5469 else { |
|
5470 poolFinish(&dtd->pool); |
|
5471 if (!ns) |
|
5472 ; |
|
5473 else if (name[0] == XML_T('x') |
|
5474 && name[1] == XML_T('m') |
|
5475 && name[2] == XML_T('l') |
|
5476 && name[3] == XML_T('n') |
|
5477 && name[4] == XML_T('s') |
|
5478 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { |
|
5479 if (name[5] == XML_T('\0')) |
|
5480 id->prefix = &dtd->defaultPrefix; |
|
5481 else |
|
5482 id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); |
|
5483 id->xmlns = XML_TRUE; |
|
5484 } |
|
5485 else { |
|
5486 int i; |
|
5487 for (i = 0; name[i]; i++) { |
|
5488 /* attributes without prefix are *not* in the default namespace */ |
|
5489 if (name[i] == XML_T(':')) { |
|
5490 int j; |
|
5491 for (j = 0; j < i; j++) { |
|
5492 if (!poolAppendChar(&dtd->pool, name[j])) |
|
5493 return NULL; |
|
5494 } |
|
5495 if (!poolAppendChar(&dtd->pool, XML_T('\0'))) |
|
5496 return NULL; |
|
5497 id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), |
|
5498 sizeof(PREFIX)); |
|
5499 if (id->prefix->name == poolStart(&dtd->pool)) |
|
5500 poolFinish(&dtd->pool); |
|
5501 else |
|
5502 poolDiscard(&dtd->pool); |
|
5503 break; |
|
5504 } |
|
5505 } |
|
5506 } |
|
5507 } |
|
5508 return id; |
|
5509 } |
|
5510 |
|
5511 #define CONTEXT_SEP XML_T('\f') |
|
5512 |
|
5513 static const XML_Char * |
|
5514 getContext(XML_Parser parser) |
|
5515 { |
|
5516 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
5517 HASH_TABLE_ITER iter; |
|
5518 XML_Bool needSep = XML_FALSE; |
|
5519 |
|
5520 if (dtd->defaultPrefix.binding) { |
|
5521 int i; |
|
5522 int len; |
|
5523 if (!poolAppendChar(&tempPool, XML_T('='))) |
|
5524 return NULL; |
|
5525 len = dtd->defaultPrefix.binding->uriLen; |
|
5526 if (namespaceSeparator) |
|
5527 len--; |
|
5528 for (i = 0; i < len; i++) |
|
5529 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) |
|
5530 return NULL; |
|
5531 needSep = XML_TRUE; |
|
5532 } |
|
5533 |
|
5534 hashTableIterInit(&iter, &(dtd->prefixes)); |
|
5535 for (;;) { |
|
5536 int i; |
|
5537 int len; |
|
5538 const XML_Char *s; |
|
5539 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); |
|
5540 if (!prefix) |
|
5541 break; |
|
5542 if (!prefix->binding) |
|
5543 continue; |
|
5544 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) |
|
5545 return NULL; |
|
5546 for (s = prefix->name; *s; s++) |
|
5547 if (!poolAppendChar(&tempPool, *s)) |
|
5548 return NULL; |
|
5549 if (!poolAppendChar(&tempPool, XML_T('='))) |
|
5550 return NULL; |
|
5551 len = prefix->binding->uriLen; |
|
5552 if (namespaceSeparator) |
|
5553 len--; |
|
5554 for (i = 0; i < len; i++) |
|
5555 if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) |
|
5556 return NULL; |
|
5557 needSep = XML_TRUE; |
|
5558 } |
|
5559 |
|
5560 |
|
5561 hashTableIterInit(&iter, &(dtd->generalEntities)); |
|
5562 for (;;) { |
|
5563 const XML_Char *s; |
|
5564 ENTITY *e = (ENTITY *)hashTableIterNext(&iter); |
|
5565 if (!e) |
|
5566 break; |
|
5567 if (!e->open) |
|
5568 continue; |
|
5569 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) |
|
5570 return NULL; |
|
5571 for (s = e->name; *s; s++) |
|
5572 if (!poolAppendChar(&tempPool, *s)) |
|
5573 return 0; |
|
5574 needSep = XML_TRUE; |
|
5575 } |
|
5576 |
|
5577 if (!poolAppendChar(&tempPool, XML_T('\0'))) |
|
5578 return NULL; |
|
5579 return tempPool.start; |
|
5580 } |
|
5581 |
|
5582 static XML_Bool |
|
5583 setContext(XML_Parser parser, const XML_Char *context) |
|
5584 { |
|
5585 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
5586 const XML_Char *s = context; |
|
5587 |
|
5588 while (*context != XML_T('\0')) { |
|
5589 if (*s == CONTEXT_SEP || *s == XML_T('\0')) { |
|
5590 ENTITY *e; |
|
5591 if (!poolAppendChar(&tempPool, XML_T('\0'))) |
|
5592 return XML_FALSE; |
|
5593 e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); |
|
5594 if (e) |
|
5595 e->open = XML_TRUE; |
|
5596 if (*s != XML_T('\0')) |
|
5597 s++; |
|
5598 context = s; |
|
5599 poolDiscard(&tempPool); |
|
5600 } |
|
5601 else if (*s == XML_T('=')) { |
|
5602 PREFIX *prefix; |
|
5603 if (poolLength(&tempPool) == 0) |
|
5604 prefix = &dtd->defaultPrefix; |
|
5605 else { |
|
5606 if (!poolAppendChar(&tempPool, XML_T('\0'))) |
|
5607 return XML_FALSE; |
|
5608 prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), |
|
5609 sizeof(PREFIX)); |
|
5610 if (!prefix) |
|
5611 return XML_FALSE; |
|
5612 if (prefix->name == poolStart(&tempPool)) { |
|
5613 prefix->name = poolCopyString(&dtd->pool, prefix->name); |
|
5614 if (!prefix->name) |
|
5615 return XML_FALSE; |
|
5616 } |
|
5617 poolDiscard(&tempPool); |
|
5618 } |
|
5619 for (context = s + 1; |
|
5620 *context != CONTEXT_SEP && *context != XML_T('\0'); |
|
5621 context++) |
|
5622 if (!poolAppendChar(&tempPool, *context)) |
|
5623 return XML_FALSE; |
|
5624 if (!poolAppendChar(&tempPool, XML_T('\0'))) |
|
5625 return XML_FALSE; |
|
5626 if (addBinding(parser, prefix, NULL, poolStart(&tempPool), |
|
5627 &inheritedBindings) != XML_ERROR_NONE) |
|
5628 return XML_FALSE; |
|
5629 poolDiscard(&tempPool); |
|
5630 if (*context != XML_T('\0')) |
|
5631 ++context; |
|
5632 s = context; |
|
5633 } |
|
5634 else { |
|
5635 if (!poolAppendChar(&tempPool, *s)) |
|
5636 return XML_FALSE; |
|
5637 s++; |
|
5638 } |
|
5639 } |
|
5640 return XML_TRUE; |
|
5641 } |
|
5642 |
|
5643 static void FASTCALL |
|
5644 normalizePublicId(XML_Char *publicId) |
|
5645 { |
|
5646 XML_Char *p = publicId; |
|
5647 XML_Char *s; |
|
5648 for (s = publicId; *s; s++) { |
|
5649 switch (*s) { |
|
5650 case 0x20: |
|
5651 case 0xD: |
|
5652 case 0xA: |
|
5653 if (p != publicId && p[-1] != 0x20) |
|
5654 *p++ = 0x20; |
|
5655 break; |
|
5656 default: |
|
5657 *p++ = *s; |
|
5658 } |
|
5659 } |
|
5660 if (p != publicId && p[-1] == 0x20) |
|
5661 --p; |
|
5662 *p = XML_T('\0'); |
|
5663 } |
|
5664 |
|
5665 static DTD * |
|
5666 dtdCreate(const XML_Memory_Handling_Suite *ms) |
|
5667 { |
|
5668 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); |
|
5669 if (p == NULL) |
|
5670 return p; |
|
5671 poolInit(&(p->pool), ms); |
|
5672 poolInit(&(p->entityValuePool), ms); |
|
5673 hashTableInit(&(p->generalEntities), ms); |
|
5674 hashTableInit(&(p->elementTypes), ms); |
|
5675 hashTableInit(&(p->attributeIds), ms); |
|
5676 hashTableInit(&(p->prefixes), ms); |
|
5677 #ifdef XML_DTD |
|
5678 p->paramEntityRead = XML_FALSE; |
|
5679 hashTableInit(&(p->paramEntities), ms); |
|
5680 #endif /* XML_DTD */ |
|
5681 p->defaultPrefix.name = NULL; |
|
5682 p->defaultPrefix.binding = NULL; |
|
5683 |
|
5684 p->in_eldecl = XML_FALSE; |
|
5685 p->scaffIndex = NULL; |
|
5686 p->scaffold = NULL; |
|
5687 p->scaffLevel = 0; |
|
5688 p->scaffSize = 0; |
|
5689 p->scaffCount = 0; |
|
5690 p->contentStringLen = 0; |
|
5691 |
|
5692 p->keepProcessing = XML_TRUE; |
|
5693 p->hasParamEntityRefs = XML_FALSE; |
|
5694 p->standalone = XML_FALSE; |
|
5695 return p; |
|
5696 } |
|
5697 |
|
5698 static void |
|
5699 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) |
|
5700 { |
|
5701 HASH_TABLE_ITER iter; |
|
5702 hashTableIterInit(&iter, &(p->elementTypes)); |
|
5703 for (;;) { |
|
5704 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); |
|
5705 if (!e) |
|
5706 break; |
|
5707 if (e->allocDefaultAtts != 0) |
|
5708 ms->free_fcn(e->defaultAtts); |
|
5709 } |
|
5710 hashTableClear(&(p->generalEntities)); |
|
5711 #ifdef XML_DTD |
|
5712 p->paramEntityRead = XML_FALSE; |
|
5713 hashTableClear(&(p->paramEntities)); |
|
5714 #endif /* XML_DTD */ |
|
5715 hashTableClear(&(p->elementTypes)); |
|
5716 hashTableClear(&(p->attributeIds)); |
|
5717 hashTableClear(&(p->prefixes)); |
|
5718 poolClear(&(p->pool)); |
|
5719 poolClear(&(p->entityValuePool)); |
|
5720 p->defaultPrefix.name = NULL; |
|
5721 p->defaultPrefix.binding = NULL; |
|
5722 |
|
5723 p->in_eldecl = XML_FALSE; |
|
5724 |
|
5725 ms->free_fcn(p->scaffIndex); |
|
5726 p->scaffIndex = NULL; |
|
5727 ms->free_fcn(p->scaffold); |
|
5728 p->scaffold = NULL; |
|
5729 |
|
5730 p->scaffLevel = 0; |
|
5731 p->scaffSize = 0; |
|
5732 p->scaffCount = 0; |
|
5733 p->contentStringLen = 0; |
|
5734 |
|
5735 p->keepProcessing = XML_TRUE; |
|
5736 p->hasParamEntityRefs = XML_FALSE; |
|
5737 p->standalone = XML_FALSE; |
|
5738 } |
|
5739 |
|
5740 static void |
|
5741 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) |
|
5742 { |
|
5743 HASH_TABLE_ITER iter; |
|
5744 hashTableIterInit(&iter, &(p->elementTypes)); |
|
5745 for (;;) { |
|
5746 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); |
|
5747 if (!e) |
|
5748 break; |
|
5749 if (e->allocDefaultAtts != 0) |
|
5750 ms->free_fcn(e->defaultAtts); |
|
5751 } |
|
5752 hashTableDestroy(&(p->generalEntities)); |
|
5753 #ifdef XML_DTD |
|
5754 hashTableDestroy(&(p->paramEntities)); |
|
5755 #endif /* XML_DTD */ |
|
5756 hashTableDestroy(&(p->elementTypes)); |
|
5757 hashTableDestroy(&(p->attributeIds)); |
|
5758 hashTableDestroy(&(p->prefixes)); |
|
5759 poolDestroy(&(p->pool)); |
|
5760 poolDestroy(&(p->entityValuePool)); |
|
5761 if (isDocEntity) { |
|
5762 ms->free_fcn(p->scaffIndex); |
|
5763 ms->free_fcn(p->scaffold); |
|
5764 } |
|
5765 ms->free_fcn(p); |
|
5766 } |
|
5767 |
|
5768 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. |
|
5769 The new DTD has already been initialized. |
|
5770 */ |
|
5771 static int |
|
5772 dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) |
|
5773 { |
|
5774 HASH_TABLE_ITER iter; |
|
5775 |
|
5776 /* Copy the prefix table. */ |
|
5777 |
|
5778 hashTableIterInit(&iter, &(oldDtd->prefixes)); |
|
5779 for (;;) { |
|
5780 const XML_Char *name; |
|
5781 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); |
|
5782 if (!oldP) |
|
5783 break; |
|
5784 name = poolCopyString(&(newDtd->pool), oldP->name); |
|
5785 if (!name) |
|
5786 return 0; |
|
5787 if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) |
|
5788 return 0; |
|
5789 } |
|
5790 |
|
5791 hashTableIterInit(&iter, &(oldDtd->attributeIds)); |
|
5792 |
|
5793 /* Copy the attribute id table. */ |
|
5794 |
|
5795 for (;;) { |
|
5796 ATTRIBUTE_ID *newA; |
|
5797 const XML_Char *name; |
|
5798 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); |
|
5799 |
|
5800 if (!oldA) |
|
5801 break; |
|
5802 /* Remember to allocate the scratch byte before the name. */ |
|
5803 if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) |
|
5804 return 0; |
|
5805 name = poolCopyString(&(newDtd->pool), oldA->name); |
|
5806 if (!name) |
|
5807 return 0; |
|
5808 ++name; |
|
5809 newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, |
|
5810 sizeof(ATTRIBUTE_ID)); |
|
5811 if (!newA) |
|
5812 return 0; |
|
5813 newA->maybeTokenized = oldA->maybeTokenized; |
|
5814 if (oldA->prefix) { |
|
5815 newA->xmlns = oldA->xmlns; |
|
5816 if (oldA->prefix == &oldDtd->defaultPrefix) |
|
5817 newA->prefix = &newDtd->defaultPrefix; |
|
5818 else |
|
5819 newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), |
|
5820 oldA->prefix->name, 0); |
|
5821 } |
|
5822 } |
|
5823 |
|
5824 /* Copy the element type table. */ |
|
5825 |
|
5826 hashTableIterInit(&iter, &(oldDtd->elementTypes)); |
|
5827 |
|
5828 for (;;) { |
|
5829 int i; |
|
5830 ELEMENT_TYPE *newE; |
|
5831 const XML_Char *name; |
|
5832 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); |
|
5833 if (!oldE) |
|
5834 break; |
|
5835 name = poolCopyString(&(newDtd->pool), oldE->name); |
|
5836 if (!name) |
|
5837 return 0; |
|
5838 newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, |
|
5839 sizeof(ELEMENT_TYPE)); |
|
5840 if (!newE) |
|
5841 return 0; |
|
5842 if (oldE->nDefaultAtts) { |
|
5843 newE->defaultAtts = (DEFAULT_ATTRIBUTE *) |
|
5844 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); |
|
5845 if (!newE->defaultAtts) { |
|
5846 ms->free_fcn(newE); |
|
5847 return 0; |
|
5848 } |
|
5849 } |
|
5850 if (oldE->idAtt) |
|
5851 newE->idAtt = (ATTRIBUTE_ID *) |
|
5852 lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); |
|
5853 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; |
|
5854 if (oldE->prefix) |
|
5855 newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), |
|
5856 oldE->prefix->name, 0); |
|
5857 for (i = 0; i < newE->nDefaultAtts; i++) { |
|
5858 newE->defaultAtts[i].id = (ATTRIBUTE_ID *) |
|
5859 lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); |
|
5860 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; |
|
5861 if (oldE->defaultAtts[i].value) { |
|
5862 newE->defaultAtts[i].value |
|
5863 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); |
|
5864 if (!newE->defaultAtts[i].value) |
|
5865 return 0; |
|
5866 } |
|
5867 else |
|
5868 newE->defaultAtts[i].value = NULL; |
|
5869 } |
|
5870 } |
|
5871 |
|
5872 /* Copy the entity tables. */ |
|
5873 if (!copyEntityTable(&(newDtd->generalEntities), |
|
5874 &(newDtd->pool), |
|
5875 &(oldDtd->generalEntities))) |
|
5876 return 0; |
|
5877 |
|
5878 #ifdef XML_DTD |
|
5879 if (!copyEntityTable(&(newDtd->paramEntities), |
|
5880 &(newDtd->pool), |
|
5881 &(oldDtd->paramEntities))) |
|
5882 return 0; |
|
5883 newDtd->paramEntityRead = oldDtd->paramEntityRead; |
|
5884 #endif /* XML_DTD */ |
|
5885 |
|
5886 newDtd->keepProcessing = oldDtd->keepProcessing; |
|
5887 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; |
|
5888 newDtd->standalone = oldDtd->standalone; |
|
5889 |
|
5890 /* Don't want deep copying for scaffolding */ |
|
5891 newDtd->in_eldecl = oldDtd->in_eldecl; |
|
5892 newDtd->scaffold = oldDtd->scaffold; |
|
5893 newDtd->contentStringLen = oldDtd->contentStringLen; |
|
5894 newDtd->scaffSize = oldDtd->scaffSize; |
|
5895 newDtd->scaffLevel = oldDtd->scaffLevel; |
|
5896 newDtd->scaffIndex = oldDtd->scaffIndex; |
|
5897 |
|
5898 return 1; |
|
5899 } /* End dtdCopy */ |
|
5900 |
|
5901 static int |
|
5902 copyEntityTable(HASH_TABLE *newTable, |
|
5903 STRING_POOL *newPool, |
|
5904 const HASH_TABLE *oldTable) |
|
5905 { |
|
5906 HASH_TABLE_ITER iter; |
|
5907 const XML_Char *cachedOldBase = NULL; |
|
5908 const XML_Char *cachedNewBase = NULL; |
|
5909 |
|
5910 hashTableIterInit(&iter, oldTable); |
|
5911 |
|
5912 for (;;) { |
|
5913 ENTITY *newE; |
|
5914 const XML_Char *name; |
|
5915 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); |
|
5916 if (!oldE) |
|
5917 break; |
|
5918 name = poolCopyString(newPool, oldE->name); |
|
5919 if (!name) |
|
5920 return 0; |
|
5921 newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); |
|
5922 if (!newE) |
|
5923 return 0; |
|
5924 if (oldE->systemId) { |
|
5925 const XML_Char *tem = poolCopyString(newPool, oldE->systemId); |
|
5926 if (!tem) |
|
5927 return 0; |
|
5928 newE->systemId = tem; |
|
5929 if (oldE->base) { |
|
5930 if (oldE->base == cachedOldBase) |
|
5931 newE->base = cachedNewBase; |
|
5932 else { |
|
5933 cachedOldBase = oldE->base; |
|
5934 tem = poolCopyString(newPool, cachedOldBase); |
|
5935 if (!tem) |
|
5936 return 0; |
|
5937 cachedNewBase = newE->base = tem; |
|
5938 } |
|
5939 } |
|
5940 if (oldE->publicId) { |
|
5941 tem = poolCopyString(newPool, oldE->publicId); |
|
5942 if (!tem) |
|
5943 return 0; |
|
5944 newE->publicId = tem; |
|
5945 } |
|
5946 } |
|
5947 else { |
|
5948 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, |
|
5949 oldE->textLen); |
|
5950 if (!tem) |
|
5951 return 0; |
|
5952 newE->textPtr = tem; |
|
5953 newE->textLen = oldE->textLen; |
|
5954 } |
|
5955 if (oldE->notation) { |
|
5956 const XML_Char *tem = poolCopyString(newPool, oldE->notation); |
|
5957 if (!tem) |
|
5958 return 0; |
|
5959 newE->notation = tem; |
|
5960 } |
|
5961 newE->is_param = oldE->is_param; |
|
5962 newE->is_internal = oldE->is_internal; |
|
5963 } |
|
5964 return 1; |
|
5965 } |
|
5966 |
|
5967 #define INIT_POWER 6 |
|
5968 |
|
5969 static XML_Bool FASTCALL |
|
5970 keyeq(KEY s1, KEY s2) |
|
5971 { |
|
5972 for (; *s1 == *s2; s1++, s2++) |
|
5973 if (*s1 == 0) |
|
5974 return XML_TRUE; |
|
5975 return XML_FALSE; |
|
5976 } |
|
5977 |
|
5978 static unsigned long FASTCALL |
|
5979 hash(KEY s) |
|
5980 { |
|
5981 unsigned long h = 0; |
|
5982 while (*s) |
|
5983 h = CHAR_HASH(h, *s++); |
|
5984 return h; |
|
5985 } |
|
5986 |
|
5987 static NAMED * |
|
5988 lookup(HASH_TABLE *table, KEY name, size_t createSize) |
|
5989 { |
|
5990 size_t i; |
|
5991 if (table->size == 0) { |
|
5992 size_t tsize; |
|
5993 if (!createSize) |
|
5994 return NULL; |
|
5995 table->power = INIT_POWER; |
|
5996 /* table->size is a power of 2 */ |
|
5997 table->size = (size_t)1 << INIT_POWER; |
|
5998 tsize = table->size * sizeof(NAMED *); |
|
5999 table->v = (NAMED **)table->mem->malloc_fcn(tsize); |
|
6000 if (!table->v) { |
|
6001 table->size = 0; |
|
6002 return NULL; |
|
6003 } |
|
6004 memset(table->v, 0, tsize); |
|
6005 i = hash(name) & ((unsigned long)table->size - 1); |
|
6006 } |
|
6007 else { |
|
6008 unsigned long h = hash(name); |
|
6009 unsigned long mask = (unsigned long)table->size - 1; |
|
6010 unsigned char step = 0; |
|
6011 i = h & mask; |
|
6012 while (table->v[i]) { |
|
6013 if (keyeq(name, table->v[i]->name)) |
|
6014 return table->v[i]; |
|
6015 if (!step) |
|
6016 step = PROBE_STEP(h, mask, table->power); |
|
6017 i < step ? (i += table->size - step) : (i -= step); |
|
6018 } |
|
6019 if (!createSize) |
|
6020 return NULL; |
|
6021 |
|
6022 /* check for overflow (table is half full) */ |
|
6023 if (table->used >> (table->power - 1)) { |
|
6024 unsigned char newPower = table->power + 1; |
|
6025 size_t newSize = (size_t)1 << newPower; |
|
6026 unsigned long newMask = (unsigned long)newSize - 1; |
|
6027 size_t tsize = newSize * sizeof(NAMED *); |
|
6028 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); |
|
6029 if (!newV) |
|
6030 return NULL; |
|
6031 memset(newV, 0, tsize); |
|
6032 for (i = 0; i < table->size; i++) |
|
6033 if (table->v[i]) { |
|
6034 unsigned long newHash = hash(table->v[i]->name); |
|
6035 size_t j = newHash & newMask; |
|
6036 step = 0; |
|
6037 while (newV[j]) { |
|
6038 if (!step) |
|
6039 step = PROBE_STEP(newHash, newMask, newPower); |
|
6040 j < step ? (j += newSize - step) : (j -= step); |
|
6041 } |
|
6042 newV[j] = table->v[i]; |
|
6043 } |
|
6044 table->mem->free_fcn(table->v); |
|
6045 table->v = newV; |
|
6046 table->power = newPower; |
|
6047 table->size = newSize; |
|
6048 i = h & newMask; |
|
6049 step = 0; |
|
6050 while (table->v[i]) { |
|
6051 if (!step) |
|
6052 step = PROBE_STEP(h, newMask, newPower); |
|
6053 i < step ? (i += newSize - step) : (i -= step); |
|
6054 } |
|
6055 } |
|
6056 } |
|
6057 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); |
|
6058 if (!table->v[i]) |
|
6059 return NULL; |
|
6060 memset(table->v[i], 0, createSize); |
|
6061 table->v[i]->name = name; |
|
6062 (table->used)++; |
|
6063 return table->v[i]; |
|
6064 } |
|
6065 |
|
6066 static void FASTCALL |
|
6067 hashTableClear(HASH_TABLE *table) |
|
6068 { |
|
6069 size_t i; |
|
6070 for (i = 0; i < table->size; i++) { |
|
6071 table->mem->free_fcn(table->v[i]); |
|
6072 table->v[i] = NULL; |
|
6073 } |
|
6074 table->used = 0; |
|
6075 } |
|
6076 |
|
6077 static void FASTCALL |
|
6078 hashTableDestroy(HASH_TABLE *table) |
|
6079 { |
|
6080 size_t i; |
|
6081 for (i = 0; i < table->size; i++) |
|
6082 table->mem->free_fcn(table->v[i]); |
|
6083 table->mem->free_fcn(table->v); |
|
6084 } |
|
6085 |
|
6086 static void FASTCALL |
|
6087 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) |
|
6088 { |
|
6089 p->power = 0; |
|
6090 p->size = 0; |
|
6091 p->used = 0; |
|
6092 p->v = NULL; |
|
6093 p->mem = ms; |
|
6094 } |
|
6095 |
|
6096 static void FASTCALL |
|
6097 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) |
|
6098 { |
|
6099 iter->p = table->v; |
|
6100 iter->end = iter->p + table->size; |
|
6101 } |
|
6102 |
|
6103 static NAMED * FASTCALL |
|
6104 hashTableIterNext(HASH_TABLE_ITER *iter) |
|
6105 { |
|
6106 while (iter->p != iter->end) { |
|
6107 NAMED *tem = *(iter->p)++; |
|
6108 if (tem) |
|
6109 return tem; |
|
6110 } |
|
6111 return NULL; |
|
6112 } |
|
6113 |
|
6114 static void FASTCALL |
|
6115 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) |
|
6116 { |
|
6117 pool->blocks = NULL; |
|
6118 pool->freeBlocks = NULL; |
|
6119 pool->start = NULL; |
|
6120 pool->ptr = NULL; |
|
6121 pool->end = NULL; |
|
6122 pool->mem = ms; |
|
6123 } |
|
6124 |
|
6125 static void FASTCALL |
|
6126 poolClear(STRING_POOL *pool) |
|
6127 { |
|
6128 if (!pool->freeBlocks) |
|
6129 pool->freeBlocks = pool->blocks; |
|
6130 else { |
|
6131 BLOCK *p = pool->blocks; |
|
6132 while (p) { |
|
6133 BLOCK *tem = p->next; |
|
6134 p->next = pool->freeBlocks; |
|
6135 pool->freeBlocks = p; |
|
6136 p = tem; |
|
6137 } |
|
6138 } |
|
6139 pool->blocks = NULL; |
|
6140 pool->start = NULL; |
|
6141 pool->ptr = NULL; |
|
6142 pool->end = NULL; |
|
6143 } |
|
6144 |
|
6145 static void FASTCALL |
|
6146 poolDestroy(STRING_POOL *pool) |
|
6147 { |
|
6148 BLOCK *p = pool->blocks; |
|
6149 while (p) { |
|
6150 BLOCK *tem = p->next; |
|
6151 pool->mem->free_fcn(p); |
|
6152 p = tem; |
|
6153 } |
|
6154 p = pool->freeBlocks; |
|
6155 while (p) { |
|
6156 BLOCK *tem = p->next; |
|
6157 pool->mem->free_fcn(p); |
|
6158 p = tem; |
|
6159 } |
|
6160 } |
|
6161 |
|
6162 static XML_Char * |
|
6163 poolAppend(STRING_POOL *pool, const ENCODING *enc, |
|
6164 const char *ptr, const char *end) |
|
6165 { |
|
6166 if (!pool->ptr && !poolGrow(pool)) |
|
6167 return NULL; |
|
6168 for (;;) { |
|
6169 XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); |
|
6170 if (ptr == end) |
|
6171 break; |
|
6172 if (!poolGrow(pool)) |
|
6173 return NULL; |
|
6174 } |
|
6175 return pool->start; |
|
6176 } |
|
6177 |
|
6178 static const XML_Char * FASTCALL |
|
6179 poolCopyString(STRING_POOL *pool, const XML_Char *s) |
|
6180 { |
|
6181 do { |
|
6182 if (!poolAppendChar(pool, *s)) |
|
6183 return NULL; |
|
6184 } while (*s++); |
|
6185 s = pool->start; |
|
6186 poolFinish(pool); |
|
6187 return s; |
|
6188 } |
|
6189 |
|
6190 static const XML_Char * |
|
6191 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) |
|
6192 { |
|
6193 if (!pool->ptr && !poolGrow(pool)) |
|
6194 return NULL; |
|
6195 for (; n > 0; --n, s++) { |
|
6196 if (!poolAppendChar(pool, *s)) |
|
6197 return NULL; |
|
6198 } |
|
6199 s = pool->start; |
|
6200 poolFinish(pool); |
|
6201 return s; |
|
6202 } |
|
6203 |
|
6204 static const XML_Char * FASTCALL |
|
6205 poolAppendString(STRING_POOL *pool, const XML_Char *s) |
|
6206 { |
|
6207 while (*s) { |
|
6208 if (!poolAppendChar(pool, *s)) |
|
6209 return NULL; |
|
6210 s++; |
|
6211 } |
|
6212 return pool->start; |
|
6213 } |
|
6214 |
|
6215 static XML_Char * |
|
6216 poolStoreString(STRING_POOL *pool, const ENCODING *enc, |
|
6217 const char *ptr, const char *end) |
|
6218 { |
|
6219 if (!poolAppend(pool, enc, ptr, end)) |
|
6220 return NULL; |
|
6221 if (pool->ptr == pool->end && !poolGrow(pool)) |
|
6222 return NULL; |
|
6223 *(pool->ptr)++ = 0; |
|
6224 return pool->start; |
|
6225 } |
|
6226 |
|
6227 static XML_Bool FASTCALL |
|
6228 poolGrow(STRING_POOL *pool) |
|
6229 { |
|
6230 if (pool->freeBlocks) { |
|
6231 if (pool->start == 0) { |
|
6232 pool->blocks = pool->freeBlocks; |
|
6233 pool->freeBlocks = pool->freeBlocks->next; |
|
6234 pool->blocks->next = NULL; |
|
6235 pool->start = pool->blocks->s; |
|
6236 pool->end = pool->start + pool->blocks->size; |
|
6237 pool->ptr = pool->start; |
|
6238 return XML_TRUE; |
|
6239 } |
|
6240 if (pool->end - pool->start < pool->freeBlocks->size) { |
|
6241 BLOCK *tem = pool->freeBlocks->next; |
|
6242 pool->freeBlocks->next = pool->blocks; |
|
6243 pool->blocks = pool->freeBlocks; |
|
6244 pool->freeBlocks = tem; |
|
6245 memcpy(pool->blocks->s, pool->start, |
|
6246 (pool->end - pool->start) * sizeof(XML_Char)); |
|
6247 pool->ptr = pool->blocks->s + (pool->ptr - pool->start); |
|
6248 pool->start = pool->blocks->s; |
|
6249 pool->end = pool->start + pool->blocks->size; |
|
6250 return XML_TRUE; |
|
6251 } |
|
6252 } |
|
6253 if (pool->blocks && pool->start == pool->blocks->s) { |
|
6254 int blockSize = (int)(pool->end - pool->start)*2; |
|
6255 pool->blocks = (BLOCK *) |
|
6256 pool->mem->realloc_fcn(pool->blocks, |
|
6257 (offsetof(BLOCK, s) |
|
6258 + blockSize * sizeof(XML_Char))); |
|
6259 if (pool->blocks == NULL) |
|
6260 return XML_FALSE; |
|
6261 pool->blocks->size = blockSize; |
|
6262 pool->ptr = pool->blocks->s + (pool->ptr - pool->start); |
|
6263 pool->start = pool->blocks->s; |
|
6264 pool->end = pool->start + blockSize; |
|
6265 } |
|
6266 else { |
|
6267 BLOCK *tem; |
|
6268 int blockSize = (int)(pool->end - pool->start); |
|
6269 if (blockSize < INIT_BLOCK_SIZE) |
|
6270 blockSize = INIT_BLOCK_SIZE; |
|
6271 else |
|
6272 blockSize *= 2; |
|
6273 tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) |
|
6274 + blockSize * sizeof(XML_Char)); |
|
6275 if (!tem) |
|
6276 return XML_FALSE; |
|
6277 tem->size = blockSize; |
|
6278 tem->next = pool->blocks; |
|
6279 pool->blocks = tem; |
|
6280 if (pool->ptr != pool->start) |
|
6281 memcpy(tem->s, pool->start, |
|
6282 (pool->ptr - pool->start) * sizeof(XML_Char)); |
|
6283 pool->ptr = tem->s + (pool->ptr - pool->start); |
|
6284 pool->start = tem->s; |
|
6285 pool->end = tem->s + blockSize; |
|
6286 } |
|
6287 return XML_TRUE; |
|
6288 } |
|
6289 |
|
6290 static int FASTCALL |
|
6291 nextScaffoldPart(XML_Parser parser) |
|
6292 { |
|
6293 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
6294 CONTENT_SCAFFOLD * me; |
|
6295 int next; |
|
6296 |
|
6297 if (!dtd->scaffIndex) { |
|
6298 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); |
|
6299 if (!dtd->scaffIndex) |
|
6300 return -1; |
|
6301 dtd->scaffIndex[0] = 0; |
|
6302 } |
|
6303 |
|
6304 if (dtd->scaffCount >= dtd->scaffSize) { |
|
6305 CONTENT_SCAFFOLD *temp; |
|
6306 if (dtd->scaffold) { |
|
6307 temp = (CONTENT_SCAFFOLD *) |
|
6308 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); |
|
6309 if (temp == NULL) |
|
6310 return -1; |
|
6311 dtd->scaffSize *= 2; |
|
6312 } |
|
6313 else { |
|
6314 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS |
|
6315 * sizeof(CONTENT_SCAFFOLD)); |
|
6316 if (temp == NULL) |
|
6317 return -1; |
|
6318 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; |
|
6319 } |
|
6320 dtd->scaffold = temp; |
|
6321 } |
|
6322 next = dtd->scaffCount++; |
|
6323 me = &dtd->scaffold[next]; |
|
6324 if (dtd->scaffLevel) { |
|
6325 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; |
|
6326 if (parent->lastchild) { |
|
6327 dtd->scaffold[parent->lastchild].nextsib = next; |
|
6328 } |
|
6329 if (!parent->childcnt) |
|
6330 parent->firstchild = next; |
|
6331 parent->lastchild = next; |
|
6332 parent->childcnt++; |
|
6333 } |
|
6334 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; |
|
6335 return next; |
|
6336 } |
|
6337 |
|
6338 static void |
|
6339 build_node(XML_Parser parser, |
|
6340 int src_node, |
|
6341 XML_Content *dest, |
|
6342 XML_Content **contpos, |
|
6343 XML_Char **strpos) |
|
6344 { |
|
6345 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
6346 dest->type = dtd->scaffold[src_node].type; |
|
6347 dest->quant = dtd->scaffold[src_node].quant; |
|
6348 if (dest->type == XML_CTYPE_NAME) { |
|
6349 const XML_Char *src; |
|
6350 dest->name = *strpos; |
|
6351 src = dtd->scaffold[src_node].name; |
|
6352 for (;;) { |
|
6353 *(*strpos)++ = *src; |
|
6354 if (!*src) |
|
6355 break; |
|
6356 src++; |
|
6357 } |
|
6358 dest->numchildren = 0; |
|
6359 dest->children = NULL; |
|
6360 } |
|
6361 else { |
|
6362 unsigned int i; |
|
6363 int cn; |
|
6364 dest->numchildren = dtd->scaffold[src_node].childcnt; |
|
6365 dest->children = *contpos; |
|
6366 *contpos += dest->numchildren; |
|
6367 for (i = 0, cn = dtd->scaffold[src_node].firstchild; |
|
6368 i < dest->numchildren; |
|
6369 i++, cn = dtd->scaffold[cn].nextsib) { |
|
6370 build_node(parser, cn, &(dest->children[i]), contpos, strpos); |
|
6371 } |
|
6372 dest->name = NULL; |
|
6373 } |
|
6374 } |
|
6375 |
|
6376 static XML_Content * |
|
6377 build_model (XML_Parser parser) |
|
6378 { |
|
6379 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
6380 XML_Content *ret; |
|
6381 XML_Content *cpos; |
|
6382 XML_Char * str; |
|
6383 int allocsize = (dtd->scaffCount * sizeof(XML_Content) |
|
6384 + (dtd->contentStringLen * sizeof(XML_Char))); |
|
6385 |
|
6386 ret = (XML_Content *)MALLOC(allocsize); |
|
6387 if (!ret) |
|
6388 return NULL; |
|
6389 |
|
6390 str = (XML_Char *) (&ret[dtd->scaffCount]); |
|
6391 cpos = &ret[1]; |
|
6392 |
|
6393 build_node(parser, 0, ret, &cpos, &str); |
|
6394 return ret; |
|
6395 } |
|
6396 |
|
6397 static ELEMENT_TYPE * |
|
6398 getElementType(XML_Parser parser, |
|
6399 const ENCODING *enc, |
|
6400 const char *ptr, |
|
6401 const char *end) |
|
6402 { |
|
6403 DTD * const dtd = _dtd; /* save one level of indirection */ |
|
6404 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); |
|
6405 ELEMENT_TYPE *ret; |
|
6406 |
|
6407 if (!name) |
|
6408 return NULL; |
|
6409 ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); |
|
6410 if (!ret) |
|
6411 return NULL; |
|
6412 if (ret->name != name) |
|
6413 poolDiscard(&dtd->pool); |
|
6414 else { |
|
6415 poolFinish(&dtd->pool); |
|
6416 if (!setElementTypePrefix(parser, ret)) |
|
6417 return NULL; |
|
6418 } |
|
6419 return ret; |
|
6420 } |