[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [libmicrohttpd] branch master updated: allow binary zero in
From: |
gnunet |
Subject: |
[GNUnet-SVN] [libmicrohttpd] branch master updated: allow binary zero in unescaped GET arguments (see mailinglist) |
Date: |
Wed, 20 Mar 2019 10:46:24 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository libmicrohttpd.
The following commit(s) were added to refs/heads/master by this push:
new 1b610e5b allow binary zero in unescaped GET arguments (see mailinglist)
1b610e5b is described below
commit 1b610e5b13b7b96e7b3f372c8da1ec9d840f896a
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Mar 20 10:46:21 2019 +0100
allow binary zero in unescaped GET arguments (see mailinglist)
---
ChangeLog | 6 +++
doc/examples/logging.c | 17 +++++--
doc/libmicrohttpd.texi | 13 +++++-
src/include/microhttpd.h | 56 +++++++++++++++++++----
src/microhttpd/connection.c | 91 ++++++++++++++++++++++++++++++-------
src/microhttpd/digestauth.c | 9 +++-
src/microhttpd/internal.c | 19 +++++---
src/microhttpd/internal.h | 9 +++-
src/microhttpd/response.c | 3 +-
src/testcurl/test_process_headers.c | 8 +++-
src/testcurl/test_urlparse.c | 9 +++-
11 files changed, 195 insertions(+), 45 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f591642d..32868ca0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed 20 Mar 2019 10:20:24 AM CET
+ Adding additional "value_length" argument to MHD_KeyValueIterator
+ callback to support binary zeros in values. This is done in a
+ backwards-compatible way, but may require adding a cast to existing
+ code to avoid a compiler warning. -CG
+
Sun Feb 10 21:00:37 BRT 2019
Added example for how to compress a chunked HTTP response. -SC
diff --git a/doc/examples/logging.c b/doc/examples/logging.c
index 239fbe7d..a88f461e 100644
--- a/doc/examples/logging.c
+++ b/doc/examples/logging.c
@@ -15,11 +15,16 @@
static int
-print_out_key (void *cls, enum MHD_ValueKind kind, const char *key,
- const char *value)
+print_out_key (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value,
+ size_t value_size)
{
- (void)cls; /* Unused. Silent compiler warning. */
- (void)kind; /* Unused. Silent compiler warning. */
+ (void) cls; /* Unused. Silent compiler warning. */
+ (void) kind; /* Unused. Silent compiler warning. */
+ (void) value_size;
+
printf ("%s: %s\n", key, value);
return MHD_YES;
}
@@ -38,7 +43,9 @@ answer_to_connection (void *cls, struct MHD_Connection
*connection,
(void)con_cls; /* Unused. Silent compiler warning. */
printf ("New %s request for %s using version %s\n", method, url, version);
- MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key,
+ MHD_get_connection_values (connection,
+ MHD_HEADER_KIND,
+ &print_out_key,
NULL);
return MHD_NO;
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index f2e3576c..97a79bdc 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -1356,7 +1356,7 @@ reason for request termination see
@code{MHD_OPTION_NOTIFY_COMPLETED}.
@end deftypefn
address@hidden {Function Pointer} int {*MHD_KeyValueIterator} (void *cls, enum
MHD_ValueKind kind, const char *key, const char *value)
address@hidden {Function Pointer} int {*MHD_KeyValueIterator} (void *cls, enum
MHD_ValueKind kind, const char *key, const char *value, size_t value_size)
Iterator over key-value pairs. This iterator can be used to iterate
over all of the cookies, headers, or @code{POST}-data fields of a
request, and also to iterate over the headers that have been added to a
@@ -1375,6 +1375,17 @@ key for the value, can be an empty string
@item value
value corresponding value, can be NULL
address@hidden value_size
+number of bytes in @code{value}. This argument was introduced in
address@hidden 0x00096301 to allow applications to use binary
+zeros in values. Applications using this argument must ensure that
+they are using a sufficiently recent version of MHD, i.e. by testing
address@hidden()} for values above or equal to 0.9.64.
+Applications that do not need zeros in values and that want to compile
+without warnings against newer versions of MHD should not declare this
+argument and cast the function pointer argument to
address@hidden
+
@end table
Return @code{MHD_YES} to continue iterating, @code{MHD_NO} to abort the
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 42f406ed..4917f62b 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -1,6 +1,6 @@
/*
This file is part of libmicrohttpd
- Copyright (C) 2006-2018 Christian Grothoff (and other contributing
authors)
+ Copyright (C) 2006--2019 Christian Grothoff (and other contributing
authors)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -126,7 +126,7 @@ typedef intptr_t ssize_t;
* Current version of the library.
* 0x01093001 = 1.9.30-1.
*/
-#define MHD_VERSION 0x00096300
+#define MHD_VERSION 0x00096301
/**
* MHD-internal return code for "YES".
@@ -1380,10 +1380,12 @@ enum MHD_OPTION
* struct MHD_Connection *c,
* char *s)
*
- * where the return value must be "strlen(s)" and "s" should be
- * updated. Note that the unescape function must not lengthen "s"
- * (the result must be shorter than the input and still be
- * 0-terminated). "cls" will be set to the second argument
+ * where the return value must be the length of the value left in
+ * "s" (without the 0-terminator) and "s" should be updated. Note
+ * that the unescape function must not lengthen "s" (the result must
+ * be shorter than the input and must still be 0-terminated).
+ * However, it may also include binary zeros before the
+ * 0-termination. "cls" will be set to the second argument
* following #MHD_OPTION_UNESCAPE_CALLBACK.
*/
MHD_OPTION_UNESCAPE_CALLBACK = 16,
@@ -2025,6 +2027,8 @@ typedef void
* @param kind kind of the header we are looking at
* @param key key for the value, can be an empty string
* @param value corresponding value, can be NULL
+ * @param value_size number of bytes in @a value, NEW since #MHD_VERSION
0x00096301;
+ * for C-strings, the length excludes the 0-terminator
* @return #MHD_YES to continue iterating,
* #MHD_NO to abort the iteration
* @ingroup request
@@ -2033,7 +2037,8 @@ typedef int
(*MHD_KeyValueIterator) (void *cls,
enum MHD_ValueKind kind,
const char *key,
- const char *value);
+ const char *value,
+ size_t value_size);
/**
@@ -2493,6 +2498,40 @@ MHD_set_connection_value (struct MHD_Connection
*connection,
const char *value);
+/**
+ * This function can be used to add an entry to the HTTP headers of a
+ * connection (so that the #MHD_get_connection_values function will
+ * return them -- and the `struct MHD_PostProcessor` will also see
+ * them). This maybe required in certain situations (see Mantis
+ * #1399) where (broken) HTTP implementations fail to supply values
+ * needed by the post processor (or other parts of the application).
+ *
+ * This function MUST only be called from within the
+ * #MHD_AccessHandlerCallback (otherwise, access maybe improperly
+ * synchronized). Furthermore, the client must guarantee that the key
+ * and value arguments are 0-terminated strings that are NOT freed
+ * until the connection is closed. (The easiest way to do this is by
+ * passing only arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ * value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @param value_size number of bytes in @a value (excluding 0-terminator for
C-strings)
+ * @return #MHD_NO if the operation could not be
+ * performed due to insufficient memory;
+ * #MHD_YES on success
+ * @ingroup request
+ */
+int
+MHD_set_connection_value2 (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value,
+ size_t value_size);
+
+
/**
* Sets the global error handler to a different implementation. @a cb
* will only be called in the case of typically fatal, serious
@@ -3075,7 +3114,8 @@ MHD_del_response_header (struct MHD_Response *response,
*/
_MHD_EXTERN int
MHD_get_response_headers (struct MHD_Response *response,
- MHD_KeyValueIterator iterator, void *iterator_cls);
+ MHD_KeyValueIterator iterator,
+ void *iterator_cls);
/**
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index bb88b969..4fe66805 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1,6 +1,6 @@
/*
This file is part of libmicrohttpd
- Copyright (C) 2007-2017 Daniel Pittman and Christian Grothoff
+ Copyright (C) 2007-2019 Daniel Pittman and Christian Grothoff
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -706,7 +706,8 @@ MHD_get_connection_values (struct MHD_Connection
*connection,
(MHD_YES != iterator (iterator_cls,
pos->kind,
pos->header,
- pos->value)) )
+ pos->value,
+ pos->value_size)) )
return ret;
}
return ret;
@@ -733,16 +734,18 @@ MHD_get_connection_values (struct MHD_Connection
*connection,
* @param kind kind of the value
* @param key key for the value
* @param value the value itself
+ * @param value_size number of bytes in @a value
* @return #MHD_NO if the operation could not be
* performed due to insufficient memory;
* #MHD_YES on success
* @ingroup request
*/
int
-MHD_set_connection_value (struct MHD_Connection *connection,
- enum MHD_ValueKind kind,
- const char *key,
- const char *value)
+MHD_set_connection_value2 (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value,
+ size_t value_size)
{
struct MHD_HTTP_Header *pos;
@@ -753,6 +756,7 @@ MHD_set_connection_value (struct MHD_Connection *connection,
return MHD_NO;
pos->header = (char *) key;
pos->value = (char *) value;
+ pos->value_size = value_size;
pos->kind = kind;
pos->next = NULL;
/* append 'pos' to the linked list of headers */
@@ -770,6 +774,47 @@ MHD_set_connection_value (struct MHD_Connection
*connection,
}
+/**
+ * This function can be used to add an entry to the HTTP headers of a
+ * connection (so that the #MHD_get_connection_values function will
+ * return them -- and the `struct MHD_PostProcessor` will also see
+ * them). This maybe required in certain situations (see Mantis
+ * #1399) where (broken) HTTP implementations fail to supply values
+ * needed by the post processor (or other parts of the application).
+ *
+ * This function MUST only be called from within the
+ * #MHD_AccessHandlerCallback (otherwise, access maybe improperly
+ * synchronized). Furthermore, the client must guarantee that the key
+ * and value arguments are 0-terminated strings that are NOT freed
+ * until the connection is closed. (The easiest way to do this is by
+ * passing only arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ * value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @return #MHD_NO if the operation could not be
+ * performed due to insufficient memory;
+ * #MHD_YES on success
+ * @ingroup request
+ */
+int
+MHD_set_connection_value (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value)
+{
+ return MHD_set_connection_value2 (connection,
+ kind,
+ key,
+ value,
+ NULL != value
+ ? strlen (value)
+ : 0);
+}
+
+
/**
* Get a particular header value. If multiple
* values match the kind, return any one of them.
@@ -2061,19 +2106,22 @@ get_next_header_line (struct MHD_Connection *connection,
* @param kind kind of the value
* @param key key for the value
* @param value the value itself
+ * @param value_size number of bytes in @a value
* @return #MHD_NO on failure (out of memory), #MHD_YES for success
*/
static int
connection_add_header (struct MHD_Connection *connection,
const char *key,
const char *value,
+ size_t value_size,
enum MHD_ValueKind kind)
{
if (MHD_NO ==
- MHD_set_connection_value (connection,
- kind,
- key,
- value))
+ MHD_set_connection_value2 (connection,
+ kind,
+ key,
+ value,
+ value_size))
{
#ifdef HAVE_MESSAGES
MHD_DLOG (connection->daemon,
@@ -2104,6 +2152,7 @@ parse_cookie_header (struct MHD_Connection *connection)
char *semicolon;
char *equals;
char *ekill;
+ char *end;
char old;
int quotes;
@@ -2155,6 +2204,7 @@ parse_cookie_header (struct MHD_Connection *connection)
connection_add_header (connection,
pos,
"",
+ 0,
MHD_COOKIE_KIND))
return MHD_NO;
if (old == '\0')
@@ -2174,6 +2224,7 @@ parse_cookie_header (struct MHD_Connection *connection)
quotes = (quotes + 1) & 1;
semicolon++;
}
+ end = semicolon;
if ('\0' == semicolon[0])
semicolon = NULL;
if (NULL != semicolon)
@@ -2183,15 +2234,17 @@ parse_cookie_header (struct MHD_Connection *connection)
}
/* remove quotes */
if ( ('"' == equals[0]) &&
- ('"' == equals[strlen (equals) - 1]) )
+ ('"' == end[-1]) )
{
- equals[strlen (equals) - 1] = '\0';
equals++;
+ end--;
+ *end = '\0';
}
if (MHD_NO ==
connection_add_header (connection,
pos,
equals,
+ end - equals,
MHD_COOKIE_KIND))
return MHD_NO;
pos = semicolon;
@@ -2711,16 +2764,20 @@ process_broken_line (struct MHD_Connection *connection,
REQUEST_TOO_BIG);
return MHD_NO;
}
- memcpy (&last[last_len], tmp, tmp_len + 1);
+ memcpy (&last[last_len],
+ tmp,
+ tmp_len + 1);
connection->last = last;
return MHD_YES; /* possibly more than 2 lines... */
}
mhd_assert ( (NULL != last) &&
(NULL != connection->colon) );
- if ((MHD_NO == connection_add_header (connection,
- last,
- connection->colon,
- kind)))
+ if (MHD_NO ==
+ connection_add_header (connection,
+ last,
+ connection->colon,
+ strlen (connection->colon),
+ kind))
{
transmit_error_response (connection,
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index c66bcadf..8f04bf38 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -732,6 +732,7 @@ calculate_nonce (uint32_t nonce_time,
* @param connection the connection
* @param key the key
* @param value the value, can be NULL
+ * @param value_size number of bytes in @a value
* @param kind type of the header
* @return #MHD_YES if the key-value pair is in the headers,
* #MHD_NO if not
@@ -740,6 +741,7 @@ static int
test_header (struct MHD_Connection *connection,
const char *key,
const char *value,
+ size_t value_size,
enum MHD_ValueKind kind)
{
struct MHD_HTTP_Header *pos;
@@ -748,6 +750,8 @@ test_header (struct MHD_Connection *connection,
{
if (kind != pos->kind)
continue;
+ if (value_size != pos->value_size)
+ continue;
if (0 != strcmp (key,
pos->header))
continue;
@@ -756,8 +760,9 @@ test_header (struct MHD_Connection *connection,
return MHD_YES;
if ( (NULL == value) ||
(NULL == pos->value) ||
- (0 != strcmp (value,
- pos->value)) )
+ (0 != memcmp (value,
+ pos->value,
+ value_size)) )
continue;
return MHD_YES;
}
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c
index d2532c54..8e9e0aac 100644
--- a/src/microhttpd/internal.c
+++ b/src/microhttpd/internal.c
@@ -162,7 +162,7 @@ MHD_http_unescape (char *val)
}
}
*wpos = '\0'; /* add 0-terminator */
- return wpos - val; /* = strlen(val) */
+ return wpos - val;
}
@@ -190,6 +190,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
struct MHD_Daemon *daemon = connection->daemon;
char *equals;
char *amper;
+ size_t len;
*num_headers = 0;
while ( (NULL != args) &&
@@ -210,6 +211,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
if (MHD_YES != cb (connection,
args,
NULL,
+ 0,
kind))
return MHD_NO;
(*num_headers)++;
@@ -223,12 +225,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
connection,
args);
MHD_unescape_plus (equals);
- daemon->unescape_callback (daemon->unescape_callback_cls,
- connection,
- equals);
+ len = daemon->unescape_callback (daemon->unescape_callback_cls,
+ connection,
+ equals);
if (MHD_YES != cb (connection,
args,
equals,
+ len,
kind))
return MHD_NO;
(*num_headers)++;
@@ -248,6 +251,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
if (MHD_YES != cb (connection,
args,
NULL,
+ 0,
kind))
return MHD_NO;
/* continue with 'bar' */
@@ -264,12 +268,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
connection,
args);
MHD_unescape_plus (equals);
- daemon->unescape_callback (daemon->unescape_callback_cls,
- connection,
- equals);
+ len = daemon->unescape_callback (daemon->unescape_callback_cls,
+ connection,
+ equals);
if (MHD_YES != cb (connection,
args,
equals,
+ len,
kind))
return MHD_NO;
(*num_headers)++;
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 0ce0b0c8..63bccd94 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -275,6 +275,11 @@ struct MHD_HTTP_Header
*/
char *value;
+ /**
+ * Number of bytes in @a value.
+ */
+ size_t value_size;
+
/**
* Type of the header (where in the HTTP protocol is this header
* from).
@@ -1881,7 +1886,8 @@ MHD_unescape_plus (char *arg);
*
* @param connection context of the iteration
* @param key 0-terminated key string, never NULL
- * @param value 0-terminated value string, may be NULL
+ * @param value 0-terminated binary data, may include binary zeros, may be NULL
+ * @param value_size number of bytes in value
* @param kind origin of the key-value pair
* @return #MHD_YES on success (continue to iterate)
* #MHD_NO to signal failure (and abort iteration)
@@ -1890,6 +1896,7 @@ typedef int
(*MHD_ArgumentIterator_)(struct MHD_Connection *connection,
const char *key,
const char *value,
+ size_t value_size,
enum MHD_ValueKind kind);
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 263f8303..9f328eef 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -240,7 +240,8 @@ MHD_get_response_headers (struct MHD_Response *response,
(MHD_YES != iterator (iterator_cls,
pos->kind,
pos->header,
- pos->value)))
+ pos->value,
+ pos->value_size)))
break;
}
return numHeaders;
diff --git a/src/testcurl/test_process_headers.c
b/src/testcurl/test_process_headers.c
index f9c7cd03..3be814e2 100644
--- a/src/testcurl/test_process_headers.c
+++ b/src/testcurl/test_process_headers.c
@@ -65,8 +65,13 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
return size * nmemb;
}
+
static int
-kv_cb (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
+kv_cb (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value,
+ size_t value_size)
{
if ((0 == strcmp (key, MHD_HTTP_HEADER_HOST)) &&
(0 == strncmp (value, "127.0.0.1", strlen("127.0.0.1"))) && (kind ==
MHD_HEADER_KIND))
@@ -77,6 +82,7 @@ kv_cb (void *cls, enum MHD_ValueKind kind, const char *key,
const char *value)
return MHD_YES;
}
+
static int
ahc_echo (void *cls,
struct MHD_Connection *connection,
diff --git a/src/testcurl/test_urlparse.c b/src/testcurl/test_urlparse.c
index 8675f19c..1e6cc28c 100644
--- a/src/testcurl/test_urlparse.c
+++ b/src/testcurl/test_urlparse.c
@@ -67,13 +67,18 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
return size * nmemb;
}
+
static int
test_values (void *cls,
enum MHD_ValueKind kind,
const char *key,
- const char *value)
+ const char *value,
+ size_t value_size)
{
- (void)cls;(void)kind; /* Unused. Silent compiler warning. */
+ (void) cls;
+ (void) kind;
+ (void) value_size;
+
if ( (0 == strcmp (key, "a")) &&
(0 == strcmp (value, "b")) )
matches += 1;
--
To stop receiving notification emails like this one, please contact
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [libmicrohttpd] branch master updated: allow binary zero in unescaped GET arguments (see mailinglist),
gnunet <=