xref: /aosp_15_r20/external/libxml2/SAX2.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
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