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