gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] 07/07: response: process "Connection" header in a specia


From: gnunet
Subject: [libmicrohttpd] 07/07: response: process "Connection" header in a special manner
Date: Mon, 05 Jul 2021 16:07:48 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit e1693575ed0edfd2c0f09abcfd1df3021c1f793e
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Mon Jul 5 12:57:34 2021 +0300

    response: process "Connection" header in a special manner
---
 src/microhttpd/.gitignore              |   1 +
 src/microhttpd/Makefile.am             |   8 +-
 src/microhttpd/internal.h              |  17 +
 src/microhttpd/response.c              | 230 ++++++++++++
 src/microhttpd/test_response_entries.c | 618 +++++++++++++++++++++++++++++++++
 5 files changed, 873 insertions(+), 1 deletion(-)

diff --git a/src/microhttpd/.gitignore b/src/microhttpd/.gitignore
index 0ff01aac..3b0d8ce4 100644
--- a/src/microhttpd/.gitignore
+++ b/src/microhttpd/.gitignore
@@ -55,6 +55,7 @@ test_http_reasons
 /test_str_token
 /test_str_token_remove
 /test_str_tokens_remove
+/test_response_entries
 test_shutdown_poll
 test_shutdown_select
 test_md5
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 369e5554..e610c1df 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -166,6 +166,7 @@ check_PROGRAMS = \
   test_sha256 \
   test_start_stop \
   test_daemon \
+  test_response_entries \
   test_postprocessor_md \
   test_options
 
@@ -217,13 +218,18 @@ endif
 test_start_stop_SOURCES = \
   test_start_stop.c
 test_start_stop_LDADD = \
-  $(top_builddir)/src/microhttpd/libmicrohttpd.la
+  libmicrohttpd.la
 
 test_daemon_SOURCES = \
   test_daemon.c
 test_daemon_LDADD = \
   $(top_builddir)/src/microhttpd/libmicrohttpd.la
 
+test_response_entries_SOURCES = \
+  test_response_entries.c
+test_response_entries_LDADD = \
+  libmicrohttpd.la
+
 test_upgrade_SOURCES = \
   test_upgrade.c test_helpers.h mhd_sockets.h
 test_upgrade_CPPFLAGS = \
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 5b5e9396..d1f3b9ff 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -351,6 +351,18 @@ struct MHD_HTTP_Header
 };
 
 
+/**
+ * Automatically assigned flags
+ */
+enum MHD_ResponseAutoFlags
+{
+  MHD_RAF_NO_FLAGS = 0,                  /**< No auto flags */
+  MHD_RAF_HAS_CONNECTION_HDR = 1 << 0,   /**< Has "Connection" header */
+  MHD_RAF_HAS_CONNECTION_CLOSE = 1 << 1, /**< Has "Connection: close" */
+  MHD_RAF_HAS_TRANS_ENC_CHUNKED = 2 << 2 /**< Has "Transfer-Encoding: chunked 
*/
+} _MHD_FIXED_FLAGS_ENUM;
+
+
 #if defined(MHD_WINSOCK_SOCKETS)
 /**
  * Internally used I/O vector type for use with winsock.
@@ -510,6 +522,11 @@ struct MHD_Response
    */
   enum MHD_ResponseFlags flags;
 
+  /**
+   * Automatic flags set for the MHD response.
+   */
+  enum MHD_ResponseAutoFlags flags_auto;
+
   /**
    * If the @e fd is a pipe (no sendfile()).
    */
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 5d22640a..674cef0d 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -193,6 +193,227 @@ add_response_entry (struct MHD_Response *response,
 }
 
 
+/**
+ * Add "Connection:" header to the response with special processing.
+ *
+ * "Connection:" header value will be combined with any existing "Connection:"
+ * header, "close" token (if any) will be de-duplicated and moved to the first
+ * position.
+ *
+ * @param response the response to add a header to
+ * @param value the value to add
+ * @return #MHD_NO on error (no memory).
+ */
+static enum MHD_Result
+add_response_header_connection (struct MHD_Response *response,
+                                const char *value)
+{
+  static const char *key = "Connection";
+  /** the length of the "Connection" key */
+  static const size_t key_len = MHD_STATICSTR_LEN_ ("Connection");
+  size_t value_len;  /**< the length of the @a value */
+  size_t old_value_len; /**< the length of the existing "Connection" value */
+  size_t buf_size;   /**< the size of the buffer */
+  ssize_t norm_len;  /**< the length of the normalised value */
+  char *buf;         /**< the temporal buffer */
+  struct MHD_HTTP_Header *hdr; /**< existing "Connection" header */
+  bool value_has_close; /**< the @a value has "close" token */
+  bool already_has_close; /**< existing "Connection" header has "close" token 
*/
+  size_t pos = 0;   /**< position of addition in the @a buf */
+
+  if ( (NULL != strchr (value, '\r')) ||
+       (NULL != strchr (value, '\n')) )
+    return MHD_NO;
+
+  if (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR))
+  {
+    hdr = MHD_get_response_element_n_ (response, MHD_HEADER_KIND,
+                                       key, key_len);
+    already_has_close =
+      (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
+    mhd_assert (already_has_close == (0 == memcmp (hdr->value, "close", 5)));
+    mhd_assert (NULL != hdr);
+  }
+  else
+  {
+    hdr = NULL;
+    already_has_close = false;
+    mhd_assert (NULL == MHD_get_response_element_n_ (response,
+                                                     MHD_HEADER_KIND,
+                                                     key, key_len));
+    mhd_assert (0 == (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
+  }
+  if (NULL != hdr)
+    old_value_len = hdr->value_size + 2; /* additional size for ", " */
+  else
+    old_value_len = 0;
+
+  value_len = strlen (value);
+  /* Additional space for normalisation and zero-termination*/
+  norm_len = (ssize_t) (value_len + value_len / 2 + 1);
+  buf_size = old_value_len + (size_t) norm_len;
+
+  buf = malloc (buf_size);
+  if (NULL == buf)
+    return MHD_NO;
+  /* Move "close" token (if any) to the front */
+  value_has_close = MHD_str_remove_token_caseless_ (value, value_len, "close",
+                                                    MHD_STATICSTR_LEN_ ( \
+                                                      "close"),
+                                                    buf + old_value_len,
+                                                    &norm_len);
+  mhd_assert (0 <= norm_len);
+  if (0 > norm_len)
+    norm_len = 0; /* Must never happen */
+  if (0 == norm_len)
+  { /* New value is empty after normalisation */
+    if (! value_has_close)
+    { /* The new value had no tokens */
+      free (buf);
+      return MHD_NO;
+    }
+    if (already_has_close)
+    { /* The "close" token is already present, nothing to modify */
+      free (buf);
+      return MHD_YES;
+    }
+  }
+  /* Add "close" token if required */
+  if (value_has_close && ! already_has_close)
+  {
+    /* Need to insert "close" token at the first position */
+    mhd_assert (buf_size >= old_value_len + (size_t) norm_len   \
+                + MHD_STATICSTR_LEN_ ("close, ") + 1);
+    if (0 != norm_len)
+      memmove (buf + MHD_STATICSTR_LEN_ ("close, ") + old_value_len,
+               buf + old_value_len, norm_len + 1);
+    memcpy (buf, "close", MHD_STATICSTR_LEN_ ("close"));
+    pos += MHD_STATICSTR_LEN_ ("close");
+  }
+  /* Add old value tokens (if any) */
+  if (0 != old_value_len)
+  {
+    if (0 != pos)
+    {
+      buf[pos++] = ',';
+      buf[pos++] = ' ';
+    }
+    memcpy (buf + pos, hdr->value,
+            hdr->value_size);
+    pos += hdr->value_size;
+  }
+  /* Add new value token (if any) */
+  if (0 != norm_len)
+  {
+    if (0 != pos)
+    {
+      buf[pos++] = ',';
+      buf[pos++] = ' ';
+    }
+    /* The new value tokens must be already at the correct position */
+    mhd_assert ((value_has_close && ! already_has_close) ? \
+                (MHD_STATICSTR_LEN_ ("close, ") + old_value_len == pos) : \
+                (old_value_len == pos));
+    pos += (size_t) norm_len;
+  }
+  mhd_assert (buf_size > pos);
+  buf[pos] = 0; /* Null terminate the result */
+
+  if (NULL == hdr)
+  {
+    struct MHD_HTTP_Header *new_hdr; /**< new "Connection" header */
+    /* Create new response header entry */
+    new_hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Header));
+    if (NULL != new_hdr)
+    {
+      new_hdr->header = malloc (key_len + 1);
+      if (NULL != new_hdr->header)
+      {
+        memcpy (new_hdr->header, key, key_len + 1);
+        new_hdr->header_size = key_len;
+        new_hdr->value = buf;
+        new_hdr->value_size = pos;
+        new_hdr->kind = MHD_HEADER_KIND;
+        if (value_has_close)
+          response->flags_auto = (MHD_RAF_HAS_CONNECTION_HDR
+                                  | MHD_RAF_HAS_CONNECTION_CLOSE);
+        else
+          response->flags_auto = MHD_RAF_HAS_CONNECTION_HDR;
+        _MHD_insert_header_first (response, new_hdr);
+        return MHD_YES;
+      }
+      free (new_hdr);
+    }
+    free (buf);
+    return MHD_NO;
+  }
+
+  /* Update existing header entry */
+  free (hdr->value);
+  hdr->value = buf;
+  hdr->value_size = pos;
+  if (value_has_close && ! already_has_close)
+    response->flags_auto |= MHD_RAF_HAS_CONNECTION_CLOSE;
+  return MHD_YES;
+}
+
+
+/**
+ * Remove tokens from "Connection:" header of the response.
+ *
+ * Provided tokens will be removed from "Connection:" header value.
+ *
+ * @param response the response to manipulate "Connection:" header
+ * @param value the tokens to remove
+ * @return #MHD_NO on error (no headers or tokens found).
+ */
+static enum MHD_Result
+del_response_header_connection (struct MHD_Response *response,
+                                const char *value)
+{
+  struct MHD_HTTP_Header *hdr; /**< existing "Connection" header */
+
+  hdr = MHD_get_response_element_n_ (response, MHD_HEADER_KIND, "Connection",
+                                     MHD_STATICSTR_LEN_ ("Connection"));
+  if (NULL == hdr)
+    return MHD_NO;
+
+  if (! MHD_str_remove_tokens_caseless_ (hdr->value, &hdr->value_size, value,
+                                         strlen (value)))
+    return MHD_NO;
+  if (0 == hdr->value_size)
+  {
+    _MHD_remove_header (response, hdr);
+    free (hdr->value);
+    free (hdr->header);
+    free (hdr);
+    response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_HDR
+                              | MHD_RAF_HAS_CONNECTION_CLOSE);
+  }
+  else
+  {
+    hdr->value[hdr->value_size] = 0; /* Null-terminate the result */
+    if (0 != (response->flags_auto & ~(MHD_RAF_HAS_CONNECTION_CLOSE)))
+    {
+      if (MHD_STATICSTR_LEN_ ("close") == hdr->value_size)
+      {
+        if (0 != memcmp (hdr->value, "close", MHD_STATICSTR_LEN_ ("close")))
+          response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+      }
+      else if (MHD_STATICSTR_LEN_ ("close, ") < hdr->value_size)
+      {
+        if (0 != memcmp (hdr->value, "close, ",
+                         MHD_STATICSTR_LEN_ ("close, ")))
+          response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+      }
+      else
+        response->flags_auto &= ~(MHD_RAF_HAS_CONNECTION_CLOSE);
+    }
+  }
+  return MHD_YES;
+}
+
+
 /**
  * Add a header line to the response.
  *
@@ -232,6 +453,9 @@ MHD_add_response_header (struct MHD_Response *response,
                          const char *header,
                          const char *content)
 {
+  if (MHD_str_equal_caseless_ (header, MHD_HTTP_HEADER_CONNECTION))
+    return add_response_header_connection (response, content);
+
   if (MHD_str_equal_caseless_ (header,
                                MHD_HTTP_HEADER_TRANSFER_ENCODING))
   {
@@ -308,6 +532,12 @@ MHD_del_response_header (struct MHD_Response *response,
        (NULL == content) )
     return MHD_NO;
   header_len = strlen (header);
+
+  if ((0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR)) &&
+      (MHD_STATICSTR_LEN_ ("Connection") == header_len) &&
+      MHD_str_equal_caseless_bin_n_ (header, "Connection", header_len))
+    return del_response_header_connection (response, content);
+
   content_len = strlen (content);
   pos = response->first_header;
   while (NULL != pos)
diff --git a/src/microhttpd/test_response_entries.c 
b/src/microhttpd/test_response_entries.c
new file mode 100644
index 00000000..5a21b025
--- /dev/null
+++ b/src/microhttpd/test_response_entries.c
@@ -0,0 +1,618 @@
+/*
+     This file is part of libmicrohttpd
+     Copyright (C) 2021 Karlson2k (Evgeny Grin)
+
+     This test_response_entries.c file is in the public domain
+*/
+
+/**
+ * @file test_response_entries.c
+ * @brief  Test adding and removing response headers
+ * @author Karlson2k (Evgeny Grin)
+ */
+#include "mhd_options.h"
+#include "platform.h"
+#include <string.h>
+#include <microhttpd.h>
+
+
+static int
+expect_str (const char *actual, const char *expected)
+{
+  if (expected == actual)
+    return ! 0;
+  if (NULL == actual)
+  {
+    fprintf (stderr, "FAILED: result: NULL\n" \
+             "        expected: \"%s\"",
+             expected);
+    return 0;
+  }
+  if (NULL == expected)
+  {
+    fprintf (stderr, "FAILED: result: \"%s\"\n" \
+             "        expected: NULL",
+             actual);
+    return 0;
+  }
+  if (0 != strcmp (actual, expected))
+  {
+    fprintf (stderr, "FAILED: result: \"%s\"\n" \
+             "        expected: \"%s\"",
+             actual, expected);
+    return 0;
+  }
+  return ! 0;
+}
+
+
+int
+main (int argc,
+      char *const *argv)
+{
+  (void) argc;
+  (void) argv; /* Unused. Silence compiler warning. */
+  struct MHD_Response *r;
+
+  r = MHD_create_response_from_buffer (0, "", MHD_RESPMEM_PERSISTENT);
+  if (NULL == r)
+  {
+    fprintf (stderr, "Cannot create a response.\n");
+    return 1;
+  }
+
+  /* ** Test basic header functions ** */
+
+  /* Add first header */
+  if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a1"))
+  {
+    fprintf (stderr, "Cannot add header A1.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a1"))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Add second header with the same name */
+  if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a2"))
+  {
+    fprintf (stderr, "Cannot add header A2.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Value of the first header must be returned */
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a1"))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Remove the first header */
+  if (MHD_YES != MHD_del_response_header (r, "Header-Type-A", "value-a1"))
+  {
+    fprintf (stderr, "Cannot remove header A1.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Value of the ex-second header must be returned */
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Header-Type-A", "value-a3"))
+  {
+    fprintf (stderr, "Cannot add header A2.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Value of the ex-second header must be returned */
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  /* Remove the last header */
+  if (MHD_YES != MHD_del_response_header (r, "Header-Type-A", "value-a3"))
+  {
+    fprintf (stderr, "Cannot add header A2.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-A"), "value-a2"))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Header-Type-B"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (MHD_NO != MHD_del_response_header (r, "Header-Type-C", "value-a3"))
+  {
+    fprintf (stderr, "Removed non-existing header.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+  if (MHD_NO != MHD_del_response_header (r, "Header-Type-A", "value-c"))
+  {
+    fprintf (stderr, "Removed non-existing header value.\n");
+    MHD_destroy_response (r);
+    return 2;
+  }
+
+  /* ** Test "Connection:" header ** */
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "a,b,c,d,e"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with simple values.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "a, b, c, d, 
e"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "e,b,c,d,a"))
+  {
+    fprintf (stderr,
+             "Cannot remove \"Connection\" header with simple values.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection",
+                                          "i,k,l,m,n,o,p,close"))
+  {
+    fprintf (stderr,
+             "Cannot add \"Connection\" header with simple values and 
\"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, i, k, l, m, n, o, p"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "i,k,l,m,n,o,p,close"))
+  {
+    fprintf (stderr,
+             "Cannot remove \"Connection\" header with simple values and 
\"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection",
+                                          "1,2,3,4,5,6,7,close"))
+  {
+    fprintf (stderr,
+             "Cannot add \"Connection\" header with simple values and 
\"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, 1, 2, 3, 4, 5, 6, 7"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "8,9,close"))
+  {
+    fprintf (stderr,
+             "Cannot add second \"Connection\" header with simple values and 
\"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, 1, 2, 3, 4, 5, 6, 7, 8, 9"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "1,3,5,7,9"))
+  {
+    fprintf (stderr,
+             "Cannot remove part of \"Connection\" header with simple 
values.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, 2, 4, 6, 8"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "10,12"))
+  {
+    fprintf (stderr,
+             "Cannot add third \"Connection\" header with simple values.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, 2, 4, 6, 8, 10, 12"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "12  ,10  ,8  ,close"))
+  {
+    fprintf (stderr,
+             "Cannot remove part of \"Connection\" header with simple values 
and \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "2, 4, 6"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\" 
only.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, 2, 4, 6"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "4  ,5,6,7  8,"))
+  {
+    fprintf (stderr,
+             "Cannot remove part of \"Connection\" header with simple values 
and non-existing tokens.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "close, 2"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\" 
only.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "close, 2"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "close, 10, 12, 22, nothing"))
+  {
+    fprintf (stderr,
+             "Cannot remove part of \"Connection\" header with \"close\" and 
non-existing tokens.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "2"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "2"))
+  {
+    fprintf (stderr,
+             "Cannot remove part of \"Connection\" header with simple values 
and non-existing tokens.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot remove \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection", 
"close,other-token"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, other-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close, new-token"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, other-token, new-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "close, new-token"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "other-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "other-token"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection",
+                                          "close, one-long-token"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, one-long-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, one-long-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "one-long-token,close"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), "close"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection",
+                                          "close, additional-token"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, additional-token"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "additional-token,close"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "token-1,token-2"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "token-1, token-2"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "token-3"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "token-1, token-2, token-3"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, token-1, token-2, token-3"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, token-1, token-2, token-3"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close, token-4"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, token-1, token-2, token-3, token-4"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection", "close"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "token-1, token-2, token-3, token-4"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_add_response_header (r, "Connection", "close, token-5"))
+  {
+    fprintf (stderr, "Cannot add \"Connection\" header with \"close\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, token-1, token-2, token-3, token-4, token-5"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_NO != MHD_del_response_header (r, "Connection",
+                                         "non-existing, token-9"))
+  {
+    fprintf (stderr,
+             "Non-existing tokens successfully removed from \"Connection\" 
header.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"),
+                    "close, token-1, token-2, token-3, token-4, token-5"))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_NO != MHD_add_response_header (r, "Connection",
+                                         ",,,,,,,,,,,,    ,\t\t\t, , , "))
+  {
+    fprintf (stderr,
+             "Empty token was added successfully to \"Connection\" header.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_YES != MHD_del_response_header (r, "Connection",
+                                          "close, token-1, token-2, token-3, 
token-4, token-5"))
+  {
+    fprintf (stderr, "Cannot remove tokens from \"Connection\".\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (MHD_NO != MHD_add_response_header (r, "Connection",
+                                         ",,,,,,,,,,,,    ,\t\t\t, , , "))
+  {
+    fprintf (stderr,
+             "Empty token was added successfully to \"Connection\" header.\n");
+    MHD_destroy_response (r);
+    return 3;
+  }
+  if (! expect_str (MHD_get_response_header (r, "Connection"), NULL))
+  {
+    MHD_destroy_response (r);
+    return 3;
+  }
+
+  MHD_destroy_response (r);
+  printf ("All tests has been successfully passed.\n");
+  return 0;
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]