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