fix a problem reported by Ashwin for system parameter entities referenced

* parser.c: fix a problem reported by Ashwin for system parameter
  entities referenced from entities in external subset, add a
  specific loading routine.
* test/valid/dtds/external.ent test/valid/dtds/external2.ent
  test/valid/t11.xml result/valid/t11.xml*: added the test to
  the regression suite
Daniel

svn path=/trunk/; revision=3713
diff --git a/ChangeLog b/ChangeLog
index d5b23cb..6a0b9bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Mon Mar 24 21:42:33 CET 2008 Daniel Veillard <daniel@veillard.com>
+
+	* parser.c: fix a problem reported by Ashwin for system parameter
+	  entities referenced from entities in external subset, add a
+	  specific loading routine.
+	* test/valid/dtds/external.ent test/valid/dtds/external2.ent
+	  test/valid/t11.xml result/valid/t11.xml*: added the test to
+	  the regression suite
+
 Mon Mar 24 15:04:54 CET 2008 Daniel Veillard <daniel@veillard.com>
 
 	* xmlschemas.c: fix an XML Schemas crash raised by Stefan Behnel
diff --git a/parser.c b/parser.c
index b08149d..69b1caf 100644
--- a/parser.c
+++ b/parser.c
@@ -126,6 +126,9 @@
 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
 		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
 
+static int
+xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
+
 /************************************************************************
  *									*
  * 		Some factorized error routines				*
@@ -2309,6 +2312,10 @@
 	    if (ent != NULL) {
 		xmlChar *rep;
 
+                if (ent->content == NULL) {
+		    if (xmlLoadEntityContent(ctxt, ent) < 0) {
+		    }
+		}
 		ctxt->depth++;
 		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
 			                      0, 0, 0);
@@ -2456,7 +2463,7 @@
  * xmlSplitQName:
  * @ctxt:  an XML parser context
  * @name:  an XML parser context
- * @prefix:  a xmlChar ** 
+ * @prefix:  a xmlChar **
  *
  * parse an UTF8 encoded XML qualified name string
  *
@@ -2507,7 +2514,7 @@
 	 * for the processing speed.
 	 */
 	max = len * 2;
-	
+
 	buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
 	if (buffer == NULL) {
 	    xmlErrMemory(ctxt, NULL);
@@ -2533,7 +2540,7 @@
 	}
 	buffer[len] = 0;
     }
-    
+
     if ((c == ':') && (*cur == 0)) {
         if (buffer != NULL)
 	    xmlFree(buffer);
@@ -6828,6 +6835,86 @@
 }
 
 /**
+ * xmlLoadEntityContent:
+ * @ctxt:  an XML parser context
+ * @entity: an unloaded system entity
+ *
+ * Load the original content of the given system entity from the
+ * ExternalID/SystemID given. This is to be used for Included in Literal
+ * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
+ *
+ * Returns 0 in case of success and -1 in case of failure
+ */
+static int
+xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
+    xmlParserInputPtr input;
+    xmlBufferPtr buf;
+    int l, c;
+    int count = 0;
+
+    if ((ctxt == NULL) || (entity == NULL) ||
+        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
+	 (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
+	(entity->content != NULL)) {
+	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+	            "xmlLoadEntityContent parameter error");
+        return(-1);
+    }
+
+    if (xmlParserDebugEntities)
+	xmlGenericError(xmlGenericErrorContext,
+		"Reading %s entity content input\n", entity->name);
+
+    buf = xmlBufferCreate();
+    if (buf == NULL) {
+	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+	            "xmlLoadEntityContent parameter error");
+        return(-1);
+    }
+
+    input = xmlNewEntityInputStream(ctxt, entity);
+    if (input == NULL) {
+	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+	            "xmlLoadEntityContent input error");
+	xmlBufferFree(buf);
+        return(-1);
+    }
+
+    /*
+     * Push the entity as the current input, read char by char
+     * saving to the buffer until the end of the entity or an error
+     */
+    xmlPushInput(ctxt, input);
+    GROW;
+    c = CUR_CHAR(l);
+    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
+           (IS_CHAR(c))) {
+        xmlBufferAdd(buf, ctxt->input->cur, l);
+	if (count++ > 100) {
+	    count = 0;
+	    GROW;
+	}
+	NEXTL(l);
+	c = CUR_CHAR(l);
+    }
+
+    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
+        xmlPopInput(ctxt);
+    } else if (!IS_CHAR(c)) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                          "xmlLoadEntityContent: invalid char value %d\n",
+	                  c);
+	xmlBufferFree(buf);
+	return(-1);
+    }
+    entity->content = buf->content;
+    buf->content = NULL;
+    xmlBufferFree(buf);
+
+    return(0);
+}
+
+/**
  * xmlParseStringPEReference:
  * @ctxt:  an XML parser context
  * @str:  a pointer to an index in the string
@@ -6838,7 +6925,7 @@
  *
  * [ WFC: No Recursion ]
  * A parsed entity must not contain a recursive
- * reference to itself, either directly or indirectly. 
+ * reference to itself, either directly or indirectly.
  *
  * [ WFC: Entity Declared ]
  * In a document without any DTD, a document with only an internal DTD
diff --git a/result/valid/t11.xml b/result/valid/t11.xml
new file mode 100644
index 0000000..d871787
--- /dev/null
+++ b/result/valid/t11.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE root SYSTEM "dtds/external.ent">
+<root>&peInCdata;</root>
diff --git a/result/valid/t11.xml.err b/result/valid/t11.xml.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/result/valid/t11.xml.err
diff --git a/test/valid/dtds/external.ent b/test/valid/dtds/external.ent
new file mode 100644
index 0000000..8a4495d
--- /dev/null
+++ b/test/valid/dtds/external.ent
@@ -0,0 +1,3 @@
+<!ELEMENT root (#PCDATA)>
+<!ENTITY % peInCdata SYSTEM "external2.ent">
+<!ENTITY peInCdata "<![CDATA[%peInCdata;]]>">
diff --git a/test/valid/dtds/external2.ent b/test/valid/dtds/external2.ent
new file mode 100644
index 0000000..348e1db
--- /dev/null
+++ b/test/valid/dtds/external2.ent
@@ -0,0 +1 @@
+<!ATTLIST root attr1 NMTOKEN "attrvalue">
diff --git a/test/valid/t11.xml b/test/valid/t11.xml
new file mode 100644
index 0000000..cc3fb31
--- /dev/null
+++ b/test/valid/t11.xml
@@ -0,0 +1,2 @@
+<!DOCTYPE root SYSTEM "dtds/external.ent">
+<root>&peInCdata;</root>