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