• 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->doc;
1715     buff = xmlBufferCreate();
1716     for (cur_node = reader->node->children; cur_node != NULL;
1717          cur_node = cur_node->next) {
1718         node = xmlDocCopyNode(cur_node, doc, 1);
1719         buff2 = xmlBufferCreate();
1720         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1721             xmlFreeNode(node);
1722             xmlBufferFree(buff2);
1723             xmlBufferFree(buff);
1724             return NULL;
1725         }
1726         xmlBufferCat(buff, buff2->content);
1727         xmlFreeNode(node);
1728         xmlBufferFree(buff2);
1729     }
1730     resbuf = buff->content;
1731     buff->content = NULL;
1732 
1733     xmlBufferFree(buff);
1734     return resbuf;
1735 }
1736 #endif
1737 
1738 #ifdef LIBXML_WRITER_ENABLED
1739 /**
1740  * xmlTextReaderReadOuterXml:
1741  * @reader:  the xmlTextReaderPtr used
1742  *
1743  * Reads the contents of the current node, including child nodes and markup.
1744  *
1745  * Returns a string containing the node and any XML content, or NULL if the
1746  *         current node cannot be serialized. The string must be deallocated
1747  *         by the caller.
1748  */
1749 xmlChar *
xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)1750 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1751 {
1752     xmlChar *resbuf;
1753     xmlNodePtr node;
1754     xmlBufferPtr buff;
1755     xmlDocPtr doc;
1756 
1757     node = reader->node;
1758     doc = reader->doc;
1759     if (xmlTextReaderExpand(reader) == NULL) {
1760         return NULL;
1761     }
1762 	if (node->type == XML_DTD_NODE) {
1763 		node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1764 	} else {
1765 		node = xmlDocCopyNode(node, doc, 1);
1766 	}
1767     buff = xmlBufferCreate();
1768     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1769         xmlFreeNode(node);
1770         xmlBufferFree(buff);
1771         return NULL;
1772     }
1773 
1774     resbuf = buff->content;
1775     buff->content = NULL;
1776 
1777     xmlFreeNode(node);
1778     xmlBufferFree(buff);
1779     return resbuf;
1780 }
1781 #endif
1782 
1783 /**
1784  * xmlTextReaderReadString:
1785  * @reader:  the xmlTextReaderPtr used
1786  *
1787  * Reads the contents of an element or a text node as a string.
1788  *
1789  * Returns a string containing the contents of the Element or Text node,
1790  *         or NULL if the reader is positioned on any other type of node.
1791  *         The string must be deallocated by the caller.
1792  */
1793 xmlChar *
xmlTextReaderReadString(xmlTextReaderPtr reader)1794 xmlTextReaderReadString(xmlTextReaderPtr reader)
1795 {
1796     xmlNodePtr node;
1797 
1798     if ((reader == NULL) || (reader->node == NULL))
1799        return(NULL);
1800 
1801     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1802     switch (node->type) {
1803     case XML_TEXT_NODE:
1804        if (node->content != NULL)
1805            return(xmlStrdup(node->content));
1806        break;
1807     case XML_ELEMENT_NODE:
1808 	if (xmlTextReaderDoExpand(reader) != -1) {
1809 	    return xmlTextReaderCollectSiblings(node->children);
1810 	}
1811 	break;
1812     case XML_ATTRIBUTE_NODE:
1813 	TODO
1814 	break;
1815     default:
1816        break;
1817     }
1818     return(NULL);
1819 }
1820 
1821 #if 0
1822 /**
1823  * xmlTextReaderReadBase64:
1824  * @reader:  the xmlTextReaderPtr used
1825  * @array:  a byte array to store the content.
1826  * @offset:  the zero-based index into array where the method should
1827  *           begin to write.
1828  * @len:  the number of bytes to write.
1829  *
1830  * Reads and decodes the Base64 encoded contents of an element and
1831  * stores the result in a byte buffer.
1832  *
1833  * Returns the number of bytes written to array, or zero if the current
1834  *         instance is not positioned on an element or -1 in case of error.
1835  */
1836 int
1837 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1838                         unsigned char *array ATTRIBUTE_UNUSED,
1839 	                int offset ATTRIBUTE_UNUSED,
1840 			int len ATTRIBUTE_UNUSED) {
1841     if ((reader == NULL) || (reader->ctxt == NULL))
1842 	return(-1);
1843     if (reader->ctxt->wellFormed != 1)
1844 	return(-1);
1845 
1846     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1847 	return(0);
1848     TODO
1849     return(0);
1850 }
1851 
1852 /**
1853  * xmlTextReaderReadBinHex:
1854  * @reader:  the xmlTextReaderPtr used
1855  * @array:  a byte array to store the content.
1856  * @offset:  the zero-based index into array where the method should
1857  *           begin to write.
1858  * @len:  the number of bytes to write.
1859  *
1860  * Reads and decodes the BinHex encoded contents of an element and
1861  * stores the result in a byte buffer.
1862  *
1863  * Returns the number of bytes written to array, or zero if the current
1864  *         instance is not positioned on an element or -1 in case of error.
1865  */
1866 int
1867 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1868                         unsigned char *array ATTRIBUTE_UNUSED,
1869 	                int offset ATTRIBUTE_UNUSED,
1870 			int len ATTRIBUTE_UNUSED) {
1871     if ((reader == NULL) || (reader->ctxt == NULL))
1872 	return(-1);
1873     if (reader->ctxt->wellFormed != 1)
1874 	return(-1);
1875 
1876     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1877 	return(0);
1878     TODO
1879     return(0);
1880 }
1881 #endif
1882 
1883 /************************************************************************
1884  *									*
1885  *			Operating on a preparsed tree			*
1886  *									*
1887  ************************************************************************/
1888 static int
xmlTextReaderNextTree(xmlTextReaderPtr reader)1889 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1890 {
1891     if (reader == NULL)
1892         return(-1);
1893 
1894     if (reader->state == XML_TEXTREADER_END)
1895         return(0);
1896 
1897     if (reader->node == NULL) {
1898         if (reader->doc->children == NULL) {
1899             reader->state = XML_TEXTREADER_END;
1900             return(0);
1901         }
1902 
1903         reader->node = reader->doc->children;
1904         reader->state = XML_TEXTREADER_START;
1905         return(1);
1906     }
1907 
1908     if (reader->state != XML_TEXTREADER_BACKTRACK) {
1909 	/* Here removed traversal to child, because we want to skip the subtree,
1910 	replace with traversal to sibling to skip subtree */
1911         if (reader->node->next != 0) {
1912 	    /* Move to sibling if present,skipping sub-tree */
1913             reader->node = reader->node->next;
1914             reader->state = XML_TEXTREADER_START;
1915             return(1);
1916         }
1917 
1918 	/* if reader->node->next is NULL mean no subtree for current node,
1919 	so need to move to sibling of parent node if present */
1920         if ((reader->node->type == XML_ELEMENT_NODE) ||
1921             (reader->node->type == XML_ATTRIBUTE_NODE)) {
1922             reader->state = XML_TEXTREADER_BACKTRACK;
1923 	    /* This will move to parent if present */
1924             xmlTextReaderRead(reader);
1925         }
1926     }
1927 
1928     if (reader->node->next != 0) {
1929         reader->node = reader->node->next;
1930         reader->state = XML_TEXTREADER_START;
1931         return(1);
1932     }
1933 
1934     if (reader->node->parent != 0) {
1935         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1936             reader->state = XML_TEXTREADER_END;
1937             return(0);
1938         }
1939 
1940         reader->node = reader->node->parent;
1941         reader->depth--;
1942         reader->state = XML_TEXTREADER_BACKTRACK;
1943 	/* Repeat process to move to sibling of parent node if present */
1944         xmlTextReaderNextTree(reader);
1945     }
1946 
1947     reader->state = XML_TEXTREADER_END;
1948 
1949     return(1);
1950 }
1951 
1952 /**
1953  * xmlTextReaderReadTree:
1954  * @reader:  the xmlTextReaderPtr used
1955  *
1956  *  Moves the position of the current instance to the next node in
1957  *  the stream, exposing its properties.
1958  *
1959  *  Returns 1 if the node was read successfully, 0 if there is no more
1960  *          nodes to read, or -1 in case of error
1961  */
1962 static int
xmlTextReaderReadTree(xmlTextReaderPtr reader)1963 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1964     if (reader->state == XML_TEXTREADER_END)
1965         return(0);
1966 
1967 next_node:
1968     if (reader->node == NULL) {
1969         if (reader->doc->children == NULL) {
1970             reader->state = XML_TEXTREADER_END;
1971             return(0);
1972         }
1973 
1974         reader->node = reader->doc->children;
1975         reader->state = XML_TEXTREADER_START;
1976         goto found_node;
1977     }
1978 
1979     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1980         (reader->node->type != XML_DTD_NODE) &&
1981         (reader->node->type != XML_XINCLUDE_START) &&
1982 	(reader->node->type != XML_ENTITY_REF_NODE)) {
1983         if (reader->node->children != NULL) {
1984             reader->node = reader->node->children;
1985             reader->depth++;
1986             reader->state = XML_TEXTREADER_START;
1987             goto found_node;
1988         }
1989 
1990         if (reader->node->type == XML_ATTRIBUTE_NODE) {
1991             reader->state = XML_TEXTREADER_BACKTRACK;
1992             goto found_node;
1993         }
1994     }
1995 
1996     if (reader->node->next != NULL) {
1997         reader->node = reader->node->next;
1998         reader->state = XML_TEXTREADER_START;
1999         goto found_node;
2000     }
2001 
2002     if (reader->node->parent != NULL) {
2003         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
2004 	    (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2005             reader->state = XML_TEXTREADER_END;
2006             return(0);
2007         }
2008 
2009         reader->node = reader->node->parent;
2010         reader->depth--;
2011         reader->state = XML_TEXTREADER_BACKTRACK;
2012         goto found_node;
2013     }
2014 
2015     reader->state = XML_TEXTREADER_END;
2016 
2017 found_node:
2018     if ((reader->node->type == XML_XINCLUDE_START) ||
2019         (reader->node->type == XML_XINCLUDE_END))
2020 	goto next_node;
2021 
2022     return(1);
2023 }
2024 
2025 /**
2026  * xmlTextReaderNextSibling:
2027  * @reader:  the xmlTextReaderPtr used
2028  *
2029  * Skip to the node following the current one in document order while
2030  * avoiding the subtree if any.
2031  * Currently implemented only for Readers built on a document
2032  *
2033  * Returns 1 if the node was read successfully, 0 if there is no more
2034  *          nodes to read, or -1 in case of error
2035  */
2036 int
xmlTextReaderNextSibling(xmlTextReaderPtr reader)2037 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2038     if (reader == NULL)
2039         return(-1);
2040     if (reader->doc == NULL) {
2041         /* TODO */
2042 	return(-1);
2043     }
2044 
2045     if (reader->state == XML_TEXTREADER_END)
2046         return(0);
2047 
2048     if (reader->node == NULL)
2049         return(xmlTextReaderNextTree(reader));
2050 
2051     if (reader->node->next != NULL) {
2052         reader->node = reader->node->next;
2053         reader->state = XML_TEXTREADER_START;
2054         return(1);
2055     }
2056 
2057     return(0);
2058 }
2059 
2060 /************************************************************************
2061  *									*
2062  *			Constructor and destructors			*
2063  *									*
2064  ************************************************************************/
2065 /**
2066  * xmlNewTextReader:
2067  * @input: the xmlParserInputBufferPtr used to read data
2068  * @URI: the URI information for the source if available
2069  *
2070  * Create an xmlTextReader structure fed with @input
2071  *
2072  * Returns the new xmlTextReaderPtr or NULL in case of error
2073  */
2074 xmlTextReaderPtr
xmlNewTextReader(xmlParserInputBufferPtr input,const char * URI)2075 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2076     xmlTextReaderPtr ret;
2077 
2078     if (input == NULL)
2079 	return(NULL);
2080     ret = xmlMalloc(sizeof(xmlTextReader));
2081     if (ret == NULL) {
2082         xmlGenericError(xmlGenericErrorContext,
2083 		"xmlNewTextReader : malloc failed\n");
2084 	return(NULL);
2085     }
2086     memset(ret, 0, sizeof(xmlTextReader));
2087     ret->doc = NULL;
2088     ret->entTab = NULL;
2089     ret->entMax = 0;
2090     ret->entNr = 0;
2091     ret->input = input;
2092     ret->buffer = xmlBufCreateSize(100);
2093     if (ret->buffer == NULL) {
2094         xmlFree(ret);
2095         xmlGenericError(xmlGenericErrorContext,
2096 		"xmlNewTextReader : malloc failed\n");
2097 	return(NULL);
2098     }
2099     /* no operation on a reader should require a huge buffer */
2100     xmlBufSetAllocationScheme(ret->buffer,
2101 			      XML_BUFFER_ALLOC_BOUNDED);
2102     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2103     if (ret->sax == NULL) {
2104 	xmlBufFree(ret->buffer);
2105 	xmlFree(ret);
2106         xmlGenericError(xmlGenericErrorContext,
2107 		"xmlNewTextReader : malloc failed\n");
2108 	return(NULL);
2109     }
2110     xmlSAXVersion(ret->sax, 2);
2111     ret->startElement = ret->sax->startElement;
2112     ret->sax->startElement = xmlTextReaderStartElement;
2113     ret->endElement = ret->sax->endElement;
2114     ret->sax->endElement = xmlTextReaderEndElement;
2115 #ifdef LIBXML_SAX1_ENABLED
2116     if (ret->sax->initialized == XML_SAX2_MAGIC) {
2117 #endif /* LIBXML_SAX1_ENABLED */
2118 	ret->startElementNs = ret->sax->startElementNs;
2119 	ret->sax->startElementNs = xmlTextReaderStartElementNs;
2120 	ret->endElementNs = ret->sax->endElementNs;
2121 	ret->sax->endElementNs = xmlTextReaderEndElementNs;
2122 #ifdef LIBXML_SAX1_ENABLED
2123     } else {
2124 	ret->startElementNs = NULL;
2125 	ret->endElementNs = NULL;
2126     }
2127 #endif /* LIBXML_SAX1_ENABLED */
2128     ret->characters = ret->sax->characters;
2129     ret->sax->characters = xmlTextReaderCharacters;
2130     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2131     ret->cdataBlock = ret->sax->cdataBlock;
2132     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2133 
2134     ret->mode = XML_TEXTREADER_MODE_INITIAL;
2135     ret->node = NULL;
2136     ret->curnode = NULL;
2137     if (xmlBufUse(ret->input->buffer) < 4) {
2138 	xmlParserInputBufferRead(input, 4);
2139     }
2140     if (xmlBufUse(ret->input->buffer) >= 4) {
2141 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2142 			     (const char *) xmlBufContent(ret->input->buffer),
2143                                             4, URI);
2144 	ret->base = 0;
2145 	ret->cur = 4;
2146     } else {
2147 	ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2148 	ret->base = 0;
2149 	ret->cur = 0;
2150     }
2151 
2152     if (ret->ctxt == NULL) {
2153         xmlGenericError(xmlGenericErrorContext,
2154 		"xmlNewTextReader : malloc failed\n");
2155 	xmlBufFree(ret->buffer);
2156 	xmlFree(ret->sax);
2157 	xmlFree(ret);
2158 	return(NULL);
2159     }
2160     ret->ctxt->parseMode = XML_PARSE_READER;
2161     ret->ctxt->_private = ret;
2162     ret->ctxt->linenumbers = 1;
2163     ret->ctxt->dictNames = 1;
2164     ret->allocs = XML_TEXTREADER_CTXT;
2165     /*
2166      * use the parser dictionary to allocate all elements and attributes names
2167      */
2168     ret->ctxt->docdict = 1;
2169     ret->dict = ret->ctxt->dict;
2170 #ifdef LIBXML_XINCLUDE_ENABLED
2171     ret->xinclude = 0;
2172 #endif
2173 #ifdef LIBXML_PATTERN_ENABLED
2174     ret->patternMax = 0;
2175     ret->patternTab = NULL;
2176 #endif
2177     return(ret);
2178 }
2179 
2180 /**
2181  * xmlNewTextReaderFilename:
2182  * @URI: the URI of the resource to process
2183  *
2184  * Create an xmlTextReader structure fed with the resource at @URI
2185  *
2186  * Returns the new xmlTextReaderPtr or NULL in case of error
2187  */
2188 xmlTextReaderPtr
xmlNewTextReaderFilename(const char * URI)2189 xmlNewTextReaderFilename(const char *URI) {
2190     xmlParserInputBufferPtr input;
2191     xmlTextReaderPtr ret;
2192     char *directory = NULL;
2193 
2194     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2195     if (input == NULL)
2196 	return(NULL);
2197     ret = xmlNewTextReader(input, URI);
2198     if (ret == NULL) {
2199 	xmlFreeParserInputBuffer(input);
2200 	return(NULL);
2201     }
2202     ret->allocs |= XML_TEXTREADER_INPUT;
2203     if (ret->ctxt->directory == NULL)
2204         directory = xmlParserGetDirectory(URI);
2205     if ((ret->ctxt->directory == NULL) && (directory != NULL))
2206         ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2207     if (directory != NULL)
2208 	xmlFree(directory);
2209     return(ret);
2210 }
2211 
2212 /**
2213  * xmlFreeTextReader:
2214  * @reader:  the xmlTextReaderPtr
2215  *
2216  * Deallocate all the resources associated to the reader
2217  */
2218 void
xmlFreeTextReader(xmlTextReaderPtr reader)2219 xmlFreeTextReader(xmlTextReaderPtr reader) {
2220     if (reader == NULL)
2221 	return;
2222 #ifdef LIBXML_SCHEMAS_ENABLED
2223     if (reader->rngSchemas != NULL) {
2224 	xmlRelaxNGFree(reader->rngSchemas);
2225 	reader->rngSchemas = NULL;
2226     }
2227     if (reader->rngValidCtxt != NULL) {
2228 	if (! reader->rngPreserveCtxt)
2229 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2230 	reader->rngValidCtxt = NULL;
2231     }
2232     if (reader->xsdPlug != NULL) {
2233 	xmlSchemaSAXUnplug(reader->xsdPlug);
2234 	reader->xsdPlug = NULL;
2235     }
2236     if (reader->xsdValidCtxt != NULL) {
2237 	if (! reader->xsdPreserveCtxt)
2238 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2239 	reader->xsdValidCtxt = NULL;
2240     }
2241     if (reader->xsdSchemas != NULL) {
2242 	xmlSchemaFree(reader->xsdSchemas);
2243 	reader->xsdSchemas = NULL;
2244     }
2245 #endif
2246 #ifdef LIBXML_XINCLUDE_ENABLED
2247     if (reader->xincctxt != NULL)
2248 	xmlXIncludeFreeContext(reader->xincctxt);
2249 #endif
2250 #ifdef LIBXML_PATTERN_ENABLED
2251     if (reader->patternTab != NULL) {
2252         int i;
2253 	for (i = 0;i < reader->patternNr;i++) {
2254 	    if (reader->patternTab[i] != NULL)
2255 	        xmlFreePattern(reader->patternTab[i]);
2256 	}
2257 	xmlFree(reader->patternTab);
2258     }
2259 #endif
2260     if (reader->faketext != NULL) {
2261 	xmlFreeNode(reader->faketext);
2262     }
2263     if (reader->ctxt != NULL) {
2264         if (reader->dict == reader->ctxt->dict)
2265 	    reader->dict = NULL;
2266 	if (reader->ctxt->myDoc != NULL) {
2267 	    if (reader->preserve == 0)
2268 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2269 	    reader->ctxt->myDoc = NULL;
2270 	}
2271 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2272 	    (reader->ctxt->vctxt.vstateMax > 0)){
2273 	    xmlFree(reader->ctxt->vctxt.vstateTab);
2274 	    reader->ctxt->vctxt.vstateTab = NULL;
2275 	    reader->ctxt->vctxt.vstateMax = 0;
2276 	}
2277 	if (reader->allocs & XML_TEXTREADER_CTXT)
2278 	    xmlFreeParserCtxt(reader->ctxt);
2279     }
2280     if (reader->sax != NULL)
2281 	xmlFree(reader->sax);
2282     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
2283 	xmlFreeParserInputBuffer(reader->input);
2284     if (reader->buffer != NULL)
2285         xmlBufFree(reader->buffer);
2286     if (reader->entTab != NULL)
2287 	xmlFree(reader->entTab);
2288     if (reader->dict != NULL)
2289         xmlDictFree(reader->dict);
2290     xmlFree(reader);
2291 }
2292 
2293 /************************************************************************
2294  *									*
2295  *			Methods for XmlTextReader			*
2296  *									*
2297  ************************************************************************/
2298 /**
2299  * xmlTextReaderClose:
2300  * @reader:  the xmlTextReaderPtr used
2301  *
2302  * This method releases any resources allocated by the current instance
2303  * changes the state to Closed and close any underlying input.
2304  *
2305  * Returns 0 or -1 in case of error
2306  */
2307 int
xmlTextReaderClose(xmlTextReaderPtr reader)2308 xmlTextReaderClose(xmlTextReaderPtr reader) {
2309     if (reader == NULL)
2310 	return(-1);
2311     reader->node = NULL;
2312     reader->curnode = NULL;
2313     reader->mode = XML_TEXTREADER_MODE_CLOSED;
2314     if (reader->ctxt != NULL) {
2315 	xmlStopParser(reader->ctxt);
2316 	if (reader->ctxt->myDoc != NULL) {
2317 	    if (reader->preserve == 0)
2318 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2319 	    reader->ctxt->myDoc = NULL;
2320 	}
2321     }
2322     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
2323 	xmlFreeParserInputBuffer(reader->input);
2324 	reader->allocs -= XML_TEXTREADER_INPUT;
2325     }
2326     return(0);
2327 }
2328 
2329 /**
2330  * xmlTextReaderGetAttributeNo:
2331  * @reader:  the xmlTextReaderPtr used
2332  * @no: the zero-based index of the attribute relative to the containing element
2333  *
2334  * Provides the value of the attribute with the specified index relative
2335  * to the containing element.
2336  *
2337  * Returns a string containing the value of the specified attribute, or NULL
2338  *    in case of error. The string must be deallocated by the caller.
2339  */
2340 xmlChar *
xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader,int no)2341 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2342     xmlChar *ret;
2343     int i;
2344     xmlAttrPtr cur;
2345     xmlNsPtr ns;
2346 
2347     if (reader == NULL)
2348 	return(NULL);
2349     if (reader->node == NULL)
2350 	return(NULL);
2351     if (reader->curnode != NULL)
2352 	return(NULL);
2353     /* TODO: handle the xmlDecl */
2354     if (reader->node->type != XML_ELEMENT_NODE)
2355 	return(NULL);
2356 
2357     ns = reader->node->nsDef;
2358     for (i = 0;(i < no) && (ns != NULL);i++) {
2359 	ns = ns->next;
2360     }
2361     if (ns != NULL)
2362 	return(xmlStrdup(ns->href));
2363 
2364     cur = reader->node->properties;
2365     if (cur == NULL)
2366 	return(NULL);
2367     for (;i < no;i++) {
2368 	cur = cur->next;
2369 	if (cur == NULL)
2370 	    return(NULL);
2371     }
2372     /* TODO walk the DTD if present */
2373 
2374     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2375     if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2376     return(ret);
2377 }
2378 
2379 /**
2380  * xmlTextReaderGetAttribute:
2381  * @reader:  the xmlTextReaderPtr used
2382  * @name: the qualified name of the attribute.
2383  *
2384  * Provides the value of the attribute with the specified qualified name.
2385  *
2386  * Returns a string containing the value of the specified attribute, or NULL
2387  *    in case of error. The string must be deallocated by the caller.
2388  */
2389 xmlChar *
xmlTextReaderGetAttribute(xmlTextReaderPtr reader,const xmlChar * name)2390 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2391     xmlChar *prefix = NULL;
2392     xmlChar *localname;
2393     xmlNsPtr ns;
2394     xmlChar *ret = NULL;
2395 
2396     if ((reader == NULL) || (name == NULL))
2397 	return(NULL);
2398     if (reader->node == NULL)
2399 	return(NULL);
2400     if (reader->curnode != NULL)
2401 	return(NULL);
2402 
2403     /* TODO: handle the xmlDecl */
2404     if (reader->node->type != XML_ELEMENT_NODE)
2405 	return(NULL);
2406 
2407     localname = xmlSplitQName2(name, &prefix);
2408     if (localname == NULL) {
2409 		/*
2410 		 * Namespace default decl
2411 		 */
2412 		if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2413 			ns = reader->node->nsDef;
2414 			while (ns != NULL) {
2415 				if (ns->prefix == NULL) {
2416 					return(xmlStrdup(ns->href));
2417 				}
2418 				ns = ns->next;
2419 			}
2420 			return NULL;
2421 		}
2422 		return(xmlGetNoNsProp(reader->node, name));
2423 	}
2424 
2425     /*
2426      * Namespace default decl
2427      */
2428     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2429 		ns = reader->node->nsDef;
2430 		while (ns != NULL) {
2431 			if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2432 				ret = xmlStrdup(ns->href);
2433 				break;
2434 			}
2435 			ns = ns->next;
2436 		}
2437     } else {
2438 		ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2439 		if (ns != NULL)
2440 			ret = xmlGetNsProp(reader->node, localname, ns->href);
2441 	}
2442 
2443     xmlFree(localname);
2444     if (prefix != NULL)
2445         xmlFree(prefix);
2446     return(ret);
2447 }
2448 
2449 
2450 /**
2451  * xmlTextReaderGetAttributeNs:
2452  * @reader:  the xmlTextReaderPtr used
2453  * @localName: the local name of the attribute.
2454  * @namespaceURI: the namespace URI of the attribute.
2455  *
2456  * Provides the value of the specified attribute
2457  *
2458  * Returns a string containing the value of the specified attribute, or NULL
2459  *    in case of error. The string must be deallocated by the caller.
2460  */
2461 xmlChar *
xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader,const xmlChar * localName,const xmlChar * namespaceURI)2462 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2463 			    const xmlChar *namespaceURI) {
2464     xmlChar *prefix = NULL;
2465     xmlNsPtr ns;
2466 
2467     if ((reader == NULL) || (localName == NULL))
2468 	return(NULL);
2469     if (reader->node == NULL)
2470 	return(NULL);
2471     if (reader->curnode != NULL)
2472 	return(NULL);
2473 
2474     /* TODO: handle the xmlDecl */
2475     if (reader->node->type != XML_ELEMENT_NODE)
2476 	return(NULL);
2477 
2478     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2479 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2480 			prefix = BAD_CAST localName;
2481 		}
2482 		ns = reader->node->nsDef;
2483 		while (ns != NULL) {
2484 			if ((prefix == NULL && ns->prefix == NULL) ||
2485 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2486 				return xmlStrdup(ns->href);
2487 			}
2488 			ns = ns->next;
2489 		}
2490 		return NULL;
2491     }
2492 
2493     return(xmlGetNsProp(reader->node, localName, namespaceURI));
2494 }
2495 
2496 /**
2497  * xmlTextReaderGetRemainder:
2498  * @reader:  the xmlTextReaderPtr used
2499  *
2500  * Method to get the remainder of the buffered XML. this method stops the
2501  * parser, set its state to End Of File and return the input stream with
2502  * what is left that the parser did not use.
2503  *
2504  * The implementation is not good, the parser certainly procgressed past
2505  * what's left in reader->input, and there is an allocation problem. Best
2506  * would be to rewrite it differently.
2507  *
2508  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2509  *    in case of error.
2510  */
2511 xmlParserInputBufferPtr
xmlTextReaderGetRemainder(xmlTextReaderPtr reader)2512 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2513     xmlParserInputBufferPtr ret = NULL;
2514 
2515     if (reader == NULL)
2516 	return(NULL);
2517     if (reader->node == NULL)
2518 	return(NULL);
2519 
2520     reader->node = NULL;
2521     reader->curnode = NULL;
2522     reader->mode = XML_TEXTREADER_MODE_EOF;
2523     if (reader->ctxt != NULL) {
2524 	xmlStopParser(reader->ctxt);
2525 	if (reader->ctxt->myDoc != NULL) {
2526 	    if (reader->preserve == 0)
2527 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2528 	    reader->ctxt->myDoc = NULL;
2529 	}
2530     }
2531     if (reader->allocs & XML_TEXTREADER_INPUT) {
2532 	ret = reader->input;
2533 	reader->input = NULL;
2534 	reader->allocs -= XML_TEXTREADER_INPUT;
2535     } else {
2536 	/*
2537 	 * Hum, one may need to duplicate the data structure because
2538 	 * without reference counting the input may be freed twice:
2539 	 *   - by the layer which allocated it.
2540 	 *   - by the layer to which would have been returned to.
2541 	 */
2542 	TODO
2543 	return(NULL);
2544     }
2545     return(ret);
2546 }
2547 
2548 /**
2549  * xmlTextReaderLookupNamespace:
2550  * @reader:  the xmlTextReaderPtr used
2551  * @prefix: the prefix whose namespace URI is to be resolved. To return
2552  *          the default namespace, specify NULL
2553  *
2554  * Resolves a namespace prefix in the scope of the current element.
2555  *
2556  * Returns a string containing the namespace URI to which the prefix maps
2557  *    or NULL in case of error. The string must be deallocated by the caller.
2558  */
2559 xmlChar *
xmlTextReaderLookupNamespace(xmlTextReaderPtr reader,const xmlChar * prefix)2560 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2561     xmlNsPtr ns;
2562 
2563     if (reader == NULL)
2564 	return(NULL);
2565     if (reader->node == NULL)
2566 	return(NULL);
2567 
2568     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2569     if (ns == NULL)
2570 	return(NULL);
2571     return(xmlStrdup(ns->href));
2572 }
2573 
2574 /**
2575  * xmlTextReaderMoveToAttributeNo:
2576  * @reader:  the xmlTextReaderPtr used
2577  * @no: the zero-based index of the attribute relative to the containing
2578  *      element.
2579  *
2580  * Moves the position of the current instance to the attribute with
2581  * the specified index relative to the containing element.
2582  *
2583  * Returns 1 in case of success, -1 in case of error, 0 if not found
2584  */
2585 int
xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader,int no)2586 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2587     int i;
2588     xmlAttrPtr cur;
2589     xmlNsPtr ns;
2590 
2591     if (reader == NULL)
2592 	return(-1);
2593     if (reader->node == NULL)
2594 	return(-1);
2595     /* TODO: handle the xmlDecl */
2596     if (reader->node->type != XML_ELEMENT_NODE)
2597 	return(-1);
2598 
2599     reader->curnode = NULL;
2600 
2601     ns = reader->node->nsDef;
2602     for (i = 0;(i < no) && (ns != NULL);i++) {
2603 	ns = ns->next;
2604     }
2605     if (ns != NULL) {
2606 	reader->curnode = (xmlNodePtr) ns;
2607 	return(1);
2608     }
2609 
2610     cur = reader->node->properties;
2611     if (cur == NULL)
2612 	return(0);
2613     for (;i < no;i++) {
2614 	cur = cur->next;
2615 	if (cur == NULL)
2616 	    return(0);
2617     }
2618     /* TODO walk the DTD if present */
2619 
2620     reader->curnode = (xmlNodePtr) cur;
2621     return(1);
2622 }
2623 
2624 /**
2625  * xmlTextReaderMoveToAttribute:
2626  * @reader:  the xmlTextReaderPtr used
2627  * @name: the qualified name of the attribute.
2628  *
2629  * Moves the position of the current instance to the attribute with
2630  * the specified qualified name.
2631  *
2632  * Returns 1 in case of success, -1 in case of error, 0 if not found
2633  */
2634 int
xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader,const xmlChar * name)2635 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2636     xmlChar *prefix = NULL;
2637     xmlChar *localname;
2638     xmlNsPtr ns;
2639     xmlAttrPtr prop;
2640 
2641     if ((reader == NULL) || (name == NULL))
2642 	return(-1);
2643     if (reader->node == NULL)
2644 	return(-1);
2645 
2646     /* TODO: handle the xmlDecl */
2647     if (reader->node->type != XML_ELEMENT_NODE)
2648 	return(0);
2649 
2650     localname = xmlSplitQName2(name, &prefix);
2651     if (localname == NULL) {
2652 	/*
2653 	 * Namespace default decl
2654 	 */
2655 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2656 	    ns = reader->node->nsDef;
2657 	    while (ns != NULL) {
2658 		if (ns->prefix == NULL) {
2659 		    reader->curnode = (xmlNodePtr) ns;
2660 		    return(1);
2661 		}
2662 		ns = ns->next;
2663 	    }
2664 	    return(0);
2665 	}
2666 
2667 	prop = reader->node->properties;
2668 	while (prop != NULL) {
2669 	    /*
2670 	     * One need to have
2671 	     *   - same attribute names
2672 	     *   - and the attribute carrying that namespace
2673 	     */
2674 	    if ((xmlStrEqual(prop->name, name)) &&
2675 		((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2676 		reader->curnode = (xmlNodePtr) prop;
2677 		return(1);
2678 	    }
2679 	    prop = prop->next;
2680 	}
2681 	return(0);
2682     }
2683 
2684     /*
2685      * Namespace default decl
2686      */
2687     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2688 	ns = reader->node->nsDef;
2689 	while (ns != NULL) {
2690 	    if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2691 		reader->curnode = (xmlNodePtr) ns;
2692 		goto found;
2693 	    }
2694 	    ns = ns->next;
2695 	}
2696 	goto not_found;
2697     }
2698     prop = reader->node->properties;
2699     while (prop != NULL) {
2700 	/*
2701 	 * One need to have
2702 	 *   - same attribute names
2703 	 *   - and the attribute carrying that namespace
2704 	 */
2705 	if ((xmlStrEqual(prop->name, localname)) &&
2706 	    (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2707 	    reader->curnode = (xmlNodePtr) prop;
2708 	    goto found;
2709 	}
2710 	prop = prop->next;
2711     }
2712 not_found:
2713     if (localname != NULL)
2714         xmlFree(localname);
2715     if (prefix != NULL)
2716         xmlFree(prefix);
2717     return(0);
2718 
2719 found:
2720     if (localname != NULL)
2721         xmlFree(localname);
2722     if (prefix != NULL)
2723         xmlFree(prefix);
2724     return(1);
2725 }
2726 
2727 /**
2728  * xmlTextReaderMoveToAttributeNs:
2729  * @reader:  the xmlTextReaderPtr used
2730  * @localName:  the local name of the attribute.
2731  * @namespaceURI:  the namespace URI of the attribute.
2732  *
2733  * Moves the position of the current instance to the attribute with the
2734  * specified local name and namespace URI.
2735  *
2736  * Returns 1 in case of success, -1 in case of error, 0 if not found
2737  */
2738 int
xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,const xmlChar * localName,const xmlChar * namespaceURI)2739 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2740 	const xmlChar *localName, const xmlChar *namespaceURI) {
2741     xmlAttrPtr prop;
2742     xmlNodePtr node;
2743     xmlNsPtr ns;
2744     xmlChar *prefix = NULL;
2745 
2746     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2747 	return(-1);
2748     if (reader->node == NULL)
2749 	return(-1);
2750     if (reader->node->type != XML_ELEMENT_NODE)
2751 	return(0);
2752     node = reader->node;
2753 
2754     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2755 		if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2756 			prefix = BAD_CAST localName;
2757 		}
2758 		ns = reader->node->nsDef;
2759 		while (ns != NULL) {
2760 			if ((prefix == NULL && ns->prefix == NULL) ||
2761 				((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2762 				reader->curnode = (xmlNodePtr) ns;
2763 				return(1);
2764 			}
2765 			ns = ns->next;
2766 		}
2767 		return(0);
2768     }
2769 
2770     prop = node->properties;
2771     while (prop != NULL) {
2772 	/*
2773 	 * One need to have
2774 	 *   - same attribute names
2775 	 *   - and the attribute carrying that namespace
2776 	 */
2777         if (xmlStrEqual(prop->name, localName) &&
2778 	    ((prop->ns != NULL) &&
2779 	     (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2780 	    reader->curnode = (xmlNodePtr) prop;
2781 	    return(1);
2782         }
2783 	prop = prop->next;
2784     }
2785     return(0);
2786 }
2787 
2788 /**
2789  * xmlTextReaderMoveToFirstAttribute:
2790  * @reader:  the xmlTextReaderPtr used
2791  *
2792  * Moves the position of the current instance to the first attribute
2793  * associated with the current node.
2794  *
2795  * Returns 1 in case of success, -1 in case of error, 0 if not found
2796  */
2797 int
xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader)2798 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2799     if (reader == NULL)
2800 	return(-1);
2801     if (reader->node == NULL)
2802 	return(-1);
2803     if (reader->node->type != XML_ELEMENT_NODE)
2804 	return(0);
2805 
2806     if (reader->node->nsDef != NULL) {
2807 	reader->curnode = (xmlNodePtr) reader->node->nsDef;
2808 	return(1);
2809     }
2810     if (reader->node->properties != NULL) {
2811 	reader->curnode = (xmlNodePtr) reader->node->properties;
2812 	return(1);
2813     }
2814     return(0);
2815 }
2816 
2817 /**
2818  * xmlTextReaderMoveToNextAttribute:
2819  * @reader:  the xmlTextReaderPtr used
2820  *
2821  * Moves the position of the current instance to the next attribute
2822  * associated with the current node.
2823  *
2824  * Returns 1 in case of success, -1 in case of error, 0 if not found
2825  */
2826 int
xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader)2827 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2828     if (reader == NULL)
2829 	return(-1);
2830     if (reader->node == NULL)
2831 	return(-1);
2832     if (reader->node->type != XML_ELEMENT_NODE)
2833 	return(0);
2834     if (reader->curnode == NULL)
2835 	return(xmlTextReaderMoveToFirstAttribute(reader));
2836 
2837     if (reader->curnode->type == XML_NAMESPACE_DECL) {
2838 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2839 	if (ns->next != NULL) {
2840 	    reader->curnode = (xmlNodePtr) ns->next;
2841 	    return(1);
2842 	}
2843 	if (reader->node->properties != NULL) {
2844 	    reader->curnode = (xmlNodePtr) reader->node->properties;
2845 	    return(1);
2846 	}
2847 	return(0);
2848     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2849 	       (reader->curnode->next != NULL)) {
2850 	reader->curnode = reader->curnode->next;
2851 	return(1);
2852     }
2853     return(0);
2854 }
2855 
2856 /**
2857  * xmlTextReaderMoveToElement:
2858  * @reader:  the xmlTextReaderPtr used
2859  *
2860  * Moves the position of the current instance to the node that
2861  * contains the current Attribute  node.
2862  *
2863  * Returns 1 in case of success, -1 in case of error, 0 if not moved
2864  */
2865 int
xmlTextReaderMoveToElement(xmlTextReaderPtr reader)2866 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2867     if (reader == NULL)
2868 	return(-1);
2869     if (reader->node == NULL)
2870 	return(-1);
2871     if (reader->node->type != XML_ELEMENT_NODE)
2872 	return(0);
2873     if (reader->curnode != NULL) {
2874 	reader->curnode = NULL;
2875 	return(1);
2876     }
2877     return(0);
2878 }
2879 
2880 /**
2881  * xmlTextReaderReadAttributeValue:
2882  * @reader:  the xmlTextReaderPtr used
2883  *
2884  * Parses an attribute value into one or more Text and EntityReference nodes.
2885  *
2886  * Returns 1 in case of success, 0 if the reader was not positionned on an
2887  *         ttribute node or all the attribute values have been read, or -1
2888  *         in case of error.
2889  */
2890 int
xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader)2891 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2892     if (reader == NULL)
2893 	return(-1);
2894     if (reader->node == NULL)
2895 	return(-1);
2896     if (reader->curnode == NULL)
2897 	return(0);
2898     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2899 	if (reader->curnode->children == NULL)
2900 	    return(0);
2901 	reader->curnode = reader->curnode->children;
2902     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2903 	xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2904 
2905 	if (reader->faketext == NULL) {
2906 	    reader->faketext = xmlNewDocText(reader->node->doc,
2907 		                             ns->href);
2908 	} else {
2909             if ((reader->faketext->content != NULL) &&
2910 	        (reader->faketext->content !=
2911 		 (xmlChar *) &(reader->faketext->properties)))
2912 		xmlFree(reader->faketext->content);
2913 	    reader->faketext->content = xmlStrdup(ns->href);
2914 	}
2915 	reader->curnode = reader->faketext;
2916     } else {
2917 	if (reader->curnode->next == NULL)
2918 	    return(0);
2919 	reader->curnode = reader->curnode->next;
2920     }
2921     return(1);
2922 }
2923 
2924 /**
2925  * xmlTextReaderConstEncoding:
2926  * @reader:  the xmlTextReaderPtr used
2927  *
2928  * Determine the encoding of the document being read.
2929  *
2930  * Returns a string containing the encoding of the document or NULL in
2931  * case of error.  The string is deallocated with the reader.
2932  */
2933 const xmlChar *
xmlTextReaderConstEncoding(xmlTextReaderPtr reader)2934 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2935     xmlDocPtr doc = NULL;
2936     if (reader == NULL)
2937 	return(NULL);
2938     if (reader->doc != NULL)
2939         doc = reader->doc;
2940     else if (reader->ctxt != NULL)
2941 	doc = reader->ctxt->myDoc;
2942     if (doc == NULL)
2943 	return(NULL);
2944 
2945     if (doc->encoding == NULL)
2946 	return(NULL);
2947     else
2948       return(CONSTSTR(doc->encoding));
2949 }
2950 
2951 
2952 /************************************************************************
2953  *									*
2954  *			Acces API to the current node			*
2955  *									*
2956  ************************************************************************/
2957 /**
2958  * xmlTextReaderAttributeCount:
2959  * @reader:  the xmlTextReaderPtr used
2960  *
2961  * Provides the number of attributes of the current node
2962  *
2963  * Returns 0 i no attributes, -1 in case of error or the attribute count
2964  */
2965 int
xmlTextReaderAttributeCount(xmlTextReaderPtr reader)2966 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2967     int ret;
2968     xmlAttrPtr attr;
2969     xmlNsPtr ns;
2970     xmlNodePtr node;
2971 
2972     if (reader == NULL)
2973 	return(-1);
2974     if (reader->node == NULL)
2975 	return(0);
2976 
2977     if (reader->curnode != NULL)
2978 	node = reader->curnode;
2979     else
2980 	node = reader->node;
2981 
2982     if (node->type != XML_ELEMENT_NODE)
2983 	return(0);
2984     if ((reader->state == XML_TEXTREADER_END) ||
2985 	(reader->state == XML_TEXTREADER_BACKTRACK))
2986 	return(0);
2987     ret = 0;
2988     attr = node->properties;
2989     while (attr != NULL) {
2990 	ret++;
2991 	attr = attr->next;
2992     }
2993     ns = node->nsDef;
2994     while (ns != NULL) {
2995 	ret++;
2996 	ns = ns->next;
2997     }
2998     return(ret);
2999 }
3000 
3001 /**
3002  * xmlTextReaderNodeType:
3003  * @reader:  the xmlTextReaderPtr used
3004  *
3005  * Get the node type of the current node
3006  * Reference:
3007  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
3008  *
3009  * Returns the xmlNodeType of the current node or -1 in case of error
3010  */
3011 int
xmlTextReaderNodeType(xmlTextReaderPtr reader)3012 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
3013     xmlNodePtr node;
3014 
3015     if (reader == NULL)
3016 	return(-1);
3017     if (reader->node == NULL)
3018 	return(XML_READER_TYPE_NONE);
3019     if (reader->curnode != NULL)
3020 	node = reader->curnode;
3021     else
3022 	node = reader->node;
3023     switch (node->type) {
3024         case XML_ELEMENT_NODE:
3025 	    if ((reader->state == XML_TEXTREADER_END) ||
3026 		(reader->state == XML_TEXTREADER_BACKTRACK))
3027 		return(XML_READER_TYPE_END_ELEMENT);
3028 	    return(XML_READER_TYPE_ELEMENT);
3029         case XML_NAMESPACE_DECL:
3030         case XML_ATTRIBUTE_NODE:
3031 	    return(XML_READER_TYPE_ATTRIBUTE);
3032         case XML_TEXT_NODE:
3033 	    if (xmlIsBlankNode(reader->node)) {
3034 		if (xmlNodeGetSpacePreserve(reader->node))
3035 		    return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3036 		else
3037 		    return(XML_READER_TYPE_WHITESPACE);
3038 	    } else {
3039 		return(XML_READER_TYPE_TEXT);
3040 	    }
3041         case XML_CDATA_SECTION_NODE:
3042 	    return(XML_READER_TYPE_CDATA);
3043         case XML_ENTITY_REF_NODE:
3044 	    return(XML_READER_TYPE_ENTITY_REFERENCE);
3045         case XML_ENTITY_NODE:
3046 	    return(XML_READER_TYPE_ENTITY);
3047         case XML_PI_NODE:
3048 	    return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3049         case XML_COMMENT_NODE:
3050 	    return(XML_READER_TYPE_COMMENT);
3051         case XML_DOCUMENT_NODE:
3052         case XML_HTML_DOCUMENT_NODE:
3053 #ifdef LIBXML_DOCB_ENABLED
3054         case XML_DOCB_DOCUMENT_NODE:
3055 #endif
3056 	    return(XML_READER_TYPE_DOCUMENT);
3057         case XML_DOCUMENT_FRAG_NODE:
3058 	    return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3059         case XML_NOTATION_NODE:
3060 	    return(XML_READER_TYPE_NOTATION);
3061         case XML_DOCUMENT_TYPE_NODE:
3062         case XML_DTD_NODE:
3063 	    return(XML_READER_TYPE_DOCUMENT_TYPE);
3064 
3065         case XML_ELEMENT_DECL:
3066         case XML_ATTRIBUTE_DECL:
3067         case XML_ENTITY_DECL:
3068         case XML_XINCLUDE_START:
3069         case XML_XINCLUDE_END:
3070 	    return(XML_READER_TYPE_NONE);
3071     }
3072     return(-1);
3073 }
3074 
3075 /**
3076  * xmlTextReaderIsEmptyElement:
3077  * @reader:  the xmlTextReaderPtr used
3078  *
3079  * Check if the current node is empty
3080  *
3081  * Returns 1 if empty, 0 if not and -1 in case of error
3082  */
3083 int
xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader)3084 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3085     if ((reader == NULL) || (reader->node == NULL))
3086 	return(-1);
3087     if (reader->node->type != XML_ELEMENT_NODE)
3088 	return(0);
3089     if (reader->curnode != NULL)
3090 	return(0);
3091     if (reader->node->children != NULL)
3092 	return(0);
3093     if (reader->state == XML_TEXTREADER_END)
3094 	return(0);
3095     if (reader->doc != NULL)
3096         return(1);
3097 #ifdef LIBXML_XINCLUDE_ENABLED
3098     if (reader->in_xinclude > 0)
3099         return(1);
3100 #endif
3101     return((reader->node->extra & NODE_IS_EMPTY) != 0);
3102 }
3103 
3104 /**
3105  * xmlTextReaderLocalName:
3106  * @reader:  the xmlTextReaderPtr used
3107  *
3108  * The local name of the node.
3109  *
3110  * Returns the local name or NULL if not available,
3111  *   if non NULL it need to be freed by the caller.
3112  */
3113 xmlChar *
xmlTextReaderLocalName(xmlTextReaderPtr reader)3114 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3115     xmlNodePtr node;
3116     if ((reader == NULL) || (reader->node == NULL))
3117 	return(NULL);
3118     if (reader->curnode != NULL)
3119 	node = reader->curnode;
3120     else
3121 	node = reader->node;
3122     if (node->type == XML_NAMESPACE_DECL) {
3123 	xmlNsPtr ns = (xmlNsPtr) node;
3124 	if (ns->prefix == NULL)
3125 	    return(xmlStrdup(BAD_CAST "xmlns"));
3126 	else
3127 	    return(xmlStrdup(ns->prefix));
3128     }
3129     if ((node->type != XML_ELEMENT_NODE) &&
3130 	(node->type != XML_ATTRIBUTE_NODE))
3131 	return(xmlTextReaderName(reader));
3132     return(xmlStrdup(node->name));
3133 }
3134 
3135 /**
3136  * xmlTextReaderConstLocalName:
3137  * @reader:  the xmlTextReaderPtr used
3138  *
3139  * The local name of the node.
3140  *
3141  * Returns the local name or NULL if not available, the
3142  *         string will be deallocated with the reader.
3143  */
3144 const xmlChar *
xmlTextReaderConstLocalName(xmlTextReaderPtr reader)3145 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3146     xmlNodePtr node;
3147     if ((reader == NULL) || (reader->node == NULL))
3148 	return(NULL);
3149     if (reader->curnode != NULL)
3150 	node = reader->curnode;
3151     else
3152 	node = reader->node;
3153     if (node->type == XML_NAMESPACE_DECL) {
3154 	xmlNsPtr ns = (xmlNsPtr) node;
3155 	if (ns->prefix == NULL)
3156 	    return(CONSTSTR(BAD_CAST "xmlns"));
3157 	else
3158 	    return(ns->prefix);
3159     }
3160     if ((node->type != XML_ELEMENT_NODE) &&
3161 	(node->type != XML_ATTRIBUTE_NODE))
3162 	return(xmlTextReaderConstName(reader));
3163     return(node->name);
3164 }
3165 
3166 /**
3167  * xmlTextReaderName:
3168  * @reader:  the xmlTextReaderPtr used
3169  *
3170  * The qualified name of the node, equal to Prefix :LocalName.
3171  *
3172  * Returns the local name or NULL if not available,
3173  *   if non NULL it need to be freed by the caller.
3174  */
3175 xmlChar *
xmlTextReaderName(xmlTextReaderPtr reader)3176 xmlTextReaderName(xmlTextReaderPtr reader) {
3177     xmlNodePtr node;
3178     xmlChar *ret;
3179 
3180     if ((reader == NULL) || (reader->node == NULL))
3181 	return(NULL);
3182     if (reader->curnode != NULL)
3183 	node = reader->curnode;
3184     else
3185 	node = reader->node;
3186     switch (node->type) {
3187         case XML_ELEMENT_NODE:
3188         case XML_ATTRIBUTE_NODE:
3189 	    if ((node->ns == NULL) ||
3190 		(node->ns->prefix == NULL))
3191 		return(xmlStrdup(node->name));
3192 
3193 	    ret = xmlStrdup(node->ns->prefix);
3194 	    ret = xmlStrcat(ret, BAD_CAST ":");
3195 	    ret = xmlStrcat(ret, node->name);
3196 	    return(ret);
3197         case XML_TEXT_NODE:
3198 	    return(xmlStrdup(BAD_CAST "#text"));
3199         case XML_CDATA_SECTION_NODE:
3200 	    return(xmlStrdup(BAD_CAST "#cdata-section"));
3201         case XML_ENTITY_NODE:
3202         case XML_ENTITY_REF_NODE:
3203 	    return(xmlStrdup(node->name));
3204         case XML_PI_NODE:
3205 	    return(xmlStrdup(node->name));
3206         case XML_COMMENT_NODE:
3207 	    return(xmlStrdup(BAD_CAST "#comment"));
3208         case XML_DOCUMENT_NODE:
3209         case XML_HTML_DOCUMENT_NODE:
3210 #ifdef LIBXML_DOCB_ENABLED
3211         case XML_DOCB_DOCUMENT_NODE:
3212 #endif
3213 	    return(xmlStrdup(BAD_CAST "#document"));
3214         case XML_DOCUMENT_FRAG_NODE:
3215 	    return(xmlStrdup(BAD_CAST "#document-fragment"));
3216         case XML_NOTATION_NODE:
3217 	    return(xmlStrdup(node->name));
3218         case XML_DOCUMENT_TYPE_NODE:
3219         case XML_DTD_NODE:
3220 	    return(xmlStrdup(node->name));
3221         case XML_NAMESPACE_DECL: {
3222 	    xmlNsPtr ns = (xmlNsPtr) node;
3223 
3224 	    ret = xmlStrdup(BAD_CAST "xmlns");
3225 	    if (ns->prefix == NULL)
3226 		return(ret);
3227 	    ret = xmlStrcat(ret, BAD_CAST ":");
3228 	    ret = xmlStrcat(ret, ns->prefix);
3229 	    return(ret);
3230 	}
3231 
3232         case XML_ELEMENT_DECL:
3233         case XML_ATTRIBUTE_DECL:
3234         case XML_ENTITY_DECL:
3235         case XML_XINCLUDE_START:
3236         case XML_XINCLUDE_END:
3237 	    return(NULL);
3238     }
3239     return(NULL);
3240 }
3241 
3242 /**
3243  * xmlTextReaderConstName:
3244  * @reader:  the xmlTextReaderPtr used
3245  *
3246  * The qualified name of the node, equal to Prefix :LocalName.
3247  *
3248  * Returns the local name or NULL if not available, the string is
3249  *         deallocated with the reader.
3250  */
3251 const xmlChar *
xmlTextReaderConstName(xmlTextReaderPtr reader)3252 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3253     xmlNodePtr node;
3254 
3255     if ((reader == NULL) || (reader->node == NULL))
3256 	return(NULL);
3257     if (reader->curnode != NULL)
3258 	node = reader->curnode;
3259     else
3260 	node = reader->node;
3261     switch (node->type) {
3262         case XML_ELEMENT_NODE:
3263         case XML_ATTRIBUTE_NODE:
3264 	    if ((node->ns == NULL) ||
3265 		(node->ns->prefix == NULL))
3266 		return(node->name);
3267 	    return(CONSTQSTR(node->ns->prefix, node->name));
3268         case XML_TEXT_NODE:
3269 	    return(CONSTSTR(BAD_CAST "#text"));
3270         case XML_CDATA_SECTION_NODE:
3271 	    return(CONSTSTR(BAD_CAST "#cdata-section"));
3272         case XML_ENTITY_NODE:
3273         case XML_ENTITY_REF_NODE:
3274 	    return(CONSTSTR(node->name));
3275         case XML_PI_NODE:
3276 	    return(CONSTSTR(node->name));
3277         case XML_COMMENT_NODE:
3278 	    return(CONSTSTR(BAD_CAST "#comment"));
3279         case XML_DOCUMENT_NODE:
3280         case XML_HTML_DOCUMENT_NODE:
3281 #ifdef LIBXML_DOCB_ENABLED
3282         case XML_DOCB_DOCUMENT_NODE:
3283 #endif
3284 	    return(CONSTSTR(BAD_CAST "#document"));
3285         case XML_DOCUMENT_FRAG_NODE:
3286 	    return(CONSTSTR(BAD_CAST "#document-fragment"));
3287         case XML_NOTATION_NODE:
3288 	    return(CONSTSTR(node->name));
3289         case XML_DOCUMENT_TYPE_NODE:
3290         case XML_DTD_NODE:
3291 	    return(CONSTSTR(node->name));
3292         case XML_NAMESPACE_DECL: {
3293 	    xmlNsPtr ns = (xmlNsPtr) node;
3294 
3295 	    if (ns->prefix == NULL)
3296 		return(CONSTSTR(BAD_CAST "xmlns"));
3297 	    return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3298 	}
3299 
3300         case XML_ELEMENT_DECL:
3301         case XML_ATTRIBUTE_DECL:
3302         case XML_ENTITY_DECL:
3303         case XML_XINCLUDE_START:
3304         case XML_XINCLUDE_END:
3305 	    return(NULL);
3306     }
3307     return(NULL);
3308 }
3309 
3310 /**
3311  * xmlTextReaderPrefix:
3312  * @reader:  the xmlTextReaderPtr used
3313  *
3314  * A shorthand reference to the namespace associated with the node.
3315  *
3316  * Returns the prefix or NULL if not available,
3317  *    if non NULL it need to be freed by the caller.
3318  */
3319 xmlChar *
xmlTextReaderPrefix(xmlTextReaderPtr reader)3320 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3321     xmlNodePtr node;
3322     if ((reader == NULL) || (reader->node == NULL))
3323 	return(NULL);
3324     if (reader->curnode != NULL)
3325 	node = reader->curnode;
3326     else
3327 	node = reader->node;
3328     if (node->type == XML_NAMESPACE_DECL) {
3329 	xmlNsPtr ns = (xmlNsPtr) node;
3330 	if (ns->prefix == NULL)
3331 	    return(NULL);
3332 	return(xmlStrdup(BAD_CAST "xmlns"));
3333     }
3334     if ((node->type != XML_ELEMENT_NODE) &&
3335 	(node->type != XML_ATTRIBUTE_NODE))
3336 	return(NULL);
3337     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3338 	return(xmlStrdup(node->ns->prefix));
3339     return(NULL);
3340 }
3341 
3342 /**
3343  * xmlTextReaderConstPrefix:
3344  * @reader:  the xmlTextReaderPtr used
3345  *
3346  * A shorthand reference to the namespace associated with the node.
3347  *
3348  * Returns the prefix or NULL if not available, the string is deallocated
3349  *         with the reader.
3350  */
3351 const xmlChar *
xmlTextReaderConstPrefix(xmlTextReaderPtr reader)3352 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3353     xmlNodePtr node;
3354     if ((reader == NULL) || (reader->node == NULL))
3355 	return(NULL);
3356     if (reader->curnode != NULL)
3357 	node = reader->curnode;
3358     else
3359 	node = reader->node;
3360     if (node->type == XML_NAMESPACE_DECL) {
3361 	xmlNsPtr ns = (xmlNsPtr) node;
3362 	if (ns->prefix == NULL)
3363 	    return(NULL);
3364 	return(CONSTSTR(BAD_CAST "xmlns"));
3365     }
3366     if ((node->type != XML_ELEMENT_NODE) &&
3367 	(node->type != XML_ATTRIBUTE_NODE))
3368 	return(NULL);
3369     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3370 	return(CONSTSTR(node->ns->prefix));
3371     return(NULL);
3372 }
3373 
3374 /**
3375  * xmlTextReaderNamespaceUri:
3376  * @reader:  the xmlTextReaderPtr used
3377  *
3378  * The URI defining the namespace associated with the node.
3379  *
3380  * Returns the namespace URI or NULL if not available,
3381  *    if non NULL it need to be freed by the caller.
3382  */
3383 xmlChar *
xmlTextReaderNamespaceUri(xmlTextReaderPtr reader)3384 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3385     xmlNodePtr node;
3386     if ((reader == NULL) || (reader->node == NULL))
3387 	return(NULL);
3388     if (reader->curnode != NULL)
3389 	node = reader->curnode;
3390     else
3391 	node = reader->node;
3392     if (node->type == XML_NAMESPACE_DECL)
3393 	return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3394     if ((node->type != XML_ELEMENT_NODE) &&
3395 	(node->type != XML_ATTRIBUTE_NODE))
3396 	return(NULL);
3397     if (node->ns != NULL)
3398 	return(xmlStrdup(node->ns->href));
3399     return(NULL);
3400 }
3401 
3402 /**
3403  * xmlTextReaderConstNamespaceUri:
3404  * @reader:  the xmlTextReaderPtr used
3405  *
3406  * The URI defining the namespace associated with the node.
3407  *
3408  * Returns the namespace URI or NULL if not available, the string
3409  *         will be deallocated with the reader
3410  */
3411 const xmlChar *
xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader)3412 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3413     xmlNodePtr node;
3414     if ((reader == NULL) || (reader->node == NULL))
3415 	return(NULL);
3416     if (reader->curnode != NULL)
3417 	node = reader->curnode;
3418     else
3419 	node = reader->node;
3420     if (node->type == XML_NAMESPACE_DECL)
3421 	return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3422     if ((node->type != XML_ELEMENT_NODE) &&
3423 	(node->type != XML_ATTRIBUTE_NODE))
3424 	return(NULL);
3425     if (node->ns != NULL)
3426 	return(CONSTSTR(node->ns->href));
3427     return(NULL);
3428 }
3429 
3430 /**
3431  * xmlTextReaderBaseUri:
3432  * @reader:  the xmlTextReaderPtr used
3433  *
3434  * The base URI of the node.
3435  *
3436  * Returns the base URI or NULL if not available,
3437  *    if non NULL it need to be freed by the caller.
3438  */
3439 xmlChar *
xmlTextReaderBaseUri(xmlTextReaderPtr reader)3440 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3441     if ((reader == NULL) || (reader->node == NULL))
3442 	return(NULL);
3443     return(xmlNodeGetBase(NULL, reader->node));
3444 }
3445 
3446 /**
3447  * xmlTextReaderConstBaseUri:
3448  * @reader:  the xmlTextReaderPtr used
3449  *
3450  * The base URI of the node.
3451  *
3452  * Returns the base URI or NULL if not available, the string
3453  *         will be deallocated with the reader
3454  */
3455 const xmlChar *
xmlTextReaderConstBaseUri(xmlTextReaderPtr reader)3456 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3457     xmlChar *tmp;
3458     const xmlChar *ret;
3459 
3460     if ((reader == NULL) || (reader->node == NULL))
3461 	return(NULL);
3462     tmp = xmlNodeGetBase(NULL, reader->node);
3463     if (tmp == NULL)
3464         return(NULL);
3465     ret = CONSTSTR(tmp);
3466     xmlFree(tmp);
3467     return(ret);
3468 }
3469 
3470 /**
3471  * xmlTextReaderDepth:
3472  * @reader:  the xmlTextReaderPtr used
3473  *
3474  * The depth of the node in the tree.
3475  *
3476  * Returns the depth or -1 in case of error
3477  */
3478 int
xmlTextReaderDepth(xmlTextReaderPtr reader)3479 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3480     if (reader == NULL)
3481 	return(-1);
3482     if (reader->node == NULL)
3483 	return(0);
3484 
3485     if (reader->curnode != NULL) {
3486 	if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3487 	    (reader->curnode->type == XML_NAMESPACE_DECL))
3488 	    return(reader->depth + 1);
3489 	return(reader->depth + 2);
3490     }
3491     return(reader->depth);
3492 }
3493 
3494 /**
3495  * xmlTextReaderHasAttributes:
3496  * @reader:  the xmlTextReaderPtr used
3497  *
3498  * Whether the node has attributes.
3499  *
3500  * Returns 1 if true, 0 if false, and -1 in case or error
3501  */
3502 int
xmlTextReaderHasAttributes(xmlTextReaderPtr reader)3503 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3504     xmlNodePtr node;
3505     if (reader == NULL)
3506 	return(-1);
3507     if (reader->node == NULL)
3508 	return(0);
3509     if (reader->curnode != NULL)
3510 	node = reader->curnode;
3511     else
3512 	node = reader->node;
3513 
3514     if ((node->type == XML_ELEMENT_NODE) &&
3515 	((node->properties != NULL) || (node->nsDef != NULL)))
3516 	return(1);
3517     /* TODO: handle the xmlDecl */
3518     return(0);
3519 }
3520 
3521 /**
3522  * xmlTextReaderHasValue:
3523  * @reader:  the xmlTextReaderPtr used
3524  *
3525  * Whether the node can have a text value.
3526  *
3527  * Returns 1 if true, 0 if false, and -1 in case or error
3528  */
3529 int
xmlTextReaderHasValue(xmlTextReaderPtr reader)3530 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3531     xmlNodePtr node;
3532     if (reader == NULL)
3533 	return(-1);
3534     if (reader->node == NULL)
3535 	return(0);
3536     if (reader->curnode != NULL)
3537 	node = reader->curnode;
3538     else
3539 	node = reader->node;
3540 
3541     switch (node->type) {
3542         case XML_ATTRIBUTE_NODE:
3543         case XML_TEXT_NODE:
3544         case XML_CDATA_SECTION_NODE:
3545         case XML_PI_NODE:
3546         case XML_COMMENT_NODE:
3547         case XML_NAMESPACE_DECL:
3548 	    return(1);
3549 	default:
3550 	    break;
3551     }
3552     return(0);
3553 }
3554 
3555 /**
3556  * xmlTextReaderValue:
3557  * @reader:  the xmlTextReaderPtr used
3558  *
3559  * Provides the text value of the node if present
3560  *
3561  * Returns the string or NULL if not available. The result must be deallocated
3562  *     with xmlFree()
3563  */
3564 xmlChar *
xmlTextReaderValue(xmlTextReaderPtr reader)3565 xmlTextReaderValue(xmlTextReaderPtr reader) {
3566     xmlNodePtr node;
3567     if (reader == NULL)
3568 	return(NULL);
3569     if (reader->node == NULL)
3570 	return(NULL);
3571     if (reader->curnode != NULL)
3572 	node = reader->curnode;
3573     else
3574 	node = reader->node;
3575 
3576     switch (node->type) {
3577         case XML_NAMESPACE_DECL:
3578 	    return(xmlStrdup(((xmlNsPtr) node)->href));
3579         case XML_ATTRIBUTE_NODE:{
3580 	    xmlAttrPtr attr = (xmlAttrPtr) node;
3581 
3582 	    if (attr->parent != NULL)
3583 		return (xmlNodeListGetString
3584 			(attr->parent->doc, attr->children, 1));
3585 	    else
3586 		return (xmlNodeListGetString(NULL, attr->children, 1));
3587 	    break;
3588 	}
3589         case XML_TEXT_NODE:
3590         case XML_CDATA_SECTION_NODE:
3591         case XML_PI_NODE:
3592         case XML_COMMENT_NODE:
3593             if (node->content != NULL)
3594                 return (xmlStrdup(node->content));
3595 	default:
3596 	    break;
3597     }
3598     return(NULL);
3599 }
3600 
3601 /**
3602  * xmlTextReaderConstValue:
3603  * @reader:  the xmlTextReaderPtr used
3604  *
3605  * Provides the text value of the node if present
3606  *
3607  * Returns the string or NULL if not available. The result will be
3608  *     deallocated on the next Read() operation.
3609  */
3610 const xmlChar *
xmlTextReaderConstValue(xmlTextReaderPtr reader)3611 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3612     xmlNodePtr node;
3613     if (reader == NULL)
3614 	return(NULL);
3615     if (reader->node == NULL)
3616 	return(NULL);
3617     if (reader->curnode != NULL)
3618 	node = reader->curnode;
3619     else
3620 	node = reader->node;
3621 
3622     switch (node->type) {
3623         case XML_NAMESPACE_DECL:
3624 	    return(((xmlNsPtr) node)->href);
3625         case XML_ATTRIBUTE_NODE:{
3626 	    xmlAttrPtr attr = (xmlAttrPtr) node;
3627 	    const xmlChar *ret;
3628 
3629 	    if ((attr->children != NULL) &&
3630 	        (attr->children->type == XML_TEXT_NODE) &&
3631 		(attr->children->next == NULL))
3632 		return(attr->children->content);
3633 	    else {
3634 		if (reader->buffer == NULL) {
3635 		    reader->buffer = xmlBufCreateSize(100);
3636                     if (reader->buffer == NULL) {
3637                         xmlGenericError(xmlGenericErrorContext,
3638                                         "xmlTextReaderSetup : malloc failed\n");
3639                         return (NULL);
3640                     }
3641 		    xmlBufSetAllocationScheme(reader->buffer,
3642 		                              XML_BUFFER_ALLOC_BOUNDED);
3643                 } else
3644                     xmlBufEmpty(reader->buffer);
3645 	        xmlBufGetNodeContent(reader->buffer, node);
3646 		ret = xmlBufContent(reader->buffer);
3647 		if (ret == NULL) {
3648 		    /* error on the buffer best to reallocate */
3649 		    xmlBufFree(reader->buffer);
3650 		    reader->buffer = xmlBufCreateSize(100);
3651 		    xmlBufSetAllocationScheme(reader->buffer,
3652 		                              XML_BUFFER_ALLOC_BOUNDED);
3653 		    ret = BAD_CAST "";
3654 		}
3655 		return(ret);
3656 	    }
3657 	    break;
3658 	}
3659         case XML_TEXT_NODE:
3660         case XML_CDATA_SECTION_NODE:
3661         case XML_PI_NODE:
3662         case XML_COMMENT_NODE:
3663 	    return(node->content);
3664 	default:
3665 	    break;
3666     }
3667     return(NULL);
3668 }
3669 
3670 /**
3671  * xmlTextReaderIsDefault:
3672  * @reader:  the xmlTextReaderPtr used
3673  *
3674  * Whether an Attribute  node was generated from the default value
3675  * defined in the DTD or schema.
3676  *
3677  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3678  */
3679 int
xmlTextReaderIsDefault(xmlTextReaderPtr reader)3680 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3681     if (reader == NULL)
3682 	return(-1);
3683     return(0);
3684 }
3685 
3686 /**
3687  * xmlTextReaderQuoteChar:
3688  * @reader:  the xmlTextReaderPtr used
3689  *
3690  * The quotation mark character used to enclose the value of an attribute.
3691  *
3692  * Returns " or ' and -1 in case of error
3693  */
3694 int
xmlTextReaderQuoteChar(xmlTextReaderPtr reader)3695 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3696     if (reader == NULL)
3697 	return(-1);
3698     /* TODO maybe lookup the attribute value for " first */
3699     return((int) '"');
3700 }
3701 
3702 /**
3703  * xmlTextReaderXmlLang:
3704  * @reader:  the xmlTextReaderPtr used
3705  *
3706  * The xml:lang scope within which the node resides.
3707  *
3708  * Returns the xml:lang value or NULL if none exists.,
3709  *    if non NULL it need to be freed by the caller.
3710  */
3711 xmlChar *
xmlTextReaderXmlLang(xmlTextReaderPtr reader)3712 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3713     if (reader == NULL)
3714 	return(NULL);
3715     if (reader->node == NULL)
3716 	return(NULL);
3717     return(xmlNodeGetLang(reader->node));
3718 }
3719 
3720 /**
3721  * xmlTextReaderConstXmlLang:
3722  * @reader:  the xmlTextReaderPtr used
3723  *
3724  * The xml:lang scope within which the node resides.
3725  *
3726  * Returns the xml:lang value or NULL if none exists.
3727  */
3728 const xmlChar *
xmlTextReaderConstXmlLang(xmlTextReaderPtr reader)3729 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3730     xmlChar *tmp;
3731     const xmlChar *ret;
3732 
3733     if (reader == NULL)
3734 	return(NULL);
3735     if (reader->node == NULL)
3736 	return(NULL);
3737     tmp = xmlNodeGetLang(reader->node);
3738     if (tmp == NULL)
3739         return(NULL);
3740     ret = CONSTSTR(tmp);
3741     xmlFree(tmp);
3742     return(ret);
3743 }
3744 
3745 /**
3746  * xmlTextReaderConstString:
3747  * @reader:  the xmlTextReaderPtr used
3748  * @str:  the string to intern.
3749  *
3750  * Get an interned string from the reader, allows for example to
3751  * speedup string name comparisons
3752  *
3753  * Returns an interned copy of the string or NULL in case of error. The
3754  *         string will be deallocated with the reader.
3755  */
3756 const xmlChar *
xmlTextReaderConstString(xmlTextReaderPtr reader,const xmlChar * str)3757 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3758     if (reader == NULL)
3759 	return(NULL);
3760     return(CONSTSTR(str));
3761 }
3762 
3763 /**
3764  * xmlTextReaderNormalization:
3765  * @reader:  the xmlTextReaderPtr used
3766  *
3767  * The value indicating whether to normalize white space and attribute values.
3768  * Since attribute value and end of line normalizations are a MUST in the XML
3769  * specification only the value true is accepted. The broken bahaviour of
3770  * accepting out of range character entities like &#0; is of course not
3771  * supported either.
3772  *
3773  * Returns 1 or -1 in case of error.
3774  */
3775 int
xmlTextReaderNormalization(xmlTextReaderPtr reader)3776 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3777     if (reader == NULL)
3778 	return(-1);
3779     return(1);
3780 }
3781 
3782 /************************************************************************
3783  *									*
3784  *			Extensions to the base APIs			*
3785  *									*
3786  ************************************************************************/
3787 
3788 /**
3789  * xmlTextReaderSetParserProp:
3790  * @reader:  the xmlTextReaderPtr used
3791  * @prop:  the xmlParserProperties to set
3792  * @value:  usually 0 or 1 to (de)activate it
3793  *
3794  * Change the parser processing behaviour by changing some of its internal
3795  * properties. Note that some properties can only be changed before any
3796  * read has been done.
3797  *
3798  * Returns 0 if the call was successful, or -1 in case of error
3799  */
3800 int
xmlTextReaderSetParserProp(xmlTextReaderPtr reader,int prop,int value)3801 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3802     xmlParserProperties p = (xmlParserProperties) prop;
3803     xmlParserCtxtPtr ctxt;
3804 
3805     if ((reader == NULL) || (reader->ctxt == NULL))
3806 	return(-1);
3807     ctxt = reader->ctxt;
3808 
3809     switch (p) {
3810         case XML_PARSER_LOADDTD:
3811 	    if (value != 0) {
3812 		if (ctxt->loadsubset == 0) {
3813 		    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3814 			return(-1);
3815 		    ctxt->loadsubset = XML_DETECT_IDS;
3816 		}
3817 	    } else {
3818 		ctxt->loadsubset = 0;
3819 	    }
3820 	    return(0);
3821         case XML_PARSER_DEFAULTATTRS:
3822 	    if (value != 0) {
3823 		ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3824 	    } else {
3825 		if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3826 		    ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3827 	    }
3828 	    return(0);
3829         case XML_PARSER_VALIDATE:
3830 	    if (value != 0) {
3831 		ctxt->validate = 1;
3832 		reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3833 	    } else {
3834 		ctxt->validate = 0;
3835 	    }
3836 	    return(0);
3837         case XML_PARSER_SUBST_ENTITIES:
3838 	    if (value != 0) {
3839 		ctxt->replaceEntities = 1;
3840 	    } else {
3841 		ctxt->replaceEntities = 0;
3842 	    }
3843 	    return(0);
3844     }
3845     return(-1);
3846 }
3847 
3848 /**
3849  * xmlTextReaderGetParserProp:
3850  * @reader:  the xmlTextReaderPtr used
3851  * @prop:  the xmlParserProperties to get
3852  *
3853  * Read the parser internal property.
3854  *
3855  * Returns the value, usually 0 or 1, or -1 in case of error.
3856  */
3857 int
xmlTextReaderGetParserProp(xmlTextReaderPtr reader,int prop)3858 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3859     xmlParserProperties p = (xmlParserProperties) prop;
3860     xmlParserCtxtPtr ctxt;
3861 
3862     if ((reader == NULL) || (reader->ctxt == NULL))
3863 	return(-1);
3864     ctxt = reader->ctxt;
3865 
3866     switch (p) {
3867         case XML_PARSER_LOADDTD:
3868 	    if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3869 		return(1);
3870 	    return(0);
3871         case XML_PARSER_DEFAULTATTRS:
3872 	    if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3873 		return(1);
3874 	    return(0);
3875         case XML_PARSER_VALIDATE:
3876 	    return(reader->validate);
3877 	case XML_PARSER_SUBST_ENTITIES:
3878 	    return(ctxt->replaceEntities);
3879     }
3880     return(-1);
3881 }
3882 
3883 
3884 /**
3885  * xmlTextReaderGetParserLineNumber:
3886  * @reader: the user data (XML reader context)
3887  *
3888  * Provide the line number of the current parsing point.
3889  *
3890  * Returns an int or 0 if not available
3891  */
3892 int
xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)3893 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3894 {
3895     if ((reader == NULL) || (reader->ctxt == NULL) ||
3896         (reader->ctxt->input == NULL)) {
3897         return (0);
3898     }
3899     return (reader->ctxt->input->line);
3900 }
3901 
3902 /**
3903  * xmlTextReaderGetParserColumnNumber:
3904  * @reader: the user data (XML reader context)
3905  *
3906  * Provide the column number of the current parsing point.
3907  *
3908  * Returns an int or 0 if not available
3909  */
3910 int
xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)3911 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3912 {
3913     if ((reader == NULL) || (reader->ctxt == NULL) ||
3914         (reader->ctxt->input == NULL)) {
3915         return (0);
3916     }
3917     return (reader->ctxt->input->col);
3918 }
3919 
3920 /**
3921  * xmlTextReaderCurrentNode:
3922  * @reader:  the xmlTextReaderPtr used
3923  *
3924  * Hacking interface allowing to get the xmlNodePtr correponding to the
3925  * current node being accessed by the xmlTextReader. This is dangerous
3926  * because the underlying node may be destroyed on the next Reads.
3927  *
3928  * Returns the xmlNodePtr or NULL in case of error.
3929  */
3930 xmlNodePtr
xmlTextReaderCurrentNode(xmlTextReaderPtr reader)3931 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3932     if (reader == NULL)
3933 	return(NULL);
3934 
3935     if (reader->curnode != NULL)
3936 	return(reader->curnode);
3937     return(reader->node);
3938 }
3939 
3940 /**
3941  * xmlTextReaderPreserve:
3942  * @reader:  the xmlTextReaderPtr used
3943  *
3944  * This tells the XML Reader to preserve the current node.
3945  * The caller must also use xmlTextReaderCurrentDoc() to
3946  * keep an handle on the resulting document once parsing has finished
3947  *
3948  * Returns the xmlNodePtr or NULL in case of error.
3949  */
3950 xmlNodePtr
xmlTextReaderPreserve(xmlTextReaderPtr reader)3951 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3952     xmlNodePtr cur, parent;
3953 
3954     if (reader == NULL)
3955 	return(NULL);
3956 
3957     if (reader->curnode != NULL)
3958         cur = reader->curnode;
3959     else
3960         cur = reader->node;
3961     if (cur == NULL)
3962         return(NULL);
3963 
3964     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3965 	cur->extra |= NODE_IS_PRESERVED;
3966 	cur->extra |= NODE_IS_SPRESERVED;
3967     }
3968     reader->preserves++;
3969 
3970     parent = cur->parent;;
3971     while (parent != NULL) {
3972         if (parent->type == XML_ELEMENT_NODE)
3973 	    parent->extra |= NODE_IS_PRESERVED;
3974 	parent = parent->parent;
3975     }
3976     return(cur);
3977 }
3978 
3979 #ifdef LIBXML_PATTERN_ENABLED
3980 /**
3981  * xmlTextReaderPreservePattern:
3982  * @reader:  the xmlTextReaderPtr used
3983  * @pattern:  an XPath subset pattern
3984  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3985  *
3986  * This tells the XML Reader to preserve all nodes matched by the
3987  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3988  * keep an handle on the resulting document once parsing has finished
3989  *
3990  * Returns a non-negative number in case of success and -1 in case of error
3991  */
3992 int
xmlTextReaderPreservePattern(xmlTextReaderPtr reader,const xmlChar * pattern,const xmlChar ** namespaces)3993 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3994                              const xmlChar **namespaces)
3995 {
3996     xmlPatternPtr comp;
3997 
3998     if ((reader == NULL) || (pattern == NULL))
3999 	return(-1);
4000 
4001     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
4002     if (comp == NULL)
4003         return(-1);
4004 
4005     if (reader->patternMax <= 0) {
4006 	reader->patternMax = 4;
4007 	reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4008 					      sizeof(reader->patternTab[0]));
4009         if (reader->patternTab == NULL) {
4010             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4011             return (-1);
4012         }
4013     }
4014     if (reader->patternNr >= reader->patternMax) {
4015         xmlPatternPtr *tmp;
4016         reader->patternMax *= 2;
4017 	tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4018                                       reader->patternMax *
4019                                       sizeof(reader->patternTab[0]));
4020         if (tmp == NULL) {
4021             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4022 	    reader->patternMax /= 2;
4023             return (-1);
4024         }
4025 	reader->patternTab = tmp;
4026     }
4027     reader->patternTab[reader->patternNr] = comp;
4028     return(reader->patternNr++);
4029 }
4030 #endif
4031 
4032 /**
4033  * xmlTextReaderCurrentDoc:
4034  * @reader:  the xmlTextReaderPtr used
4035  *
4036  * Hacking interface allowing to get the xmlDocPtr correponding to the
4037  * current document being accessed by the xmlTextReader.
4038  * NOTE: as a result of this call, the reader will not destroy the
4039  *       associated XML document and calling xmlFreeDoc() on the result
4040  *       is needed once the reader parsing has finished.
4041  *
4042  * Returns the xmlDocPtr or NULL in case of error.
4043  */
4044 xmlDocPtr
xmlTextReaderCurrentDoc(xmlTextReaderPtr reader)4045 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4046     if (reader == NULL)
4047 	return(NULL);
4048     if (reader->doc != NULL)
4049         return(reader->doc);
4050     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4051 	return(NULL);
4052 
4053     reader->preserve = 1;
4054     return(reader->ctxt->myDoc);
4055 }
4056 
4057 #ifdef LIBXML_SCHEMAS_ENABLED
4058 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
4059 
4060 static void XMLCDECL
4061 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4062 
4063 static void XMLCDECL
4064 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4065 
4066 static void XMLCDECL
4067 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4068 
4069 static void XMLCDECL
4070 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4071 
4072 static void XMLCDECL
xmlTextReaderValidityErrorRelay(void * ctx,const char * msg,...)4073 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4074 {
4075     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4076 
4077     char *str;
4078 
4079     va_list ap;
4080 
4081     va_start(ap, msg);
4082     str = xmlTextReaderBuildMessage(msg, ap);
4083     if (!reader->errorFunc) {
4084         xmlTextReaderValidityError(ctx, "%s", str);
4085     } else {
4086         reader->errorFunc(reader->errorFuncArg, str,
4087                           XML_PARSER_SEVERITY_VALIDITY_ERROR,
4088                           NULL /* locator */ );
4089     }
4090     if (str != NULL)
4091         xmlFree(str);
4092     va_end(ap);
4093 }
4094 
4095 static void XMLCDECL
xmlTextReaderValidityWarningRelay(void * ctx,const char * msg,...)4096 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4097 {
4098     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4099 
4100     char *str;
4101 
4102     va_list ap;
4103 
4104     va_start(ap, msg);
4105     str = xmlTextReaderBuildMessage(msg, ap);
4106     if (!reader->errorFunc) {
4107         xmlTextReaderValidityWarning(ctx, "%s", str);
4108     } else {
4109         reader->errorFunc(reader->errorFuncArg, str,
4110                           XML_PARSER_SEVERITY_VALIDITY_WARNING,
4111                           NULL /* locator */ );
4112     }
4113     if (str != NULL)
4114         xmlFree(str);
4115     va_end(ap);
4116 }
4117 
4118 static void
4119   xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4120 
4121 static void
xmlTextReaderValidityStructuredRelay(void * userData,xmlErrorPtr error)4122 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4123 {
4124     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4125 
4126     if (reader->sErrorFunc) {
4127         reader->sErrorFunc(reader->errorFuncArg, error);
4128     } else {
4129         xmlTextReaderStructuredError(reader, error);
4130     }
4131 }
4132 /**
4133  * xmlTextReaderRelaxNGSetSchema:
4134  * @reader:  the xmlTextReaderPtr used
4135  * @schema:  a precompiled RelaxNG schema
4136  *
4137  * Use RelaxNG to validate the document as it is processed.
4138  * Activation is only possible before the first Read().
4139  * if @schema is NULL, then RelaxNG validation is desactivated.
4140  @ The @schema should not be freed until the reader is deallocated
4141  * or its use has been deactivated.
4142  *
4143  * Returns 0 in case the RelaxNG validation could be (des)activated and
4144  *         -1 in case of error.
4145  */
4146 int
xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader,xmlRelaxNGPtr schema)4147 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4148     if (reader == NULL)
4149         return(-1);
4150     if (schema == NULL) {
4151         if (reader->rngSchemas != NULL) {
4152 	    xmlRelaxNGFree(reader->rngSchemas);
4153 	    reader->rngSchemas = NULL;
4154 	}
4155         if (reader->rngValidCtxt != NULL) {
4156 	    if (! reader->rngPreserveCtxt)
4157 		xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4158 	    reader->rngValidCtxt = NULL;
4159         }
4160 	reader->rngPreserveCtxt = 0;
4161 	return(0);
4162     }
4163     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4164 	return(-1);
4165     if (reader->rngSchemas != NULL) {
4166 	xmlRelaxNGFree(reader->rngSchemas);
4167 	reader->rngSchemas = NULL;
4168     }
4169     if (reader->rngValidCtxt != NULL) {
4170 	if (! reader->rngPreserveCtxt)
4171 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4172 	reader->rngValidCtxt = NULL;
4173     }
4174     reader->rngPreserveCtxt = 0;
4175     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4176     if (reader->rngValidCtxt == NULL)
4177         return(-1);
4178     if (reader->errorFunc != NULL) {
4179 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4180 			xmlTextReaderValidityErrorRelay,
4181 			xmlTextReaderValidityWarningRelay,
4182 			reader);
4183     }
4184 	if (reader->sErrorFunc != NULL) {
4185 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4186 			xmlTextReaderValidityStructuredRelay,
4187 			reader);
4188     }
4189     reader->rngValidErrors = 0;
4190     reader->rngFullNode = NULL;
4191     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4192     return(0);
4193 }
4194 
4195 /**
4196  * xmlTextReaderLocator:
4197  * @ctx: the xmlTextReaderPtr used
4198  * @file: returned file information
4199  * @line: returned line information
4200  *
4201  * Internal locator function for the readers
4202  *
4203  * Returns 0 in case the Schema validation could be (des)activated and
4204  *         -1 in case of error.
4205  */
4206 static int
xmlTextReaderLocator(void * ctx,const char ** file,unsigned long * line)4207 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4208     xmlTextReaderPtr reader;
4209 
4210     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4211         return(-1);
4212 
4213     if (file != NULL)
4214         *file = NULL;
4215     if (line != NULL)
4216         *line = 0;
4217 
4218     reader = (xmlTextReaderPtr) ctx;
4219     if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4220 	if (file != NULL)
4221 	    *file = reader->ctxt->input->filename;
4222 	if (line != NULL)
4223 	    *line = reader->ctxt->input->line;
4224 	return(0);
4225     }
4226     if (reader->node != NULL) {
4227         long res;
4228 	int ret = 0;
4229 
4230 	if (line != NULL) {
4231 	    res = xmlGetLineNo(reader->node);
4232 	    if (res > 0)
4233 	        *line = (unsigned long) res;
4234 	    else
4235                 ret = -1;
4236 	}
4237         if (file != NULL) {
4238 	    xmlDocPtr doc = reader->node->doc;
4239 	    if ((doc != NULL) && (doc->URL != NULL))
4240 	        *file = (const char *) doc->URL;
4241 	    else
4242                 ret = -1;
4243 	}
4244 	return(ret);
4245     }
4246     return(-1);
4247 }
4248 
4249 /**
4250  * xmlTextReaderSetSchema:
4251  * @reader:  the xmlTextReaderPtr used
4252  * @schema:  a precompiled Schema schema
4253  *
4254  * Use XSD Schema to validate the document as it is processed.
4255  * Activation is only possible before the first Read().
4256  * if @schema is NULL, then Schema validation is desactivated.
4257  @ The @schema should not be freed until the reader is deallocated
4258  * or its use has been deactivated.
4259  *
4260  * Returns 0 in case the Schema validation could be (des)activated and
4261  *         -1 in case of error.
4262  */
4263 int
xmlTextReaderSetSchema(xmlTextReaderPtr reader,xmlSchemaPtr schema)4264 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4265     if (reader == NULL)
4266         return(-1);
4267     if (schema == NULL) {
4268 	if (reader->xsdPlug != NULL) {
4269 	    xmlSchemaSAXUnplug(reader->xsdPlug);
4270 	    reader->xsdPlug = NULL;
4271 	}
4272         if (reader->xsdValidCtxt != NULL) {
4273 	    if (! reader->xsdPreserveCtxt)
4274 		xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4275 	    reader->xsdValidCtxt = NULL;
4276         }
4277 	reader->xsdPreserveCtxt = 0;
4278         if (reader->xsdSchemas != NULL) {
4279 	    xmlSchemaFree(reader->xsdSchemas);
4280 	    reader->xsdSchemas = NULL;
4281 	}
4282 	return(0);
4283     }
4284     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4285 	return(-1);
4286     if (reader->xsdPlug != NULL) {
4287 	xmlSchemaSAXUnplug(reader->xsdPlug);
4288 	reader->xsdPlug = NULL;
4289     }
4290     if (reader->xsdValidCtxt != NULL) {
4291 	if (! reader->xsdPreserveCtxt)
4292 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4293 	reader->xsdValidCtxt = NULL;
4294     }
4295     reader->xsdPreserveCtxt = 0;
4296     if (reader->xsdSchemas != NULL) {
4297 	xmlSchemaFree(reader->xsdSchemas);
4298 	reader->xsdSchemas = NULL;
4299     }
4300     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4301     if (reader->xsdValidCtxt == NULL) {
4302 	xmlSchemaFree(reader->xsdSchemas);
4303 	reader->xsdSchemas = NULL;
4304         return(-1);
4305     }
4306     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4307                                        &(reader->ctxt->sax),
4308 				       &(reader->ctxt->userData));
4309     if (reader->xsdPlug == NULL) {
4310 	xmlSchemaFree(reader->xsdSchemas);
4311 	reader->xsdSchemas = NULL;
4312 	xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4313 	reader->xsdValidCtxt = NULL;
4314 	return(-1);
4315     }
4316     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4317                                 xmlTextReaderLocator,
4318 				(void *) reader);
4319 
4320     if (reader->errorFunc != NULL) {
4321 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4322 			xmlTextReaderValidityErrorRelay,
4323 			xmlTextReaderValidityWarningRelay,
4324 			reader);
4325     }
4326 	if (reader->sErrorFunc != NULL) {
4327 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4328 			xmlTextReaderValidityStructuredRelay,
4329 			reader);
4330     }
4331     reader->xsdValidErrors = 0;
4332     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4333     return(0);
4334 }
4335 
4336 /**
4337  * xmlTextReaderRelaxNGValidateInternal:
4338  * @reader:  the xmlTextReaderPtr used
4339  * @rng:  the path to a RelaxNG schema or NULL
4340  * @ctxt: the RelaxNG schema validation context or NULL
4341  * @options: options (not yet used)
4342  *
4343  * Use RelaxNG to validate the document as it is processed.
4344  * Activation is only possible before the first Read().
4345  * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4346  *
4347  * Returns 0 in case the RelaxNG validation could be (de)activated and
4348  *	   -1 in case of error.
4349  */
4350 static int
xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,const char * rng,xmlRelaxNGValidCtxtPtr ctxt,int options ATTRIBUTE_UNUSED)4351 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4352 				     const char *rng,
4353 				     xmlRelaxNGValidCtxtPtr ctxt,
4354 				     int options ATTRIBUTE_UNUSED)
4355 {
4356     if (reader == NULL)
4357 	return(-1);
4358 
4359     if ((rng != NULL) && (ctxt != NULL))
4360 	return (-1);
4361 
4362     if (((rng != NULL) || (ctxt != NULL)) &&
4363 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4364 	 (reader->ctxt == NULL)))
4365 	return(-1);
4366 
4367     /* Cleanup previous validation stuff. */
4368     if (reader->rngValidCtxt != NULL) {
4369 	if ( !reader->rngPreserveCtxt)
4370 	    xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4371 	reader->rngValidCtxt = NULL;
4372     }
4373     reader->rngPreserveCtxt = 0;
4374     if (reader->rngSchemas != NULL) {
4375 	xmlRelaxNGFree(reader->rngSchemas);
4376 	reader->rngSchemas = NULL;
4377     }
4378 
4379     if ((rng == NULL) && (ctxt == NULL)) {
4380 	/* We just want to deactivate the validation, so get out. */
4381 	return(0);
4382     }
4383 
4384 
4385     if (rng != NULL) {
4386 	xmlRelaxNGParserCtxtPtr pctxt;
4387 	/* Parse the schema and create validation environment. */
4388 
4389 	pctxt = xmlRelaxNGNewParserCtxt(rng);
4390 	if (reader->errorFunc != NULL) {
4391 	    xmlRelaxNGSetParserErrors(pctxt,
4392 		xmlTextReaderValidityErrorRelay,
4393 		xmlTextReaderValidityWarningRelay,
4394 		reader);
4395 	}
4396 	if (reader->sErrorFunc != NULL) {
4397 	    xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4398 		xmlTextReaderValidityStructuredRelay,
4399 		reader);
4400 	}
4401 	reader->rngSchemas = xmlRelaxNGParse(pctxt);
4402 	xmlRelaxNGFreeParserCtxt(pctxt);
4403 	if (reader->rngSchemas == NULL)
4404 	    return(-1);
4405 	reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4406 	if (reader->rngValidCtxt == NULL) {
4407 	    xmlRelaxNGFree(reader->rngSchemas);
4408 	    reader->rngSchemas = NULL;
4409 	    return(-1);
4410 	}
4411     } else {
4412 	/* Use the given validation context. */
4413 	reader->rngValidCtxt = ctxt;
4414 	reader->rngPreserveCtxt = 1;
4415     }
4416     /*
4417     * Redirect the validation context's error channels to use
4418     * the reader channels.
4419     * TODO: In case the user provides the validation context we
4420     *	could make this redirection optional.
4421     */
4422     if (reader->errorFunc != NULL) {
4423 	xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4424 			 xmlTextReaderValidityErrorRelay,
4425 			 xmlTextReaderValidityWarningRelay,
4426 			 reader);
4427     }
4428 	if (reader->sErrorFunc != NULL) {
4429 		xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4430 			xmlTextReaderValidityStructuredRelay,
4431 			reader);
4432     }
4433     reader->rngValidErrors = 0;
4434     reader->rngFullNode = NULL;
4435     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4436     return(0);
4437 }
4438 
4439 /**
4440  * xmlTextReaderSchemaValidateInternal:
4441  * @reader:  the xmlTextReaderPtr used
4442  * @xsd:  the path to a W3C XSD schema or NULL
4443  * @ctxt: the XML Schema validation context or NULL
4444  * @options: options (not used yet)
4445  *
4446  * Validate the document as it is processed using XML Schema.
4447  * Activation is only possible before the first Read().
4448  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4449  *
4450  * Returns 0 in case the schemas validation could be (de)activated and
4451  *         -1 in case of error.
4452  */
4453 static int
xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,const char * xsd,xmlSchemaValidCtxtPtr ctxt,int options ATTRIBUTE_UNUSED)4454 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4455 				    const char *xsd,
4456 				    xmlSchemaValidCtxtPtr ctxt,
4457 				    int options ATTRIBUTE_UNUSED)
4458 {
4459     if (reader == NULL)
4460         return(-1);
4461 
4462     if ((xsd != NULL) && (ctxt != NULL))
4463 	return(-1);
4464 
4465     if (((xsd != NULL) || (ctxt != NULL)) &&
4466 	((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4467         (reader->ctxt == NULL)))
4468 	return(-1);
4469 
4470     /* Cleanup previous validation stuff. */
4471     if (reader->xsdPlug != NULL) {
4472 	xmlSchemaSAXUnplug(reader->xsdPlug);
4473 	reader->xsdPlug = NULL;
4474     }
4475     if (reader->xsdValidCtxt != NULL) {
4476 	if (! reader->xsdPreserveCtxt)
4477 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4478 	reader->xsdValidCtxt = NULL;
4479     }
4480     reader->xsdPreserveCtxt = 0;
4481     if (reader->xsdSchemas != NULL) {
4482 	xmlSchemaFree(reader->xsdSchemas);
4483 	reader->xsdSchemas = NULL;
4484     }
4485 
4486     if ((xsd == NULL) && (ctxt == NULL)) {
4487 	/* We just want to deactivate the validation, so get out. */
4488 	return(0);
4489     }
4490 
4491     if (xsd != NULL) {
4492 	xmlSchemaParserCtxtPtr pctxt;
4493 	/* Parse the schema and create validation environment. */
4494 	pctxt = xmlSchemaNewParserCtxt(xsd);
4495 	if (reader->errorFunc != NULL) {
4496 	    xmlSchemaSetParserErrors(pctxt,
4497 		xmlTextReaderValidityErrorRelay,
4498 		xmlTextReaderValidityWarningRelay,
4499 		reader);
4500 	}
4501 	reader->xsdSchemas = xmlSchemaParse(pctxt);
4502 	xmlSchemaFreeParserCtxt(pctxt);
4503 	if (reader->xsdSchemas == NULL)
4504 	    return(-1);
4505 	reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4506 	if (reader->xsdValidCtxt == NULL) {
4507 	    xmlSchemaFree(reader->xsdSchemas);
4508 	    reader->xsdSchemas = NULL;
4509 	    return(-1);
4510 	}
4511 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4512 	    &(reader->ctxt->sax),
4513 	    &(reader->ctxt->userData));
4514 	if (reader->xsdPlug == NULL) {
4515 	    xmlSchemaFree(reader->xsdSchemas);
4516 	    reader->xsdSchemas = NULL;
4517 	    xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4518 	    reader->xsdValidCtxt = NULL;
4519 	    return(-1);
4520 	}
4521     } else {
4522 	/* Use the given validation context. */
4523 	reader->xsdValidCtxt = ctxt;
4524 	reader->xsdPreserveCtxt = 1;
4525 	reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4526 	    &(reader->ctxt->sax),
4527 	    &(reader->ctxt->userData));
4528 	if (reader->xsdPlug == NULL) {
4529 	    reader->xsdValidCtxt = NULL;
4530 	    reader->xsdPreserveCtxt = 0;
4531 	    return(-1);
4532 	}
4533     }
4534     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4535                                 xmlTextReaderLocator,
4536 				(void *) reader);
4537     /*
4538     * Redirect the validation context's error channels to use
4539     * the reader channels.
4540     * TODO: In case the user provides the validation context we
4541     *   could make this redirection optional.
4542     */
4543     if (reader->errorFunc != NULL) {
4544 	xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4545 			 xmlTextReaderValidityErrorRelay,
4546 			 xmlTextReaderValidityWarningRelay,
4547 			 reader);
4548     }
4549 	if (reader->sErrorFunc != NULL) {
4550 		xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4551 			xmlTextReaderValidityStructuredRelay,
4552 			reader);
4553     }
4554     reader->xsdValidErrors = 0;
4555     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4556     return(0);
4557 }
4558 
4559 /**
4560  * xmlTextReaderSchemaValidateCtxt:
4561  * @reader:  the xmlTextReaderPtr used
4562  * @ctxt: the XML Schema validation context or NULL
4563  * @options: options (not used yet)
4564  *
4565  * Use W3C XSD schema context to validate the document as it is processed.
4566  * Activation is only possible before the first Read().
4567  * If @ctxt is NULL, then XML Schema validation is deactivated.
4568  *
4569  * Returns 0 in case the schemas validation could be (de)activated and
4570  *         -1 in case of error.
4571  */
4572 int
xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,xmlSchemaValidCtxtPtr ctxt,int options)4573 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4574 				    xmlSchemaValidCtxtPtr ctxt,
4575 				    int options)
4576 {
4577     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4578 }
4579 
4580 /**
4581  * xmlTextReaderSchemaValidate:
4582  * @reader:  the xmlTextReaderPtr used
4583  * @xsd:  the path to a W3C XSD schema or NULL
4584  *
4585  * Use W3C XSD schema to validate the document as it is processed.
4586  * Activation is only possible before the first Read().
4587  * If @xsd is NULL, then XML Schema validation is deactivated.
4588  *
4589  * Returns 0 in case the schemas validation could be (de)activated and
4590  *         -1 in case of error.
4591  */
4592 int
xmlTextReaderSchemaValidate(xmlTextReaderPtr reader,const char * xsd)4593 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4594 {
4595     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4596 }
4597 
4598 /**
4599  * xmlTextReaderRelaxNGValidateCtxt:
4600  * @reader:  the xmlTextReaderPtr used
4601  * @ctxt: the RelaxNG schema validation context or NULL
4602  * @options: options (not used yet)
4603  *
4604  * Use RelaxNG schema context to validate the document as it is processed.
4605  * Activation is only possible before the first Read().
4606  * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4607  *
4608  * Returns 0 in case the schemas validation could be (de)activated and
4609  *         -1 in case of error.
4610  */
4611 int
xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,xmlRelaxNGValidCtxtPtr ctxt,int options)4612 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4613 				 xmlRelaxNGValidCtxtPtr ctxt,
4614 				 int options)
4615 {
4616     return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4617 }
4618 
4619 /**
4620  * xmlTextReaderRelaxNGValidate:
4621  * @reader:  the xmlTextReaderPtr used
4622  * @rng:  the path to a RelaxNG schema or NULL
4623  *
4624  * Use RelaxNG schema to validate the document as it is processed.
4625  * Activation is only possible before the first Read().
4626  * If @rng is NULL, then RelaxNG schema validation is deactivated.
4627  *
4628  * Returns 0 in case the schemas validation could be (de)activated and
4629  *         -1 in case of error.
4630  */
4631 int
xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader,const char * rng)4632 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4633 {
4634     return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4635 }
4636 
4637 #endif
4638 
4639 /**
4640  * xmlTextReaderIsNamespaceDecl:
4641  * @reader: the xmlTextReaderPtr used
4642  *
4643  * Determine whether the current node is a namespace declaration
4644  * rather than a regular attribute.
4645  *
4646  * Returns 1 if the current node is a namespace declaration, 0 if it
4647  * is a regular attribute or other type of node, or -1 in case of
4648  * error.
4649  */
4650 int
xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader)4651 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4652     xmlNodePtr node;
4653     if (reader == NULL)
4654 	return(-1);
4655     if (reader->node == NULL)
4656 	return(-1);
4657     if (reader->curnode != NULL)
4658 	node = reader->curnode;
4659     else
4660 	node = reader->node;
4661 
4662     if (XML_NAMESPACE_DECL == node->type)
4663 	return(1);
4664     else
4665 	return(0);
4666 }
4667 
4668 /**
4669  * xmlTextReaderConstXmlVersion:
4670  * @reader:  the xmlTextReaderPtr used
4671  *
4672  * Determine the XML version of the document being read.
4673  *
4674  * Returns a string containing the XML version of the document or NULL
4675  * in case of error.  The string is deallocated with the reader.
4676  */
4677 const xmlChar *
xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader)4678 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4679     xmlDocPtr doc = NULL;
4680     if (reader == NULL)
4681 	return(NULL);
4682     if (reader->doc != NULL)
4683         doc = reader->doc;
4684     else if (reader->ctxt != NULL)
4685 	doc = reader->ctxt->myDoc;
4686     if (doc == NULL)
4687 	return(NULL);
4688 
4689     if (doc->version == NULL)
4690 	return(NULL);
4691     else
4692       return(CONSTSTR(doc->version));
4693 }
4694 
4695 /**
4696  * xmlTextReaderStandalone:
4697  * @reader:  the xmlTextReaderPtr used
4698  *
4699  * Determine the standalone status of the document being read.
4700  *
4701  * Returns 1 if the document was declared to be standalone, 0 if it
4702  * was declared to be not standalone, or -1 if the document did not
4703  * specify its standalone status or in case of error.
4704  */
4705 int
xmlTextReaderStandalone(xmlTextReaderPtr reader)4706 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4707     xmlDocPtr doc = NULL;
4708     if (reader == NULL)
4709 	return(-1);
4710     if (reader->doc != NULL)
4711         doc = reader->doc;
4712     else if (reader->ctxt != NULL)
4713 	doc = reader->ctxt->myDoc;
4714     if (doc == NULL)
4715 	return(-1);
4716 
4717     return(doc->standalone);
4718 }
4719 
4720 /************************************************************************
4721  *									*
4722  *			Error Handling Extensions                       *
4723  *									*
4724  ************************************************************************/
4725 
4726 /* helper to build a xmlMalloc'ed string from a format and va_list */
4727 static char *
xmlTextReaderBuildMessage(const char * msg,va_list ap)4728 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4729     int size = 0;
4730     int chars;
4731     char *larger;
4732     char *str = NULL;
4733     va_list aq;
4734 
4735     while (1) {
4736         VA_COPY(aq, ap);
4737         chars = vsnprintf(str, size, msg, aq);
4738         va_end(aq);
4739         if (chars < 0) {
4740 	    xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4741 	    if (str)
4742 		xmlFree(str);
4743 	    return NULL;
4744 	}
4745 	if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4746             break;
4747         if (chars < MAX_ERR_MSG_SIZE)
4748 	size = chars + 1;
4749 	else
4750 		size = MAX_ERR_MSG_SIZE;
4751         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4752 	    xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4753 	    if (str)
4754                 xmlFree(str);
4755             return NULL;
4756         }
4757         str = larger;
4758     }
4759 
4760     return str;
4761 }
4762 
4763 /**
4764  * xmlTextReaderLocatorLineNumber:
4765  * @locator: the xmlTextReaderLocatorPtr used
4766  *
4767  * Obtain the line number for the given locator.
4768  *
4769  * Returns the line number or -1 in case of error.
4770  */
4771 int
xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator)4772 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4773     /* we know that locator is a xmlParserCtxtPtr */
4774     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4775     int ret = -1;
4776 
4777     if (locator == NULL)
4778         return(-1);
4779     if (ctx->node != NULL) {
4780 	ret = xmlGetLineNo(ctx->node);
4781     }
4782     else {
4783 	/* inspired from error.c */
4784 	xmlParserInputPtr input;
4785 	input = ctx->input;
4786 	if ((input->filename == NULL) && (ctx->inputNr > 1))
4787 	    input = ctx->inputTab[ctx->inputNr - 2];
4788 	if (input != NULL) {
4789 	    ret = input->line;
4790 	}
4791 	else {
4792 	    ret = -1;
4793 	}
4794     }
4795 
4796     return ret;
4797 }
4798 
4799 /**
4800  * xmlTextReaderLocatorBaseURI:
4801  * @locator: the xmlTextReaderLocatorPtr used
4802  *
4803  * Obtain the base URI for the given locator.
4804  *
4805  * Returns the base URI or NULL in case of error,
4806  *    if non NULL it need to be freed by the caller.
4807  */
4808 xmlChar *
xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator)4809 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4810     /* we know that locator is a xmlParserCtxtPtr */
4811     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4812     xmlChar *ret = NULL;
4813 
4814     if (locator == NULL)
4815         return(NULL);
4816     if (ctx->node != NULL) {
4817 	ret = xmlNodeGetBase(NULL,ctx->node);
4818     }
4819     else {
4820 	/* inspired from error.c */
4821 	xmlParserInputPtr input;
4822 	input = ctx->input;
4823 	if ((input->filename == NULL) && (ctx->inputNr > 1))
4824 	    input = ctx->inputTab[ctx->inputNr - 2];
4825 	if (input != NULL) {
4826 	    ret = xmlStrdup(BAD_CAST input->filename);
4827 	}
4828 	else {
4829 	    ret = NULL;
4830 	}
4831     }
4832 
4833     return ret;
4834 }
4835 
4836 static void
xmlTextReaderGenericError(void * ctxt,xmlParserSeverities severity,char * str)4837 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4838                           char *str)
4839 {
4840     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4841 
4842     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4843 
4844     if (str != NULL) {
4845         if (reader->errorFunc)
4846             reader->errorFunc(reader->errorFuncArg, str, severity,
4847                               (xmlTextReaderLocatorPtr) ctx);
4848         xmlFree(str);
4849     }
4850 }
4851 
4852 static void
xmlTextReaderStructuredError(void * ctxt,xmlErrorPtr error)4853 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4854 {
4855     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4856 
4857     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4858 
4859     if (error && reader->sErrorFunc) {
4860         reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4861     }
4862 }
4863 
4864 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderError(void * ctxt,const char * msg,...)4865 xmlTextReaderError(void *ctxt, const char *msg, ...)
4866 {
4867     va_list ap;
4868 
4869     va_start(ap, msg);
4870     xmlTextReaderGenericError(ctxt,
4871                               XML_PARSER_SEVERITY_ERROR,
4872                               xmlTextReaderBuildMessage(msg, ap));
4873     va_end(ap);
4874 
4875 }
4876 
4877 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
xmlTextReaderWarning(void * ctxt,const char * msg,...)4878 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4879 {
4880     va_list ap;
4881 
4882     va_start(ap, msg);
4883     xmlTextReaderGenericError(ctxt,
4884                               XML_PARSER_SEVERITY_WARNING,
4885                               xmlTextReaderBuildMessage(msg, ap));
4886     va_end(ap);
4887 }
4888 
4889 static void XMLCDECL
xmlTextReaderValidityError(void * ctxt,const char * msg,...)4890 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4891 {
4892     va_list ap;
4893 
4894     int len = xmlStrlen((const xmlChar *) msg);
4895 
4896     if ((len > 1) && (msg[len - 2] != ':')) {
4897         /*
4898          * some callbacks only report locator information:
4899          * skip them (mimicking behaviour in error.c)
4900          */
4901         va_start(ap, msg);
4902         xmlTextReaderGenericError(ctxt,
4903                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
4904                                   xmlTextReaderBuildMessage(msg, ap));
4905         va_end(ap);
4906     }
4907 }
4908 
4909 static void XMLCDECL
xmlTextReaderValidityWarning(void * ctxt,const char * msg,...)4910 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4911 {
4912     va_list ap;
4913 
4914     int len = xmlStrlen((const xmlChar *) msg);
4915 
4916     if ((len != 0) && (msg[len - 1] != ':')) {
4917         /*
4918          * some callbacks only report locator information:
4919          * skip them (mimicking behaviour in error.c)
4920          */
4921         va_start(ap, msg);
4922         xmlTextReaderGenericError(ctxt,
4923                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
4924                                   xmlTextReaderBuildMessage(msg, ap));
4925         va_end(ap);
4926     }
4927 }
4928 
4929 /**
4930  * xmlTextReaderSetErrorHandler:
4931  * @reader:  the xmlTextReaderPtr used
4932  * @f:	the callback function to call on error and warnings
4933  * @arg:    a user argument to pass to the callback function
4934  *
4935  * Register a callback function that will be called on error and warnings.
4936  *
4937  * If @f is NULL, the default error and warning handlers are restored.
4938  */
4939 void
xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,xmlTextReaderErrorFunc f,void * arg)4940 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4941                              xmlTextReaderErrorFunc f, void *arg)
4942 {
4943     if (f != NULL) {
4944         reader->ctxt->sax->error = xmlTextReaderError;
4945         reader->ctxt->sax->serror = NULL;
4946         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4947         reader->ctxt->sax->warning = xmlTextReaderWarning;
4948         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4949         reader->errorFunc = f;
4950         reader->sErrorFunc = NULL;
4951         reader->errorFuncArg = arg;
4952 #ifdef LIBXML_SCHEMAS_ENABLED
4953         if (reader->rngValidCtxt) {
4954             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4955                                      xmlTextReaderValidityErrorRelay,
4956                                      xmlTextReaderValidityWarningRelay,
4957                                      reader);
4958             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4959                                                reader);
4960         }
4961         if (reader->xsdValidCtxt) {
4962             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4963                                     xmlTextReaderValidityErrorRelay,
4964                                     xmlTextReaderValidityWarningRelay,
4965                                     reader);
4966             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4967                                               reader);
4968         }
4969 #endif
4970     } else {
4971         /* restore defaults */
4972         reader->ctxt->sax->error = xmlParserError;
4973         reader->ctxt->vctxt.error = xmlParserValidityError;
4974         reader->ctxt->sax->warning = xmlParserWarning;
4975         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4976         reader->errorFunc = NULL;
4977         reader->sErrorFunc = NULL;
4978         reader->errorFuncArg = NULL;
4979 #ifdef LIBXML_SCHEMAS_ENABLED
4980         if (reader->rngValidCtxt) {
4981             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4982                                      reader);
4983             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4984                                                reader);
4985         }
4986         if (reader->xsdValidCtxt) {
4987             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4988                                     reader);
4989             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4990                                               reader);
4991         }
4992 #endif
4993     }
4994 }
4995 
4996 /**
4997 * xmlTextReaderSetStructuredErrorHandler:
4998  * @reader:  the xmlTextReaderPtr used
4999  * @f:	the callback function to call on error and warnings
5000  * @arg:    a user argument to pass to the callback function
5001  *
5002  * Register a callback function that will be called on error and warnings.
5003  *
5004  * If @f is NULL, the default error and warning handlers are restored.
5005  */
5006 void
xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,xmlStructuredErrorFunc f,void * arg)5007 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5008                                        xmlStructuredErrorFunc f, void *arg)
5009 {
5010     if (f != NULL) {
5011         reader->ctxt->sax->error = NULL;
5012         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5013         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5014         reader->ctxt->sax->warning = xmlTextReaderWarning;
5015         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5016         reader->sErrorFunc = f;
5017         reader->errorFunc = NULL;
5018         reader->errorFuncArg = arg;
5019 #ifdef LIBXML_SCHEMAS_ENABLED
5020         if (reader->rngValidCtxt) {
5021             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5022                                      reader);
5023             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5024                                         xmlTextReaderValidityStructuredRelay,
5025                                                reader);
5026         }
5027         if (reader->xsdValidCtxt) {
5028             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5029                                     reader);
5030             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5031                                        xmlTextReaderValidityStructuredRelay,
5032                                               reader);
5033         }
5034 #endif
5035     } else {
5036         /* restore defaults */
5037         reader->ctxt->sax->error = xmlParserError;
5038         reader->ctxt->sax->serror = NULL;
5039         reader->ctxt->vctxt.error = xmlParserValidityError;
5040         reader->ctxt->sax->warning = xmlParserWarning;
5041         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5042         reader->errorFunc = NULL;
5043         reader->sErrorFunc = NULL;
5044         reader->errorFuncArg = NULL;
5045 #ifdef LIBXML_SCHEMAS_ENABLED
5046         if (reader->rngValidCtxt) {
5047             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5048                                      reader);
5049             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5050                                                reader);
5051         }
5052         if (reader->xsdValidCtxt) {
5053             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5054                                     reader);
5055             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5056                                               reader);
5057         }
5058 #endif
5059     }
5060 }
5061 
5062 /**
5063  * xmlTextReaderIsValid:
5064  * @reader:  the xmlTextReaderPtr used
5065  *
5066  * Retrieve the validity status from the parser context
5067  *
5068  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5069  */
5070 int
xmlTextReaderIsValid(xmlTextReaderPtr reader)5071 xmlTextReaderIsValid(xmlTextReaderPtr reader)
5072 {
5073     if (reader == NULL)
5074         return (-1);
5075 #ifdef LIBXML_SCHEMAS_ENABLED
5076     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5077         return (reader->rngValidErrors == 0);
5078     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5079         return (reader->xsdValidErrors == 0);
5080 #endif
5081     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5082         return (reader->ctxt->valid);
5083     return (0);
5084 }
5085 
5086 /**
5087  * xmlTextReaderGetErrorHandler:
5088  * @reader:  the xmlTextReaderPtr used
5089  * @f:	the callback function or NULL is no callback has been registered
5090  * @arg:    a user argument
5091  *
5092  * Retrieve the error callback function and user argument.
5093  */
5094 void
xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,xmlTextReaderErrorFunc * f,void ** arg)5095 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5096                              xmlTextReaderErrorFunc * f, void **arg)
5097 {
5098     if (f != NULL)
5099         *f = reader->errorFunc;
5100     if (arg != NULL)
5101         *arg = reader->errorFuncArg;
5102 }
5103 /************************************************************************
5104  *									*
5105  *	New set (2.6.0) of simpler and more flexible APIs		*
5106  *									*
5107  ************************************************************************/
5108 
5109 /**
5110  * xmlTextReaderSetup:
5111  * @reader:  an XML reader
5112  * @input: xmlParserInputBufferPtr used to feed the reader, will
5113  *         be destroyed with it.
5114  * @URL:  the base URL to use for the document
5115  * @encoding:  the document encoding, or NULL
5116  * @options:  a combination of xmlParserOption
5117  *
5118  * Setup an XML reader with new options
5119  *
5120  * Returns 0 in case of success and -1 in case of error.
5121  */
5122 int
xmlTextReaderSetup(xmlTextReaderPtr reader,xmlParserInputBufferPtr input,const char * URL,const char * encoding,int options)5123 xmlTextReaderSetup(xmlTextReaderPtr reader,
5124                    xmlParserInputBufferPtr input, const char *URL,
5125                    const char *encoding, int options)
5126 {
5127     if (reader == NULL) {
5128         if (input != NULL)
5129 	    xmlFreeParserInputBuffer(input);
5130         return (-1);
5131     }
5132 
5133     /*
5134      * we force the generation of compact text nodes on the reader
5135      * since usr applications should never modify the tree
5136      */
5137     options |= XML_PARSE_COMPACT;
5138 
5139     reader->doc = NULL;
5140     reader->entNr = 0;
5141     reader->parserFlags = options;
5142     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5143     if ((input != NULL) && (reader->input != NULL) &&
5144         (reader->allocs & XML_TEXTREADER_INPUT)) {
5145 	xmlFreeParserInputBuffer(reader->input);
5146 	reader->input = NULL;
5147 	reader->allocs -= XML_TEXTREADER_INPUT;
5148     }
5149     if (input != NULL) {
5150 	reader->input = input;
5151 	reader->allocs |= XML_TEXTREADER_INPUT;
5152     }
5153     if (reader->buffer == NULL)
5154         reader->buffer = xmlBufCreateSize(100);
5155     if (reader->buffer == NULL) {
5156         xmlGenericError(xmlGenericErrorContext,
5157                         "xmlTextReaderSetup : malloc failed\n");
5158         return (-1);
5159     }
5160     /* no operation on a reader should require a huge buffer */
5161     xmlBufSetAllocationScheme(reader->buffer,
5162 			      XML_BUFFER_ALLOC_BOUNDED);
5163     if (reader->sax == NULL)
5164 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5165     if (reader->sax == NULL) {
5166         xmlGenericError(xmlGenericErrorContext,
5167                         "xmlTextReaderSetup : malloc failed\n");
5168         return (-1);
5169     }
5170     xmlSAXVersion(reader->sax, 2);
5171     reader->startElement = reader->sax->startElement;
5172     reader->sax->startElement = xmlTextReaderStartElement;
5173     reader->endElement = reader->sax->endElement;
5174     reader->sax->endElement = xmlTextReaderEndElement;
5175 #ifdef LIBXML_SAX1_ENABLED
5176     if (reader->sax->initialized == XML_SAX2_MAGIC) {
5177 #endif /* LIBXML_SAX1_ENABLED */
5178         reader->startElementNs = reader->sax->startElementNs;
5179         reader->sax->startElementNs = xmlTextReaderStartElementNs;
5180         reader->endElementNs = reader->sax->endElementNs;
5181         reader->sax->endElementNs = xmlTextReaderEndElementNs;
5182 #ifdef LIBXML_SAX1_ENABLED
5183     } else {
5184         reader->startElementNs = NULL;
5185         reader->endElementNs = NULL;
5186     }
5187 #endif /* LIBXML_SAX1_ENABLED */
5188     reader->characters = reader->sax->characters;
5189     reader->sax->characters = xmlTextReaderCharacters;
5190     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5191     reader->cdataBlock = reader->sax->cdataBlock;
5192     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5193 
5194     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5195     reader->node = NULL;
5196     reader->curnode = NULL;
5197     if (input != NULL) {
5198         if (xmlBufUse(reader->input->buffer) < 4) {
5199             xmlParserInputBufferRead(input, 4);
5200         }
5201         if (reader->ctxt == NULL) {
5202             if (xmlBufUse(reader->input->buffer) >= 4) {
5203                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5204 		       (const char *) xmlBufContent(reader->input->buffer),
5205                                       4, URL);
5206                 reader->base = 0;
5207                 reader->cur = 4;
5208             } else {
5209                 reader->ctxt =
5210                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5211                 reader->base = 0;
5212                 reader->cur = 0;
5213             }
5214         } else {
5215 	    xmlParserInputPtr inputStream;
5216 	    xmlParserInputBufferPtr buf;
5217 	    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5218 
5219 	    xmlCtxtReset(reader->ctxt);
5220 	    buf = xmlAllocParserInputBuffer(enc);
5221 	    if (buf == NULL) return(-1);
5222 	    inputStream = xmlNewInputStream(reader->ctxt);
5223 	    if (inputStream == NULL) {
5224 		xmlFreeParserInputBuffer(buf);
5225 		return(-1);
5226 	    }
5227 
5228 	    if (URL == NULL)
5229 		inputStream->filename = NULL;
5230 	    else
5231 		inputStream->filename = (char *)
5232 		    xmlCanonicPath((const xmlChar *) URL);
5233 	    inputStream->buf = buf;
5234             xmlBufResetInput(buf->buffer, inputStream);
5235 
5236 	    inputPush(reader->ctxt, inputStream);
5237 	    reader->cur = 0;
5238 	}
5239         if (reader->ctxt == NULL) {
5240             xmlGenericError(xmlGenericErrorContext,
5241                             "xmlTextReaderSetup : malloc failed\n");
5242             return (-1);
5243         }
5244     }
5245     if (reader->dict != NULL) {
5246         if (reader->ctxt->dict != NULL) {
5247 	    if (reader->dict != reader->ctxt->dict) {
5248 		xmlDictFree(reader->dict);
5249 		reader->dict = reader->ctxt->dict;
5250 	    }
5251 	} else {
5252 	    reader->ctxt->dict = reader->dict;
5253 	}
5254     } else {
5255 	if (reader->ctxt->dict == NULL)
5256 	    reader->ctxt->dict = xmlDictCreate();
5257         reader->dict = reader->ctxt->dict;
5258     }
5259     reader->ctxt->_private = reader;
5260     reader->ctxt->linenumbers = 1;
5261     reader->ctxt->dictNames = 1;
5262     /*
5263      * use the parser dictionary to allocate all elements and attributes names
5264      */
5265     reader->ctxt->docdict = 1;
5266     reader->ctxt->parseMode = XML_PARSE_READER;
5267 
5268 #ifdef LIBXML_XINCLUDE_ENABLED
5269     if (reader->xincctxt != NULL) {
5270 	xmlXIncludeFreeContext(reader->xincctxt);
5271 	reader->xincctxt = NULL;
5272     }
5273     if (options & XML_PARSE_XINCLUDE) {
5274         reader->xinclude = 1;
5275 	reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5276 	options -= XML_PARSE_XINCLUDE;
5277     } else
5278         reader->xinclude = 0;
5279     reader->in_xinclude = 0;
5280 #endif
5281 #ifdef LIBXML_PATTERN_ENABLED
5282     if (reader->patternTab == NULL) {
5283         reader->patternNr = 0;
5284 	reader->patternMax = 0;
5285     }
5286     while (reader->patternNr > 0) {
5287         reader->patternNr--;
5288 	if (reader->patternTab[reader->patternNr] != NULL) {
5289 	    xmlFreePattern(reader->patternTab[reader->patternNr]);
5290             reader->patternTab[reader->patternNr] = NULL;
5291 	}
5292     }
5293 #endif
5294 
5295     if (options & XML_PARSE_DTDVALID)
5296         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5297 
5298     xmlCtxtUseOptions(reader->ctxt, options);
5299     if (encoding != NULL) {
5300         xmlCharEncodingHandlerPtr hdlr;
5301 
5302         hdlr = xmlFindCharEncodingHandler(encoding);
5303         if (hdlr != NULL)
5304             xmlSwitchToEncoding(reader->ctxt, hdlr);
5305     }
5306     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5307         (reader->ctxt->input->filename == NULL))
5308         reader->ctxt->input->filename = (char *)
5309             xmlStrdup((const xmlChar *) URL);
5310 
5311     reader->doc = NULL;
5312 
5313     return (0);
5314 }
5315 
5316 /**
5317  * xmlTextReaderByteConsumed:
5318  * @reader: an XML reader
5319  *
5320  * This function provides the current index of the parser used
5321  * by the reader, relative to the start of the current entity.
5322  * This function actually just wraps a call to xmlBytesConsumed()
5323  * for the parser context associated with the reader.
5324  * See xmlBytesConsumed() for more information.
5325  *
5326  * Returns the index in bytes from the beginning of the entity or -1
5327  *         in case the index could not be computed.
5328  */
5329 long
xmlTextReaderByteConsumed(xmlTextReaderPtr reader)5330 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5331     if ((reader == NULL) || (reader->ctxt == NULL))
5332         return(-1);
5333     return(xmlByteConsumed(reader->ctxt));
5334 }
5335 
5336 
5337 /**
5338  * xmlReaderWalker:
5339  * @doc:  a preparsed document
5340  *
5341  * Create an xmltextReader for a preparsed document.
5342  *
5343  * Returns the new reader or NULL in case of error.
5344  */
5345 xmlTextReaderPtr
xmlReaderWalker(xmlDocPtr doc)5346 xmlReaderWalker(xmlDocPtr doc)
5347 {
5348     xmlTextReaderPtr ret;
5349 
5350     if (doc == NULL)
5351         return(NULL);
5352 
5353     ret = xmlMalloc(sizeof(xmlTextReader));
5354     if (ret == NULL) {
5355         xmlGenericError(xmlGenericErrorContext,
5356 		"xmlNewTextReader : malloc failed\n");
5357 	return(NULL);
5358     }
5359     memset(ret, 0, sizeof(xmlTextReader));
5360     ret->entNr = 0;
5361     ret->input = NULL;
5362     ret->mode = XML_TEXTREADER_MODE_INITIAL;
5363     ret->node = NULL;
5364     ret->curnode = NULL;
5365     ret->base = 0;
5366     ret->cur = 0;
5367     ret->allocs = XML_TEXTREADER_CTXT;
5368     ret->doc = doc;
5369     ret->state = XML_TEXTREADER_START;
5370     ret->dict = xmlDictCreate();
5371     return(ret);
5372 }
5373 
5374 /**
5375  * xmlReaderForDoc:
5376  * @cur:  a pointer to a zero terminated string
5377  * @URL:  the base URL to use for the document
5378  * @encoding:  the document encoding, or NULL
5379  * @options:  a combination of xmlParserOption
5380  *
5381  * Create an xmltextReader for an XML in-memory document.
5382  * The parsing flags @options are a combination of xmlParserOption.
5383  *
5384  * Returns the new reader or NULL in case of error.
5385  */
5386 xmlTextReaderPtr
xmlReaderForDoc(const xmlChar * cur,const char * URL,const char * encoding,int options)5387 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5388                 int options)
5389 {
5390     int len;
5391 
5392     if (cur == NULL)
5393         return (NULL);
5394     len = xmlStrlen(cur);
5395 
5396     return (xmlReaderForMemory
5397             ((const char *) cur, len, URL, encoding, options));
5398 }
5399 
5400 /**
5401  * xmlReaderForFile:
5402  * @filename:  a file or URL
5403  * @encoding:  the document encoding, or NULL
5404  * @options:  a combination of xmlParserOption
5405  *
5406  * parse an XML file from the filesystem or the network.
5407  * The parsing flags @options are a combination of xmlParserOption.
5408  *
5409  * Returns the new reader or NULL in case of error.
5410  */
5411 xmlTextReaderPtr
xmlReaderForFile(const char * filename,const char * encoding,int options)5412 xmlReaderForFile(const char *filename, const char *encoding, int options)
5413 {
5414     xmlTextReaderPtr reader;
5415 
5416     reader = xmlNewTextReaderFilename(filename);
5417     if (reader == NULL)
5418         return (NULL);
5419     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5420     return (reader);
5421 }
5422 
5423 /**
5424  * xmlReaderForMemory:
5425  * @buffer:  a pointer to a char array
5426  * @size:  the size of the array
5427  * @URL:  the base URL to use for the document
5428  * @encoding:  the document encoding, or NULL
5429  * @options:  a combination of xmlParserOption
5430  *
5431  * Create an xmltextReader for an XML in-memory document.
5432  * The parsing flags @options are a combination of xmlParserOption.
5433  *
5434  * Returns the new reader or NULL in case of error.
5435  */
5436 xmlTextReaderPtr
xmlReaderForMemory(const char * buffer,int size,const char * URL,const char * encoding,int options)5437 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5438                    const char *encoding, int options)
5439 {
5440     xmlTextReaderPtr reader;
5441     xmlParserInputBufferPtr buf;
5442 
5443     buf = xmlParserInputBufferCreateStatic(buffer, size,
5444                                       XML_CHAR_ENCODING_NONE);
5445     if (buf == NULL) {
5446         return (NULL);
5447     }
5448     reader = xmlNewTextReader(buf, URL);
5449     if (reader == NULL) {
5450         xmlFreeParserInputBuffer(buf);
5451         return (NULL);
5452     }
5453     reader->allocs |= XML_TEXTREADER_INPUT;
5454     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5455     return (reader);
5456 }
5457 
5458 /**
5459  * xmlReaderForFd:
5460  * @fd:  an open file descriptor
5461  * @URL:  the base URL to use for the document
5462  * @encoding:  the document encoding, or NULL
5463  * @options:  a combination of xmlParserOption
5464  *
5465  * Create an xmltextReader for an XML from a file descriptor.
5466  * The parsing flags @options are a combination of xmlParserOption.
5467  * NOTE that the file descriptor will not be closed when the
5468  *      reader is closed or reset.
5469  *
5470  * Returns the new reader or NULL in case of error.
5471  */
5472 xmlTextReaderPtr
xmlReaderForFd(int fd,const char * URL,const char * encoding,int options)5473 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5474 {
5475     xmlTextReaderPtr reader;
5476     xmlParserInputBufferPtr input;
5477 
5478     if (fd < 0)
5479         return (NULL);
5480 
5481     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5482     if (input == NULL)
5483         return (NULL);
5484     input->closecallback = NULL;
5485     reader = xmlNewTextReader(input, URL);
5486     if (reader == NULL) {
5487         xmlFreeParserInputBuffer(input);
5488         return (NULL);
5489     }
5490     reader->allocs |= XML_TEXTREADER_INPUT;
5491     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5492     return (reader);
5493 }
5494 
5495 /**
5496  * xmlReaderForIO:
5497  * @ioread:  an I/O read function
5498  * @ioclose:  an I/O close function
5499  * @ioctx:  an I/O handler
5500  * @URL:  the base URL to use for the document
5501  * @encoding:  the document encoding, or NULL
5502  * @options:  a combination of xmlParserOption
5503  *
5504  * Create an xmltextReader for an XML document from I/O functions and source.
5505  * The parsing flags @options are a combination of xmlParserOption.
5506  *
5507  * Returns the new reader or NULL in case of error.
5508  */
5509 xmlTextReaderPtr
xmlReaderForIO(xmlInputReadCallback ioread,xmlInputCloseCallback ioclose,void * ioctx,const char * URL,const char * encoding,int options)5510 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5511                void *ioctx, const char *URL, const char *encoding,
5512                int options)
5513 {
5514     xmlTextReaderPtr reader;
5515     xmlParserInputBufferPtr input;
5516 
5517     if (ioread == NULL)
5518         return (NULL);
5519 
5520     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5521                                          XML_CHAR_ENCODING_NONE);
5522     if (input == NULL) {
5523         if (ioclose != NULL)
5524             ioclose(ioctx);
5525         return (NULL);
5526     }
5527     reader = xmlNewTextReader(input, URL);
5528     if (reader == NULL) {
5529         xmlFreeParserInputBuffer(input);
5530         return (NULL);
5531     }
5532     reader->allocs |= XML_TEXTREADER_INPUT;
5533     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5534     return (reader);
5535 }
5536 
5537 /**
5538  * xmlReaderNewWalker:
5539  * @reader:  an XML reader
5540  * @doc:  a preparsed document
5541  *
5542  * Setup an xmltextReader to parse a preparsed XML document.
5543  * This reuses the existing @reader xmlTextReader.
5544  *
5545  * Returns 0 in case of success and -1 in case of error
5546  */
5547 int
xmlReaderNewWalker(xmlTextReaderPtr reader,xmlDocPtr doc)5548 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5549 {
5550     if (doc == NULL)
5551         return (-1);
5552     if (reader == NULL)
5553         return (-1);
5554 
5555     if (reader->input != NULL) {
5556         xmlFreeParserInputBuffer(reader->input);
5557     }
5558     if (reader->ctxt != NULL) {
5559 	xmlCtxtReset(reader->ctxt);
5560     }
5561 
5562     reader->entNr = 0;
5563     reader->input = NULL;
5564     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5565     reader->node = NULL;
5566     reader->curnode = NULL;
5567     reader->base = 0;
5568     reader->cur = 0;
5569     reader->allocs = XML_TEXTREADER_CTXT;
5570     reader->doc = doc;
5571     reader->state = XML_TEXTREADER_START;
5572     if (reader->dict == NULL) {
5573         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5574 	    reader->dict = reader->ctxt->dict;
5575 	else
5576 	    reader->dict = xmlDictCreate();
5577     }
5578     return(0);
5579 }
5580 
5581 /**
5582  * xmlReaderNewDoc:
5583  * @reader:  an XML reader
5584  * @cur:  a pointer to a zero terminated string
5585  * @URL:  the base URL to use for the document
5586  * @encoding:  the document encoding, or NULL
5587  * @options:  a combination of xmlParserOption
5588  *
5589  * Setup an xmltextReader to parse an XML in-memory document.
5590  * The parsing flags @options are a combination of xmlParserOption.
5591  * This reuses the existing @reader xmlTextReader.
5592  *
5593  * Returns 0 in case of success and -1 in case of error
5594  */
5595 int
xmlReaderNewDoc(xmlTextReaderPtr reader,const xmlChar * cur,const char * URL,const char * encoding,int options)5596 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5597                 const char *URL, const char *encoding, int options)
5598 {
5599 
5600     int len;
5601 
5602     if (cur == NULL)
5603         return (-1);
5604     if (reader == NULL)
5605         return (-1);
5606 
5607     len = xmlStrlen(cur);
5608     return (xmlReaderNewMemory(reader, (const char *)cur, len,
5609                                URL, encoding, options));
5610 }
5611 
5612 /**
5613  * xmlReaderNewFile:
5614  * @reader:  an XML reader
5615  * @filename:  a file or URL
5616  * @encoding:  the document encoding, or NULL
5617  * @options:  a combination of xmlParserOption
5618  *
5619  * parse an XML file from the filesystem or the network.
5620  * The parsing flags @options are a combination of xmlParserOption.
5621  * This reuses the existing @reader xmlTextReader.
5622  *
5623  * Returns 0 in case of success and -1 in case of error
5624  */
5625 int
xmlReaderNewFile(xmlTextReaderPtr reader,const char * filename,const char * encoding,int options)5626 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5627                  const char *encoding, int options)
5628 {
5629     xmlParserInputBufferPtr input;
5630 
5631     if (filename == NULL)
5632         return (-1);
5633     if (reader == NULL)
5634         return (-1);
5635 
5636     input =
5637         xmlParserInputBufferCreateFilename(filename,
5638                                            XML_CHAR_ENCODING_NONE);
5639     if (input == NULL)
5640         return (-1);
5641     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5642 }
5643 
5644 /**
5645  * xmlReaderNewMemory:
5646  * @reader:  an XML reader
5647  * @buffer:  a pointer to a char array
5648  * @size:  the size of the array
5649  * @URL:  the base URL to use for the document
5650  * @encoding:  the document encoding, or NULL
5651  * @options:  a combination of xmlParserOption
5652  *
5653  * Setup an xmltextReader to parse an XML in-memory document.
5654  * The parsing flags @options are a combination of xmlParserOption.
5655  * This reuses the existing @reader xmlTextReader.
5656  *
5657  * Returns 0 in case of success and -1 in case of error
5658  */
5659 int
xmlReaderNewMemory(xmlTextReaderPtr reader,const char * buffer,int size,const char * URL,const char * encoding,int options)5660 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5661                    const char *URL, const char *encoding, int options)
5662 {
5663     xmlParserInputBufferPtr input;
5664 
5665     if (reader == NULL)
5666         return (-1);
5667     if (buffer == NULL)
5668         return (-1);
5669 
5670     input = xmlParserInputBufferCreateStatic(buffer, size,
5671                                       XML_CHAR_ENCODING_NONE);
5672     if (input == NULL) {
5673         return (-1);
5674     }
5675     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5676 }
5677 
5678 /**
5679  * xmlReaderNewFd:
5680  * @reader:  an XML reader
5681  * @fd:  an open file descriptor
5682  * @URL:  the base URL to use for the document
5683  * @encoding:  the document encoding, or NULL
5684  * @options:  a combination of xmlParserOption
5685  *
5686  * Setup an xmltextReader to parse an XML from a file descriptor.
5687  * NOTE that the file descriptor will not be closed when the
5688  *      reader is closed or reset.
5689  * The parsing flags @options are a combination of xmlParserOption.
5690  * This reuses the existing @reader xmlTextReader.
5691  *
5692  * Returns 0 in case of success and -1 in case of error
5693  */
5694 int
xmlReaderNewFd(xmlTextReaderPtr reader,int fd,const char * URL,const char * encoding,int options)5695 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5696                const char *URL, const char *encoding, int options)
5697 {
5698     xmlParserInputBufferPtr input;
5699 
5700     if (fd < 0)
5701         return (-1);
5702     if (reader == NULL)
5703         return (-1);
5704 
5705     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5706     if (input == NULL)
5707         return (-1);
5708     input->closecallback = NULL;
5709     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5710 }
5711 
5712 /**
5713  * xmlReaderNewIO:
5714  * @reader:  an XML reader
5715  * @ioread:  an I/O read function
5716  * @ioclose:  an I/O close function
5717  * @ioctx:  an I/O handler
5718  * @URL:  the base URL to use for the document
5719  * @encoding:  the document encoding, or NULL
5720  * @options:  a combination of xmlParserOption
5721  *
5722  * Setup an xmltextReader to parse an XML document from I/O functions
5723  * and source.
5724  * The parsing flags @options are a combination of xmlParserOption.
5725  * This reuses the existing @reader xmlTextReader.
5726  *
5727  * Returns 0 in case of success and -1 in case of error
5728  */
5729 int
xmlReaderNewIO(xmlTextReaderPtr reader,xmlInputReadCallback ioread,xmlInputCloseCallback ioclose,void * ioctx,const char * URL,const char * encoding,int options)5730 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5731                xmlInputCloseCallback ioclose, void *ioctx,
5732                const char *URL, const char *encoding, int options)
5733 {
5734     xmlParserInputBufferPtr input;
5735 
5736     if (ioread == NULL)
5737         return (-1);
5738     if (reader == NULL)
5739         return (-1);
5740 
5741     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5742                                          XML_CHAR_ENCODING_NONE);
5743     if (input == NULL) {
5744         if (ioclose != NULL)
5745             ioclose(ioctx);
5746         return (-1);
5747     }
5748     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5749 }
5750 
5751 /************************************************************************
5752  *									*
5753  *			Utilities					*
5754  *									*
5755  ************************************************************************/
5756 #ifdef NOT_USED_YET
5757 
5758 /**
5759  * xmlBase64Decode:
5760  * @in:  the input buffer
5761  * @inlen:  the size of the input (in), the size read from it (out)
5762  * @to:  the output buffer
5763  * @tolen:  the size of the output (in), the size written to (out)
5764  *
5765  * Base64 decoder, reads from @in and save in @to
5766  * TODO: tell jody when this is actually exported
5767  *
5768  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5769  *         2 if there wasn't enough space on the output or -1 in case of error.
5770  */
5771 static int
xmlBase64Decode(const unsigned char * in,unsigned long * inlen,unsigned char * to,unsigned long * tolen)5772 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5773                 unsigned char *to, unsigned long *tolen)
5774 {
5775     unsigned long incur;        /* current index in in[] */
5776 
5777     unsigned long inblk;        /* last block index in in[] */
5778 
5779     unsigned long outcur;       /* current index in out[] */
5780 
5781     unsigned long inmax;        /* size of in[] */
5782 
5783     unsigned long outmax;       /* size of out[] */
5784 
5785     unsigned char cur;          /* the current value read from in[] */
5786 
5787     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
5788 
5789     int nbintmp;                /* number of byte in intmp[] */
5790 
5791     int is_ignore;              /* cur should be ignored */
5792 
5793     int is_end = 0;             /* the end of the base64 was found */
5794 
5795     int retval = 1;
5796 
5797     int i;
5798 
5799     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5800         return (-1);
5801 
5802     incur = 0;
5803     inblk = 0;
5804     outcur = 0;
5805     inmax = *inlen;
5806     outmax = *tolen;
5807     nbintmp = 0;
5808 
5809     while (1) {
5810         if (incur >= inmax)
5811             break;
5812         cur = in[incur++];
5813         is_ignore = 0;
5814         if ((cur >= 'A') && (cur <= 'Z'))
5815             cur = cur - 'A';
5816         else if ((cur >= 'a') && (cur <= 'z'))
5817             cur = cur - 'a' + 26;
5818         else if ((cur >= '0') && (cur <= '9'))
5819             cur = cur - '0' + 52;
5820         else if (cur == '+')
5821             cur = 62;
5822         else if (cur == '/')
5823             cur = 63;
5824         else if (cur == '.')
5825             cur = 0;
5826         else if (cur == '=')    /*no op , end of the base64 stream */
5827             is_end = 1;
5828         else {
5829             is_ignore = 1;
5830             if (nbintmp == 0)
5831                 inblk = incur;
5832         }
5833 
5834         if (!is_ignore) {
5835             int nbouttmp = 3;
5836 
5837             int is_break = 0;
5838 
5839             if (is_end) {
5840                 if (nbintmp == 0)
5841                     break;
5842                 if ((nbintmp == 1) || (nbintmp == 2))
5843                     nbouttmp = 1;
5844                 else
5845                     nbouttmp = 2;
5846                 nbintmp = 3;
5847                 is_break = 1;
5848             }
5849             intmp[nbintmp++] = cur;
5850             /*
5851              * if intmp is full, push the 4byte sequence as a 3 byte
5852              * sequence out
5853              */
5854             if (nbintmp == 4) {
5855                 nbintmp = 0;
5856                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5857                 outtmp[1] =
5858                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5859                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5860                 if (outcur + 3 >= outmax) {
5861                     retval = 2;
5862                     break;
5863                 }
5864 
5865                 for (i = 0; i < nbouttmp; i++)
5866                     to[outcur++] = outtmp[i];
5867                 inblk = incur;
5868             }
5869 
5870             if (is_break) {
5871                 retval = 0;
5872                 break;
5873             }
5874         }
5875     }
5876 
5877     *tolen = outcur;
5878     *inlen = inblk;
5879     return (retval);
5880 }
5881 
5882 /*
5883  * Test routine for the xmlBase64Decode function
5884  */
5885 #if 0
5886 int
5887 main(int argc, char **argv)
5888 {
5889     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
5890 
5891     char output[100];
5892 
5893     char output2[100];
5894 
5895     char output3[100];
5896 
5897     unsigned long inlen = strlen(input);
5898 
5899     unsigned long outlen = 100;
5900 
5901     int ret;
5902 
5903     unsigned long cons, tmp, tmp2, prod;
5904 
5905     /*
5906      * Direct
5907      */
5908     ret = xmlBase64Decode(input, &inlen, output, &outlen);
5909 
5910     output[outlen] = 0;
5911     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5912            outlen, output)indent: Standard input:179: Error:Unmatched #endif
5913 ;
5914 
5915     /*
5916      * output chunking
5917      */
5918     cons = 0;
5919     prod = 0;
5920     while (cons < inlen) {
5921         tmp = 5;
5922         tmp2 = inlen - cons;
5923 
5924         printf("%ld %ld\n", cons, prod);
5925         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5926         cons += tmp2;
5927         prod += tmp;
5928         printf("%ld %ld\n", cons, prod);
5929     }
5930     output2[outlen] = 0;
5931     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5932            prod, output2);
5933 
5934     /*
5935      * input chunking
5936      */
5937     cons = 0;
5938     prod = 0;
5939     while (cons < inlen) {
5940         tmp = 100 - prod;
5941         tmp2 = inlen - cons;
5942         if (tmp2 > 5)
5943             tmp2 = 5;
5944 
5945         printf("%ld %ld\n", cons, prod);
5946         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5947         cons += tmp2;
5948         prod += tmp;
5949         printf("%ld %ld\n", cons, prod);
5950     }
5951     output3[outlen] = 0;
5952     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5953            prod, output3);
5954     return (0);
5955 
5956 }
5957 #endif
5958 #endif /* NOT_USED_YET */
5959 #define bottom_xmlreader
5960 #include "elfgcchack.h"
5961 #endif /* LIBXML_READER_ENABLED */
5962