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