• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * xmlreader.c: implements the xmlTextReader streaming node API
3  *
4  * NOTE:
5  *   XmlTextReader.Normalization Property won't be supported, since
6  *     it makes the parser non compliant to the XML recommendation
7  *
8  * See Copyright for the status of this software.
9  *
10  * daniel@veillard.com
11  */
12 
13 /*
14  * TODOs:
15  *   - XML Schemas validation
16  */
17 #define IN_LIBXML
18 #include "libxml.h"
19 
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
23 
24 #ifdef HAVE_CTYPE_H
25 #include <ctype.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 
31 #include <libxml/xmlmemory.h>
32 #include <libxml/xmlIO.h>
33 #include <libxml/xmlreader.h>
34 #include <libxml/parserInternals.h>
35 #ifdef LIBXML_SCHEMAS_ENABLED
36 #include <libxml/relaxng.h>
37 #include <libxml/xmlschemas.h>
38 #endif
39 #include <libxml/uri.h>
40 #ifdef LIBXML_XINCLUDE_ENABLED
41 #include <libxml/xinclude.h>
42 #endif
43 #ifdef LIBXML_PATTERN_ENABLED
44 #include <libxml/pattern.h>
45 #endif
46 
47 #include "buf.h"
48 
49 #define MAX_ERR_MSG_SIZE 64000
50 
51 /*
52  * The following VA_COPY was coded following an example in
53  * the Samba project.  It may not be sufficient for some
54  * esoteric implementations of va_list but (hopefully) will
55  * be sufficient for libxml2.
56  */
57 #ifndef VA_COPY
58   #ifdef HAVE_VA_COPY
59     #define VA_COPY(dest, src) va_copy(dest, src)
60   #else
61     #ifdef HAVE___VA_COPY
62       #define VA_COPY(dest,src) __va_copy(dest, src)
63     #else
64       #ifndef VA_LIST_IS_ARRAY
65         #define VA_COPY(dest,src) (dest) = (src)
66       #else
67         #include <string.h>
68         #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
69       #endif
70     #endif
71   #endif
72 #endif
73 
74 /* #define DEBUG_CALLBACKS */
75 /* #define DEBUG_READER */
76 
77 /**
78  * TODO:
79  *
80  * macro to flag unimplemented blocks
81  */
82 #define TODO								\
83     xmlGenericError(xmlGenericErrorContext,				\
84 	    "Unimplemented block at %s:%d\n",				\
85             __FILE__, __LINE__);
86 
87 #ifdef DEBUG_READER
88 #define DUMP_READER xmlTextReaderDebug(reader);
89 #else
90 #define DUMP_READER
91 #endif
92 
93 #define CHUNK_SIZE 512
94 /************************************************************************
95  *									*
96  *	The parser: maps the Text Reader API on top of the existing	*
97  *		parsing routines building a tree			*
98  *									*
99  ************************************************************************/
100 
101 #define XML_TEXTREADER_INPUT	1
102 #define XML_TEXTREADER_CTXT	2
103 
104 typedef enum {
105     XML_TEXTREADER_NONE = -1,
106     XML_TEXTREADER_START= 0,
107     XML_TEXTREADER_ELEMENT= 1,
108     XML_TEXTREADER_END= 2,
109     XML_TEXTREADER_EMPTY= 3,
110     XML_TEXTREADER_BACKTRACK= 4,
111     XML_TEXTREADER_DONE= 5,
112     XML_TEXTREADER_ERROR= 6
113 } xmlTextReaderState;
114 
115 typedef enum {
116     XML_TEXTREADER_NOT_VALIDATE = 0,
117     XML_TEXTREADER_VALIDATE_DTD = 1,
118     XML_TEXTREADER_VALIDATE_RNG = 2,
119     XML_TEXTREADER_VALIDATE_XSD = 4
120 } xmlTextReaderValidate;
121 
122 struct _xmlTextReader {
123     int				mode;	/* the parsing mode */
124     xmlDocPtr			doc;    /* when walking an existing doc */
125     xmlTextReaderValidate       validate;/* is there any validation */
126     int				allocs;	/* what structure were deallocated */
127     xmlTextReaderState		state;
128     xmlParserCtxtPtr		ctxt;	/* the parser context */
129     xmlSAXHandlerPtr		sax;	/* the parser SAX callbacks */
130     xmlParserInputBufferPtr	input;	/* the input */
131     startElementSAXFunc		startElement;/* initial SAX callbacks */
132     endElementSAXFunc		endElement;  /* idem */
133     startElementNsSAX2Func	startElementNs;/* idem */
134     endElementNsSAX2Func	endElementNs;  /* idem */
135     charactersSAXFunc		characters;
136     cdataBlockSAXFunc		cdataBlock;
137     unsigned int		base;	/* base of the segment in the input */
138     unsigned int		cur;	/* current position in the input */
139     xmlNodePtr			node;	/* current node */
140     xmlNodePtr			curnode;/* current attribute node */
141     int				depth;  /* depth of the current node */
142     xmlNodePtr			faketext;/* fake xmlNs chld */
143     int				preserve;/* preserve the resulting document */
144     xmlBufPtr		        buffer; /* used to return const xmlChar * */
145     xmlDictPtr			dict;	/* the context dictionary */
146 
147     /* entity stack when traversing entities content */
148     xmlNodePtr         ent;          /* Current Entity Ref Node */
149     int                entNr;        /* Depth of the entities stack */
150     int                entMax;       /* Max depth of the entities stack */
151     xmlNodePtr        *entTab;       /* array of entities */
152 
153     /* error handling */
154     xmlTextReaderErrorFunc errorFunc;    /* callback function */
155     void                  *errorFuncArg; /* callback function user argument */
156 
157 #ifdef LIBXML_SCHEMAS_ENABLED
158     /* Handling of RelaxNG validation */
159     xmlRelaxNGPtr          rngSchemas;	/* The Relax NG schemas */
160     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
161     int                    rngPreserveCtxt; /* 1 if the context was provided by the user */
162     int                    rngValidErrors;/* The number of errors detected */
163     xmlNodePtr             rngFullNode;	/* the node if RNG not progressive */
164     /* Handling of Schemas validation */
165     xmlSchemaPtr          xsdSchemas;	/* The Schemas schemas */
166     xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
167     int                   xsdPreserveCtxt; /* 1 if the context was provided by the user */
168     int                   xsdValidErrors;/* The number of errors detected */
169     xmlSchemaSAXPlugPtr   xsdPlug;	/* the schemas plug in SAX pipeline */
170 #endif
171 #ifdef LIBXML_XINCLUDE_ENABLED
172     /* Handling of XInclude processing */
173     int                xinclude;	/* is xinclude asked for */
174     const xmlChar *    xinclude_name;	/* the xinclude name from dict */
175     xmlXIncludeCtxtPtr xincctxt;	/* the xinclude context */
176     int                in_xinclude;	/* counts for xinclude */
177 #endif
178 #ifdef LIBXML_PATTERN_ENABLED
179     int                patternNr;       /* number of preserve patterns */
180     int                patternMax;      /* max preserve patterns */
181     xmlPatternPtr     *patternTab;      /* array of preserve patterns */
182 #endif
183     int                preserves;	/* level of preserves */
184     int                parserFlags;	/* the set of options set */
185     /* Structured error handling */
186     xmlStructuredErrorFunc sErrorFunc;  /* callback function */
187 };
188 
189 #define NODE_IS_EMPTY		0x1
190 #define NODE_IS_PRESERVED	0x2
191 #define NODE_IS_SPRESERVED	0x4
192 
193 /**
194  * CONSTSTR:
195  *
196  * Macro used to return an interned string
197  */
198 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
199 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
200 
201 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
202 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
203 
204 /************************************************************************
205  *									*
206  *	Our own version of the freeing routines as we recycle nodes	*
207  *									*
208  ************************************************************************/
209 /**
210  * DICT_FREE:
211  * @str:  a string
212  *
213  * Free a string if it is not owned by the "dict" dictionary in the
214  * current scope
215  */
216 #define DICT_FREE(str)						\
217 	if ((str) && ((!dict) ||				\
218 	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
219 	    xmlFree((char *)(str));
220 
221 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
222 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
223 
224 /**
225  * xmlFreeID:
226  * @not:  A id
227  *
228  * Deallocate the memory used by an id definition
229  */
230 static void
xmlFreeID(xmlIDPtr id)231 xmlFreeID(xmlIDPtr id) {
232     xmlDictPtr dict = NULL;
233 
234     if (id == NULL) return;
235 
236     if (id->doc != NULL)
237         dict = id->doc->dict;
238 
239     if (id->value != NULL)
240 	DICT_FREE(id->value)
241     xmlFree(id);
242 }
243 
244 /**
245  * xmlTextReaderRemoveID:
246  * @doc:  the document
247  * @attr:  the attribute
248  *
249  * Remove the given attribute from the ID table maintained internally.
250  *
251  * Returns -1 if the lookup failed and 0 otherwise
252  */
253 static int
xmlTextReaderRemoveID(xmlDocPtr doc,xmlAttrPtr attr)254 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
255     xmlIDTablePtr table;
256     xmlIDPtr id;
257     xmlChar *ID;
258 
259     if (doc == NULL) return(-1);
260     if (attr == NULL) return(-1);
261     table = (xmlIDTablePtr) doc->ids;
262     if (table == NULL)
263         return(-1);
264 
265     ID = xmlNodeListGetString(doc, attr->children, 1);
266     if (ID == NULL)
267 	return(-1);
268     id = xmlHashLookup(table, ID);
269     xmlFree(ID);
270     if (id == NULL || id->attr != attr) {
271 	return(-1);
272     }
273     id->name = attr->name;
274     id->attr = NULL;
275     return(0);
276 }
277 
278 /**
279  * xmlTextReaderFreeProp:
280  * @reader:  the xmlTextReaderPtr used
281  * @cur:  the node
282  *
283  * Free a node.
284  */
285 static void
xmlTextReaderFreeProp(xmlTextReaderPtr reader,xmlAttrPtr cur)286 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
287     xmlDictPtr dict;
288 
289     if ((reader != NULL) && (reader->ctxt != NULL))
290 	dict = reader->ctxt->dict;
291     else
292         dict = NULL;
293     if (cur == NULL) return;
294 
295     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
296 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
297 
298     /* Check for ID removal -> leading to invalid references ! */
299     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
300 	((cur->parent->doc->intSubset != NULL) ||
301 	 (cur->parent->doc->extSubset != NULL))) {
302         if (xmlIsID(cur->parent->doc, cur->parent, cur))
303 	    xmlTextReaderRemoveID(cur->parent->doc, cur);
304     }
305     if (cur->children != NULL)
306         xmlTextReaderFreeNodeList(reader, cur->children);
307 
308     DICT_FREE(cur->name);
309     if ((reader != NULL) && (reader->ctxt != NULL) &&
310         (reader->ctxt->freeAttrsNr < 100)) {
311         cur->next = reader->ctxt->freeAttrs;
312 	reader->ctxt->freeAttrs = cur;
313 	reader->ctxt->freeAttrsNr++;
314     } else {
315 	xmlFree(cur);
316     }
317 }
318 
319 /**
320  * xmlTextReaderFreePropList:
321  * @reader:  the xmlTextReaderPtr used
322  * @cur:  the first property in the list
323  *
324  * Free a property and all its siblings, all the children are freed too.
325  */
326 static void
xmlTextReaderFreePropList(xmlTextReaderPtr reader,xmlAttrPtr cur)327 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
328     xmlAttrPtr next;
329 
330     while (cur != NULL) {
331         next = cur->next;
332         xmlTextReaderFreeProp(reader, cur);
333 	cur = next;
334     }
335 }
336 
337 /**
338  * xmlTextReaderFreeNodeList:
339  * @reader:  the xmlTextReaderPtr used
340  * @cur:  the first node in the list
341  *
342  * Free a node and all its siblings, this is a recursive behaviour, all
343  * the children are freed too.
344  */
345 static void
xmlTextReaderFreeNodeList(xmlTextReaderPtr reader,xmlNodePtr cur)346 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
347     xmlNodePtr next;
348     xmlDictPtr dict;
349 
350     if ((reader != NULL) && (reader->ctxt != NULL))
351 	dict = reader->ctxt->dict;
352     else
353         dict = NULL;
354     if (cur == NULL) return;
355     if (cur->type == XML_NAMESPACE_DECL) {
356 	xmlFreeNsList((xmlNsPtr) cur);
357 	return;
358     }
359     if ((cur->type == XML_DOCUMENT_NODE) ||
360 	(cur->type == XML_HTML_DOCUMENT_NODE)) {
361 	xmlFreeDoc((xmlDocPtr) cur);
362 	return;
363     }
364     while (cur != NULL) {
365         next = cur->next;
366 	/* unroll to speed up freeing the document */
367 	if (cur->type != XML_DTD_NODE) {
368 
369 	    if ((cur->children != NULL) &&
370 		(cur->type != XML_ENTITY_REF_NODE)) {
371 		if (cur->children->parent == cur)
372 		    xmlTextReaderFreeNodeList(reader, cur->children);
373 		cur->children = NULL;
374 	    }
375 
376 	    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
377 		xmlDeregisterNodeDefaultValue(cur);
378 
379 	    if (((cur->type == XML_ELEMENT_NODE) ||
380 		 (cur->type == XML_XINCLUDE_START) ||
381 		 (cur->type == XML_XINCLUDE_END)) &&
382 		(cur->properties != NULL))
383 		xmlTextReaderFreePropList(reader, cur->properties);
384 	    if ((cur->content != (xmlChar *) &(cur->properties)) &&
385 	        (cur->type != XML_ELEMENT_NODE) &&
386 		(cur->type != XML_XINCLUDE_START) &&
387 		(cur->type != XML_XINCLUDE_END) &&
388 		(cur->type != XML_ENTITY_REF_NODE)) {
389 		DICT_FREE(cur->content);
390 	    }
391 	    if (((cur->type == XML_ELEMENT_NODE) ||
392 	         (cur->type == XML_XINCLUDE_START) ||
393 		 (cur->type == XML_XINCLUDE_END)) &&
394 		(cur->nsDef != NULL))
395 		xmlFreeNsList(cur->nsDef);
396 
397 	    /*
398 	     * we don't free element names here they are interned now
399 	     */
400 	    if ((cur->type != XML_TEXT_NODE) &&
401 		(cur->type != XML_COMMENT_NODE))
402 		DICT_FREE(cur->name);
403 	    if (((cur->type == XML_ELEMENT_NODE) ||
404 		 (cur->type == XML_TEXT_NODE)) &&
405 	        (reader != NULL) && (reader->ctxt != NULL) &&
406 		(reader->ctxt->freeElemsNr < 100)) {
407 	        cur->next = reader->ctxt->freeElems;
408 		reader->ctxt->freeElems = cur;
409 		reader->ctxt->freeElemsNr++;
410 	    } else {
411 		xmlFree(cur);
412 	    }
413 	}
414 	cur = next;
415     }
416 }
417 
418 /**
419  * xmlTextReaderFreeNode:
420  * @reader:  the xmlTextReaderPtr used
421  * @cur:  the node
422  *
423  * Free a node, this is a recursive behaviour, all the children are freed too.
424  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
425  */
426 static void
xmlTextReaderFreeNode(xmlTextReaderPtr reader,xmlNodePtr cur)427 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
428     xmlDictPtr dict;
429 
430     if ((reader != NULL) && (reader->ctxt != NULL))
431 	dict = reader->ctxt->dict;
432     else
433         dict = NULL;
434     if (cur->type == XML_DTD_NODE) {
435 	xmlFreeDtd((xmlDtdPtr) cur);
436 	return;
437     }
438     if (cur->type == XML_NAMESPACE_DECL) {
439 	xmlFreeNs((xmlNsPtr) cur);
440         return;
441     }
442     if (cur->type == XML_ATTRIBUTE_NODE) {
443 	xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
444 	return;
445     }
446 
447     if ((cur->children != NULL) &&
448 	(cur->type != XML_ENTITY_REF_NODE)) {
449 	if (cur->children->parent == cur)
450 	    xmlTextReaderFreeNodeList(reader, cur->children);
451 	cur->children = NULL;
452     }
453 
454     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
455 	xmlDeregisterNodeDefaultValue(cur);
456 
457     if (((cur->type == XML_ELEMENT_NODE) ||
458 	 (cur->type == XML_XINCLUDE_START) ||
459 	 (cur->type == XML_XINCLUDE_END)) &&
460 	(cur->properties != NULL))
461 	xmlTextReaderFreePropList(reader, cur->properties);
462     if ((cur->content != (xmlChar *) &(cur->properties)) &&
463         (cur->type != XML_ELEMENT_NODE) &&
464 	(cur->type != XML_XINCLUDE_START) &&
465 	(cur->type != XML_XINCLUDE_END) &&
466 	(cur->type != XML_ENTITY_REF_NODE)) {
467 	DICT_FREE(cur->content);
468     }
469     if (((cur->type == XML_ELEMENT_NODE) ||
470 	 (cur->type == XML_XINCLUDE_START) ||
471 	 (cur->type == XML_XINCLUDE_END)) &&
472 	(cur->nsDef != NULL))
473 	xmlFreeNsList(cur->nsDef);
474 
475     /*
476      * we don't free names here they are interned now
477      */
478     if ((cur->type != XML_TEXT_NODE) &&
479         (cur->type != XML_COMMENT_NODE))
480 	DICT_FREE(cur->name);
481 
482     if (((cur->type == XML_ELEMENT_NODE) ||
483 	 (cur->type == XML_TEXT_NODE)) &&
484 	(reader != NULL) && (reader->ctxt != NULL) &&
485 	(reader->ctxt->freeElemsNr < 100)) {
486 	cur->next = reader->ctxt->freeElems;
487 	reader->ctxt->freeElems = cur;
488 	reader->ctxt->freeElemsNr++;
489     } else {
490 	xmlFree(cur);
491     }
492 }
493 
494 static void
xmlTextReaderFreeIDTableEntry(void * id,const xmlChar * name ATTRIBUTE_UNUSED)495 xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
496     xmlFreeID((xmlIDPtr) id);
497 }
498 
499 /**
500  * xmlTextReaderFreeIDTable:
501  * @table:  An id table
502  *
503  * Deallocate the memory used by an ID hash table.
504  */
505 static void
xmlTextReaderFreeIDTable(xmlIDTablePtr table)506 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
507     xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
508 }
509 
510 /**
511  * xmlTextReaderFreeDoc:
512  * @reader:  the xmlTextReaderPtr used
513  * @cur:  pointer to the document
514  *
515  * Free up all the structures used by a document, tree included.
516  */
517 static void
xmlTextReaderFreeDoc(xmlTextReaderPtr reader,xmlDocPtr cur)518 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
519     xmlDtdPtr extSubset, intSubset;
520 
521     if (cur == NULL) return;
522 
523     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
524 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
525 
526     /*
527      * Do this before freeing the children list to avoid ID lookups
528      */
529     if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
530     cur->ids = NULL;
531     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
532     cur->refs = NULL;
533     extSubset = cur->extSubset;
534     intSubset = cur->intSubset;
535     if (intSubset == extSubset)
536 	extSubset = NULL;
537     if (extSubset != NULL) {
538 	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
539 	cur->extSubset = NULL;
540 	xmlFreeDtd(extSubset);
541     }
542     if (intSubset != NULL) {
543 	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
544 	cur->intSubset = NULL;
545 	xmlFreeDtd(intSubset);
546     }
547 
548     if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
549 
550     if (cur->version != NULL) xmlFree((char *) cur->version);
551     if (cur->name != NULL) xmlFree((char *) cur->name);
552     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
553     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
554     if (cur->URL != NULL) xmlFree((char *) cur->URL);
555     if (cur->dict != NULL) xmlDictFree(cur->dict);
556 
557     xmlFree(cur);
558 }
559 
560 /************************************************************************
561  *									*
562  *			The reader core parser				*
563  *									*
564  ************************************************************************/
565 #ifdef DEBUG_READER
566 static void
xmlTextReaderDebug(xmlTextReaderPtr reader)567 xmlTextReaderDebug(xmlTextReaderPtr reader) {
568     if ((reader == NULL) || (reader->ctxt == NULL)) {
569 	fprintf(stderr, "xmlTextReader NULL\n");
570 	return;
571     }
572     fprintf(stderr, "xmlTextReader: state %d depth %d ",
573 	    reader->state, reader->depth);
574     if (reader->node == NULL) {
575 	fprintf(stderr, "node = NULL\n");
576     } else {
577 	fprintf(stderr, "node %s\n", reader->node->name);
578     }
579     fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
580 	    reader->base, reader->cur, reader->ctxt->nodeNr);
581     if (reader->input->buffer == NULL) {
582 	fprintf(stderr, "buffer is NULL\n");
583     } else {
584 #ifdef LIBXML_DEBUG_ENABLED
585 	xmlDebugDumpString(stderr,
586 		&reader->input->buffer->content[reader->cur]);
587 #endif
588 	fprintf(stderr, "\n");
589     }
590 }
591 #endif
592 
593 /**
594  * xmlTextReaderEntPush:
595  * @reader:  the xmlTextReaderPtr used
596  * @value:  the entity reference node
597  *
598  * Pushes a new entity reference node on top of the entities stack
599  *
600  * Returns 0 in case of error, the index in the stack otherwise
601  */
602 static int
xmlTextReaderEntPush(xmlTextReaderPtr reader,xmlNodePtr value)603 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
604 {
605     if (reader->entMax <= 0) {
606 	reader->entMax = 10;
607 	reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
608 		                                  sizeof(reader->entTab[0]));
609         if (reader->entTab == NULL) {
610             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
611             return (0);
612         }
613     }
614     if (reader->entNr >= reader->entMax) {
615         reader->entMax *= 2;
616         reader->entTab =
617             (xmlNodePtr *) xmlRealloc(reader->entTab,
618                                       reader->entMax *
619                                       sizeof(reader->entTab[0]));
620         if (reader->entTab == NULL) {
621             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
622             return (0);
623         }
624     }
625     reader->entTab[reader->entNr] = value;
626     reader->ent = value;
627     return (reader->entNr++);
628 }
629 
630 /**
631  * xmlTextReaderEntPop:
632  * @reader:  the xmlTextReaderPtr used
633  *
634  * Pops the top element entity from the entities stack
635  *
636  * Returns the entity just removed
637  */
638 static xmlNodePtr
xmlTextReaderEntPop(xmlTextReaderPtr reader)639 xmlTextReaderEntPop(xmlTextReaderPtr reader)
640 {
641     xmlNodePtr ret;
642 
643     if (reader->entNr <= 0)
644         return (NULL);
645     reader->entNr--;
646     if (reader->entNr > 0)
647         reader->ent = reader->entTab[reader->entNr - 1];
648     else
649         reader->ent = NULL;
650     ret = reader->entTab[reader->entNr];
651     reader->entTab[reader->entNr] = NULL;
652     return (ret);
653 }
654 
655 /**
656  * xmlTextReaderStartElement:
657  * @ctx: the user data (XML parser context)
658  * @fullname:  The element name, including namespace prefix
659  * @atts:  An array of name/value attributes pairs, NULL terminated
660  *
661  * called when an opening tag has been processed.
662  */
663 static void
xmlTextReaderStartElement(void * ctx,const xmlChar * fullname,const xmlChar ** atts)664 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
665 	                  const xmlChar **atts) {
666     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
667     xmlTextReaderPtr reader = ctxt->_private;
668 
669 #ifdef DEBUG_CALLBACKS
670     printf("xmlTextReaderStartElement(%s)\n", fullname);
671 #endif
672     if ((reader != NULL) && (reader->startElement != NULL)) {
673 	reader->startElement(ctx, fullname, atts);
674 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
675 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
676 	    (ctxt->input->cur[1] == '>'))
677 	    ctxt->node->extra = NODE_IS_EMPTY;
678     }
679     if (reader != NULL)
680 	reader->state = XML_TEXTREADER_ELEMENT;
681 }
682 
683 /**
684  * xmlTextReaderEndElement:
685  * @ctx: the user data (XML parser context)
686  * @fullname:  The element name, including namespace prefix
687  *
688  * called when an ending tag has been processed.
689  */
690 static void
xmlTextReaderEndElement(void * ctx,const xmlChar * fullname)691 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
692     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
693     xmlTextReaderPtr reader = ctxt->_private;
694 
695 #ifdef DEBUG_CALLBACKS
696     printf("xmlTextReaderEndElement(%s)\n", fullname);
697 #endif
698     if ((reader != NULL) && (reader->endElement != NULL)) {
699 	reader->endElement(ctx, fullname);
700     }
701 }
702 
703 /**
704  * xmlTextReaderStartElementNs:
705  * @ctx: the user data (XML parser context)
706  * @localname:  the local name of the element
707  * @prefix:  the element namespace prefix if available
708  * @URI:  the element namespace name if available
709  * @nb_namespaces:  number of namespace definitions on that node
710  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
711  * @nb_attributes:  the number of attributes on that node
712  * nb_defaulted:  the number of defaulted attributes.
713  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
714  *               attribute values.
715  *
716  * called when an opening tag has been processed.
717  */
718 static void
xmlTextReaderStartElementNs(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted,const xmlChar ** attributes)719 xmlTextReaderStartElementNs(void *ctx,
720                       const xmlChar *localname,
721 		      const xmlChar *prefix,
722 		      const xmlChar *URI,
723 		      int nb_namespaces,
724 		      const xmlChar **namespaces,
725 		      int nb_attributes,
726 		      int nb_defaulted,
727 		      const xmlChar **attributes)
728 {
729     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
730     xmlTextReaderPtr reader = ctxt->_private;
731 
732 #ifdef DEBUG_CALLBACKS
733     printf("xmlTextReaderStartElementNs(%s)\n", localname);
734 #endif
735     if ((reader != NULL) && (reader->startElementNs != NULL)) {
736 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
737 	                       namespaces, nb_attributes, nb_defaulted,
738 			       attributes);
739 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
740 	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
741 	    (ctxt->input->cur[1] == '>'))
742 	    ctxt->node->extra = NODE_IS_EMPTY;
743     }
744     if (reader != NULL)
745 	reader->state = XML_TEXTREADER_ELEMENT;
746 }
747 
748 /**
749  * xmlTextReaderEndElementNs:
750  * @ctx: the user data (XML parser context)
751  * @localname:  the local name of the element
752  * @prefix:  the element namespace prefix if available
753  * @URI:  the element namespace name if available
754  *
755  * called when an ending tag has been processed.
756  */
757 static void
xmlTextReaderEndElementNs(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)758 xmlTextReaderEndElementNs(void *ctx,
759                           const xmlChar * localname,
760                           const xmlChar * prefix,
761 		          const xmlChar * URI)
762 {
763     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
764     xmlTextReaderPtr reader = ctxt->_private;
765 
766 #ifdef DEBUG_CALLBACKS
767     printf("xmlTextReaderEndElementNs(%s)\n", localname);
768 #endif
769     if ((reader != NULL) && (reader->endElementNs != NULL)) {
770 	reader->endElementNs(ctx, localname, prefix, URI);
771     }
772 }
773 
774 
775 /**
776  * xmlTextReaderCharacters:
777  * @ctx: the user data (XML parser context)
778  * @ch:  a xmlChar string
779  * @len: the number of xmlChar
780  *
781  * receiving some chars from the parser.
782  */
783 static void
xmlTextReaderCharacters(void * ctx,const xmlChar * ch,int len)784 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
785 {
786     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
787     xmlTextReaderPtr reader = ctxt->_private;
788 
789 #ifdef DEBUG_CALLBACKS
790     printf("xmlTextReaderCharacters()\n");
791 #endif
792     if ((reader != NULL) && (reader->characters != NULL)) {
793 	reader->characters(ctx, ch, len);
794     }
795 }
796 
797 /**
798  * xmlTextReaderCDataBlock:
799  * @ctx: the user data (XML parser context)
800  * @value:  The pcdata content
801  * @len:  the block length
802  *
803  * called when a pcdata block has been parsed
804  */
805 static void
xmlTextReaderCDataBlock(void * ctx,const xmlChar * ch,int len)806 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
807 {
808     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
809     xmlTextReaderPtr reader = ctxt->_private;
810 
811 #ifdef DEBUG_CALLBACKS
812     printf("xmlTextReaderCDataBlock()\n");
813 #endif
814     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
815 	reader->cdataBlock(ctx, ch, len);
816     }
817 }
818 
819 /**
820  * xmlTextReaderPushData:
821  * @reader:  the xmlTextReaderPtr used
822  *
823  * Push data down the progressive parser until a significant callback
824  * got raised.
825  *
826  * Returns -1 in case of failure, 0 otherwise
827  */
828 static int
xmlTextReaderPushData(xmlTextReaderPtr reader)829 xmlTextReaderPushData(xmlTextReaderPtr reader) {
830     xmlBufPtr inbuf;
831     int val, s;
832     xmlTextReaderState oldstate;
833     int alloc;
834 
835     if ((reader->input == NULL) || (reader->input->buffer == NULL))
836 	return(-1);
837 
838     oldstate = reader->state;
839     reader->state = XML_TEXTREADER_NONE;
840     inbuf = reader->input->buffer;
841     alloc = xmlBufGetAllocationScheme(inbuf);
842 
843     while (reader->state == XML_TEXTREADER_NONE) {
844 	if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
845 	    /*
846 	     * Refill the buffer unless we are at the end of the stream
847 	     */
848 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
849 		val = xmlParserInputBufferRead(reader->input, 4096);
850 		if ((val == 0) &&
851 		    (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
852 		    if (xmlBufUse(inbuf) == reader->cur) {
853 			reader->mode = XML_TEXTREADER_MODE_EOF;
854 			reader->state = oldstate;
855 		    }
856 		} else if (val < 0) {
857 		    reader->mode = XML_TEXTREADER_MODE_EOF;
858 		    reader->state = oldstate;
859 		    if ((oldstate != XML_TEXTREADER_START) ||
860 			(reader->ctxt->myDoc != NULL))
861 			return(val);
862 		} else if (val == 0) {
863 		    /* mark the end of the stream and process the remains */
864 		    reader->mode = XML_TEXTREADER_MODE_EOF;
865 		    break;
866 		}
867 
868 	    } else
869 		break;
870 	}
871 	/*
872 	 * parse by block of CHUNK_SIZE bytes, various tests show that
873 	 * it's the best tradeoff at least on a 1.2GH Duron
874 	 */
875 	if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
876 	    val = xmlParseChunk(reader->ctxt,
877                  (const char *) xmlBufContent(inbuf) + reader->cur,
878                                 CHUNK_SIZE, 0);
879 	    reader->cur += CHUNK_SIZE;
880 	    if (val != 0)
881 		reader->ctxt->wellFormed = 0;
882 	    if (reader->ctxt->wellFormed == 0)
883 		break;
884 	} else {
885 	    s = xmlBufUse(inbuf) - reader->cur;
886 	    val = xmlParseChunk(reader->ctxt,
887 		 (const char *) xmlBufContent(inbuf) + reader->cur,
888 			        s, 0);
889 	    reader->cur += s;
890 	    if (val != 0)
891 		reader->ctxt->wellFormed = 0;
892 	    break;
893 	}
894     }
895 
896     /*
897      * Discard the consumed input when needed and possible
898      */
899     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
900         if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
901 	    if ((reader->cur >= 4096) &&
902 		(xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
903 		val = xmlBufShrink(inbuf, reader->cur);
904 		if (val >= 0) {
905 		    reader->cur -= val;
906 		}
907 	    }
908 	}
909     }
910 
911     /*
912      * At the end of the stream signal that the work is done to the Push
913      * parser.
914      */
915     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
916 	if (reader->state != XML_TEXTREADER_DONE) {
917 	    s = xmlBufUse(inbuf) - reader->cur;
918 	    val = xmlParseChunk(reader->ctxt,
919 		 (const char *) xmlBufContent(inbuf) + reader->cur,
920 			        s, 1);
921 	    reader->cur = xmlBufUse(inbuf);
922 	    reader->state  = XML_TEXTREADER_DONE;
923 	    if (val != 0) {
924 	        if (reader->ctxt->wellFormed)
925 		    reader->ctxt->wellFormed = 0;
926 		else
927 		    return(-1);
928 	    }
929 	}
930     }
931     reader->state = oldstate;
932     if (reader->ctxt->wellFormed == 0) {
933 	reader->mode = XML_TEXTREADER_MODE_EOF;
934         return(-1);
935     }
936 
937     return(0);
938 }
939 
940 #ifdef LIBXML_REGEXP_ENABLED
941 /**
942  * xmlTextReaderValidatePush:
943  * @reader:  the xmlTextReaderPtr used
944  *
945  * Push the current node for validation
946  */
947 static void
xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)948 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
949     xmlNodePtr node = reader->node;
950 
951 #ifdef LIBXML_VALID_ENABLED
952     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
953         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
954 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
955 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
956 				    reader->ctxt->myDoc, node, node->name);
957 	} else {
958 	    /* TODO use the BuildQName interface */
959 	    xmlChar *qname;
960 
961 	    qname = xmlStrdup(node->ns->prefix);
962 	    qname = xmlStrcat(qname, BAD_CAST ":");
963 	    qname = xmlStrcat(qname, node->name);
964 	    reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
965 				    reader->ctxt->myDoc, node, qname);
966 	    if (qname != NULL)
967 		xmlFree(qname);
968 	}
969     }
970 #endif /* LIBXML_VALID_ENABLED */
971 #ifdef LIBXML_SCHEMAS_ENABLED
972     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
973                (reader->rngValidCtxt != NULL)) {
974 	int ret;
975 
976 	if (reader->rngFullNode != NULL) return;
977 	ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
978 	                                    reader->ctxt->myDoc,
979 					    node);
980 	if (ret == 0) {
981 	    /*
982 	     * this element requires a full tree
983 	     */
984 	    node = xmlTextReaderExpand(reader);
985 	    if (node == NULL) {
986 printf("Expand failed !\n");
987 	        ret = -1;
988 	    } else {
989 		ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
990 						    reader->ctxt->myDoc,
991 						    node);
992 		reader->rngFullNode = node;
993 	    }
994 	}
995 	if (ret != 1)
996 	    reader->rngValidErrors++;
997     }
998 #endif
999 }
1000 
1001 /**
1002  * xmlTextReaderValidateCData:
1003  * @reader:  the xmlTextReaderPtr used
1004  * @data:  pointer to the CData
1005  * @len:  length of the CData block in bytes.
1006  *
1007  * Push some CData for validation
1008  */
1009 static void
xmlTextReaderValidateCData(xmlTextReaderPtr reader,const xmlChar * data,int len)1010 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
1011                            const xmlChar *data, int len) {
1012 #ifdef LIBXML_VALID_ENABLED
1013     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1014         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1015 	reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1016 	                                            data, len);
1017     }
1018 #endif /* LIBXML_VALID_ENABLED */
1019 #ifdef LIBXML_SCHEMAS_ENABLED
1020     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1021                (reader->rngValidCtxt != NULL)) {
1022 	int ret;
1023 
1024 	if (reader->rngFullNode != NULL) return;
1025 	ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1026 	if (ret != 1)
1027 	    reader->rngValidErrors++;
1028     }
1029 #endif
1030 }
1031 
1032 /**
1033  * xmlTextReaderValidatePop:
1034  * @reader:  the xmlTextReaderPtr used
1035  *
1036  * Pop the current node from validation
1037  */
1038 static void
xmlTextReaderValidatePop(xmlTextReaderPtr reader)1039 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1040     xmlNodePtr node = reader->node;
1041 
1042 #ifdef LIBXML_VALID_ENABLED
1043     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1044         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1045 	if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1046 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1047 				    reader->ctxt->myDoc, node, node->name);
1048 	} else {
1049 	    /* TODO use the BuildQName interface */
1050 	    xmlChar *qname;
1051 
1052 	    qname = xmlStrdup(node->ns->prefix);
1053 	    qname = xmlStrcat(qname, BAD_CAST ":");
1054 	    qname = xmlStrcat(qname, node->name);
1055 	    reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1056 				    reader->ctxt->myDoc, node, qname);
1057 	    if (qname != NULL)
1058 		xmlFree(qname);
1059 	}
1060     }
1061 #endif /* LIBXML_VALID_ENABLED */
1062 #ifdef LIBXML_SCHEMAS_ENABLED
1063     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1064                (reader->rngValidCtxt != NULL)) {
1065 	int ret;
1066 
1067 	if (reader->rngFullNode != NULL) {
1068 	    if (node == reader->rngFullNode)
1069 	        reader->rngFullNode = NULL;
1070 	    return;
1071 	}
1072 	ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1073 	                                   reader->ctxt->myDoc,
1074 					   node);
1075 	if (ret != 1)
1076 	    reader->rngValidErrors++;
1077     }
1078 #endif
1079 }
1080 
1081 /**
1082  * xmlTextReaderValidateEntity:
1083  * @reader:  the xmlTextReaderPtr used
1084  *
1085  * Handle the validation when an entity reference is encountered and
1086  * entity substitution is not activated. As a result the parser interface
1087  * must walk through the entity and do the validation calls
1088  */
1089 static void
xmlTextReaderValidateEntity(xmlTextReaderPtr reader)1090 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1091     xmlNodePtr oldnode = reader->node;
1092     xmlNodePtr node = reader->node;
1093     xmlParserCtxtPtr ctxt = reader->ctxt;
1094 
1095     do {
1096 	if (node->type == XML_ENTITY_REF_NODE) {
1097 	    /*
1098 	     * Case where the underlying tree is not availble, lookup the entity
1099 	     * and walk it.
1100 	     */
1101 	    if ((node->children == NULL) && (ctxt->sax != NULL) &&
1102 		(ctxt->sax->getEntity != NULL)) {
1103 		node->children = (xmlNodePtr)
1104 		    ctxt->sax->getEntity(ctxt, node->name);
1105 	    }
1106 
1107 	    if ((node->children != NULL) &&
1108 		(node->children->type == XML_ENTITY_DECL) &&
1109 		(node->children->children != NULL)) {
1110 		xmlTextReaderEntPush(reader, node);
1111 		node = node->children->children;
1112 		continue;
1113 	    } else {
1114 		/*
1115 		 * The error has probably be raised already.
1116 		 */
1117 		if (node == oldnode)
1118 		    break;
1119 		node = node->next;
1120 	    }
1121 #ifdef LIBXML_REGEXP_ENABLED
1122 	} else if (node->type == XML_ELEMENT_NODE) {
1123 	    reader->node = node;
1124 	    xmlTextReaderValidatePush(reader);
1125 	} else if ((node->type == XML_TEXT_NODE) ||
1126 		   (node->type == XML_CDATA_SECTION_NODE)) {
1127             xmlTextReaderValidateCData(reader, node->content,
1128 	                               xmlStrlen(node->content));
1129 #endif
1130 	}
1131 
1132 	/*
1133 	 * go to next node
1134 	 */
1135 	if (node->children != NULL) {
1136 	    node = node->children;
1137 	    continue;
1138 	} else if (node->type == XML_ELEMENT_NODE) {
1139 	    xmlTextReaderValidatePop(reader);
1140 	}
1141 	if (node->next != NULL) {
1142 	    node = node->next;
1143 	    continue;
1144 	}
1145 	do {
1146 	    node = node->parent;
1147 	    if (node->type == XML_ELEMENT_NODE) {
1148 	        xmlNodePtr tmp;
1149 		if (reader->entNr == 0) {
1150 		    while ((tmp = node->last) != NULL) {
1151 			if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1152 			    xmlUnlinkNode(tmp);
1153 			    xmlTextReaderFreeNode(reader, tmp);
1154 			} else
1155 			    break;
1156 		    }
1157 		}
1158 		reader->node = node;
1159 		xmlTextReaderValidatePop(reader);
1160 	    }
1161 	    if ((node->type == XML_ENTITY_DECL) &&
1162 		(reader->ent != NULL) && (reader->ent->children == node)) {
1163 		node = xmlTextReaderEntPop(reader);
1164 	    }
1165 	    if (node == oldnode)
1166 		break;
1167 	    if (node->next != NULL) {
1168 		node = node->next;
1169 		break;
1170 	    }
1171 	} while ((node != NULL) && (node != oldnode));
1172     } while ((node != NULL) && (node != oldnode));
1173     reader->node = oldnode;
1174 }
1175 #endif /* LIBXML_REGEXP_ENABLED */
1176 
1177 
1178 /**
1179  * xmlTextReaderGetSuccessor:
1180  * @cur:  the current node
1181  *
1182  * Get the successor of a node if available.
1183  *
1184  * Returns the successor node or NULL
1185  */
1186 static xmlNodePtr
xmlTextReaderGetSuccessor(xmlNodePtr cur)1187 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1188     if (cur == NULL) return(NULL) ; /* ERROR */
1189     if (cur->next != NULL) return(cur->next) ;
1190     do {
1191         cur = cur->parent;
1192         if (cur == NULL) break;
1193         if (cur->next != NULL) return(cur->next);
1194     } while (cur != NULL);
1195     return(cur);
1196 }
1197 
1198 /**
1199  * xmlTextReaderDoExpand:
1200  * @reader:  the xmlTextReaderPtr used
1201  *
1202  * Makes sure that the current node is fully read as well as all its
1203  * descendant. It means the full DOM subtree must be available at the
1204  * end of the call.
1205  *
1206  * Returns 1 if the node was expanded successfully, 0 if there is no more
1207  *          nodes to read, or -1 in case of error
1208  */
1209 static int
xmlTextReaderDoExpand(xmlTextReaderPtr reader)1210 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1211     int val;
1212 
1213     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1214         return(-1);
1215     do {
1216 	if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1217 
1218         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1219 	    return(1);
1220 	if (reader->ctxt->nodeNr < reader->depth)
1221 	    return(1);
1222 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
1223 	    return(1);
1224 	val = xmlTextReaderPushData(reader);
1225 	if (val < 0){
1226 	    reader->mode = XML_TEXTREADER_MODE_ERROR;
1227 	    return(-1);
1228 	}
1229     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1230     return(1);
1231 }
1232 
1233 /**
1234  * xmlTextReaderCollectSiblings:
1235  * @node:    the first child
1236  *
1237  *  Traverse depth-first through all sibling nodes and their children
1238  *  nodes and concatenate their content. This is an auxiliary function
1239  *  to xmlTextReaderReadString.
1240  *
1241  *  Returns a string containing the content, or NULL in case of error.
1242  */
1243 static xmlChar *
xmlTextReaderCollectSiblings(xmlNodePtr node)1244 xmlTextReaderCollectSiblings(xmlNodePtr node)
1245 {
1246     xmlBufferPtr buffer;
1247     xmlChar *ret;
1248 
1249     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1250         return(NULL);
1251 
1252     buffer = xmlBufferCreate();
1253     if (buffer == NULL)
1254        return NULL;
1255 
1256     for ( ; node != NULL; node = node->next) {
1257        switch (node->type) {
1258        case XML_TEXT_NODE:
1259        case XML_CDATA_SECTION_NODE:
1260            xmlBufferCat(buffer, node->content);
1261            break;
1262        case XML_ELEMENT_NODE: {
1263            xmlChar *tmp;
1264 
1265 	   tmp = xmlTextReaderCollectSiblings(node->children);
1266            xmlBufferCat(buffer, tmp);
1267 	   xmlFree(tmp);
1268 	   break;
1269        }
1270        default:
1271            break;
1272        }
1273     }
1274     ret = buffer->content;
1275     buffer->content = NULL;
1276     xmlBufferFree(buffer);
1277     return(ret);
1278 }
1279 
1280 /**
1281  * xmlTextReaderRead:
1282  * @reader:  the xmlTextReaderPtr used
1283  *
1284  *  Moves the position of the current instance to the next node in
1285  *  the stream, exposing its properties.
1286  *
1287  *  Returns 1 if the node was read successfully, 0 if there is no more
1288  *          nodes to read, or -1 in case of error
1289  */
1290 int
xmlTextReaderRead(xmlTextReaderPtr reader)1291 xmlTextReaderRead(xmlTextReaderPtr reader) {
1292     int val, olddepth = 0;
1293     xmlTextReaderState oldstate = XML_TEXTREADER_START;
1294     xmlNodePtr oldnode = NULL;
1295 
1296 
1297     if (reader == NULL)
1298 	return(-1);
1299     reader->curnode = NULL;
1300     if (reader->doc != NULL)
1301         return(xmlTextReaderReadTree(reader));
1302     if (reader->ctxt == NULL)
1303 	return(-1);
1304 
1305 #ifdef DEBUG_READER
1306     fprintf(stderr, "\nREAD ");
1307     DUMP_READER
1308 #endif
1309     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1310 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1311 	/*
1312 	 * Initial state
1313 	 */
1314 	do {
1315 	    val = xmlTextReaderPushData(reader);
1316 		if (val < 0){
1317 			reader->mode = XML_TEXTREADER_MODE_ERROR;
1318 			reader->state = XML_TEXTREADER_ERROR;
1319 		return(-1);
1320 		}
1321 	} while ((reader->ctxt->node == NULL) &&
1322 		 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1323 		  (reader->state != XML_TEXTREADER_DONE)));
1324 	if (reader->ctxt->node == NULL) {
1325 	    if (reader->ctxt->myDoc != NULL) {
1326 		reader->node = reader->ctxt->myDoc->children;
1327 	    }
1328 	    if (reader->node == NULL){
1329 			reader->mode = XML_TEXTREADER_MODE_ERROR;
1330 			reader->state = XML_TEXTREADER_ERROR;
1331 		return(-1);
1332 		}
1333 	    reader->state = XML_TEXTREADER_ELEMENT;
1334 	} else {
1335 	    if (reader->ctxt->myDoc != NULL) {
1336 		reader->node = reader->ctxt->myDoc->children;
1337 	    }
1338 	    if (reader->node == NULL)
1339 		reader->node = reader->ctxt->nodeTab[0];
1340 	    reader->state = XML_TEXTREADER_ELEMENT;
1341 	}
1342 	reader->depth = 0;
1343 	reader->ctxt->parseMode = XML_PARSE_READER;
1344 	goto node_found;
1345     }
1346     oldstate = reader->state;
1347     olddepth = reader->ctxt->nodeNr;
1348     oldnode = reader->node;
1349 
1350 get_next_node:
1351     if (reader->node == NULL) {
1352 	if (reader->mode == XML_TEXTREADER_MODE_EOF)
1353 	    return(0);
1354 	else
1355 	    return(-1);
1356     }
1357 
1358     /*
1359      * If we are not backtracking on ancestors or examined nodes,
1360      * that the parser didn't finished or that we arent at the end
1361      * of stream, continue processing.
1362      */
1363     while ((reader->node != NULL) && (reader->node->next == NULL) &&
1364 	   (reader->ctxt->nodeNr == olddepth) &&
1365            ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1366             (reader->node->children == NULL) ||
1367 	    (reader->node->type == XML_ENTITY_REF_NODE) ||
1368 	    ((reader->node->children != NULL) &&
1369 	     (reader->node->children->type == XML_TEXT_NODE) &&
1370 	     (reader->node->children->next == NULL)) ||
1371 	    (reader->node->type == XML_DTD_NODE) ||
1372 	    (reader->node->type == XML_DOCUMENT_NODE) ||
1373 	    (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1374 	   ((reader->ctxt->node == NULL) ||
1375 	    (reader->ctxt->node == reader->node) ||
1376 	    (reader->ctxt->node == reader->node->parent)) &&
1377 	   (reader->ctxt->instate != XML_PARSER_EOF)) {
1378 	val = xmlTextReaderPushData(reader);
1379 	if (val < 0){
1380 		reader->mode = XML_TEXTREADER_MODE_ERROR;
1381 		reader->state = XML_TEXTREADER_ERROR;
1382 	    return(-1);
1383 	}
1384 	if (reader->node == NULL)
1385 	    goto node_end;
1386     }
1387     if (oldstate != XML_TEXTREADER_BACKTRACK) {
1388 	if ((reader->node->children != NULL) &&
1389 	    (reader->node->type != XML_ENTITY_REF_NODE) &&
1390 	    (reader->node->type != XML_XINCLUDE_START) &&
1391 	    (reader->node->type != XML_DTD_NODE)) {
1392 	    reader->node = reader->node->children;
1393 	    reader->depth++;
1394 	    reader->state = XML_TEXTREADER_ELEMENT;
1395 	    goto node_found;
1396 	}
1397     }
1398     if (reader->node->next != NULL) {
1399 	if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1400             (reader->node->type == XML_ELEMENT_NODE) &&
1401 	    (reader->node->children == NULL) &&
1402 	    ((reader->node->extra & NODE_IS_EMPTY) == 0)
1403 #ifdef LIBXML_XINCLUDE_ENABLED
1404 	    && (reader->in_xinclude <= 0)
1405 #endif
1406 	    ) {
1407 	    reader->state = XML_TEXTREADER_END;
1408 	    goto node_found;
1409 	}
1410 #ifdef LIBXML_REGEXP_ENABLED
1411 	if ((reader->validate) &&
1412 	    (reader->node->type == XML_ELEMENT_NODE))
1413 	    xmlTextReaderValidatePop(reader);
1414 #endif /* LIBXML_REGEXP_ENABLED */
1415         if ((reader->preserves > 0) &&
1416 	    (reader->node->extra & NODE_IS_SPRESERVED))
1417 	    reader->preserves--;
1418 	reader->node = reader->node->next;
1419 	reader->state = XML_TEXTREADER_ELEMENT;
1420 
1421 	/*
1422 	 * Cleanup of the old node
1423 	 */
1424 	if ((reader->preserves == 0) &&
1425 #ifdef LIBXML_XINCLUDE_ENABLED
1426 	    (reader->in_xinclude == 0) &&
1427 #endif
1428 	    (reader->entNr == 0) &&
1429 	    (reader->node->prev != NULL) &&
1430             (reader->node->prev->type != XML_DTD_NODE)) {
1431 	    xmlNodePtr tmp = reader->node->prev;
1432 	    if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1433 		xmlUnlinkNode(tmp);
1434 		xmlTextReaderFreeNode(reader, tmp);
1435 	    }
1436 	}
1437 
1438 	goto node_found;
1439     }
1440     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1441 	(reader->node->type == XML_ELEMENT_NODE) &&
1442 	(reader->node->children == NULL) &&
1443 	((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1444 	reader->state = XML_TEXTREADER_END;
1445 	goto node_found;
1446     }
1447 #ifdef LIBXML_REGEXP_ENABLED
1448     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1449 	xmlTextReaderValidatePop(reader);
1450 #endif /* LIBXML_REGEXP_ENABLED */
1451     if ((reader->preserves > 0) &&
1452 	(reader->node->extra & NODE_IS_SPRESERVED))
1453 	reader->preserves--;
1454     reader->node = reader->node->parent;
1455     if ((reader->node == NULL) ||
1456 	(reader->node->type == XML_DOCUMENT_NODE) ||
1457 #ifdef LIBXML_DOCB_ENABLED
1458 	(reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1459 #endif
1460 	(reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1461 	if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1462 	    val = xmlParseChunk(reader->ctxt, "", 0, 1);
1463 	    reader->state = XML_TEXTREADER_DONE;
1464 	    if (val != 0)
1465 	        return(-1);
1466 	}
1467 	reader->node = NULL;
1468 	reader->depth = -1;
1469 
1470 	/*
1471 	 * Cleanup of the old node
1472 	 */
1473 	if ((oldnode != NULL) && (reader->preserves == 0) &&
1474 #ifdef LIBXML_XINCLUDE_ENABLED
1475 	    (reader->in_xinclude == 0) &&
1476 #endif
1477 	    (reader->entNr == 0) &&
1478 	    (oldnode->type != XML_DTD_NODE) &&
1479 	    ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1480 	    xmlUnlinkNode(oldnode);
1481 	    xmlTextReaderFreeNode(reader, oldnode);
1482 	}
1483 
1484 	goto node_end;
1485     }
1486     if ((reader->preserves == 0) &&
1487 #ifdef LIBXML_XINCLUDE_ENABLED
1488         (reader->in_xinclude == 0) &&
1489 #endif
1490 	(reader->entNr == 0) &&
1491         (reader->node->last != NULL) &&
1492         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1493 	xmlNodePtr tmp = reader->node->last;
1494 	xmlUnlinkNode(tmp);
1495 	xmlTextReaderFreeNode(reader, tmp);
1496     }
1497     reader->depth--;
1498     reader->state = XML_TEXTREADER_BACKTRACK;
1499 
1500 node_found:
1501     DUMP_READER
1502 
1503     /*
1504      * If we are in the middle of a piece of CDATA make sure it's finished
1505      */
1506     if ((reader->node != NULL) &&
1507         (reader->node->next == NULL) &&
1508         ((reader->node->type == XML_TEXT_NODE) ||
1509 	 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1510             if (xmlTextReaderExpand(reader) == NULL)
1511 	        return -1;
1512     }
1513 
1514 #ifdef LIBXML_XINCLUDE_ENABLED
1515     /*
1516      * Handle XInclude if asked for
1517      */
1518     if ((reader->xinclude) && (reader->node != NULL) &&
1519 	(reader->node->type == XML_ELEMENT_NODE) &&
1520 	(reader->node->ns != NULL) &&
1521 	((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1522 	 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1523 	if (reader->xincctxt == NULL) {
1524 	    reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1525 	    xmlXIncludeSetFlags(reader->xincctxt,
1526 	                        reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1527 	}
1528 	/*
1529 	 * expand that node and process it
1530 	 */
1531 	if (xmlTextReaderExpand(reader) == NULL)
1532 	    return -1;
1533 	xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1534     }
1535     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1536         reader->in_xinclude++;
1537 	goto get_next_node;
1538     }
1539     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1540         reader->in_xinclude--;
1541 	goto get_next_node;
1542     }
1543 #endif
1544     /*
1545      * Handle entities enter and exit when in entity replacement mode
1546      */
1547     if ((reader->node != NULL) &&
1548 	(reader->node->type == XML_ENTITY_REF_NODE) &&
1549 	(reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1550 	/*
1551 	 * Case where the underlying tree is not availble, lookup the entity
1552 	 * and walk it.
1553 	 */
1554 	if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1555 	    (reader->ctxt->sax->getEntity != NULL)) {
1556 	    reader->node->children = (xmlNodePtr)
1557 		reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1558 	}
1559 
1560 	if ((reader->node->children != NULL) &&
1561 	    (reader->node->children->type == XML_ENTITY_DECL) &&
1562 	    (reader->node->children->children != NULL)) {
1563 	    xmlTextReaderEntPush(reader, reader->node);
1564 	    reader->node = reader->node->children->children;
1565 	}
1566 #ifdef LIBXML_REGEXP_ENABLED
1567     } else if ((reader->node != NULL) &&
1568 	       (reader->node->type == XML_ENTITY_REF_NODE) &&
1569 	       (reader->ctxt != NULL) && (reader->validate)) {
1570 	xmlTextReaderValidateEntity(reader);
1571 #endif /* LIBXML_REGEXP_ENABLED */
1572     }
1573     if ((reader->node != NULL) &&
1574 	(reader->node->type == XML_ENTITY_DECL) &&
1575 	(reader->ent != NULL) && (reader->ent->children == reader->node)) {
1576 	reader->node = xmlTextReaderEntPop(reader);
1577 	reader->depth++;
1578         goto get_next_node;
1579     }
1580 #ifdef LIBXML_REGEXP_ENABLED
1581     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1582 	xmlNodePtr node = reader->node;
1583 
1584 	if ((node->type == XML_ELEMENT_NODE) &&
1585             ((reader->state != XML_TEXTREADER_END) &&
1586 	     (reader->state != XML_TEXTREADER_BACKTRACK))) {
1587 	    xmlTextReaderValidatePush(reader);
1588 	} else if ((node->type == XML_TEXT_NODE) ||
1589 		   (node->type == XML_CDATA_SECTION_NODE)) {
1590             xmlTextReaderValidateCData(reader, node->content,
1591 	                               xmlStrlen(node->content));
1592 	}
1593     }
1594 #endif /* LIBXML_REGEXP_ENABLED */
1595 #ifdef LIBXML_PATTERN_ENABLED
1596     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1597         (reader->state != XML_TEXTREADER_BACKTRACK)) {
1598         int i;
1599 	for (i = 0;i < reader->patternNr;i++) {
1600 	     if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1601 	         xmlTextReaderPreserve(reader);
1602 		 break;
1603              }
1604 	}
1605     }
1606 #endif /* LIBXML_PATTERN_ENABLED */
1607 #ifdef LIBXML_SCHEMAS_ENABLED
1608     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1609         (reader->xsdValidErrors == 0) &&
1610 	(reader->xsdValidCtxt != NULL)) {
1611 	reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1612     }
1613 #endif /* LIBXML_PATTERN_ENABLED */
1614     return(1);
1615 node_end:
1616     reader->state = XML_TEXTREADER_DONE;
1617     return(0);
1618 }
1619 
1620 /**
1621  * xmlTextReaderReadState:
1622  * @reader:  the xmlTextReaderPtr used
1623  *
1624  * Gets the read state of the reader.
1625  *
1626  * Returns the state value, or -1 in case of error
1627  */
1628 int
xmlTextReaderReadState(xmlTextReaderPtr reader)1629 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1630     if (reader == NULL)
1631 	return(-1);
1632     return(reader->mode);
1633 }
1634 
1635 /**
1636  * xmlTextReaderExpand:
1637  * @reader:  the xmlTextReaderPtr used
1638  *
1639  * Reads the contents of the current node and the full subtree. It then makes
1640  * the subtree available until the next xmlTextReaderRead() call
1641  *
1642  * Returns a node pointer valid until the next xmlTextReaderRead() call
1643  *         or NULL in case of error.
1644  */
1645 xmlNodePtr
xmlTextReaderExpand(xmlTextReaderPtr reader)1646 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1647     if ((reader == NULL) || (reader->node == NULL))
1648         return(NULL);
1649     if (reader->doc != NULL)
1650         return(reader->node);
1651     if (reader->ctxt == NULL)
1652         return(NULL);
1653     if (xmlTextReaderDoExpand(reader) < 0)
1654         return(NULL);
1655     return(reader->node);
1656 }
1657 
1658 /**
1659  * xmlTextReaderNext:
1660  * @reader:  the xmlTextReaderPtr used
1661  *
1662  * Skip to the node following the current one in document order while
1663  * avoiding the subtree if any.
1664  *
1665  * Returns 1 if the node was read successfully, 0 if there is no more
1666  *          nodes to read, or -1 in case of error
1667  */
1668 int
xmlTextReaderNext(xmlTextReaderPtr reader)1669 xmlTextReaderNext(xmlTextReaderPtr reader) {
1670     int ret;
1671     xmlNodePtr cur;
1672 
1673     if (reader == NULL)
1674 	return(-1);
1675     if (reader->doc != NULL)
1676         return(xmlTextReaderNextTree(reader));
1677     cur = reader->node;
1678     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1679         return(xmlTextReaderRead(reader));
1680     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1681         return(xmlTextReaderRead(reader));
1682     if (cur->extra & NODE_IS_EMPTY)
1683         return(xmlTextReaderRead(reader));
1684     do {
1685         ret = xmlTextReaderRead(reader);
1686 	if (ret != 1)
1687 	    return(ret);
1688     } while (reader->node != cur);
1689     return(xmlTextReaderRead(reader));
1690 }
1691 
1692 #ifdef LIBXML_WRITER_ENABLED
1693 /**
1694  * xmlTextReaderReadInnerXml:
1695  * @reader:  the xmlTextReaderPtr used
1696  *
1697  * Reads the contents of the current node, including child nodes and markup.
1698  *
1699  * Returns a string containing the XML content, or NULL if the current node
1700  *         is neither an element nor attribute, or has no child nodes. The
1701  *         string must be deallocated by the caller.
1702  */
1703 xmlChar *
xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)1704 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1705 {
1706     xmlChar *resbuf;
1707     xmlNodePtr node, cur_node;
1708     xmlBufferPtr buff, buff2;
1709     xmlDocPtr doc;
1710 
1711     if (xmlTextReaderExpand(reader) == NULL) {
1712         return NULL;
1713     }
1714     doc = reader->node->doc;
1715     buff = xmlBufferCreate();
1716     for (cur_node = reader->node->children; cur_node != NULL;
1717          cur_node = cur_node->next) {
1718         /* XXX: Why is the node copied? */
1719         node = xmlDocCopyNode(cur_node, doc, 1);
1720         buff2 = xmlBufferCreate();
1721         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1722             xmlFreeNode(node);
1723             xmlBufferFree(buff2);
1724             xmlBufferFree(buff);
1725             return NULL;
1726         }
1727         xmlBufferCat(buff, buff2->content);
1728         xmlFreeNode(node);
1729         xmlBufferFree(buff2);
1730     }
1731     resbuf = buff->content;
1732     buff->content = NULL;
1733 
1734     xmlBufferFree(buff);
1735     return resbuf;
1736 }
1737 #endif
1738 
1739 #ifdef LIBXML_WRITER_ENABLED
1740 /**
1741  * xmlTextReaderReadOuterXml:
1742  * @reader:  the xmlTextReaderPtr used
1743  *
1744  * Reads the contents of the current node, including child nodes and markup.
1745  *
1746  * Returns a string containing the node and any XML content, or NULL if the
1747  *         current node cannot be serialized. The string must be deallocated
1748  *         by the caller.
1749  */
1750 xmlChar *
xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)1751 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1752 {
1753     xmlChar *resbuf;
1754     xmlNodePtr node;
1755     xmlBufferPtr buff;
1756     xmlDocPtr doc;
1757 
1758     node = reader->node;
1759     doc = node->doc;
1760     if (xmlTextReaderExpand(reader) == NULL) {
1761         return NULL;
1762     }
1763     /* XXX: Why is the node copied? */
1764 	if (node->type == XML_DTD_NODE) {
1765 		node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1766 	} else {
1767 		node = xmlDocCopyNode(node, doc, 1);
1768 	}
1769     buff = xmlBufferCreate();
1770     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1771         xmlFreeNode(node);
1772         xmlBufferFree(buff);
1773         return NULL;
1774     }
1775 
1776     resbuf = buff->content;
1777     buff->content = NULL;
1778 
1779     xmlFreeNode(node);
1780     xmlBufferFree(buff);
1781     return resbuf;
1782 }
1783 #endif
1784 
1785 /**
1786  * xmlTextReaderReadString:
1787  * @reader:  the xmlTextReaderPtr used
1788  *
1789  * Reads the contents of an element or a text node as a string.
1790  *
1791  * Returns a string containing the contents of the Element or Text node,
1792  *         or NULL if the reader is positioned on any other type of node.
1793  *         The string must be deallocated by the caller.
1794  */
1795 xmlChar *
xmlTextReaderReadString(xmlTextReaderPtr reader)1796 xmlTextReaderReadString(xmlTextReaderPtr reader)
1797 {
1798     xmlNodePtr node;
1799 
1800     if ((reader == NULL) || (reader->node == NULL))
1801        return(NULL);
1802 
1803     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1804     switch (node->type) {
1805     case XML_TEXT_NODE:
1806        if (node->content != NULL)
1807            return(xmlStrdup(node->content));
1808        break;
1809     case XML_ELEMENT_NODE:
1810 	if (xmlTextReaderDoExpand(reader) != -1) {
1811 	    return xmlTextReaderCollectSiblings(node->children);
1812 	}
1813 	break;
1814     case XML_ATTRIBUTE_NODE:
1815 	TODO
1816 	break;
1817     default:
1818        break;
1819     }
1820     return(NULL);
1821 }
1822 
1823 #if 0
1824 /**
1825  * xmlTextReaderReadBase64:
1826  * @reader:  the xmlTextReaderPtr used
1827  * @array:  a byte array to store the content.
1828  * @offset:  the zero-based index into array where the method should
1829  *           begin to write.
1830  * @len:  the number of bytes to write.
1831  *
1832  * Reads and decodes the Base64 encoded contents of an element and
1833  * stores the result in a byte buffer.
1834  *
1835  * Returns the number of bytes written to array, or zero if the current
1836  *         instance is not positioned on an element or -1 in case of error.
1837  */
1838 int
1839 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1840                         unsigned char *array ATTRIBUTE_UNUSED,
1841 	                int offset ATTRIBUTE_UNUSED,
1842 			int len ATTRIBUTE_UNUSED) {
1843     if ((reader == NULL) || (reader->ctxt == NULL))
1844 	return(-1);
1845     if (reader->ctxt->wellFormed != 1)
1846 	return(-1);
1847 
1848     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1849 	return(0);
1850     TODO
1851     return(0);
1852 }
1853 
1854 /**
1855  * xmlTextReaderReadBinHex:
1856  * @reader:  the xmlTextReaderPtr used
1857  * @array:  a byte array to store the content.
1858  * @offset:  the zero-based index into array where the method should
1859  *           begin to write.
1860  * @len:  the number of bytes to write.
1861  *
1862  * Reads and decodes the BinHex encoded contents of an element and
1863  * stores the result in a byte buffer.
1864  *
1865  * Returns the number of bytes written to array, or zero if the current
1866  *         instance is not positioned on an element or -1 in case of error.
1867  */
1868 int
1869 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1870                         unsigned char *array ATTRIBUTE_UNUSED,
1871 	                int offset ATTRIBUTE_UNUSED,
1872 			int len ATTRIBUTE_UNUSED) {
1873     if ((reader == NULL) || (reader->ctxt == NULL))
1874 	return(-1);
1875     if (reader->ctxt->wellFormed != 1)
1876 	return(-1);
1877 
1878     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1879 	return(0);
1880     TODO
1881     return(0);
1882 }
1883 #endif
1884 
1885 /************************************************************************
1886  *									*
1887  *			Operating on a preparsed tree			*
1888  *									*
1889  ************************************************************************/
1890 static int
xmlTextReaderNextTree(xmlTextReaderPtr reader)1891 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1892 {
1893     if (reader == NULL)
1894         return(-1);
1895 
1896     if (reader->state == XML_TEXTREADER_END)
1897         return(0);
1898 
1899     if (reader->node == NULL) {
1900         if (reader->doc->children == NULL) {
1901             reader->state = XML_TEXTREADER_END;
1902             return(0);
1903         }
1904 
1905         reader->node = reader->doc->children;
1906         reader->state = XML_TEXTREADER_START;
1907         return(1);
1908     }
1909 
1910     if (reader->state != XML_TEXTREADER_BACKTRACK) {
1911 	/* Here removed traversal to child, because we want to skip the subtree,
1912 	replace with traversal to sibling to skip subtree */
1913         if (reader->node->next != 0) {
1914 	    /* Move to sibling if present,skipping sub-tree */
1915             reader->node = reader->node->next;
1916             reader->state = XML_TEXTREADER_START;
1917             return(1);
1918         }
1919 
1920 	/* if reader->node->next is NULL mean no subtree for current node,
1921 	so need to move to sibling of parent node if present */
1922 	reader->state = XML_TEXTREADER_BACKTRACK;
1923 	/* This will move to parent if present */
1924 	xmlTextReaderRead(reader);
1925     }
1926 
1927     if (reader->node->next != 0) {
1928         reader->node = reader->node->next;
1929         reader->state = XML_TEXTREADER_START;
1930         return(1);
1931     }
1932 
1933     if (reader->node->parent != 0) {
1934         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1935             reader->state = XML_TEXTREADER_END;
1936             return(0);
1937         }
1938 
1939         reader->node = reader->node->parent;
1940         reader->depth--;
1941         reader->state = XML_TEXTREADER_BACKTRACK;
1942 	/* Repeat process to move to sibling of parent node if present */
1943         xmlTextReaderNextTree(reader);
1944     }
1945 
1946     reader->state = XML_TEXTREADER_END;
1947 
1948     return(1);
1949 }
1950 
1951 /**
1952  * xmlTextReaderReadTree:
1953  * @reader:  the xmlTextReaderPtr used
1954  *
1955  *  Moves the position of the current instance to the next node in
1956  *  the stream, exposing its properties.
1957  *
1958  *  Returns 1 if the node was read successfully, 0 if there is no more
1959  *          nodes to read, or -1 in case of error
1960  */
1961 static int
xmlTextReaderReadTree(xmlTextReaderPtr reader)1962 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1963     if (reader->state == XML_TEXTREADER_END)
1964         return(0);
1965 
1966 next_node:
1967     if (reader->node == NULL) {
1968         if (reader->doc->children == NULL) {
1969             reader->state = XML_TEXTREADER_END;
1970             return(0);
1971         }
1972 
1973         reader->node = reader->doc->children;
1974         reader->state = XML_TEXTREADER_START;
1975         goto found_node;
1976     }
1977 
1978     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1979         (reader->node->type != XML_DTD_NODE) &&
1980         (reader->node->type != XML_XINCLUDE_START) &&
1981 	(reader->node->type != XML_ENTITY_REF_NODE)) {
1982         if (reader->node->children != NULL) {
1983             reader->node = reader->node->children;
1984             reader->depth++;
1985             reader->state = XML_TEXTREADER_START;
1986             goto found_node;
1987         }
1988 
1989         if (reader->node->type == XML_ATTRIBUTE_NODE) {
1990             reader->state = XML_TEXTREADER_BACKTRACK;
1991             goto found_node;
1992         }
1993     }
1994 
1995     if (reader->node->next != NULL) {
1996         reader->node = reader->node->next;
1997         reader->state = XML_TEXTREADER_START;
1998         goto found_node;
1999     }
2000 
2001     if (reader->node->parent != NULL) {
2002         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
2003 	    (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2004             reader->state = XML_TEXTREADER_END;
2005             return(0);
2006         }
2007 
2008         reader->node = reader->node->parent;
2009         reader->depth--;
2010         reader->state = XML_TEXTREADER_BACKTRACK;
2011         goto found_node;
2012     }
2013 
2014     reader->state = XML_TEXTREADER_END;
2015 
2016 found_node:
2017     if ((reader->node->type == XML_XINCLUDE_START) ||
2018         (reader->node->type == XML_XINCLUDE_END))
2019 	goto next_node;
2020 
2021     return(1);
2022 }
2023 
2024 /**
2025  * xmlTextReaderNextSibling:
2026  * @reader:  the xmlTextReaderPtr used
2027  *
2028  * Skip to the node following the current one in document order while
2029  * avoiding the subtree if any.
2030  * Currently implemented only for Readers built on a document
2031  *
2032  * Returns 1 if the node was read successfully, 0 if there is no more
2033  *          nodes to read, or -1 in case of error
2034  */
2035 int
xmlTextReaderNextSibling(xmlTextReaderPtr reader)2036 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2037     if (reader == NULL)
2038         return(-1);
2039     if (reader->doc == NULL) {
2040         /* TODO */
2041 	return(-1);
2042     }
2043 
2044     if (reader->state == XML_TEXTREADER_END)
2045         return(0);
2046 
2047     if (reader->node == NULL)
2048         return(xmlTextReaderNextTree(reader));
2049 
2050     if (reader->node->next != NULL) {
2051         reader->node = reader->node->next;
2052         reader->state = XML_TEXTREADER_START;
2053         return(1);
2054     }
2055 
2056     return(0);
2057 }
2058 
2059 /************************************************************************
2060  *									*
2061  *			Constructor and destructors			*
2062  *									*
2063  ************************************************************************/
2064 /**
2065  * xmlNewTextReader:
2066  * @input: the xmlParserInputBufferPtr used to read data
2067  * @URI: the URI information for the source if available
2068  *
2069  * Create an xmlTextReader structure fed with @input
2070  *
2071  * Returns the new xmlTextReaderPtr or NULL in case of error
2072  */
2073 xmlTextReaderPtr
xmlNewTextReader(xmlParserInputBufferPtr input,const char * URI)2074 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2075     xmlTextReaderPtr ret;
2076 
2077     if (input == NULL)
2078 	return(NULL);
2079     ret = xmlMalloc(sizeof(xmlTextReader));
2080     if (ret == NULL) {
2081         xmlGenericError(xmlGenericErrorContext,
2082 		"xmlNewTextReader : malloc failed\n");
2083 	return(NULL);
2084     }
2085     memset(ret, 0, sizeof(xmlTextReader));
2086     ret->doc = NULL;
2087     ret->entTab = NULL;
2088     ret->entMax = 0;
2089     ret->entNr = 0;
2090     ret->input = input;
2091     ret->buffer = xmlBufCreateSize(100);
2092     if (ret->buffer == NULL) {
2093         xmlFree(ret);
2094         xmlGenericError(xmlGenericErrorContext,
2095 		"xmlNewTextReader : malloc failed\n");
2096 	return(NULL);
2097     }
2098     /* no operation on a reader should require a huge buffer */
2099     xmlBufSetAllocationScheme(ret->buffer,
2100 			      XML_BUFFER_ALLOC_BOUNDED);
2101     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2102     if (ret->sax == NULL) {
2103 	xmlBufFree(ret->buffer);
2104 	xmlFree(ret);
2105         xmlGenericError(xmlGenericErrorContext,
2106 		"xmlNewTextReader : malloc failed\n");
2107 	return(NULL);
2108     }
2109     xmlSAXVersion(ret->sax, 2);
2110     ret->startElement = ret->sax->startElement;
2111     ret->sax->startElement = xmlTextReaderStartElement;
2112     ret->endElement = ret->sax->endElement;
2113     ret->sax->endElement = xmlTextReaderEndElement;
2114 #ifdef LIBXML_SAX1_ENABLED
2115     if (ret->sax->initialized == XML_SAX2_MAGIC) {
2116 #endif /* LIBXML_SAX1_ENABLED */
2117 	ret->startElementNs = ret->sax->startElementNs;
2118 	ret->sax->startElementNs = xmlTextReaderStartElementNs;
2119 	ret->endElementNs = ret->sax->endElementNs;
2120 	ret->sax->endElementNs = xmlTextReaderEndElementNs;
2121 #ifdef LIBXML_SAX1_ENABLED
2122     } else {
2123 	ret->startElementNs = NULL;
2124 	ret->endElementNs = NULL;
2125     }
2126 #endif /* LIBXML_SAX1_ENABLED */
2127     ret->characters = ret->sax->characters;
2128     ret->sax->characters = xmlTextReaderCharacters;
2129     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2130     ret->cdataBlock = ret->sax->cdataBlock;
2131     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2132 
2133     ret->mode = XML_TEXTREADER_MODE_INITIAL;
2134     ret->node = NULL;
2135     ret->curnode = NULL;
2136     if (xmlBufUse(ret->input->buffer) < 4) {
2137 	xmlParserInputBufferRead(input, 4);
2138     }
2139     if (xmlBufUse(ret->input->buffer) >= 4) {
2140 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2141 			     (const char *) xmlBufContent(ret->input->buffer),
2142                                             4, URI);
2143 	ret->base = 0;
2144 	ret->cur = 4;
2145     } else {
2146 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2147 	ret->base = 0;
2148 	ret->cur = 0;
2149     }
2150 
2151     if (ret->ctxt == NULL) {
2152         xmlGenericError(xmlGenericErrorContext,
2153 		"xmlNewTextReader : malloc failed\n");
2154 	xmlBufFree(ret->buffer);
2155 	xmlFree(ret->sax);
2156 	xmlFree(ret);
2157 	return(NULL);
2158     }
2159     ret->ctxt->parseMode = XML_PARSE_READER;
2160     ret->ctxt->_private = ret;
2161     ret->ctxt->linenumbers = 1;
2162     ret->ctxt->dictNames = 1;
2163     ret->allocs = XML_TEXTREADER_CTXT;
2164     /*
2165      * use the parser dictionary to allocate all elements and attributes names
2166      */
2167     ret->ctxt->docdict = 1;
2168     ret->dict = ret->ctxt->dict;
2169 #ifdef LIBXML_XINCLUDE_ENABLED
2170     ret->xinclude = 0;
2171 #endif
2172 #ifdef LIBXML_PATTERN_ENABLED
2173     ret->patternMax = 0;
2174     ret->patternTab = NULL;
2175 #endif
2176     return(ret);
2177 }
2178 
2179 /**
2180  * xmlNewTextReaderFilename:
2181  * @URI: the URI of the resource to process
2182  *
2183  * Create an xmlTextReader structure fed with the resource at @URI
2184  *
2185  * Returns the new xmlTextReaderPtr or NULL in case of error
2186  */
2187 xmlTextReaderPtr
xmlNewTextReaderFilename(const char * URI)2188 xmlNewTextReaderFilename(const char *URI) {
2189     xmlParserInputBufferPtr input;
2190     xmlTextReaderPtr ret;
2191     char *directory = NULL;
2192 
2193     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2194     if (input == NULL)
2195 	return(NULL);
2196     ret = xmlNewTextReader(input, URI);
2197     if (ret == NULL) {
2198 	xmlFreeParserInputBuffer(input);
2199 	return(NULL);
2200     }
2201     ret->allocs |= XML_TEXTREADER_INPUT;
2202     if (ret->ctxt->directory == NULL)
2203         directory = xmlParserGetDirectory(URI);
2204     if ((ret->ctxt->directory == NULL) && (directory != NULL))
2205         ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2206     if (directory != NULL)
2207 	xmlFree(directory);
2208     return(ret);
2209 }
2210 
2211 /**
2212  * xmlFreeTextReader:
2213  * @reader:  the xmlTextReaderPtr
2214  *
2215  * Deallocate all the resources associated to the reader
2216  */
2217 void
xmlFreeTextReader(xmlTextReaderPtr reader)2218 xmlFreeTextReader(xmlTextReaderPtr reader) {
2219     if (reader == NULL)
2220 	return;
2221 #ifdef LIBXML_SCHEMAS_ENABLED
2222     if (reader->rngSchemas != NULL) {
2223 	xmlRelaxNGFree(reader->rngSchemas);
2224 	reader->rngSchemas = NULL;
2225     }
2226     if (reader->rngValidCtxt != NULL) {
2227 	if (! reader->rngPreserveCtxt)
2228 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2229 	reader->rngValidCtxt = NULL;
2230     }
2231     if (reader->xsdPlug != NULL) {
2232 	xmlSchemaSAXUnplug(reader->xsdPlug);
2233 	reader->xsdPlug = NULL;
2234     }
2235     if (reader->xsdValidCtxt != NULL) {
2236 	if (! reader->xsdPreserveCtxt)
2237 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2238 	reader->xsdValidCtxt = NULL;
2239     }
2240     if (reader->xsdSchemas != NULL) {
2241 	xmlSchemaFree(reader->xsdSchemas);
2242 	reader->xsdSchemas = NULL;
2243     }
2244 #endif
2245 #ifdef LIBXML_XINCLUDE_ENABLED
2246     if (reader->xincctxt != NULL)
2247 	xmlXIncludeFreeContext(reader->xincctxt);
2248 #endif
2249 #ifdef LIBXML_PATTERN_ENABLED
2250     if (reader->patternTab != NULL) {
2251         int i;
2252 	for (i = 0;i < reader->patternNr;i++) {
2253 	    if (reader->patternTab[i] != NULL)
2254 	        xmlFreePattern(reader->patternTab[i]);
2255 	}
2256 	xmlFree(reader->patternTab);
2257     }
2258 #endif
2259     if (reader->faketext != NULL) {
2260 	xmlFreeNode(reader->faketext);
2261     }
2262     if (reader->ctxt != NULL) {
2263         if (reader->dict == reader->ctxt->dict)
2264 	    reader->dict = NULL;
2265 	if (reader->ctxt->myDoc != NULL) {
2266 	    if (reader->preserve == 0)
2267 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2268 	    reader->ctxt->myDoc = NULL;
2269 	}
2270 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2271 	    (reader->ctxt->vctxt.vstateMax > 0)){
2272 	    xmlFree(reader->ctxt->vctxt.vstateTab);
2273 	    reader->ctxt->vctxt.vstateTab = NULL;
2274 	    reader->ctxt->vctxt.vstateMax = 0;
2275 	}
2276 	if (reader->allocs & XML_TEXTREADER_CTXT)
2277 	    xmlFreeParserCtxt(reader->ctxt);
2278     }
2279     if (reader->sax != NULL)
2280 	xmlFree(reader->sax);
2281     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
2282 	xmlFreeParserInputBuffer(reader->input);
2283     if (reader->buffer != NULL)
2284         xmlBufFree(reader->buffer);
2285     if (reader->entTab != NULL)
2286 	xmlFree(reader->entTab);
2287     if (reader->dict != NULL)
2288         xmlDictFree(reader->dict);
2289     xmlFree(reader);
2290 }
2291 
2292 /************************************************************************
2293  *									*
2294  *			Methods for XmlTextReader			*
2295  *									*
2296  ************************************************************************/
2297 /**
2298  * xmlTextReaderClose:
2299  * @reader:  the xmlTextReaderPtr used
2300  *
2301  * This method releases any resources allocated by the current instance
2302  * changes the state to Closed and close any underlying input.
2303  *
2304  * Returns 0 or -1 in case of error
2305  */
2306 int
xmlTextReaderClose(xmlTextReaderPtr reader)2307 xmlTextReaderClose(xmlTextReaderPtr reader) {
2308     if (reader == NULL)
2309 	return(-1);
2310     reader->node = NULL;
2311     reader->curnode = NULL;
2312     reader->mode = XML_TEXTREADER_MODE_CLOSED;
2313     if (reader->ctxt != NULL) {
2314 	xmlStopParser(reader->ctxt);
2315 	if (reader->ctxt->myDoc != NULL) {
2316 	    if (reader->preserve == 0)
2317 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2318 	    reader->ctxt->myDoc = NULL;
2319 	}
2320     }
2321     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
2322 	xmlFreeParserInputBuffer(reader->input);
2323 	reader->allocs -= XML_TEXTREADER_INPUT;
2324     }
2325     return(0);
2326 }
2327 
2328 /**
2329  * xmlTextReaderGetAttributeNo:
2330  * @reader:  the xmlTextReaderPtr used
2331  * @no: the zero-based index of the attribute relative to the containing element
2332  *
2333  * Provides the value of the attribute with the specified index relative
2334  * to the containing element.
2335  *
2336  * Returns a string containing the value of the specified attribute, or NULL
2337  *    in case of error. The string must be deallocated by the caller.
2338  */
2339 xmlChar *
xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader,int no)2340 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2341     xmlChar *ret;
2342     int i;
2343     xmlAttrPtr cur;
2344     xmlNsPtr ns;
2345 
2346     if (reader == NULL)
2347 	return(NULL);
2348     if (reader->node == NULL)
2349 	return(NULL);
2350     if (reader->curnode != NULL)
2351 	return(NULL);
2352     /* TODO: handle the xmlDecl */
2353     if (reader->node->type != XML_ELEMENT_NODE)
2354 	return(NULL);
2355 
2356     ns = reader->node->nsDef;
2357     for (i = 0;(i < no) && (ns != NULL);i++) {
2358 	ns = ns->next;
2359     }
2360     if (ns != NULL)
2361 	return(xmlStrdup(ns->href));
2362 
2363     cur = reader->node->properties;
2364     if (cur == NULL)
2365 	return(NULL);
2366     for (;i < no;i++) {
2367 	cur = cur->next;
2368 	if (cur == NULL)
2369 	    return(NULL);
2370     }
2371     /* TODO walk the DTD if present */
2372 
2373     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2374     if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2375     return(ret);
2376 }
2377 
2378 /**
2379  * xmlTextReaderGetAttribute:
2380  * @reader:  the xmlTextReaderPtr used
2381  * @name: the qualified name of the attribute.
2382  *
2383  * Provides the value of the attribute with the specified qualified name.
2384  *
2385  * Returns a string containing the value of the specified attribute, or NULL
2386  *    in case of error. The string must be deallocated by the caller.
2387  */
2388 xmlChar *
xmlTextReaderGetAttribute(xmlTextReaderPtr reader,const xmlChar * name)2389 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2390     xmlChar *prefix = NULL;
2391     xmlChar *localname;
2392     xmlNsPtr ns;
2393     xmlChar *ret = NULL;
2394 
2395     if ((reader == NULL) || (name == NULL))
2396 	return(NULL);
2397     if (reader->node == NULL)
2398 	return(NULL);
2399     if (reader->curnode != NULL)
2400 	return(NULL);
2401 
2402     /* TODO: handle the xmlDecl */
2403     if (reader->node->type != XML_ELEMENT_NODE)
2404 	return(NULL);
2405 
2406     localname = xmlSplitQName2(name, &prefix);
2407     if (localname == NULL) {
2408 		/*
2409 		 * Namespace default decl
2410 		 */
2411 		if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2412 			ns = reader->node->nsDef;
2413 			while (ns != NULL) {
2414 				if (ns->prefix == NULL) {
2415 					return(xmlStrdup(ns->href));
2416 				}
2417 				ns = ns->next;
2418 			}
2419 			return NULL;
2420 		}
2421 		return(xmlGetNoNsProp(reader->node, name));
2422 	}
2423 
2424     /*
2425      * Namespace default decl
2426      */
2427     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2428 		ns = reader->node->nsDef;
2429 		while (ns != NULL) {
2430 			if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2431 				ret = xmlStrdup(ns->href);
2432 				break;
2433 			}
2434 			ns = ns->next;
2435 		}
2436     } else {
2437 		ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2438 		if (ns != NULL)
2439 			ret = xmlGetNsProp(reader->node, localname, ns->href);
2440 	}
2441 
2442     xmlFree(localname);
2443     if (prefix != NULL)
2444         xmlFree(prefix);
2445     return(ret);
2446 }
2447 
2448 
2449 /**
2450  * xmlTextReaderGetAttributeNs:
2451  * @reader:  the xmlTextReaderPtr used
2452  * @localName: the local name of the attribute.
2453  * @namespaceURI: the namespace URI of the attribute.
2454  *
2455  * Provides the value of the specified attribute
2456  *
2457  * Returns a string containing the value of the specified attribute, or NULL
2458  *    in case of error. The string must be deallocated by the caller.
2459  */
2460 xmlChar *
xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader,const xmlChar * localName,const xmlChar * namespaceURI)2461 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2462 			    const xmlChar *namespaceURI) {
2463     xmlChar *prefix = NULL;
2464     xmlNsPtr ns;
2465 
2466     if ((reader == NULL) || (localName == NULL))
2467 	return(NULL);
2468     if (reader->node == NULL)
2469 	return(NULL);
2470     if (reader->curnode != NULL)
2471 	return(NULL);
2472 
2473     /* TODO: handle the xmlDecl */
2474     if (reader->node->type != XML_ELEMENT_NODE)
2475 	return(NULL);
2476 
2477     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2478 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2479 			prefix = BAD_CAST localName;
2480 		}
2481 		ns = reader->node->nsDef;
2482 		while (ns != NULL) {
2483 			if ((prefix == NULL && ns->prefix == NULL) ||
2484 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2485 				return xmlStrdup(ns->href);
2486 			}
2487 			ns = ns->next;
2488 		}
2489 		return NULL;
2490     }
2491 
2492     return(xmlGetNsProp(reader->node, localName, namespaceURI));
2493 }
2494 
2495 /**
2496  * xmlTextReaderGetRemainder:
2497  * @reader:  the xmlTextReaderPtr used
2498  *
2499  * Method to get the remainder of the buffered XML. this method stops the
2500  * parser, set its state to End Of File and return the input stream with
2501  * what is left that the parser did not use.
2502  *
2503  * The implementation is not good, the parser certainly procgressed past
2504  * what's left in reader->input, and there is an allocation problem. Best
2505  * would be to rewrite it differently.
2506  *
2507  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2508  *    in case of error.
2509  */
2510 xmlParserInputBufferPtr
xmlTextReaderGetRemainder(xmlTextReaderPtr reader)2511 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2512     xmlParserInputBufferPtr ret = NULL;
2513 
2514     if (reader == NULL)
2515 	return(NULL);
2516     if (reader->node == NULL)
2517 	return(NULL);
2518 
2519     reader->node = NULL;
2520     reader->curnode = NULL;
2521     reader->mode = XML_TEXTREADER_MODE_EOF;
2522     if (reader->ctxt != NULL) {
2523 	xmlStopParser(reader->ctxt);
2524 	if (reader->ctxt->myDoc != NULL) {
2525 	    if (reader->preserve == 0)
2526 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2527 	    reader->ctxt->myDoc = NULL;
2528 	}
2529     }
2530     if (reader->allocs & XML_TEXTREADER_INPUT) {
2531 	ret = reader->input;
2532 	reader->input = NULL;
2533 	reader->allocs -= XML_TEXTREADER_INPUT;
2534     } else {
2535 	/*
2536 	 * Hum, one may need to duplicate the data structure because
2537 	 * without reference counting the input may be freed twice:
2538 	 *   - by the layer which allocated it.
2539 	 *   - by the layer to which would have been returned to.
2540 	 */
2541 	TODO
2542 	return(NULL);
2543     }
2544     return(ret);
2545 }
2546 
2547 /**
2548  * xmlTextReaderLookupNamespace:
2549  * @reader:  the xmlTextReaderPtr used
2550  * @prefix: the prefix whose namespace URI is to be resolved. To return
2551  *          the default namespace, specify NULL
2552  *
2553  * Resolves a namespace prefix in the scope of the current element.
2554  *
2555  * Returns a string containing the namespace URI to which the prefix maps
2556  *    or NULL in case of error. The string must be deallocated by the caller.
2557  */
2558 xmlChar *
xmlTextReaderLookupNamespace(xmlTextReaderPtr reader,const xmlChar * prefix)2559 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2560     xmlNsPtr ns;
2561 
2562     if (reader == NULL)
2563 	return(NULL);
2564     if (reader->node == NULL)
2565 	return(NULL);
2566 
2567     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2568     if (ns == NULL)
2569 	return(NULL);
2570     return(xmlStrdup(ns->href));
2571 }
2572 
2573 /**
2574  * xmlTextReaderMoveToAttributeNo:
2575  * @reader:  the xmlTextReaderPtr used
2576  * @no: the zero-based index of the attribute relative to the containing
2577  *      element.
2578  *
2579  * Moves the position of the current instance to the attribute with
2580  * the specified index relative to the containing element.
2581  *
2582  * Returns 1 in case of success, -1 in case of error, 0 if not found
2583  */
2584 int
xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader,int no)2585 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2586     int i;
2587     xmlAttrPtr cur;
2588     xmlNsPtr ns;
2589 
2590     if (reader == NULL)
2591 	return(-1);
2592     if (reader->node == NULL)
2593 	return(-1);
2594     /* TODO: handle the xmlDecl */
2595     if (reader->node->type != XML_ELEMENT_NODE)
2596 	return(-1);
2597 
2598     reader->curnode = NULL;
2599 
2600     ns = reader->node->nsDef;
2601     for (i = 0;(i < no) && (ns != NULL);i++) {
2602 	ns = ns->next;
2603     }
2604     if (ns != NULL) {
2605 	reader->curnode = (xmlNodePtr) ns;
2606 	return(1);
2607     }
2608 
2609     cur = reader->node->properties;
2610     if (cur == NULL)
2611 	return(0);
2612     for (;i < no;i++) {
2613 	cur = cur->next;
2614 	if (cur == NULL)
2615 	    return(0);
2616     }
2617     /* TODO walk the DTD if present */
2618 
2619     reader->curnode = (xmlNodePtr) cur;
2620     return(1);
2621 }
2622 
2623 /**
2624  * xmlTextReaderMoveToAttribute:
2625  * @reader:  the xmlTextReaderPtr used
2626  * @name: the qualified name of the attribute.
2627  *
2628  * Moves the position of the current instance to the attribute with
2629  * the specified qualified name.
2630  *
2631  * Returns 1 in case of success, -1 in case of error, 0 if not found
2632  */
2633 int
xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader,const xmlChar * name)2634 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2635     xmlChar *prefix = NULL;
2636     xmlChar *localname;
2637     xmlNsPtr ns;
2638     xmlAttrPtr prop;
2639 
2640     if ((reader == NULL) || (name == NULL))
2641 	return(-1);
2642     if (reader->node == NULL)
2643 	return(-1);
2644 
2645     /* TODO: handle the xmlDecl */
2646     if (reader->node->type != XML_ELEMENT_NODE)
2647 	return(0);
2648 
2649     localname = xmlSplitQName2(name, &prefix);
2650     if (localname == NULL) {
2651 	/*
2652 	 * Namespace default decl
2653 	 */
2654 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2655 	    ns = reader->node->nsDef;
2656 	    while (ns != NULL) {
2657 		if (ns->prefix == NULL) {
2658 		    reader->curnode = (xmlNodePtr) ns;
2659 		    return(1);
2660 		}
2661 		ns = ns->next;
2662 	    }
2663 	    return(0);
2664 	}
2665 
2666 	prop = reader->node->properties;
2667 	while (prop != NULL) {
2668 	    /*
2669 	     * One need to have
2670 	     *   - same attribute names
2671 	     *   - and the attribute carrying that namespace
2672 	     */
2673 	    if ((xmlStrEqual(prop->name, name)) &&
2674 		((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2675 		reader->curnode = (xmlNodePtr) prop;
2676 		return(1);
2677 	    }
2678 	    prop = prop->next;
2679 	}
2680 	return(0);
2681     }
2682 
2683     /*
2684      * Namespace default decl
2685      */
2686     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2687 	ns = reader->node->nsDef;
2688 	while (ns != NULL) {
2689 	    if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2690 		reader->curnode = (xmlNodePtr) ns;
2691 		goto found;
2692 	    }
2693 	    ns = ns->next;
2694 	}
2695 	goto not_found;
2696     }
2697     prop = reader->node->properties;
2698     while (prop != NULL) {
2699 	/*
2700 	 * One need to have
2701 	 *   - same attribute names
2702 	 *   - and the attribute carrying that namespace
2703 	 */
2704 	if ((xmlStrEqual(prop->name, localname)) &&
2705 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2706 	    reader->curnode = (xmlNodePtr) prop;
2707 	    goto found;
2708 	}
2709 	prop = prop->next;
2710     }
2711 not_found:
2712     if (localname != NULL)
2713         xmlFree(localname);
2714     if (prefix != NULL)
2715         xmlFree(prefix);
2716     return(0);
2717 
2718 found:
2719     if (localname != NULL)
2720         xmlFree(localname);
2721     if (prefix != NULL)
2722         xmlFree(prefix);
2723     return(1);
2724 }
2725 
2726 /**
2727  * xmlTextReaderMoveToAttributeNs:
2728  * @reader:  the xmlTextReaderPtr used
2729  * @localName:  the local name of the attribute.
2730  * @namespaceURI:  the namespace URI of the attribute.
2731  *
2732  * Moves the position of the current instance to the attribute with the
2733  * specified local name and namespace URI.
2734  *
2735  * Returns 1 in case of success, -1 in case of error, 0 if not found
2736  */
2737 int
xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,const xmlChar * localName,const xmlChar * namespaceURI)2738 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2739 	const xmlChar *localName, const xmlChar *namespaceURI) {
2740     xmlAttrPtr prop;
2741     xmlNodePtr node;
2742     xmlNsPtr ns;
2743     xmlChar *prefix = NULL;
2744 
2745     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2746 	return(-1);
2747     if (reader->node == NULL)
2748 	return(-1);
2749     if (reader->node->type != XML_ELEMENT_NODE)
2750 	return(0);
2751     node = reader->node;
2752 
2753     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2754 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2755 			prefix = BAD_CAST localName;
2756 		}
2757 		ns = reader->node->nsDef;
2758 		while (ns != NULL) {
2759 			if ((prefix == NULL && ns->prefix == NULL) ||
2760 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2761 				reader->curnode = (xmlNodePtr) ns;
2762 				return(1);
2763 			}
2764 			ns = ns->next;
2765 		}
2766 		return(0);
2767     }
2768 
2769     prop = node->properties;
2770     while (prop != NULL) {
2771 	/*
2772 	 * One need to have
2773 	 *   - same attribute names
2774 	 *   - and the attribute carrying that namespace
2775 	 */
2776         if (xmlStrEqual(prop->name, localName) &&
2777 	    ((prop->ns != NULL) &&
2778 	     (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2779 	    reader->curnode = (xmlNodePtr) prop;
2780 	    return(1);
2781         }
2782 	prop = prop->next;
2783     }
2784     return(0);
2785 }
2786 
2787 /**
2788  * xmlTextReaderMoveToFirstAttribute:
2789  * @reader:  the xmlTextReaderPtr used
2790  *
2791  * Moves the position of the current instance to the first attribute
2792  * associated with the current node.
2793  *
2794  * Returns 1 in case of success, -1 in case of error, 0 if not found
2795  */
2796 int
xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader)2797 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2798     if (reader == NULL)
2799 	return(-1);
2800     if (reader->node == NULL)
2801 	return(-1);
2802     if (reader->node->type != XML_ELEMENT_NODE)
2803 	return(0);
2804 
2805     if (reader->node->nsDef != NULL) {
2806 	reader->curnode = (xmlNodePtr) reader->node->nsDef;
2807 	return(1);
2808     }
2809     if (reader->node->properties != NULL) {
2810 	reader->curnode = (xmlNodePtr) reader->node->properties;
2811 	return(1);
2812     }
2813     return(0);
2814 }
2815 
2816 /**
2817  * xmlTextReaderMoveToNextAttribute:
2818  * @reader:  the xmlTextReaderPtr used
2819  *
2820  * Moves the position of the current instance to the next attribute
2821  * associated with the current node.
2822  *
2823  * Returns 1 in case of success, -1 in case of error, 0 if not found
2824  */
2825 int
xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader)2826 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2827     if (reader == NULL)
2828 	return(-1);
2829     if (reader->node == NULL)
2830 	return(-1);
2831     if (reader->node->type != XML_ELEMENT_NODE)
2832 	return(0);
2833     if (reader->curnode == NULL)
2834 	return(xmlTextReaderMoveToFirstAttribute(reader));
2835 
2836     if (reader->curnode->type == XML_NAMESPACE_DECL) {
2837 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2838 	if (ns->next != NULL) {
2839 	    reader->curnode = (xmlNodePtr) ns->next;
2840 	    return(1);
2841 	}
2842 	if (reader->node->properties != NULL) {
2843 	    reader->curnode = (xmlNodePtr) reader->node->properties;
2844 	    return(1);
2845 	}
2846 	return(0);
2847     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2848 	       (reader->curnode->next != NULL)) {
2849 	reader->curnode = reader->curnode->next;
2850 	return(1);
2851     }
2852     return(0);
2853 }
2854 
2855 /**
2856  * xmlTextReaderMoveToElement:
2857  * @reader:  the xmlTextReaderPtr used
2858  *
2859  * Moves the position of the current instance to the node that
2860  * contains the current Attribute  node.
2861  *
2862  * Returns 1 in case of success, -1 in case of error, 0 if not moved
2863  */
2864 int
xmlTextReaderMoveToElement(xmlTextReaderPtr reader)2865 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2866     if (reader == NULL)
2867 	return(-1);
2868     if (reader->node == NULL)
2869 	return(-1);
2870     if (reader->node->type != XML_ELEMENT_NODE)
2871 	return(0);
2872     if (reader->curnode != NULL) {
2873 	reader->curnode = NULL;
2874 	return(1);
2875     }
2876     return(0);
2877 }
2878 
2879 /**
2880  * xmlTextReaderReadAttributeValue:
2881  * @reader:  the xmlTextReaderPtr used
2882  *
2883  * Parses an attribute value into one or more Text and EntityReference nodes.
2884  *
2885  * Returns 1 in case of success, 0 if the reader was not positionned on an
2886  *         ttribute node or all the attribute values have been read, or -1
2887  *         in case of error.
2888  */
2889 int
xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader)2890 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2891     if (reader == NULL)
2892 	return(-1);
2893     if (reader->node == NULL)
2894 	return(-1);
2895     if (reader->curnode == NULL)
2896 	return(0);
2897     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2898 	if (reader->curnode->children == NULL)
2899 	    return(0);
2900 	reader->curnode = reader->curnode->children;
2901     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2902 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2903 
2904 	if (reader->faketext == NULL) {
2905 	    reader->faketext = xmlNewDocText(reader->node->doc,
2906 		                             ns->href);
2907 	} else {
2908             if ((reader->faketext->content != NULL) &&
2909 	        (reader->faketext->content !=
2910 		 (xmlChar *) &(reader->faketext->properties)))
2911 		xmlFree(reader->faketext->content);
2912 	    reader->faketext->content = xmlStrdup(ns->href);
2913 	}
2914 	reader->curnode = reader->faketext;
2915     } else {
2916 	if (reader->curnode->next == NULL)
2917 	    return(0);
2918 	reader->curnode = reader->curnode->next;
2919     }
2920     return(1);
2921 }
2922 
2923 /**
2924  * xmlTextReaderConstEncoding:
2925  * @reader:  the xmlTextReaderPtr used
2926  *
2927  * Determine the encoding of the document being read.
2928  *
2929  * Returns a string containing the encoding of the document or NULL in
2930  * case of error.  The string is deallocated with the reader.
2931  */
2932 const xmlChar *
xmlTextReaderConstEncoding(xmlTextReaderPtr reader)2933 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2934     xmlDocPtr doc = NULL;
2935     if (reader == NULL)
2936 	return(NULL);
2937     if (reader->doc != NULL)
2938         doc = reader->doc;
2939     else if (reader->ctxt != NULL)
2940 	doc = reader->ctxt->myDoc;
2941     if (doc == NULL)
2942 	return(NULL);
2943 
2944     if (doc->encoding == NULL)
2945 	return(NULL);
2946     else
2947       return(CONSTSTR(doc->encoding));
2948 }
2949 
2950 
2951 /************************************************************************
2952  *									*
2953  *			Acces API to the current node			*
2954  *									*
2955  ************************************************************************/
2956 /**
2957  * xmlTextReaderAttributeCount:
2958  * @reader:  the xmlTextReaderPtr used
2959  *
2960  * Provides the number of attributes of the current node
2961  *
2962  * Returns 0 i no attributes, -1 in case of error or the attribute count
2963  */
2964 int
xmlTextReaderAttributeCount(xmlTextReaderPtr reader)2965 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2966     int ret;
2967     xmlAttrPtr attr;
2968     xmlNsPtr ns;
2969     xmlNodePtr node;
2970 
2971     if (reader == NULL)
2972 	return(-1);
2973     if (reader->node == NULL)
2974 	return(0);
2975 
2976     if (reader->curnode != NULL)
2977 	node = reader->curnode;
2978     else
2979 	node = reader->node;
2980 
2981     if (node->type != XML_ELEMENT_NODE)
2982 	return(0);
2983     if ((reader->state == XML_TEXTREADER_END) ||
2984 	(reader->state == XML_TEXTREADER_BACKTRACK))
2985 	return(0);
2986     ret = 0;
2987     attr = node->properties;
2988     while (attr != NULL) {
2989 	ret++;
2990 	attr = attr->next;
2991     }
2992     ns = node->nsDef;
2993     while (ns != NULL) {
2994 	ret++;
2995 	ns = ns->next;
2996     }
2997     return(ret);
2998 }
2999 
3000 /**
3001  * xmlTextReaderNodeType:
3002  * @reader:  the xmlTextReaderPtr used
3003  *
3004  * Get the node type of the current node
3005  * Reference:
3006  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
3007  *
3008  * Returns the xmlReaderTypes of the current node or -1 in case of error
3009  */
3010 int
xmlTextReaderNodeType(xmlTextReaderPtr reader)3011 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
3012     xmlNodePtr node;
3013 
3014     if (reader == NULL)
3015 	return(-1);
3016     if (reader->node == NULL)
3017 	return(XML_READER_TYPE_NONE);
3018     if (reader->curnode != NULL)
3019 	node = reader->curnode;
3020     else
3021 	node = reader->node;
3022     switch (node->type) {
3023         case XML_ELEMENT_NODE:
3024 	    if ((reader->state == XML_TEXTREADER_END) ||
3025 		(reader->state == XML_TEXTREADER_BACKTRACK))
3026 		return(XML_READER_TYPE_END_ELEMENT);
3027 	    return(XML_READER_TYPE_ELEMENT);
3028         case XML_NAMESPACE_DECL:
3029         case XML_ATTRIBUTE_NODE:
3030 	    return(XML_READER_TYPE_ATTRIBUTE);
3031         case XML_TEXT_NODE:
3032 	    if (xmlIsBlankNode(reader->node)) {
3033 		if (xmlNodeGetSpacePreserve(reader->node))
3034 		    return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3035 		else
3036 		    return(XML_READER_TYPE_WHITESPACE);
3037 	    } else {
3038 		return(XML_READER_TYPE_TEXT);
3039 	    }
3040         case XML_CDATA_SECTION_NODE:
3041 	    return(XML_READER_TYPE_CDATA);
3042         case XML_ENTITY_REF_NODE:
3043 	    return(XML_READER_TYPE_ENTITY_REFERENCE);
3044         case XML_ENTITY_NODE:
3045 	    return(XML_READER_TYPE_ENTITY);
3046         case XML_PI_NODE:
3047 	    return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3048         case XML_COMMENT_NODE:
3049 	    return(XML_READER_TYPE_COMMENT);
3050         case XML_DOCUMENT_NODE:
3051         case XML_HTML_DOCUMENT_NODE:
3052 #ifdef LIBXML_DOCB_ENABLED
3053         case XML_DOCB_DOCUMENT_NODE:
3054 #endif
3055 	    return(XML_READER_TYPE_DOCUMENT);
3056         case XML_DOCUMENT_FRAG_NODE:
3057 	    return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3058         case XML_NOTATION_NODE:
3059 	    return(XML_READER_TYPE_NOTATION);
3060         case XML_DOCUMENT_TYPE_NODE:
3061         case XML_DTD_NODE:
3062 	    return(XML_READER_TYPE_DOCUMENT_TYPE);
3063 
3064         case XML_ELEMENT_DECL:
3065         case XML_ATTRIBUTE_DECL:
3066         case XML_ENTITY_DECL:
3067         case XML_XINCLUDE_START:
3068         case XML_XINCLUDE_END:
3069 	    return(XML_READER_TYPE_NONE);
3070     }
3071     return(-1);
3072 }
3073 
3074 /**
3075  * xmlTextReaderIsEmptyElement:
3076  * @reader:  the xmlTextReaderPtr used
3077  *
3078  * Check if the current node is empty
3079  *
3080  * Returns 1 if empty, 0 if not and -1 in case of error
3081  */
3082 int
xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader)3083 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3084     if ((reader == NULL) || (reader->node == NULL))
3085 	return(-1);
3086     if (reader->node->type != XML_ELEMENT_NODE)
3087 	return(0);
3088     if (reader->curnode != NULL)
3089 	return(0);
3090     if (reader->node->children != NULL)
3091 	return(0);
3092     if (reader->state == XML_TEXTREADER_END)
3093 	return(0);
3094     if (reader->doc != NULL)
3095         return(1);
3096 #ifdef LIBXML_XINCLUDE_ENABLED
3097     if (reader->in_xinclude > 0)
3098         return(1);
3099 #endif
3100     return((reader->node->extra & NODE_IS_EMPTY) != 0);
3101 }
3102 
3103 /**
3104  * xmlTextReaderLocalName:
3105  * @reader:  the xmlTextReaderPtr used
3106  *
3107  * The local name of the node.
3108  *
3109  * Returns the local name or NULL if not available,
3110  *   if non NULL it need to be freed by the caller.
3111  */
3112 xmlChar *
xmlTextReaderLocalName(xmlTextReaderPtr reader)3113 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3114     xmlNodePtr node;
3115     if ((reader == NULL) || (reader->node == NULL))
3116 	return(NULL);
3117     if (reader->curnode != NULL)
3118 	node = reader->curnode;
3119     else
3120 	node = reader->node;
3121     if (node->type == XML_NAMESPACE_DECL) {
3122 	xmlNsPtr ns = (xmlNsPtr) node;
3123 	if (ns->prefix == NULL)
3124 	    return(xmlStrdup(BAD_CAST "xmlns"));
3125 	else
3126 	    return(xmlStrdup(ns->prefix));
3127     }
3128     if ((node->type != XML_ELEMENT_NODE) &&
3129 	(node->type != XML_ATTRIBUTE_NODE))
3130 	return(xmlTextReaderName(reader));
3131     return(xmlStrdup(node->name));
3132 }
3133 
3134 /**
3135  * xmlTextReaderConstLocalName:
3136  * @reader:  the xmlTextReaderPtr used
3137  *
3138  * The local name of the node.
3139  *
3140  * Returns the local name or NULL if not available, the
3141  *         string will be deallocated with the reader.
3142  */
3143 const xmlChar *
xmlTextReaderConstLocalName(xmlTextReaderPtr reader)3144 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3145     xmlNodePtr node;
3146     if ((reader == NULL) || (reader->node == NULL))
3147 	return(NULL);
3148     if (reader->curnode != NULL)
3149 	node = reader->curnode;
3150     else
3151 	node = reader->node;
3152     if (node->type == XML_NAMESPACE_DECL) {
3153 	xmlNsPtr ns = (xmlNsPtr) node;
3154 	if (ns->prefix == NULL)
3155 	    return(CONSTSTR(BAD_CAST "xmlns"));
3156 	else
3157 	    return(ns->prefix);
3158     }
3159     if ((node->type != XML_ELEMENT_NODE) &&
3160 	(node->type != XML_ATTRIBUTE_NODE))
3161 	return(xmlTextReaderConstName(reader));
3162     return(node->name);
3163 }
3164 
3165 /**
3166  * xmlTextReaderName:
3167  * @reader:  the xmlTextReaderPtr used
3168  *
3169  * The qualified name of the node, equal to Prefix :LocalName.
3170  *
3171  * Returns the local name or NULL if not available,
3172  *   if non NULL it need to be freed by the caller.
3173  */
3174 xmlChar *
xmlTextReaderName(xmlTextReaderPtr reader)3175 xmlTextReaderName(xmlTextReaderPtr reader) {
3176     xmlNodePtr node;
3177     xmlChar *ret;
3178 
3179     if ((reader == NULL) || (reader->node == NULL))
3180 	return(NULL);
3181     if (reader->curnode != NULL)
3182 	node = reader->curnode;
3183     else
3184 	node = reader->node;
3185     switch (node->type) {
3186         case XML_ELEMENT_NODE:
3187         case XML_ATTRIBUTE_NODE:
3188 	    if ((node->ns == NULL) ||
3189 		(node->ns->prefix == NULL))
3190 		return(xmlStrdup(node->name));
3191 
3192 	    ret = xmlStrdup(node->ns->prefix);
3193 	    ret = xmlStrcat(ret, BAD_CAST ":");
3194 	    ret = xmlStrcat(ret, node->name);
3195 	    return(ret);
3196         case XML_TEXT_NODE:
3197 	    return(xmlStrdup(BAD_CAST "#text"));
3198         case XML_CDATA_SECTION_NODE:
3199 	    return(xmlStrdup(BAD_CAST "#cdata-section"));
3200         case XML_ENTITY_NODE:
3201         case XML_ENTITY_REF_NODE:
3202 	    return(xmlStrdup(node->name));
3203         case XML_PI_NODE:
3204 	    return(xmlStrdup(node->name));
3205         case XML_COMMENT_NODE:
3206 	    return(xmlStrdup(BAD_CAST "#comment"));
3207         case XML_DOCUMENT_NODE:
3208         case XML_HTML_DOCUMENT_NODE:
3209 #ifdef LIBXML_DOCB_ENABLED
3210         case XML_DOCB_DOCUMENT_NODE:
3211 #endif
3212 	    return(xmlStrdup(BAD_CAST "#document"));
3213         case XML_DOCUMENT_FRAG_NODE:
3214 	    return(xmlStrdup(BAD_CAST "#document-fragment"));
3215         case XML_NOTATION_NODE:
3216 	    return(xmlStrdup(node->name));
3217         case XML_DOCUMENT_TYPE_NODE:
3218         case XML_DTD_NODE:
3219 	    return(xmlStrdup(node->name));
3220         case XML_NAMESPACE_DECL: {
3221 	    xmlNsPtr ns = (xmlNsPtr) node;
3222 
3223 	    ret = xmlStrdup(BAD_CAST "xmlns");
3224 	    if (ns->prefix == NULL)
3225 		return(ret);
3226 	    ret = xmlStrcat(ret, BAD_CAST ":");
3227 	    ret = xmlStrcat(ret, ns->prefix);
3228 	    return(ret);
3229 	}
3230 
3231         case XML_ELEMENT_DECL:
3232         case XML_ATTRIBUTE_DECL:
3233         case XML_ENTITY_DECL:
3234         case XML_XINCLUDE_START:
3235         case XML_XINCLUDE_END:
3236 	    return(NULL);
3237     }
3238     return(NULL);
3239 }
3240 
3241 /**
3242  * xmlTextReaderConstName:
3243  * @reader:  the xmlTextReaderPtr used
3244  *
3245  * The qualified name of the node, equal to Prefix :LocalName.
3246  *
3247  * Returns the local name or NULL if not available, the string is
3248  *         deallocated with the reader.
3249  */
3250 const xmlChar *
xmlTextReaderConstName(xmlTextReaderPtr reader)3251 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3252     xmlNodePtr node;
3253 
3254     if ((reader == NULL) || (reader->node == NULL))
3255 	return(NULL);
3256     if (reader->curnode != NULL)
3257 	node = reader->curnode;
3258     else
3259 	node = reader->node;
3260     switch (node->type) {
3261         case XML_ELEMENT_NODE:
3262         case XML_ATTRIBUTE_NODE:
3263 	    if ((node->ns == NULL) ||
3264 		(node->ns->prefix == NULL))
3265 		return(node->name);
3266 	    return(CONSTQSTR(node->ns->prefix, node->name));
3267         case XML_TEXT_NODE:
3268 	    return(CONSTSTR(BAD_CAST "#text"));
3269         case XML_CDATA_SECTION_NODE:
3270 	    return(CONSTSTR(BAD_CAST "#cdata-section"));
3271         case XML_ENTITY_NODE:
3272         case XML_ENTITY_REF_NODE:
3273 	    return(CONSTSTR(node->name));
3274         case XML_PI_NODE:
3275 	    return(CONSTSTR(node->name));
3276         case XML_COMMENT_NODE:
3277 	    return(CONSTSTR(BAD_CAST "#comment"));
3278         case XML_DOCUMENT_NODE:
3279         case XML_HTML_DOCUMENT_NODE:
3280 #ifdef LIBXML_DOCB_ENABLED
3281         case XML_DOCB_DOCUMENT_NODE:
3282 #endif
3283 	    return(CONSTSTR(BAD_CAST "#document"));
3284         case XML_DOCUMENT_FRAG_NODE:
3285 	    return(CONSTSTR(BAD_CAST "#document-fragment"));
3286         case XML_NOTATION_NODE:
3287 	    return(CONSTSTR(node->name));
3288         case XML_DOCUMENT_TYPE_NODE:
3289         case XML_DTD_NODE:
3290 	    return(CONSTSTR(node->name));
3291         case XML_NAMESPACE_DECL: {
3292 	    xmlNsPtr ns = (xmlNsPtr) node;
3293 
3294 	    if (ns->prefix == NULL)
3295 		return(CONSTSTR(BAD_CAST "xmlns"));
3296 	    return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3297 	}
3298 
3299         case XML_ELEMENT_DECL:
3300         case XML_ATTRIBUTE_DECL:
3301         case XML_ENTITY_DECL:
3302         case XML_XINCLUDE_START:
3303         case XML_XINCLUDE_END:
3304 	    return(NULL);
3305     }
3306     return(NULL);
3307 }
3308 
3309 /**
3310  * xmlTextReaderPrefix:
3311  * @reader:  the xmlTextReaderPtr used
3312  *
3313  * A shorthand reference to the namespace associated with the node.
3314  *
3315  * Returns the prefix or NULL if not available,
3316  *    if non NULL it need to be freed by the caller.
3317  */
3318 xmlChar *
xmlTextReaderPrefix(xmlTextReaderPtr reader)3319 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3320     xmlNodePtr node;
3321     if ((reader == NULL) || (reader->node == NULL))
3322 	return(NULL);
3323     if (reader->curnode != NULL)
3324 	node = reader->curnode;
3325     else
3326 	node = reader->node;
3327     if (node->type == XML_NAMESPACE_DECL) {
3328 	xmlNsPtr ns = (xmlNsPtr) node;
3329 	if (ns->prefix == NULL)
3330 	    return(NULL);
3331 	return(xmlStrdup(BAD_CAST "xmlns"));
3332     }
3333     if ((node->type != XML_ELEMENT_NODE) &&
3334 	(node->type != XML_ATTRIBUTE_NODE))
3335 	return(NULL);
3336     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3337 	return(xmlStrdup(node->ns->prefix));
3338     return(NULL);
3339 }
3340 
3341 /**
3342  * xmlTextReaderConstPrefix:
3343  * @reader:  the xmlTextReaderPtr used
3344  *
3345  * A shorthand reference to the namespace associated with the node.
3346  *
3347  * Returns the prefix or NULL if not available, the string is deallocated
3348  *         with the reader.
3349  */
3350 const xmlChar *
xmlTextReaderConstPrefix(xmlTextReaderPtr reader)3351 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3352     xmlNodePtr node;
3353     if ((reader == NULL) || (reader->node == NULL))
3354 	return(NULL);
3355     if (reader->curnode != NULL)
3356 	node = reader->curnode;
3357     else
3358 	node = reader->node;
3359     if (node->type == XML_NAMESPACE_DECL) {
3360 	xmlNsPtr ns = (xmlNsPtr) node;
3361 	if (ns->prefix == NULL)
3362 	    return(NULL);
3363 	return(CONSTSTR(BAD_CAST "xmlns"));
3364     }
3365     if ((node->type != XML_ELEMENT_NODE) &&
3366 	(node->type != XML_ATTRIBUTE_NODE))
3367 	return(NULL);
3368     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3369 	return(CONSTSTR(node->ns->prefix));
3370     return(NULL);
3371 }
3372 
3373 /**
3374  * xmlTextReaderNamespaceUri:
3375  * @reader:  the xmlTextReaderPtr used
3376  *
3377  * The URI defining the namespace associated with the node.
3378  *
3379  * Returns the namespace URI or NULL if not available,
3380  *    if non NULL it need to be freed by the caller.
3381  */
3382 xmlChar *
xmlTextReaderNamespaceUri(xmlTextReaderPtr reader)3383 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3384     xmlNodePtr node;
3385     if ((reader == NULL) || (reader->node == NULL))
3386 	return(NULL);
3387     if (reader->curnode != NULL)
3388 	node = reader->curnode;
3389     else
3390 	node = reader->node;
3391     if (node->type == XML_NAMESPACE_DECL)
3392 	return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3393     if ((node->type != XML_ELEMENT_NODE) &&
3394 	(node->type != XML_ATTRIBUTE_NODE))
3395 	return(NULL);
3396     if (node->ns != NULL)
3397 	return(xmlStrdup(node->ns->href));
3398     return(NULL);
3399 }
3400 
3401 /**
3402  * xmlTextReaderConstNamespaceUri:
3403  * @reader:  the xmlTextReaderPtr used
3404  *
3405  * The URI defining the namespace associated with the node.
3406  *
3407  * Returns the namespace URI or NULL if not available, the string
3408  *         will be deallocated with the reader
3409  */
3410 const xmlChar *
xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader)3411 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3412     xmlNodePtr node;
3413     if ((reader == NULL) || (reader->node == NULL))
3414 	return(NULL);
3415     if (reader->curnode != NULL)
3416 	node = reader->curnode;
3417     else
3418 	node = reader->node;
3419     if (node->type == XML_NAMESPACE_DECL)
3420 	return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3421     if ((node->type != XML_ELEMENT_NODE) &&
3422 	(node->type != XML_ATTRIBUTE_NODE))
3423 	return(NULL);
3424     if (node->ns != NULL)
3425 	return(CONSTSTR(node->ns->href));
3426     return(NULL);
3427 }
3428 
3429 /**
3430  * xmlTextReaderBaseUri:
3431  * @reader:  the xmlTextReaderPtr used
3432  *
3433  * The base URI of the node.
3434  *
3435  * Returns the base URI or NULL if not available,
3436  *    if non NULL it need to be freed by the caller.
3437  */
3438 xmlChar *
xmlTextReaderBaseUri(xmlTextReaderPtr reader)3439 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3440     if ((reader == NULL) || (reader->node == NULL))
3441 	return(NULL);
3442     return(xmlNodeGetBase(NULL, reader->node));
3443 }
3444 
3445 /**
3446  * xmlTextReaderConstBaseUri:
3447  * @reader:  the xmlTextReaderPtr used
3448  *
3449  * The base URI of the node.
3450  *
3451  * Returns the base URI or NULL if not available, the string
3452  *         will be deallocated with the reader
3453  */
3454 const xmlChar *
xmlTextReaderConstBaseUri(xmlTextReaderPtr reader)3455 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3456     xmlChar *tmp;
3457     const xmlChar *ret;
3458 
3459     if ((reader == NULL) || (reader->node == NULL))
3460 	return(NULL);
3461     tmp = xmlNodeGetBase(NULL, reader->node);
3462     if (tmp == NULL)
3463         return(NULL);
3464     ret = CONSTSTR(tmp);
3465     xmlFree(tmp);
3466     return(ret);
3467 }
3468 
3469 /**
3470  * xmlTextReaderDepth:
3471  * @reader:  the xmlTextReaderPtr used
3472  *
3473  * The depth of the node in the tree.
3474  *
3475  * Returns the depth or -1 in case of error
3476  */
3477 int
xmlTextReaderDepth(xmlTextReaderPtr reader)3478 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3479     if (reader == NULL)
3480 	return(-1);
3481     if (reader->node == NULL)
3482 	return(0);
3483 
3484     if (reader->curnode != NULL) {
3485 	if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3486 	    (reader->curnode->type == XML_NAMESPACE_DECL))
3487 	    return(reader->depth + 1);
3488 	return(reader->depth + 2);
3489     }
3490     return(reader->depth);
3491 }
3492 
3493 /**
3494  * xmlTextReaderHasAttributes:
3495  * @reader:  the xmlTextReaderPtr used
3496  *
3497  * Whether the node has attributes.
3498  *
3499  * Returns 1 if true, 0 if false, and -1 in case or error
3500  */
3501 int
xmlTextReaderHasAttributes(xmlTextReaderPtr reader)3502 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3503     xmlNodePtr node;
3504     if (reader == NULL)
3505 	return(-1);
3506     if (reader->node == NULL)
3507 	return(0);
3508     if (reader->curnode != NULL)
3509 	node = reader->curnode;
3510     else
3511 	node = reader->node;
3512 
3513     if ((node->type == XML_ELEMENT_NODE) &&
3514 	((node->properties != NULL) || (node->nsDef != NULL)))
3515 	return(1);
3516     /* TODO: handle the xmlDecl */
3517     return(0);
3518 }
3519 
3520 /**
3521  * xmlTextReaderHasValue:
3522  * @reader:  the xmlTextReaderPtr used
3523  *
3524  * Whether the node can have a text value.
3525  *
3526  * Returns 1 if true, 0 if false, and -1 in case or error
3527  */
3528 int
xmlTextReaderHasValue(xmlTextReaderPtr reader)3529 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3530     xmlNodePtr node;
3531     if (reader == NULL)
3532 	return(-1);
3533     if (reader->node == NULL)
3534 	return(0);
3535     if (reader->curnode != NULL)
3536 	node = reader->curnode;
3537     else
3538 	node = reader->node;
3539 
3540     switch (node->type) {
3541         case XML_ATTRIBUTE_NODE:
3542         case XML_TEXT_NODE:
3543         case XML_CDATA_SECTION_NODE:
3544         case XML_PI_NODE:
3545         case XML_COMMENT_NODE:
3546         case XML_NAMESPACE_DECL:
3547 	    return(1);
3548 	default:
3549 	    break;
3550     }
3551     return(0);
3552 }
3553 
3554 /**
3555  * xmlTextReaderValue:
3556  * @reader:  the xmlTextReaderPtr used
3557  *
3558  * Provides the text value of the node if present
3559  *
3560  * Returns the string or NULL if not available. The result must be deallocated
3561  *     with xmlFree()
3562  */
3563 xmlChar *
xmlTextReaderValue(xmlTextReaderPtr reader)3564 xmlTextReaderValue(xmlTextReaderPtr reader) {
3565     xmlNodePtr node;
3566     if (reader == NULL)
3567 	return(NULL);
3568     if (reader->node == NULL)
3569 	return(NULL);
3570     if (reader->curnode != NULL)
3571 	node = reader->curnode;
3572     else
3573 	node = reader->node;
3574 
3575     switch (node->type) {
3576         case XML_NAMESPACE_DECL:
3577 	    return(xmlStrdup(((xmlNsPtr) node)->href));
3578         case XML_ATTRIBUTE_NODE:{
3579 	    xmlAttrPtr attr = (xmlAttrPtr) node;
3580 
3581 	    if (attr->parent != NULL)
3582 		return (xmlNodeListGetString
3583 			(attr->parent->doc, attr->children, 1));
3584 	    else
3585 		return (xmlNodeListGetString(NULL, attr->children, 1));
3586 	    break;
3587 	}
3588         case XML_TEXT_NODE:
3589         case XML_CDATA_SECTION_NODE:
3590         case XML_PI_NODE:
3591         case XML_COMMENT_NODE:
3592             if (node->content != NULL)
3593                 return (xmlStrdup(node->content));
3594 	default:
3595 	    break;
3596     }
3597     return(NULL);
3598 }
3599 
3600 /**
3601  * xmlTextReaderConstValue:
3602  * @reader:  the xmlTextReaderPtr used
3603  *
3604  * Provides the text value of the node if present
3605  *
3606  * Returns the string or NULL if not available. The result will be
3607  *     deallocated on the next Read() operation.
3608  */
3609 const xmlChar *
xmlTextReaderConstValue(xmlTextReaderPtr reader)3610 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3611     xmlNodePtr node;
3612     if (reader == NULL)
3613 	return(NULL);
3614     if (reader->node == NULL)
3615 	return(NULL);
3616     if (reader->curnode != NULL)
3617 	node = reader->curnode;
3618     else
3619 	node = reader->node;
3620 
3621     switch (node->type) {
3622         case XML_NAMESPACE_DECL:
3623 	    return(((xmlNsPtr) node)->href);
3624         case XML_ATTRIBUTE_NODE:{
3625 	    xmlAttrPtr attr = (xmlAttrPtr) node;
3626 	    const xmlChar *ret;
3627 
3628 	    if ((attr->children != NULL) &&
3629 	        (attr->children->type == XML_TEXT_NODE) &&
3630 		(attr->children->next == NULL))
3631 		return(attr->children->content);
3632 	    else {
3633 		if (reader->buffer == NULL) {
3634 		    reader->buffer = xmlBufCreateSize(100);
3635                     if (reader->buffer == NULL) {
3636                         xmlGenericError(xmlGenericErrorContext,
3637                                         "xmlTextReaderSetup : malloc failed\n");
3638                         return (NULL);
3639                     }
3640 		    xmlBufSetAllocationScheme(reader->buffer,
3641 		                              XML_BUFFER_ALLOC_BOUNDED);
3642                 } else
3643                     xmlBufEmpty(reader->buffer);
3644 	        xmlBufGetNodeContent(reader->buffer, node);
3645 		ret = xmlBufContent(reader->buffer);
3646 		if (ret == NULL) {
3647 		    /* error on the buffer best to reallocate */
3648 		    xmlBufFree(reader->buffer);
3649 		    reader->buffer = xmlBufCreateSize(100);
3650 		    xmlBufSetAllocationScheme(reader->buffer,
3651 		                              XML_BUFFER_ALLOC_BOUNDED);
3652 		    ret = BAD_CAST "";
3653 		}
3654 		return(ret);
3655 	    }
3656 	    break;
3657 	}
3658         case XML_TEXT_NODE:
3659         case XML_CDATA_SECTION_NODE:
3660         case XML_PI_NODE:
3661         case XML_COMMENT_NODE:
3662 	    return(node->content);
3663 	default:
3664 	    break;
3665     }
3666     return(NULL);
3667 }
3668 
3669 /**
3670  * xmlTextReaderIsDefault:
3671  * @reader:  the xmlTextReaderPtr used
3672  *
3673  * Whether an Attribute  node was generated from the default value
3674  * defined in the DTD or schema.
3675  *
3676  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3677  */
3678 int
xmlTextReaderIsDefault(xmlTextReaderPtr reader)3679 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3680     if (reader == NULL)
3681 	return(-1);
3682     return(0);
3683 }
3684 
3685 /**
3686  * xmlTextReaderQuoteChar:
3687  * @reader:  the xmlTextReaderPtr used
3688  *
3689  * The quotation mark character used to enclose the value of an attribute.
3690  *
3691  * Returns " or ' and -1 in case of error
3692  */
3693 int
xmlTextReaderQuoteChar(xmlTextReaderPtr reader)3694 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3695     if (reader == NULL)
3696 	return(-1);
3697     /* TODO maybe lookup the attribute value for " first */
3698     return((int) '"');
3699 }
3700 
3701 /**
3702  * xmlTextReaderXmlLang:
3703  * @reader:  the xmlTextReaderPtr used
3704  *
3705  * The xml:lang scope within which the node resides.
3706  *
3707  * Returns the xml:lang value or NULL if none exists.,
3708  *    if non NULL it need to be freed by the caller.
3709  */
3710 xmlChar *
xmlTextReaderXmlLang(xmlTextReaderPtr reader)3711 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3712     if (reader == NULL)
3713 	return(NULL);
3714     if (reader->node == NULL)
3715 	return(NULL);
3716     return(xmlNodeGetLang(reader->node));
3717 }
3718 
3719 /**
3720  * xmlTextReaderConstXmlLang:
3721  * @reader:  the xmlTextReaderPtr used
3722  *
3723  * The xml:lang scope within which the node resides.
3724  *
3725  * Returns the xml:lang value or NULL if none exists.
3726  */
3727 const xmlChar *
xmlTextReaderConstXmlLang(xmlTextReaderPtr reader)3728 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3729     xmlChar *tmp;
3730     const xmlChar *ret;
3731 
3732     if (reader == NULL)
3733 	return(NULL);
3734     if (reader->node == NULL)
3735 	return(NULL);
3736     tmp = xmlNodeGetLang(reader->node);
3737     if (tmp == NULL)
3738         return(NULL);
3739     ret = CONSTSTR(tmp);
3740     xmlFree(tmp);
3741     return(ret);
3742 }
3743 
3744 /**
3745  * xmlTextReaderConstString:
3746  * @reader:  the xmlTextReaderPtr used
3747  * @str:  the string to intern.
3748  *
3749  * Get an interned string from the reader, allows for example to
3750  * speedup string name comparisons
3751  *
3752  * Returns an interned copy of the string or NULL in case of error. The
3753  *         string will be deallocated with the reader.
3754  */
3755 const xmlChar *
xmlTextReaderConstString(xmlTextReaderPtr reader,const xmlChar * str)3756 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3757     if (reader == NULL)
3758 	return(NULL);
3759     return(CONSTSTR(str));
3760 }
3761 
3762 /**
3763  * xmlTextReaderNormalization:
3764  * @reader:  the xmlTextReaderPtr used
3765  *
3766  * The value indicating whether to normalize white space and attribute values.
3767  * Since attribute value and end of line normalizations are a MUST in the XML
3768  * specification only the value true is accepted. The broken bahaviour of
3769  * accepting out of range character entities like &#0; is of course not
3770  * supported either.
3771  *
3772  * Returns 1 or -1 in case of error.
3773  */
3774 int
xmlTextReaderNormalization(xmlTextReaderPtr reader)3775 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3776     if (reader == NULL)
3777 	return(-1);
3778     return(1);
3779 }
3780 
3781 /************************************************************************
3782  *									*
3783  *			Extensions to the base APIs			*
3784  *									*
3785  ************************************************************************/
3786 
3787 /**
3788  * xmlTextReaderSetParserProp:
3789  * @reader:  the xmlTextReaderPtr used
3790  * @prop:  the xmlParserProperties to set
3791  * @value:  usually 0 or 1 to (de)activate it
3792  *
3793  * Change the parser processing behaviour by changing some of its internal
3794  * properties. Note that some properties can only be changed before any
3795  * read has been done.
3796  *
3797  * Returns 0 if the call was successful, or -1 in case of error
3798  */
3799 int
xmlTextReaderSetParserProp(xmlTextReaderPtr reader,int prop,int value)3800 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3801     xmlParserProperties p = (xmlParserProperties) prop;
3802     xmlParserCtxtPtr ctxt;
3803 
3804     if ((reader == NULL) || (reader->ctxt == NULL))
3805 	return(-1);
3806     ctxt = reader->ctxt;
3807 
3808     switch (p) {
3809         case XML_PARSER_LOADDTD:
3810 	    if (value != 0) {
3811 		if (ctxt->loadsubset == 0) {
3812 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3813 			return(-1);
3814 		    ctxt->loadsubset = XML_DETECT_IDS;
3815 		}
3816 	    } else {
3817 		ctxt->loadsubset = 0;
3818 	    }
3819 	    return(0);
3820         case XML_PARSER_DEFAULTATTRS:
3821 	    if (value != 0) {
3822 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3823 	    } else {
3824 		if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3825 		    ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3826 	    }
3827 	    return(0);
3828         case XML_PARSER_VALIDATE:
3829 	    if (value != 0) {
3830 		ctxt->validate = 1;
3831 		reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3832 	    } else {
3833 		ctxt->validate = 0;
3834 	    }
3835 	    return(0);
3836         case XML_PARSER_SUBST_ENTITIES:
3837 	    if (value != 0) {
3838 		ctxt->replaceEntities = 1;
3839 	    } else {
3840 		ctxt->replaceEntities = 0;
3841 	    }
3842 	    return(0);
3843     }
3844     return(-1);
3845 }
3846 
3847 /**
3848  * xmlTextReaderGetParserProp:
3849  * @reader:  the xmlTextReaderPtr used
3850  * @prop:  the xmlParserProperties to get
3851  *
3852  * Read the parser internal property.
3853  *
3854  * Returns the value, usually 0 or 1, or -1 in case of error.
3855  */
3856 int
xmlTextReaderGetParserProp(xmlTextReaderPtr reader,int prop)3857 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3858     xmlParserProperties p = (xmlParserProperties) prop;
3859     xmlParserCtxtPtr ctxt;
3860 
3861     if ((reader == NULL) || (reader->ctxt == NULL))
3862 	return(-1);
3863     ctxt = reader->ctxt;
3864 
3865     switch (p) {
3866         case XML_PARSER_LOADDTD:
3867 	    if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3868 		return(1);
3869 	    return(0);
3870         case XML_PARSER_DEFAULTATTRS:
3871 	    if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3872 		return(1);
3873 	    return(0);
3874         case XML_PARSER_VALIDATE:
3875 	    return(reader->validate);
3876 	case XML_PARSER_SUBST_ENTITIES:
3877 	    return(ctxt->replaceEntities);
3878     }
3879     return(-1);
3880 }
3881 
3882 
3883 /**
3884  * xmlTextReaderGetParserLineNumber:
3885  * @reader: the user data (XML reader context)
3886  *
3887  * Provide the line number of the current parsing point.
3888  *
3889  * Returns an int or 0 if not available
3890  */
3891 int
xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)3892 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3893 {
3894     if ((reader == NULL) || (reader->ctxt == NULL) ||
3895         (reader->ctxt->input == NULL)) {
3896         return (0);
3897     }
3898     return (reader->ctxt->input->line);
3899 }
3900 
3901 /**
3902  * xmlTextReaderGetParserColumnNumber:
3903  * @reader: the user data (XML reader context)
3904  *
3905  * Provide the column number of the current parsing point.
3906  *
3907  * Returns an int or 0 if not available
3908  */
3909 int
xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)3910 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3911 {
3912     if ((reader == NULL) || (reader->ctxt == NULL) ||
3913         (reader->ctxt->input == NULL)) {
3914         return (0);
3915     }
3916     return (reader->ctxt->input->col);
3917 }
3918 
3919 /**
3920  * xmlTextReaderCurrentNode:
3921  * @reader:  the xmlTextReaderPtr used
3922  *
3923  * Hacking interface allowing to get the xmlNodePtr correponding to the
3924  * current node being accessed by the xmlTextReader. This is dangerous
3925  * because the underlying node may be destroyed on the next Reads.
3926  *
3927  * Returns the xmlNodePtr or NULL in case of error.
3928  */
3929 xmlNodePtr
xmlTextReaderCurrentNode(xmlTextReaderPtr reader)3930 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3931     if (reader == NULL)
3932 	return(NULL);
3933 
3934     if (reader->curnode != NULL)
3935 	return(reader->curnode);
3936     return(reader->node);
3937 }
3938 
3939 /**
3940  * xmlTextReaderPreserve:
3941  * @reader:  the xmlTextReaderPtr used
3942  *
3943  * This tells the XML Reader to preserve the current node.
3944  * The caller must also use xmlTextReaderCurrentDoc() to
3945  * keep an handle on the resulting document once parsing has finished
3946  *
3947  * Returns the xmlNodePtr or NULL in case of error.
3948  */
3949 xmlNodePtr
xmlTextReaderPreserve(xmlTextReaderPtr reader)3950 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3951     xmlNodePtr cur, parent;
3952 
3953     if (reader == NULL)
3954 	return(NULL);
3955 
3956     if (reader->curnode != NULL)
3957         cur = reader->curnode;
3958     else
3959         cur = reader->node;
3960     if (cur == NULL)
3961         return(NULL);
3962 
3963     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3964 	cur->extra |= NODE_IS_PRESERVED;
3965 	cur->extra |= NODE_IS_SPRESERVED;
3966     }
3967     reader->preserves++;
3968 
3969     parent = cur->parent;;
3970     while (parent != NULL) {
3971         if (parent->type == XML_ELEMENT_NODE)
3972 	    parent->extra |= NODE_IS_PRESERVED;
3973 	parent = parent->parent;
3974     }
3975     return(cur);
3976 }
3977 
3978 #ifdef LIBXML_PATTERN_ENABLED
3979 /**
3980  * xmlTextReaderPreservePattern:
3981  * @reader:  the xmlTextReaderPtr used
3982  * @pattern:  an XPath subset pattern
3983  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3984  *
3985  * This tells the XML Reader to preserve all nodes matched by the
3986  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3987  * keep an handle on the resulting document once parsing has finished
3988  *
3989  * Returns a non-negative number in case of success and -1 in case of error
3990  */
3991 int
xmlTextReaderPreservePattern(xmlTextReaderPtr reader,const xmlChar * pattern,const xmlChar ** namespaces)3992 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3993                              const xmlChar **namespaces)
3994 {
3995     xmlPatternPtr comp;
3996 
3997     if ((reader == NULL) || (pattern == NULL))
3998 	return(-1);
3999 
4000     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
4001     if (comp == NULL)
4002         return(-1);
4003 
4004     if (reader->patternMax <= 0) {
4005 	reader->patternMax = 4;
4006 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4007 					      sizeof(reader->patternTab[0]));
4008         if (reader->patternTab == NULL) {
4009             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4010             return (-1);
4011         }
4012     }
4013     if (reader->patternNr >= reader->patternMax) {
4014         xmlPatternPtr *tmp;
4015         reader->patternMax *= 2;
4016 	tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4017                                       reader->patternMax *
4018                                       sizeof(reader->patternTab[0]));
4019         if (tmp == NULL) {
4020             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4021 	    reader->patternMax /= 2;
4022             return (-1);
4023         }
4024 	reader->patternTab = tmp;
4025     }
4026     reader->patternTab[reader->patternNr] = comp;
4027     return(reader->patternNr++);
4028 }
4029 #endif
4030 
4031 /**
4032  * xmlTextReaderCurrentDoc:
4033  * @reader:  the xmlTextReaderPtr used
4034  *
4035  * Hacking interface allowing to get the xmlDocPtr correponding to the
4036  * current document being accessed by the xmlTextReader.
4037  * NOTE: as a result of this call, the reader will not destroy the
4038  *       associated XML document and calling xmlFreeDoc() on the result
4039  *       is needed once the reader parsing has finished.
4040  *
4041  * Returns the xmlDocPtr or NULL in case of error.
4042  */
4043 xmlDocPtr
xmlTextReaderCurrentDoc(xmlTextReaderPtr reader)4044 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4045     if (reader == NULL)
4046 	return(NULL);
4047     if (reader->doc != NULL)
4048         return(reader->doc);
4049     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4050 	return(NULL);
4051 
4052     reader->preserve = 1;
4053     return(reader->ctxt->myDoc);
4054 }
4055 
4056 #ifdef LIBXML_SCHEMAS_ENABLED
4057 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
4058 
4059 static void XMLCDECL
4060 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4061 
4062 static void XMLCDECL
4063 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4064 
4065 static void XMLCDECL
4066 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4067 
4068 static void XMLCDECL
4069 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4070 
4071 static void XMLCDECL
xmlTextReaderValidityErrorRelay(void * ctx,const char * msg,...)4072 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4073 {
4074     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4075 
4076     char *str;
4077 
4078     va_list ap;
4079 
4080     va_start(ap, msg);
4081     str = xmlTextReaderBuildMessage(msg, ap);
4082     if (!reader->errorFunc) {
4083         xmlTextReaderValidityError(ctx, "%s", str);
4084     } else {
4085         reader->errorFunc(reader->errorFuncArg, str,
4086                           XML_PARSER_SEVERITY_VALIDITY_ERROR,
4087                           NULL /* locator */ );
4088     }
4089     if (str != NULL)
4090         xmlFree(str);
4091     va_end(ap);
4092 }
4093 
4094 static void XMLCDECL
xmlTextReaderValidityWarningRelay(void * ctx,const char * msg,...)4095 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4096 {
4097     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4098 
4099     char *str;
4100 
4101     va_list ap;
4102 
4103     va_start(ap, msg);
4104     str = xmlTextReaderBuildMessage(msg, ap);
4105     if (!reader->errorFunc) {
4106         xmlTextReaderValidityWarning(ctx, "%s", str);
4107     } else {
4108         reader->errorFunc(reader->errorFuncArg, str,
4109                           XML_PARSER_SEVERITY_VALIDITY_WARNING,
4110                           NULL /* locator */ );
4111     }
4112     if (str != NULL)
4113         xmlFree(str);
4114     va_end(ap);
4115 }
4116 
4117 static void
4118   xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4119 
4120 static void
xmlTextReaderValidityStructuredRelay(void * userData,xmlErrorPtr error)4121 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4122 {
4123     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4124 
4125     if (reader->sErrorFunc) {
4126         reader->sErrorFunc(reader->errorFuncArg, error);
4127     } else {
4128         xmlTextReaderStructuredError(reader, error);
4129     }
4130 }
4131 /**
4132  * xmlTextReaderRelaxNGSetSchema:
4133  * @reader:  the xmlTextReaderPtr used
4134  * @schema:  a precompiled RelaxNG schema
4135  *
4136  * Use RelaxNG to validate the document as it is processed.
4137  * Activation is only possible before the first Read().
4138  * if @schema is NULL, then RelaxNG validation is desactivated.
4139  @ The @schema should not be freed until the reader is deallocated
4140  * or its use has been deactivated.
4141  *
4142  * Returns 0 in case the RelaxNG validation could be (des)activated and
4143  *         -1 in case of error.
4144  */
4145 int
xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader,xmlRelaxNGPtr schema)4146 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4147     if (reader == NULL)
4148         return(-1);
4149     if (schema == NULL) {
4150         if (reader->rngSchemas != NULL) {
4151 	    xmlRelaxNGFree(reader->rngSchemas);
4152 	    reader->rngSchemas = NULL;
4153 	}
4154         if (reader->rngValidCtxt != NULL) {
4155 	    if (! reader->rngPreserveCtxt)
4156 		xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4157 	    reader->rngValidCtxt = NULL;
4158         }
4159 	reader->rngPreserveCtxt = 0;
4160 	return(0);
4161     }
4162     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4163 	return(-1);
4164     if (reader->rngSchemas != NULL) {
4165 	xmlRelaxNGFree(reader->rngSchemas);
4166 	reader->rngSchemas = NULL;
4167     }
4168     if (reader->rngValidCtxt != NULL) {
4169 	if (! reader->rngPreserveCtxt)
4170 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4171 	reader->rngValidCtxt = NULL;
4172     }
4173     reader->rngPreserveCtxt = 0;
4174     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4175     if (reader->rngValidCtxt == NULL)
4176         return(-1);
4177     if (reader->errorFunc != NULL) {
4178 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4179 			xmlTextReaderValidityErrorRelay,
4180 			xmlTextReaderValidityWarningRelay,
4181 			reader);
4182     }
4183 	if (reader->sErrorFunc != NULL) {
4184 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4185 			xmlTextReaderValidityStructuredRelay,
4186 			reader);
4187     }
4188     reader->rngValidErrors = 0;
4189     reader->rngFullNode = NULL;
4190     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4191     return(0);
4192 }
4193 
4194 /**
4195  * xmlTextReaderLocator:
4196  * @ctx: the xmlTextReaderPtr used
4197  * @file: returned file information
4198  * @line: returned line information
4199  *
4200  * Internal locator function for the readers
4201  *
4202  * Returns 0 in case the Schema validation could be (des)activated and
4203  *         -1 in case of error.
4204  */
4205 static int
xmlTextReaderLocator(void * ctx,const char ** file,unsigned long * line)4206 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4207     xmlTextReaderPtr reader;
4208 
4209     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4210         return(-1);
4211 
4212     if (file != NULL)
4213         *file = NULL;
4214     if (line != NULL)
4215         *line = 0;
4216 
4217     reader = (xmlTextReaderPtr) ctx;
4218     if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4219 	if (file != NULL)
4220 	    *file = reader->ctxt->input->filename;
4221 	if (line != NULL)
4222 	    *line = reader->ctxt->input->line;
4223 	return(0);
4224     }
4225     if (reader->node != NULL) {
4226         long res;
4227 	int ret = 0;
4228 
4229 	if (line != NULL) {
4230 	    res = xmlGetLineNo(reader->node);
4231 	    if (res > 0)
4232 	        *line = (unsigned long) res;
4233 	    else
4234                 ret = -1;
4235 	}
4236         if (file != NULL) {
4237 	    xmlDocPtr doc = reader->node->doc;
4238 	    if ((doc != NULL) && (doc->URL != NULL))
4239 	        *file = (const char *) doc->URL;
4240 	    else
4241                 ret = -1;
4242 	}
4243 	return(ret);
4244     }
4245     return(-1);
4246 }
4247 
4248 /**
4249  * xmlTextReaderSetSchema:
4250  * @reader:  the xmlTextReaderPtr used
4251  * @schema:  a precompiled Schema schema
4252  *
4253  * Use XSD Schema to validate the document as it is processed.
4254  * Activation is only possible before the first Read().
4255  * if @schema is NULL, then Schema validation is desactivated.
4256  @ The @schema should not be freed until the reader is deallocated
4257  * or its use has been deactivated.
4258  *
4259  * Returns 0 in case the Schema validation could be (des)activated and
4260  *         -1 in case of error.
4261  */
4262 int
xmlTextReaderSetSchema(xmlTextReaderPtr reader,xmlSchemaPtr schema)4263 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4264     if (reader == NULL)
4265         return(-1);
4266     if (schema == NULL) {
4267 	if (reader->xsdPlug != NULL) {
4268 	    xmlSchemaSAXUnplug(reader->xsdPlug);
4269 	    reader->xsdPlug = NULL;
4270 	}
4271         if (reader->xsdValidCtxt != NULL) {
4272 	    if (! reader->xsdPreserveCtxt)
4273 		xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4274 	    reader->xsdValidCtxt = NULL;
4275         }
4276 	reader->xsdPreserveCtxt = 0;
4277         if (reader->xsdSchemas != NULL) {
4278 	    xmlSchemaFree(reader->xsdSchemas);
4279 	    reader->xsdSchemas = NULL;
4280 	}
4281 	return(0);
4282     }
4283     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4284 	return(-1);
4285     if (reader->xsdPlug != NULL) {
4286 	xmlSchemaSAXUnplug(reader->xsdPlug);
4287 	reader->xsdPlug = NULL;
4288     }
4289     if (reader->xsdValidCtxt != NULL) {
4290 	if (! reader->xsdPreserveCtxt)
4291 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4292 	reader->xsdValidCtxt = NULL;
4293     }
4294     reader->xsdPreserveCtxt = 0;
4295     if (reader->xsdSchemas != NULL) {
4296 	xmlSchemaFree(reader->xsdSchemas);
4297 	reader->xsdSchemas = NULL;
4298     }
4299     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4300     if (reader->xsdValidCtxt == NULL) {
4301 	xmlSchemaFree(reader->xsdSchemas);
4302 	reader->xsdSchemas = NULL;
4303         return(-1);
4304     }
4305     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4306                                        &(reader->ctxt->sax),
4307 				       &(reader->ctxt->userData));
4308     if (reader->xsdPlug == NULL) {
4309 	xmlSchemaFree(reader->xsdSchemas);
4310 	reader->xsdSchemas = NULL;
4311 	xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4312 	reader->xsdValidCtxt = NULL;
4313 	return(-1);
4314     }
4315     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4316                                 xmlTextReaderLocator,
4317 				(void *) reader);
4318 
4319     if (reader->errorFunc != NULL) {
4320 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4321 			xmlTextReaderValidityErrorRelay,
4322 			xmlTextReaderValidityWarningRelay,
4323 			reader);
4324     }
4325 	if (reader->sErrorFunc != NULL) {
4326 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4327 			xmlTextReaderValidityStructuredRelay,
4328 			reader);
4329     }
4330     reader->xsdValidErrors = 0;
4331     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4332     return(0);
4333 }
4334 
4335 /**
4336  * xmlTextReaderRelaxNGValidateInternal:
4337  * @reader:  the xmlTextReaderPtr used
4338  * @rng:  the path to a RelaxNG schema or NULL
4339  * @ctxt: the RelaxNG schema validation context or NULL
4340  * @options: options (not yet used)
4341  *
4342  * Use RelaxNG to validate the document as it is processed.
4343  * Activation is only possible before the first Read().
4344  * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4345  *
4346  * Returns 0 in case the RelaxNG validation could be (de)activated and
4347  *	   -1 in case of error.
4348  */
4349 static int
xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,const char * rng,xmlRelaxNGValidCtxtPtr ctxt,int options ATTRIBUTE_UNUSED)4350 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4351 				     const char *rng,
4352 				     xmlRelaxNGValidCtxtPtr ctxt,
4353 				     int options ATTRIBUTE_UNUSED)
4354 {
4355     if (reader == NULL)
4356 	return(-1);
4357 
4358     if ((rng != NULL) && (ctxt != NULL))
4359 	return (-1);
4360 
4361     if (((rng != NULL) || (ctxt != NULL)) &&
4362 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4363 	 (reader->ctxt == NULL)))
4364 	return(-1);
4365 
4366     /* Cleanup previous validation stuff. */
4367     if (reader->rngValidCtxt != NULL) {
4368 	if ( !reader->rngPreserveCtxt)
4369 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4370 	reader->rngValidCtxt = NULL;
4371     }
4372     reader->rngPreserveCtxt = 0;
4373     if (reader->rngSchemas != NULL) {
4374 	xmlRelaxNGFree(reader->rngSchemas);
4375 	reader->rngSchemas = NULL;
4376     }
4377 
4378     if ((rng == NULL) && (ctxt == NULL)) {
4379 	/* We just want to deactivate the validation, so get out. */
4380 	return(0);
4381     }
4382 
4383 
4384     if (rng != NULL) {
4385 	xmlRelaxNGParserCtxtPtr pctxt;
4386 	/* Parse the schema and create validation environment. */
4387 
4388 	pctxt = xmlRelaxNGNewParserCtxt(rng);
4389 	if (reader->errorFunc != NULL) {
4390 	    xmlRelaxNGSetParserErrors(pctxt,
4391 		xmlTextReaderValidityErrorRelay,
4392 		xmlTextReaderValidityWarningRelay,
4393 		reader);
4394 	}
4395 	if (reader->sErrorFunc != NULL) {
4396 	    xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4397 		xmlTextReaderValidityStructuredRelay,
4398 		reader);
4399 	}
4400 	reader->rngSchemas = xmlRelaxNGParse(pctxt);
4401 	xmlRelaxNGFreeParserCtxt(pctxt);
4402 	if (reader->rngSchemas == NULL)
4403 	    return(-1);
4404 	reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4405 	if (reader->rngValidCtxt == NULL) {
4406 	    xmlRelaxNGFree(reader->rngSchemas);
4407 	    reader->rngSchemas = NULL;
4408 	    return(-1);
4409 	}
4410     } else {
4411 	/* Use the given validation context. */
4412 	reader->rngValidCtxt = ctxt;
4413 	reader->rngPreserveCtxt = 1;
4414     }
4415     /*
4416     * Redirect the validation context's error channels to use
4417     * the reader channels.
4418     * TODO: In case the user provides the validation context we
4419     *	could make this redirection optional.
4420     */
4421     if (reader->errorFunc != NULL) {
4422 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4423 			 xmlTextReaderValidityErrorRelay,
4424 			 xmlTextReaderValidityWarningRelay,
4425 			 reader);
4426     }
4427 	if (reader->sErrorFunc != NULL) {
4428 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4429 			xmlTextReaderValidityStructuredRelay,
4430 			reader);
4431     }
4432     reader->rngValidErrors = 0;
4433     reader->rngFullNode = NULL;
4434     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4435     return(0);
4436 }
4437 
4438 /**
4439  * xmlTextReaderSchemaValidateInternal:
4440  * @reader:  the xmlTextReaderPtr used
4441  * @xsd:  the path to a W3C XSD schema or NULL
4442  * @ctxt: the XML Schema validation context or NULL
4443  * @options: options (not used yet)
4444  *
4445  * Validate the document as it is processed using XML Schema.
4446  * Activation is only possible before the first Read().
4447  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4448  *
4449  * Returns 0 in case the schemas validation could be (de)activated and
4450  *         -1 in case of error.
4451  */
4452 static int
xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,const char * xsd,xmlSchemaValidCtxtPtr ctxt,int options ATTRIBUTE_UNUSED)4453 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4454 				    const char *xsd,
4455 				    xmlSchemaValidCtxtPtr ctxt,
4456 				    int options ATTRIBUTE_UNUSED)
4457 {
4458     if (reader == NULL)
4459         return(-1);
4460 
4461     if ((xsd != NULL) && (ctxt != NULL))
4462 	return(-1);
4463 
4464     if (((xsd != NULL) || (ctxt != NULL)) &&
4465 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4466         (reader->ctxt == NULL)))
4467 	return(-1);
4468 
4469     /* Cleanup previous validation stuff. */
4470     if (reader->xsdPlug != NULL) {
4471 	xmlSchemaSAXUnplug(reader->xsdPlug);
4472 	reader->xsdPlug = NULL;
4473     }
4474     if (reader->xsdValidCtxt != NULL) {
4475 	if (! reader->xsdPreserveCtxt)
4476 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4477 	reader->xsdValidCtxt = NULL;
4478     }
4479     reader->xsdPreserveCtxt = 0;
4480     if (reader->xsdSchemas != NULL) {
4481 	xmlSchemaFree(reader->xsdSchemas);
4482 	reader->xsdSchemas = NULL;
4483     }
4484 
4485     if ((xsd == NULL) && (ctxt == NULL)) {
4486 	/* We just want to deactivate the validation, so get out. */
4487 	return(0);
4488     }
4489 
4490     if (xsd != NULL) {
4491 	xmlSchemaParserCtxtPtr pctxt;
4492 	/* Parse the schema and create validation environment. */
4493 	pctxt = xmlSchemaNewParserCtxt(xsd);
4494 	if (reader->errorFunc != NULL) {
4495 	    xmlSchemaSetParserErrors(pctxt,
4496 		xmlTextReaderValidityErrorRelay,
4497 		xmlTextReaderValidityWarningRelay,
4498 		reader);
4499 	}
4500 	reader->xsdSchemas = xmlSchemaParse(pctxt);
4501 	xmlSchemaFreeParserCtxt(pctxt);
4502 	if (reader->xsdSchemas == NULL)
4503 	    return(-1);
4504 	reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4505 	if (reader->xsdValidCtxt == NULL) {
4506 	    xmlSchemaFree(reader->xsdSchemas);
4507 	    reader->xsdSchemas = NULL;
4508 	    return(-1);
4509 	}
4510 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4511 	    &(reader->ctxt->sax),
4512 	    &(reader->ctxt->userData));
4513 	if (reader->xsdPlug == NULL) {
4514 	    xmlSchemaFree(reader->xsdSchemas);
4515 	    reader->xsdSchemas = NULL;
4516 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4517 	    reader->xsdValidCtxt = NULL;
4518 	    return(-1);
4519 	}
4520     } else {
4521 	/* Use the given validation context. */
4522 	reader->xsdValidCtxt = ctxt;
4523 	reader->xsdPreserveCtxt = 1;
4524 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4525 	    &(reader->ctxt->sax),
4526 	    &(reader->ctxt->userData));
4527 	if (reader->xsdPlug == NULL) {
4528 	    reader->xsdValidCtxt = NULL;
4529 	    reader->xsdPreserveCtxt = 0;
4530 	    return(-1);
4531 	}
4532     }
4533     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4534                                 xmlTextReaderLocator,
4535 				(void *) reader);
4536     /*
4537     * Redirect the validation context's error channels to use
4538     * the reader channels.
4539     * TODO: In case the user provides the validation context we
4540     *   could make this redirection optional.
4541     */
4542     if (reader->errorFunc != NULL) {
4543 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4544 			 xmlTextReaderValidityErrorRelay,
4545 			 xmlTextReaderValidityWarningRelay,
4546 			 reader);
4547     }
4548 	if (reader->sErrorFunc != NULL) {
4549 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4550 			xmlTextReaderValidityStructuredRelay,
4551 			reader);
4552     }
4553     reader->xsdValidErrors = 0;
4554     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4555     return(0);
4556 }
4557 
4558 /**
4559  * xmlTextReaderSchemaValidateCtxt:
4560  * @reader:  the xmlTextReaderPtr used
4561  * @ctxt: the XML Schema validation context or NULL
4562  * @options: options (not used yet)
4563  *
4564  * Use W3C XSD schema context to validate the document as it is processed.
4565  * Activation is only possible before the first Read().
4566  * If @ctxt is NULL, then XML Schema validation is deactivated.
4567  *
4568  * Returns 0 in case the schemas validation could be (de)activated and
4569  *         -1 in case of error.
4570  */
4571 int
xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,xmlSchemaValidCtxtPtr ctxt,int options)4572 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4573 				    xmlSchemaValidCtxtPtr ctxt,
4574 				    int options)
4575 {
4576     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4577 }
4578 
4579 /**
4580  * xmlTextReaderSchemaValidate:
4581  * @reader:  the xmlTextReaderPtr used
4582  * @xsd:  the path to a W3C XSD schema or NULL
4583  *
4584  * Use W3C XSD schema to validate the document as it is processed.
4585  * Activation is only possible before the first Read().
4586  * If @xsd is NULL, then XML Schema validation is deactivated.
4587  *
4588  * Returns 0 in case the schemas validation could be (de)activated and
4589  *         -1 in case of error.
4590  */
4591 int
xmlTextReaderSchemaValidate(xmlTextReaderPtr reader,const char * xsd)4592 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4593 {
4594     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4595 }
4596 
4597 /**
4598  * xmlTextReaderRelaxNGValidateCtxt:
4599  * @reader:  the xmlTextReaderPtr used
4600  * @ctxt: the RelaxNG schema validation context or NULL
4601  * @options: options (not used yet)
4602  *
4603  * Use RelaxNG schema context to validate the document as it is processed.
4604  * Activation is only possible before the first Read().
4605  * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4606  *
4607  * Returns 0 in case the schemas validation could be (de)activated and
4608  *         -1 in case of error.
4609  */
4610 int
xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,xmlRelaxNGValidCtxtPtr ctxt,int options)4611 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4612 				 xmlRelaxNGValidCtxtPtr ctxt,
4613 				 int options)
4614 {
4615     return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4616 }
4617 
4618 /**
4619  * xmlTextReaderRelaxNGValidate:
4620  * @reader:  the xmlTextReaderPtr used
4621  * @rng:  the path to a RelaxNG schema or NULL
4622  *
4623  * Use RelaxNG schema to validate the document as it is processed.
4624  * Activation is only possible before the first Read().
4625  * If @rng is NULL, then RelaxNG schema validation is deactivated.
4626  *
4627  * Returns 0 in case the schemas validation could be (de)activated and
4628  *         -1 in case of error.
4629  */
4630 int
xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader,const char * rng)4631 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4632 {
4633     return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4634 }
4635 
4636 #endif
4637 
4638 /**
4639  * xmlTextReaderIsNamespaceDecl:
4640  * @reader: the xmlTextReaderPtr used
4641  *
4642  * Determine whether the current node is a namespace declaration
4643  * rather than a regular attribute.
4644  *
4645  * Returns 1 if the current node is a namespace declaration, 0 if it
4646  * is a regular attribute or other type of node, or -1 in case of
4647  * error.
4648  */
4649 int
xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader)4650 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4651     xmlNodePtr node;
4652     if (reader == NULL)
4653 	return(-1);
4654     if (reader->node == NULL)
4655 	return(-1);
4656     if (reader->curnode != NULL)
4657 	node = reader->curnode;
4658     else
4659 	node = reader->node;
4660 
4661     if (XML_NAMESPACE_DECL == node->type)
4662 	return(1);
4663     else
4664 	return(0);
4665 }
4666 
4667 /**
4668  * xmlTextReaderConstXmlVersion:
4669  * @reader:  the xmlTextReaderPtr used
4670  *
4671  * Determine the XML version of the document being read.
4672  *
4673  * Returns a string containing the XML version of the document or NULL
4674  * in case of error.  The string is deallocated with the reader.
4675  */
4676 const xmlChar *
xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader)4677 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4678     xmlDocPtr doc = NULL;
4679     if (reader == NULL)
4680 	return(NULL);
4681     if (reader->doc != NULL)
4682         doc = reader->doc;
4683     else if (reader->ctxt != NULL)
4684 	doc = reader->ctxt->myDoc;
4685     if (doc == NULL)
4686 	return(NULL);
4687 
4688     if (doc->version == NULL)
4689 	return(NULL);
4690     else
4691       return(CONSTSTR(doc->version));
4692 }
4693 
4694 /**
4695  * xmlTextReaderStandalone:
4696  * @reader:  the xmlTextReaderPtr used
4697  *
4698  * Determine the standalone status of the document being read.
4699  *
4700  * Returns 1 if the document was declared to be standalone, 0 if it
4701  * was declared to be not standalone, or -1 if the document did not
4702  * specify its standalone status or in case of error.
4703  */
4704 int
xmlTextReaderStandalone(xmlTextReaderPtr reader)4705 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4706     xmlDocPtr doc = NULL;
4707     if (reader == NULL)
4708 	return(-1);
4709     if (reader->doc != NULL)
4710         doc = reader->doc;
4711     else if (reader->ctxt != NULL)
4712 	doc = reader->ctxt->myDoc;
4713     if (doc == NULL)
4714 	return(-1);
4715 
4716     return(doc->standalone);
4717 }
4718 
4719 /************************************************************************
4720  *									*
4721  *			Error Handling Extensions                       *
4722  *									*
4723  ************************************************************************/
4724 
4725 /* helper to build a xmlMalloc'ed string from a format and va_list */
4726 static char *
xmlTextReaderBuildMessage(const char * msg,va_list ap)4727 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4728     int size = 0;
4729     int chars;
4730     char *larger;
4731     char *str = NULL;
4732     va_list aq;
4733 
4734     while (1) {
4735         VA_COPY(aq, ap);
4736         chars = vsnprintf(str, size, msg, aq);
4737         va_end(aq);
4738         if (chars < 0) {
4739 	    xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4740 	    if (str)
4741 		xmlFree(str);
4742 	    return NULL;
4743 	}
4744 	if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4745             break;
4746         if (chars < MAX_ERR_MSG_SIZE)
4747 	size = chars + 1;
4748 	else
4749 		size = MAX_ERR_MSG_SIZE;
4750         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4751 	    xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4752 	    if (str)
4753                 xmlFree(str);
4754             return NULL;
4755         }
4756         str = larger;
4757     }
4758 
4759     return str;
4760 }
4761 
4762 /**
4763  * xmlTextReaderLocatorLineNumber:
4764  * @locator: the xmlTextReaderLocatorPtr used
4765  *
4766  * Obtain the line number for the given locator.
4767  *
4768  * Returns the line number or -1 in case of error.
4769  */
4770 int
xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator)4771 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4772     /* we know that locator is a xmlParserCtxtPtr */
4773     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4774     int ret = -1;
4775 
4776     if (locator == NULL)
4777         return(-1);
4778     if (ctx->node != NULL) {
4779 	ret = xmlGetLineNo(ctx->node);
4780     }
4781     else {
4782 	/* inspired from error.c */
4783 	xmlParserInputPtr input;
4784 	input = ctx->input;
4785 	if ((input->filename == NULL) && (ctx->inputNr > 1))
4786 	    input = ctx->inputTab[ctx->inputNr - 2];
4787 	if (input != NULL) {
4788 	    ret = input->line;
4789 	}
4790 	else {
4791 	    ret = -1;
4792 	}
4793     }
4794 
4795     return ret;
4796 }
4797 
4798 /**
4799  * xmlTextReaderLocatorBaseURI:
4800  * @locator: the xmlTextReaderLocatorPtr used
4801  *
4802  * Obtain the base URI for the given locator.
4803  *
4804  * Returns the base URI or NULL in case of error,
4805  *    if non NULL it need to be freed by the caller.
4806  */
4807 xmlChar *
xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator)4808 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4809     /* we know that locator is a xmlParserCtxtPtr */
4810     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4811     xmlChar *ret = NULL;
4812 
4813     if (locator == NULL)
4814         return(NULL);
4815     if (ctx->node != NULL) {
4816 	ret = xmlNodeGetBase(NULL,ctx->node);
4817     }
4818     else {
4819 	/* inspired from error.c */
4820 	xmlParserInputPtr input;
4821 	input = ctx->input;
4822 	if ((input->filename == NULL) && (ctx->inputNr > 1))
4823 	    input = ctx->inputTab[ctx->inputNr - 2];
4824 	if (input != NULL) {
4825 	    ret = xmlStrdup(BAD_CAST input->filename);
4826 	}
4827 	else {
4828 	    ret = NULL;
4829 	}
4830     }
4831 
4832     return ret;
4833 }
4834 
4835 static void
xmlTextReaderGenericError(void * ctxt,xmlParserSeverities severity,char * str)4836 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4837                           char *str)
4838 {
4839     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4840 
4841     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4842 
4843     if (str != NULL) {
4844         if (reader->errorFunc)
4845             reader->errorFunc(reader->errorFuncArg, str, severity,
4846                               (xmlTextReaderLocatorPtr) ctx);
4847         xmlFree(str);
4848     }
4849 }
4850 
4851 static void
xmlTextReaderStructuredError(void * ctxt,xmlErrorPtr error)4852 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4853 {
4854     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4855 
4856     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4857 
4858     if (error && reader->sErrorFunc) {
4859         reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4860     }
4861 }
4862 
4863 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderError(void * ctxt,const char * msg,...)4864 xmlTextReaderError(void *ctxt, const char *msg, ...)
4865 {
4866     va_list ap;
4867 
4868     va_start(ap, msg);
4869     xmlTextReaderGenericError(ctxt,
4870                               XML_PARSER_SEVERITY_ERROR,
4871                               xmlTextReaderBuildMessage(msg, ap));
4872     va_end(ap);
4873 
4874 }
4875 
4876 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderWarning(void * ctxt,const char * msg,...)4877 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4878 {
4879     va_list ap;
4880 
4881     va_start(ap, msg);
4882     xmlTextReaderGenericError(ctxt,
4883                               XML_PARSER_SEVERITY_WARNING,
4884                               xmlTextReaderBuildMessage(msg, ap));
4885     va_end(ap);
4886 }
4887 
4888 static void XMLCDECL
xmlTextReaderValidityError(void * ctxt,const char * msg,...)4889 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4890 {
4891     va_list ap;
4892 
4893     int len = xmlStrlen((const xmlChar *) msg);
4894 
4895     if ((len > 1) && (msg[len - 2] != ':')) {
4896         /*
4897          * some callbacks only report locator information:
4898          * skip them (mimicking behaviour in error.c)
4899          */
4900         va_start(ap, msg);
4901         xmlTextReaderGenericError(ctxt,
4902                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
4903                                   xmlTextReaderBuildMessage(msg, ap));
4904         va_end(ap);
4905     }
4906 }
4907 
4908 static void XMLCDECL
xmlTextReaderValidityWarning(void * ctxt,const char * msg,...)4909 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4910 {
4911     va_list ap;
4912 
4913     int len = xmlStrlen((const xmlChar *) msg);
4914 
4915     if ((len != 0) && (msg[len - 1] != ':')) {
4916         /*
4917          * some callbacks only report locator information:
4918          * skip them (mimicking behaviour in error.c)
4919          */
4920         va_start(ap, msg);
4921         xmlTextReaderGenericError(ctxt,
4922                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
4923                                   xmlTextReaderBuildMessage(msg, ap));
4924         va_end(ap);
4925     }
4926 }
4927 
4928 /**
4929  * xmlTextReaderSetErrorHandler:
4930  * @reader:  the xmlTextReaderPtr used
4931  * @f:	the callback function to call on error and warnings
4932  * @arg:    a user argument to pass to the callback function
4933  *
4934  * Register a callback function that will be called on error and warnings.
4935  *
4936  * If @f is NULL, the default error and warning handlers are restored.
4937  */
4938 void
xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,xmlTextReaderErrorFunc f,void * arg)4939 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4940                              xmlTextReaderErrorFunc f, void *arg)
4941 {
4942     if (f != NULL) {
4943         reader->ctxt->sax->error = xmlTextReaderError;
4944         reader->ctxt->sax->serror = NULL;
4945         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4946         reader->ctxt->sax->warning = xmlTextReaderWarning;
4947         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4948         reader->errorFunc = f;
4949         reader->sErrorFunc = NULL;
4950         reader->errorFuncArg = arg;
4951 #ifdef LIBXML_SCHEMAS_ENABLED
4952         if (reader->rngValidCtxt) {
4953             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4954                                      xmlTextReaderValidityErrorRelay,
4955                                      xmlTextReaderValidityWarningRelay,
4956                                      reader);
4957             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4958                                                reader);
4959         }
4960         if (reader->xsdValidCtxt) {
4961             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4962                                     xmlTextReaderValidityErrorRelay,
4963                                     xmlTextReaderValidityWarningRelay,
4964                                     reader);
4965             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4966                                               reader);
4967         }
4968 #endif
4969     } else {
4970         /* restore defaults */
4971         reader->ctxt->sax->error = xmlParserError;
4972         reader->ctxt->vctxt.error = xmlParserValidityError;
4973         reader->ctxt->sax->warning = xmlParserWarning;
4974         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4975         reader->errorFunc = NULL;
4976         reader->sErrorFunc = NULL;
4977         reader->errorFuncArg = NULL;
4978 #ifdef LIBXML_SCHEMAS_ENABLED
4979         if (reader->rngValidCtxt) {
4980             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4981                                      reader);
4982             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4983                                                reader);
4984         }
4985         if (reader->xsdValidCtxt) {
4986             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4987                                     reader);
4988             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4989                                               reader);
4990         }
4991 #endif
4992     }
4993 }
4994 
4995 /**
4996 * xmlTextReaderSetStructuredErrorHandler:
4997  * @reader:  the xmlTextReaderPtr used
4998  * @f:	the callback function to call on error and warnings
4999  * @arg:    a user argument to pass to the callback function
5000  *
5001  * Register a callback function that will be called on error and warnings.
5002  *
5003  * If @f is NULL, the default error and warning handlers are restored.
5004  */
5005 void
xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,xmlStructuredErrorFunc f,void * arg)5006 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5007                                        xmlStructuredErrorFunc f, void *arg)
5008 {
5009     if (f != NULL) {
5010         reader->ctxt->sax->error = NULL;
5011         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5012         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5013         reader->ctxt->sax->warning = xmlTextReaderWarning;
5014         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5015         reader->sErrorFunc = f;
5016         reader->errorFunc = NULL;
5017         reader->errorFuncArg = arg;
5018 #ifdef LIBXML_SCHEMAS_ENABLED
5019         if (reader->rngValidCtxt) {
5020             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5021                                      reader);
5022             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5023                                         xmlTextReaderValidityStructuredRelay,
5024                                                reader);
5025         }
5026         if (reader->xsdValidCtxt) {
5027             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5028                                     reader);
5029             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5030                                        xmlTextReaderValidityStructuredRelay,
5031                                               reader);
5032         }
5033 #endif
5034     } else {
5035         /* restore defaults */
5036         reader->ctxt->sax->error = xmlParserError;
5037         reader->ctxt->sax->serror = NULL;
5038         reader->ctxt->vctxt.error = xmlParserValidityError;
5039         reader->ctxt->sax->warning = xmlParserWarning;
5040         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5041         reader->errorFunc = NULL;
5042         reader->sErrorFunc = NULL;
5043         reader->errorFuncArg = NULL;
5044 #ifdef LIBXML_SCHEMAS_ENABLED
5045         if (reader->rngValidCtxt) {
5046             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5047                                      reader);
5048             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5049                                                reader);
5050         }
5051         if (reader->xsdValidCtxt) {
5052             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5053                                     reader);
5054             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5055                                               reader);
5056         }
5057 #endif
5058     }
5059 }
5060 
5061 /**
5062  * xmlTextReaderIsValid:
5063  * @reader:  the xmlTextReaderPtr used
5064  *
5065  * Retrieve the validity status from the parser context
5066  *
5067  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5068  */
5069 int
xmlTextReaderIsValid(xmlTextReaderPtr reader)5070 xmlTextReaderIsValid(xmlTextReaderPtr reader)
5071 {
5072     if (reader == NULL)
5073         return (-1);
5074 #ifdef LIBXML_SCHEMAS_ENABLED
5075     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5076         return (reader->rngValidErrors == 0);
5077     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5078         return (reader->xsdValidErrors == 0);
5079 #endif
5080     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5081         return (reader->ctxt->valid);
5082     return (0);
5083 }
5084 
5085 /**
5086  * xmlTextReaderGetErrorHandler:
5087  * @reader:  the xmlTextReaderPtr used
5088  * @f:	the callback function or NULL is no callback has been registered
5089  * @arg:    a user argument
5090  *
5091  * Retrieve the error callback function and user argument.
5092  */
5093 void
xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,xmlTextReaderErrorFunc * f,void ** arg)5094 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5095                              xmlTextReaderErrorFunc * f, void **arg)
5096 {
5097     if (f != NULL)
5098         *f = reader->errorFunc;
5099     if (arg != NULL)
5100         *arg = reader->errorFuncArg;
5101 }
5102 /************************************************************************
5103  *									*
5104  *	New set (2.6.0) of simpler and more flexible APIs		*
5105  *									*
5106  ************************************************************************/
5107 
5108 /**
5109  * xmlTextReaderSetup:
5110  * @reader:  an XML reader
5111  * @input: xmlParserInputBufferPtr used to feed the reader, will
5112  *         be destroyed with it.
5113  * @URL:  the base URL to use for the document
5114  * @encoding:  the document encoding, or NULL
5115  * @options:  a combination of xmlParserOption
5116  *
5117  * Setup an XML reader with new options
5118  *
5119  * Returns 0 in case of success and -1 in case of error.
5120  */
5121 int
xmlTextReaderSetup(xmlTextReaderPtr reader,xmlParserInputBufferPtr input,const char * URL,const char * encoding,int options)5122 xmlTextReaderSetup(xmlTextReaderPtr reader,
5123                    xmlParserInputBufferPtr input, const char *URL,
5124                    const char *encoding, int options)
5125 {
5126     if (reader == NULL) {
5127         if (input != NULL)
5128 	    xmlFreeParserInputBuffer(input);
5129         return (-1);
5130     }
5131 
5132     /*
5133      * we force the generation of compact text nodes on the reader
5134      * since usr applications should never modify the tree
5135      */
5136     options |= XML_PARSE_COMPACT;
5137 
5138     reader->doc = NULL;
5139     reader->entNr = 0;
5140     reader->parserFlags = options;
5141     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5142     if ((input != NULL) && (reader->input != NULL) &&
5143         (reader->allocs & XML_TEXTREADER_INPUT)) {
5144 	xmlFreeParserInputBuffer(reader->input);
5145 	reader->input = NULL;
5146 	reader->allocs -= XML_TEXTREADER_INPUT;
5147     }
5148     if (input != NULL) {
5149 	reader->input = input;
5150 	reader->allocs |= XML_TEXTREADER_INPUT;
5151     }
5152     if (reader->buffer == NULL)
5153         reader->buffer = xmlBufCreateSize(100);
5154     if (reader->buffer == NULL) {
5155         xmlGenericError(xmlGenericErrorContext,
5156                         "xmlTextReaderSetup : malloc failed\n");
5157         return (-1);
5158     }
5159     /* no operation on a reader should require a huge buffer */
5160     xmlBufSetAllocationScheme(reader->buffer,
5161 			      XML_BUFFER_ALLOC_BOUNDED);
5162     if (reader->sax == NULL)
5163 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5164     if (reader->sax == NULL) {
5165         xmlGenericError(xmlGenericErrorContext,
5166                         "xmlTextReaderSetup : malloc failed\n");
5167         return (-1);
5168     }
5169     xmlSAXVersion(reader->sax, 2);
5170     reader->startElement = reader->sax->startElement;
5171     reader->sax->startElement = xmlTextReaderStartElement;
5172     reader->endElement = reader->sax->endElement;
5173     reader->sax->endElement = xmlTextReaderEndElement;
5174 #ifdef LIBXML_SAX1_ENABLED
5175     if (reader->sax->initialized == XML_SAX2_MAGIC) {
5176 #endif /* LIBXML_SAX1_ENABLED */
5177         reader->startElementNs = reader->sax->startElementNs;
5178         reader->sax->startElementNs = xmlTextReaderStartElementNs;
5179         reader->endElementNs = reader->sax->endElementNs;
5180         reader->sax->endElementNs = xmlTextReaderEndElementNs;
5181 #ifdef LIBXML_SAX1_ENABLED
5182     } else {
5183         reader->startElementNs = NULL;
5184         reader->endElementNs = NULL;
5185     }
5186 #endif /* LIBXML_SAX1_ENABLED */
5187     reader->characters = reader->sax->characters;
5188     reader->sax->characters = xmlTextReaderCharacters;
5189     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5190     reader->cdataBlock = reader->sax->cdataBlock;
5191     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5192 
5193     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5194     reader->node = NULL;
5195     reader->curnode = NULL;
5196     if (input != NULL) {
5197         if (xmlBufUse(reader->input->buffer) < 4) {
5198             xmlParserInputBufferRead(input, 4);
5199         }
5200         if (reader->ctxt == NULL) {
5201             if (xmlBufUse(reader->input->buffer) >= 4) {
5202                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5203 		       (const char *) xmlBufContent(reader->input->buffer),
5204                                       4, URL);
5205                 reader->base = 0;
5206                 reader->cur = 4;
5207             } else {
5208                 reader->ctxt =
5209                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5210                 reader->base = 0;
5211                 reader->cur = 0;
5212             }
5213         } else {
5214 	    xmlParserInputPtr inputStream;
5215 	    xmlParserInputBufferPtr buf;
5216 	    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5217 
5218 	    xmlCtxtReset(reader->ctxt);
5219 	    buf = xmlAllocParserInputBuffer(enc);
5220 	    if (buf == NULL) return(-1);
5221 	    inputStream = xmlNewInputStream(reader->ctxt);
5222 	    if (inputStream == NULL) {
5223 		xmlFreeParserInputBuffer(buf);
5224 		return(-1);
5225 	    }
5226 
5227 	    if (URL == NULL)
5228 		inputStream->filename = NULL;
5229 	    else
5230 		inputStream->filename = (char *)
5231 		    xmlCanonicPath((const xmlChar *) URL);
5232 	    inputStream->buf = buf;
5233             xmlBufResetInput(buf->buffer, inputStream);
5234 
5235 	    inputPush(reader->ctxt, inputStream);
5236 	    reader->cur = 0;
5237 	}
5238         if (reader->ctxt == NULL) {
5239             xmlGenericError(xmlGenericErrorContext,
5240                             "xmlTextReaderSetup : malloc failed\n");
5241             return (-1);
5242         }
5243     }
5244     if (reader->dict != NULL) {
5245         if (reader->ctxt->dict != NULL) {
5246 	    if (reader->dict != reader->ctxt->dict) {
5247 		xmlDictFree(reader->dict);
5248 		reader->dict = reader->ctxt->dict;
5249 	    }
5250 	} else {
5251 	    reader->ctxt->dict = reader->dict;
5252 	}
5253     } else {
5254 	if (reader->ctxt->dict == NULL)
5255 	    reader->ctxt->dict = xmlDictCreate();
5256         reader->dict = reader->ctxt->dict;
5257     }
5258     reader->ctxt->_private = reader;
5259     reader->ctxt->linenumbers = 1;
5260     reader->ctxt->dictNames = 1;
5261     /*
5262      * use the parser dictionary to allocate all elements and attributes names
5263      */
5264     reader->ctxt->docdict = 1;
5265     reader->ctxt->parseMode = XML_PARSE_READER;
5266 
5267 #ifdef LIBXML_XINCLUDE_ENABLED
5268     if (reader->xincctxt != NULL) {
5269 	xmlXIncludeFreeContext(reader->xincctxt);
5270 	reader->xincctxt = NULL;
5271     }
5272     if (options & XML_PARSE_XINCLUDE) {
5273         reader->xinclude = 1;
5274 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5275 	options -= XML_PARSE_XINCLUDE;
5276     } else
5277         reader->xinclude = 0;
5278     reader->in_xinclude = 0;
5279 #endif
5280 #ifdef LIBXML_PATTERN_ENABLED
5281     if (reader->patternTab == NULL) {
5282         reader->patternNr = 0;
5283 	reader->patternMax = 0;
5284     }
5285     while (reader->patternNr > 0) {
5286         reader->patternNr--;
5287 	if (reader->patternTab[reader->patternNr] != NULL) {
5288 	    xmlFreePattern(reader->patternTab[reader->patternNr]);
5289             reader->patternTab[reader->patternNr] = NULL;
5290 	}
5291     }
5292 #endif
5293 
5294     if (options & XML_PARSE_DTDVALID)
5295         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5296 
5297     xmlCtxtUseOptions(reader->ctxt, options);
5298     if (encoding != NULL) {
5299         xmlCharEncodingHandlerPtr hdlr;
5300 
5301         hdlr = xmlFindCharEncodingHandler(encoding);
5302         if (hdlr != NULL)
5303             xmlSwitchToEncoding(reader->ctxt, hdlr);
5304     }
5305     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5306         (reader->ctxt->input->filename == NULL))
5307         reader->ctxt->input->filename = (char *)
5308             xmlStrdup((const xmlChar *) URL);
5309 
5310     reader->doc = NULL;
5311 
5312     return (0);
5313 }
5314 
5315 /**
5316  * xmlTextReaderByteConsumed:
5317  * @reader: an XML reader
5318  *
5319  * This function provides the current index of the parser used
5320  * by the reader, relative to the start of the current entity.
5321  * This function actually just wraps a call to xmlBytesConsumed()
5322  * for the parser context associated with the reader.
5323  * See xmlBytesConsumed() for more information.
5324  *
5325  * Returns the index in bytes from the beginning of the entity or -1
5326  *         in case the index could not be computed.
5327  */
5328 long
xmlTextReaderByteConsumed(xmlTextReaderPtr reader)5329 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5330     if ((reader == NULL) || (reader->ctxt == NULL))
5331         return(-1);
5332     return(xmlByteConsumed(reader->ctxt));
5333 }
5334 
5335 
5336 /**
5337  * xmlReaderWalker:
5338  * @doc:  a preparsed document
5339  *
5340  * Create an xmltextReader for a preparsed document.
5341  *
5342  * Returns the new reader or NULL in case of error.
5343  */
5344 xmlTextReaderPtr
xmlReaderWalker(xmlDocPtr doc)5345 xmlReaderWalker(xmlDocPtr doc)
5346 {
5347     xmlTextReaderPtr ret;
5348 
5349     if (doc == NULL)
5350         return(NULL);
5351 
5352     ret = xmlMalloc(sizeof(xmlTextReader));
5353     if (ret == NULL) {
5354         xmlGenericError(xmlGenericErrorContext,
5355 		"xmlNewTextReader : malloc failed\n");
5356 	return(NULL);
5357     }
5358     memset(ret, 0, sizeof(xmlTextReader));
5359     ret->entNr = 0;
5360     ret->input = NULL;
5361     ret->mode = XML_TEXTREADER_MODE_INITIAL;
5362     ret->node = NULL;
5363     ret->curnode = NULL;
5364     ret->base = 0;
5365     ret->cur = 0;
5366     ret->allocs = XML_TEXTREADER_CTXT;
5367     ret->doc = doc;
5368     ret->state = XML_TEXTREADER_START;
5369     ret->dict = xmlDictCreate();
5370     return(ret);
5371 }
5372 
5373 /**
5374  * xmlReaderForDoc:
5375  * @cur:  a pointer to a zero terminated string
5376  * @URL:  the base URL to use for the document
5377  * @encoding:  the document encoding, or NULL
5378  * @options:  a combination of xmlParserOption
5379  *
5380  * Create an xmltextReader for an XML in-memory document.
5381  * The parsing flags @options are a combination of xmlParserOption.
5382  *
5383  * Returns the new reader or NULL in case of error.
5384  */
5385 xmlTextReaderPtr
xmlReaderForDoc(const xmlChar * cur,const char * URL,const char * encoding,int options)5386 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5387                 int options)
5388 {
5389     int len;
5390 
5391     if (cur == NULL)
5392         return (NULL);
5393     len = xmlStrlen(cur);
5394 
5395     return (xmlReaderForMemory
5396             ((const char *) cur, len, URL, encoding, options));
5397 }
5398 
5399 /**
5400  * xmlReaderForFile:
5401  * @filename:  a file or URL
5402  * @encoding:  the document encoding, or NULL
5403  * @options:  a combination of xmlParserOption
5404  *
5405  * parse an XML file from the filesystem or the network.
5406  * The parsing flags @options are a combination of xmlParserOption.
5407  *
5408  * Returns the new reader or NULL in case of error.
5409  */
5410 xmlTextReaderPtr
xmlReaderForFile(const char * filename,const char * encoding,int options)5411 xmlReaderForFile(const char *filename, const char *encoding, int options)
5412 {
5413     xmlTextReaderPtr reader;
5414 
5415     reader = xmlNewTextReaderFilename(filename);
5416     if (reader == NULL)
5417         return (NULL);
5418     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5419     return (reader);
5420 }
5421 
5422 /**
5423  * xmlReaderForMemory:
5424  * @buffer:  a pointer to a char array
5425  * @size:  the size of the array
5426  * @URL:  the base URL to use for the document
5427  * @encoding:  the document encoding, or NULL
5428  * @options:  a combination of xmlParserOption
5429  *
5430  * Create an xmltextReader for an XML in-memory document.
5431  * The parsing flags @options are a combination of xmlParserOption.
5432  *
5433  * Returns the new reader or NULL in case of error.
5434  */
5435 xmlTextReaderPtr
xmlReaderForMemory(const char * buffer,int size,const char * URL,const char * encoding,int options)5436 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5437                    const char *encoding, int options)
5438 {
5439     xmlTextReaderPtr reader;
5440     xmlParserInputBufferPtr buf;
5441 
5442     buf = xmlParserInputBufferCreateStatic(buffer, size,
5443                                       XML_CHAR_ENCODING_NONE);
5444     if (buf == NULL) {
5445         return (NULL);
5446     }
5447     reader = xmlNewTextReader(buf, URL);
5448     if (reader == NULL) {
5449         xmlFreeParserInputBuffer(buf);
5450         return (NULL);
5451     }
5452     reader->allocs |= XML_TEXTREADER_INPUT;
5453     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5454     return (reader);
5455 }
5456 
5457 /**
5458  * xmlReaderForFd:
5459  * @fd:  an open file descriptor
5460  * @URL:  the base URL to use for the document
5461  * @encoding:  the document encoding, or NULL
5462  * @options:  a combination of xmlParserOption
5463  *
5464  * Create an xmltextReader for an XML from a file descriptor.
5465  * The parsing flags @options are a combination of xmlParserOption.
5466  * NOTE that the file descriptor will not be closed when the
5467  *      reader is closed or reset.
5468  *
5469  * Returns the new reader or NULL in case of error.
5470  */
5471 xmlTextReaderPtr
xmlReaderForFd(int fd,const char * URL,const char * encoding,int options)5472 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5473 {
5474     xmlTextReaderPtr reader;
5475     xmlParserInputBufferPtr input;
5476 
5477     if (fd < 0)
5478         return (NULL);
5479 
5480     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5481     if (input == NULL)
5482         return (NULL);
5483     input->closecallback = NULL;
5484     reader = xmlNewTextReader(input, URL);
5485     if (reader == NULL) {
5486         xmlFreeParserInputBuffer(input);
5487         return (NULL);
5488     }
5489     reader->allocs |= XML_TEXTREADER_INPUT;
5490     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5491     return (reader);
5492 }
5493 
5494 /**
5495  * xmlReaderForIO:
5496  * @ioread:  an I/O read function
5497  * @ioclose:  an I/O close function
5498  * @ioctx:  an I/O handler
5499  * @URL:  the base URL to use for the document
5500  * @encoding:  the document encoding, or NULL
5501  * @options:  a combination of xmlParserOption
5502  *
5503  * Create an xmltextReader for an XML document from I/O functions and source.
5504  * The parsing flags @options are a combination of xmlParserOption.
5505  *
5506  * Returns the new reader or NULL in case of error.
5507  */
5508 xmlTextReaderPtr
xmlReaderForIO(xmlInputReadCallback ioread,xmlInputCloseCallback ioclose,void * ioctx,const char * URL,const char * encoding,int options)5509 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5510                void *ioctx, const char *URL, const char *encoding,
5511                int options)
5512 {
5513     xmlTextReaderPtr reader;
5514     xmlParserInputBufferPtr input;
5515 
5516     if (ioread == NULL)
5517         return (NULL);
5518 
5519     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5520                                          XML_CHAR_ENCODING_NONE);
5521     if (input == NULL) {
5522         if (ioclose != NULL)
5523             ioclose(ioctx);
5524         return (NULL);
5525     }
5526     reader = xmlNewTextReader(input, URL);
5527     if (reader == NULL) {
5528         xmlFreeParserInputBuffer(input);
5529         return (NULL);
5530     }
5531     reader->allocs |= XML_TEXTREADER_INPUT;
5532     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5533     return (reader);
5534 }
5535 
5536 /**
5537  * xmlReaderNewWalker:
5538  * @reader:  an XML reader
5539  * @doc:  a preparsed document
5540  *
5541  * Setup an xmltextReader to parse a preparsed XML document.
5542  * This reuses the existing @reader xmlTextReader.
5543  *
5544  * Returns 0 in case of success and -1 in case of error
5545  */
5546 int
xmlReaderNewWalker(xmlTextReaderPtr reader,xmlDocPtr doc)5547 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5548 {
5549     if (doc == NULL)
5550         return (-1);
5551     if (reader == NULL)
5552         return (-1);
5553 
5554     if (reader->input != NULL) {
5555         xmlFreeParserInputBuffer(reader->input);
5556     }
5557     if (reader->ctxt != NULL) {
5558 	xmlCtxtReset(reader->ctxt);
5559     }
5560 
5561     reader->entNr = 0;
5562     reader->input = NULL;
5563     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5564     reader->node = NULL;
5565     reader->curnode = NULL;
5566     reader->base = 0;
5567     reader->cur = 0;
5568     reader->allocs = XML_TEXTREADER_CTXT;
5569     reader->doc = doc;
5570     reader->state = XML_TEXTREADER_START;
5571     if (reader->dict == NULL) {
5572         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5573 	    reader->dict = reader->ctxt->dict;
5574 	else
5575 	    reader->dict = xmlDictCreate();
5576     }
5577     return(0);
5578 }
5579 
5580 /**
5581  * xmlReaderNewDoc:
5582  * @reader:  an XML reader
5583  * @cur:  a pointer to a zero terminated string
5584  * @URL:  the base URL to use for the document
5585  * @encoding:  the document encoding, or NULL
5586  * @options:  a combination of xmlParserOption
5587  *
5588  * Setup an xmltextReader to parse an XML in-memory document.
5589  * The parsing flags @options are a combination of xmlParserOption.
5590  * This reuses the existing @reader xmlTextReader.
5591  *
5592  * Returns 0 in case of success and -1 in case of error
5593  */
5594 int
xmlReaderNewDoc(xmlTextReaderPtr reader,const xmlChar * cur,const char * URL,const char * encoding,int options)5595 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5596                 const char *URL, const char *encoding, int options)
5597 {
5598 
5599     int len;
5600 
5601     if (cur == NULL)
5602         return (-1);
5603     if (reader == NULL)
5604         return (-1);
5605 
5606     len = xmlStrlen(cur);
5607     return (xmlReaderNewMemory(reader, (const char *)cur, len,
5608                                URL, encoding, options));
5609 }
5610 
5611 /**
5612  * xmlReaderNewFile:
5613  * @reader:  an XML reader
5614  * @filename:  a file or URL
5615  * @encoding:  the document encoding, or NULL
5616  * @options:  a combination of xmlParserOption
5617  *
5618  * parse an XML file from the filesystem or the network.
5619  * The parsing flags @options are a combination of xmlParserOption.
5620  * This reuses the existing @reader xmlTextReader.
5621  *
5622  * Returns 0 in case of success and -1 in case of error
5623  */
5624 int
xmlReaderNewFile(xmlTextReaderPtr reader,const char * filename,const char * encoding,int options)5625 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5626                  const char *encoding, int options)
5627 {
5628     xmlParserInputBufferPtr input;
5629 
5630     if (filename == NULL)
5631         return (-1);
5632     if (reader == NULL)
5633         return (-1);
5634 
5635     input =
5636         xmlParserInputBufferCreateFilename(filename,
5637                                            XML_CHAR_ENCODING_NONE);
5638     if (input == NULL)
5639         return (-1);
5640     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5641 }
5642 
5643 /**
5644  * xmlReaderNewMemory:
5645  * @reader:  an XML reader
5646  * @buffer:  a pointer to a char array
5647  * @size:  the size of the array
5648  * @URL:  the base URL to use for the document
5649  * @encoding:  the document encoding, or NULL
5650  * @options:  a combination of xmlParserOption
5651  *
5652  * Setup an xmltextReader to parse an XML in-memory document.
5653  * The parsing flags @options are a combination of xmlParserOption.
5654  * This reuses the existing @reader xmlTextReader.
5655  *
5656  * Returns 0 in case of success and -1 in case of error
5657  */
5658 int
xmlReaderNewMemory(xmlTextReaderPtr reader,const char * buffer,int size,const char * URL,const char * encoding,int options)5659 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5660                    const char *URL, const char *encoding, int options)
5661 {
5662     xmlParserInputBufferPtr input;
5663 
5664     if (reader == NULL)
5665         return (-1);
5666     if (buffer == NULL)
5667         return (-1);
5668 
5669     input = xmlParserInputBufferCreateStatic(buffer, size,
5670                                       XML_CHAR_ENCODING_NONE);
5671     if (input == NULL) {
5672         return (-1);
5673     }
5674     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5675 }
5676 
5677 /**
5678  * xmlReaderNewFd:
5679  * @reader:  an XML reader
5680  * @fd:  an open file descriptor
5681  * @URL:  the base URL to use for the document
5682  * @encoding:  the document encoding, or NULL
5683  * @options:  a combination of xmlParserOption
5684  *
5685  * Setup an xmltextReader to parse an XML from a file descriptor.
5686  * NOTE that the file descriptor will not be closed when the
5687  *      reader is closed or reset.
5688  * The parsing flags @options are a combination of xmlParserOption.
5689  * This reuses the existing @reader xmlTextReader.
5690  *
5691  * Returns 0 in case of success and -1 in case of error
5692  */
5693 int
xmlReaderNewFd(xmlTextReaderPtr reader,int fd,const char * URL,const char * encoding,int options)5694 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5695                const char *URL, const char *encoding, int options)
5696 {
5697     xmlParserInputBufferPtr input;
5698 
5699     if (fd < 0)
5700         return (-1);
5701     if (reader == NULL)
5702         return (-1);
5703 
5704     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5705     if (input == NULL)
5706         return (-1);
5707     input->closecallback = NULL;
5708     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5709 }
5710 
5711 /**
5712  * xmlReaderNewIO:
5713  * @reader:  an XML reader
5714  * @ioread:  an I/O read function
5715  * @ioclose:  an I/O close function
5716  * @ioctx:  an I/O handler
5717  * @URL:  the base URL to use for the document
5718  * @encoding:  the document encoding, or NULL
5719  * @options:  a combination of xmlParserOption
5720  *
5721  * Setup an xmltextReader to parse an XML document from I/O functions
5722  * and source.
5723  * The parsing flags @options are a combination of xmlParserOption.
5724  * This reuses the existing @reader xmlTextReader.
5725  *
5726  * Returns 0 in case of success and -1 in case of error
5727  */
5728 int
xmlReaderNewIO(xmlTextReaderPtr reader,xmlInputReadCallback ioread,xmlInputCloseCallback ioclose,void * ioctx,const char * URL,const char * encoding,int options)5729 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5730                xmlInputCloseCallback ioclose, void *ioctx,
5731                const char *URL, const char *encoding, int options)
5732 {
5733     xmlParserInputBufferPtr input;
5734 
5735     if (ioread == NULL)
5736         return (-1);
5737     if (reader == NULL)
5738         return (-1);
5739 
5740     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5741                                          XML_CHAR_ENCODING_NONE);
5742     if (input == NULL) {
5743         if (ioclose != NULL)
5744             ioclose(ioctx);
5745         return (-1);
5746     }
5747     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5748 }
5749 
5750 /************************************************************************
5751  *									*
5752  *			Utilities					*
5753  *									*
5754  ************************************************************************/
5755 #ifdef NOT_USED_YET
5756 
5757 /**
5758  * xmlBase64Decode:
5759  * @in:  the input buffer
5760  * @inlen:  the size of the input (in), the size read from it (out)
5761  * @to:  the output buffer
5762  * @tolen:  the size of the output (in), the size written to (out)
5763  *
5764  * Base64 decoder, reads from @in and save in @to
5765  * TODO: tell jody when this is actually exported
5766  *
5767  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5768  *         2 if there wasn't enough space on the output or -1 in case of error.
5769  */
5770 static int
xmlBase64Decode(const unsigned char * in,unsigned long * inlen,unsigned char * to,unsigned long * tolen)5771 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5772                 unsigned char *to, unsigned long *tolen)
5773 {
5774     unsigned long incur;        /* current index in in[] */
5775 
5776     unsigned long inblk;        /* last block index in in[] */
5777 
5778     unsigned long outcur;       /* current index in out[] */
5779 
5780     unsigned long inmax;        /* size of in[] */
5781 
5782     unsigned long outmax;       /* size of out[] */
5783 
5784     unsigned char cur;          /* the current value read from in[] */
5785 
5786     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
5787 
5788     int nbintmp;                /* number of byte in intmp[] */
5789 
5790     int is_ignore;              /* cur should be ignored */
5791 
5792     int is_end = 0;             /* the end of the base64 was found */
5793 
5794     int retval = 1;
5795 
5796     int i;
5797 
5798     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5799         return (-1);
5800 
5801     incur = 0;
5802     inblk = 0;
5803     outcur = 0;
5804     inmax = *inlen;
5805     outmax = *tolen;
5806     nbintmp = 0;
5807 
5808     while (1) {
5809         if (incur >= inmax)
5810             break;
5811         cur = in[incur++];
5812         is_ignore = 0;
5813         if ((cur >= 'A') && (cur <= 'Z'))
5814             cur = cur - 'A';
5815         else if ((cur >= 'a') && (cur <= 'z'))
5816             cur = cur - 'a' + 26;
5817         else if ((cur >= '0') && (cur <= '9'))
5818             cur = cur - '0' + 52;
5819         else if (cur == '+')
5820             cur = 62;
5821         else if (cur == '/')
5822             cur = 63;
5823         else if (cur == '.')
5824             cur = 0;
5825         else if (cur == '=')    /*no op , end of the base64 stream */
5826             is_end = 1;
5827         else {
5828             is_ignore = 1;
5829             if (nbintmp == 0)
5830                 inblk = incur;
5831         }
5832 
5833         if (!is_ignore) {
5834             int nbouttmp = 3;
5835 
5836             int is_break = 0;
5837 
5838             if (is_end) {
5839                 if (nbintmp == 0)
5840                     break;
5841                 if ((nbintmp == 1) || (nbintmp == 2))
5842                     nbouttmp = 1;
5843                 else
5844                     nbouttmp = 2;
5845                 nbintmp = 3;
5846                 is_break = 1;
5847             }
5848             intmp[nbintmp++] = cur;
5849             /*
5850              * if intmp is full, push the 4byte sequence as a 3 byte
5851              * sequence out
5852              */
5853             if (nbintmp == 4) {
5854                 nbintmp = 0;
5855                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5856                 outtmp[1] =
5857                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5858                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5859                 if (outcur + 3 >= outmax) {
5860                     retval = 2;
5861                     break;
5862                 }
5863 
5864                 for (i = 0; i < nbouttmp; i++)
5865                     to[outcur++] = outtmp[i];
5866                 inblk = incur;
5867             }
5868 
5869             if (is_break) {
5870                 retval = 0;
5871                 break;
5872             }
5873         }
5874     }
5875 
5876     *tolen = outcur;
5877     *inlen = inblk;
5878     return (retval);
5879 }
5880 
5881 /*
5882  * Test routine for the xmlBase64Decode function
5883  */
5884 #if 0
5885 int
5886 main(int argc, char **argv)
5887 {
5888     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
5889 
5890     char output[100];
5891 
5892     char output2[100];
5893 
5894     char output3[100];
5895 
5896     unsigned long inlen = strlen(input);
5897 
5898     unsigned long outlen = 100;
5899 
5900     int ret;
5901 
5902     unsigned long cons, tmp, tmp2, prod;
5903 
5904     /*
5905      * Direct
5906      */
5907     ret = xmlBase64Decode(input, &inlen, output, &outlen);
5908 
5909     output[outlen] = 0;
5910     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5911            outlen, output)indent: Standard input:179: Error:Unmatched #endif
5912 ;
5913 
5914     /*
5915      * output chunking
5916      */
5917     cons = 0;
5918     prod = 0;
5919     while (cons < inlen) {
5920         tmp = 5;
5921         tmp2 = inlen - cons;
5922 
5923         printf("%ld %ld\n", cons, prod);
5924         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5925         cons += tmp2;
5926         prod += tmp;
5927         printf("%ld %ld\n", cons, prod);
5928     }
5929     output2[outlen] = 0;
5930     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5931            prod, output2);
5932 
5933     /*
5934      * input chunking
5935      */
5936     cons = 0;
5937     prod = 0;
5938     while (cons < inlen) {
5939         tmp = 100 - prod;
5940         tmp2 = inlen - cons;
5941         if (tmp2 > 5)
5942             tmp2 = 5;
5943 
5944         printf("%ld %ld\n", cons, prod);
5945         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5946         cons += tmp2;
5947         prod += tmp;
5948         printf("%ld %ld\n", cons, prod);
5949     }
5950     output3[outlen] = 0;
5951     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5952            prod, output3);
5953     return (0);
5954 
5955 }
5956 #endif
5957 #endif /* NOT_USED_YET */
5958 #define bottom_xmlreader
5959 #include "elfgcchack.h"
5960 #endif /* LIBXML_READER_ENABLED */
5961