blob: 9a093bcd88c2a0763de1def308e7e167e472b3d8 [file] [log] [blame]
Daniel Veillard1af9a412003-08-20 22:54:39 +00001/*
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>
Daniel Veillard1dc9feb2008-11-17 15:59:21 +000014#include <limits.h>
Nick Wellnhoferd422b952017-10-09 13:37:42 +020015#include <stddef.h>
Daniel Veillard1af9a412003-08-20 22:54:39 +000016#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
Daniel Veillard1dc9feb2008-11-17 15:59:21 +000031/* 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
Daniel Veillard1af9a412003-08-20 22:54:39 +000036/* #define DEBUG_SAX2 */
37/* #define DEBUG_SAX2_TREE */
38
39/**
Daniel Veillarde57ec792003-09-10 10:50:59 +000040 * TODO:
41 *
42 * macro to flag unimplemented blocks
Haibo Huangcfd91dc2020-07-30 23:01:33 -070043 * XML_CATALOG_PREFER user env to select between system/public preferred
Daniel Veillarde57ec792003-09-10 10:50:59 +000044 * 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 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +080049#define TODO \
Daniel Veillarde57ec792003-09-10 10:50:59 +000050 xmlGenericError(xmlGenericErrorContext, \
51 "Unimplemented block at %s:%d\n", \
52 __FILE__, __LINE__);
53
William M. Brack42331a92004-07-29 07:07:16 +000054/*
55 * xmlSAX2ErrMemory:
56 * @ctxt: an XML validation parser context
57 * @msg: a string to accompany the error message
58 */
David Kilzer4472c3a2016-05-13 15:13:17 +080059static void LIBXML_ATTR_FORMAT(2,0)
William M. Bracka3215c72004-07-31 16:24:01 +000060xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
Daniel Veillard740cb1a2012-07-18 16:05:37 +080061 xmlStructuredErrorFunc schannel = NULL;
62 const char *str1 = "out of memory\n";
63
Daniel Veillard34099b42004-11-04 17:34:35 +000064 if (ctxt != NULL) {
Daniel Veillard740cb1a2012-07-18 16:05:37 +080065 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);
Daniel Veillard34099b42004-11-04 17:34:35 +000074 ctxt->errNo = XML_ERR_NO_MEMORY;
75 ctxt->instate = XML_PARSER_EOF;
76 ctxt->disableSAX = 1;
Daniel Veillard740cb1a2012-07-18 16:05:37 +080077 } 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);
Daniel Veillard34099b42004-11-04 17:34:35 +000084 }
William M. Brack42331a92004-07-29 07:07:16 +000085}
86
Daniel Veillarde57ec792003-09-10 10:50:59 +000087/**
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000088 * 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 */
David Kilzer4472c3a2016-05-13 15:13:17 +080097static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000098xmlErrValid(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;
Daniel Veillard34099b42004-11-04 17:34:35 +0000106 if (ctxt != NULL) {
107 ctxt->errNo = error;
108 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
109 schannel = ctxt->sax->serror;
Daniel Veillard2728f842006-03-09 16:49:24 +0000110 __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);
Daniel Veillard34099b42004-11-04 17:34:35 +0000116 ctxt->valid = 0;
Daniel Veillard2728f842006-03-09 16:49:24 +0000117 } 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 }
Daniel Veillardf88d8cf2003-12-08 10:25:02 +0000125}
126
127/**
Daniel Veillard87b30462005-07-05 14:04:36 +0000128 * 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 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800137static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000138xmlFatalErrMsg(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,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800147 XML_ERR_FATAL, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000148 (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 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800168static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000169xmlWarnMsg(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,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800178 XML_ERR_WARNING, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000179 (const char *) str1, NULL,
180 NULL, 0, 0, msg, str1);
181}
182
183/**
Daniel Veillard87b30462005-07-05 14:04:36 +0000184 * xmlNsWarnMsg:
185 * @ctxt: an XML parser context
186 * @error: the error number
187 * @msg: the error message
188 * @str1: an error string
189 *
190 * Handle a namespace warning
191 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800192static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000193xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
194 const char *msg, const xmlChar *str1, const xmlChar *str2)
195{
196 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
197 (ctxt->instate == XML_PARSER_EOF))
198 return;
199 if (ctxt != NULL)
200 ctxt->errNo = error;
201 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800202 XML_ERR_WARNING, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000203 (const char *) str1, (const char *) str2,
204 NULL, 0, 0, msg, str1, str2);
205}
206
207/**
Daniel Veillard1af9a412003-08-20 22:54:39 +0000208 * xmlSAX2GetPublicId:
209 * @ctx: the user data (XML parser context)
210 *
211 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
212 *
213 * Returns a xmlChar *
214 */
215const xmlChar *
216xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
217{
218 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
219 return(NULL);
220}
221
222/**
223 * xmlSAX2GetSystemId:
224 * @ctx: the user data (XML parser context)
225 *
226 * Provides the system ID, basically URL or filename e.g.
227 * http://www.sgmlsource.com/dtds/memo.dtd
228 *
229 * Returns a xmlChar *
230 */
231const xmlChar *
232xmlSAX2GetSystemId(void *ctx)
233{
234 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard24505b02005-07-28 23:49:35 +0000235 if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800236 return((const xmlChar *) ctxt->input->filename);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000237}
238
239/**
240 * xmlSAX2GetLineNumber:
241 * @ctx: the user data (XML parser context)
242 *
243 * Provide the line number of the current parsing point.
244 *
245 * Returns an int
246 */
247int
248xmlSAX2GetLineNumber(void *ctx)
249{
250 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000251 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000252 return(ctxt->input->line);
253}
254
255/**
256 * xmlSAX2GetColumnNumber:
257 * @ctx: the user data (XML parser context)
258 *
259 * Provide the column number of the current parsing point.
260 *
261 * Returns an int
262 */
263int
264xmlSAX2GetColumnNumber(void *ctx)
265{
266 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000267 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000268 return(ctxt->input->col);
269}
270
271/**
272 * xmlSAX2IsStandalone:
273 * @ctx: the user data (XML parser context)
274 *
275 * Is this document tagged standalone ?
276 *
277 * Returns 1 if true
278 */
279int
280xmlSAX2IsStandalone(void *ctx)
281{
282 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000283 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000284 return(ctxt->myDoc->standalone == 1);
285}
286
287/**
288 * xmlSAX2HasInternalSubset:
289 * @ctx: the user data (XML parser context)
290 *
291 * Does this document has an internal subset
292 *
293 * Returns 1 if true
294 */
295int
296xmlSAX2HasInternalSubset(void *ctx)
297{
298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000299 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000300 return(ctxt->myDoc->intSubset != NULL);
301}
302
303/**
304 * xmlSAX2HasExternalSubset:
305 * @ctx: the user data (XML parser context)
306 *
307 * Does this document has an external subset
308 *
309 * Returns 1 if true
310 */
311int
312xmlSAX2HasExternalSubset(void *ctx)
313{
314 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000315 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000316 return(ctxt->myDoc->extSubset != NULL);
317}
318
319/**
320 * xmlSAX2InternalSubset:
321 * @ctx: the user data (XML parser context)
322 * @name: the root element name
323 * @ExternalID: the external ID
324 * @SystemID: the SYSTEM ID (e.g. filename or URL)
325 *
326 * Callback on internal subset declaration.
327 */
328void
329xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
330 const xmlChar *ExternalID, const xmlChar *SystemID)
331{
332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
333 xmlDtdPtr dtd;
Daniel Veillard34099b42004-11-04 17:34:35 +0000334 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000335#ifdef DEBUG_SAX
336 xmlGenericError(xmlGenericErrorContext,
337 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
338 name, ExternalID, SystemID);
339#endif
340
341 if (ctxt->myDoc == NULL)
342 return;
343 dtd = xmlGetIntSubset(ctxt->myDoc);
344 if (dtd != NULL) {
345 if (ctxt->html)
346 return;
347 xmlUnlinkNode((xmlNodePtr) dtd);
348 xmlFreeDtd(dtd);
349 ctxt->myDoc->intSubset = NULL;
350 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800351 ctxt->myDoc->intSubset =
Daniel Veillard1af9a412003-08-20 22:54:39 +0000352 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
William M. Brack42331a92004-07-29 07:07:16 +0000353 if (ctxt->myDoc->intSubset == NULL)
354 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000355}
356
357/**
358 * xmlSAX2ExternalSubset:
359 * @ctx: the user data (XML parser context)
360 * @name: the root element name
361 * @ExternalID: the external ID
362 * @SystemID: the SYSTEM ID (e.g. filename or URL)
363 *
364 * Callback on external subset declaration.
365 */
366void
367xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
368 const xmlChar *ExternalID, const xmlChar *SystemID)
369{
370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000371 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000372#ifdef DEBUG_SAX
373 xmlGenericError(xmlGenericErrorContext,
374 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
375 name, ExternalID, SystemID);
376#endif
377 if (((ExternalID != NULL) || (SystemID != NULL)) &&
378 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
379 (ctxt->wellFormed && ctxt->myDoc))) {
380 /*
381 * Try to fetch and parse the external subset.
382 */
383 xmlParserInputPtr oldinput;
384 int oldinputNr;
385 int oldinputMax;
386 xmlParserInputPtr *oldinputTab;
387 xmlParserInputPtr input = NULL;
388 xmlCharEncoding enc;
389 int oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800390 const xmlChar *oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000391
392 /*
393 * Ask the Entity resolver to load the damn thing
394 */
395 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
396 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
397 SystemID);
398 if (input == NULL) {
399 return;
400 }
401
402 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
403
404 /*
405 * make sure we won't destroy the main document context
406 */
407 oldinput = ctxt->input;
408 oldinputNr = ctxt->inputNr;
409 oldinputMax = ctxt->inputMax;
410 oldinputTab = ctxt->inputTab;
411 oldcharset = ctxt->charset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800412 oldencoding = ctxt->encoding;
413 ctxt->encoding = NULL;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000414
415 ctxt->inputTab = (xmlParserInputPtr *)
416 xmlMalloc(5 * sizeof(xmlParserInputPtr));
417 if (ctxt->inputTab == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000418 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000419 ctxt->input = oldinput;
420 ctxt->inputNr = oldinputNr;
421 ctxt->inputMax = oldinputMax;
422 ctxt->inputTab = oldinputTab;
423 ctxt->charset = oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800424 ctxt->encoding = oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000425 return;
426 }
427 ctxt->inputNr = 0;
428 ctxt->inputMax = 5;
429 ctxt->input = NULL;
430 xmlPushInput(ctxt, input);
431
432 /*
433 * On the fly encoding conversion if needed
434 */
435 if (ctxt->input->length >= 4) {
436 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
437 xmlSwitchEncoding(ctxt, enc);
438 }
439
440 if (input->filename == NULL)
441 input->filename = (char *) xmlCanonicPath(SystemID);
442 input->line = 1;
443 input->col = 1;
444 input->base = ctxt->input->cur;
445 input->cur = ctxt->input->cur;
446 input->free = NULL;
447
448 /*
449 * let's parse that entity knowing it's an external subset.
450 */
451 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
452
453 /*
454 * Free up the external entities
455 */
456
457 while (ctxt->inputNr > 1)
458 xmlPopInput(ctxt);
459 xmlFreeInputStream(ctxt->input);
460 xmlFree(ctxt->inputTab);
461
462 /*
463 * Restore the parsing context of the main entity
464 */
465 ctxt->input = oldinput;
466 ctxt->inputNr = oldinputNr;
467 ctxt->inputMax = oldinputMax;
468 ctxt->inputTab = oldinputTab;
469 ctxt->charset = oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800470 if ((ctxt->encoding != NULL) &&
471 ((ctxt->dict == NULL) ||
472 (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
473 xmlFree((xmlChar *) ctxt->encoding);
474 ctxt->encoding = oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000475 /* ctxt->wellFormed = oldwellFormed; */
476 }
477}
478
479/**
480 * xmlSAX2ResolveEntity:
481 * @ctx: the user data (XML parser context)
482 * @publicId: The public ID of the entity
483 * @systemId: The system ID of the entity
484 *
485 * The entity loader, to control the loading of external entities,
486 * the application can either:
487 * - override this xmlSAX2ResolveEntity() callback in the SAX block
488 * - or better use the xmlSetExternalEntityLoader() function to
489 * set up it's own entity resolution routine
490 *
491 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
492 */
493xmlParserInputPtr
494xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
495{
496 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
497 xmlParserInputPtr ret;
498 xmlChar *URI;
499 const char *base = NULL;
500
Daniel Veillard34099b42004-11-04 17:34:35 +0000501 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000502 if (ctxt->input != NULL)
503 base = ctxt->input->filename;
504 if (base == NULL)
505 base = ctxt->directory;
506
507 URI = xmlBuildURI(systemId, (const xmlChar *) base);
508
509#ifdef DEBUG_SAX
510 xmlGenericError(xmlGenericErrorContext,
511 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
512#endif
513
514 ret = xmlLoadExternalEntity((const char *) URI,
515 (const char *) publicId, ctxt);
516 if (URI != NULL)
517 xmlFree(URI);
518 return(ret);
519}
520
521/**
522 * xmlSAX2GetEntity:
523 * @ctx: the user data (XML parser context)
524 * @name: The entity name
525 *
526 * Get an entity by name
527 *
528 * Returns the xmlEntityPtr if found.
529 */
530xmlEntityPtr
531xmlSAX2GetEntity(void *ctx, const xmlChar *name)
532{
533 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
534 xmlEntityPtr ret = NULL;
535
Daniel Veillard34099b42004-11-04 17:34:35 +0000536 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000537#ifdef DEBUG_SAX
538 xmlGenericError(xmlGenericErrorContext,
539 "SAX.xmlSAX2GetEntity(%s)\n", name);
540#endif
541
542 if (ctxt->inSubset == 0) {
543 ret = xmlGetPredefinedEntity(name);
544 if (ret != NULL)
545 return(ret);
546 }
547 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
548 if (ctxt->inSubset == 2) {
549 ctxt->myDoc->standalone = 0;
550 ret = xmlGetDocEntity(ctxt->myDoc, name);
551 ctxt->myDoc->standalone = 1;
552 } else {
553 ret = xmlGetDocEntity(ctxt->myDoc, name);
554 if (ret == NULL) {
555 ctxt->myDoc->standalone = 0;
556 ret = xmlGetDocEntity(ctxt->myDoc, name);
557 if (ret != NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000558 xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
559 "Entity(%s) document marked standalone but requires external subset\n",
560 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000561 }
562 ctxt->myDoc->standalone = 1;
563 }
564 }
565 } else {
566 ret = xmlGetDocEntity(ctxt->myDoc, name);
567 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000568 return(ret);
569}
570
571/**
572 * xmlSAX2GetParameterEntity:
573 * @ctx: the user data (XML parser context)
574 * @name: The entity name
575 *
576 * Get a parameter entity by name
577 *
578 * Returns the xmlEntityPtr if found.
579 */
580xmlEntityPtr
581xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
582{
583 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
584 xmlEntityPtr ret;
585
Daniel Veillard34099b42004-11-04 17:34:35 +0000586 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000587#ifdef DEBUG_SAX
588 xmlGenericError(xmlGenericErrorContext,
589 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
590#endif
591
592 ret = xmlGetParameterEntity(ctxt->myDoc, name);
593 return(ret);
594}
595
596
597/**
598 * xmlSAX2EntityDecl:
599 * @ctx: the user data (XML parser context)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800600 * @name: the entity name
601 * @type: the entity type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000602 * @publicId: The public ID of the entity
603 * @systemId: The system ID of the entity
604 * @content: the entity value (without processing).
605 *
606 * An entity definition has been parsed
607 */
608void
609xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
610 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
611{
612 xmlEntityPtr ent;
613 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
614
Daniel Veillard34099b42004-11-04 17:34:35 +0000615 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000616#ifdef DEBUG_SAX
617 xmlGenericError(xmlGenericErrorContext,
618 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
619 name, type, publicId, systemId, content);
620#endif
621 if (ctxt->inSubset == 1) {
622 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
623 systemId, content);
Daniel Veillard87b30462005-07-05 14:04:36 +0000624 if ((ent == NULL) && (ctxt->pedantic))
625 xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
626 "Entity(%s) already defined in the internal subset\n",
627 name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000628 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
629 xmlChar *URI;
630 const char *base = NULL;
631
632 if (ctxt->input != NULL)
633 base = ctxt->input->filename;
634 if (base == NULL)
635 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800636
Daniel Veillard1af9a412003-08-20 22:54:39 +0000637 URI = xmlBuildURI(systemId, (const xmlChar *) base);
638 ent->URI = URI;
639 }
640 } else if (ctxt->inSubset == 2) {
641 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
642 systemId, content);
643 if ((ent == NULL) && (ctxt->pedantic) &&
644 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800645 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000646 "Entity(%s) already defined in the external subset\n", name);
647 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
648 xmlChar *URI;
649 const char *base = NULL;
650
651 if (ctxt->input != NULL)
652 base = ctxt->input->filename;
653 if (base == NULL)
654 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800655
Daniel Veillard1af9a412003-08-20 22:54:39 +0000656 URI = xmlBuildURI(systemId, (const xmlChar *) base);
657 ent->URI = URI;
658 }
659 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000660 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
661 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
662 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000663 }
664}
665
666/**
667 * xmlSAX2AttributeDecl:
668 * @ctx: the user data (XML parser context)
669 * @elem: the name of the element
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800670 * @fullname: the attribute name
671 * @type: the attribute type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000672 * @def: the type of default value
673 * @defaultValue: the attribute default value
674 * @tree: the tree of enumerated value set
675 *
676 * An attribute definition has been parsed
677 */
678void
679xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
680 int type, int def, const xmlChar *defaultValue,
681 xmlEnumerationPtr tree)
682{
683 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
684 xmlAttributePtr attr;
685 xmlChar *name = NULL, *prefix = NULL;
686
Elliott Hughesecdab2a2022-02-23 14:33:50 -0800687 /* Avoid unused variable warning if features are disabled. */
688 (void) attr;
689
Daniel Veillard2728f842006-03-09 16:49:24 +0000690 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
691 return;
692
Daniel Veillard1af9a412003-08-20 22:54:39 +0000693#ifdef DEBUG_SAX
694 xmlGenericError(xmlGenericErrorContext,
695 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
696 elem, fullname, type, def, defaultValue);
697#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000698 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
699 (type != XML_ATTRIBUTE_ID)) {
700 /*
701 * Raise the error but keep the validity flag
702 */
703 int tmp = ctxt->valid;
704 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
705 "xml:id : attribute type should be ID\n", NULL, NULL);
706 ctxt->valid = tmp;
707 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000708 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000709 name = xmlSplitQName(ctxt, fullname, &prefix);
710 ctxt->vctxt.valid = 1;
711 if (ctxt->inSubset == 1)
712 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
713 name, prefix, (xmlAttributeType) type,
714 (xmlAttributeDefault) def, defaultValue, tree);
715 else if (ctxt->inSubset == 2)
716 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800717 name, prefix, (xmlAttributeType) type,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000718 (xmlAttributeDefault) def, defaultValue, tree);
719 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000720 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
721 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
722 name, NULL);
Elliott Hughesecdab2a2022-02-23 14:33:50 -0800723 xmlFree(name);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000724 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000725 return;
726 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000727#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000728 if (ctxt->vctxt.valid == 0)
729 ctxt->valid = 0;
730 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
Daniel Veillard2728f842006-03-09 16:49:24 +0000731 (ctxt->myDoc->intSubset != NULL))
Daniel Veillard1af9a412003-08-20 22:54:39 +0000732 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
733 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000734#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000735 if (prefix != NULL)
736 xmlFree(prefix);
737 if (name != NULL)
738 xmlFree(name);
739}
740
741/**
742 * xmlSAX2ElementDecl:
743 * @ctx: the user data (XML parser context)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800744 * @name: the element name
745 * @type: the element type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000746 * @content: the element value tree
747 *
748 * An element definition has been parsed
749 */
750void
751xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
752 xmlElementContentPtr content)
753{
754 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
755 xmlElementPtr elem = NULL;
756
Elliott Hughesecdab2a2022-02-23 14:33:50 -0800757 /* Avoid unused variable warning if features are disabled. */
758 (void) elem;
759
Daniel Veillard2728f842006-03-09 16:49:24 +0000760 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
761 return;
762
Daniel Veillard1af9a412003-08-20 22:54:39 +0000763#ifdef DEBUG_SAX
764 xmlGenericError(xmlGenericErrorContext,
765 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
766#endif
767
768 if (ctxt->inSubset == 1)
769 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
770 name, (xmlElementTypeVal) type, content);
771 else if (ctxt->inSubset == 2)
772 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
773 name, (xmlElementTypeVal) type, content);
774 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000775 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
776 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
777 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000778 return;
779 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000780#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000781 if (elem == NULL)
782 ctxt->valid = 0;
783 if (ctxt->validate && ctxt->wellFormed &&
784 ctxt->myDoc && ctxt->myDoc->intSubset)
785 ctxt->valid &=
786 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000787#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000788}
789
790/**
791 * xmlSAX2NotationDecl:
792 * @ctx: the user data (XML parser context)
793 * @name: The name of the notation
794 * @publicId: The public ID of the entity
795 * @systemId: The system ID of the entity
796 *
797 * What to do when a notation declaration has been parsed.
798 */
799void
800xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
801 const xmlChar *publicId, const xmlChar *systemId)
802{
803 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
804 xmlNotationPtr nota = NULL;
805
Elliott Hughesecdab2a2022-02-23 14:33:50 -0800806 /* Avoid unused variable warning if features are disabled. */
807 (void) nota;
808
Daniel Veillard2728f842006-03-09 16:49:24 +0000809 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
810 return;
811
Daniel Veillard1af9a412003-08-20 22:54:39 +0000812#ifdef DEBUG_SAX
813 xmlGenericError(xmlGenericErrorContext,
814 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
815#endif
816
817 if ((publicId == NULL) && (systemId == NULL)) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000818 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
819 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
820 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000821 return;
822 } else if (ctxt->inSubset == 1)
823 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
824 publicId, systemId);
825 else if (ctxt->inSubset == 2)
826 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
827 publicId, systemId);
828 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000829 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
830 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
831 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000832 return;
833 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000834#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000835 if (nota == NULL) ctxt->valid = 0;
Daniel Veillard2728f842006-03-09 16:49:24 +0000836 if ((ctxt->validate) && (ctxt->wellFormed) &&
837 (ctxt->myDoc->intSubset != NULL))
Daniel Veillard1af9a412003-08-20 22:54:39 +0000838 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
839 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000840#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000841}
842
843/**
844 * xmlSAX2UnparsedEntityDecl:
845 * @ctx: the user data (XML parser context)
846 * @name: The name of the entity
847 * @publicId: The public ID of the entity
848 * @systemId: The system ID of the entity
849 * @notationName: the name of the notation
850 *
851 * What to do when an unparsed entity declaration is parsed
852 */
853void
854xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
855 const xmlChar *publicId, const xmlChar *systemId,
856 const xmlChar *notationName)
857{
858 xmlEntityPtr ent;
859 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000860 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000861#ifdef DEBUG_SAX
862 xmlGenericError(xmlGenericErrorContext,
863 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
864 name, publicId, systemId, notationName);
865#endif
866 if (ctxt->inSubset == 1) {
867 ent = xmlAddDocEntity(ctxt->myDoc, name,
868 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
869 publicId, systemId, notationName);
870 if ((ent == NULL) && (ctxt->pedantic) &&
871 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800872 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000873 "Entity(%s) already defined in the internal subset\n", name);
874 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
875 xmlChar *URI;
876 const char *base = NULL;
877
878 if (ctxt->input != NULL)
879 base = ctxt->input->filename;
880 if (base == NULL)
881 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800882
Daniel Veillard1af9a412003-08-20 22:54:39 +0000883 URI = xmlBuildURI(systemId, (const xmlChar *) base);
884 ent->URI = URI;
885 }
886 } else if (ctxt->inSubset == 2) {
887 ent = xmlAddDtdEntity(ctxt->myDoc, name,
888 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
889 publicId, systemId, notationName);
890 if ((ent == NULL) && (ctxt->pedantic) &&
891 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800892 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000893 "Entity(%s) already defined in the external subset\n", name);
894 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
895 xmlChar *URI;
896 const char *base = NULL;
897
898 if (ctxt->input != NULL)
899 base = ctxt->input->filename;
900 if (base == NULL)
901 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800902
Daniel Veillard1af9a412003-08-20 22:54:39 +0000903 URI = xmlBuildURI(systemId, (const xmlChar *) base);
904 ent->URI = URI;
905 }
906 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000907 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
908 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
909 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000910 }
911}
912
913/**
914 * xmlSAX2SetDocumentLocator:
915 * @ctx: the user data (XML parser context)
916 * @loc: A SAX Locator
917 *
918 * Receive the document locator at startup, actually xmlDefaultSAXLocator
919 * Everything is available on the context, so this is useless in our case.
920 */
921void
922xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
923{
924 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
925#ifdef DEBUG_SAX
926 xmlGenericError(xmlGenericErrorContext,
927 "SAX.xmlSAX2SetDocumentLocator()\n");
928#endif
929}
930
931/**
932 * xmlSAX2StartDocument:
933 * @ctx: the user data (XML parser context)
934 *
935 * called when the document start being processed.
936 */
937void
938xmlSAX2StartDocument(void *ctx)
939{
940 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
941 xmlDocPtr doc;
942
Daniel Veillard34099b42004-11-04 17:34:35 +0000943 if (ctx == NULL) return;
944
Daniel Veillard1af9a412003-08-20 22:54:39 +0000945#ifdef DEBUG_SAX
946 xmlGenericError(xmlGenericErrorContext,
947 "SAX.xmlSAX2StartDocument()\n");
948#endif
949 if (ctxt->html) {
950#ifdef LIBXML_HTML_ENABLED
951 if (ctxt->myDoc == NULL)
952 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
953 if (ctxt->myDoc == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000954 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000955 return;
956 }
Gaurava885f132013-08-03 22:16:02 +0800957 ctxt->myDoc->properties = XML_DOC_HTML;
958 ctxt->myDoc->parseFlags = ctxt->options;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000959#else
960 xmlGenericError(xmlGenericErrorContext,
961 "libxml2 built without HTML support\n");
962 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
963 ctxt->instate = XML_PARSER_EOF;
964 ctxt->disableSAX = 1;
965 return;
966#endif
967 } else {
968 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
969 if (doc != NULL) {
Daniel Veillardae0765b2008-07-31 19:54:59 +0000970 doc->properties = 0;
971 if (ctxt->options & XML_PARSE_OLD10)
972 doc->properties |= XML_DOC_OLD10;
973 doc->parseFlags = ctxt->options;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000974 if (ctxt->encoding != NULL)
975 doc->encoding = xmlStrdup(ctxt->encoding);
976 else
977 doc->encoding = NULL;
978 doc->standalone = ctxt->standalone;
979 } else {
William M. Brack42331a92004-07-29 07:07:16 +0000980 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000981 return;
982 }
Daniel Veillard500a1de2004-03-22 15:22:58 +0000983 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +0000984 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000985 xmlDictReference(doc->dict);
986 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000987 }
988 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
989 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
Daniel Veillardb8efdda2006-10-10 12:37:14 +0000990 ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000991 if (ctxt->myDoc->URL == NULL)
William M. Bracka3215c72004-07-31 16:24:01 +0000992 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000993 }
994}
995
996/**
997 * xmlSAX2EndDocument:
998 * @ctx: the user data (XML parser context)
999 *
1000 * called when the document end has been detected.
1001 */
1002void
1003xmlSAX2EndDocument(void *ctx)
1004{
1005 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1006#ifdef DEBUG_SAX
1007 xmlGenericError(xmlGenericErrorContext,
1008 "SAX.xmlSAX2EndDocument()\n");
1009#endif
Daniel Veillard34099b42004-11-04 17:34:35 +00001010 if (ctx == NULL) return;
Daniel Veillard4432df22003-09-28 18:58:27 +00001011#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001012 if (ctxt->validate && ctxt->wellFormed &&
1013 ctxt->myDoc && ctxt->myDoc->intSubset)
1014 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +00001015#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001016
1017 /*
1018 * Grab the encoding if it was added on-the-fly
1019 */
1020 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1021 (ctxt->myDoc->encoding == NULL)) {
1022 ctxt->myDoc->encoding = ctxt->encoding;
1023 ctxt->encoding = NULL;
1024 }
Daniel Veillard36e5cd52004-11-02 14:52:23 +00001025 if ((ctxt->inputTab != NULL) &&
1026 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1027 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001028 (ctxt->myDoc->encoding == NULL)) {
1029 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1030 }
1031 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1032 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1033 ctxt->myDoc->charset = ctxt->charset;
1034 }
1035}
1036
Nicolas Le Cam77b5b462014-02-10 10:32:45 +08001037#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001038/**
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001039 * xmlNsErrMsg:
1040 * @ctxt: an XML parser context
1041 * @error: the error number
1042 * @msg: the error message
1043 * @str1: an error string
1044 * @str2: an error string
1045 *
1046 * Handle a namespace error
1047 */
1048static void LIBXML_ATTR_FORMAT(3,0)
1049xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
1050 const char *msg, const xmlChar *str1, const xmlChar *str2)
1051{
1052 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
1053 (ctxt->instate == XML_PARSER_EOF))
1054 return;
1055 if (ctxt != NULL)
1056 ctxt->errNo = error;
1057 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
1058 XML_ERR_ERROR, NULL, 0,
1059 (const char *) str1, (const char *) str2,
1060 NULL, 0, 0, msg, str1, str2);
1061}
1062
1063/**
Daniel Veillard1af9a412003-08-20 22:54:39 +00001064 * xmlSAX2AttributeInternal:
1065 * @ctx: the user data (XML parser context)
1066 * @fullname: The attribute name, including namespace prefix
1067 * @value: The attribute value
1068 * @prefix: the prefix on the element node
1069 *
1070 * Handle an attribute that has been read by the parser.
1071 * The default handling is to convert the attribute into an
1072 * DOM subtree and past it in a new xmlAttr element added to
1073 * the element.
1074 */
1075static void
1076xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001077 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001078{
1079 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1080 xmlAttrPtr ret;
1081 xmlChar *name;
1082 xmlChar *ns;
1083 xmlChar *nval;
1084 xmlNsPtr namespace;
1085
Daniel Veillarddbbd72b2007-06-12 15:15:52 +00001086 if (ctxt->html) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001087 name = xmlStrdup(fullname);
Daniel Veillarddbbd72b2007-06-12 15:15:52 +00001088 ns = NULL;
1089 namespace = NULL;
1090 } else {
1091 /*
1092 * Split the full name into a namespace prefix and the tag name
1093 */
1094 name = xmlSplitQName(ctxt, fullname, &ns);
1095 if ((name != NULL) && (name[0] == 0)) {
1096 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1097 xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1098 "invalid namespace declaration '%s'\n",
1099 fullname, NULL);
1100 } else {
1101 xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1102 "Avoid attribute ending with ':' like '%s'\n",
1103 fullname, NULL);
1104 }
1105 if (ns != NULL)
1106 xmlFree(ns);
1107 ns = NULL;
1108 xmlFree(name);
1109 name = xmlStrdup(fullname);
1110 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001111 }
1112 if (name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001113 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001114 if (ns != NULL)
1115 xmlFree(ns);
1116 return;
1117 }
1118
Daniel Veillard3c080d62010-03-15 15:47:50 +01001119#ifdef LIBXML_HTML_ENABLED
1120 if ((ctxt->html) &&
1121 (value == NULL) && (htmlIsBooleanAttr(fullname))) {
Daniel Veillard06c93b72010-03-15 16:08:44 +01001122 nval = xmlStrdup(fullname);
1123 value = (const xmlChar *) nval;
Daniel Veillard3c080d62010-03-15 15:47:50 +01001124 } else
1125#endif
1126 {
Daniel Veillard4432df22003-09-28 18:58:27 +00001127#ifdef LIBXML_VALID_ENABLED
Daniel Veillard3c080d62010-03-15 15:47:50 +01001128 /*
1129 * Do the last stage of the attribute normalization
1130 * Needed for HTML too:
1131 * http://www.w3.org/TR/html4/types.html#h-6.2
1132 */
1133 ctxt->vctxt.valid = 1;
1134 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1135 ctxt->myDoc, ctxt->node,
1136 fullname, value);
1137 if (ctxt->vctxt.valid != 1) {
1138 ctxt->valid = 0;
1139 }
1140 if (nval != NULL)
1141 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +00001142#else
Daniel Veillard3c080d62010-03-15 15:47:50 +01001143 nval = NULL;
Daniel Veillard4432df22003-09-28 18:58:27 +00001144#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard3c080d62010-03-15 15:47:50 +01001145 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001146
1147 /*
1148 * Check whether it's a namespace definition
1149 */
1150 if ((!ctxt->html) && (ns == NULL) &&
1151 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1152 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1153 xmlNsPtr nsret;
1154 xmlChar *val;
1155
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001156 /* Avoid unused variable warning if features are disabled. */
1157 (void) nsret;
1158
Daniel Veillard1af9a412003-08-20 22:54:39 +00001159 if (!ctxt->replaceEntities) {
1160 ctxt->depth++;
1161 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1162 0,0,0);
1163 ctxt->depth--;
Gaurav3e0eec42014-06-13 14:45:20 +08001164 if (val == NULL) {
1165 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1166 if (name != NULL)
1167 xmlFree(name);
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001168 if (nval != NULL)
1169 xmlFree(nval);
Gaurav3e0eec42014-06-13 14:45:20 +08001170 return;
1171 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001172 } else {
1173 val = (xmlChar *) value;
1174 }
1175
1176 if (val[0] != 0) {
1177 xmlURIPtr uri;
1178
1179 uri = xmlParseURI((const char *)val);
1180 if (uri == NULL) {
1181 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001182 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +00001183 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001184 } else {
1185 if (uri->scheme == NULL) {
1186 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001187 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001188 "xmlns: URI %s is not absolute\n", val);
1189 }
1190 xmlFreeURI(uri);
1191 }
1192 }
1193
1194 /* a default namespace definition */
1195 nsret = xmlNewNs(ctxt->node, val, NULL);
1196
Daniel Veillard4432df22003-09-28 18:58:27 +00001197#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001198 /*
1199 * Validate also for namespace decls, they are attributes from
1200 * an XML-1.0 perspective
1201 */
1202 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1203 ctxt->myDoc && ctxt->myDoc->intSubset)
1204 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1205 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001206#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001207 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001208 xmlFree(name);
1209 if (nval != NULL)
1210 xmlFree(nval);
1211 if (val != value)
1212 xmlFree(val);
1213 return;
1214 }
1215 if ((!ctxt->html) &&
1216 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1217 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1218 xmlNsPtr nsret;
1219 xmlChar *val;
1220
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001221 /* Avoid unused variable warning if features are disabled. */
1222 (void) nsret;
1223
Daniel Veillard1af9a412003-08-20 22:54:39 +00001224 if (!ctxt->replaceEntities) {
1225 ctxt->depth++;
1226 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1227 0,0,0);
1228 ctxt->depth--;
1229 if (val == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001230 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001231 xmlFree(ns);
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001232 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001233 xmlFree(name);
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001234 if (nval != NULL)
1235 xmlFree(nval);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001236 return;
1237 }
1238 } else {
1239 val = (xmlChar *) value;
1240 }
1241
1242 if (val[0] == 0) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001243 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1244 "Empty namespace name for prefix %s\n", name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001245 }
1246 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1247 xmlURIPtr uri;
1248
1249 uri = xmlParseURI((const char *)val);
1250 if (uri == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001251 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001252 "xmlns:%s: %s not a valid URI\n", name, value);
1253 } else {
1254 if (uri->scheme == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001255 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001256 "xmlns:%s: URI %s is not absolute\n", name, value);
1257 }
1258 xmlFreeURI(uri);
1259 }
1260 }
1261
1262 /* a standard namespace definition */
1263 nsret = xmlNewNs(ctxt->node, val, name);
1264 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001265#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001266 /*
1267 * Validate also for namespace decls, they are attributes from
1268 * an XML-1.0 perspective
1269 */
1270 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1271 ctxt->myDoc && ctxt->myDoc->intSubset)
1272 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1273 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001274#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001275 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001276 xmlFree(name);
1277 if (nval != NULL)
1278 xmlFree(nval);
1279 if (val != value)
1280 xmlFree(val);
1281 return;
1282 }
1283
1284 if (ns != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001285 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001286
Daniel Veillard67906942003-08-28 21:13:25 +00001287 if (namespace == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001288 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
William M. Brack4811ba32003-09-06 18:02:53 +00001289 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001290 ns, name);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001291 } else {
1292 xmlAttrPtr prop;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001293
Daniel Veillardd44b9362009-09-07 12:15:08 +02001294 prop = ctxt->node->properties;
1295 while (prop != NULL) {
1296 if (prop->ns != NULL) {
1297 if ((xmlStrEqual(name, prop->name)) &&
1298 ((namespace == prop->ns) ||
1299 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1300 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1301 "Attribute %s in %s redefined\n",
1302 name, namespace->href);
1303 ctxt->wellFormed = 0;
1304 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001305 if (name != NULL)
1306 xmlFree(name);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001307 goto error;
1308 }
1309 }
1310 prop = prop->next;
1311 }
1312 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001313 } else {
1314 namespace = NULL;
1315 }
1316
1317 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1318 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1319
1320 if (ret != NULL) {
1321 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1322 xmlNodePtr tmp;
1323
1324 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1325 tmp = ret->children;
1326 while (tmp != NULL) {
1327 tmp->parent = (xmlNodePtr) ret;
1328 if (tmp->next == NULL)
1329 ret->last = tmp;
1330 tmp = tmp->next;
1331 }
1332 } else if (value != NULL) {
1333 ret->children = xmlNewDocText(ctxt->myDoc, value);
1334 ret->last = ret->children;
1335 if (ret->children != NULL)
1336 ret->children->parent = (xmlNodePtr) ret;
1337 }
1338 }
1339
Daniel Veillard4432df22003-09-28 18:58:27 +00001340#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001341 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1342 ctxt->myDoc && ctxt->myDoc->intSubset) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001343
Daniel Veillard1af9a412003-08-20 22:54:39 +00001344 /*
1345 * If we don't substitute entities, the validation should be
1346 * done on a value with replaced entities anyway.
1347 */
1348 if (!ctxt->replaceEntities) {
1349 xmlChar *val;
1350
1351 ctxt->depth++;
1352 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1353 0,0,0);
1354 ctxt->depth--;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001355
Daniel Veillard1af9a412003-08-20 22:54:39 +00001356 if (val == NULL)
1357 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1358 ctxt->myDoc, ctxt->node, ret, value);
1359 else {
1360 xmlChar *nvalnorm;
1361
1362 /*
1363 * Do the last stage of the attribute normalization
1364 * It need to be done twice ... it's an extra burden related
1365 * to the ability to keep xmlSAX2References in attributes
1366 */
1367 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1368 ctxt->node, fullname, val);
1369 if (nvalnorm != NULL) {
1370 xmlFree(val);
1371 val = nvalnorm;
1372 }
1373
1374 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1375 ctxt->myDoc, ctxt->node, ret, val);
1376 xmlFree(val);
1377 }
1378 } else {
1379 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1380 ctxt->node, ret, value);
1381 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001382 } else
1383#endif /* LIBXML_VALID_ENABLED */
1384 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001385 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001386 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
1387 /* Don't create IDs containing entity references */
1388 (ret->children != NULL) &&
1389 (ret->children->type == XML_TEXT_NODE) &&
1390 (ret->children->next == NULL)) {
1391 xmlChar *content = ret->children->content;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001392 /*
1393 * when validating, the ID registration is done at the attribute
1394 * validation level. Otherwise we have to do specific handling here.
1395 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001396 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001397 /*
1398 * Add the xml:id value
1399 *
1400 * Open issue: normalization of the value.
1401 */
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001402 if (xmlValidateNCName(content, 1) != 0) {
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001403 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1404 "xml:id : attribute value %s is not an NCName\n",
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001405 (const char *) content, NULL);
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001406 }
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001407 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001408 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001409 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001410 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001411 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001412 }
1413
1414error:
1415 if (nval != NULL)
1416 xmlFree(nval);
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001417 if (ns != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001418 xmlFree(ns);
1419}
1420
Daniel Veillard1af9a412003-08-20 22:54:39 +00001421/*
1422 * xmlCheckDefaultedAttributes:
1423 *
1424 * Check defaulted attributes from the DTD
1425 */
1426static void
1427xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1428 const xmlChar *prefix, const xmlChar **atts) {
1429 xmlElementPtr elemDecl;
1430 const xmlChar *att;
1431 int internal = 1;
1432 int i;
1433
1434 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1435 if (elemDecl == NULL) {
1436 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1437 internal = 0;
1438 }
1439
1440process_external_subset:
1441
1442 if (elemDecl != NULL) {
1443 xmlAttributePtr attr = elemDecl->attributes;
1444 /*
1445 * Check against defaulted attributes from the external subset
1446 * if the document is stamped as standalone
1447 */
1448 if ((ctxt->myDoc->standalone == 1) &&
1449 (ctxt->myDoc->extSubset != NULL) &&
1450 (ctxt->validate)) {
1451 while (attr != NULL) {
1452 if ((attr->defaultValue != NULL) &&
1453 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1454 attr->elem, attr->name,
1455 attr->prefix) == attr) &&
1456 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1457 attr->elem, attr->name,
1458 attr->prefix) == NULL)) {
1459 xmlChar *fulln;
1460
1461 if (attr->prefix != NULL) {
1462 fulln = xmlStrdup(attr->prefix);
1463 fulln = xmlStrcat(fulln, BAD_CAST ":");
1464 fulln = xmlStrcat(fulln, attr->name);
1465 } else {
1466 fulln = xmlStrdup(attr->name);
1467 }
Jim Meyering669e88c2009-07-29 11:33:32 +02001468 if (fulln == NULL) {
1469 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1470 break;
1471 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001472
1473 /*
1474 * Check that the attribute is not declared in the
1475 * serialization
1476 */
1477 att = NULL;
1478 if (atts != NULL) {
1479 i = 0;
1480 att = atts[i];
1481 while (att != NULL) {
1482 if (xmlStrEqual(att, fulln))
1483 break;
1484 i += 2;
1485 att = atts[i];
1486 }
1487 }
1488 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001489 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001490 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001491 (const char *)fulln,
1492 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001493 }
Daniel Veillard023d0ba2009-07-29 11:34:50 +02001494 xmlFree(fulln);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001495 }
1496 attr = attr->nexth;
1497 }
1498 }
1499
1500 /*
1501 * Actually insert defaulted values when needed
1502 */
1503 attr = elemDecl->attributes;
1504 while (attr != NULL) {
1505 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001506 * Make sure that attributes redefinition occurring in the
1507 * internal subset are not overridden by definitions in the
Daniel Veillard1af9a412003-08-20 22:54:39 +00001508 * external subset.
1509 */
1510 if (attr->defaultValue != NULL) {
1511 /*
1512 * the element should be instantiated in the tree if:
1513 * - this is a namespace prefix
1514 * - the user required for completion in the tree
1515 * like XSLT
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001516 * - there isn't already an attribute definition
Daniel Veillard1af9a412003-08-20 22:54:39 +00001517 * in the internal subset overriding it.
1518 */
1519 if (((attr->prefix != NULL) &&
1520 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1521 ((attr->prefix == NULL) &&
1522 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1523 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1524 xmlAttributePtr tst;
1525
1526 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1527 attr->elem, attr->name,
1528 attr->prefix);
1529 if ((tst == attr) || (tst == NULL)) {
1530 xmlChar fn[50];
1531 xmlChar *fulln;
1532
1533 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1534 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001535 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001536 return;
1537 }
1538
1539 /*
1540 * Check that the attribute is not declared in the
1541 * serialization
1542 */
1543 att = NULL;
1544 if (atts != NULL) {
1545 i = 0;
1546 att = atts[i];
1547 while (att != NULL) {
1548 if (xmlStrEqual(att, fulln))
1549 break;
1550 i += 2;
1551 att = atts[i];
1552 }
1553 }
1554 if (att == NULL) {
1555 xmlSAX2AttributeInternal(ctxt, fulln,
1556 attr->defaultValue, prefix);
1557 }
1558 if ((fulln != fn) && (fulln != attr->name))
1559 xmlFree(fulln);
1560 }
1561 }
1562 }
1563 attr = attr->nexth;
1564 }
1565 if (internal == 1) {
1566 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1567 name, prefix);
1568 internal = 0;
1569 goto process_external_subset;
1570 }
1571 }
1572}
1573
1574/**
1575 * xmlSAX2StartElement:
1576 * @ctx: the user data (XML parser context)
1577 * @fullname: The element name, including namespace prefix
1578 * @atts: An array of name/value attributes pairs, NULL terminated
1579 *
1580 * called when an opening tag has been processed.
1581 */
1582void
1583xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1584{
1585 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1586 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001587 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001588 xmlNsPtr ns;
1589 xmlChar *name;
1590 xmlChar *prefix;
1591 const xmlChar *att;
1592 const xmlChar *value;
1593 int i;
1594
Daniel Veillarda521d282004-11-09 14:59:59 +00001595 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001596 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001597#ifdef DEBUG_SAX
1598 xmlGenericError(xmlGenericErrorContext,
1599 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1600#endif
1601
1602 /*
1603 * First check on validity:
1604 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001605 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001606 ((ctxt->myDoc->intSubset == NULL) ||
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001607 ((ctxt->myDoc->intSubset->notations == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001608 (ctxt->myDoc->intSubset->elements == NULL) &&
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001609 (ctxt->myDoc->intSubset->attributes == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001610 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001611 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1612 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001613 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001614 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001615
Daniel Veillard1af9a412003-08-20 22:54:39 +00001616
1617 /*
1618 * Split the full name into a namespace prefix and the tag name
1619 */
1620 name = xmlSplitQName(ctxt, fullname, &prefix);
1621
1622
1623 /*
1624 * Note : the namespace resolution is deferred until the end of the
1625 * attributes parsing, since local namespace can be defined as
1626 * an attribute at this level.
1627 */
1628 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1629 if (ret == NULL) {
1630 if (prefix != NULL)
1631 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001632 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001633 return;
1634 }
1635 if (ctxt->myDoc->children == NULL) {
1636#ifdef DEBUG_SAX_TREE
1637 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1638#endif
1639 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1640 } else if (parent == NULL) {
1641 parent = ctxt->myDoc->children;
1642 }
1643 ctxt->nodemem = -1;
1644 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001645 if (ctxt->input != NULL) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001646 if (ctxt->input->line < USHRT_MAX)
1647 ret->line = (unsigned short) ctxt->input->line;
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001648 else
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001649 ret->line = USHRT_MAX;
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001650 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001651 }
1652
1653 /*
1654 * We are parsing a new node.
1655 */
1656#ifdef DEBUG_SAX_TREE
1657 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1658#endif
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001659 if (nodePush(ctxt, ret) < 0) {
1660 xmlUnlinkNode(ret);
1661 xmlFreeNode(ret);
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001662 if (prefix != NULL)
1663 xmlFree(prefix);
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001664 return;
1665 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001666
1667 /*
1668 * Link the child element
1669 */
1670 if (parent != NULL) {
1671 if (parent->type == XML_ELEMENT_NODE) {
1672#ifdef DEBUG_SAX_TREE
1673 xmlGenericError(xmlGenericErrorContext,
1674 "adding child %s to %s\n", name, parent->name);
1675#endif
1676 xmlAddChild(parent, ret);
1677 } else {
1678#ifdef DEBUG_SAX_TREE
1679 xmlGenericError(xmlGenericErrorContext,
1680 "adding sibling %s to ", name);
1681 xmlDebugDumpOneNode(stderr, parent, 0);
1682#endif
1683 xmlAddSibling(parent, ret);
1684 }
1685 }
1686
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001687 if (!ctxt->html) {
1688 /*
1689 * Insert all the defaulted attributes from the DTD especially
1690 * namespaces
1691 */
1692 if ((ctxt->myDoc->intSubset != NULL) ||
1693 (ctxt->myDoc->extSubset != NULL)) {
1694 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1695 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001696
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001697 /*
1698 * process all the attributes whose name start with "xmlns"
1699 */
1700 if (atts != NULL) {
1701 i = 0;
1702 att = atts[i++];
1703 value = atts[i++];
Daniel Veillard1af9a412003-08-20 22:54:39 +00001704 while ((att != NULL) && (value != NULL)) {
1705 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1706 (att[3] == 'n') && (att[4] == 's'))
1707 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1708
1709 att = atts[i++];
1710 value = atts[i++];
1711 }
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001712 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001713
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001714 /*
1715 * Search the namespace, note that since the attributes have been
1716 * processed, the local namespaces are available.
1717 */
1718 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1719 if ((ns == NULL) && (parent != NULL))
1720 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1721 if ((prefix != NULL) && (ns == NULL)) {
1722 ns = xmlNewNs(ret, NULL, prefix);
1723 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1724 "Namespace prefix %s is not defined\n",
1725 prefix, NULL);
1726 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001727
Haibo Huangcfd91dc2020-07-30 23:01:33 -07001728 /*
1729 * set the namespace node, making sure that if the default namespace
1730 * is unbound on a parent we simply keep it NULL
1731 */
1732 if ((ns != NULL) && (ns->href != NULL) &&
1733 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1734 xmlSetNs(ret, ns);
1735 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001736
1737 /*
1738 * process all the other attributes
1739 */
1740 if (atts != NULL) {
1741 i = 0;
1742 att = atts[i++];
1743 value = atts[i++];
1744 if (ctxt->html) {
1745 while (att != NULL) {
1746 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1747 att = atts[i++];
1748 value = atts[i++];
1749 }
1750 } else {
1751 while ((att != NULL) && (value != NULL)) {
1752 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1753 (att[3] != 'n') || (att[4] != 's'))
1754 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1755
1756 /*
1757 * Next ones
1758 */
1759 att = atts[i++];
1760 value = atts[i++];
1761 }
1762 }
1763 }
1764
Daniel Veillard4432df22003-09-28 18:58:27 +00001765#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001766 /*
1767 * If it's the Document root, finish the DTD validation and
1768 * check the document root element for validity
1769 */
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001770 if ((ctxt->validate) &&
1771 ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001772 int chk;
1773
1774 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1775 if (chk <= 0)
1776 ctxt->valid = 0;
1777 if (chk < 0)
1778 ctxt->wellFormed = 0;
1779 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001780 ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001781 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001782#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001783
1784 if (prefix != NULL)
1785 xmlFree(prefix);
1786
1787}
1788
1789/**
1790 * xmlSAX2EndElement:
1791 * @ctx: the user data (XML parser context)
1792 * @name: The element name
1793 *
1794 * called when the end of an element has been detected.
1795 */
1796void
1797xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1798{
1799 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001800 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001801
Daniel Veillard34099b42004-11-04 17:34:35 +00001802 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001803 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001804#ifdef DEBUG_SAX
1805 if (name == NULL)
1806 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1807 else
1808 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1809#endif
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001810
Daniel Veillard1af9a412003-08-20 22:54:39 +00001811 /* Capture end position and add node */
1812 if (cur != NULL && ctxt->record_info) {
Pavel Andrejs8ad4da52012-05-08 11:01:12 +08001813 ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
1814 ctxt->nodeInfo->end_line = ctxt->input->line;
1815 ctxt->nodeInfo->node = cur;
1816 xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001817 }
1818 ctxt->nodemem = -1;
1819
Daniel Veillard4432df22003-09-28 18:58:27 +00001820#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001821 if (ctxt->validate && ctxt->wellFormed &&
1822 ctxt->myDoc && ctxt->myDoc->intSubset)
1823 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1824 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001825#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001826
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001827
Daniel Veillard1af9a412003-08-20 22:54:39 +00001828 /*
1829 * end of parsing of this node.
1830 */
1831#ifdef DEBUG_SAX_TREE
1832 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1833#endif
1834 nodePop(ctxt);
1835}
Nicolas Le Cam77b5b462014-02-10 10:32:45 +08001836#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001837
Daniel Veillarde57ec792003-09-10 10:50:59 +00001838/*
Daniel Veillard19895052003-09-17 13:59:32 +00001839 * xmlSAX2TextNode:
1840 * @ctxt: the parser context
1841 * @str: the input string
1842 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001843 *
Daniel Veillard968a03a2012-08-13 12:41:33 +08001844 * Callback for a text node
Daniel Veillard19895052003-09-17 13:59:32 +00001845 *
1846 * Returns the newly allocated string or NULL if not needed or error
1847 */
1848static xmlNodePtr
1849xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1850 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001851 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001852
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001853 /*
1854 * Allocate
1855 */
Daniel Veillard19895052003-09-17 13:59:32 +00001856 if (ctxt->freeElems != NULL) {
1857 ret = ctxt->freeElems;
1858 ctxt->freeElems = ret->next;
1859 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001860 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001861 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001862 }
1863 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001864 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001865 return(NULL);
1866 }
Daniel Veillard8874b942005-08-25 13:19:21 +00001867 memset(ret, 0, sizeof(xmlNode));
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001868 /*
1869 * intern the formatting blanks found between tags, or the
1870 * very short strings
1871 */
1872 if (ctxt->dictNames) {
1873 xmlChar cur = str[len];
1874
Daniel Veillard8874b942005-08-25 13:19:21 +00001875 if ((len < (int) (2 * sizeof(void *))) &&
1876 (ctxt->options & XML_PARSE_COMPACT)) {
Daniel Veillard968a03a2012-08-13 12:41:33 +08001877 /* store the string in the node overriding properties and nsDef */
Daniel Veillard8874b942005-08-25 13:19:21 +00001878 xmlChar *tmp = (xmlChar *) &(ret->properties);
1879 memcpy(tmp, str, len);
1880 tmp[len] = 0;
1881 intern = tmp;
1882 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001883 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001884 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001885 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001886 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001887 int i;
1888
1889 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001890 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001891 }
1892 intern = xmlDictLookup(ctxt->dict, str, len);
1893 }
1894 }
1895skip:
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001896 ret->type = XML_TEXT_NODE;
1897
1898 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001899 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001900 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001901 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001902 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1903 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001904 return(NULL);
1905 }
1906 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001907 ret->content = (xmlChar *) intern;
1908
Daniel Veillard968a03a2012-08-13 12:41:33 +08001909 if (ctxt->linenumbers) {
1910 if (ctxt->input != NULL) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001911 if (ctxt->input->line < USHRT_MAX)
1912 ret->line = (unsigned short) ctxt->input->line;
Daniel Veillard968a03a2012-08-13 12:41:33 +08001913 else {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08001914 ret->line = USHRT_MAX;
Daniel Veillard968a03a2012-08-13 12:41:33 +08001915 if (ctxt->options & XML_PARSE_BIG_LINES)
Nick Wellnhoferd422b952017-10-09 13:37:42 +02001916 ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
Daniel Veillard968a03a2012-08-13 12:41:33 +08001917 }
1918 }
1919 }
Daniel Veillard45efd082008-07-07 13:52:52 +00001920
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001921 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1922 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001923 return(ret);
1924}
1925
Daniel Veillard4432df22003-09-28 18:58:27 +00001926#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001927/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001928 * xmlSAX2DecodeAttrEntities:
1929 * @ctxt: the parser context
1930 * @str: the input string
1931 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001932 *
Daniel Veillarde57ec792003-09-10 10:50:59 +00001933 * Remove the entities from an attribute value
1934 *
1935 * Returns the newly allocated string or NULL if not needed or error
1936 */
1937static xmlChar *
1938xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1939 const xmlChar *end) {
1940 const xmlChar *in;
1941 xmlChar *ret;
1942
1943 in = str;
1944 while (in < end)
1945 if (*in++ == '&')
1946 goto decode;
1947 return(NULL);
1948decode:
1949 ctxt->depth++;
1950 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1951 XML_SUBSTITUTE_REF, 0,0,0);
1952 ctxt->depth--;
1953 return(ret);
1954}
Daniel Veillard4432df22003-09-28 18:58:27 +00001955#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001956
1957/**
1958 * xmlSAX2AttributeNs:
1959 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001960 * @localname: the local name of the attribute
1961 * @prefix: the attribute namespace prefix if available
1962 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001963 * @value: Start of the attribute value
1964 * @valueend: end of the attribute value
1965 *
1966 * Handle an attribute that has been read by the parser.
1967 * The default handling is to convert the attribute into an
1968 * DOM subtree and past it in a new xmlAttr element added to
1969 * the element.
1970 */
1971static void
1972xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1973 const xmlChar * localname,
1974 const xmlChar * prefix,
1975 const xmlChar * value,
1976 const xmlChar * valueend)
1977{
1978 xmlAttrPtr ret;
1979 xmlNsPtr namespace = NULL;
1980 xmlChar *dup = NULL;
1981
Daniel Veillarde57ec792003-09-10 10:50:59 +00001982 /*
1983 * Note: if prefix == NULL, the attribute is not in the default namespace
1984 */
1985 if (prefix != NULL)
1986 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1987
Daniel Veillard8a44e592003-09-15 14:50:06 +00001988 /*
1989 * allocate the node
1990 */
1991 if (ctxt->freeAttrs != NULL) {
1992 ret = ctxt->freeAttrs;
1993 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001994 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001995 memset(ret, 0, sizeof(xmlAttr));
1996 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001997
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001998 ret->parent = ctxt->node;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001999 ret->doc = ctxt->myDoc;
2000 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002001
Daniel Veillard8a44e592003-09-15 14:50:06 +00002002 if (ctxt->dictNames)
2003 ret->name = localname;
2004 else
2005 ret->name = xmlStrdup(localname);
2006
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002007 /* link at the end to preserve order, TODO speed up with a last */
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002008 if (ctxt->node->properties == NULL) {
2009 ctxt->node->properties = ret;
2010 } else {
2011 xmlAttrPtr prev = ctxt->node->properties;
2012
2013 while (prev->next != NULL) prev = prev->next;
2014 prev->next = ret;
2015 ret->prev = prev;
2016 }
2017
Daniel Veillard8a44e592003-09-15 14:50:06 +00002018 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2019 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
2020 } else {
2021 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002022 ret = xmlNewNsPropEatName(ctxt->node, namespace,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002023 (xmlChar *) localname, NULL);
2024 else
2025 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
2026 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002027 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002028 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002029 }
2030 }
2031
Daniel Veillard8a44e592003-09-15 14:50:06 +00002032 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
2033 xmlNodePtr tmp;
2034
Daniel Veillard19895052003-09-17 13:59:32 +00002035 /*
2036 * We know that if there is an entity reference, then
2037 * the string has been dup'ed and terminates with 0
2038 * otherwise with ' or "
2039 */
2040 if (*valueend != 0) {
2041 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2042 ret->children = tmp;
2043 ret->last = tmp;
2044 if (tmp != NULL) {
2045 tmp->doc = ret->doc;
2046 tmp->parent = (xmlNodePtr) ret;
2047 }
2048 } else {
2049 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2050 valueend - value);
2051 tmp = ret->children;
2052 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00002053 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00002054 tmp->parent = (xmlNodePtr) ret;
2055 if (tmp->next == NULL)
2056 ret->last = tmp;
2057 tmp = tmp->next;
2058 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002059 }
2060 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002061 xmlNodePtr tmp;
2062
2063 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2064 ret->children = tmp;
2065 ret->last = tmp;
2066 if (tmp != NULL) {
2067 tmp->doc = ret->doc;
2068 tmp->parent = (xmlNodePtr) ret;
2069 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002070 }
2071
Daniel Veillard4432df22003-09-28 18:58:27 +00002072#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002073 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2074 ctxt->myDoc && ctxt->myDoc->intSubset) {
2075 /*
2076 * If we don't substitute entities, the validation should be
2077 * done on a value with replaced entities anyway.
2078 */
2079 if (!ctxt->replaceEntities) {
2080 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2081 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00002082 if (*valueend == 0) {
2083 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2084 ctxt->myDoc, ctxt->node, ret, value);
2085 } else {
2086 /*
2087 * That should already be normalized.
2088 * cheaper to finally allocate here than duplicate
2089 * entry points in the full validation code
2090 */
2091 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002092
Daniel Veillard62998c02003-09-15 12:56:36 +00002093 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2094 ctxt->myDoc, ctxt->node, ret, dup);
2095 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002096 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00002097 /*
2098 * dup now contains a string of the flattened attribute
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002099 * content with entities substituted. Check if we need to
Daniel Veillard62998c02003-09-15 12:56:36 +00002100 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002101 * It need to be done twice ... it's an extra burden related
2102 * to the ability to keep references in attributes
2103 */
Daniel Veillard62998c02003-09-15 12:56:36 +00002104 if (ctxt->attsSpecial != NULL) {
2105 xmlChar *nvalnorm;
2106 xmlChar fn[50];
2107 xmlChar *fullname;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002108
Daniel Veillard62998c02003-09-15 12:56:36 +00002109 fullname = xmlBuildQName(localname, prefix, fn, 50);
2110 if (fullname != NULL) {
2111 ctxt->vctxt.valid = 1;
2112 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2113 &ctxt->vctxt, ctxt->myDoc,
2114 ctxt->node, fullname, dup);
2115 if (ctxt->vctxt.valid != 1)
2116 ctxt->valid = 0;
2117
2118 if ((fullname != fn) && (fullname != localname))
2119 xmlFree(fullname);
2120 if (nvalnorm != NULL) {
2121 xmlFree(dup);
2122 dup = nvalnorm;
2123 }
2124 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002125 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002126
2127 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2128 ctxt->myDoc, ctxt->node, ret, dup);
2129 }
2130 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002131 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002132 * if entities already have been substituted, then
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002133 * the attribute as passed is already normalized
2134 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002135 dup = xmlStrndup(value, valueend - value);
2136
2137 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2138 ctxt->myDoc, ctxt->node, ret, dup);
2139 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002140 } else
2141#endif /* LIBXML_VALID_ENABLED */
2142 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002143 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002144 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
2145 /* Don't create IDs containing entity references */
2146 (ret->children != NULL) &&
2147 (ret->children->type == XML_TEXT_NODE) &&
2148 (ret->children->next == NULL)) {
2149 xmlChar *content = ret->children->content;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002150 /*
2151 * when validating, the ID registration is done at the attribute
2152 * validation level. Otherwise we have to do specific handling here.
2153 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002154 if ((prefix == ctxt->str_xml) &&
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002155 (localname[0] == 'i') && (localname[1] == 'd') &&
2156 (localname[2] == 0)) {
2157 /*
2158 * Add the xml:id value
2159 *
2160 * Open issue: normalization of the value.
2161 */
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002162#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
William M. Brack5ef2f812004-05-23 23:56:47 +00002163#ifdef LIBXML_VALID_ENABLED
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002164 if (xmlValidateNCName(content, 1) != 0) {
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002165 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2166 "xml:id : attribute value %s is not an NCName\n",
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002167 (const char *) content, NULL);
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002168 }
William M. Brack3f147372004-05-22 01:09:26 +00002169#endif
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002170#endif
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002171 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002172 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002173 xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002174 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002175 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002176 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002177 }
2178 if (dup != NULL)
2179 xmlFree(dup);
2180}
2181
2182/**
2183 * xmlSAX2StartElementNs:
2184 * @ctx: the user data (XML parser context)
2185 * @localname: the local name of the element
2186 * @prefix: the element namespace prefix if available
2187 * @URI: the element namespace name if available
2188 * @nb_namespaces: number of namespace definitions on that node
2189 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2190 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002191 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002192 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2193 * attribute values.
2194 *
2195 * SAX2 callback when an element start has been detected by the parser.
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002196 * It provides the namespace information for the element, as well as
Daniel Veillarde57ec792003-09-10 10:50:59 +00002197 * the new namespace declarations on the element.
2198 */
2199void
2200xmlSAX2StartElementNs(void *ctx,
2201 const xmlChar *localname,
2202 const xmlChar *prefix,
2203 const xmlChar *URI,
2204 int nb_namespaces,
2205 const xmlChar **namespaces,
2206 int nb_attributes,
2207 int nb_defaulted,
2208 const xmlChar **attributes)
2209{
2210 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2211 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002212 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002213 xmlNsPtr last = NULL, ns;
2214 const xmlChar *uri, *pref;
Daniel Veillard77b77b12012-01-26 19:11:02 +08002215 xmlChar *lname = NULL;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002216 int i, j;
2217
Daniel Veillard34099b42004-11-04 17:34:35 +00002218 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002219 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002220 /*
2221 * First check on validity:
2222 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002223 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002224 ((ctxt->myDoc->intSubset == NULL) ||
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002225 ((ctxt->myDoc->intSubset->notations == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002226 (ctxt->myDoc->intSubset->elements == NULL) &&
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002227 (ctxt->myDoc->intSubset->attributes == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002228 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillard6c91aa32012-10-25 15:33:59 +08002229 xmlErrValid(ctxt, XML_DTD_NO_DTD,
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002230 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002231 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002232 }
2233
Daniel Veillard8a44e592003-09-15 14:50:06 +00002234 /*
Daniel Veillard77b77b12012-01-26 19:11:02 +08002235 * Take care of the rare case of an undefined namespace prefix
2236 */
2237 if ((prefix != NULL) && (URI == NULL)) {
2238 if (ctxt->dictNames) {
2239 const xmlChar *fullname;
2240
2241 fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2242 if (fullname != NULL)
2243 localname = fullname;
2244 } else {
2245 lname = xmlBuildQName(localname, prefix, NULL, 0);
2246 }
2247 }
2248 /*
Daniel Veillard8a44e592003-09-15 14:50:06 +00002249 * allocate the node
2250 */
2251 if (ctxt->freeElems != NULL) {
2252 ret = ctxt->freeElems;
2253 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002254 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002255 memset(ret, 0, sizeof(xmlNode));
Elliott Hughes7fbecab2019-01-10 16:42:03 -08002256 ret->doc = ctxt->myDoc;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002257 ret->type = XML_ELEMENT_NODE;
2258
2259 if (ctxt->dictNames)
2260 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002261 else {
Daniel Veillard77b77b12012-01-26 19:11:02 +08002262 if (lname == NULL)
2263 ret->name = xmlStrdup(localname);
2264 else
2265 ret->name = lname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002266 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002267 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002268 return;
2269 }
2270 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002271 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2272 xmlRegisterNodeDefaultValue(ret);
2273 } else {
2274 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002275 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002276 (xmlChar *) localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002277 else if (lname == NULL)
Daniel Veillard8a44e592003-09-15 14:50:06 +00002278 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002279 else
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002280 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard77b77b12012-01-26 19:11:02 +08002281 (xmlChar *) lname, NULL);
Daniel Veillard8a44e592003-09-15 14:50:06 +00002282 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002283 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002284 return;
2285 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002286 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002287 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002288 if (ctxt->input != NULL) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002289 if (ctxt->input->line < USHRT_MAX)
2290 ret->line = (unsigned short) ctxt->input->line;
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002291 else
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002292 ret->line = USHRT_MAX;
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002293 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002294 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002295
Tim Elliott71a243d2012-01-17 19:25:08 -08002296 if (parent == NULL) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002297 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002298 }
2299 /*
2300 * Build the namespace list
2301 */
2302 for (i = 0,j = 0;j < nb_namespaces;j++) {
2303 pref = namespaces[i++];
2304 uri = namespaces[i++];
2305 ns = xmlNewNs(NULL, uri, pref);
2306 if (ns != NULL) {
2307 if (last == NULL) {
2308 ret->nsDef = last = ns;
2309 } else {
2310 last->next = ns;
2311 last = ns;
2312 }
2313 if ((URI != NULL) && (prefix == pref))
2314 ret->ns = ns;
2315 } else {
Daniel Veillardaa54d372010-09-09 18:17:47 +02002316 /*
2317 * any out of memory error would already have been raised
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +02002318 * but we can't be guaranteed it's the actual error due to the
Daniel Veillardaa54d372010-09-09 18:17:47 +02002319 * API, best is to skip in this case
2320 */
2321 continue;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002322 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002323#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002324 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2325 ctxt->myDoc && ctxt->myDoc->intSubset) {
2326 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2327 ret, prefix, ns, uri);
2328 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002329#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002330 }
2331 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002332
2333 /*
2334 * We are parsing a new node.
2335 */
Elliott Hughes7fbecab2019-01-10 16:42:03 -08002336 if (nodePush(ctxt, ret) < 0) {
2337 xmlUnlinkNode(ret);
2338 xmlFreeNode(ret);
2339 return;
2340 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002341
2342 /*
2343 * Link the child element
2344 */
2345 if (parent != NULL) {
2346 if (parent->type == XML_ELEMENT_NODE) {
2347 xmlAddChild(parent, ret);
2348 } else {
2349 xmlAddSibling(parent, ret);
2350 }
2351 }
2352
2353 /*
2354 * Insert the defaulted attributes from the DTD only if requested:
2355 */
2356 if ((nb_defaulted != 0) &&
2357 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2358 nb_attributes -= nb_defaulted;
2359
2360 /*
2361 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002362 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002363 */
2364 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002365 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002366 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2367 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2368 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002369 if (ret->ns == NULL) {
2370 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002371 if (ns == NULL) {
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002372
William M. Brack42331a92004-07-29 07:07:16 +00002373 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002374 return;
2375 }
Daniel Veillard74eaec12009-08-26 15:57:20 +02002376 if (prefix != NULL)
2377 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2378 "Namespace prefix %s was not found\n",
2379 prefix, NULL);
2380 else
2381 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2382 "Namespace default prefix was not found\n",
2383 NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002384 }
2385 }
2386
2387 /*
2388 * process all the other attributes
2389 */
2390 if (nb_attributes > 0) {
2391 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
Daniel Veillard1c989272012-01-26 19:43:06 +08002392 /*
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002393 * Handle the rare case of an undefined attribute prefix
Daniel Veillard1c989272012-01-26 19:43:06 +08002394 */
2395 if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2396 if (ctxt->dictNames) {
2397 const xmlChar *fullname;
2398
2399 fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2400 attributes[j]);
2401 if (fullname != NULL) {
2402 xmlSAX2AttributeNs(ctxt, fullname, NULL,
2403 attributes[j+3], attributes[j+4]);
2404 continue;
2405 }
2406 } else {
2407 lname = xmlBuildQName(attributes[j], attributes[j+1],
2408 NULL, 0);
2409 if (lname != NULL) {
2410 xmlSAX2AttributeNs(ctxt, lname, NULL,
2411 attributes[j+3], attributes[j+4]);
2412 xmlFree(lname);
2413 continue;
2414 }
2415 }
2416 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002417 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
Daniel Veillard1c989272012-01-26 19:43:06 +08002418 attributes[j+3], attributes[j+4]);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002419 }
2420 }
2421
Daniel Veillard4432df22003-09-28 18:58:27 +00002422#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002423 /*
2424 * If it's the Document root, finish the DTD validation and
2425 * check the document root element for validity
2426 */
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002427 if ((ctxt->validate) &&
2428 ((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002429 int chk;
2430
2431 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2432 if (chk <= 0)
2433 ctxt->valid = 0;
2434 if (chk < 0)
2435 ctxt->wellFormed = 0;
2436 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002437 ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002438 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002439#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002440}
2441
2442/**
2443 * xmlSAX2EndElementNs:
2444 * @ctx: the user data (XML parser context)
2445 * @localname: the local name of the element
2446 * @prefix: the element namespace prefix if available
2447 * @URI: the element namespace name if available
2448 *
2449 * SAX2 callback when an element end has been detected by the parser.
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002450 * It provides the namespace information for the element.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002451 */
2452void
2453xmlSAX2EndElementNs(void *ctx,
2454 const xmlChar * localname ATTRIBUTE_UNUSED,
2455 const xmlChar * prefix ATTRIBUTE_UNUSED,
2456 const xmlChar * URI ATTRIBUTE_UNUSED)
2457{
2458 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2459 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002460 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002461
Daniel Veillard34099b42004-11-04 17:34:35 +00002462 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002463 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002464 /* Capture end position and add node */
2465 if ((ctxt->record_info) && (cur != NULL)) {
2466 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2467 node_info.end_line = ctxt->input->line;
2468 node_info.node = cur;
2469 xmlParserAddNodeInfo(ctxt, &node_info);
2470 }
2471 ctxt->nodemem = -1;
2472
Daniel Veillard4432df22003-09-28 18:58:27 +00002473#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002474 if (ctxt->validate && ctxt->wellFormed &&
2475 ctxt->myDoc && ctxt->myDoc->intSubset)
2476 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002477#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002478
2479 /*
2480 * end of parsing of this node.
2481 */
2482 nodePop(ctxt);
2483}
2484
Daniel Veillard1af9a412003-08-20 22:54:39 +00002485/**
2486 * xmlSAX2Reference:
2487 * @ctx: the user data (XML parser context)
2488 * @name: The entity name
2489 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002490 * called when an entity xmlSAX2Reference is detected.
Daniel Veillard1af9a412003-08-20 22:54:39 +00002491 */
2492void
2493xmlSAX2Reference(void *ctx, const xmlChar *name)
2494{
2495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2496 xmlNodePtr ret;
2497
Daniel Veillard34099b42004-11-04 17:34:35 +00002498 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002499#ifdef DEBUG_SAX
2500 xmlGenericError(xmlGenericErrorContext,
2501 "SAX.xmlSAX2Reference(%s)\n", name);
2502#endif
2503 if (name[0] == '#')
2504 ret = xmlNewCharRef(ctxt->myDoc, name);
2505 else
2506 ret = xmlNewReference(ctxt->myDoc, name);
2507#ifdef DEBUG_SAX_TREE
2508 xmlGenericError(xmlGenericErrorContext,
2509 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2510#endif
Daniel Veillardb242b082008-02-08 09:56:31 +00002511 if (xmlAddChild(ctxt->node, ret) == NULL) {
2512 xmlFreeNode(ret);
2513 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002514}
2515
2516/**
Haibo Huang615b24a2021-02-05 01:38:09 -08002517 * xmlSAX2Text:
Daniel Veillard1af9a412003-08-20 22:54:39 +00002518 * @ctx: the user data (XML parser context)
2519 * @ch: a xmlChar string
2520 * @len: the number of xmlChar
Haibo Huang615b24a2021-02-05 01:38:09 -08002521 * @type: text or cdata
Daniel Veillard1af9a412003-08-20 22:54:39 +00002522 *
Haibo Huang615b24a2021-02-05 01:38:09 -08002523 * Append characters.
Daniel Veillard1af9a412003-08-20 22:54:39 +00002524 */
Haibo Huang615b24a2021-02-05 01:38:09 -08002525static void
2526xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
2527 xmlElementType type)
Daniel Veillard1af9a412003-08-20 22:54:39 +00002528{
Daniel Veillard1af9a412003-08-20 22:54:39 +00002529 xmlNodePtr lastChild;
2530
Haibo Huang615b24a2021-02-05 01:38:09 -08002531 if (ctxt == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002532#ifdef DEBUG_SAX
2533 xmlGenericError(xmlGenericErrorContext,
2534 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2535#endif
2536 /*
2537 * Handle the data if any. If there is no child
2538 * add it as content, otherwise if the last child is text,
2539 * concatenate it, else create a new node of type text.
2540 */
2541
2542 if (ctxt->node == NULL) {
2543#ifdef DEBUG_SAX_TREE
2544 xmlGenericError(xmlGenericErrorContext,
2545 "add chars: ctxt->node == NULL !\n");
2546#endif
2547 return;
2548 }
Daniel Veillard19895052003-09-17 13:59:32 +00002549 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002550#ifdef DEBUG_SAX_TREE
2551 xmlGenericError(xmlGenericErrorContext,
2552 "add chars to %s \n", ctxt->node->name);
2553#endif
2554
2555 /*
2556 * Here we needed an accelerator mechanism in case of very large
2557 * elements. Use an attribute in the structure !!!
2558 */
2559 if (lastChild == NULL) {
Haibo Huang615b24a2021-02-05 01:38:09 -08002560 if (type == XML_TEXT_NODE)
2561 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2562 else
2563 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
Daniel Veillard19895052003-09-17 13:59:32 +00002564 if (lastChild != NULL) {
2565 ctxt->node->children = lastChild;
2566 ctxt->node->last = lastChild;
2567 lastChild->parent = ctxt->node;
2568 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002569 ctxt->nodelen = len;
2570 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002571 } else {
2572 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2573 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002574 }
2575 } else {
2576 int coalesceText = (lastChild != NULL) &&
Haibo Huang615b24a2021-02-05 01:38:09 -08002577 (lastChild->type == type) &&
2578 ((type != XML_TEXT_NODE) ||
2579 (lastChild->name == xmlStringText));
Daniel Veillard1af9a412003-08-20 22:54:39 +00002580 if ((coalesceText) && (ctxt->nodemem != 0)) {
2581 /*
2582 * The whole point of maintaining nodelen and nodemem,
2583 * xmlTextConcat is too costly, i.e. compute length,
2584 * reallocate a new buffer, move data, append ch. Here
Haibo Huangcfd91dc2020-07-30 23:01:33 -07002585 * We try to minimize realloc() uses and avoid copying
Daniel Veillard1af9a412003-08-20 22:54:39 +00002586 * and recomputing length over and over.
2587 */
Daniel Veillard8874b942005-08-25 13:19:21 +00002588 if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2589 lastChild->content = xmlStrdup(lastChild->content);
2590 lastChild->properties = NULL;
2591 } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2592 (xmlDictOwns(ctxt->dict, lastChild->content))) {
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002593 lastChild->content = xmlStrdup(lastChild->content);
2594 }
Gaurav3e0eec42014-06-13 14:45:20 +08002595 if (lastChild->content == NULL) {
2596 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
Daniel Veillarda6ea72a2014-07-14 20:29:34 +08002597 return;
Gaurav3e0eec42014-06-13 14:45:20 +08002598 }
Daniel Veillard97ff9b32009-01-18 21:43:30 +00002599 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002600 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2601 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2602 return;
2603 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002604 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002605 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002606 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2607 return;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002608 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002609 if (ctxt->nodelen + len >= ctxt->nodemem) {
2610 xmlChar *newbuf;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002611 size_t size;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002612
2613 size = ctxt->nodemem + len;
2614 size *= 2;
2615 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2616 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002617 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002618 return;
2619 }
2620 ctxt->nodemem = size;
2621 lastChild->content = newbuf;
2622 }
2623 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2624 ctxt->nodelen += len;
2625 lastChild->content[ctxt->nodelen] = 0;
2626 } else if (coalesceText) {
2627 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002628 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002629 }
2630 if (ctxt->node->children != NULL) {
2631 ctxt->nodelen = xmlStrlen(lastChild->content);
2632 ctxt->nodemem = ctxt->nodelen + 1;
2633 }
2634 } else {
2635 /* Mixed content, first time */
Haibo Huang615b24a2021-02-05 01:38:09 -08002636 if (type == XML_TEXT_NODE)
2637 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2638 else
2639 lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
Daniel Veillard19895052003-09-17 13:59:32 +00002640 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002641 xmlAddChild(ctxt->node, lastChild);
2642 if (ctxt->node->children != NULL) {
2643 ctxt->nodelen = len;
2644 ctxt->nodemem = len + 1;
2645 }
2646 }
2647 }
2648 }
2649}
2650
2651/**
Haibo Huang615b24a2021-02-05 01:38:09 -08002652 * xmlSAX2Characters:
2653 * @ctx: the user data (XML parser context)
2654 * @ch: a xmlChar string
2655 * @len: the number of xmlChar
2656 *
2657 * receiving some chars from the parser.
2658 */
2659void
2660xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2661{
2662 xmlSAX2Text((xmlParserCtxtPtr) ctx, ch, len, XML_TEXT_NODE);
2663}
2664
2665/**
Daniel Veillard1af9a412003-08-20 22:54:39 +00002666 * xmlSAX2IgnorableWhitespace:
2667 * @ctx: the user data (XML parser context)
2668 * @ch: a xmlChar string
2669 * @len: the number of xmlChar
2670 *
2671 * receiving some ignorable whitespaces from the parser.
2672 * UNUSED: by default the DOM building will use xmlSAX2Characters
2673 */
2674void
2675xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2676{
2677 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2678#ifdef DEBUG_SAX
2679 xmlGenericError(xmlGenericErrorContext,
2680 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2681#endif
2682}
2683
2684/**
2685 * xmlSAX2ProcessingInstruction:
2686 * @ctx: the user data (XML parser context)
2687 * @target: the target name
2688 * @data: the PI data's
2689 *
2690 * A processing instruction has been parsed.
2691 */
2692void
2693xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2694 const xmlChar *data)
2695{
2696 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2697 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002698 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002699
Daniel Veillard34099b42004-11-04 17:34:35 +00002700 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002701 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002702#ifdef DEBUG_SAX
2703 xmlGenericError(xmlGenericErrorContext,
2704 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2705#endif
2706
Daniel Veillard03a53c32004-10-26 16:06:51 +00002707 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002708 if (ret == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002709
Daniel Veillard73da77e2005-08-24 14:05:37 +00002710 if (ctxt->linenumbers) {
2711 if (ctxt->input != NULL) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002712 if (ctxt->input->line < USHRT_MAX)
2713 ret->line = (unsigned short) ctxt->input->line;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002714 else
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002715 ret->line = USHRT_MAX;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002716 }
2717 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002718 if (ctxt->inSubset == 1) {
2719 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2720 return;
2721 } else if (ctxt->inSubset == 2) {
2722 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2723 return;
2724 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002725 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002726#ifdef DEBUG_SAX_TREE
2727 xmlGenericError(xmlGenericErrorContext,
2728 "Setting PI %s as root\n", target);
2729#endif
2730 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2731 return;
2732 }
2733 if (parent->type == XML_ELEMENT_NODE) {
2734#ifdef DEBUG_SAX_TREE
2735 xmlGenericError(xmlGenericErrorContext,
2736 "adding PI %s child to %s\n", target, parent->name);
2737#endif
2738 xmlAddChild(parent, ret);
2739 } else {
2740#ifdef DEBUG_SAX_TREE
2741 xmlGenericError(xmlGenericErrorContext,
2742 "adding PI %s sibling to ", target);
2743 xmlDebugDumpOneNode(stderr, parent, 0);
2744#endif
2745 xmlAddSibling(parent, ret);
2746 }
2747}
2748
2749/**
2750 * xmlSAX2Comment:
2751 * @ctx: the user data (XML parser context)
2752 * @value: the xmlSAX2Comment content
2753 *
2754 * A xmlSAX2Comment has been parsed.
2755 */
2756void
2757xmlSAX2Comment(void *ctx, const xmlChar *value)
2758{
2759 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2760 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002761 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002762
Daniel Veillard34099b42004-11-04 17:34:35 +00002763 if (ctx == NULL) return;
2764 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002765#ifdef DEBUG_SAX
2766 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2767#endif
2768 ret = xmlNewDocComment(ctxt->myDoc, value);
2769 if (ret == NULL) return;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002770 if (ctxt->linenumbers) {
2771 if (ctxt->input != NULL) {
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002772 if (ctxt->input->line < USHRT_MAX)
2773 ret->line = (unsigned short) ctxt->input->line;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002774 else
Elliott Hughesecdab2a2022-02-23 14:33:50 -08002775 ret->line = USHRT_MAX;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002776 }
2777 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002778
2779 if (ctxt->inSubset == 1) {
2780 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2781 return;
2782 } else if (ctxt->inSubset == 2) {
2783 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2784 return;
2785 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002786 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002787#ifdef DEBUG_SAX_TREE
2788 xmlGenericError(xmlGenericErrorContext,
2789 "Setting xmlSAX2Comment as root\n");
2790#endif
2791 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2792 return;
2793 }
2794 if (parent->type == XML_ELEMENT_NODE) {
2795#ifdef DEBUG_SAX_TREE
2796 xmlGenericError(xmlGenericErrorContext,
2797 "adding xmlSAX2Comment child to %s\n", parent->name);
2798#endif
2799 xmlAddChild(parent, ret);
2800 } else {
2801#ifdef DEBUG_SAX_TREE
2802 xmlGenericError(xmlGenericErrorContext,
2803 "adding xmlSAX2Comment sibling to ");
2804 xmlDebugDumpOneNode(stderr, parent, 0);
2805#endif
2806 xmlAddSibling(parent, ret);
2807 }
2808}
2809
2810/**
2811 * xmlSAX2CDataBlock:
2812 * @ctx: the user data (XML parser context)
2813 * @value: The pcdata content
2814 * @len: the block length
2815 *
2816 * called when a pcdata block has been parsed
2817 */
2818void
2819xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2820{
Haibo Huang615b24a2021-02-05 01:38:09 -08002821 xmlSAX2Text((xmlParserCtxtPtr) ctx, value, len, XML_CDATA_SECTION_NODE);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002822}
2823
Daniel Veillard62998c02003-09-15 12:56:36 +00002824static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002825
Daniel Veillard81273902003-09-30 00:43:48 +00002826#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002827/**
2828 * xmlSAXDefaultVersion:
2829 * @version: the version, 1 or 2
2830 *
2831 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002832 * By default, during initialization the default is set to 2.
2833 * Note that it is generally a better coding style to use
2834 * xmlSAXVersion() to set up the version explicitly for a given
2835 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002836 *
2837 * Returns the previous value in case of success and -1 in case of error.
2838 */
2839int
2840xmlSAXDefaultVersion(int version)
2841{
2842 int ret = xmlSAX2DefaultVersionValue;
2843
2844 if ((version != 1) && (version != 2))
2845 return(-1);
2846 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002847 return(ret);
2848}
Daniel Veillard81273902003-09-30 00:43:48 +00002849#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002850
2851/**
2852 * xmlSAXVersion:
2853 * @hdlr: the SAX handler
2854 * @version: the version, 1 or 2
2855 *
2856 * Initialize the default XML SAX handler according to the version
2857 *
2858 * Returns 0 in case of success and -1 in case of error.
2859 */
2860int
2861xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2862{
2863 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002864 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002865 hdlr->startElement = NULL;
2866 hdlr->endElement = NULL;
2867 hdlr->startElementNs = xmlSAX2StartElementNs;
2868 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002869 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002870 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002871#ifdef LIBXML_SAX1_ENABLED
2872 } else if (version == 1) {
2873 hdlr->startElement = xmlSAX2StartElement;
2874 hdlr->endElement = xmlSAX2EndElement;
2875 hdlr->initialized = 1;
2876#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002877 } else
2878 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002879 hdlr->internalSubset = xmlSAX2InternalSubset;
2880 hdlr->externalSubset = xmlSAX2ExternalSubset;
2881 hdlr->isStandalone = xmlSAX2IsStandalone;
2882 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2883 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2884 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2885 hdlr->getEntity = xmlSAX2GetEntity;
2886 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2887 hdlr->entityDecl = xmlSAX2EntityDecl;
2888 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2889 hdlr->elementDecl = xmlSAX2ElementDecl;
2890 hdlr->notationDecl = xmlSAX2NotationDecl;
2891 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2892 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2893 hdlr->startDocument = xmlSAX2StartDocument;
2894 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002895 hdlr->reference = xmlSAX2Reference;
2896 hdlr->characters = xmlSAX2Characters;
2897 hdlr->cdataBlock = xmlSAX2CDataBlock;
2898 hdlr->ignorableWhitespace = xmlSAX2Characters;
2899 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2900 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002901 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002902 hdlr->error = xmlParserError;
2903 hdlr->fatalError = xmlParserError;
2904
Daniel Veillarde57ec792003-09-10 10:50:59 +00002905 return(0);
2906}
2907
2908/**
2909 * xmlSAX2InitDefaultSAXHandler:
2910 * @hdlr: the SAX handler
2911 * @warning: flag if non-zero sets the handler warning procedure
2912 *
2913 * Initialize the default XML SAX2 handler
2914 */
2915void
2916xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2917{
2918 if ((hdlr == NULL) || (hdlr->initialized != 0))
2919 return;
2920
2921 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2922 if (warning == 0)
2923 hdlr->warning = NULL;
2924 else
2925 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002926}
2927
2928/**
2929 * xmlDefaultSAXHandlerInit:
2930 *
2931 * Initialize the default SAX2 handler
2932 */
2933void
2934xmlDefaultSAXHandlerInit(void)
2935{
Daniel Veillard81273902003-09-30 00:43:48 +00002936#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002937 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002938#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002939}
2940
2941#ifdef LIBXML_HTML_ENABLED
2942
2943/**
2944 * xmlSAX2InitHtmlDefaultSAXHandler:
2945 * @hdlr: the SAX handler
2946 *
2947 * Initialize the default HTML SAX2 handler
2948 */
2949void
2950xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2951{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002952 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002953 return;
2954
2955 hdlr->internalSubset = xmlSAX2InternalSubset;
2956 hdlr->externalSubset = NULL;
2957 hdlr->isStandalone = NULL;
2958 hdlr->hasInternalSubset = NULL;
2959 hdlr->hasExternalSubset = NULL;
2960 hdlr->resolveEntity = NULL;
2961 hdlr->getEntity = xmlSAX2GetEntity;
2962 hdlr->getParameterEntity = NULL;
2963 hdlr->entityDecl = NULL;
2964 hdlr->attributeDecl = NULL;
2965 hdlr->elementDecl = NULL;
2966 hdlr->notationDecl = NULL;
2967 hdlr->unparsedEntityDecl = NULL;
2968 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2969 hdlr->startDocument = xmlSAX2StartDocument;
2970 hdlr->endDocument = xmlSAX2EndDocument;
2971 hdlr->startElement = xmlSAX2StartElement;
2972 hdlr->endElement = xmlSAX2EndElement;
2973 hdlr->reference = NULL;
2974 hdlr->characters = xmlSAX2Characters;
2975 hdlr->cdataBlock = xmlSAX2CDataBlock;
2976 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002977 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002978 hdlr->comment = xmlSAX2Comment;
2979 hdlr->warning = xmlParserWarning;
2980 hdlr->error = xmlParserError;
2981 hdlr->fatalError = xmlParserError;
2982
Daniel Veillard092643b2003-09-25 14:29:29 +00002983 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002984}
2985
2986/**
2987 * htmlDefaultSAXHandlerInit:
2988 *
2989 * Initialize the default SAX handler
2990 */
2991void
2992htmlDefaultSAXHandlerInit(void)
2993{
Daniel Veillard092643b2003-09-25 14:29:29 +00002994 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002995}
2996
2997#endif /* LIBXML_HTML_ENABLED */
2998
2999#ifdef LIBXML_DOCB_ENABLED
3000
3001/**
3002 * xmlSAX2InitDocbDefaultSAXHandler:
3003 * @hdlr: the SAX handler
3004 *
3005 * Initialize the default DocBook SAX2 handler
3006 */
3007void
3008xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
3009{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00003010 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00003011 return;
3012
3013 hdlr->internalSubset = xmlSAX2InternalSubset;
3014 hdlr->externalSubset = NULL;
3015 hdlr->isStandalone = xmlSAX2IsStandalone;
3016 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
3017 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
3018 hdlr->resolveEntity = xmlSAX2ResolveEntity;
3019 hdlr->getEntity = xmlSAX2GetEntity;
3020 hdlr->getParameterEntity = NULL;
3021 hdlr->entityDecl = xmlSAX2EntityDecl;
3022 hdlr->attributeDecl = NULL;
3023 hdlr->elementDecl = NULL;
3024 hdlr->notationDecl = NULL;
3025 hdlr->unparsedEntityDecl = NULL;
3026 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
3027 hdlr->startDocument = xmlSAX2StartDocument;
3028 hdlr->endDocument = xmlSAX2EndDocument;
3029 hdlr->startElement = xmlSAX2StartElement;
3030 hdlr->endElement = xmlSAX2EndElement;
3031 hdlr->reference = xmlSAX2Reference;
3032 hdlr->characters = xmlSAX2Characters;
3033 hdlr->cdataBlock = NULL;
3034 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
3035 hdlr->processingInstruction = NULL;
3036 hdlr->comment = xmlSAX2Comment;
3037 hdlr->warning = xmlParserWarning;
3038 hdlr->error = xmlParserError;
3039 hdlr->fatalError = xmlParserError;
3040
Daniel Veillardffbbed42003-10-10 14:46:54 +00003041 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00003042}
3043
3044/**
3045 * docbDefaultSAXHandlerInit:
3046 *
3047 * Initialize the default SAX handler
3048 */
3049void
3050docbDefaultSAXHandlerInit(void)
3051{
Daniel Veillard092643b2003-09-25 14:29:29 +00003052 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00003053}
3054
3055#endif /* LIBXML_DOCB_ENABLED */