VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/SAX2.c

Last change on this file was 104106, checked in by vboxsync, 8 weeks ago

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

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

© 2023 Oracle
ContactPrivacy policyTerms of Use