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