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