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