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