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