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