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