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