patch from Richard Jones to save the query part in raw form. Daniel

* uri.c include/libxml/uri.h: patch from Richard Jones to save
  the query part in raw form.
Daniel

svn path=/trunk/; revision=3607
diff --git a/ChangeLog b/ChangeLog
index 3e3871f..91e9abd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Apr 26 10:36:26 CEST 2007 Daniel Veillard <daniel@veillard.com>
+
+	* uri.c include/libxml/uri.h: patch from Richard Jones to save
+	  the query part in raw form.
+
 Wed Apr 25 15:57:32 CEST 2007 Daniel Veillard <daniel@veillard.com>
 
 	* xstc/Makefile.am doc/examples/Makefile.am Makefile.am: applied
diff --git a/include/libxml/uri.h b/include/libxml/uri.h
index 5e29671..49ed105 100644
--- a/include/libxml/uri.h
+++ b/include/libxml/uri.h
@@ -23,6 +23,10 @@
  *
  * A parsed URI reference. This is a struct containing the various fields
  * as described in RFC 2396 but separated for further processing.
+ *
+ * Note: query is a deprecated field which is incorrectly unescaped.
+ * query_raw takes precedence over query if the former is set.
+ * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00127
  */
 typedef struct _xmlURI xmlURI;
 typedef xmlURI *xmlURIPtr;
@@ -34,9 +38,10 @@
     char *user;		/* the user part */
     int port;		/* the port number */
     char *path;		/* the path string */
-    char *query;	/* the query string */
+    char *query;	/* the query string (deprecated - use with caution) */
     char *fragment;	/* the fragment identifier */
     int  cleanup;	/* parsing potentially unclean URI */
+    char *query_raw;	/* the query string (as it appears in the URI) */
 };
 
 /*
diff --git a/uri.c b/uri.c
index 0b91c24..2141317 100644
--- a/uri.c
+++ b/uri.c
@@ -446,7 +446,33 @@
 		}
 	    }
 	}
-	if (uri->query != NULL) {
+	if (uri->query_raw != NULL) {
+	    if (len + 1 >= max) {
+		max *= 2;
+		ret = (xmlChar *) xmlRealloc(ret,
+			(max + 1) * sizeof(xmlChar));
+		if (ret == NULL) {
+		    xmlGenericError(xmlGenericErrorContext,
+			    "xmlSaveUri: out of memory\n");
+		    return(NULL);
+		}
+	    }
+	    ret[len++] = '?';
+	    p = uri->query_raw;
+	    while (*p != 0) {
+		if (len + 1 >= max) {
+		    max *= 2;
+		    ret = (xmlChar *) xmlRealloc(ret,
+			    (max + 1) * sizeof(xmlChar));
+		    if (ret == NULL) {
+			xmlGenericError(xmlGenericErrorContext,
+				"xmlSaveUri: out of memory\n");
+			return(NULL);
+		    }
+		}
+		ret[len++] = *p++;
+	    }
+	} else if (uri->query != NULL) {
 	    if (len + 3 >= max) {
 		max *= 2;
 		ret = (xmlChar *) xmlRealloc(ret,
@@ -574,6 +600,8 @@
     uri->authority = NULL;
     if (uri->query != NULL) xmlFree(uri->query);
     uri->query = NULL;
+    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
+    uri->query_raw = NULL;
 }
 
 /**
@@ -594,6 +622,7 @@
     if (uri->opaque != NULL) xmlFree(uri->opaque);
     if (uri->authority != NULL) xmlFree(uri->authority);
     if (uri->query != NULL) xmlFree(uri->query);
+    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
     xmlFree(uri);
 }
 
@@ -1030,7 +1059,11 @@
         xmlFree(segment);
     }
 
-    if (uri->query) {
+    if (uri->query_raw) {
+        ret = xmlStrcat(ret, BAD_CAST "?");
+        ret = xmlStrcat(ret, BAD_CAST uri->query_raw);
+    }
+    else if (uri->query) {
         segment =
             xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
         NULLCHK(segment)
@@ -1133,6 +1166,13 @@
 	    uri->query = STRNDUP(*str, cur - *str);
 	else
 	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
+
+	/* Save the raw bytes of the query as well.
+	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
+	 */
+	if (uri->query_raw != NULL)
+	    xmlFree (uri->query_raw);
+	uri->query_raw = STRNDUP (*str, cur - *str);
     }
     *str = cur;
     return (0);
@@ -1946,8 +1986,12 @@
 	}
 	if (bas->path != NULL)
 	    res->path = xmlMemStrdup(bas->path);
-	if (ref->query != NULL)
+	if (ref->query_raw != NULL)
+	    res->query_raw = xmlMemStrdup (ref->query_raw);
+	else if (ref->query != NULL)
 	    res->query = xmlMemStrdup(ref->query);
+	else if (bas->query_raw != NULL)
+	    res->query_raw = xmlMemStrdup(bas->query_raw);
 	else if (bas->query != NULL)
 	    res->query = xmlMemStrdup(bas->query);
 	if (ref->fragment != NULL)
@@ -1968,7 +2012,9 @@
     if (bas->scheme != NULL)
 	res->scheme = xmlMemStrdup(bas->scheme);
  
-    if (ref->query != NULL)
+    if (ref->query_raw != NULL)
+	res->query_raw = xmlMemStrdup(ref->query_raw);
+    else if (ref->query != NULL)
 	res->query = xmlMemStrdup(ref->query);
     if (ref->fragment != NULL)
 	res->fragment = xmlMemStrdup(ref->fragment);