<someurl>?field1=value1&field2=value2 into [(field1, value1), (field2, value2)].The semantics of query strings don't seem to be very well defined. Where there could be ambiguities, I have looked at what Perl CGI.pm does and implemented that.
I've added a fairly comprehensive test suite for the code. With the patch we pass the old and new tests.
The current uri->query field is always unescaped during parsing. I have changed so it always stored in its raw form. This because otherwise it's impossible to parse query strings such as: file:///tmp/test.html?test=%26&second=%26 which can be generated by web browsers. If anyone was relying on the current semantics, then it seems to me that they cannot parse such query strings correctly.
Rich. -- Emerging Technologies, Red Hat http://et.redhat.com/~rjones/ 64 Baker Street, London, W1U 7DF Mobile: +44 7866 314 421 Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Directors: Michael Cunningham (USA), Charlie Peters (USA) and David Owens (Ireland)
Index: testURIQuery.c
===================================================================
--- testURIQuery.c (revision 0)
+++ testURIQuery.c (revision 0)
@@ -0,0 +1,157 @@
+/*
+ * testURIQuery.c : test the xmlURIQuery* functions.
+ *
+ * See Copyright for the status of this software.
+ *
+ * Author: Richard W.M. Jones <rjones redhat com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "libxml.h"
+
+#include <libxml/xmlmemory.h>
+#include <libxml/uri.h>
+#include <libxml/globals.h>
+
+/* This code reads in the list of URLs, one per line, from stdin.
+ * For each one it writes out several variations which exercise
+ * all the xmlURIQuery* functions.
+ */
+int
+main (void)
+{
+ const char *query;
+ char line[1024], *str = NULL;
+ xmlURIPtr uri = NULL;
+ xmlURIQueryFieldsPtr fields = NULL, field;
+ int errors = 0;
+ int b, len;
+
+ while (fgets (line, sizeof line, stdin)) {
+ /* Strip trailing \n. */
+ len = xmlStrlen (BAD_CAST line);
+ if (len > 0 && line[len-1] == '\n')
+ line[len-1] = '\0';
+
+ /* Ignore lines which begin with '#' and blank lines. */
+ if (line[0] == '\0' || line[0] == '#')
+ continue;
+
+ /* Parse the URI. */
+ uri = xmlParseURI (line);
+ if (!uri) {
+ printf ("testURIQuery: xmlParseURI: %s: failed\n", line);
+ errors++;
+ goto next;
+ }
+
+ printf ("%s\n", line);
+ query = uri->query;
+ printf ("\tquery string = %s\n", query ? query : "NULL");
+
+ /* Parse the query string and write out the list of fields. */
+ if (xmlURIQueryParse (query, NULL, &fields) != 0) {
+ printf ("testURIQuery: xmlURIQueryParse: failed\n");
+ errors++;
+ goto next;
+ }
+ for (field = fields; field; field = field->next) {
+ printf ("\tname = %s\n\tvalue = %s\n",
+ field->name ? field->name : "NULL",
+ field->value ? field->value : "NULL");
+ if (field->ignore)
+ printf ("testURIQuery: field->ignore should be 0\n");
+ }
+
+ /* Recreate query string with all fields. */
+ if (xmlURIQueryCreate (fields, NULL, &str) != 0) {
+ printf ("testURIQuery: xmlURIQueryCreate: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\treassembled query = %s\n", str ? str : "NULL");
+ if (str) xmlFree (str);
+ str = NULL;
+
+ /* Mark some of the fields to be ignored and reassemble. */
+ for (field = fields; field; field = field->next) {
+ if (xmlStrncasecmp (BAD_CAST field->name, BAD_CAST "del", 3) == 0)
+ field->ignore = 1;
+ }
+ if (xmlURIQueryCreate (fields, NULL, &str) != 0) {
+ printf ("testURIQuery: xmlURIQueryCreate: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\treassembled query - del* = %s\n", str ? str : "NULL");
+ if (str) xmlFree (str);
+ str = NULL;
+
+ xmlFreeURIQueryFields (fields);
+ fields = NULL;
+
+ /* Try the high-level Exists function on the original URI. */
+ if (xmlURIQueryExists (query, "check", &b) != 0) {
+ printf ("testURIQuery: xmlURIQueryExists: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\tcheck field exists = %s\n", b ? "true" : "false");
+
+ /* Try the high-level IsTrue function on the original URI. */
+ if (xmlURIQueryIsTrue (query, "check", &b) != 0) {
+ printf ("testURIQuery: xmlURIQueryIsTrue: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\tcheck field is true = %s\n", b ? "true" : "false");
+
+ /* Try the high-level GetSingle function on the original URI. */
+ if (xmlURIQueryGetSingle (query, "check", &str) != 0) {
+ printf ("testURIQuery: xmlURIQueryGetSingle: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\tcheck field = %s\n", str ? str : "not present");
+ if (str) xmlFree (str);
+ str = NULL;
+
+ /* Try the high-level GetMultiple function on the original URI. */
+ if (xmlURIQueryGetMultiple (query, "check", &fields) != 0) {
+ printf ("testURIQuery: xmlURIQueryGetMultiple: failed\n");
+ errors++;
+ goto next;
+ }
+ for (field = fields; field; field = field->next) {
+ printf ("\t\tcheck field name = %s\n\t\tvalue = %s\n",
+ field->name ? field->name : "NULL",
+ field->value ? field->value : "NULL");
+ if (field->ignore)
+ printf ("testURIQuery: field->ignore should be 0\n");
+ }
+ xmlFreeURIQueryFields (fields);
+ fields = NULL;
+
+ /* Try the high-level Remove function on the original URI. */
+ if (xmlURIQueryRemove (query, "remove", &str) != 0) {
+ printf ("testURIQuery: xmlURIQueryRemove: failed\n");
+ errors++;
+ goto next;
+ }
+ printf ("\treassembled query - remove = %s\n", str ? str : "NULL");
+ if (str) xmlFree (str);
+ str = NULL;
+
+ next:
+ if (str) xmlFree (str);
+ if (fields) xmlFreeURIQueryFields (fields);
+ if (uri) xmlFreeURI (uri);
+
+ fflush (stdout);
+ }
+
+ xmlMemoryDump();
+ return errors ? 1 : 0;
+}
Index: uri.c
===================================================================
--- uri.c (revision 3604)
+++ uri.c (working copy)
@@ -17,6 +17,7 @@
#include <libxml/uri.h>
#include <libxml/globals.h>
#include <libxml/xmlerror.h>
+#include <libxml/tree.h>
/************************************************************************
* *
@@ -1031,12 +1032,11 @@
}
if (uri->query) {
- segment =
- xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
- NULLCHK(segment)
+ /* Assume the query has already been escaped. This is the only
+ * sensible way to deal with queries like: first=%26&second=%26
+ */
ret = xmlStrcat(ret, BAD_CAST "?");
- ret = xmlStrcat(ret, segment);
- xmlFree(segment);
+ ret = xmlStrcat(ret, BAD_CAST uri->query);
}
if (uri->opaque) {
@@ -1129,10 +1129,10 @@
if (uri != NULL) {
if (uri->query != NULL)
xmlFree(uri->query);
- if (uri->cleanup & 2)
- uri->query = STRNDUP(*str, cur - *str);
- else
- uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
+ /* Do not attempt to unescape the query. See xmlURIQuery*
+ * functions instead.
+ */
+ uri->query = STRNDUP(*str, cur - *str);
}
*str = cur;
return (0);
@@ -2510,5 +2510,507 @@
xmlFree(cal);
return(ret);
}
+
+/************************************************************************
+ * *
+ * Low-level parse and create functions for query strings *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlURIQueryCreate:
+ * @fields: Linked list of fields
+ * @separator: Separator, if NULL uses the default ("&")
+ * @query_out: The returned query string.
+ *
+ * This function concatenates the linked list of (field name, field value)
+ * pairs into a query string.
+ *
+ * If any field has the 'ignore' field set, it is ignored and not
+ * concatenated into the query string.
+ *
+ * If a field with the same name appears more than once, then it will
+ * appear multiple times in the query string. Web browsers generate
+ * such query strings, and query string parsers handle them in
+ * various ways. (See xmlURIQueryGetSingle and xmlURIQueryGetMultiple).
+ *
+ * The field name and value are URI-escaped properly before being
+ * added to the query.
+ *
+ * The returned query string should be freed by the caller. If
+ * fields is NULL then query_out will be set to NULL.
+ *
+ * Returns 0 if successful or an error code.
+ */
+int
+xmlURIQueryCreate (xmlURIQueryFieldsPtr fields,
+ const char *separator,
+ char **query_out)
+{
+ /* List of characters which are safe inside names or values,
+ * apart from '@', IS_MARK and IS_ALPHANUM. Best to escape
+ * as much as possible. Certainly '=', '&' and '#' must NEVER
+ * be added to this list.
+ */
+ static const xmlChar *special_chars = BAD_CAST "";
+
+ int append_sep = 0, sep_len;
+ xmlBufferPtr buf;
+ xmlChar *str;
+ int rv;
+
+ if (query_out) *query_out = NULL;
+ if (!fields) return 0;
+
+ if (separator == NULL) {
+ separator = "&";
+ sep_len = 1;
+ } else
+ sep_len = xmlStrlen (BAD_CAST separator);
+
+ buf = xmlBufferCreate ();
+ if (!buf) return -1;
+
+ rv = 0;
+ while (fields) {
+ if (!fields->ignore) {
+ if (append_sep) {
+ rv = xmlBufferAdd (buf, BAD_CAST separator, sep_len);
+ if (rv != 0) goto error;
+ }
+ append_sep = 1;
+
+ str = xmlURIEscapeStr (BAD_CAST fields->name, special_chars);
+ if (!str) { rv = XML_ERR_NO_MEMORY; goto error; }
+ rv = xmlBufferAdd (buf, str, xmlStrlen (str));
+ xmlFree (str);
+ if (rv != 0) goto error;
+
+ rv = xmlBufferAdd (buf, BAD_CAST "=", 1);
+ if (rv != 0) goto error;
+ str = xmlURIEscapeStr (BAD_CAST fields->value, special_chars);
+ if (!str) { rv = XML_ERR_NO_MEMORY; goto error; }
+ rv = xmlBufferAdd (buf, str, xmlStrlen (str));
+ xmlFree (str);
+ if (rv != 0) goto error;
+ }
+
+ fields = fields->next;
+ }
+
+ if (query_out && buf->content) {
+ *query_out = (char *) xmlStrdup (buf->content);
+ if (!*query_out) {
+ rv = XML_ERR_NO_MEMORY;
+ goto error;
+ }
+ }
+
+ error:
+ if (buf)
+ xmlBufferFree (buf);
+ return rv;
+}
+
+/**
+ * xmlURIQueryParse:
+ * @query: Query string to parse.
+ * @separator: Separator, if NULL uses the default ("&")
+ * @fields_out: Returned linked list of fields, or NULL if query is empty.
+ *
+ * This function parses the query string and returns a list of
+ * (field name, field value) pairs of fields found in the query
+ * string.
+ *
+ * Field names are not unique, and for a given query string this
+ * function may return the same name several times
+ * (eg. "name=val1&name=val2"). Web browsers generate such query
+ * strings.
+ *
+ * The returned list should be freed by the caller (see
+ * xmlFreeURIQueryFields). If the query string passed in is
+ * NULL or an empty string, then fields_out will be set to NULL.
+ *
+ * The field name and value are URI-unescaped properly when parsed
+ * out of the query. If the value is missing, it is set to "".
+ * If the name is missing then the field is ignored. This behaviour
+ * is consistent with Perl's CGI.pm.
+ *
+ * The ignore flags are set to 0 (see xmlURIQueryCreate).
+ *
+ * Returns 0 if successful or an error code.
+ */
+int
+xmlURIQueryParse (const char *query_,
+ const char *separator,
+ xmlURIQueryFieldsPtr *fields_out)
+{
+ xmlURIQueryFieldsPtr fields, field, *prev;
+ int sep_len;
+ const xmlChar *query = BAD_CAST query_, *end, *eq;
+ char *name, *value;
+
+ if (fields_out) *fields_out = NULL;
+ if (!query || query[0] == '\0') return 0;
+
+ if (separator == NULL) {
+ separator = "&";
+ sep_len = 1;
+ } else
+ sep_len = xmlStrlen (BAD_CAST separator);
+
+ fields = NULL;
+ prev = &fields;
+
+ while (*query) {
+ /* Find the next separator, or end of the string. */
+ end = xmlStrstr (query, BAD_CAST separator);
+ if (!end) end = query + xmlStrlen (query);
+
+ /* Find the first '=' character between here and end. */
+ eq = xmlStrchr (query, '=');
+ if (eq && eq >= end) eq = NULL;
+
+ /* Empty section (eg. "?&"). */
+ if (end == query)
+ goto next;
+ /* If there is no '=' character, then we have just "name"
+ * and consistent with CGI.pm we assume value is "".
+ */
+ else if (!eq) {
+ name = xmlURIUnescapeString ((const char *) query,
+ end - query, NULL);
+ value = (char *) xmlStrdup (BAD_CAST "");
+ if (!name || !value) goto out_of_memory;
+ }
+ /* Or if we have "name=" here (works around annoying
+ * problem when calling xmlURIUnescapeString with len = 0).
+ */
+ else if (eq+1 == end) {
+ name = xmlURIUnescapeString ((const char *) query,
+ eq - query, NULL);
+ value = (char *) xmlStrdup (BAD_CAST "");
+ if (!name || !value) goto out_of_memory;
+ }
+ /* If the '=' character is at the beginning then we have
+ * "=value" and consistent with CGI.pm we _ignore_ this.
+ */
+ else if (query == eq)
+ goto next;
+ /* Otherwise it's "name=value". */
+ else {
+ name = xmlURIUnescapeString ((const char *) query,
+ eq - query, NULL);
+ value = xmlURIUnescapeString ((const char *) eq+1,
+ end - (eq+1), NULL);
+ if (!name || !value) goto out_of_memory;
+ }
+
+ /* Allocate this field and append to the list. */
+ field = xmlMalloc (sizeof *field);
+ if (!field) goto out_of_memory;
+ field->next = NULL;
+ field->name = name;
+ field->value = value;
+ field->ignore = 0;
+ *prev = field;
+ prev = &field->next;
+
+ next:
+ query = end;
+ if (*query) query += sep_len; /* skip separator */
+ }
+
+ if (fields_out) *fields_out = fields;
+ return 0;
+
+ out_of_memory:
+ xmlFreeURIQueryFields (fields);
+ return XML_ERR_NO_MEMORY;
+}
+
+/**
+ * xmlFreeURIQueryFields:
+ * @fields: Linked list of fields
+ *
+ * This function frees the linked list of fields, and all strings
+ * contained within.
+ *
+ * If fields is NULL then this function does nothing.
+ */
+void
+xmlFreeURIQueryFields (xmlURIQueryFieldsPtr fields)
+{
+ xmlURIQueryFieldsPtr t;
+
+ while (fields) {
+ if (fields->name) xmlFree (fields->name);
+ if (fields->value) xmlFree (fields->value);
+ t = fields;
+ fields = fields->next;
+ xmlFree (t);
+ }
+}
+
+/************************************************************************
+ * *
+ * High-level convenience operations for query strings *
+ * *
+ ************************************************************************/
+
+/* NB. These functions generally parse the whole string each time
+ * they are called, so they are useful for occasional use, or code
+ * where you don't particularly care about raw speed. Otherwise you
+ * should use the low-level parse function above and work on the
+ * xmlURIQueryFields structure directly.
+ */
+
+/**
+ * xmlURIQueryExists:
+ * @query: The query string (from uri->query)
+ * @name: The field name (unescaped)
+ * @bool_out: Boolean returned
+ *
+ * Sets bool_out to true if and only if the field name appears in the
+ * query string with any value (including an empty value).
+ *
+ * See also xmlURIQueryIsTrue.
+ *
+ * Notes:
+ * (1) this function parses the query string each time it is called.
+ * (2) field name comparisons are case-insensitive.
+ *
+ * Returns 0 if successful, or an error code.
+ */
+int
+xmlURIQueryExists (const char *query,
+ const char *name,
+ int *bool_out)
+{
+ xmlURIQueryFieldsPtr fields, field;
+ int rv;
+
+ if (bool_out) *bool_out = 0;
+
+ rv = xmlURIQueryParse (query, NULL, &fields);
+ if (rv != 0) return rv;
+
+ for (field = fields; field; field = field->next) {
+ if (xmlStrcasecmp (BAD_CAST field->name, BAD_CAST name) == 0) {
+ if (bool_out) *bool_out = 1;
+ break;
+ }
+ }
+
+ xmlFreeURIQueryFields (fields);
+
+ return 0;
+}
+
+/**
+ * xmlURIQueryIsTrue:
+ * @query: The query string (from uri->query)
+ * @name: The field name (unescaped)
+ * @bool_out: Boolean returned
+ *
+ * Sets bool_out to true if and only if the field name appears in the
+ * query string with a "non-false" value. A false value means
+ * a value which is empty or "0". Thus this function will return
+ * false for "..&name=&.." or "..&name=0&..", but will return true
+ * for "..&name=1&.." or "..&name=foo&..".
+ *
+ * If the name appears multiple times, then we check if any has a
+ * non-false value.
+ *
+ * (This is the same convention for truthfulness as used in Perl's
+ * CGI.pm).
+ *
+ * See also xmlURIQueryExists.
+ *
+ * Notes:
+ * (1) this function parses the query string each time it is called.
+ * (2) field name comparisons are case-insensitive.
+ *
+ * Returns 0 if successful, or an error code.
+ */
+static inline int
+is_false (const char *value)
+{
+ return value[0] == '\0' || (value[0] == '0' && value[1] == '\0');
+}
+
+int
+xmlURIQueryIsTrue (const char *query,
+ const char *name,
+ int *bool_out)
+{
+ xmlURIQueryFieldsPtr fields, field;
+ int rv;
+
+ if (bool_out) *bool_out = 0;
+
+ rv = xmlURIQueryParse (query, NULL, &fields);
+ if (rv != 0) return rv;
+
+ for (field = fields; field; field = field->next) {
+ if (xmlStrcasecmp (BAD_CAST field->name, BAD_CAST name) == 0 &&
+ !is_false (field->value)) {
+ if (bool_out) *bool_out = 1;
+ break;
+ }
+ }
+
+ xmlFreeURIQueryFields (fields);
+
+ return 0;
+}
+
+/**
+ * xmlURIQueryGetSingle:
+ * @query: The query string (from uri->query)
+ * @name: The field name (unescaped)
+ * @value_out: Value returned (if found) or set to NULL.
+ *
+ * Gets the value of the named field from the query string, unescaped.
+ * The returned value must be freed by the caller.
+ *
+ * If the named field cannot be found, sets value_out to NULL.
+ *
+ * If the named field appears more than once, the first value is
+ * the one returned. (See also xmlURIQueryGetMultiple).
+ *
+ * Notes:
+ * (1) this function parses the query string each time it is called.
+ * (2) field name comparisons are case-insensitive.
+ *
+ * Returns 0 if successful, or an error code.
+ */
+int
+xmlURIQueryGetSingle (const char *query,
+ const char *name,
+ char **value_out)
+{
+ xmlURIQueryFieldsPtr fields, field;
+ int rv;
+
+ if (value_out) *value_out = NULL;
+
+ rv = xmlURIQueryParse (query, NULL, &fields);
+ if (rv != 0) return rv;
+
+ rv = 0;
+ for (field = fields; field; field = field->next) {
+ if (xmlStrcasecmp (BAD_CAST field->name, BAD_CAST name) == 0) {
+ if (value_out) {
+ *value_out = (char *) xmlStrdup (BAD_CAST field->value);
+ if (!*value_out) rv = XML_ERR_NO_MEMORY;
+ }
+ break;
+ }
+ }
+
+ xmlFreeURIQueryFields (fields);
+
+ return rv;
+}
+
+/**
+ * xmlURIQueryGetMultiple:
+ * @query: The query string (from uri->query)
+ * @name: The field name (unescaped)
+ * @fields_out: The fields with the given name (or NULL if no fields).
+ *
+ * Gets the value(s) of the named field from the query string, unescaped.
+ * The returned value must be freed by the caller by calling
+ * xmlFreeURIQueryFields.
+ *
+ * If the named field cannot be found, sets fields_out to NULL.
+ *
+ * Notes:
+ * (1) this function parses the query string each time it is called.
+ * (2) field name comparisons are case-insensitive.
+ *
+ * Returns 0 if successful, or an error code.
+ */
+int
+xmlURIQueryGetMultiple (const char *query,
+ const char *name,
+ xmlURIQueryFieldsPtr *fields_out)
+{
+ xmlURIQueryFieldsPtr fields, field, *prev;
+ int rv;
+
+ if (fields_out) *fields_out = NULL;
+
+ rv = xmlURIQueryParse (query, NULL, &fields);
+ if (rv != 0) return rv;
+
+ prev = &fields;
+ field = fields;
+ while (field) {
+ if (xmlStrcasecmp (BAD_CAST field->name, BAD_CAST name) == 0) {
+ /* Keep this field in the linked list. */
+ prev = &field->next;
+ field = field->next;
+ } else {
+ /* We're going to remove and free the current field (field).
+ * '*prev' is the pointer to the current field from the previous,
+ * and field->next points to the next one.
+ */
+ *prev = field->next;
+ field->next = NULL;
+ xmlFreeURIQueryFields (field);
+ field = *prev;
+ }
+ }
+
+ if (fields_out) *fields_out = fields;
+
+ return 0;
+}
+
+/**
+ * xmlURIQueryRemove:
+ * @query: The query string (from uri->query)
+ * @name: The field name (unescaped)
+ * @query_out: The returned query string.
+ *
+ * This function removes all fields named name from the query
+ * string, constructing a new query string and returning it in
+ * query_out.
+ *
+ * query_out must be freed by the caller.
+ *
+ * Notes:
+ * (1) this function parses the query string each time it is called.
+ * (2) field name comparisons are case-insensitive.
+ *
+ * Returns 0 if successful, or an error code.
+ */
+int
+xmlURIQueryRemove (const char *query,
+ const char *name,
+ char **query_out)
+{
+ xmlURIQueryFieldsPtr fields, field;
+ int rv;
+
+ if (query_out) *query_out = NULL;
+
+ rv = xmlURIQueryParse (query, NULL, &fields);
+ if (rv != 0) return rv;
+
+ for (field = fields; field; field = field->next) {
+ if (xmlStrcasecmp (BAD_CAST field->name, BAD_CAST name) == 0)
+ field->ignore = 1;
+ }
+
+ rv = xmlURIQueryCreate (fields, NULL, query_out);
+
+ xmlFreeURIQueryFields (fields);
+ return rv;
+}
+
+
#define bottom_uri
#include "elfgcchack.h"
Index: include/libxml/uri.h
===================================================================
--- include/libxml/uri.h (revision 3604)
+++ include/libxml/uri.h (working copy)
@@ -83,6 +83,60 @@
XMLPUBFUN xmlChar* XMLCALL
xmlPathToURI (const xmlChar *path);
+/**
+ * xmlURIQueryFields:
+ *
+ * A query string parsed into a linked list of (field name, field value) pairs.
+ *
+ * The name and value strings are stored here without %-escaping. In
+ * the final query string they may be escaped if necessary.
+ *
+ * The ignore field is useful when parsing a query string, removing
+ * some fields, and leaving the rest. xmlURIQueryParse always sets
+ * this to zero. xmlURIQueryCreate checks this, and if it is non-zero
+ * it will ignore that field when constructing the query string.
+ */
+typedef struct _xmlURIQueryFields xmlURIQueryFields;
+typedef xmlURIQueryFields *xmlURIQueryFieldsPtr;
+struct _xmlURIQueryFields {
+ xmlURIQueryFieldsPtr next; /* Linked list chain. */
+ char *name; /* Field name (unescaped). */
+ char *value; /* Field value (unescaped). */
+ int ignore; /* Ignore field in xmlURIQueryCreate. */
+};
+
+XMLPUBFUN int XMLCALL
+ xmlURIQueryParse (const char *query,
+ const char *separator,
+ xmlURIQueryFieldsPtr *fields_out);
+XMLPUBFUN int XMLCALL
+ xmlURIQueryCreate (const xmlURIQueryFieldsPtr fields,
+ const char *separator,
+ char **query_out);
+XMLPUBFUN void XMLCALL
+ xmlFreeURIQueryFields (xmlURIQueryFieldsPtr fields);
+
+XMLPUBFUN int XMLCALL
+ xmlURIQueryExists (const char *query,
+ const char *name,
+ int *bool_out);
+XMLPUBFUN int XMLCALL
+ xmlURIQueryIsTrue (const char *query,
+ const char *name,
+ int *bool_out);
+XMLPUBFUN int XMLCALL
+ xmlURIQueryGetSingle (const char *query,
+ const char *name,
+ char **value_out);
+XMLPUBFUN int XMLCALL
+ xmlURIQueryGetMultiple (const char *query,
+ const char *name,
+ xmlURIQueryFieldsPtr *fields_out);
+XMLPUBFUN int XMLCALL
+ xmlURIQueryRemove (const char *query,
+ const char *name,
+ char **query_out);
+
#ifdef __cplusplus
}
#endif
Index: result/URIQuery/test1.data
===================================================================
--- result/URIQuery/test1.data (revision 0)
+++ result/URIQuery/test1.data (revision 0)
@@ -0,0 +1,1524 @@
+/
+ query string = NULL
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?
+ query string =
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?field1=value1
+ query string = field1=value1
+ name = field1
+ value = value1
+ reassembled query = field1=value1
+ reassembled query - del* = field1=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1
+/?field1=value1&field2=value2
+ query string = field1=value1&field2=value2
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?field1=value1&field2=value2&field3=value3
+ query string = field1=value1&field2=value2&field3=value3
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ name = field3
+ value = value3
+ reassembled query = field1=value1&field2=value2&field3=value3
+ reassembled query - del* = field1=value1&field2=value2&field3=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2&field3=value3
+/?field1=value1&field2=value2&field3=value3&field4=value4
+ query string = field1=value1&field2=value2&field3=value3&field4=value4
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ name = field3
+ value = value3
+ name = field4
+ value = value4
+ reassembled query = field1=value1&field2=value2&field3=value3&field4=value4
+ reassembled query - del* = field1=value1&field2=value2&field3=value3&field4=value4
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2&field3=value3&field4=value4
+/?field1=
+ query string = field1=
+ name = field1
+ value =
+ reassembled query = field1=
+ reassembled query - del* = field1=
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=
+/?=value1
+ query string = =value1
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?field1=&field2=value2
+ query string = field1=&field2=value2
+ name = field1
+ value =
+ name = field2
+ value = value2
+ reassembled query = field1=&field2=value2
+ reassembled query - del* = field1=&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=&field2=value2
+/?=value1&field2=value2
+ query string = =value1&field2=value2
+ name = field2
+ value = value2
+ reassembled query = field2=value2
+ reassembled query - del* = field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field2=value2
+/?field1=value1&field2=
+ query string = field1=value1&field2=
+ name = field1
+ value = value1
+ name = field2
+ value =
+ reassembled query = field1=value1&field2=
+ reassembled query - del* = field1=value1&field2=
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=
+/?field1=value1&=value2
+ query string = field1=value1&=value2
+ name = field1
+ value = value1
+ reassembled query = field1=value1
+ reassembled query - del* = field1=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1
+/?field1=value1&field2=&field3=value3
+ query string = field1=value1&field2=&field3=value3
+ name = field1
+ value = value1
+ name = field2
+ value =
+ name = field3
+ value = value3
+ reassembled query = field1=value1&field2=&field3=value3
+ reassembled query - del* = field1=value1&field2=&field3=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=&field3=value3
+/?field1=value1&=value2&field3=value3
+ query string = field1=value1&=value2&field3=value3
+ name = field1
+ value = value1
+ name = field3
+ value = value3
+ reassembled query = field1=value1&field3=value3
+ reassembled query - del* = field1=value1&field3=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field3=value3
+/?&
+ query string = &
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?&&
+ query string = &&
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?&&&
+ query string = &&&
+ reassembled query = NULL
+ reassembled query - del* = NULL
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = NULL
+/?field1=value1&&field2=value2
+ query string = field1=value1&&field2=value2
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?&field1=value1&field2=value2
+ query string = &field1=value1&field2=value2
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?&&field1=value1&field2=value2
+ query string = &&field1=value1&field2=value2
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?field1=value1&field2=value2&
+ query string = field1=value1&field2=value2&
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?field1=value1&field2=value2&&
+ query string = field1=value1&field2=value2&&
+ name = field1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = field1=value1&field2=value2
+ reassembled query - del* = field1=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field2=value2
+/?field1=value1&delme=value2&field3=value3
+ query string = field1=value1&delme=value2&field3=value3
+ name = field1
+ value = value1
+ name = delme
+ value = value2
+ name = field3
+ value = value3
+ reassembled query = field1=value1&delme=value2&field3=value3
+ reassembled query - del* = field1=value1&field3=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&delme=value2&field3=value3
+/?del=delete
+ query string = del=delete
+ name = del
+ value = delete
+ reassembled query = del=delete
+ reassembled query - del* =
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = del=delete
+/?field1=del
+ query string = field1=del
+ name = field1
+ value = del
+ reassembled query = field1=del
+ reassembled query - del* = field1=del
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=del
+/?del1=value1&del2=value2&del3=value3
+ query string = del1=value1&del2=value2&del3=value3
+ name = del1
+ value = value1
+ name = del2
+ value = value2
+ name = del3
+ value = value3
+ reassembled query = del1=value1&del2=value2&del3=value3
+ reassembled query - del* =
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = del1=value1&del2=value2&del3=value3
+/?field1=value1&del2=value2
+ query string = field1=value1&del2=value2
+ name = field1
+ value = value1
+ name = del2
+ value = value2
+ reassembled query = field1=value1&del2=value2
+ reassembled query - del* = field1=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&del2=value2
+/?del1=value1&field2=value2
+ query string = del1=value1&field2=value2
+ name = del1
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = del1=value1&field2=value2
+ reassembled query - del* = field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = del1=value1&field2=value2
+/?field1=value1&del2=value2&del3=value3&del4=value4
+ query string = field1=value1&del2=value2&del3=value3&del4=value4
+ name = field1
+ value = value1
+ name = del2
+ value = value2
+ name = del3
+ value = value3
+ name = del4
+ value = value4
+ reassembled query = field1=value1&del2=value2&del3=value3&del4=value4
+ reassembled query - del* = field1=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&del2=value2&del3=value3&del4=value4
+/?del1=value1&del2=value2&del3=value3&field4=value4
+ query string = del1=value1&del2=value2&del3=value3&field4=value4
+ name = del1
+ value = value1
+ name = del2
+ value = value2
+ name = del3
+ value = value3
+ name = field4
+ value = value4
+ reassembled query = del1=value1&del2=value2&del3=value3&field4=value4
+ reassembled query - del* = field4=value4
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = del1=value1&del2=value2&del3=value3&field4=value4
+/?field1=value1&remove=value2&field3=value3
+ query string = field1=value1&remove=value2&field3=value3
+ name = field1
+ value = value1
+ name = remove
+ value = value2
+ name = field3
+ value = value3
+ reassembled query = field1=value1&remove=value2&field3=value3
+ reassembled query - del* = field1=value1&remove=value2&field3=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field3=value3
+/?field1=remove
+ query string = field1=remove
+ name = field1
+ value = remove
+ reassembled query = field1=remove
+ reassembled query - del* = field1=remove
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=remove
+/?remove=value1
+ query string = remove=value1
+ name = remove
+ value = value1
+ reassembled query = remove=value1
+ reassembled query - del* = remove=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove =
+/?remove=value1&remove=value2
+ query string = remove=value1&remove=value2
+ name = remove
+ value = value1
+ name = remove
+ value = value2
+ reassembled query = remove=value1&remove=value2
+ reassembled query - del* = remove=value1&remove=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove =
+/?remove=value1&remove=value2&remove=value3
+ query string = remove=value1&remove=value2&remove=value3
+ name = remove
+ value = value1
+ name = remove
+ value = value2
+ name = remove
+ value = value3
+ reassembled query = remove=value1&remove=value2&remove=value3
+ reassembled query - del* = remove=value1&remove=value2&remove=value3
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove =
+/?remove=value1&field2=value2
+ query string = remove=value1&field2=value2
+ name = remove
+ value = value1
+ name = field2
+ value = value2
+ reassembled query = remove=value1&field2=value2
+ reassembled query - del* = remove=value1&field2=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field2=value2
+/?field1=value1&remove=value2&remove=value3&remove=value4
+ query string = field1=value1&remove=value2&remove=value3&remove=value4
+ name = field1
+ value = value1
+ name = remove
+ value = value2
+ name = remove
+ value = value3
+ name = remove
+ value = value4
+ reassembled query = field1=value1&remove=value2&remove=value3&remove=value4
+ reassembled query - del* = field1=value1&remove=value2&remove=value3&remove=value4
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1
+/?remove=value1&remove=value2&remove=value3&field4=value4
+ query string = remove=value1&remove=value2&remove=value3&field4=value4
+ name = remove
+ value = value1
+ name = remove
+ value = value2
+ name = remove
+ value = value3
+ name = field4
+ value = value4
+ reassembled query = remove=value1&remove=value2&remove=value3&field4=value4
+ reassembled query - del* = remove=value1&remove=value2&remove=value3&field4=value4
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field4=value4
+/?field1=value1&remove=value2&remove=value3&field4=value4
+ query string = field1=value1&remove=value2&remove=value3&field4=value4
+ name = field1
+ value = value1
+ name = remove
+ value = value2
+ name = remove
+ value = value3
+ name = field4
+ value = value4
+ reassembled query = field1=value1&remove=value2&remove=value3&field4=value4
+ reassembled query - del* = field1=value1&remove=value2&remove=value3&field4=value4
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=value1&field4=value4
+/?check=0
+ query string = check=0
+ name = check
+ value = 0
+ reassembled query = check=0
+ reassembled query - del* = check=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = check
+ value = 0
+ reassembled query - remove = check=0
+/?check=0&check=0
+ query string = check=0&check=0
+ name = check
+ value = 0
+ name = check
+ value = 0
+ reassembled query = check=0&check=0
+ reassembled query - del* = check=0&check=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = check
+ value = 0
+ check field name = check
+ value = 0
+ reassembled query - remove = check=0&check=0
+/?check=0&check=0&check=1
+ query string = check=0&check=0&check=1
+ name = check
+ value = 0
+ name = check
+ value = 0
+ name = check
+ value = 1
+ reassembled query = check=0&check=0&check=1
+ reassembled query - del* = check=0&check=0&check=1
+ check field exists = true
+ check field is true = true
+ check field = 0
+ check field name = check
+ value = 0
+ check field name = check
+ value = 0
+ check field name = check
+ value = 1
+ reassembled query - remove = check=0&check=0&check=1
+/?check=
+ query string = check=
+ name = check
+ value =
+ reassembled query = check=
+ reassembled query - del* = check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = check=
+/?check=&check=
+ query string = check=&check=
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = check=&check=
+ reassembled query - del* = check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=
+/?check=&check=&check=foo
+ query string = check=&check=&check=foo
+ name = check
+ value =
+ name = check
+ value =
+ name = check
+ value = foo
+ reassembled query = check=&check=&check=foo
+ reassembled query - del* = check=&check=&check=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ check field name = check
+ value = foo
+ reassembled query - remove = check=&check=&check=foo
+/?check
+ query string = check
+ name = check
+ value =
+ reassembled query = check=
+ reassembled query - del* = check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = check=
+/?check&check
+ query string = check&check
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = check=&check=
+ reassembled query - del* = check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=
+/?check&check&check=BAR
+ query string = check&check&check=BAR
+ name = check
+ value =
+ name = check
+ value =
+ name = check
+ value = BAR
+ reassembled query = check=&check=&check=BAR
+ reassembled query - del* = check=&check=&check=BAR
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ check field name = check
+ value = BAR
+ reassembled query - remove = check=&check=&check=BAR
+/?ChecK=0
+ query string = ChecK=0
+ name = ChecK
+ value = 0
+ reassembled query = ChecK=0
+ reassembled query - del* = ChecK=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = ChecK
+ value = 0
+ reassembled query - remove = ChecK=0
+/?ChecK=0&ChecK=0
+ query string = ChecK=0&ChecK=0
+ name = ChecK
+ value = 0
+ name = ChecK
+ value = 0
+ reassembled query = ChecK=0&ChecK=0
+ reassembled query - del* = ChecK=0&ChecK=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = ChecK
+ value = 0
+ check field name = ChecK
+ value = 0
+ reassembled query - remove = ChecK=0&ChecK=0
+/?ChecK=0&ChecK=0&ChecK=1
+ query string = ChecK=0&ChecK=0&ChecK=1
+ name = ChecK
+ value = 0
+ name = ChecK
+ value = 0
+ name = ChecK
+ value = 1
+ reassembled query = ChecK=0&ChecK=0&ChecK=1
+ reassembled query - del* = ChecK=0&ChecK=0&ChecK=1
+ check field exists = true
+ check field is true = true
+ check field = 0
+ check field name = ChecK
+ value = 0
+ check field name = ChecK
+ value = 0
+ check field name = ChecK
+ value = 1
+ reassembled query - remove = ChecK=0&ChecK=0&ChecK=1
+/?ChecK=
+ query string = ChecK=
+ name = ChecK
+ value =
+ reassembled query = ChecK=
+ reassembled query - del* = ChecK=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = ChecK
+ value =
+ reassembled query - remove = ChecK=
+/?ChecK=&ChecK=
+ query string = ChecK=&ChecK=
+ name = ChecK
+ value =
+ name = ChecK
+ value =
+ reassembled query = ChecK=&ChecK=
+ reassembled query - del* = ChecK=&ChecK=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value =
+ reassembled query - remove = ChecK=&ChecK=
+/?ChecK=&ChecK=&ChecK=foo
+ query string = ChecK=&ChecK=&ChecK=foo
+ name = ChecK
+ value =
+ name = ChecK
+ value =
+ name = ChecK
+ value = foo
+ reassembled query = ChecK=&ChecK=&ChecK=foo
+ reassembled query - del* = ChecK=&ChecK=&ChecK=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value = foo
+ reassembled query - remove = ChecK=&ChecK=&ChecK=foo
+/?ChecK
+ query string = ChecK
+ name = ChecK
+ value =
+ reassembled query = ChecK=
+ reassembled query - del* = ChecK=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = ChecK
+ value =
+ reassembled query - remove = ChecK=
+/?ChecK&ChecK
+ query string = ChecK&ChecK
+ name = ChecK
+ value =
+ name = ChecK
+ value =
+ reassembled query = ChecK=&ChecK=
+ reassembled query - del* = ChecK=&ChecK=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value =
+ reassembled query - remove = ChecK=&ChecK=
+/?ChecK&ChecK&ChecK=BAR
+ query string = ChecK&ChecK&ChecK=BAR
+ name = ChecK
+ value =
+ name = ChecK
+ value =
+ name = ChecK
+ value = BAR
+ reassembled query = ChecK=&ChecK=&ChecK=BAR
+ reassembled query - del* = ChecK=&ChecK=&ChecK=BAR
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value =
+ check field name = ChecK
+ value = BAR
+ reassembled query - remove = ChecK=&ChecK=&ChecK=BAR
+/?check
+ query string = check
+ name = check
+ value =
+ reassembled query = check=
+ reassembled query - del* = check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = check=
+/?check=0
+ query string = check=0
+ name = check
+ value = 0
+ reassembled query = check=0
+ reassembled query - del* = check=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = check
+ value = 0
+ reassembled query - remove = check=0
+/?check=1
+ query string = check=1
+ name = check
+ value = 1
+ reassembled query = check=1
+ reassembled query - del* = check=1
+ check field exists = true
+ check field is true = true
+ check field = 1
+ check field name = check
+ value = 1
+ reassembled query - remove = check=1
+/?check=foo
+ query string = check=foo
+ name = check
+ value = foo
+ reassembled query = check=foo
+ reassembled query - del* = check=foo
+ check field exists = true
+ check field is true = true
+ check field = foo
+ check field name = check
+ value = foo
+ reassembled query - remove = check=foo
+/?check&check=foo
+ query string = check&check=foo
+ name = check
+ value =
+ name = check
+ value = foo
+ reassembled query = check=&check=foo
+ reassembled query - del* = check=&check=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value = foo
+ reassembled query - remove = check=&check=foo
+/?check=&check=foo
+ query string = check=&check=foo
+ name = check
+ value =
+ name = check
+ value = foo
+ reassembled query = check=&check=foo
+ reassembled query - del* = check=&check=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value = foo
+ reassembled query - remove = check=&check=foo
+/?check=0&check=foo
+ query string = check=0&check=foo
+ name = check
+ value = 0
+ name = check
+ value = foo
+ reassembled query = check=0&check=foo
+ reassembled query - del* = check=0&check=foo
+ check field exists = true
+ check field is true = true
+ check field = 0
+ check field name = check
+ value = 0
+ check field name = check
+ value = foo
+ reassembled query - remove = check=0&check=foo
+/?check=1&check=foo
+ query string = check=1&check=foo
+ name = check
+ value = 1
+ name = check
+ value = foo
+ reassembled query = check=1&check=foo
+ reassembled query - del* = check=1&check=foo
+ check field exists = true
+ check field is true = true
+ check field = 1
+ check field name = check
+ value = 1
+ check field name = check
+ value = foo
+ reassembled query - remove = check=1&check=foo
+/?CHEck
+ query string = CHEck
+ name = CHEck
+ value =
+ reassembled query = CHEck=
+ reassembled query - del* = CHEck=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = CHEck
+ value =
+ reassembled query - remove = CHEck=
+/?CHEck=0
+ query string = CHEck=0
+ name = CHEck
+ value = 0
+ reassembled query = CHEck=0
+ reassembled query - del* = CHEck=0
+ check field exists = true
+ check field is true = false
+ check field = 0
+ check field name = CHEck
+ value = 0
+ reassembled query - remove = CHEck=0
+/?CHEck=1
+ query string = CHEck=1
+ name = CHEck
+ value = 1
+ reassembled query = CHEck=1
+ reassembled query - del* = CHEck=1
+ check field exists = true
+ check field is true = true
+ check field = 1
+ check field name = CHEck
+ value = 1
+ reassembled query - remove = CHEck=1
+/?CHEck=foo
+ query string = CHEck=foo
+ name = CHEck
+ value = foo
+ reassembled query = CHEck=foo
+ reassembled query - del* = CHEck=foo
+ check field exists = true
+ check field is true = true
+ check field = foo
+ check field name = CHEck
+ value = foo
+ reassembled query - remove = CHEck=foo
+/?CHEck&CHEck=foo
+ query string = CHEck&CHEck=foo
+ name = CHEck
+ value =
+ name = CHEck
+ value = foo
+ reassembled query = CHEck=&CHEck=foo
+ reassembled query - del* = CHEck=&CHEck=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = CHEck
+ value =
+ check field name = CHEck
+ value = foo
+ reassembled query - remove = CHEck=&CHEck=foo
+/?CHEck=&CHEck=foo
+ query string = CHEck=&CHEck=foo
+ name = CHEck
+ value =
+ name = CHEck
+ value = foo
+ reassembled query = CHEck=&CHEck=foo
+ reassembled query - del* = CHEck=&CHEck=foo
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = CHEck
+ value =
+ check field name = CHEck
+ value = foo
+ reassembled query - remove = CHEck=&CHEck=foo
+/?CHEck=0&CHEck=foo
+ query string = CHEck=0&CHEck=foo
+ name = CHEck
+ value = 0
+ name = CHEck
+ value = foo
+ reassembled query = CHEck=0&CHEck=foo
+ reassembled query - del* = CHEck=0&CHEck=foo
+ check field exists = true
+ check field is true = true
+ check field = 0
+ check field name = CHEck
+ value = 0
+ check field name = CHEck
+ value = foo
+ reassembled query - remove = CHEck=0&CHEck=foo
+/?CHEck=1&CHEck=foo
+ query string = CHEck=1&CHEck=foo
+ name = CHEck
+ value = 1
+ name = CHEck
+ value = foo
+ reassembled query = CHEck=1&CHEck=foo
+ reassembled query - del* = CHEck=1&CHEck=foo
+ check field exists = true
+ check field is true = true
+ check field = 1
+ check field name = CHEck
+ value = 1
+ check field name = CHEck
+ value = foo
+ reassembled query - remove = CHEck=1&CHEck=foo
+/?check
+ query string = check
+ name = check
+ value =
+ reassembled query = check=
+ reassembled query - del* = check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = check=
+/?check&check
+ query string = check&check
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = check=&check=
+ reassembled query - del* = check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=
+/?check&check&check
+ query string = check&check&check
+ name = check
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = check=&check=&check=
+ reassembled query - del* = check=&check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=&check=
+/?foo&check
+ query string = foo&check
+ name = foo
+ value =
+ name = check
+ value =
+ reassembled query = foo=&check=
+ reassembled query - del* = foo=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = foo=&check=
+/?foo&check&check
+ query string = foo&check&check
+ name = foo
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = foo=&check=&check=
+ reassembled query - del* = foo=&check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = foo=&check=&check=
+/?foo&check&check&check
+ query string = foo&check&check&check
+ name = foo
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ reassembled query = foo=&check=&check=&check=
+ reassembled query - del* = foo=&check=&check=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = foo=&check=&check=&check=
+/?check&bar
+ query string = check&bar
+ name = check
+ value =
+ name = bar
+ value =
+ reassembled query = check=&bar=
+ reassembled query - del* = check=&bar=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = check=&bar=
+/?check&check&bar
+ query string = check&check&bar
+ name = check
+ value =
+ name = check
+ value =
+ name = bar
+ value =
+ reassembled query = check=&check=&bar=
+ reassembled query - del* = check=&check=&bar=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=&bar=
+/?check&check&check&bar
+ query string = check&check&check&bar
+ name = check
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ name = bar
+ value =
+ reassembled query = check=&check=&check=&bar=
+ reassembled query - del* = check=&check=&check=&bar=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&check=&check=&bar=
+/?foo&check&bar
+ query string = foo&check&bar
+ name = foo
+ value =
+ name = check
+ value =
+ name = bar
+ value =
+ reassembled query = foo=&check=&bar=
+ reassembled query - del* = foo=&check=&bar=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ reassembled query - remove = foo=&check=&bar=
+/?foo&check&check&bar
+ query string = foo&check&check&bar
+ name = foo
+ value =
+ name = check
+ value =
+ name = check
+ value =
+ name = bar
+ value =
+ reassembled query = foo=&check=&check=&bar=
+ reassembled query - del* = foo=&check=&check=&bar=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = foo=&check=&check=&bar=
+/?check&foo&check
+ query string = check&foo&check
+ name = check
+ value =
+ name = foo
+ value =
+ name = check
+ value =
+ reassembled query = check=&foo=&check=
+ reassembled query - del* = check=&foo=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&foo=&check=
+/?check&foo&foo&check
+ query string = check&foo&foo&check
+ name = check
+ value =
+ name = foo
+ value =
+ name = foo
+ value =
+ name = check
+ value =
+ reassembled query = check=&foo=&foo=&check=
+ reassembled query - del* = check=&foo=&foo=&check=
+ check field exists = true
+ check field is true = false
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value =
+ reassembled query - remove = check=&foo=&foo=&check=
+/?check=value1
+ query string = check=value1
+ name = check
+ value = value1
+ reassembled query = check=value1
+ reassembled query - del* = check=value1
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ reassembled query - remove = check=value1
+/?check=value1&check=value2
+ query string = check=value1&check=value2
+ name = check
+ value = value1
+ name = check
+ value = value2
+ reassembled query = check=value1&check=value2
+ reassembled query - del* = check=value1&check=value2
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = check=value1&check=value2
+/?check&check=value1&check=value2
+ query string = check&check=value1&check=value2
+ name = check
+ value =
+ name = check
+ value = value1
+ name = check
+ value = value2
+ reassembled query = check=&check=value1&check=value2
+ reassembled query - del* = check=&check=value1&check=value2
+ check field exists = true
+ check field is true = true
+ check field =
+ check field name = check
+ value =
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = check=&check=value1&check=value2
+/?foo&check=value1
+ query string = foo&check=value1
+ name = foo
+ value =
+ name = check
+ value = value1
+ reassembled query = foo=&check=value1
+ reassembled query - del* = foo=&check=value1
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ reassembled query - remove = foo=&check=value1
+/?foo&check=value1&check=value2
+ query string = foo&check=value1&check=value2
+ name = foo
+ value =
+ name = check
+ value = value1
+ name = check
+ value = value2
+ reassembled query = foo=&check=value1&check=value2
+ reassembled query - del* = foo=&check=value1&check=value2
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = foo=&check=value1&check=value2
+/?foo&check=value1&check=value2&check=value3
+ query string = foo&check=value1&check=value2&check=value3
+ name = foo
+ value =
+ name = check
+ value = value1
+ name = check
+ value = value2
+ name = check
+ value = value3
+ reassembled query = foo=&check=value1&check=value2&check=value3
+ reassembled query - del* = foo=&check=value1&check=value2&check=value3
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ check field name = check
+ value = value3
+ reassembled query - remove = foo=&check=value1&check=value2&check=value3
+/?check=value1&bar
+ query string = check=value1&bar
+ name = check
+ value = value1
+ name = bar
+ value =
+ reassembled query = check=value1&bar=
+ reassembled query - del* = check=value1&bar=
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ reassembled query - remove = check=value1&bar=
+/?check=value1&check=value2&bar
+ query string = check=value1&check=value2&bar
+ name = check
+ value = value1
+ name = check
+ value = value2
+ name = bar
+ value =
+ reassembled query = check=value1&check=value2&bar=
+ reassembled query - del* = check=value1&check=value2&bar=
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = check=value1&check=value2&bar=
+/?check=value1&check=value2&check=value3&bar
+ query string = check=value1&check=value2&check=value3&bar
+ name = check
+ value = value1
+ name = check
+ value = value2
+ name = check
+ value = value3
+ name = bar
+ value =
+ reassembled query = check=value1&check=value2&check=value3&bar=
+ reassembled query - del* = check=value1&check=value2&check=value3&bar=
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ check field name = check
+ value = value3
+ reassembled query - remove = check=value1&check=value2&check=value3&bar=
+/?foo&check=value1&bar
+ query string = foo&check=value1&bar
+ name = foo
+ value =
+ name = check
+ value = value1
+ name = bar
+ value =
+ reassembled query = foo=&check=value1&bar=
+ reassembled query - del* = foo=&check=value1&bar=
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ reassembled query - remove = foo=&check=value1&bar=
+/?foo&check=value1&check=value2&bar
+ query string = foo&check=value1&check=value2&bar
+ name = foo
+ value =
+ name = check
+ value = value1
+ name = check
+ value = value2
+ name = bar
+ value =
+ reassembled query = foo=&check=value1&check=value2&bar=
+ reassembled query - del* = foo=&check=value1&check=value2&bar=
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = foo=&check=value1&check=value2&bar=
+/?check=value1&foo&check=value2
+ query string = check=value1&foo&check=value2
+ name = check
+ value = value1
+ name = foo
+ value =
+ name = check
+ value = value2
+ reassembled query = check=value1&foo=&check=value2
+ reassembled query - del* = check=value1&foo=&check=value2
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = check=value1&foo=&check=value2
+/?check=value1&foo&foo&check=value2
+ query string = check=value1&foo&foo&check=value2
+ name = check
+ value = value1
+ name = foo
+ value =
+ name = foo
+ value =
+ name = check
+ value = value2
+ reassembled query = check=value1&foo=&foo=&check=value2
+ reassembled query - del* = check=value1&foo=&foo=&check=value2
+ check field exists = true
+ check field is true = true
+ check field = value1
+ check field name = check
+ value = value1
+ check field name = check
+ value = value2
+ reassembled query - remove = check=value1&foo=&foo=&check=value2
+/?field1=%26
+ query string = field1=%26
+ name = field1
+ value = &
+ reassembled query = field1=%26
+ reassembled query - del* = field1=%26
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=%26
+/?field1=%26&field2=%26
+ query string = field1=%26&field2=%26
+ name = field1
+ value = &
+ name = field2
+ value = &
+ reassembled query = field1=%26&field2=%26
+ reassembled query - del* = field1=%26&field2=%26
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=%26&field2=%26
+/?field1=%3d
+ query string = field1=%3d
+ name = field1
+ value = =
+ reassembled query = field1=%3D
+ reassembled query - del* = field1=%3D
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=%3D
+/?field1=%3d&field2=%3d
+ query string = field1=%3d&field2=%3d
+ name = field1
+ value = =
+ name = field2
+ value = =
+ reassembled query = field1=%3D&field2=%3D
+ reassembled query - del* = field1=%3D&field2=%3D
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field1=%3D&field2=%3D
+/?field%26=value1
+ query string = field%26=value1
+ name = field&
+ value = value1
+ reassembled query = field%26=value1
+ reassembled query - del* = field%26=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field%26=value1
+/?field%26=value1&field%26=value2
+ query string = field%26=value1&field%26=value2
+ name = field&
+ value = value1
+ name = field&
+ value = value2
+ reassembled query = field%26=value1&field%26=value2
+ reassembled query - del* = field%26=value1&field%26=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field%26=value1&field%26=value2
+/?field%3d=value1
+ query string = field%3d=value1
+ name = field=
+ value = value1
+ reassembled query = field%3D=value1
+ reassembled query - del* = field%3D=value1
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field%3D=value1
+/?field%3d=value1&field%3d=value2
+ query string = field%3d=value1&field%3d=value2
+ name = field=
+ value = value1
+ name = field=
+ value = value2
+ reassembled query = field%3D=value1&field%3D=value2
+ reassembled query - del* = field%3D=value1&field%3D=value2
+ check field exists = false
+ check field is true = false
+ check field = not present
+ reassembled query - remove = field%3D=value1&field%3D=value2
Index: Makefile.am
===================================================================
--- Makefile.am (revision 3604)
+++ Makefile.am (working copy)
@@ -6,7 +6,8 @@
INCLUDES = -I$(top_builddir)/include -I srcdir@/include @THREAD_CFLAGS@ @Z_CFLAGS@
-noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \
+noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath \
+ testURI testURIQuery \
testThreads testC14N testAutomata testRegexp \
testReader testapi testModule runtest runsuite
@@ -100,6 +101,11 @@
testURI_DEPENDENCIES = $(DEPS)
testURI_LDADD= $(LDADDS)
+testURIQuery_SOURCES=testURIQuery.c
+testURIQuery_LDFLAGS =
+testURIQuery_DEPENDENCIES = $(DEPS)
+testURIQuery_LDADD= $(LDADDS)
+
testRegexp_SOURCES=testRegexp.c
testRegexp_LDFLAGS =
testRegexp_DEPENDENCIES = $(DEPS)
@@ -159,7 +165,7 @@
testall : tests SVGtests SAXtests
-tests: XMLtests XMLenttests NStests IDtests Errtests APItests @READER_TEST@ @TEST_SAX@ @TEST_PUSH@
@TEST_HTML@ @TEST_PHTML@ @TEST_VALID@ URItests @TEST_PATTERN@ @TEST_XPATH@ @TEST_XPTR@ @TEST_XINCLUDE@
@TEST_C14N@ @TEST_DEBUG@ @TEST_CATALOG@ @TEST_REGEXPS@ @TEST_SCHEMAS@ @TEST_SCHEMATRON@ @TEST_THREADS@
Timingtests @TEST_VTIME@ @PYTHON_TESTS@ @TEST_MODULES@
+tests: XMLtests XMLenttests NStests IDtests Errtests APItests @READER_TEST@ @TEST_SAX@ @TEST_PUSH@
@TEST_HTML@ @TEST_PHTML@ @TEST_VALID@ URItests URIQuerytests @TEST_PATTERN@ @TEST_XPATH@ @TEST_XPTR@
@TEST_XINCLUDE@ @TEST_C14N@ @TEST_DEBUG@ @TEST_CATALOG@ @TEST_REGEXPS@ @TEST_SCHEMAS@ @TEST_SCHEMATRON@
@TEST_THREADS@ Timingtests @TEST_VTIME@ @PYTHON_TESTS@ @TEST_MODULES@
@(if [ "@PYTHON_SUBDIR@" != "" ] ; then cd python ; \
$(MAKE) MAKEFLAGS+=--silent tests ; fi)
@(cd doc/examples ; $(MAKE) MAKEFLAGS+=--silent tests)
@@ -437,6 +443,24 @@
rm result.$$name ; \
fi ; fi ; done)
+URIQuerytests : testURIQuery$(EXEEXT)
+ @(echo > .memdump)
+ @echo "## URI query string parser regression tests"
+ -@(for i in $(srcdir)/test/URIQuery/*.data ; do \
+ name=`basename $$i`; \
+ if [ ! -d $$i ] ; then \
+ if [ ! -f $(srcdir)/result/URIQuery/$$name ] ; then \
+ echo New test file $$name ; \
+ $(CHECKER) $(top_builddir)/testURIQuery < $$i > $(srcdir)/result/URIQuery/$$name ; \
+ grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \
+ else \
+ log=`$(CHECKER) $(top_builddir)/testURIQuery < $$i 2>&1 > result.$$name ; \
+ grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
+ diff $(srcdir)/result/URIQuery/$$name result.$$name` ; \
+ if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \
+ rm result.$$name ; \
+ fi ; fi ; done)
+
XPathtests : testXPath$(EXEEXT)
@(echo > .memdump)
@echo "## XPath regression tests"
Index: .cvsignore
===================================================================
--- .cvsignore (revision 3604)
+++ .cvsignore (working copy)
@@ -34,6 +34,7 @@
xmlversion.h
xmllint
testURI
+testURIQuery
testDocbook
testCatalog
xmlcatalog
Index: test/URIQuery/test1.data
===================================================================
--- test/URIQuery/test1.data (revision 0)
+++ test/URIQuery/test1.data (revision 0)
@@ -0,0 +1,144 @@
+# List of tests URIs supplied to the testURIQuery.c program.
+# That program takes each URL, extracts the query string (if any)
+# and performs a series of xmlURIQuery* functions on that
+# query string. You can find out more by looking at the test
+# program and the result file (result/URIQuery/test1.data).
+
+# No query string:
+
+/
+/?
+
+# Some simple query strings just to test parsing:
+
+/?field1=value1
+/?field1=value1&field2=value2
+/?field1=value1&field2=value2&field3=value3
+/?field1=value1&field2=value2&field3=value3&field4=value4
+
+# Test name= and =value
+
+/?field1=
+/?=value1
+/?field1=&field2=value2
+/?=value1&field2=value2
+/?field1=value1&field2=
+/?field1=value1&=value2
+/?field1=value1&field2=&field3=value3
+/?field1=value1&=value2&field3=value3
+
+# Empty fields
+
+/?&
+/?&&
+/?&&&
+/?field1=value1&&field2=value2
+/?&field1=value1&field2=value2
+/?&&field1=value1&field2=value2
+/?field1=value1&field2=value2&
+/?field1=value1&field2=value2&&
+
+# Any field names matching "del*" should be removed (tests the
+# "ignore" feature of xmlURIQueryCreate):
+
+/?field1=value1&delme=value2&field3=value3
+/?del=delete
+/?field1=del
+/?del1=value1&del2=value2&del3=value3
+/?field1=value1&del2=value2
+/?del1=value1&field2=value2
+/?field1=value1&del2=value2&del3=value3&del4=value4
+/?del1=value1&del2=value2&del3=value3&field4=value4
+
+# Any field names called "remove" should be removed (tests
+# xmlURIQueryRemove):
+
+/?field1=value1&remove=value2&field3=value3
+/?field1=remove
+/?remove=value1
+/?remove=value1&remove=value2
+/?remove=value1&remove=value2&remove=value3
+/?remove=value1&field2=value2
+/?field1=value1&remove=value2&remove=value3&remove=value4
+/?remove=value1&remove=value2&remove=value3&field4=value4
+/?field1=value1&remove=value2&remove=value3&field4=value4
+
+# Check Exists/IsTrue
+
+/?check=0
+/?check=0&check=0
+/?check=0&check=0&check=1
+/?check=
+/?check=&check=
+/?check=&check=&check=foo
+/?check
+/?check&check
+/?check&check&check=BAR
+/?ChecK=0
+/?ChecK=0&ChecK=0
+/?ChecK=0&ChecK=0&ChecK=1
+/?ChecK=
+/?ChecK=&ChecK=
+/?ChecK=&ChecK=&ChecK=foo
+/?ChecK
+/?ChecK&ChecK
+/?ChecK&ChecK&ChecK=BAR
+
+# Check GetSingle
+
+/?check
+/?check=0
+/?check=1
+/?check=foo
+/?check&check=foo
+/?check=&check=foo
+/?check=0&check=foo
+/?check=1&check=foo
+/?CHEck
+/?CHEck=0
+/?CHEck=1
+/?CHEck=foo
+/?CHEck&CHEck=foo
+/?CHEck=&CHEck=foo
+/?CHEck=0&CHEck=foo
+/?CHEck=1&CHEck=foo
+
+# Check GetMultiple
+
+/?check
+/?check&check
+/?check&check&check
+/?foo&check
+/?foo&check&check
+/?foo&check&check&check
+/?check&bar
+/?check&check&bar
+/?check&check&check&bar
+/?foo&check&bar
+/?foo&check&check&bar
+/?check&foo&check
+/?check&foo&foo&check
+/?check=value1
+/?check=value1&check=value2
+/?check&check=value1&check=value2
+/?foo&check=value1
+/?foo&check=value1&check=value2
+/?foo&check=value1&check=value2&check=value3
+/?check=value1&bar
+/?check=value1&check=value2&bar
+/?check=value1&check=value2&check=value3&bar
+/?foo&check=value1&bar
+/?foo&check=value1&check=value2&bar
+/?check=value1&foo&check=value2
+/?check=value1&foo&foo&check=value2
+
+# %-sequences in URLs
+
+/?field1=%26
+/?field1=%26&field2=%26
+/?field1=%3d
+/?field1=%3d&field2=%3d
+/?field%26=value1
+/?field%26=value1&field%26=value2
+/?field%3d=value1
+/?field%3d=value1&field%3d=value2
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature