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