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_VALID_ENABLED 1109 /* 1110 * Do the last stage of the attribute normalization 1111 * Needed for HTML too: 1112 * http://www.w3.org/TR/html4/types.html#h-6.2 1113 */ 1114 ctxt->vctxt.valid = 1; 1115 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt, 1116 ctxt->myDoc, ctxt->node, 1117 fullname, value); 1118 if (ctxt->vctxt.valid != 1) { 1119 ctxt->valid = 0; 1120 } 1121 if (nval != NULL) 1122 value = nval; 1123 #else 1124 nval = NULL; 1125 #endif /* LIBXML_VALID_ENABLED */ 1126 1127 /* 1128 * Check whether it's a namespace definition 1129 */ 1130 if ((!ctxt->html) && (ns == NULL) && 1131 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && 1132 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) { 1133 xmlNsPtr nsret; 1134 xmlChar *val; 1135 1136 if (!ctxt->replaceEntities) { 1137 ctxt->depth++; 1138 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1139 0,0,0); 1140 ctxt->depth--; 1141 } else { 1142 val = (xmlChar *) value; 1143 } 1144 1145 if (val[0] != 0) { 1146 xmlURIPtr uri; 1147 1148 uri = xmlParseURI((const char *)val); 1149 if (uri == NULL) { 1150 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 1151 ctxt->sax->warning(ctxt->userData, 1152 "xmlns: %s not a valid URI\n", val); 1153 } else { 1154 if (uri->scheme == NULL) { 1155 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 1156 ctxt->sax->warning(ctxt->userData, 1157 "xmlns: URI %s is not absolute\n", val); 1158 } 1159 xmlFreeURI(uri); 1160 } 1161 } 1162 1163 /* a default namespace definition */ 1164 nsret = xmlNewNs(ctxt->node, val, NULL); 1165 1166 #ifdef LIBXML_VALID_ENABLED 1167 /* 1168 * Validate also for namespace decls, they are attributes from 1169 * an XML-1.0 perspective 1170 */ 1171 if (nsret != NULL && ctxt->validate && ctxt->wellFormed && 1172 ctxt->myDoc && ctxt->myDoc->intSubset) 1173 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 1174 ctxt->node, prefix, nsret, val); 1175 #endif /* LIBXML_VALID_ENABLED */ 1176 if (name != NULL) 1177 xmlFree(name); 1178 if (nval != NULL) 1179 xmlFree(nval); 1180 if (val != value) 1181 xmlFree(val); 1182 return; 1183 } 1184 if ((!ctxt->html) && 1185 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && 1186 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) { 1187 xmlNsPtr nsret; 1188 xmlChar *val; 1189 1190 if (!ctxt->replaceEntities) { 1191 ctxt->depth++; 1192 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1193 0,0,0); 1194 ctxt->depth--; 1195 if (val == NULL) { 1196 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1197 xmlFree(ns); 1198 if (name != NULL) 1199 xmlFree(name); 1200 return; 1201 } 1202 } else { 1203 val = (xmlChar *) value; 1204 } 1205 1206 if (val[0] == 0) { 1207 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY, 1208 "Empty namespace name for prefix %s\n", name, NULL); 1209 } 1210 if ((ctxt->pedantic != 0) && (val[0] != 0)) { 1211 xmlURIPtr uri; 1212 1213 uri = xmlParseURI((const char *)val); 1214 if (uri == NULL) { 1215 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI, 1216 "xmlns:%s: %s not a valid URI\n", name, value); 1217 } else { 1218 if (uri->scheme == NULL) { 1219 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE, 1220 "xmlns:%s: URI %s is not absolute\n", name, value); 1221 } 1222 xmlFreeURI(uri); 1223 } 1224 } 1225 1226 /* a standard namespace definition */ 1227 nsret = xmlNewNs(ctxt->node, val, name); 1228 xmlFree(ns); 1229 #ifdef LIBXML_VALID_ENABLED 1230 /* 1231 * Validate also for namespace decls, they are attributes from 1232 * an XML-1.0 perspective 1233 */ 1234 if (nsret != NULL && ctxt->validate && ctxt->wellFormed && 1235 ctxt->myDoc && ctxt->myDoc->intSubset) 1236 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 1237 ctxt->node, prefix, nsret, value); 1238 #endif /* LIBXML_VALID_ENABLED */ 1239 if (name != NULL) 1240 xmlFree(name); 1241 if (nval != NULL) 1242 xmlFree(nval); 1243 if (val != value) 1244 xmlFree(val); 1245 return; 1246 } 1247 1248 if (ns != NULL) { 1249 xmlAttrPtr prop; 1250 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns); 1251 if (namespace == NULL) { 1252 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 1253 "Namespace prefix %s of attribute %s is not defined\n", 1254 ns, name); 1255 } 1256 1257 prop = ctxt->node->properties; 1258 while (prop != NULL) { 1259 if (prop->ns != NULL) { 1260 if ((xmlStrEqual(name, prop->name)) && 1261 ((namespace == prop->ns) || 1262 (xmlStrEqual(namespace->href, prop->ns->href)))) { 1263 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED, 1264 "Attribute %s in %s redefined\n", 1265 name, namespace->href); 1266 ctxt->wellFormed = 0; 1267 if (ctxt->recovery == 0) ctxt->disableSAX = 1; 1268 goto error; 1269 } 1270 } 1271 prop = prop->next; 1272 } 1273 } else { 1274 namespace = NULL; 1275 } 1276 1277 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */ 1278 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL); 1279 1280 if (ret != NULL) { 1281 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { 1282 xmlNodePtr tmp; 1283 1284 ret->children = xmlStringGetNodeList(ctxt->myDoc, value); 1285 tmp = ret->children; 1286 while (tmp != NULL) { 1287 tmp->parent = (xmlNodePtr) ret; 1288 if (tmp->next == NULL) 1289 ret->last = tmp; 1290 tmp = tmp->next; 1291 } 1292 } else if (value != NULL) { 1293 ret->children = xmlNewDocText(ctxt->myDoc, value); 1294 ret->last = ret->children; 1295 if (ret->children != NULL) 1296 ret->children->parent = (xmlNodePtr) ret; 1297 } 1298 } 1299 1300 #ifdef LIBXML_VALID_ENABLED 1301 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 1302 ctxt->myDoc && ctxt->myDoc->intSubset) { 1303 1304 /* 1305 * If we don't substitute entities, the validation should be 1306 * done on a value with replaced entities anyway. 1307 */ 1308 if (!ctxt->replaceEntities) { 1309 xmlChar *val; 1310 1311 ctxt->depth++; 1312 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 1313 0,0,0); 1314 ctxt->depth--; 1315 1316 if (val == NULL) 1317 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 1318 ctxt->myDoc, ctxt->node, ret, value); 1319 else { 1320 xmlChar *nvalnorm; 1321 1322 /* 1323 * Do the last stage of the attribute normalization 1324 * It need to be done twice ... it's an extra burden related 1325 * to the ability to keep xmlSAX2References in attributes 1326 */ 1327 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc, 1328 ctxt->node, fullname, val); 1329 if (nvalnorm != NULL) { 1330 xmlFree(val); 1331 val = nvalnorm; 1332 } 1333 1334 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 1335 ctxt->myDoc, ctxt->node, ret, val); 1336 xmlFree(val); 1337 } 1338 } else { 1339 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, 1340 ctxt->node, ret, value); 1341 } 1342 } else 1343 #endif /* LIBXML_VALID_ENABLED */ 1344 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && 1345 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || 1346 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { 1347 /* 1348 * when validating, the ID registration is done at the attribute 1349 * validation level. Otherwise we have to do specific handling here. 1350 */ 1351 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) { 1352 /* 1353 * Add the xml:id value 1354 * 1355 * Open issue: normalization of the value. 1356 */ 1357 if (xmlValidateNCName(value, 1) != 0) { 1358 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, 1359 "xml:id : attribute value %s is not an NCName\n", 1360 (const char *) value, NULL); 1361 } 1362 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); 1363 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) 1364 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); 1365 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) 1366 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret); 1367 } 1368 1369 error: 1370 if (nval != NULL) 1371 xmlFree(nval); 1372 if (ns != NULL) 1373 xmlFree(ns); 1374 } 1375 1376 /* 1377 * xmlCheckDefaultedAttributes: 1378 * 1379 * Check defaulted attributes from the DTD 1380 */ 1381 static void 1382 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, 1383 const xmlChar *prefix, const xmlChar **atts) { 1384 xmlElementPtr elemDecl; 1385 const xmlChar *att; 1386 int internal = 1; 1387 int i; 1388 1389 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix); 1390 if (elemDecl == NULL) { 1391 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix); 1392 internal = 0; 1393 } 1394 1395 process_external_subset: 1396 1397 if (elemDecl != NULL) { 1398 xmlAttributePtr attr = elemDecl->attributes; 1399 /* 1400 * Check against defaulted attributes from the external subset 1401 * if the document is stamped as standalone 1402 */ 1403 if ((ctxt->myDoc->standalone == 1) && 1404 (ctxt->myDoc->extSubset != NULL) && 1405 (ctxt->validate)) { 1406 while (attr != NULL) { 1407 if ((attr->defaultValue != NULL) && 1408 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset, 1409 attr->elem, attr->name, 1410 attr->prefix) == attr) && 1411 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, 1412 attr->elem, attr->name, 1413 attr->prefix) == NULL)) { 1414 xmlChar *fulln; 1415 1416 if (attr->prefix != NULL) { 1417 fulln = xmlStrdup(attr->prefix); 1418 fulln = xmlStrcat(fulln, BAD_CAST ":"); 1419 fulln = xmlStrcat(fulln, attr->name); 1420 } else { 1421 fulln = xmlStrdup(attr->name); 1422 } 1423 1424 /* 1425 * Check that the attribute is not declared in the 1426 * serialization 1427 */ 1428 att = NULL; 1429 if (atts != NULL) { 1430 i = 0; 1431 att = atts[i]; 1432 while (att != NULL) { 1433 if (xmlStrEqual(att, fulln)) 1434 break; 1435 i += 2; 1436 att = atts[i]; 1437 } 1438 } 1439 if (att == NULL) { 1440 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED, 1441 "standalone: attribute %s on %s defaulted from external subset\n", 1442 (const char *)fulln, 1443 (const char *)attr->elem); 1444 } 1445 } 1446 attr = attr->nexth; 1447 } 1448 } 1449 1450 /* 1451 * Actually insert defaulted values when needed 1452 */ 1453 attr = elemDecl->attributes; 1454 while (attr != NULL) { 1455 /* 1456 * Make sure that attributes redefinition occuring in the 1457 * internal subset are not overriden by definitions in the 1458 * external subset. 1459 */ 1460 if (attr->defaultValue != NULL) { 1461 /* 1462 * the element should be instantiated in the tree if: 1463 * - this is a namespace prefix 1464 * - the user required for completion in the tree 1465 * like XSLT 1466 * - there isn't already an attribute definition 1467 * in the internal subset overriding it. 1468 */ 1469 if (((attr->prefix != NULL) && 1470 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) || 1471 ((attr->prefix == NULL) && 1472 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) || 1473 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) { 1474 xmlAttributePtr tst; 1475 1476 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, 1477 attr->elem, attr->name, 1478 attr->prefix); 1479 if ((tst == attr) || (tst == NULL)) { 1480 xmlChar fn[50]; 1481 xmlChar *fulln; 1482 1483 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50); 1484 if (fulln == NULL) { 1485 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1486 return; 1487 } 1488 1489 /* 1490 * Check that the attribute is not declared in the 1491 * serialization 1492 */ 1493 att = NULL; 1494 if (atts != NULL) { 1495 i = 0; 1496 att = atts[i]; 1497 while (att != NULL) { 1498 if (xmlStrEqual(att, fulln)) 1499 break; 1500 i += 2; 1501 att = atts[i]; 1502 } 1503 } 1504 if (att == NULL) { 1505 xmlSAX2AttributeInternal(ctxt, fulln, 1506 attr->defaultValue, prefix); 1507 } 1508 if ((fulln != fn) && (fulln != attr->name)) 1509 xmlFree(fulln); 1510 } 1511 } 1512 } 1513 attr = attr->nexth; 1514 } 1515 if (internal == 1) { 1516 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, 1517 name, prefix); 1518 internal = 0; 1519 goto process_external_subset; 1520 } 1521 } 1522 } 1523 1524 /** 1525 * xmlSAX2StartElement: 1526 * @ctx: the user data (XML parser context) 1527 * @fullname: The element name, including namespace prefix 1528 * @atts: An array of name/value attributes pairs, NULL terminated 1529 * 1530 * called when an opening tag has been processed. 1531 */ 1532 void 1533 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) 1534 { 1535 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1536 xmlNodePtr ret; 1537 xmlNodePtr parent; 1538 xmlNsPtr ns; 1539 xmlChar *name; 1540 xmlChar *prefix; 1541 const xmlChar *att; 1542 const xmlChar *value; 1543 int i; 1544 1545 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return; 1546 parent = ctxt->node; 1547 #ifdef DEBUG_SAX 1548 xmlGenericError(xmlGenericErrorContext, 1549 "SAX.xmlSAX2StartElement(%s)\n", fullname); 1550 #endif 1551 1552 /* 1553 * First check on validity: 1554 */ 1555 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 1556 ((ctxt->myDoc->intSubset == NULL) || 1557 ((ctxt->myDoc->intSubset->notations == NULL) && 1558 (ctxt->myDoc->intSubset->elements == NULL) && 1559 (ctxt->myDoc->intSubset->attributes == NULL) && 1560 (ctxt->myDoc->intSubset->entities == NULL)))) { 1561 xmlErrValid(ctxt, XML_ERR_NO_DTD, 1562 "Validation failed: no DTD found !", NULL, NULL); 1563 ctxt->validate = 0; 1564 } 1565 1566 1567 /* 1568 * Split the full name into a namespace prefix and the tag name 1569 */ 1570 name = xmlSplitQName(ctxt, fullname, &prefix); 1571 1572 1573 /* 1574 * Note : the namespace resolution is deferred until the end of the 1575 * attributes parsing, since local namespace can be defined as 1576 * an attribute at this level. 1577 */ 1578 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); 1579 if (ret == NULL) { 1580 if (prefix != NULL) 1581 xmlFree(prefix); 1582 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); 1583 return; 1584 } 1585 if (ctxt->myDoc->children == NULL) { 1586 #ifdef DEBUG_SAX_TREE 1587 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); 1588 #endif 1589 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 1590 } else if (parent == NULL) { 1591 parent = ctxt->myDoc->children; 1592 } 1593 ctxt->nodemem = -1; 1594 if (ctxt->linenumbers) { 1595 if (ctxt->input != NULL) { 1596 if (ctxt->input->line < 65535) 1597 ret->line = (short) ctxt->input->line; 1598 else 1599 ret->line = 65535; 1600 } 1601 } 1602 1603 /* 1604 * We are parsing a new node. 1605 */ 1606 #ifdef DEBUG_SAX_TREE 1607 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); 1608 #endif 1609 nodePush(ctxt, ret); 1610 1611 /* 1612 * Link the child element 1613 */ 1614 if (parent != NULL) { 1615 if (parent->type == XML_ELEMENT_NODE) { 1616 #ifdef DEBUG_SAX_TREE 1617 xmlGenericError(xmlGenericErrorContext, 1618 "adding child %s to %s\n", name, parent->name); 1619 #endif 1620 xmlAddChild(parent, ret); 1621 } else { 1622 #ifdef DEBUG_SAX_TREE 1623 xmlGenericError(xmlGenericErrorContext, 1624 "adding sibling %s to ", name); 1625 xmlDebugDumpOneNode(stderr, parent, 0); 1626 #endif 1627 xmlAddSibling(parent, ret); 1628 } 1629 } 1630 1631 /* 1632 * Insert all the defaulted attributes from the DTD especially namespaces 1633 */ 1634 if ((!ctxt->html) && 1635 ((ctxt->myDoc->intSubset != NULL) || 1636 (ctxt->myDoc->extSubset != NULL))) { 1637 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts); 1638 } 1639 1640 /* 1641 * process all the attributes whose name start with "xmlns" 1642 */ 1643 if (atts != NULL) { 1644 i = 0; 1645 att = atts[i++]; 1646 value = atts[i++]; 1647 if (!ctxt->html) { 1648 while ((att != NULL) && (value != NULL)) { 1649 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') && 1650 (att[3] == 'n') && (att[4] == 's')) 1651 xmlSAX2AttributeInternal(ctxt, att, value, prefix); 1652 1653 att = atts[i++]; 1654 value = atts[i++]; 1655 } 1656 } 1657 } 1658 1659 /* 1660 * Search the namespace, note that since the attributes have been 1661 * processed, the local namespaces are available. 1662 */ 1663 ns = xmlSearchNs(ctxt->myDoc, ret, prefix); 1664 if ((ns == NULL) && (parent != NULL)) 1665 ns = xmlSearchNs(ctxt->myDoc, parent, prefix); 1666 if ((prefix != NULL) && (ns == NULL)) { 1667 ns = xmlNewNs(ret, NULL, prefix); 1668 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 1669 "Namespace prefix %s is not defined\n", 1670 prefix, NULL); 1671 } 1672 1673 /* 1674 * set the namespace node, making sure that if the default namspace 1675 * is unbound on a parent we simply kee it NULL 1676 */ 1677 if ((ns != NULL) && (ns->href != NULL) && 1678 ((ns->href[0] != 0) || (ns->prefix != NULL))) 1679 xmlSetNs(ret, ns); 1680 1681 /* 1682 * process all the other attributes 1683 */ 1684 if (atts != NULL) { 1685 i = 0; 1686 att = atts[i++]; 1687 value = atts[i++]; 1688 if (ctxt->html) { 1689 while (att != NULL) { 1690 xmlSAX2AttributeInternal(ctxt, att, value, NULL); 1691 att = atts[i++]; 1692 value = atts[i++]; 1693 } 1694 } else { 1695 while ((att != NULL) && (value != NULL)) { 1696 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') || 1697 (att[3] != 'n') || (att[4] != 's')) 1698 xmlSAX2AttributeInternal(ctxt, att, value, NULL); 1699 1700 /* 1701 * Next ones 1702 */ 1703 att = atts[i++]; 1704 value = atts[i++]; 1705 } 1706 } 1707 } 1708 1709 #ifdef LIBXML_VALID_ENABLED 1710 /* 1711 * If it's the Document root, finish the DTD validation and 1712 * check the document root element for validity 1713 */ 1714 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { 1715 int chk; 1716 1717 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); 1718 if (chk <= 0) 1719 ctxt->valid = 0; 1720 if (chk < 0) 1721 ctxt->wellFormed = 0; 1722 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 1723 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; 1724 } 1725 #endif /* LIBXML_VALID_ENABLED */ 1726 1727 if (prefix != NULL) 1728 xmlFree(prefix); 1729 1730 } 1731 1732 /** 1733 * xmlSAX2EndElement: 1734 * @ctx: the user data (XML parser context) 1735 * @name: The element name 1736 * 1737 * called when the end of an element has been detected. 1738 */ 1739 void 1740 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) 1741 { 1742 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1743 xmlParserNodeInfo node_info; 1744 xmlNodePtr cur; 1745 1746 if (ctx == NULL) return; 1747 cur = ctxt->node; 1748 #ifdef DEBUG_SAX 1749 if (name == NULL) 1750 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); 1751 else 1752 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name); 1753 #endif 1754 1755 /* Capture end position and add node */ 1756 if (cur != NULL && ctxt->record_info) { 1757 node_info.end_pos = ctxt->input->cur - ctxt->input->base; 1758 node_info.end_line = ctxt->input->line; 1759 node_info.node = cur; 1760 xmlParserAddNodeInfo(ctxt, &node_info); 1761 } 1762 ctxt->nodemem = -1; 1763 1764 #ifdef LIBXML_VALID_ENABLED 1765 if (ctxt->validate && ctxt->wellFormed && 1766 ctxt->myDoc && ctxt->myDoc->intSubset) 1767 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, 1768 cur); 1769 #endif /* LIBXML_VALID_ENABLED */ 1770 1771 1772 /* 1773 * end of parsing of this node. 1774 */ 1775 #ifdef DEBUG_SAX_TREE 1776 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); 1777 #endif 1778 nodePop(ctxt); 1779 } 1780 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */ 1781 1782 /* 1783 * xmlSAX2TextNode: 1784 * @ctxt: the parser context 1785 * @str: the input string 1786 * @len: the string length 1787 * 1788 * Remove the entities from an attribute value 1789 * 1790 * Returns the newly allocated string or NULL if not needed or error 1791 */ 1792 static xmlNodePtr 1793 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { 1794 xmlNodePtr ret; 1795 const xmlChar *intern = NULL; 1796 1797 /* 1798 * Allocate 1799 */ 1800 if (ctxt->freeElems != NULL) { 1801 ret = ctxt->freeElems; 1802 ctxt->freeElems = ret->next; 1803 ctxt->freeElemsNr--; 1804 } else { 1805 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); 1806 } 1807 if (ret == NULL) { 1808 xmlErrMemory(ctxt, "xmlSAX2Characters"); 1809 return(NULL); 1810 } 1811 memset(ret, 0, sizeof(xmlNode)); 1812 /* 1813 * intern the formatting blanks found between tags, or the 1814 * very short strings 1815 */ 1816 if (ctxt->dictNames) { 1817 xmlChar cur = str[len]; 1818 1819 if ((len < (int) (2 * sizeof(void *))) && 1820 (ctxt->options & XML_PARSE_COMPACT)) { 1821 /* store the string in the node overrithing properties and nsDef */ 1822 xmlChar *tmp = (xmlChar *) &(ret->properties); 1823 memcpy(tmp, str, len); 1824 tmp[len] = 0; 1825 intern = tmp; 1826 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') || 1827 ((cur == '<') && (str[len + 1] != '!')))) { 1828 intern = xmlDictLookup(ctxt->dict, str, len); 1829 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && 1830 (str[len + 1] != '!')) { 1831 int i; 1832 1833 for (i = 1;i < len;i++) { 1834 if (!IS_BLANK_CH(str[i])) goto skip; 1835 } 1836 intern = xmlDictLookup(ctxt->dict, str, len); 1837 } 1838 } 1839 skip: 1840 ret->type = XML_TEXT_NODE; 1841 1842 ret->name = xmlStringText; 1843 if (intern == NULL) { 1844 ret->content = xmlStrndup(str, len); 1845 if (ret->content == NULL) { 1846 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode"); 1847 xmlFree(ret); 1848 return(NULL); 1849 } 1850 } else 1851 ret->content = (xmlChar *) intern; 1852 1853 if (ctxt->input != NULL) 1854 ret->line = ctxt->input->line; 1855 1856 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 1857 xmlRegisterNodeDefaultValue(ret); 1858 return(ret); 1859 } 1860 1861 #ifdef LIBXML_VALID_ENABLED 1862 /* 1863 * xmlSAX2DecodeAttrEntities: 1864 * @ctxt: the parser context 1865 * @str: the input string 1866 * @len: the string length 1867 * 1868 * Remove the entities from an attribute value 1869 * 1870 * Returns the newly allocated string or NULL if not needed or error 1871 */ 1872 static xmlChar * 1873 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, 1874 const xmlChar *end) { 1875 const xmlChar *in; 1876 xmlChar *ret; 1877 1878 in = str; 1879 while (in < end) 1880 if (*in++ == '&') 1881 goto decode; 1882 return(NULL); 1883 decode: 1884 ctxt->depth++; 1885 ret = xmlStringLenDecodeEntities(ctxt, str, end - str, 1886 XML_SUBSTITUTE_REF, 0,0,0); 1887 ctxt->depth--; 1888 return(ret); 1889 } 1890 #endif /* LIBXML_VALID_ENABLED */ 1891 1892 /** 1893 * xmlSAX2AttributeNs: 1894 * @ctx: the user data (XML parser context) 1895 * @localname: the local name of the attribute 1896 * @prefix: the attribute namespace prefix if available 1897 * @URI: the attribute namespace name if available 1898 * @value: Start of the attribute value 1899 * @valueend: end of the attribute value 1900 * 1901 * Handle an attribute that has been read by the parser. 1902 * The default handling is to convert the attribute into an 1903 * DOM subtree and past it in a new xmlAttr element added to 1904 * the element. 1905 */ 1906 static void 1907 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, 1908 const xmlChar * localname, 1909 const xmlChar * prefix, 1910 const xmlChar * value, 1911 const xmlChar * valueend) 1912 { 1913 xmlAttrPtr ret; 1914 xmlNsPtr namespace = NULL; 1915 xmlChar *dup = NULL; 1916 1917 /* 1918 * Note: if prefix == NULL, the attribute is not in the default namespace 1919 */ 1920 if (prefix != NULL) 1921 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); 1922 1923 /* 1924 * allocate the node 1925 */ 1926 if (ctxt->freeAttrs != NULL) { 1927 ret = ctxt->freeAttrs; 1928 ctxt->freeAttrs = ret->next; 1929 ctxt->freeAttrsNr--; 1930 memset(ret, 0, sizeof(xmlAttr)); 1931 ret->type = XML_ATTRIBUTE_NODE; 1932 1933 ret->parent = ctxt->node; 1934 ret->doc = ctxt->myDoc; 1935 ret->ns = namespace; 1936 1937 if (ctxt->dictNames) 1938 ret->name = localname; 1939 else 1940 ret->name = xmlStrdup(localname); 1941 1942 /* link at the end to preserv order, TODO speed up with a last */ 1943 if (ctxt->node->properties == NULL) { 1944 ctxt->node->properties = ret; 1945 } else { 1946 xmlAttrPtr prev = ctxt->node->properties; 1947 1948 while (prev->next != NULL) prev = prev->next; 1949 prev->next = ret; 1950 ret->prev = prev; 1951 } 1952 1953 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 1954 xmlRegisterNodeDefaultValue((xmlNodePtr)ret); 1955 } else { 1956 if (ctxt->dictNames) 1957 ret = xmlNewNsPropEatName(ctxt->node, namespace, 1958 (xmlChar *) localname, NULL); 1959 else 1960 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL); 1961 if (ret == NULL) { 1962 xmlErrMemory(ctxt, "xmlSAX2AttributeNs"); 1963 return; 1964 } 1965 } 1966 1967 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { 1968 xmlNodePtr tmp; 1969 1970 /* 1971 * We know that if there is an entity reference, then 1972 * the string has been dup'ed and terminates with 0 1973 * otherwise with ' or " 1974 */ 1975 if (*valueend != 0) { 1976 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); 1977 ret->children = tmp; 1978 ret->last = tmp; 1979 if (tmp != NULL) { 1980 tmp->doc = ret->doc; 1981 tmp->parent = (xmlNodePtr) ret; 1982 } 1983 } else { 1984 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, 1985 valueend - value); 1986 tmp = ret->children; 1987 while (tmp != NULL) { 1988 tmp->doc = ret->doc; 1989 tmp->parent = (xmlNodePtr) ret; 1990 if (tmp->next == NULL) 1991 ret->last = tmp; 1992 tmp = tmp->next; 1993 } 1994 } 1995 } else if (value != NULL) { 1996 xmlNodePtr tmp; 1997 1998 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); 1999 ret->children = tmp; 2000 ret->last = tmp; 2001 if (tmp != NULL) { 2002 tmp->doc = ret->doc; 2003 tmp->parent = (xmlNodePtr) ret; 2004 } 2005 } 2006 2007 #ifdef LIBXML_VALID_ENABLED 2008 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 2009 ctxt->myDoc && ctxt->myDoc->intSubset) { 2010 /* 2011 * If we don't substitute entities, the validation should be 2012 * done on a value with replaced entities anyway. 2013 */ 2014 if (!ctxt->replaceEntities) { 2015 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend); 2016 if (dup == NULL) { 2017 if (*valueend == 0) { 2018 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2019 ctxt->myDoc, ctxt->node, ret, value); 2020 } else { 2021 /* 2022 * That should already be normalized. 2023 * cheaper to finally allocate here than duplicate 2024 * entry points in the full validation code 2025 */ 2026 dup = xmlStrndup(value, valueend - value); 2027 2028 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2029 ctxt->myDoc, ctxt->node, ret, dup); 2030 } 2031 } else { 2032 /* 2033 * dup now contains a string of the flattened attribute 2034 * content with entities substitued. Check if we need to 2035 * apply an extra layer of normalization. 2036 * It need to be done twice ... it's an extra burden related 2037 * to the ability to keep references in attributes 2038 */ 2039 if (ctxt->attsSpecial != NULL) { 2040 xmlChar *nvalnorm; 2041 xmlChar fn[50]; 2042 xmlChar *fullname; 2043 2044 fullname = xmlBuildQName(localname, prefix, fn, 50); 2045 if (fullname != NULL) { 2046 ctxt->vctxt.valid = 1; 2047 nvalnorm = xmlValidCtxtNormalizeAttributeValue( 2048 &ctxt->vctxt, ctxt->myDoc, 2049 ctxt->node, fullname, dup); 2050 if (ctxt->vctxt.valid != 1) 2051 ctxt->valid = 0; 2052 2053 if ((fullname != fn) && (fullname != localname)) 2054 xmlFree(fullname); 2055 if (nvalnorm != NULL) { 2056 xmlFree(dup); 2057 dup = nvalnorm; 2058 } 2059 } 2060 } 2061 2062 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2063 ctxt->myDoc, ctxt->node, ret, dup); 2064 } 2065 } else { 2066 /* 2067 * if entities already have been substitued, then 2068 * the attribute as passed is already normalized 2069 */ 2070 dup = xmlStrndup(value, valueend - value); 2071 2072 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 2073 ctxt->myDoc, ctxt->node, ret, dup); 2074 } 2075 } else 2076 #endif /* LIBXML_VALID_ENABLED */ 2077 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && 2078 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || 2079 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { 2080 /* 2081 * when validating, the ID registration is done at the attribute 2082 * validation level. Otherwise we have to do specific handling here. 2083 */ 2084 if ((prefix == ctxt->str_xml) && 2085 (localname[0] == 'i') && (localname[1] == 'd') && 2086 (localname[2] == 0)) { 2087 /* 2088 * Add the xml:id value 2089 * 2090 * Open issue: normalization of the value. 2091 */ 2092 if (dup == NULL) 2093 dup = xmlStrndup(value, valueend - value); 2094 #ifdef LIBXML_VALID_ENABLED 2095 if (xmlValidateNCName(dup, 1) != 0) { 2096 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, 2097 "xml:id : attribute value %s is not an NCName\n", 2098 (const char *) dup, NULL); 2099 } 2100 #endif 2101 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2102 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { 2103 /* might be worth duplicate entry points and not copy */ 2104 if (dup == NULL) 2105 dup = xmlStrndup(value, valueend - value); 2106 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2107 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) { 2108 if (dup == NULL) 2109 dup = xmlStrndup(value, valueend - value); 2110 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret); 2111 } 2112 } 2113 if (dup != NULL) 2114 xmlFree(dup); 2115 } 2116 2117 /** 2118 * xmlSAX2StartElementNs: 2119 * @ctx: the user data (XML parser context) 2120 * @localname: the local name of the element 2121 * @prefix: the element namespace prefix if available 2122 * @URI: the element namespace name if available 2123 * @nb_namespaces: number of namespace definitions on that node 2124 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions 2125 * @nb_attributes: the number of attributes on that node 2126 * @nb_defaulted: the number of defaulted attributes. 2127 * @attributes: pointer to the array of (localname/prefix/URI/value/end) 2128 * attribute values. 2129 * 2130 * SAX2 callback when an element start has been detected by the parser. 2131 * It provides the namespace informations for the element, as well as 2132 * the new namespace declarations on the element. 2133 */ 2134 void 2135 xmlSAX2StartElementNs(void *ctx, 2136 const xmlChar *localname, 2137 const xmlChar *prefix, 2138 const xmlChar *URI, 2139 int nb_namespaces, 2140 const xmlChar **namespaces, 2141 int nb_attributes, 2142 int nb_defaulted, 2143 const xmlChar **attributes) 2144 { 2145 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2146 xmlNodePtr ret; 2147 xmlNodePtr parent; 2148 xmlNsPtr last = NULL, ns; 2149 const xmlChar *uri, *pref; 2150 int i, j; 2151 2152 if (ctx == NULL) return; 2153 parent = ctxt->node; 2154 /* 2155 * First check on validity: 2156 */ 2157 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 2158 ((ctxt->myDoc->intSubset == NULL) || 2159 ((ctxt->myDoc->intSubset->notations == NULL) && 2160 (ctxt->myDoc->intSubset->elements == NULL) && 2161 (ctxt->myDoc->intSubset->attributes == NULL) && 2162 (ctxt->myDoc->intSubset->entities == NULL)))) { 2163 xmlErrValid(ctxt, XML_ERR_NO_DTD, 2164 "Validation failed: no DTD found !", NULL, NULL); 2165 ctxt->validate = 0; 2166 } 2167 2168 /* 2169 * allocate the node 2170 */ 2171 if (ctxt->freeElems != NULL) { 2172 ret = ctxt->freeElems; 2173 ctxt->freeElems = ret->next; 2174 ctxt->freeElemsNr--; 2175 memset(ret, 0, sizeof(xmlNode)); 2176 ret->type = XML_ELEMENT_NODE; 2177 2178 if (ctxt->dictNames) 2179 ret->name = localname; 2180 else { 2181 ret->name = xmlStrdup(localname); 2182 if (ret->name == NULL) { 2183 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2184 return; 2185 } 2186 } 2187 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) 2188 xmlRegisterNodeDefaultValue(ret); 2189 } else { 2190 if (ctxt->dictNames) 2191 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, 2192 (xmlChar *) localname, NULL); 2193 else 2194 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL); 2195 if (ret == NULL) { 2196 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2197 return; 2198 } 2199 } 2200 if (ctxt->linenumbers) { 2201 if (ctxt->input != NULL) { 2202 if (ctxt->input->line < 65535) 2203 ret->line = (short) ctxt->input->line; 2204 else 2205 ret->line = 65535; 2206 } 2207 } 2208 2209 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2210 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2211 } 2212 /* 2213 * Build the namespace list 2214 */ 2215 for (i = 0,j = 0;j < nb_namespaces;j++) { 2216 pref = namespaces[i++]; 2217 uri = namespaces[i++]; 2218 ns = xmlNewNs(NULL, uri, pref); 2219 if (ns != NULL) { 2220 if (last == NULL) { 2221 ret->nsDef = last = ns; 2222 } else { 2223 last->next = ns; 2224 last = ns; 2225 } 2226 if ((URI != NULL) && (prefix == pref)) 2227 ret->ns = ns; 2228 } else { 2229 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2230 return; 2231 } 2232 #ifdef LIBXML_VALID_ENABLED 2233 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 2234 ctxt->myDoc && ctxt->myDoc->intSubset) { 2235 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, 2236 ret, prefix, ns, uri); 2237 } 2238 #endif /* LIBXML_VALID_ENABLED */ 2239 } 2240 ctxt->nodemem = -1; 2241 2242 /* 2243 * We are parsing a new node. 2244 */ 2245 nodePush(ctxt, ret); 2246 2247 /* 2248 * Link the child element 2249 */ 2250 if (parent != NULL) { 2251 if (parent->type == XML_ELEMENT_NODE) { 2252 xmlAddChild(parent, ret); 2253 } else { 2254 xmlAddSibling(parent, ret); 2255 } 2256 } 2257 2258 /* 2259 * Insert the defaulted attributes from the DTD only if requested: 2260 */ 2261 if ((nb_defaulted != 0) && 2262 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0)) 2263 nb_attributes -= nb_defaulted; 2264 2265 /* 2266 * Search the namespace if it wasn't already found 2267 * Note that, if prefix is NULL, this searches for the default Ns 2268 */ 2269 if ((URI != NULL) && (ret->ns == NULL)) { 2270 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix); 2271 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { 2272 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix); 2273 } 2274 if (ret->ns == NULL) { 2275 ns = xmlNewNs(ret, NULL, prefix); 2276 if (ns == NULL) { 2277 2278 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); 2279 return; 2280 } 2281 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 2282 "Namespace prefix %s was not found\n", 2283 prefix, NULL); 2284 } 2285 } 2286 2287 /* 2288 * process all the other attributes 2289 */ 2290 if (nb_attributes > 0) { 2291 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) { 2292 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], 2293 attributes[j+3], attributes[j+4]); 2294 } 2295 } 2296 2297 #ifdef LIBXML_VALID_ENABLED 2298 /* 2299 * If it's the Document root, finish the DTD validation and 2300 * check the document root element for validity 2301 */ 2302 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { 2303 int chk; 2304 2305 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); 2306 if (chk <= 0) 2307 ctxt->valid = 0; 2308 if (chk < 0) 2309 ctxt->wellFormed = 0; 2310 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 2311 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; 2312 } 2313 #endif /* LIBXML_VALID_ENABLED */ 2314 } 2315 2316 /** 2317 * xmlSAX2EndElementNs: 2318 * @ctx: the user data (XML parser context) 2319 * @localname: the local name of the element 2320 * @prefix: the element namespace prefix if available 2321 * @URI: the element namespace name if available 2322 * 2323 * SAX2 callback when an element end has been detected by the parser. 2324 * It provides the namespace informations for the element. 2325 */ 2326 void 2327 xmlSAX2EndElementNs(void *ctx, 2328 const xmlChar * localname ATTRIBUTE_UNUSED, 2329 const xmlChar * prefix ATTRIBUTE_UNUSED, 2330 const xmlChar * URI ATTRIBUTE_UNUSED) 2331 { 2332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2333 xmlParserNodeInfo node_info; 2334 xmlNodePtr cur; 2335 2336 if (ctx == NULL) return; 2337 cur = ctxt->node; 2338 /* Capture end position and add node */ 2339 if ((ctxt->record_info) && (cur != NULL)) { 2340 node_info.end_pos = ctxt->input->cur - ctxt->input->base; 2341 node_info.end_line = ctxt->input->line; 2342 node_info.node = cur; 2343 xmlParserAddNodeInfo(ctxt, &node_info); 2344 } 2345 ctxt->nodemem = -1; 2346 2347 #ifdef LIBXML_VALID_ENABLED 2348 if (ctxt->validate && ctxt->wellFormed && 2349 ctxt->myDoc && ctxt->myDoc->intSubset) 2350 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur); 2351 #endif /* LIBXML_VALID_ENABLED */ 2352 2353 /* 2354 * end of parsing of this node. 2355 */ 2356 nodePop(ctxt); 2357 } 2358 2359 /** 2360 * xmlSAX2Reference: 2361 * @ctx: the user data (XML parser context) 2362 * @name: The entity name 2363 * 2364 * called when an entity xmlSAX2Reference is detected. 2365 */ 2366 void 2367 xmlSAX2Reference(void *ctx, const xmlChar *name) 2368 { 2369 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2370 xmlNodePtr ret; 2371 2372 if (ctx == NULL) return; 2373 #ifdef DEBUG_SAX 2374 xmlGenericError(xmlGenericErrorContext, 2375 "SAX.xmlSAX2Reference(%s)\n", name); 2376 #endif 2377 if (name[0] == '#') 2378 ret = xmlNewCharRef(ctxt->myDoc, name); 2379 else 2380 ret = xmlNewReference(ctxt->myDoc, name); 2381 #ifdef DEBUG_SAX_TREE 2382 xmlGenericError(xmlGenericErrorContext, 2383 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name); 2384 #endif 2385 if (xmlAddChild(ctxt->node, ret) == NULL) { 2386 xmlFreeNode(ret); 2387 } 2388 } 2389 2390 /** 2391 * xmlSAX2Characters: 2392 * @ctx: the user data (XML parser context) 2393 * @ch: a xmlChar string 2394 * @len: the number of xmlChar 2395 * 2396 * receiving some chars from the parser. 2397 */ 2398 void 2399 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len) 2400 { 2401 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2402 xmlNodePtr lastChild; 2403 2404 if (ctx == NULL) return; 2405 #ifdef DEBUG_SAX 2406 xmlGenericError(xmlGenericErrorContext, 2407 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len); 2408 #endif 2409 /* 2410 * Handle the data if any. If there is no child 2411 * add it as content, otherwise if the last child is text, 2412 * concatenate it, else create a new node of type text. 2413 */ 2414 2415 if (ctxt->node == NULL) { 2416 #ifdef DEBUG_SAX_TREE 2417 xmlGenericError(xmlGenericErrorContext, 2418 "add chars: ctxt->node == NULL !\n"); 2419 #endif 2420 return; 2421 } 2422 lastChild = ctxt->node->last; 2423 #ifdef DEBUG_SAX_TREE 2424 xmlGenericError(xmlGenericErrorContext, 2425 "add chars to %s \n", ctxt->node->name); 2426 #endif 2427 2428 /* 2429 * Here we needed an accelerator mechanism in case of very large 2430 * elements. Use an attribute in the structure !!! 2431 */ 2432 if (lastChild == NULL) { 2433 lastChild = xmlSAX2TextNode(ctxt, ch, len); 2434 if (lastChild != NULL) { 2435 ctxt->node->children = lastChild; 2436 ctxt->node->last = lastChild; 2437 lastChild->parent = ctxt->node; 2438 lastChild->doc = ctxt->node->doc; 2439 ctxt->nodelen = len; 2440 ctxt->nodemem = len + 1; 2441 } else { 2442 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2443 return; 2444 } 2445 } else { 2446 int coalesceText = (lastChild != NULL) && 2447 (lastChild->type == XML_TEXT_NODE) && 2448 (lastChild->name == xmlStringText); 2449 if ((coalesceText) && (ctxt->nodemem != 0)) { 2450 /* 2451 * The whole point of maintaining nodelen and nodemem, 2452 * xmlTextConcat is too costly, i.e. compute length, 2453 * reallocate a new buffer, move data, append ch. Here 2454 * We try to minimaze realloc() uses and avoid copying 2455 * and recomputing length over and over. 2456 */ 2457 if (lastChild->content == (xmlChar *)&(lastChild->properties)) { 2458 lastChild->content = xmlStrdup(lastChild->content); 2459 lastChild->properties = NULL; 2460 } else if ((ctxt->nodemem == ctxt->nodelen + 1) && 2461 (xmlDictOwns(ctxt->dict, lastChild->content))) { 2462 lastChild->content = xmlStrdup(lastChild->content); 2463 } 2464 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) && 2465 ((ctxt->options & XML_PARSE_HUGE) == 0)) { 2466 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node"); 2467 return; 2468 } 2469 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len || 2470 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) { 2471 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented"); 2472 return; 2473 } 2474 if (ctxt->nodelen + len >= ctxt->nodemem) { 2475 xmlChar *newbuf; 2476 size_t size; 2477 2478 size = ctxt->nodemem + len; 2479 size *= 2; 2480 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); 2481 if (newbuf == NULL) { 2482 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2483 return; 2484 } 2485 ctxt->nodemem = size; 2486 lastChild->content = newbuf; 2487 } 2488 memcpy(&lastChild->content[ctxt->nodelen], ch, len); 2489 ctxt->nodelen += len; 2490 lastChild->content[ctxt->nodelen] = 0; 2491 } else if (coalesceText) { 2492 if (xmlTextConcat(lastChild, ch, len)) { 2493 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); 2494 } 2495 if (ctxt->node->children != NULL) { 2496 ctxt->nodelen = xmlStrlen(lastChild->content); 2497 ctxt->nodemem = ctxt->nodelen + 1; 2498 } 2499 } else { 2500 /* Mixed content, first time */ 2501 lastChild = xmlSAX2TextNode(ctxt, ch, len); 2502 if (lastChild != NULL) { 2503 xmlAddChild(ctxt->node, lastChild); 2504 if (ctxt->node->children != NULL) { 2505 ctxt->nodelen = len; 2506 ctxt->nodemem = len + 1; 2507 } 2508 } 2509 } 2510 } 2511 } 2512 2513 /** 2514 * xmlSAX2IgnorableWhitespace: 2515 * @ctx: the user data (XML parser context) 2516 * @ch: a xmlChar string 2517 * @len: the number of xmlChar 2518 * 2519 * receiving some ignorable whitespaces from the parser. 2520 * UNUSED: by default the DOM building will use xmlSAX2Characters 2521 */ 2522 void 2523 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) 2524 { 2525 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 2526 #ifdef DEBUG_SAX 2527 xmlGenericError(xmlGenericErrorContext, 2528 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len); 2529 #endif 2530 } 2531 2532 /** 2533 * xmlSAX2ProcessingInstruction: 2534 * @ctx: the user data (XML parser context) 2535 * @target: the target name 2536 * @data: the PI data's 2537 * 2538 * A processing instruction has been parsed. 2539 */ 2540 void 2541 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target, 2542 const xmlChar *data) 2543 { 2544 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2545 xmlNodePtr ret; 2546 xmlNodePtr parent; 2547 2548 if (ctx == NULL) return; 2549 parent = ctxt->node; 2550 #ifdef DEBUG_SAX 2551 xmlGenericError(xmlGenericErrorContext, 2552 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data); 2553 #endif 2554 2555 ret = xmlNewDocPI(ctxt->myDoc, target, data); 2556 if (ret == NULL) return; 2557 parent = ctxt->node; 2558 2559 if (ctxt->linenumbers) { 2560 if (ctxt->input != NULL) { 2561 if (ctxt->input->line < 65535) 2562 ret->line = (short) ctxt->input->line; 2563 else 2564 ret->line = 65535; 2565 } 2566 } 2567 if (ctxt->inSubset == 1) { 2568 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 2569 return; 2570 } else if (ctxt->inSubset == 2) { 2571 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 2572 return; 2573 } 2574 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2575 #ifdef DEBUG_SAX_TREE 2576 xmlGenericError(xmlGenericErrorContext, 2577 "Setting PI %s as root\n", target); 2578 #endif 2579 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2580 return; 2581 } 2582 if (parent->type == XML_ELEMENT_NODE) { 2583 #ifdef DEBUG_SAX_TREE 2584 xmlGenericError(xmlGenericErrorContext, 2585 "adding PI %s child to %s\n", target, parent->name); 2586 #endif 2587 xmlAddChild(parent, ret); 2588 } else { 2589 #ifdef DEBUG_SAX_TREE 2590 xmlGenericError(xmlGenericErrorContext, 2591 "adding PI %s sibling to ", target); 2592 xmlDebugDumpOneNode(stderr, parent, 0); 2593 #endif 2594 xmlAddSibling(parent, ret); 2595 } 2596 } 2597 2598 /** 2599 * xmlSAX2Comment: 2600 * @ctx: the user data (XML parser context) 2601 * @value: the xmlSAX2Comment content 2602 * 2603 * A xmlSAX2Comment has been parsed. 2604 */ 2605 void 2606 xmlSAX2Comment(void *ctx, const xmlChar *value) 2607 { 2608 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2609 xmlNodePtr ret; 2610 xmlNodePtr parent; 2611 2612 if (ctx == NULL) return; 2613 parent = ctxt->node; 2614 #ifdef DEBUG_SAX 2615 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value); 2616 #endif 2617 ret = xmlNewDocComment(ctxt->myDoc, value); 2618 if (ret == NULL) return; 2619 if (ctxt->linenumbers) { 2620 if (ctxt->input != NULL) { 2621 if (ctxt->input->line < 65535) 2622 ret->line = (short) ctxt->input->line; 2623 else 2624 ret->line = 65535; 2625 } 2626 } 2627 2628 if (ctxt->inSubset == 1) { 2629 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 2630 return; 2631 } else if (ctxt->inSubset == 2) { 2632 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 2633 return; 2634 } 2635 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 2636 #ifdef DEBUG_SAX_TREE 2637 xmlGenericError(xmlGenericErrorContext, 2638 "Setting xmlSAX2Comment as root\n"); 2639 #endif 2640 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 2641 return; 2642 } 2643 if (parent->type == XML_ELEMENT_NODE) { 2644 #ifdef DEBUG_SAX_TREE 2645 xmlGenericError(xmlGenericErrorContext, 2646 "adding xmlSAX2Comment child to %s\n", parent->name); 2647 #endif 2648 xmlAddChild(parent, ret); 2649 } else { 2650 #ifdef DEBUG_SAX_TREE 2651 xmlGenericError(xmlGenericErrorContext, 2652 "adding xmlSAX2Comment sibling to "); 2653 xmlDebugDumpOneNode(stderr, parent, 0); 2654 #endif 2655 xmlAddSibling(parent, ret); 2656 } 2657 } 2658 2659 /** 2660 * xmlSAX2CDataBlock: 2661 * @ctx: the user data (XML parser context) 2662 * @value: The pcdata content 2663 * @len: the block length 2664 * 2665 * called when a pcdata block has been parsed 2666 */ 2667 void 2668 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len) 2669 { 2670 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 2671 xmlNodePtr ret, lastChild; 2672 2673 if (ctx == NULL) return; 2674 #ifdef DEBUG_SAX 2675 xmlGenericError(xmlGenericErrorContext, 2676 "SAX.pcdata(%.10s, %d)\n", value, len); 2677 #endif 2678 lastChild = xmlGetLastChild(ctxt->node); 2679 #ifdef DEBUG_SAX_TREE 2680 xmlGenericError(xmlGenericErrorContext, 2681 "add chars to %s \n", ctxt->node->name); 2682 #endif 2683 if ((lastChild != NULL) && 2684 (lastChild->type == XML_CDATA_SECTION_NODE)) { 2685 xmlTextConcat(lastChild, value, len); 2686 } else { 2687 ret = xmlNewCDataBlock(ctxt->myDoc, value, len); 2688 xmlAddChild(ctxt->node, ret); 2689 } 2690 } 2691 2692 static int xmlSAX2DefaultVersionValue = 2; 2693 2694 #ifdef LIBXML_SAX1_ENABLED 2695 /** 2696 * xmlSAXDefaultVersion: 2697 * @version: the version, 1 or 2 2698 * 2699 * Set the default version of SAX used globally by the library. 2700 * By default, during initialization the default is set to 2. 2701 * Note that it is generally a better coding style to use 2702 * xmlSAXVersion() to set up the version explicitly for a given 2703 * parsing context. 2704 * 2705 * Returns the previous value in case of success and -1 in case of error. 2706 */ 2707 int 2708 xmlSAXDefaultVersion(int version) 2709 { 2710 int ret = xmlSAX2DefaultVersionValue; 2711 2712 if ((version != 1) && (version != 2)) 2713 return(-1); 2714 xmlSAX2DefaultVersionValue = version; 2715 return(ret); 2716 } 2717 #endif /* LIBXML_SAX1_ENABLED */ 2718 2719 /** 2720 * xmlSAXVersion: 2721 * @hdlr: the SAX handler 2722 * @version: the version, 1 or 2 2723 * 2724 * Initialize the default XML SAX handler according to the version 2725 * 2726 * Returns 0 in case of success and -1 in case of error. 2727 */ 2728 int 2729 xmlSAXVersion(xmlSAXHandler *hdlr, int version) 2730 { 2731 if (hdlr == NULL) return(-1); 2732 if (version == 2) { 2733 hdlr->startElement = NULL; 2734 hdlr->endElement = NULL; 2735 hdlr->startElementNs = xmlSAX2StartElementNs; 2736 hdlr->endElementNs = xmlSAX2EndElementNs; 2737 hdlr->serror = NULL; 2738 hdlr->initialized = XML_SAX2_MAGIC; 2739 #ifdef LIBXML_SAX1_ENABLED 2740 } else if (version == 1) { 2741 hdlr->startElement = xmlSAX2StartElement; 2742 hdlr->endElement = xmlSAX2EndElement; 2743 hdlr->initialized = 1; 2744 #endif /* LIBXML_SAX1_ENABLED */ 2745 } else 2746 return(-1); 2747 hdlr->internalSubset = xmlSAX2InternalSubset; 2748 hdlr->externalSubset = xmlSAX2ExternalSubset; 2749 hdlr->isStandalone = xmlSAX2IsStandalone; 2750 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; 2751 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; 2752 hdlr->resolveEntity = xmlSAX2ResolveEntity; 2753 hdlr->getEntity = xmlSAX2GetEntity; 2754 hdlr->getParameterEntity = xmlSAX2GetParameterEntity; 2755 hdlr->entityDecl = xmlSAX2EntityDecl; 2756 hdlr->attributeDecl = xmlSAX2AttributeDecl; 2757 hdlr->elementDecl = xmlSAX2ElementDecl; 2758 hdlr->notationDecl = xmlSAX2NotationDecl; 2759 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl; 2760 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2761 hdlr->startDocument = xmlSAX2StartDocument; 2762 hdlr->endDocument = xmlSAX2EndDocument; 2763 hdlr->reference = xmlSAX2Reference; 2764 hdlr->characters = xmlSAX2Characters; 2765 hdlr->cdataBlock = xmlSAX2CDataBlock; 2766 hdlr->ignorableWhitespace = xmlSAX2Characters; 2767 hdlr->processingInstruction = xmlSAX2ProcessingInstruction; 2768 hdlr->comment = xmlSAX2Comment; 2769 hdlr->warning = xmlParserWarning; 2770 hdlr->error = xmlParserError; 2771 hdlr->fatalError = xmlParserError; 2772 2773 return(0); 2774 } 2775 2776 /** 2777 * xmlSAX2InitDefaultSAXHandler: 2778 * @hdlr: the SAX handler 2779 * @warning: flag if non-zero sets the handler warning procedure 2780 * 2781 * Initialize the default XML SAX2 handler 2782 */ 2783 void 2784 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning) 2785 { 2786 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2787 return; 2788 2789 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue); 2790 if (warning == 0) 2791 hdlr->warning = NULL; 2792 else 2793 hdlr->warning = xmlParserWarning; 2794 } 2795 2796 /** 2797 * xmlDefaultSAXHandlerInit: 2798 * 2799 * Initialize the default SAX2 handler 2800 */ 2801 void 2802 xmlDefaultSAXHandlerInit(void) 2803 { 2804 #ifdef LIBXML_SAX1_ENABLED 2805 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1); 2806 #endif /* LIBXML_SAX1_ENABLED */ 2807 } 2808 2809 #ifdef LIBXML_HTML_ENABLED 2810 2811 /** 2812 * xmlSAX2InitHtmlDefaultSAXHandler: 2813 * @hdlr: the SAX handler 2814 * 2815 * Initialize the default HTML SAX2 handler 2816 */ 2817 void 2818 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr) 2819 { 2820 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2821 return; 2822 2823 hdlr->internalSubset = xmlSAX2InternalSubset; 2824 hdlr->externalSubset = NULL; 2825 hdlr->isStandalone = NULL; 2826 hdlr->hasInternalSubset = NULL; 2827 hdlr->hasExternalSubset = NULL; 2828 hdlr->resolveEntity = NULL; 2829 hdlr->getEntity = xmlSAX2GetEntity; 2830 hdlr->getParameterEntity = NULL; 2831 hdlr->entityDecl = NULL; 2832 hdlr->attributeDecl = NULL; 2833 hdlr->elementDecl = NULL; 2834 hdlr->notationDecl = NULL; 2835 hdlr->unparsedEntityDecl = NULL; 2836 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2837 hdlr->startDocument = xmlSAX2StartDocument; 2838 hdlr->endDocument = xmlSAX2EndDocument; 2839 hdlr->startElement = xmlSAX2StartElement; 2840 hdlr->endElement = xmlSAX2EndElement; 2841 hdlr->reference = NULL; 2842 hdlr->characters = xmlSAX2Characters; 2843 hdlr->cdataBlock = xmlSAX2CDataBlock; 2844 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; 2845 hdlr->processingInstruction = xmlSAX2ProcessingInstruction; 2846 hdlr->comment = xmlSAX2Comment; 2847 hdlr->warning = xmlParserWarning; 2848 hdlr->error = xmlParserError; 2849 hdlr->fatalError = xmlParserError; 2850 2851 hdlr->initialized = 1; 2852 } 2853 2854 /** 2855 * htmlDefaultSAXHandlerInit: 2856 * 2857 * Initialize the default SAX handler 2858 */ 2859 void 2860 htmlDefaultSAXHandlerInit(void) 2861 { 2862 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler); 2863 } 2864 2865 #endif /* LIBXML_HTML_ENABLED */ 2866 2867 #ifdef LIBXML_DOCB_ENABLED 2868 2869 /** 2870 * xmlSAX2InitDocbDefaultSAXHandler: 2871 * @hdlr: the SAX handler 2872 * 2873 * Initialize the default DocBook SAX2 handler 2874 */ 2875 void 2876 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr) 2877 { 2878 if ((hdlr == NULL) || (hdlr->initialized != 0)) 2879 return; 2880 2881 hdlr->internalSubset = xmlSAX2InternalSubset; 2882 hdlr->externalSubset = NULL; 2883 hdlr->isStandalone = xmlSAX2IsStandalone; 2884 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; 2885 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; 2886 hdlr->resolveEntity = xmlSAX2ResolveEntity; 2887 hdlr->getEntity = xmlSAX2GetEntity; 2888 hdlr->getParameterEntity = NULL; 2889 hdlr->entityDecl = xmlSAX2EntityDecl; 2890 hdlr->attributeDecl = NULL; 2891 hdlr->elementDecl = NULL; 2892 hdlr->notationDecl = NULL; 2893 hdlr->unparsedEntityDecl = NULL; 2894 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; 2895 hdlr->startDocument = xmlSAX2StartDocument; 2896 hdlr->endDocument = xmlSAX2EndDocument; 2897 hdlr->startElement = xmlSAX2StartElement; 2898 hdlr->endElement = xmlSAX2EndElement; 2899 hdlr->reference = xmlSAX2Reference; 2900 hdlr->characters = xmlSAX2Characters; 2901 hdlr->cdataBlock = NULL; 2902 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; 2903 hdlr->processingInstruction = NULL; 2904 hdlr->comment = xmlSAX2Comment; 2905 hdlr->warning = xmlParserWarning; 2906 hdlr->error = xmlParserError; 2907 hdlr->fatalError = xmlParserError; 2908 2909 hdlr->initialized = 1; 2910 } 2911 2912 /** 2913 * docbDefaultSAXHandlerInit: 2914 * 2915 * Initialize the default SAX handler 2916 */ 2917 void 2918 docbDefaultSAXHandlerInit(void) 2919 { 2920 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler); 2921 } 2922 2923 #endif /* LIBXML_DOCB_ENABLED */ 2924 #define bottom_SAX2 2925 #include "elfgcchack.h" 2926