1 /* 2 * SAX2.c : Default SAX2 handler to build a tree. 3 * 4 * See Copyright for the status of this software. 5 * 6 * Daniel Veillard <daniel (at) veillard.com> 7 */ 8 9 10 #define IN_LIBXML 11 #include "libxml.h" 12 #include <stdlib.h> 13 #include <string.h> 14 #include <limits.h> 15 #include <libxml/xmlmemory.h> 16 #include <libxml/tree.h> 17 #include <libxml/parser.h> 18 #include <libxml/parserInternals.h> 19 #include <libxml/valid.h> 20 #include <libxml/entities.h> 21 #include <libxml/xmlerror.h> 22 #include <libxml/debugXML.h> 23 #include <libxml/xmlIO.h> 24 #include <libxml/SAX.h> 25 #include <libxml/uri.h> 26 #include <libxml/valid.h> 27 #include <libxml/HTMLtree.h> 28 #include <libxml/globals.h> 29 30 /* Define SIZE_T_MAX unless defined through <limits.h>. */ 31 #ifndef SIZE_T_MAX 32 # define SIZE_T_MAX ((size_t)-1) 33 #endif /* !SIZE_T_MAX */ 34 35 /* #define DEBUG_SAX2 */ 36 /* #define DEBUG_SAX2_TREE */ 37 38 /** 39 * TODO: 40 * 41 * macro to flag unimplemented blocks 42 * XML_CATALOG_PREFER user env to select between system/public prefered 43 * option. C.f. Richard Tobin <richard (at) cogsci.ed.ac.uk> 44 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with 45 *> values "system" and "public". I have made the default be "system" to 46 *> match yours. 47 */ 48 #define TODO \ 49 xmlGenericError(xmlGenericErrorContext, \ 50 "Unimplemented block at %s:%d\n", \ 51 __FILE__, __LINE__); 52 53 /* 54 * xmlSAX2ErrMemory: 55 * @ctxt: an XML validation parser context 56 * @msg: a string to accompany the error message 57 */ 58 static void 59 xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) { 60 if (ctxt != NULL) { 61 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 62 ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg); 63 ctxt->errNo = XML_ERR_NO_MEMORY; 64 ctxt->instate = XML_PARSER_EOF; 65 ctxt->disableSAX = 1; 66 } 67 } 68 69 /** 70 * xmlValidError: 71 * @ctxt: an XML validation parser context 72 * @error: the error number 73 * @msg: the error message 74 * @str1: extra data 75 * @str2: extra data 76 * 77 * Handle a validation error 78 */ 79 static void 80 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error, 81 const char *msg, const char *str1, const char *str2) 82 { 83 xmlStructuredErrorFunc schannel = NULL; 84 85 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 86 (ctxt->instate == XML_PARSER_EOF)) 87 return; 88 if (ctxt != NULL) { 89 ctxt->errNo = error; 90 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) 91 schannel = ctxt->sax->serror; 92 __xmlRaiseError(schannel, 93 ctxt->vctxt.error, ctxt->vctxt.userData, 94 ctxt, NULL, XML_FROM_DTD, error, 95 XML_ERR_ERROR, NULL, 0, (const char *) str1, 96 (const char *) str2, NULL, 0, 0, 97 msg, (const char *) str1, (const char *) str2); 98 ctxt->valid = 0; 99 } else { 100 __xmlRaiseError(schannel, 101 NULL, NULL, 102 ctxt, NULL, XML_FROM_DTD, error, 103 XML_ERR_ERROR, NULL, 0, (const char *) str1, 104 (const char *) str2, NULL, 0, 0, 105 msg, (const char *) str1, (const char *) str2); 106 } 107 } 108 109 /** 110 * xmlFatalErrMsg: 111 * @ctxt: an XML parser context 112 * @error: the error number 113 * @msg: the error message 114 * @str1: an error string 115 * @str2: an error string 116 * 117 * Handle a fatal parser error, i.e. violating Well-Formedness constraints 118 */ 119 static void 120 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 121 const char *msg, const xmlChar *str1, const xmlChar *str2) 122 { 123 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 124 (ctxt->instate == XML_PARSER_EOF)) 125 return; 126 if (ctxt != NULL) 127 ctxt->errNo = error; 128 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, 129 XML_ERR_FATAL, NULL, 0, 130 (const char *) str1, (const char *) str2, 131 NULL, 0, 0, msg, str1, str2); 132 if (ctxt != NULL) { 133 ctxt->wellFormed = 0; 134 ctxt->valid = 0; 135 if (ctxt->recovery == 0) 136 ctxt->disableSAX = 1; 137 } 138 } 139 140 /** 141 * xmlWarnMsg: 142 * @ctxt: an XML parser context 143 * @error: the error number 144 * @msg: the error message 145 * @str1: an error string 146 * @str2: an error string 147 * 148 * Handle a parser warning 149 */ 150 static void 151 xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 152 const char *msg, const xmlChar *str1) 153 { 154 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 155 (ctxt->instate == XML_PARSER_EOF)) 156 return; 157 if (ctxt != NULL) 158 ctxt->errNo = error; 159 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, 160 XML_ERR_WARNING, NULL, 0, 161 (const char *) str1, NULL, 162 NULL, 0, 0, msg, str1); 163 } 164 165 /** 166 * xmlNsErrMsg: 167 * @ctxt: an XML parser context 168 * @error: the error number 169 * @msg: the error message 170 * @str1: an error string 171 * @str2: an error string 172 * 173 * Handle a namespace error 174 */ 175 static void 176 xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 177 const char *msg, const xmlChar *str1, const xmlChar *str2) 178 { 179 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 180 (ctxt->instate == XML_PARSER_EOF)) 181 return; 182 if (ctxt != NULL) 183 ctxt->errNo = error; 184 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, 185 XML_ERR_ERROR, NULL, 0, 186 (const char *) str1, (const char *) str2, 187 NULL, 0, 0, msg, str1, str2); 188 } 189 190 /** 191 * xmlNsWarnMsg: 192 * @ctxt: an XML parser context 193 * @error: the error number 194 * @msg: the error message 195 * @str1: an error string 196 * 197 * Handle a namespace warning 198 */ 199 static void 200 xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 201 const char *msg, const xmlChar *str1, const xmlChar *str2) 202 { 203 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 204 (ctxt->instate == XML_PARSER_EOF)) 205 return; 206 if (ctxt != NULL) 207 ctxt->errNo = error; 208 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, 209 XML_ERR_WARNING, NULL, 0, 210 (const char *) str1, (const char *) str2, 211 NULL, 0, 0, msg, str1, str2); 212 } 213 214 /** 215 * xmlSAX2GetPublicId: 216 * @ctx: the user data (XML parser context) 217 * 218 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN" 219 * 220 * Returns a xmlChar * 221 */ 222 const xmlChar * 223 xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED) 224 { 225 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 226 return(NULL); 227 } 228 229 /** 230 * xmlSAX2GetSystemId: 231 * @ctx: the user data (XML parser context) 232 * 233 * Provides the system ID, basically URL or filename e.g. 234 * http://www.sgmlsource.com/dtds/memo.dtd 235 * 236 * Returns a xmlChar * 237 */ 238 const xmlChar * 239 xmlSAX2GetSystemId(void *ctx) 240 { 241 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 242 if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL); 243 return((const xmlChar *) ctxt->input->filename); 244 } 245 246 /** 247 * xmlSAX2GetLineNumber: 248 * @ctx: the user data (XML parser context) 249 * 250 * Provide the line number of the current parsing point. 251 * 252 * Returns an int 253 */ 254 int 255 xmlSAX2GetLineNumber(void *ctx) 256 { 257 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 258 if ((ctx == NULL) || (ctxt->input == NULL)) return(0); 259 return(ctxt->input->line); 260 } 261 262 /** 263 * xmlSAX2GetColumnNumber: 264 * @ctx: the user data (XML parser context) 265 * 266 * Provide the column number of the current parsing point. 267 * 268 * Returns an int 269 */ 270 int 271 xmlSAX2GetColumnNumber(void *ctx) 272 { 273 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 274 if ((ctx == NULL) || (ctxt->input == NULL)) return(0); 275 return(ctxt->input->col); 276 } 277 278 /** 279 * xmlSAX2IsStandalone: 280 * @ctx: the user data (XML parser context) 281 * 282 * Is this document tagged standalone ? 283 * 284 * Returns 1 if true 285 */ 286 int 287 xmlSAX2IsStandalone(void *ctx) 288 { 289 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 290 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0); 291 return(ctxt->myDoc->standalone == 1); 292 } 293 294 /** 295 * xmlSAX2HasInternalSubset: 296 * @ctx: the user data (XML parser context) 297 * 298 * Does this document has an internal subset 299 * 300 * Returns 1 if true 301 */ 302 int 303 xmlSAX2HasInternalSubset(void *ctx) 304 { 305 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 306 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0); 307 return(ctxt->myDoc->intSubset != NULL); 308 } 309 310 /** 311 * xmlSAX2HasExternalSubset: 312 * @ctx: the user data (XML parser context) 313 * 314 * Does this document has an external subset 315 * 316 * Returns 1 if true 317 */ 318 int 319 xmlSAX2HasExternalSubset(void *ctx) 320 { 321 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 322 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0); 323 return(ctxt->myDoc->extSubset != NULL); 324 } 325 326 /** 327 * xmlSAX2InternalSubset: 328 * @ctx: the user data (XML parser context) 329 * @name: the root element name 330 * @ExternalID: the external ID 331 * @SystemID: the SYSTEM ID (e.g. filename or URL) 332 * 333 * Callback on internal subset declaration. 334 */ 335 void 336 xmlSAX2InternalSubset(void *ctx, const xmlChar *name, 337 const xmlChar *ExternalID, const xmlChar *SystemID) 338 { 339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 340 xmlDtdPtr dtd; 341 if (ctx == NULL) return; 342 #ifdef DEBUG_SAX 343 xmlGenericError(xmlGenericErrorContext, 344 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n", 345 name, ExternalID, SystemID); 346 #endif 347 348 if (ctxt->myDoc == NULL) 349 return; 350 dtd = xmlGetIntSubset(ctxt->myDoc); 351 if (dtd != NULL) { 352 if (ctxt->html) 353 return; 354 xmlUnlinkNode((xmlNodePtr) dtd); 355 xmlFreeDtd(dtd); 356 ctxt->myDoc->intSubset = NULL; 357 } 358 ctxt->myDoc->intSubset = 359 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID); 360 if (ctxt->myDoc->intSubset == NULL) 361 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset"); 362 } 363 364 /** 365 * xmlSAX2ExternalSubset: 366 * @ctx: the user data (XML parser context) 367 * @name: the root element name 368 * @ExternalID: the external ID 369 * @SystemID: the SYSTEM ID (e.g. filename or URL) 370 * 371 * Callback on external subset declaration. 372 */ 373 void 374 xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, 375 const xmlChar *ExternalID, const xmlChar *SystemID) 376 { 377 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 378 if (ctx == NULL) return; 379 #ifdef DEBUG_SAX 380 xmlGenericError(xmlGenericErrorContext, 381 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n", 382 name, ExternalID, SystemID); 383 #endif 384 if (((ExternalID != NULL) || (SystemID != NULL)) && 385 (((ctxt->validate) || (ctxt->loadsubset != 0)) && 386 (ctxt->wellFormed && ctxt->myDoc))) { 387 /* 388 * Try to fetch and parse the external subset. 389 */ 390 xmlParserInputPtr oldinput; 391 int oldinputNr; 392 int oldinputMax; 393 xmlParserInputPtr *oldinputTab; 394 xmlParserInputPtr input = NULL; 395 xmlCharEncoding enc; 396 int oldcharset; 397 398 /* 399 * Ask the Entity resolver to load the damn thing 400 */ 401 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) 402 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, 403 SystemID); 404 if (input == NULL) { 405 return; 406 } 407 408 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID); 409 410 /* 411 * make sure we won't destroy the main document context 412 */ 413 oldinput = ctxt->input; 414 oldinputNr = ctxt->inputNr; 415 oldinputMax = ctxt->inputMax; 416 oldinputTab = ctxt->inputTab; 417 oldcharset = ctxt->charset; 418 419 ctxt->inputTab = (xmlParserInputPtr *) 420 xmlMalloc(5 * sizeof(xmlParserInputPtr)); 421 if (ctxt->inputTab == NULL) { 422 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset"); 423 ctxt->input = oldinput; 424 ctxt->inputNr = oldinputNr; 425 ctxt->inputMax = oldinputMax; 426 ctxt->inputTab = oldinputTab; 427 ctxt->charset = oldcharset; 428 return; 429 } 430 ctxt->inputNr = 0; 431 ctxt->inputMax = 5; 432 ctxt->input = NULL; 433 xmlPushInput(ctxt, input); 434 435 /* 436 * On the fly encoding conversion if needed 437 */ 438 if (ctxt->input->length >= 4) { 439 enc = xmlDetectCharEncoding(ctxt->input->cur, 4); 440 xmlSwitchEncoding(ctxt, enc); 441 } 442 443 if (input->filename == NULL) 444 input->filename = (char *) xmlCanonicPath(SystemID); 445 input->line = 1; 446 input->col = 1; 447 input->base = ctxt->input->cur; 448 input->cur = ctxt->input->cur; 449 input->free = NULL; 450 451 /* 452 * let's parse that entity knowing it's an external subset. 453 */ 454 xmlParseExternalSubset(ctxt, ExternalID, SystemID); 455 456 /* 457 * Free up the external entities 458 */ 459 460 while (ctxt->inputNr > 1) 461 xmlPopInput(ctxt); 462 xmlFreeInputStream(ctxt->input); 463 xmlFree(ctxt->inputTab); 464 465 /* 466 * Restore the parsing context of the main entity 467 */ 468 ctxt->input = oldinput; 469 ctxt->inputNr = oldinputNr; 470 ctxt->inputMax = oldinputMax; 471 ctxt->inputTab = oldinputTab; 472 ctxt->charset = oldcharset; 473 /* ctxt->wellFormed = oldwellFormed; */ 474 } 475 } 476 477 /** 478 * xmlSAX2ResolveEntity: 479 * @ctx: the user data (XML parser context) 480 * @publicId: The public ID of the entity 481 * @systemId: The system ID of the entity 482 * 483 * The entity loader, to control the loading of external entities, 484 * the application can either: 485 * - override this xmlSAX2ResolveEntity() callback in the SAX block 486 * - or better use the xmlSetExternalEntityLoader() function to 487 * set up it's own entity resolution routine 488 * 489 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 490 */ 491 xmlParserInputPtr 492 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId) 493 { 494 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 495 xmlParserInputPtr ret; 496 xmlChar *URI; 497 const char *base = NULL; 498 499 if (ctx == NULL) return(NULL); 500 if (ctxt->input != NULL) 501 base = ctxt->input->filename; 502 if (base == NULL) 503 base = ctxt->directory; 504 505 URI = xmlBuildURI(systemId, (const xmlChar *) base); 506 507 #ifdef DEBUG_SAX 508 xmlGenericError(xmlGenericErrorContext, 509 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId); 510 #endif 511 512 ret = xmlLoadExternalEntity((const char *) URI, 513 (const char *) publicId, ctxt); 514 if (URI != NULL) 515 xmlFree(URI); 516 return(ret); 517 } 518 519 /** 520 * xmlSAX2GetEntity: 521 * @ctx: the user data (XML parser context) 522 * @name: The entity name 523 * 524 * Get an entity by name 525 * 526 * Returns the xmlEntityPtr if found. 527 */ 528 xmlEntityPtr 529 xmlSAX2GetEntity(void *ctx, const xmlChar *name) 530 { 531 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 532 xmlEntityPtr ret = NULL; 533 534 if (ctx == NULL) return(NULL); 535 #ifdef DEBUG_SAX 536 xmlGenericError(xmlGenericErrorContext, 537 "SAX.xmlSAX2GetEntity(%s)\n", name); 538 #endif 539 540 if (ctxt->inSubset == 0) { 541 ret = xmlGetPredefinedEntity(name); 542 if (ret != NULL) 543 return(ret); 544 } 545 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) { 546 if (ctxt->inSubset == 2) { 547 ctxt->myDoc->standalone = 0; 548 ret = xmlGetDocEntity(ctxt->myDoc, name); 549 ctxt->myDoc->standalone = 1; 550 } else { 551 ret = xmlGetDocEntity(ctxt->myDoc, name); 552 if (ret == NULL) { 553 ctxt->myDoc->standalone = 0; 554 ret = xmlGetDocEntity(ctxt->myDoc, name); 555 if (ret != NULL) { 556 xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE, 557 "Entity(%s) document marked standalone but requires external subset\n", 558 name, NULL); 559 } 560 ctxt->myDoc->standalone = 1; 561 } 562 } 563 } else { 564 ret = xmlGetDocEntity(ctxt->myDoc, name); 565 } 566 if ((ret != NULL) && 567 ((ctxt->validate) || (ctxt->replaceEntities)) && 568 (ret->children == NULL) && 569 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { 570 int val; 571 572 /* 573 * for validation purposes we really need to fetch and 574 * parse the external entity 575 */ 576 xmlNodePtr children; 577 578 val = xmlParseCtxtExternalEntity(ctxt, ret->URI, 579 ret->ExternalID, &children); 580 if (val == 0) { 581 xmlAddChildList((xmlNodePtr) ret, children); 582 } else { 583 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING, 584 "Failure to process entity %s\n", name, NULL); 585 ctxt->validate = 0; 586 return(NULL); 587 } 588 ret->owner = 1; 589 if (ret->checked == 0) 590 ret->checked = 1; 591 } 592 return(ret); 593 } 594 595 /** 596 * xmlSAX2GetParameterEntity: 597 * @ctx: the user data (XML parser context) 598 * @name: The entity name 599 * 600 * Get a parameter entity by name 601 * 602 * Returns the xmlEntityPtr if found. 603 */ 604 xmlEntityPtr 605 xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name) 606 { 607 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 608 xmlEntityPtr ret; 609 610 if (ctx == NULL) return(NULL); 611 #ifdef DEBUG_SAX 612 xmlGenericError(xmlGenericErrorContext, 613 "SAX.xmlSAX2GetParameterEntity(%s)\n", name); 614 #endif 615 616 ret = xmlGetParameterEntity(ctxt->myDoc, name); 617 return(ret); 618 } 619 620 621 /** 622 * xmlSAX2EntityDecl: 623 * @ctx: the user data (XML parser context) 624 * @name: the entity name 625 * @type: the entity type 626 * @publicId: The public ID of the entity 627 * @systemId: The system ID of the entity 628 * @content: the entity value (without processing). 629 * 630 * An entity definition has been parsed 631 */ 632 void 633 xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type, 634 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 635 { 636 xmlEntityPtr ent; 637 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 638 639 if (ctx == NULL) return; 640 #ifdef DEBUG_SAX 641 xmlGenericError(xmlGenericErrorContext, 642 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n", 643 name, type, publicId, systemId, content); 644 #endif 645 if (ctxt->inSubset == 1) { 646 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId, 647 systemId, content); 648 if ((ent == NULL) && (ctxt->pedantic)) 649 xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED, 650 "Entity(%s) already defined in the internal subset\n", 651 name); 652 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 653 xmlChar *URI; 654 const char *base = NULL; 655 656 if (ctxt->input != NULL) 657 base = ctxt->input->filename; 658 if (base == NULL) 659 base = ctxt->directory; 660 661 URI = xmlBuildURI(systemId, (const xmlChar *) base); 662 ent->URI = URI; 663 } 664 } else if (ctxt->inSubset == 2) { 665 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId, 666 systemId, content); 667 if ((ent == NULL) && (ctxt->pedantic) && 668 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 669 ctxt->sax->warning(ctxt->userData, 670 "Entity(%s) already defined in the external subset\n", name); 671 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 672 xmlChar *URI; 673 const char *base = NULL; 674 675 if (ctxt->input != NULL) 676 base = ctxt->input->filename; 677 if (base == NULL) 678 base = ctxt->directory; 679 680 URI = xmlBuildURI(systemId, (const xmlChar *) base); 681 ent->URI = URI; 682 } 683 } else { 684 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING, 685 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", 686 name, NULL); 687 } 688 } 689 690 /** 691 * xmlSAX2AttributeDecl: 692 * @ctx: the user data (XML parser context) 693 * @elem: the name of the element 694 * @fullname: the attribute name 695 * @type: the attribute type 696 * @def: the type of default value 697 * @defaultValue: the attribute default value 698 * @tree: the tree of enumerated value set 699 * 700 * An attribute definition has been parsed 701 */ 702 void 703 xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, 704 int type, int def, const xmlChar *defaultValue, 705 xmlEnumerationPtr tree) 706 { 707 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 708 xmlAttributePtr attr; 709 xmlChar *name = NULL, *prefix = NULL; 710 711 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) 712 return; 713 714 #ifdef DEBUG_SAX 715 xmlGenericError(xmlGenericErrorContext, 716 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n", 717 elem, fullname, type, def, defaultValue); 718 #endif 719 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) && 720 (type != XML_ATTRIBUTE_ID)) { 721 /* 722 * Raise the error but keep the validity flag 723 */ 724 int tmp = ctxt->valid; 725 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE, 726 "xml:id : attribute type should be ID\n", NULL, NULL); 727 ctxt->valid = tmp; 728 } 729 /* TODO: optimize name/prefix allocation */ 730 name = xmlSplitQName(ctxt, fullname, &prefix); 731 ctxt->vctxt.valid = 1; 732 if (ctxt->inSubset == 1) 733 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem, 734 name, prefix, (xmlAttributeType) type, 735 (xmlAttributeDefault) def, defaultValue, tree); 736 else if (ctxt->inSubset == 2) 737 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem, 738 name, prefix, (xmlAttributeType) type, 739 (xmlAttributeDefault) def, defaultValue, tree); 740 else { 741 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, 742 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", 743 name, NULL); 744 xmlFreeEnumeration(tree); 745 return; 746 } 747 #ifdef LIBXML_VALID_ENABLED 748 if (ctxt->vctxt.valid == 0) 749 ctxt->valid = 0; 750 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) && 751 (ctxt->myDoc->intSubset != NULL)) 752 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc, 753 attr); 754 #endif /* LIBXML_VALID_ENABLED */ 755 if (prefix != NULL) 756 xmlFree(prefix); 757 if (name != NULL) 758 xmlFree(name); 759 } 760 761 /** 762 * xmlSAX2ElementDecl: 763 * @ctx: the user data (XML parser context) 764 * @name: the element name 765 * @type: the element type 766 * @content: the element value tree 767 * 768 * An element definition has been parsed 769 */ 770 void 771 xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type, 772 xmlElementContentPtr content) 773 { 774 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 775 xmlElementPtr elem = NULL; 776 777 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) 778 return; 779 780 #ifdef DEBUG_SAX 781 xmlGenericError(xmlGenericErrorContext, 782 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type); 783 #endif 784 785 if (ctxt->inSubset == 1) 786 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, 787 name, (xmlElementTypeVal) type, content); 788 else if (ctxt->inSubset == 2) 789 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, 790 name, (xmlElementTypeVal) type, content); 791 else { 792 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, 793 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n", 794 name, NULL); 795 return; 796 } 797 #ifdef LIBXML_VALID_ENABLED 798 if (elem == NULL) 799 ctxt->valid = 0; 800 if (ctxt->validate && ctxt->wellFormed && 801 ctxt->myDoc && ctxt->myDoc->intSubset) 802 ctxt->valid &= 803 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem); 804 #endif /* LIBXML_VALID_ENABLED */ 805 } 806 807 /** 808 * xmlSAX2NotationDecl: 809 * @ctx: the user data (XML parser context) 810 * @name: The name of the notation 811 * @publicId: The public ID of the entity 812 * @systemId: The system ID of the entity 813 * 814 * What to do when a notation declaration has been parsed. 815 */ 816 void 817 xmlSAX2NotationDecl(void *ctx, const xmlChar *name, 818 const xmlChar *publicId, const xmlChar *systemId) 819 { 820 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 821 xmlNotationPtr nota = NULL; 822 823 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) 824 return; 825 826 #ifdef DEBUG_SAX 827 xmlGenericError(xmlGenericErrorContext, 828 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId); 829 #endif 830 831 if ((publicId == NULL) && (systemId == NULL)) { 832 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING, 833 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", 834 name, NULL); 835 return; 836 } else if (ctxt->inSubset == 1) 837 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name, 838 publicId, systemId); 839 else if (ctxt->inSubset == 2) 840 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name, 841 publicId, systemId); 842 else { 843 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING, 844 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", 845 name, NULL); 846 return; 847 } 848 #ifdef LIBXML_VALID_ENABLED 849 if (nota == NULL) ctxt->valid = 0; 850 if ((ctxt->validate) && (ctxt->wellFormed) && 851 (ctxt->myDoc->intSubset != NULL)) 852 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc, 853 nota); 854 #endif /* LIBXML_VALID_ENABLED */ 855 } 856 857 /** 858 * xmlSAX2UnparsedEntityDecl: 859 * @ctx: the user data (XML parser context) 860 * @name: The name of the entity 861 * @publicId: The public ID of the entity 862 * @systemId: The system ID of the entity 863 * @notationName: the name of the notation 864 * 865 * What to do when an unparsed entity declaration is parsed 866 */ 867 void 868 xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name, 869 const xmlChar *publicId, const xmlChar *systemId, 870 const xmlChar *notationName) 871 { 872 xmlEntityPtr ent; 873 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 874 if (ctx == NULL) return; 875 #ifdef DEBUG_SAX 876 xmlGenericError(xmlGenericErrorContext, 877 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n", 878 name, publicId, systemId, notationName); 879 #endif 880 if (ctxt->inSubset == 1) { 881 ent = xmlAddDocEntity(ctxt->myDoc, name, 882 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, 883 publicId, systemId, notationName); 884 if ((ent == NULL) && (ctxt->pedantic) && 885 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 886 ctxt->sax->warning(ctxt->userData, 887 "Entity(%s) already defined in the internal subset\n", name); 888 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 889 xmlChar *URI; 890 const char *base = NULL; 891 892 if (ctxt->input != NULL) 893 base = ctxt->input->filename; 894 if (base == NULL) 895 base = ctxt->directory; 896 897 URI = xmlBuildURI(systemId, (const xmlChar *) base); 898 ent->URI = URI; 899 } 900 } else if (ctxt->inSubset == 2) { 901 ent = xmlAddDtdEntity(ctxt->myDoc, name, 902 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, 903 publicId, systemId, notationName); 904 if ((ent == NULL) && (ctxt->pedantic) && 905 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 906 ctxt->sax->warning(ctxt->userData, 907 "Entity(%s) already defined in the external subset\n", name); 908 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 909 xmlChar *URI; 910 const char *base = NULL; 911 912 if (ctxt->input != NULL) 913 base = ctxt->input->filename; 914 if (base == NULL) 915 base = ctxt->directory; 916 917 URI = xmlBuildURI(systemId, (const xmlChar *) base); 918 ent->URI = URI; 919 } 920 } else { 921 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, 922 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", 923 name, NULL); 924 } 925 } 926 927 /** 928 * xmlSAX2SetDocumentLocator: 929 * @ctx: the user data (XML parser context) 930 * @loc: A SAX Locator 931 * 932 * Receive the document locator at startup, actually xmlDefaultSAXLocator 933 * Everything is available on the context, so this is useless in our case. 934 */ 935 void 936 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED) 937 { 938 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 939 #ifdef DEBUG_SAX 940 xmlGenericError(xmlGenericErrorContext, 941 "SAX.xmlSAX2SetDocumentLocator()\n"); 942 #endif 943 } 944 945 /** 946 * xmlSAX2StartDocument: 947 * @ctx: the user data (XML parser context) 948 * 949 * called when the document start being processed. 950 */ 951 void 952 xmlSAX2StartDocument(void *ctx) 953 { 954 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 955 xmlDocPtr doc; 956 957 if (ctx == NULL) return; 958 959 #ifdef DEBUG_SAX 960 xmlGenericError(xmlGenericErrorContext, 961 "SAX.xmlSAX2StartDocument()\n"); 962 #endif 963 if (ctxt->html) { 964 #ifdef LIBXML_HTML_ENABLED 965 if (ctxt->myDoc == NULL) 966 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); 967 ctxt->myDoc->properties = XML_DOC_HTML; 968 ctxt->myDoc->parseFlags = ctxt->options; 969 if (ctxt->myDoc == NULL) { 970 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); 971 return; 972 } 973 #else 974 xmlGenericError(xmlGenericErrorContext, 975 "libxml2 built without HTML support\n"); 976 ctxt->errNo = XML_ERR_INTERNAL_ERROR; 977 ctxt->instate = XML_PARSER_EOF; 978 ctxt->disableSAX = 1; 979 return; 980 #endif 981 } else { 982 doc = ctxt->myDoc = xmlNewDoc(ctxt->version); 983 if (doc != NULL) { 984 doc->properties = 0; 985 if (ctxt->options & XML_PARSE_OLD10) 986 doc->properties |= XML_DOC_OLD10; 987 doc->parseFlags = ctxt->options; 988 if (ctxt->encoding != NULL) 989 doc->encoding = xmlStrdup(ctxt->encoding); 990 else 991 doc->encoding = NULL; 992 doc->standalone = ctxt->standalone; 993 } else { 994 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); 995 return; 996 } 997 if ((ctxt->dictNames) && (doc != NULL)) { 998 doc->dict = ctxt->dict; 999 xmlDictReference(doc->dict); 1000 } 1001 } 1002 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) && 1003 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) { 1004 ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename); 1005 if (ctxt->myDoc->URL == NULL) 1006 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); 1007 } 1008 } 1009 1010 /** 1011 * xmlSAX2EndDocument: 1012 * @ctx: the user data (XML parser context) 1013 * 1014 * called when the document end has been detected. 1015 */ 1016 void 1017 xmlSAX2EndDocument(void *ctx) 1018 { 1019 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1020 #ifdef DEBUG_SAX 1021 xmlGenericError(xmlGenericErrorContext, 1022 "SAX.xmlSAX2EndDocument()\n"); 1023 #endif 1024 if (ctx == NULL) return; 1025 #ifdef LIBXML_VALID_ENABLED 1026 if (ctxt->validate && ctxt->wellFormed && 1027 ctxt->myDoc && ctxt->myDoc->intSubset) 1028 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc); 1029 #endif /* LIBXML_VALID_ENABLED */ 1030 1031 /* 1032 * Grab the encoding if it was added on-the-fly 1033 */ 1034 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) && 1035 (ctxt->myDoc->encoding == NULL)) { 1036 ctxt->myDoc->encoding = ctxt->encoding; 1037 ctxt->encoding = NULL; 1038 } 1039 if ((ctxt->inputTab != NULL) && 1040 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) && 1041 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) && 1042 (ctxt->myDoc->encoding == NULL)) { 1043 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding); 1044 } 1045 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) && 1046 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) { 1047 ctxt->myDoc->charset = ctxt->charset; 1048 } 1049 } 1050 1051 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) 1052 /** 1053 * xmlSAX2AttributeInternal: 1054 * @ctx: the user data (XML parser context) 1055 * @fullname: The attribute name, including namespace prefix 1056 * @value: The attribute value 1057 * @prefix: the prefix on the element node 1058 * 1059 * Handle an attribute that has been read by the parser. 1060 * The default handling is to convert the attribute into an 1061 * DOM subtree and past it in a new xmlAttr element added to 1062 * the element. 1063 */ 1064 static void 1065 xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, 1066 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED) 1067 { 1068 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1069 xmlAttrPtr ret; 1070 xmlChar *name; 1071 xmlChar *ns; 1072 xmlChar *nval; 1073 xmlNsPtr namespace; 1074 1075 if (ctxt->html) { 1076 name = xmlStrdup(fullname); 1077 ns = NULL; 1078 namespace = NULL; 1079 } else { 1080 /* 1081 * Split the full name into a namespace prefix and the tag name 1082 */ 1083 name = xmlSplitQName(ctxt, fullname, &ns); 1084 if ((name != NULL) && (name[0] == 0)) { 1085 if (xmlStrEqual(ns, BAD_CAST "xmlns")) { 1086 xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR, 1087 "invalid namespace declaration '%s'\n", 1088 fullname, NULL); 1089 } else { 1090 xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN, 1091 "Avoid attribute ending with ':' like '%s'\n", 1092 fullname, NULL); 1093 } 1094 if (ns != NULL) 1095 xmlFree(ns); 1096 ns = NULL; 1097 xmlFree(name); 1098 name = xmlStrdup(fullname); 1099 } 1100 } 1101 if (name == NULL) { 1102 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1103 if (ns != NULL) 1104 xmlFree(ns); 1105 return; 1106 } 1107 1108 #ifdef LIBXML_HTML_ENABLED 1109 if ((ctxt->html) && 1110 (value == NULL) && (htmlIsBooleanAttr(fullname))) { 1111 nval = xmlStrdup(fullname); 1112 value = (const xmlChar *) nval; 1113 } else 1114 #endif 1115 { 1116 #ifdef LIBXML_VALID_ENABLED 1117 /* 1118 * Do the last stage of the attribute normalization 1119 * Needed for HTML too: 1120 * http://www.w3.org/TR/html4/types.html#h-6.2 1121 */ 1122 ctxt->vctxt.valid = 1; 1123 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt, 1124 ctxt->myDoc, ctxt->node, 1125 fullname, value); 1126 if (ctxt->vctxt.valid != 1) { 1127 ctxt->valid = 0; 1128 } 1129 if (nval != NULL) 1130 value = nval; 1131 #else 1132 nval = NULL; 1133 #endif /* LIBXML_VALID_ENABLED */ 1134 } 1135 1136 /* 1137 * Check whether it's a namespace definition 1138 */ 1139 if ((!ctxt->html) && (ns == NULL) && 1140 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && 1141 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) { 1142 xmlNsPtr nsret; 1143 xmlChar *val; 1144 1145 if (!ctxt->replaceEntities) { 1146 ctxt->depth++; 1147 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1148 0,0,0); 1149 ctxt->depth--; 1150 } else { 1151 val = (xmlChar *) value; 1152 } 1153 1154 if (val[0] != 0) { 1155 xmlURIPtr uri; 1156 1157 uri = xmlParseURI((const char *)val); 1158 if (uri == NULL) { 1159 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 1160 ctxt->sax->warning(ctxt->userData, 1161 "xmlns: %s not a valid URI\n", val); 1162 } else { 1163 if (uri->scheme == NULL) { 1164 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 1165 ctxt->sax->warning(ctxt->userData, 1166 "xmlns: URI %s is not absolute\n", val); 1167 } 1168 xmlFreeURI(uri); 1169 } 1170 } 1171 1172 /* a default namespace definition */ 1173 nsret = xmlNewNs(ctxt->node, val, NULL); 1174 1175 #ifdef LIBXML_VALID_ENABLED 1176 /* 1177 * Validate also for namespace decls, they are attributes from 1178 * an XML-1.0 perspective 1179 */ 1180 if (nsret != NULL && ctxt->validate && ctxt->wellFormed && 1181 ctxt->myDoc && ctxt->myDoc->intSubset) 1182 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 1183 ctxt->node, prefix, nsret, val); 1184 #endif /* LIBXML_VALID_ENABLED */ 1185 if (name != NULL) 1186 xmlFree(name); 1187 if (nval != NULL) 1188 xmlFree(nval); 1189 if (val != value) 1190 xmlFree(val); 1191 return; 1192 } 1193 if ((!ctxt->html) && 1194 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && 1195 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) { 1196 xmlNsPtr nsret; 1197 xmlChar *val; 1198 1199 if (!ctxt->replaceEntities) { 1200 ctxt->depth++; 1201 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1202 0,0,0); 1203 ctxt->depth--; 1204 if (val == NULL) { 1205 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1206 xmlFree(ns); 1207 if (name != NULL) 1208 xmlFree(name); 1209 return; 1210 } 1211 } else { 1212 val = (xmlChar *) value; 1213 } 1214 1215 if (val[0] == 0) { 1216 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY, 1217 "Empty namespace name for prefix %s\n", name, NULL); 1218 } 1219 if ((ctxt->pedantic != 0) && (val[0] != 0)) { 1220 xmlURIPtr uri; 1221 1222 uri = xmlParseURI((const char *)val); 1223 if (uri == NULL) { 1224 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI, 1225 "xmlns:%s: %s not a valid URI\n", name, value); 1226 } else { 1227 if (uri->scheme == NULL) { 1228 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE, 1229 "xmlns:%s: URI %s is not absolute\n", name, value); 1230 } 1231 xmlFreeURI(uri); 1232 } 1233 } 1234 1235 /* a standard namespace definition */ 1236 nsret = xmlNewNs(ctxt->node, val, name); 1237 xmlFree(ns); 1238 #ifdef LIBXML_VALID_ENABLED 1239 /* 1240 * Validate also for namespace decls, they are attributes from 1241 * an XML-1.0 perspective 1242 */ 1243 if (nsret != NULL && ctxt->validate && ctxt->wellFormed && 1244 ctxt->myDoc && ctxt->myDoc->intSubset) 1245 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 1246 ctxt->node, prefix, nsret, value); 1247 #endif /* LIBXML_VALID_ENABLED */ 1248 if (name != NULL) 1249 xmlFree(name); 1250 if (nval != NULL) 1251 xmlFree(nval); 1252 if (val != value) 1253 xmlFree(val); 1254 return; 1255 } 1256 1257 if (ns != NULL) { 1258 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns); 1259 1260 if (namespace == NULL) { 1261 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 1262 "Namespace prefix %s of attribute %s is not defined\n", 1263 ns, name); 1264 } else { 1265 xmlAttrPtr prop; 1266 1267 prop = ctxt->node->properties; 1268 while (prop != NULL) { 1269 if (prop->ns != NULL) { 1270 if ((xmlStrEqual(name, prop->name)) && 1271 ((namespace == prop->ns) || 1272 (xmlStrEqual(namespace->href, prop->ns->href)))) { 1273 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED, 1274 "Attribute %s in %s redefined\n", 1275 name, namespace->href); 1276 ctxt->wellFormed = 0; 1277 if (ctxt->recovery == 0) ctxt->disableSAX = 1; 1278 goto error; 1279 } 1280 } 1281 prop = prop->next; 1282 } 1283 } 1284 } else { 1285 namespace = NULL; 1286 } 1287 1288 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */ 1289 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL); 1290 1291 if (ret != NULL) { 1292 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { 1293 xmlNodePtr tmp; 1294 1295 ret->children = xmlStringGetNodeList(ctxt->myDoc, value); 1296 tmp = ret->children; 1297 while (tmp != NULL) { 1298 tmp->parent = (xmlNodePtr) ret; 1299 if (tmp->next == NULL) 1300 ret->last = tmp; 1301 tmp = tmp->next; 1302 } 1303 } else if (value != NULL) { 1304 ret->children = xmlNewDocText(ctxt->myDoc, value); 1305 ret->last = ret->children; 1306 if (ret->children != NULL) 1307 ret->children->parent = (xmlNodePtr) ret; 1308 } 1309 } 1310 1311 #ifdef LIBXML_VALID_ENABLED 1312 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 1313 ctxt->myDoc && ctxt->myDoc->intSubset) { 1314 1315 /* 1316 * If we don't substitute entities, the validation should be 1317 * done on a value with replaced entities anyway. 1318 */ 1319 if (!ctxt->replaceEntities) { 1320 xmlChar *val; 1321 1322 ctxt->depth++; 1323 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1324 0,0,0); 1325 ctxt->depth--; 1326 1327 if (val == NULL) 1328 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 1329 ctxt->myDoc, ctxt->node, ret, value); 1330 else { 1331 xmlChar *nvalnorm; 1332 1333 /* 1334 * Do the last stage of the attribute normalization 1335 * It need to be done twice ... it's an extra burden related 1336 * to the ability to keep xmlSAX2References in attributes 1337 */ 1338 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc, 1339 ctxt->node, fullname, val); 1340 if (nvalnorm != NULL) { 1341 xmlFree(val); 1342 val = nvalnorm; 1343 } 1344 1345 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 1346 ctxt->myDoc, ctxt->node, ret, val); 1347 xmlFree(val); 1348 } 1349 } else { 1350 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, 1351 ctxt->node, ret, value); 1352 } 1353 } else 1354 #endif /* LIBXML_VALID_ENABLED */ 1355 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && 1356 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || 1357 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { 1358 /* 1359 * when validating, the ID registration is done at the attribute 1360 * validation level. Otherwise we have to do specific handling here. 1361 */ 1362 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) { 1363 /* 1364 * Add the xml:id value 1365 * 1366 * Open issue: normalization of the value. 1367 */ 1368 if (xmlValidateNCName(value, 1) != 0) { 1369 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, 1370 "xml:id : attribute value %s is not an NCName\n", 1371 (const char *) value, NULL); 1372 } 1373 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); 1374 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) 1375 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); 1376 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) 1377 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret); 1378 } 1379 1380 error: 1381 if (nval != NULL) 1382 xmlFree(nval); 1383 if (ns != NULL) 1384 xmlFree(ns); 1385 } 1386 1387 /* 1388 * xmlCheckDefaultedAttributes: 1389 * 1390 * Check defaulted attributes from the DTD 1391 */ 1392 static void 1393 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, 1394 const xmlChar *prefix, const xmlChar **atts) { 1395 xmlElementPtr elemDecl; 1396 const xmlChar *att; 1397 int internal = 1; 1398 int i; 1399 1400 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix); 1401 if (elemDecl == NULL) { 1402 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix); 1403 internal = 0; 1404 } 1405 1406 process_external_subset: 1407 1408 if (elemDecl != NULL) { 1409 xmlAttributePtr attr = elemDecl->attributes; 1410 /* 1411 * Check against defaulted attributes from the external subset 1412 * if the document is stamped as standalone 1413 */ 1414 if ((ctxt->myDoc->standalone == 1) && 1415 (ctxt->myDoc->extSubset != NULL) && 1416 (ctxt->validate)) { 1417 while (attr != NULL) { 1418 if ((attr->defaultValue != NULL) && 1419 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset, 1420 attr->elem, attr->name, 1421 attr->prefix) == attr) && 1422 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, 1423 attr->elem, attr->name, 1424 attr->prefix) == NULL)) { 1425 xmlChar *fulln; 1426 1427 if (attr->prefix != NULL) { 1428 fulln = xmlStrdup(attr->prefix); 1429 fulln = xmlStrcat(fulln, BAD_CAST ":"); 1430 fulln = xmlStrcat(fulln, attr->name); 1431 } else { 1432 fulln = xmlStrdup(attr->name); 1433 } 1434 if (fulln == NULL) { 1435 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1436 break; 1437 } 1438 1439 /* 1440 * Check that the attribute is not declared in the 1441 * serialization 1442 */ 1443 att = NULL; 1444 if (atts != NULL) { 1445 i = 0; 1446 att = atts[i]; 1447 while (att != NULL) { 1448 if (xmlStrEqual(att, fulln)) 1449 break; 1450 i += 2; 1451 att = atts[i]; 1452 } 1453 } 1454 if (att == NULL) { 1455 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED, 1456 "standalone: attribute %s on %s defaulted from external subset\n", 1457 (const char *)fulln, 1458 (const char *)attr->elem); 1459 } 1460 xmlFree(fulln); 1461 } 1462 attr = attr->nexth; 1463 } 1464 } 1465 1466 /* 1467 * Actually insert defaulted values when needed 1468 */ 1469 attr = elemDecl->attributes; 1470 while (attr != NULL) { 1471 /* 1472 * Make sure that attributes redefinition occuring in the 1473 * internal subset are not overriden by definitions in the 1474 * external subset. 1475 */ 1476 if (attr->defaultValue != NULL) { 1477 /* 1478 * the element should be instantiated in the tree if: 1479 * - this is a namespace prefix 1480 * - the user required for completion in the tree 1481 * like XSLT 1482 * - there isn't already an attribute definition 1483 * in the internal subset overriding it. 1484 */ 1485 if (((attr->prefix != NULL) && 1486 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) || 1487 ((attr->prefix == NULL) && 1488 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) || 1489 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) { 1490 xmlAttributePtr tst; 1491 1492 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, 1493 attr->elem, attr->name, 1494 attr->prefix); 1495 if ((tst == attr) || (tst == NULL)) { 1496 xmlChar fn[50]; 1497 xmlChar *fulln; 1498 1499 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50); 1500 if (fulln == NULL) { 1501 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1502 return; 1503 } 1504 1505 /* 1506 * Check that the attribute is not declared in the 1507 * serialization 1508 */ 1509 att = NULL; 1510 if (atts != NULL) { 1511 i = 0; 1512 att = atts[i]; 1513 while (att != NULL) { 1514 if (xmlStrEqual(att, fulln)) 1515 break; 1516 i += 2; 1517 att = atts[i]; 1518 } 1519 } 1520 if (att == NULL) { 1521 xmlSAX2AttributeInternal(ctxt, fulln, 1522 attr->defaultValue, prefix); 1523 } 1524 if ((fulln != fn) && (fulln != attr->name)) 1525 xmlFree(fulln); 1526 } 1527 } 1528 } 1529 attr = attr->nexth; 1530 } 1531 if (internal == 1) { 1532 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, 1533 name, prefix); 1534 internal = 0; 1535 goto process_external_subset; 1536 } 1537 } 1538 } 1539 1540 /** 1541 * xmlSAX2StartElement: 1542 * @ctx: the user data (XML parser context) 1543 * @fullname: The element name, including namespace prefix 1544 * @atts: An array of name/value attributes pairs, NULL terminated 1545 * 1546 * called when an opening tag has been processed. 1547 */ 1548 void 1549 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) 1550 { 1551 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1552 xmlNodePtr ret; 1553 xmlNodePtr parent; 1554 xmlNsPtr ns; 1555 xmlChar *name; 1556 xmlChar *prefix; 1557 const xmlChar *att; 1558 const xmlChar *value; 1559 int i; 1560 1561 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return; 1562 parent = ctxt->node; 1563 #ifdef DEBUG_SAX 1564 xmlGenericError(xmlGenericErrorContext, 1565 "SAX.xmlSAX2StartElement(%s)\n", fullname); 1566 #endif 1567 1568 /* 1569 * First check on validity: 1570 */ 1571 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 1572 ((ctxt->myDoc->intSubset == NULL) || 1573 ((ctxt->myDoc->intSubset->notations == NULL) && 1574 (ctxt->myDoc->intSubset->elements == NULL) && 1575 (ctxt->myDoc->intSubset->attributes == NULL) && 1576 (ctxt->myDoc->intSubset->entities == NULL)))) { 1577 xmlErrValid(ctxt, XML_ERR_NO_DTD, 1578 "Validation failed: no DTD found !", NULL, NULL); 1579 ctxt->validate = 0; 1580 } 1581 1582 1583 /* 1584 * Split the full name into a namespace prefix and the tag name 1585 */ 1586 name = xmlSplitQName(ctxt, fullname, &prefix); 1587 1588 1589 /* 1590 * Note : the namespace resolution is deferred until the end of the 1591 * attributes parsing, since local namespace can be defined as 1592 * an attribute at this level. 1593 */ 1594 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); 1595 if (ret == NULL) { 1596 if (prefix != NULL) 1597 xmlFree(prefix); 1598 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1599 return; 1600 } 1601 if (ctxt->myDoc->children == NULL) { 1602 #ifdef DEBUG_SAX_TREE 1603 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); 1604 #endif 1605 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 1606 } else if (parent == NULL) { 1607 parent = ctxt->myDoc->children; 1608 } 1609 ctxt->nodemem = -1; 1610 if (ctxt->linenumbers) { 1611 if (ctxt->input != NULL) { 1612 if (ctxt->input->line < 65535) 1613 ret->line = (short) ctxt->input->line; 1614 else 1615 ret->line = 65535; 1616 } 1617 } 1618 1619 /* 1620 * We are parsing a new node. 1621 */ 1622 #ifdef DEBUG_SAX_TREE 1623 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); 1624 #endif 1625 nodePush(ctxt, ret); 1626 1627 /* 1628 * Link the child element 1629 */ 1630 if (parent != NULL) { 1631 if (parent->type == XML_ELEMENT_NODE) { 1632 #ifdef DEBUG_SAX_TREE 1633 xmlGenericError(xmlGenericErrorContext, 1634 "adding child %s to %s\n", name, parent->name); 1635 #endif 1636 xmlAddChild(parent, ret); 1637 } else { 1638 #ifdef DEBUG_SAX_TREE 1639 xmlGenericError(xmlGenericErrorContext, 1640 "adding sibling %s to ", name); 1641 xmlDebugDumpOneNode(stderr, parent, 0); 1642 #endif 1643 xmlAddSibling(parent, ret); 1644 } 1645 } 1646 1647 /* 1648 * Insert all the defaulted attributes from the DTD especially namespaces 1649 */ 1650 if ((!ctxt->html) && 1651 ((ctxt->myDoc->intSubset != NULL) || 1652 (ctxt->myDoc->extSubset != NULL))) { 1653 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts); 1654 } 1655 1656 /* 1657 * process all the attributes whose name start with "xmlns" 1658 */ 1659 if (atts != NULL) { 1660 i = 0; 1661 att = atts[i++]; 1662 value = atts[i++]; 1663 if (!ctxt->html) { 1664 while ((att != NULL) && (value != NULL)) { 1665 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') && 1666 (att[3] == 'n') && (att[4] == 's')) 1667 xmlSAX2AttributeInternal(ctxt, att, value, prefix); 1668 1669 att = atts[i++]; 1670 value = atts[i++]; 1671 } 1672 } 1673 } 1674 1675 /* 1676 * Search the namespace, note that since the attributes have been 1677 * processed, the local namespaces are available. 1678 */ 1679 ns = xmlSearchNs(ctxt->myDoc, ret, prefix); 1680 if ((ns == NULL) && (parent != NULL)) 1681 ns = xmlSearchNs(ctxt->myDoc, parent, prefix); 1682 if ((prefix != NULL) && (ns == NULL)) { 1683 ns = xmlNewNs(ret, NULL, prefix); 1684 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 1685 "Namespace prefix %s is not defined\n", 1686 prefix, NULL); 1687 } 1688 1689 /* 1690 * set the namespace node, making sure that if the default namspace 1691 * is unbound on a parent we simply kee it NULL 1692 */ 1693 if ((ns != NULL) && (ns->href != NULL) && 1694 ((ns->href[0] != 0) || (ns->prefix != NULL))) 1695 xmlSetNs(ret, ns); 1696 1697 /* 1698 * process all the other attributes 1699 */ 1700 if (atts != NULL) { 1701 i = 0; 1702 att = atts[i++]; 1703 value = atts[i++]; 1704 if (ctxt->html) { 1705 while (att != NULL) { 1706 xmlSAX2AttributeInternal(ctxt, att, value, NULL); 1707 att = atts[i++]; 1708 value = atts[i++]; 1709 } 1710 } else { 1711 while ((att != NULL) && (value != NULL)) { 1712 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') || 1713 (att[3] != 'n') || (att[4] != 's')) 1714 xmlSAX2AttributeInternal(ctxt, att, value, NULL); 1715 1716 /* 1717 * Next ones 1718 */ 1719 att = atts[i++]; 1720 value = atts[i++]; 1721 } 1722 } 1723 } 1724 1725 #ifdef LIBXML_VALID_ENABLED 1726 /* 1727 * If it's the Document root, finish the DTD validation and 1728 * check the document root element for validity 1729 */ 1730 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { 1731 int chk; 1732 1733 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); 1734 if (chk <= 0) 1735 ctxt->valid = 0; 1736 if (chk < 0) 1737 ctxt->wellFormed = 0; 1738 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 1739 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; 1740 } 1741 #endif /* LIBXML_VALID_ENABLED */ 1742 1743 if (prefix != NULL) 1744 xmlFree(prefix); 1745 1746 } 1747 1748 /** 1749 * xmlSAX2EndElement: 1750 * @ctx: the user data (XML parser context) 1751 * @name: The element name 1752 * 1753 * called when the end of an element has been detected. 1754 */ 1755 void 1756 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) 1757 { 1758 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1759 xmlParserNodeInfo node_info; 1760 xmlNodePtr cur; 1761 1762 if (ctx == NULL) return; 1763 cur = ctxt->node; 1764 #ifdef DEBUG_SAX 1765 if (name == NULL) 1766 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); 1767 else 1768 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name); 1769 #endif 1770 1771 /* Capture end position and add node */ 1772 if (cur != NULL && ctxt->record_info) { 1773 node_info.end_pos = ctxt->input->cur - ctxt->input->base; 1774 node_info.end_line = ctxt->input->line; 1775 node_info.node = cur; 1776 xmlParserAddNodeInfo(ctxt, &node_info); 1777 } 1778 ctxt->nodemem = -1; 1779 1780 #ifdef LIBXML_VALID_ENABLED 1781 if (ctxt->validate && ctxt->wellFormed && 1782 ctxt->myDoc && ctxt->myDoc->intSubset) 1783 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, 1784 cur); 1785 #endif /* LIBXML_VALID_ENABLED */ 1786 1787 1788 /* 1789 * end of parsing of this node. 1790 */ 1791 #ifdef DEBUG_SAX_TREE 1792 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); 1793 #endif 1794 nodePop(ctxt); 1795 } 1796 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */ 1797 1798 /* 1799 * xmlSAX2TextNode: 1800 * @ctxt: the parser context 1801 * @str: the input string 1802 * @len: the string length 1803 * 1804 * Remove the entities from an attribute value 1805 * 1806 * Returns the newly allocated string or NULL if not needed or error 1807 */ 1808 static xmlNodePtr 1809 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { 1810 xmlNodePtr ret; 1811 const xmlChar *intern = NULL; 1812 1813 /* 1814 * Allocate 1815 */ 1816 if (ctxt->freeElems != NULL) { 1817 ret = ctxt->freeElems; 1818 ctxt->freeElems = ret->next; 1819 ctxt->freeElemsNr--; 1820 } else { 1821 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); 1822 } 1823 if (ret == NULL) { 1824 xmlErrMemory(ctxt, "xmlSAX2Characters"); 1825 return(NULL); 1826 } 1827 memset(ret, 0, sizeof(xmlNode)); 1828 /* 1829 * intern the formatting blanks found between tags, or the 1830 * very short strings 1831 */ 1832 if (ctxt->dictNames) { 1833 xmlChar cur = str[len]; 1834 1835 if ((len < (int) (2 * sizeof(void *))) && 1836 (ctxt->options & XML_PARSE_COMPACT)) { 1837 /* store the string in the node overrithing properties and nsDef */ 1838 xmlChar *tmp = (xmlChar *) &(ret->properties); 1839 memcpy(tmp, str, len); 1840 tmp[len] = 0; 1841 intern = tmp; 1842 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') || 1843 ((cur == '<') && (str[len + 1] != '!')))) { 1844 intern = xmlDictLookup(ctxt->dict, str, len); 1845 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && 1846 (str[len + 1] != '!')) { 1847 int i; 1848 1849 for (i = 1;i < len;i++) { 1850 if (!IS_BLANK_CH(str[i])) goto skip; 1851 } 1852 intern = xmlDictLookup(ctxt->dict, str, len); 1853 } 1854 } 1855 skip: 1856 ret->type = XML_TEXT_NODE; 1857 1858 ret->name = xmlStringText; 1859 if (intern == NULL) { 1860 ret->content = xmlStrndup(str, len); 1861 if (ret->content == NULL) { 1862 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode"); 1863 xmlFree(ret); 1864 return(NULL); 1865 } 1866 } else 1867 ret->content = (xmlChar *) intern; 1868 1869 if (ctxt->input != NULL) 1870 ret->line = ctxt->input->line; 1871 1872 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 1873 xmlRegisterNodeDefaultValue(ret); 1874 return(ret); 1875 } 1876 1877 #ifdef LIBXML_VALID_ENABLED 1878 /* 1879 * xmlSAX2DecodeAttrEntities: 1880 * @ctxt: the parser context 1881 * @str: the input string 1882 * @len: the string length 1883 * 1884 * Remove the entities from an attribute value 1885 * 1886 * Returns the newly allocated string or NULL if not needed or error 1887 */ 1888 static xmlChar * 1889 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, 1890 const xmlChar *end) { 1891 const xmlChar *in; 1892 xmlChar *ret; 1893 1894 in = str; 1895 while (in < end) 1896 if (*in++ == '&') 1897 goto decode; 1898 return(NULL); 1899 decode: 1900 ctxt->depth++; 1901 ret = xmlStringLenDecodeEntities(ctxt, str, end - str, 1902 XML_SUBSTITUTE_REF, 0,0,0); 1903 ctxt->depth--; 1904 return(ret); 1905 } 1906 #endif /* LIBXML_VALID_ENABLED */ 1907 1908 /** 1909 * xmlSAX2AttributeNs: 1910 * @ctx: the user data (XML parser context) 1911 * @localname: the local name of the attribute 1912 * @prefix: the attribute namespace prefix if available 1913 * @URI: the attribute namespace name if available 1914 * @value: Start of the attribute value 1915 * @valueend: end of the attribute value 1916 * 1917 * Handle an attribute that has been read by the parser. 1918 * The default handling is to convert the attribute into an 1919 * DOM subtree and past it in a new xmlAttr element added to 1920 * the element. 1921 */ 1922 static void 1923 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, 1924 const xmlChar * localname, 1925 const xmlChar * prefix, 1926 const xmlChar * value, 1927 const xmlChar * valueend) 1928 { 1929 xmlAttrPtr ret; 1930 xmlNsPtr namespace = NULL; 1931 xmlChar *dup = NULL; 1932 1933 /* 1934 * Note: if prefix == NULL, the attribute is not in the default namespace 1935 */ 1936 if (prefix != NULL) 1937 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); 1938 1939 /* 1940 * allocate the node 1941 */ 1942 if (ctxt->freeAttrs != NULL) { 1943 ret = ctxt->freeAttrs; 1944 ctxt->freeAttrs = ret->next; 1945 ctxt->freeAttrsNr--; 1946 memset(ret, 0, sizeof(xmlAttr)); 1947 ret->type = XML_ATTRIBUTE_NODE; 1948 1949 ret->parent = ctxt->node; 1950 ret->doc = ctxt->myDoc; 1951 ret->ns = namespace; 1952 1953 if (ctxt->dictNames) 1954 ret->name = localname; 1955 else 1956 ret->name = xmlStrdup(localname); 1957 1958 /* link at the end to preserv order, TODO speed up with a last */ 1959 if (ctxt->node->properties == NULL) { 1960 ctxt->node->properties = ret; 1961 } else { 1962 xmlAttrPtr prev = ctxt->node->properties; 1963 1964 while (prev->next != NULL) prev = prev->next; 1965 prev->next = ret; 1966 ret->prev = prev; 1967 } 1968 1969 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 1970 xmlRegisterNodeDefaultValue((xmlNodePtr)ret); 1971 } else { 1972 if (ctxt->dictNames) 1973 ret = xmlNewNsPropEatName(ctxt->node, namespace, 1974 (xmlChar *) localname, NULL); 1975 else 1976 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL); 1977 if (ret == NULL) { 1978 xmlErrMemory(ctxt, "xmlSAX2AttributeNs"); 1979 return; 1980 } 1981 } 1982 1983 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { 1984 xmlNodePtr tmp; 1985 1986 /* 1987 * We know that if there is an entity reference, then 1988 * the string has been dup'ed and terminates with 0 1989 * otherwise with ' or " 1990 */ 1991 if (*valueend != 0) { 1992 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); 1993 ret->children = tmp; 1994 ret->last = tmp; 1995 if (tmp != NULL) { 1996 tmp->doc = ret->doc; 1997 tmp->parent = (xmlNodePtr) ret; 1998 } 1999 } else { 2000 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, 2001 valueend - value); 2002 tmp = ret->children; 2003 while (tmp != NULL) { 2004 tmp->doc = ret->doc; 2005 tmp->parent = (xmlNodePtr) ret; 2006 if (tmp->next == NULL) 2007 ret->last = tmp; 2008 tmp = tmp->next; 2009 } 2010 } 2011 } else if (value != NULL) { 2012 xmlNodePtr tmp; 2013 2014 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); 2015 ret->children = tmp; 2016 ret->last = tmp; 2017 if (tmp != NULL) { 2018 tmp->doc = ret->doc; 2019 tmp->parent = (xmlNodePtr) ret; 2020 } 2021 } 2022 2023 #ifdef LIBXML_VALID_ENABLED 2024 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 2025 ctxt->myDoc && ctxt->myDoc->intSubset) { 2026 /* 2027 * If we don't substitute entities, the validation should be 2028 * done on a value with replaced entities anyway. 2029 */ 2030 if (!ctxt->replaceEntities) { 2031 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend); 2032 if (dup == NULL) { 2033 if (*valueend == 0) { 2034 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2035 ctxt->myDoc, ctxt->node, ret, value); 2036 } else { 2037 /* 2038 * That should already be normalized. 2039 * cheaper to finally allocate here than duplicate 2040 * entry points in the full validation code 2041 */ 2042 dup = xmlStrndup(value, valueend - value); 2043 2044 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2045 ctxt->myDoc, ctxt->node, ret, dup); 2046 } 2047 } else { 2048 /* 2049 * dup now contains a string of the flattened attribute 2050 * content with entities substitued. Check if we need to 2051 * apply an extra layer of normalization. 2052 * It need to be done twice ... it's an extra burden related 2053 * to the ability to keep references in attributes 2054 */ 2055 if (ctxt->attsSpecial != NULL) { 2056 xmlChar *nvalnorm; 2057 xmlChar fn[50]; 2058 xmlChar *fullname; 2059 2060 fullname = xmlBuildQName(localname, prefix, fn, 50); 2061 if (fullname != NULL) { 2062 ctxt->vctxt.valid = 1; 2063 nvalnorm = xmlValidCtxtNormalizeAttributeValue( 2064 &ctxt->vctxt, ctxt->myDoc, 2065 ctxt->node, fullname, dup); 2066 if (ctxt->vctxt.valid != 1) 2067 ctxt->valid = 0; 2068 2069 if ((fullname != fn) && (fullname != localname)) 2070 xmlFree(fullname); 2071 if (nvalnorm != NULL) { 2072 xmlFree(dup); 2073 dup = nvalnorm; 2074 } 2075 } 2076 } 2077 2078 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2079 ctxt->myDoc, ctxt->node, ret, dup); 2080 } 2081 } else { 2082 /* 2083 * if entities already have been substitued, then 2084 * the attribute as passed is already normalized 2085 */ 2086 dup = xmlStrndup(value, valueend - value); 2087 2088 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2089 ctxt->myDoc, ctxt->node, ret, dup); 2090 } 2091 } else 2092 #endif /* LIBXML_VALID_ENABLED */ 2093 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && 2094 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || 2095 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { 2096 /* 2097 * when validating, the ID registration is done at the attribute 2098 * validation level. Otherwise we have to do specific handling here. 2099 */ 2100 if ((prefix == ctxt->str_xml) && 2101 (localname[0] == 'i') && (localname[1] == 'd') && 2102 (localname[2] == 0)) { 2103 /* 2104 * Add the xml:id value 2105 * 2106 * Open issue: normalization of the value. 2107 */ 2108 if (dup == NULL) 2109 dup = xmlStrndup(value, valueend - value); 2110 #ifdef LIBXML_VALID_ENABLED 2111 if (xmlValidateNCName(dup, 1) != 0) { 2112 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, 2113 "xml:id : attribute value %s is not an NCName\n", 2114 (const char *) dup, NULL); 2115 } 2116 #endif 2117 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2118 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { 2119 /* might be worth duplicate entry points and not copy */ 2120 if (dup == NULL) 2121 dup = xmlStrndup(value, valueend - value); 2122 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2123 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) { 2124 if (dup == NULL) 2125 dup = xmlStrndup(value, valueend - value); 2126 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2127 } 2128 } 2129 if (dup != NULL) 2130 xmlFree(dup); 2131 } 2132 2133 /** 2134 * xmlSAX2StartElementNs: 2135 * @ctx: the user data (XML parser context) 2136 * @localname: the local name of the element 2137 * @prefix: the element namespace prefix if available 2138 * @URI: the element namespace name if available 2139 * @nb_namespaces: number of namespace definitions on that node 2140 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions 2141 * @nb_attributes: the number of attributes on that node 2142 * @nb_defaulted: the number of defaulted attributes. 2143 * @attributes: pointer to the array of (localname/prefix/URI/value/end) 2144 * attribute values. 2145 * 2146 * SAX2 callback when an element start has been detected by the parser. 2147 * It provides the namespace informations for the element, as well as 2148 * the new namespace declarations on the element. 2149 */ 2150 void 2151 xmlSAX2StartElementNs(void *ctx, 2152 const xmlChar *localname, 2153 const xmlChar *prefix, 2154 const xmlChar *URI, 2155 int nb_namespaces, 2156 const xmlChar **namespaces, 2157 int nb_attributes, 2158 int nb_defaulted, 2159 const xmlChar **attributes) 2160 { 2161 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2162 xmlNodePtr ret; 2163 xmlNodePtr parent; 2164 xmlNsPtr last = NULL, ns; 2165 const xmlChar *uri, *pref; 2166 xmlChar *lname = NULL; 2167 int i, j; 2168 2169 if (ctx == NULL) return; 2170 parent = ctxt->node; 2171 /* 2172 * First check on validity: 2173 */ 2174 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 2175 ((ctxt->myDoc->intSubset == NULL) || 2176 ((ctxt->myDoc->intSubset->notations == NULL) && 2177 (ctxt->myDoc->intSubset->elements == NULL) && 2178 (ctxt->myDoc->intSubset->attributes == NULL) && 2179 (ctxt->myDoc->intSubset->entities == NULL)))) { 2180 xmlErrValid(ctxt, XML_ERR_NO_DTD, 2181 "Validation failed: no DTD found !", NULL, NULL); 2182 ctxt->validate = 0; 2183 } 2184 2185 /* 2186 * Take care of the rare case of an undefined namespace prefix 2187 */ 2188 if ((prefix != NULL) && (URI == NULL)) { 2189 if (ctxt->dictNames) { 2190 const xmlChar *fullname; 2191 2192 fullname = xmlDictQLookup(ctxt->dict, prefix, localname); 2193 if (fullname != NULL) 2194 localname = fullname; 2195 } else { 2196 lname = xmlBuildQName(localname, prefix, NULL, 0); 2197 } 2198 } 2199 /* 2200 * allocate the node 2201 */ 2202 if (ctxt->freeElems != NULL) { 2203 ret = ctxt->freeElems; 2204 ctxt->freeElems = ret->next; 2205 ctxt->freeElemsNr--; 2206 memset(ret, 0, sizeof(xmlNode)); 2207 ret->type = XML_ELEMENT_NODE; 2208 2209 if (ctxt->dictNames) 2210 ret->name = localname; 2211 else { 2212 if (lname == NULL) 2213 ret->name = xmlStrdup(localname); 2214 else 2215 ret->name = lname; 2216 if (ret->name == NULL) { 2217 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2218 return; 2219 } 2220 } 2221 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 2222 xmlRegisterNodeDefaultValue(ret); 2223 } else { 2224 if (ctxt->dictNames) 2225 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, 2226 (xmlChar *) localname, NULL); 2227 else if (lname == NULL) 2228 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL); 2229 else 2230 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, 2231 (xmlChar *) lname, NULL); 2232 if (ret == NULL) { 2233 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2234 return; 2235 } 2236 } 2237 if (ctxt->linenumbers) { 2238 if (ctxt->input != NULL) { 2239 if (ctxt->input->line < 65535) 2240 ret->line = (short) ctxt->input->line; 2241 else 2242 ret->line = 65535; 2243 } 2244 } 2245 2246 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2247 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2248 } 2249 /* 2250 * Build the namespace list 2251 */ 2252 for (i = 0,j = 0;j < nb_namespaces;j++) { 2253 pref = namespaces[i++]; 2254 uri = namespaces[i++]; 2255 ns = xmlNewNs(NULL, uri, pref); 2256 if (ns != NULL) { 2257 if (last == NULL) { 2258 ret->nsDef = last = ns; 2259 } else { 2260 last->next = ns; 2261 last = ns; 2262 } 2263 if ((URI != NULL) && (prefix == pref)) 2264 ret->ns = ns; 2265 } else { 2266 /* 2267 * any out of memory error would already have been raised 2268 * but we can't be garanteed it's the actual error due to the 2269 * API, best is to skip in this case 2270 */ 2271 continue; 2272 } 2273 #ifdef LIBXML_VALID_ENABLED 2274 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 2275 ctxt->myDoc && ctxt->myDoc->intSubset) { 2276 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 2277 ret, prefix, ns, uri); 2278 } 2279 #endif /* LIBXML_VALID_ENABLED */ 2280 } 2281 ctxt->nodemem = -1; 2282 2283 /* 2284 * We are parsing a new node. 2285 */ 2286 nodePush(ctxt, ret); 2287 2288 /* 2289 * Link the child element 2290 */ 2291 if (parent != NULL) { 2292 if (parent->type == XML_ELEMENT_NODE) { 2293 xmlAddChild(parent, ret); 2294 } else { 2295 xmlAddSibling(parent, ret); 2296 } 2297 } 2298 2299 /* 2300 * Insert the defaulted attributes from the DTD only if requested: 2301 */ 2302 if ((nb_defaulted != 0) && 2303 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0)) 2304 nb_attributes -= nb_defaulted; 2305 2306 /* 2307 * Search the namespace if it wasn't already found 2308 * Note that, if prefix is NULL, this searches for the default Ns 2309 */ 2310 if ((URI != NULL) && (ret->ns == NULL)) { 2311 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix); 2312 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { 2313 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix); 2314 } 2315 if (ret->ns == NULL) { 2316 ns = xmlNewNs(ret, NULL, prefix); 2317 if (ns == NULL) { 2318 2319 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2320 return; 2321 } 2322 if (prefix != NULL) 2323 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 2324 "Namespace prefix %s was not found\n", 2325 prefix, NULL); 2326 else 2327 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 2328 "Namespace default prefix was not found\n", 2329 NULL, NULL); 2330 } 2331 } 2332 2333 /* 2334 * process all the other attributes 2335 */ 2336 if (nb_attributes > 0) { 2337 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) { 2338 /* 2339 * Handle the rare case of an undefined atribute prefix 2340 */ 2341 if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) { 2342 if (ctxt->dictNames) { 2343 const xmlChar *fullname; 2344 2345 fullname = xmlDictQLookup(ctxt->dict, attributes[j+1], 2346 attributes[j]); 2347 if (fullname != NULL) { 2348 xmlSAX2AttributeNs(ctxt, fullname, NULL, 2349 attributes[j+3], attributes[j+4]); 2350 continue; 2351 } 2352 } else { 2353 lname = xmlBuildQName(attributes[j], attributes[j+1], 2354 NULL, 0); 2355 if (lname != NULL) { 2356 xmlSAX2AttributeNs(ctxt, lname, NULL, 2357 attributes[j+3], attributes[j+4]); 2358 xmlFree(lname); 2359 continue; 2360 } 2361 } 2362 } 2363 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], 2364 attributes[j+3], attributes[j+4]); 2365 } 2366 } 2367 2368 #ifdef LIBXML_VALID_ENABLED 2369 /* 2370 * If it's the Document root, finish the DTD validation and 2371 * check the document root element for validity 2372 */ 2373 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { 2374 int chk; 2375 2376 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); 2377 if (chk <= 0) 2378 ctxt->valid = 0; 2379 if (chk < 0) 2380 ctxt->wellFormed = 0; 2381 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 2382 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; 2383 } 2384 #endif /* LIBXML_VALID_ENABLED */ 2385 } 2386 2387 /** 2388 * xmlSAX2EndElementNs: 2389 * @ctx: the user data (XML parser context) 2390 * @localname: the local name of the element 2391 * @prefix: the element namespace prefix if available 2392 * @URI: the element namespace name if available 2393 * 2394 * SAX2 callback when an element end has been detected by the parser. 2395 * It provides the namespace informations for the element. 2396 */ 2397 void 2398 xmlSAX2EndElementNs(void *ctx, 2399 const xmlChar * localname ATTRIBUTE_UNUSED, 2400 const xmlChar * prefix ATTRIBUTE_UNUSED, 2401 const xmlChar * URI ATTRIBUTE_UNUSED) 2402 { 2403 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2404 xmlParserNodeInfo node_info; 2405 xmlNodePtr cur; 2406 2407 if (ctx == NULL) return; 2408 cur = ctxt->node; 2409 /* Capture end position and add node */ 2410 if ((ctxt->record_info) && (cur != NULL)) { 2411 node_info.end_pos = ctxt->input->cur - ctxt->input->base; 2412 node_info.end_line = ctxt->input->line; 2413 node_info.node = cur; 2414 xmlParserAddNodeInfo(ctxt, &node_info); 2415 } 2416 ctxt->nodemem = -1; 2417 2418 #ifdef LIBXML_VALID_ENABLED 2419 if (ctxt->validate && ctxt->wellFormed && 2420 ctxt->myDoc && ctxt->myDoc->intSubset) 2421 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur); 2422 #endif /* LIBXML_VALID_ENABLED */ 2423 2424 /* 2425 * end of parsing of this node. 2426 */ 2427 nodePop(ctxt); 2428 } 2429 2430 /** 2431 * xmlSAX2Reference: 2432 * @ctx: the user data (XML parser context) 2433 * @name: The entity name 2434 * 2435 * called when an entity xmlSAX2Reference is detected. 2436 */ 2437 void 2438 xmlSAX2Reference(void *ctx, const xmlChar *name) 2439 { 2440 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2441 xmlNodePtr ret; 2442 2443 if (ctx == NULL) return; 2444 #ifdef DEBUG_SAX 2445 xmlGenericError(xmlGenericErrorContext, 2446 "SAX.xmlSAX2Reference(%s)\n", name); 2447 #endif 2448 if (name[0] == '#') 2449 ret = xmlNewCharRef(ctxt->myDoc, name); 2450 else 2451 ret = xmlNewReference(ctxt->myDoc, name); 2452 #ifdef DEBUG_SAX_TREE 2453 xmlGenericError(xmlGenericErrorContext, 2454 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name); 2455 #endif 2456 if (xmlAddChild(ctxt->node, ret) == NULL) { 2457 xmlFreeNode(ret); 2458 } 2459 } 2460 2461 /** 2462 * xmlSAX2Characters: 2463 * @ctx: the user data (XML parser context) 2464 * @ch: a xmlChar string 2465 * @len: the number of xmlChar 2466 * 2467 * receiving some chars from the parser. 2468 */ 2469 void 2470 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len) 2471 { 2472 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2473 xmlNodePtr lastChild; 2474 2475 if (ctx == NULL) return; 2476 #ifdef DEBUG_SAX 2477 xmlGenericError(xmlGenericErrorContext, 2478 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len); 2479 #endif 2480 /* 2481 * Handle the data if any. If there is no child 2482 * add it as content, otherwise if the last child is text, 2483 * concatenate it, else create a new node of type text. 2484 */ 2485 2486 if (ctxt->node == NULL) { 2487 #ifdef DEBUG_SAX_TREE 2488 xmlGenericError(xmlGenericErrorContext, 2489 "add chars: ctxt->node == NULL !\n"); 2490 #endif 2491 return; 2492 } 2493 lastChild = ctxt->node->last; 2494 #ifdef DEBUG_SAX_TREE 2495 xmlGenericError(xmlGenericErrorContext, 2496 "add chars to %s \n", ctxt->node->name); 2497 #endif 2498 2499 /* 2500 * Here we needed an accelerator mechanism in case of very large 2501 * elements. Use an attribute in the structure !!! 2502 */ 2503 if (lastChild == NULL) { 2504 lastChild = xmlSAX2TextNode(ctxt, ch, len); 2505 if (lastChild != NULL) { 2506 ctxt->node->children = lastChild; 2507 ctxt->node->last = lastChild; 2508 lastChild->parent = ctxt->node; 2509 lastChild->doc = ctxt->node->doc; 2510 ctxt->nodelen = len; 2511 ctxt->nodemem = len + 1; 2512 } else { 2513 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2514 return; 2515 } 2516 } else { 2517 int coalesceText = (lastChild != NULL) && 2518 (lastChild->type == XML_TEXT_NODE) && 2519 (lastChild->name == xmlStringText); 2520 if ((coalesceText) && (ctxt->nodemem != 0)) { 2521 /* 2522 * The whole point of maintaining nodelen and nodemem, 2523 * xmlTextConcat is too costly, i.e. compute length, 2524 * reallocate a new buffer, move data, append ch. Here 2525 * We try to minimaze realloc() uses and avoid copying 2526 * and recomputing length over and over. 2527 */ 2528 if (lastChild->content == (xmlChar *)&(lastChild->properties)) { 2529 lastChild->content = xmlStrdup(lastChild->content); 2530 lastChild->properties = NULL; 2531 } else if ((ctxt->nodemem == ctxt->nodelen + 1) && 2532 (xmlDictOwns(ctxt->dict, lastChild->content))) { 2533 lastChild->content = xmlStrdup(lastChild->content); 2534 } 2535 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) && 2536 ((ctxt->options & XML_PARSE_HUGE) == 0)) { 2537 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node"); 2538 return; 2539 } 2540 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len || 2541 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) { 2542 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented"); 2543 return; 2544 } 2545 if (ctxt->nodelen + len >= ctxt->nodemem) { 2546 xmlChar *newbuf; 2547 size_t size; 2548 2549 size = ctxt->nodemem + len; 2550 size *= 2; 2551 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); 2552 if (newbuf == NULL) { 2553 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2554 return; 2555 } 2556 ctxt->nodemem = size; 2557 lastChild->content = newbuf; 2558 } 2559 memcpy(&lastChild->content[ctxt->nodelen], ch, len); 2560 ctxt->nodelen += len; 2561 lastChild->content[ctxt->nodelen] = 0; 2562 } else if (coalesceText) { 2563 if (xmlTextConcat(lastChild, ch, len)) { 2564 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2565 } 2566 if (ctxt->node->children != NULL) { 2567 ctxt->nodelen = xmlStrlen(lastChild->content); 2568 ctxt->nodemem = ctxt->nodelen + 1; 2569 } 2570 } else { 2571 /* Mixed content, first time */ 2572 lastChild = xmlSAX2TextNode(ctxt, ch, len); 2573 if (lastChild != NULL) { 2574 xmlAddChild(ctxt->node, lastChild); 2575 if (ctxt->node->children != NULL) { 2576 ctxt->nodelen = len; 2577 ctxt->nodemem = len + 1; 2578 } 2579 } 2580 } 2581 } 2582 } 2583 2584 /** 2585 * xmlSAX2IgnorableWhitespace: 2586 * @ctx: the user data (XML parser context) 2587 * @ch: a xmlChar string 2588 * @len: the number of xmlChar 2589 * 2590 * receiving some ignorable whitespaces from the parser. 2591 * UNUSED: by default the DOM building will use xmlSAX2Characters 2592 */ 2593 void 2594 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) 2595 { 2596 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 2597 #ifdef DEBUG_SAX 2598 xmlGenericError(xmlGenericErrorContext, 2599 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len); 2600 #endif 2601 } 2602 2603 /** 2604 * xmlSAX2ProcessingInstruction: 2605 * @ctx: the user data (XML parser context) 2606 * @target: the target name 2607 * @data: the PI data's 2608 * 2609 * A processing instruction has been parsed. 2610 */ 2611 void 2612 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target, 2613 const xmlChar *data) 2614 { 2615 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2616 xmlNodePtr ret; 2617 xmlNodePtr parent; 2618 2619 if (ctx == NULL) return; 2620 parent = ctxt->node; 2621 #ifdef DEBUG_SAX 2622 xmlGenericError(xmlGenericErrorContext, 2623 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data); 2624 #endif 2625 2626 ret = xmlNewDocPI(ctxt->myDoc, target, data); 2627 if (ret == NULL) return; 2628 2629 if (ctxt->linenumbers) { 2630 if (ctxt->input != NULL) { 2631 if (ctxt->input->line < 65535) 2632 ret->line = (short) ctxt->input->line; 2633 else 2634 ret->line = 65535; 2635 } 2636 } 2637 if (ctxt->inSubset == 1) { 2638 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 2639 return; 2640 } else if (ctxt->inSubset == 2) { 2641 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 2642 return; 2643 } 2644 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2645 #ifdef DEBUG_SAX_TREE 2646 xmlGenericError(xmlGenericErrorContext, 2647 "Setting PI %s as root\n", target); 2648 #endif 2649 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2650 return; 2651 } 2652 if (parent->type == XML_ELEMENT_NODE) { 2653 #ifdef DEBUG_SAX_TREE 2654 xmlGenericError(xmlGenericErrorContext, 2655 "adding PI %s child to %s\n", target, parent->name); 2656 #endif 2657 xmlAddChild(parent, ret); 2658 } else { 2659 #ifdef DEBUG_SAX_TREE 2660 xmlGenericError(xmlGenericErrorContext, 2661 "adding PI %s sibling to ", target); 2662 xmlDebugDumpOneNode(stderr, parent, 0); 2663 #endif 2664 xmlAddSibling(parent, ret); 2665 } 2666 } 2667 2668 /** 2669 * xmlSAX2Comment: 2670 * @ctx: the user data (XML parser context) 2671 * @value: the xmlSAX2Comment content 2672 * 2673 * A xmlSAX2Comment has been parsed. 2674 */ 2675 void 2676 xmlSAX2Comment(void *ctx, const xmlChar *value) 2677 { 2678 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2679 xmlNodePtr ret; 2680 xmlNodePtr parent; 2681 2682 if (ctx == NULL) return; 2683 parent = ctxt->node; 2684 #ifdef DEBUG_SAX 2685 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value); 2686 #endif 2687 ret = xmlNewDocComment(ctxt->myDoc, value); 2688 if (ret == NULL) return; 2689 if (ctxt->linenumbers) { 2690 if (ctxt->input != NULL) { 2691 if (ctxt->input->line < 65535) 2692 ret->line = (short) ctxt->input->line; 2693 else 2694 ret->line = 65535; 2695 } 2696 } 2697 2698 if (ctxt->inSubset == 1) { 2699 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 2700 return; 2701 } else if (ctxt->inSubset == 2) { 2702 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 2703 return; 2704 } 2705 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2706 #ifdef DEBUG_SAX_TREE 2707 xmlGenericError(xmlGenericErrorContext, 2708 "Setting xmlSAX2Comment as root\n"); 2709 #endif 2710 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2711 return; 2712 } 2713 if (parent->type == XML_ELEMENT_NODE) { 2714 #ifdef DEBUG_SAX_TREE 2715 xmlGenericError(xmlGenericErrorContext, 2716 "adding xmlSAX2Comment child to %s\n", parent->name); 2717 #endif 2718 xmlAddChild(parent, ret); 2719 } else { 2720 #ifdef DEBUG_SAX_TREE 2721 xmlGenericError(xmlGenericErrorContext, 2722 "adding xmlSAX2Comment sibling to "); 2723 xmlDebugDumpOneNode(stderr, parent, 0); 2724 #endif 2725 xmlAddSibling(parent, ret); 2726 } 2727 } 2728 2729 /** 2730 * xmlSAX2CDataBlock: 2731 * @ctx: the user data (XML parser context) 2732 * @value: The pcdata content 2733 * @len: the block length 2734 * 2735 * called when a pcdata block has been parsed 2736 */ 2737 void 2738 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len) 2739 { 2740 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2741 xmlNodePtr ret, lastChild; 2742 2743 if (ctx == NULL) return; 2744 #ifdef DEBUG_SAX 2745 xmlGenericError(xmlGenericErrorContext, 2746 "SAX.pcdata(%.10s, %d)\n", value, len); 2747 #endif 2748 lastChild = xmlGetLastChild(ctxt->node); 2749 #ifdef DEBUG_SAX_TREE 2750 xmlGenericError(xmlGenericErrorContext, 2751 "add chars to %s \n", ctxt->node->name); 2752 #endif 2753 if ((lastChild != NULL) && 2754 (lastChild->type == XML_CDATA_SECTION_NODE)) { 2755 xmlTextConcat(lastChild, value, len); 2756 } else { 2757 ret = xmlNewCDataBlock(ctxt->myDoc, value, len); 2758 xmlAddChild(ctxt->node, ret); 2759 } 2760 } 2761 2762 static int xmlSAX2DefaultVersionValue = 2; 2763 2764 #ifdef LIBXML_SAX1_ENABLED 2765 /** 2766 * xmlSAXDefaultVersion: 2767 * @version: the version, 1 or 2 2768 * 2769 * Set the default version of SAX used globally by the library. 2770 * By default, during initialization the default is set to 2. 2771 * Note that it is generally a better coding style to use 2772 * xmlSAXVersion() to set up the version explicitly for a given 2773 * parsing context. 2774 * 2775 * Returns the previous value in case of success and -1 in case of error. 2776 */ 2777 int 2778 xmlSAXDefaultVersion(int version) 2779 { 2780 int ret = xmlSAX2DefaultVersionValue; 2781 2782 if ((version != 1) && (version != 2)) 2783 return(-1); 2784 xmlSAX2DefaultVersionValue = version; 2785 return(ret); 2786 } 2787 #endif /* LIBXML_SAX1_ENABLED */ 2788 2789 /** 2790 * xmlSAXVersion: 2791 * @hdlr: the SAX handler 2792 * @version: the version, 1 or 2 2793 * 2794 * Initialize the default XML SAX handler according to the version 2795 * 2796 * Returns 0 in case of success and -1 in case of error. 2797 */ 2798 int 2799 xmlSAXVersion(xmlSAXHandler *hdlr, int version) 2800 { 2801 if (hdlr == NULL) return(-1); 2802 if (version == 2) { 2803 hdlr->startElement = NULL; 2804 hdlr->endElement = NULL; 2805 hdlr->startElementNs = xmlSAX2StartElementNs; 2806 hdlr->endElementNs = xmlSAX2EndElementNs; 2807 hdlr->serror = NULL; 2808 hdlr->initialized = XML_SAX2_MAGIC; 2809 #ifdef LIBXML_SAX1_ENABLED 2810 } else if (version == 1) { 2811 hdlr->startElement = xmlSAX2StartElement; 2812 hdlr->endElement = xmlSAX2EndElement; 2813 hdlr->initialized = 1; 2814 #endif /* LIBXML_SAX1_ENABLED */ 2815 } else 2816 return(-1); 2817 hdlr->internalSubset = xmlSAX2InternalSubset; 2818 hdlr->externalSubset = xmlSAX2ExternalSubset; 2819 hdlr->isStandalone = xmlSAX2IsStandalone; 2820 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; 2821 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; 2822 hdlr->resolveEntity = xmlSAX2ResolveEntity; 2823 hdlr->getEntity = xmlSAX2GetEntity; 2824 hdlr->getParameterEntity = xmlSAX2GetParameterEntity; 2825 hdlr->entityDecl = xmlSAX2EntityDecl; 2826 hdlr->attributeDecl = xmlSAX2AttributeDecl; 2827 hdlr->elementDecl = xmlSAX2ElementDecl; 2828 hdlr->notationDecl = xmlSAX2NotationDecl; 2829 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl; 2830 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2831 hdlr->startDocument = xmlSAX2StartDocument; 2832 hdlr->endDocument = xmlSAX2EndDocument; 2833 hdlr->reference = xmlSAX2Reference; 2834 hdlr->characters = xmlSAX2Characters; 2835 hdlr->cdataBlock = xmlSAX2CDataBlock; 2836 hdlr->ignorableWhitespace = xmlSAX2Characters; 2837 hdlr->processingInstruction = xmlSAX2ProcessingInstruction; 2838 hdlr->comment = xmlSAX2Comment; 2839 hdlr->warning = xmlParserWarning; 2840 hdlr->error = xmlParserError; 2841 hdlr->fatalError = xmlParserError; 2842 2843 return(0); 2844 } 2845 2846 /** 2847 * xmlSAX2InitDefaultSAXHandler: 2848 * @hdlr: the SAX handler 2849 * @warning: flag if non-zero sets the handler warning procedure 2850 * 2851 * Initialize the default XML SAX2 handler 2852 */ 2853 void 2854 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning) 2855 { 2856 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2857 return; 2858 2859 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue); 2860 if (warning == 0) 2861 hdlr->warning = NULL; 2862 else 2863 hdlr->warning = xmlParserWarning; 2864 } 2865 2866 /** 2867 * xmlDefaultSAXHandlerInit: 2868 * 2869 * Initialize the default SAX2 handler 2870 */ 2871 void 2872 xmlDefaultSAXHandlerInit(void) 2873 { 2874 #ifdef LIBXML_SAX1_ENABLED 2875 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1); 2876 #endif /* LIBXML_SAX1_ENABLED */ 2877 } 2878 2879 #ifdef LIBXML_HTML_ENABLED 2880 2881 /** 2882 * xmlSAX2InitHtmlDefaultSAXHandler: 2883 * @hdlr: the SAX handler 2884 * 2885 * Initialize the default HTML SAX2 handler 2886 */ 2887 void 2888 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr) 2889 { 2890 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2891 return; 2892 2893 hdlr->internalSubset = xmlSAX2InternalSubset; 2894 hdlr->externalSubset = NULL; 2895 hdlr->isStandalone = NULL; 2896 hdlr->hasInternalSubset = NULL; 2897 hdlr->hasExternalSubset = NULL; 2898 hdlr->resolveEntity = NULL; 2899 hdlr->getEntity = xmlSAX2GetEntity; 2900 hdlr->getParameterEntity = NULL; 2901 hdlr->entityDecl = NULL; 2902 hdlr->attributeDecl = NULL; 2903 hdlr->elementDecl = NULL; 2904 hdlr->notationDecl = NULL; 2905 hdlr->unparsedEntityDecl = NULL; 2906 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2907 hdlr->startDocument = xmlSAX2StartDocument; 2908 hdlr->endDocument = xmlSAX2EndDocument; 2909 hdlr->startElement = xmlSAX2StartElement; 2910 hdlr->endElement = xmlSAX2EndElement; 2911 hdlr->reference = NULL; 2912 hdlr->characters = xmlSAX2Characters; 2913 hdlr->cdataBlock = xmlSAX2CDataBlock; 2914 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; 2915 hdlr->processingInstruction = xmlSAX2ProcessingInstruction; 2916 hdlr->comment = xmlSAX2Comment; 2917 hdlr->warning = xmlParserWarning; 2918 hdlr->error = xmlParserError; 2919 hdlr->fatalError = xmlParserError; 2920 2921 hdlr->initialized = 1; 2922 } 2923 2924 /** 2925 * htmlDefaultSAXHandlerInit: 2926 * 2927 * Initialize the default SAX handler 2928 */ 2929 void 2930 htmlDefaultSAXHandlerInit(void) 2931 { 2932 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler); 2933 } 2934 2935 #endif /* LIBXML_HTML_ENABLED */ 2936 2937 #ifdef LIBXML_DOCB_ENABLED 2938 2939 /** 2940 * xmlSAX2InitDocbDefaultSAXHandler: 2941 * @hdlr: the SAX handler 2942 * 2943 * Initialize the default DocBook SAX2 handler 2944 */ 2945 void 2946 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr) 2947 { 2948 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2949 return; 2950 2951 hdlr->internalSubset = xmlSAX2InternalSubset; 2952 hdlr->externalSubset = NULL; 2953 hdlr->isStandalone = xmlSAX2IsStandalone; 2954 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; 2955 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; 2956 hdlr->resolveEntity = xmlSAX2ResolveEntity; 2957 hdlr->getEntity = xmlSAX2GetEntity; 2958 hdlr->getParameterEntity = NULL; 2959 hdlr->entityDecl = xmlSAX2EntityDecl; 2960 hdlr->attributeDecl = NULL; 2961 hdlr->elementDecl = NULL; 2962 hdlr->notationDecl = NULL; 2963 hdlr->unparsedEntityDecl = NULL; 2964 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2965 hdlr->startDocument = xmlSAX2StartDocument; 2966 hdlr->endDocument = xmlSAX2EndDocument; 2967 hdlr->startElement = xmlSAX2StartElement; 2968 hdlr->endElement = xmlSAX2EndElement; 2969 hdlr->reference = xmlSAX2Reference; 2970 hdlr->characters = xmlSAX2Characters; 2971 hdlr->cdataBlock = NULL; 2972 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; 2973 hdlr->processingInstruction = NULL; 2974 hdlr->comment = xmlSAX2Comment; 2975 hdlr->warning = xmlParserWarning; 2976 hdlr->error = xmlParserError; 2977 hdlr->fatalError = xmlParserError; 2978 2979 hdlr->initialized = 1; 2980 } 2981 2982 /** 2983 * docbDefaultSAXHandlerInit: 2984 * 2985 * Initialize the default SAX handler 2986 */ 2987 void 2988 docbDefaultSAXHandlerInit(void) 2989 { 2990 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler); 2991 } 2992 2993 #endif /* LIBXML_DOCB_ENABLED */ 2994 #define bottom_SAX2 2995 #include "elfgcchack.h" 2996