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