summaryrefslogtreecommitdiff
path: root/xmlreader.c
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2003-01-03 01:18:43 +0000
committerDaniel Veillard <veillard@src.gnome.org>2003-01-03 01:18:43 +0000
commit1fdfd115e522b45ead8ee1576c8a863483f767e1 (patch)
tree131e284135d60e6df3140a21f392e38a5f76f2fc /xmlreader.c
parentdab8ea9b83b22ecd48d97dd13fe5035cf392d3fd (diff)
downloadlibxml2-1fdfd115e522b45ead8ee1576c8a863483f767e1.tar.gz
Fixing some more mess with validation and recursive entities while using
* xmlreader.c python/tests/reader2py: Fixing some more mess with validation and recursive entities while using the reader interface, it's getting a bit messy... Daniel
Diffstat (limited to 'xmlreader.c')
-rw-r--r--xmlreader.c217
1 files changed, 202 insertions, 15 deletions
diff --git a/xmlreader.c b/xmlreader.c
index 930ec53b..f7d5b433 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -92,6 +92,12 @@ struct _xmlTextReader {
int depth; /* depth of the current node */
xmlNodePtr faketext;/* fake xmlNs chld */
int wasempty;/* was the last node empty */
+
+ /* entity stack when traversing entities content */
+ xmlNodePtr ent; /* Current Entity Ref Node */
+ int entNr; /* Depth of the entities stack */
+ int entMax; /* Max depth of the entities stack */
+ xmlNodePtr *entTab; /* array of entities */
};
#ifdef DEBUG_READER
@@ -123,6 +129,68 @@ xmlTextReaderDebug(xmlTextReaderPtr reader) {
#endif
/**
+ * xmlTextReaderEntPush:
+ * @reader: the xmlTextReaderPtr used
+ * @value: the entity reference node
+ *
+ * Pushes a new entity reference node on top of the entities stack
+ *
+ * Returns 0 in case of error, the index in the stack otherwise
+ */
+static int
+xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
+{
+ if (reader->entMax <= 0) {
+ reader->entMax = 10;
+ reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
+ sizeof(reader->entTab[0]));
+ if (reader->entTab == NULL) {
+ xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
+ return (0);
+ }
+ }
+ if (reader->entNr >= reader->entMax) {
+ reader->entMax *= 2;
+ reader->entTab =
+ (xmlNodePtr *) xmlRealloc(reader->entTab,
+ reader->entMax *
+ sizeof(reader->entTab[0]));
+ if (reader->entTab == NULL) {
+ xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
+ return (0);
+ }
+ }
+ reader->entTab[reader->entNr] = value;
+ reader->ent = value;
+ return (reader->entNr++);
+}
+
+/**
+ * xmlTextReaderEntPop:
+ * @reader: the xmlTextReaderPtr used
+ *
+ * Pops the top element entity from the entities stack
+ *
+ * Returns the entity just removed
+ */
+static xmlNodePtr
+xmlTextReaderEntPop(xmlTextReaderPtr reader)
+{
+ xmlNodePtr ret;
+
+ if (reader->entNr <= 0)
+ return (0);
+ reader->entNr--;
+ if (reader->entNr > 0)
+ reader->ent = reader->entTab[reader->entNr - 1];
+ else
+ reader->ent = NULL;
+ ret = reader->entTab[reader->entNr];
+ reader->entTab[reader->entNr] = 0;
+ return (ret);
+}
+
+/**
* xmlTextReaderStartElement:
* @ctx: the user data (XML parser context)
* @fullname: The element name, including namespace prefix
@@ -146,10 +214,13 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
*/
origctxt = reader->ctxt;
reader->startElement(ctx, fullname, atts);
+#if 0
+ 123
if (origctxt->validate) {
ctxt->valid &= xmlValidatePushElement(&origctxt->vctxt,
ctxt->myDoc, ctxt->node, fullname);
}
+#endif
}
if (reader != NULL)
reader->state = XML_TEXTREADER_ELEMENT;
@@ -180,10 +251,13 @@ xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
reader->endElement(ctx, fullname);
+#if 0
+ 123
if (origctxt->validate) {
ctxt->valid &= xmlValidatePopElement(&origctxt->vctxt,
ctxt->myDoc, node, fullname);
}
+#endif
}
if (reader != NULL) {
if (reader->state == XML_TEXTREADER_ELEMENT)
@@ -218,9 +292,12 @@ xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
*/
origctxt = reader->ctxt;
+#if 0
+ 123
if (origctxt->validate) {
ctxt->valid &= xmlValidatePushCData(&origctxt->vctxt, ch, len);
}
+#endif
}
}
@@ -289,7 +366,8 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
} else
break;
}
- if ((inbuf->content[cur] == '>') || (inbuf->content[cur] == '&')) {
+ if ((inbuf->content[cur] == '>') || (inbuf->content[cur] == '&') ||
+ (inbuf->content[cur] == ';')) {
cur = cur + 1;
val = xmlParseChunk(reader->ctxt,
(const char *) &inbuf->content[reader->cur],
@@ -345,6 +423,58 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
}
/**
+ * xmlTextReaderValidatePush:
+ * @reader: the xmlTextReaderPtr used
+ *
+ * Push the current node for validation
+ */
+static void
+xmlTextReaderValidatePush(xmlTextReaderPtr reader) {
+ xmlNodePtr node = reader->node;
+
+ if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
+ reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
+ reader->ctxt->myDoc, node, node->name);
+ } else {
+ xmlChar *qname;
+
+ qname = xmlStrdup(node->ns->prefix);
+ qname = xmlStrcat(qname, BAD_CAST ":");
+ qname = xmlStrcat(qname, node->name);
+ reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
+ reader->ctxt->myDoc, node, qname);
+ if (qname != NULL)
+ xmlFree(qname);
+ }
+}
+/**
+ * xmlTextReaderValidatePop:
+ * @reader: the xmlTextReaderPtr used
+ *
+ * Pop the current node from validation
+ */
+static void
+xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
+ xmlNodePtr node = reader->node;
+
+ if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
+ reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
+ reader->ctxt->myDoc, node, node->name);
+ } else {
+ xmlChar *qname;
+
+ qname = xmlStrdup(node->ns->prefix);
+ qname = xmlStrcat(qname, BAD_CAST ":");
+ qname = xmlStrcat(qname, node->name);
+ reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
+ reader->ctxt->myDoc, node, qname);
+ if (qname != NULL)
+ xmlFree(qname);
+ }
+}
+
+
+/**
* xmlTextReaderRead:
* @reader: the xmlTextReaderPtr used
*
@@ -356,9 +486,9 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
*/
int
xmlTextReaderRead(xmlTextReaderPtr reader) {
- int val, olddepth, wasempty;
- xmlTextReaderState oldstate;
- xmlNodePtr oldnode;
+ int val, olddepth = 0, wasempty = 0;
+ xmlTextReaderState oldstate = 0;
+ xmlNodePtr oldnode = NULL;
if ((reader == NULL) || (reader->ctxt == NULL))
return(-1);
@@ -396,7 +526,7 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
reader->node = reader->ctxt->nodeTab[0];
}
reader->depth = 0;
- return(1);
+ goto node_found;
}
oldstate = reader->state;
olddepth = reader->ctxt->nodeNr;
@@ -412,6 +542,7 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
(reader->ctxt->node->last == reader->node)) ||
(reader->node != reader->ctxt->node));
+get_next_node:
/*
* If we are not backtracking on ancestors or examined nodes,
* that the parser didn't finished or that we arent at the end
@@ -428,7 +559,7 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
if (val < 0)
return(-1);
if (reader->node == NULL)
- return(0);
+ goto node_end;
}
if (oldstate != XML_TEXTREADER_BACKTRACK) {
if ((reader->node->children != NULL) &&
@@ -437,8 +568,7 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
reader->node = reader->node->children;
reader->depth++;
reader->state = XML_TEXTREADER_ELEMENT;
- DUMP_READER
- return(1);
+ goto node_found;
}
}
if (reader->node->next != NULL) {
@@ -446,12 +576,14 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
(reader->node->type == XML_ELEMENT_NODE) &&
(wasempty == 0)) {
reader->state = XML_TEXTREADER_END;
- DUMP_READER
- return(1);
+ goto node_found;
}
+ if ((reader->ctxt->validate) &&
+ (reader->node->type == XML_ELEMENT_NODE))
+ xmlTextReaderValidatePop(reader);
reader->node = reader->node->next;
reader->state = XML_TEXTREADER_ELEMENT;
- DUMP_READER
+
/*
* Cleanup of the old node
*/
@@ -460,15 +592,16 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
xmlFreeNode(oldnode);
}
- return(1);
+ goto node_found;
}
if ((oldstate == XML_TEXTREADER_ELEMENT) &&
(reader->node->type == XML_ELEMENT_NODE) &&
(wasempty == 0)) {
reader->state = XML_TEXTREADER_END;
- DUMP_READER
- return(1);
+ goto node_found;
}
+ if ((reader->ctxt->validate) && (reader->node->type == XML_ELEMENT_NODE))
+ xmlTextReaderValidatePop(reader);
reader->node = reader->node->parent;
if ((reader->node == NULL) ||
(reader->node->type == XML_DOCUMENT_NODE) ||
@@ -491,12 +624,61 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
xmlFreeNode(oldnode);
}
- return(0);
+ goto node_end;
}
reader->depth--;
reader->state = XML_TEXTREADER_BACKTRACK;
+
+node_found:
DUMP_READER
+
+ /*
+ * Handle entities enter and exit
+ */
+ if ((reader->node != NULL) &&
+ (reader->node->type == XML_ENTITY_REF_NODE) &&
+ (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
+ /*
+ * Case where the underlying tree is not availble, lookup the entity
+ * and walk it.
+ */
+ if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
+ (reader->ctxt->sax->getEntity != NULL)) {
+ reader->node->children = (xmlNodePtr)
+ reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
+ }
+
+ if ((reader->node->children != NULL) &&
+ (reader->node->children->type == XML_ENTITY_DECL) &&
+ (reader->node->children->children != NULL)) {
+ xmlTextReaderEntPush(reader, reader->node);
+ reader->node = reader->node->children->children;
+ }
+ }
+ if ((reader->node != NULL) &&
+ (reader->node->type == XML_ENTITY_DECL) &&
+ (reader->ent != NULL) && (reader->ent->children == reader->node)) {
+ reader->node = xmlTextReaderEntPop(reader);
+ reader->depth++;
+ goto get_next_node;
+ }
+ if ((reader->ctxt->validate) && (reader->node != NULL)) {
+ xmlNodePtr node = reader->node;
+ xmlParserCtxtPtr ctxt = reader->ctxt;
+
+ if ((node->type == XML_ELEMENT_NODE) &&
+ ((reader->state != XML_TEXTREADER_END) &&
+ (reader->state != XML_TEXTREADER_BACKTRACK))) {
+ xmlTextReaderValidatePush(reader);
+ } else if ((node->type == XML_TEXT_NODE) ||
+ (node->type == XML_CDATA_SECTION_NODE)) {
+ ctxt->valid &= xmlValidatePushCData(&ctxt->vctxt,
+ node->content, xmlStrlen(node->content));
+ }
+ }
return(1);
+node_end:
+ return(0);
}
/**
@@ -646,6 +828,9 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
return(NULL);
}
memset(ret, 0, sizeof(xmlTextReader));
+ ret->entTab = NULL;
+ ret->entMax = 0;
+ ret->entNr = 0;
ret->input = input;
ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
if (ret->sax == NULL) {
@@ -748,6 +933,8 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
if (reader->faketext != NULL) {
xmlFreeNode(reader->faketext);
}
+ if (reader->entTab != NULL)
+ xmlFree(reader->entTab);
xmlFree(reader);
}