diff options
Diffstat (limited to 'src/microhttpd/test_postprocessor.c')
-rw-r--r-- | src/microhttpd/test_postprocessor.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c new file mode 100644 index 00000000..66bab81e --- /dev/null +++ b/src/microhttpd/test_postprocessor.c @@ -0,0 +1,349 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2007,2013 Christian Grothoff + + libmicrohttpd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + libmicrohttpd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file test_postprocessor.c + * @brief Testcase for postprocessor + * @author Christian Grothoff + */ + +#include "platform.h" +#include "microhttpd.h" +#include "internal.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#ifndef WINDOWS +#include <unistd.h> +#endif + +/** + * Array of values that the value checker "wants". + * Each series of checks should be terminated by + * five NULL-entries. + */ +const char *want[] = { +#define URL_DATA "abc=def&x=5" +#define URL_START 0 + "abc", NULL, NULL, NULL, "def", + "x", NULL, NULL, NULL, "5", +#define URL_END (URL_START + 10) + NULL, NULL, NULL, NULL, NULL, +#define FORM_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJoe Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata\r\n--AaB03x--\r\n" +#define FORM_START (URL_END + 5) + "field1", NULL, NULL, NULL, "Joe Blow", + "pics", "file1.txt", "text/plain", "binary", "filedata", +#define FORM_END (FORM_START + 10) + NULL, NULL, NULL, NULL, NULL, +#define FORM_NESTED_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJane Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"\r\nContent-type: multipart/mixed, boundary=BbC04y\r\n\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\n\r\nfiledata1\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file2.gif\"\r\nContent-type: image/gif\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata2\r\n--BbC04y--\r\n--AaB03x--" +#define FORM_NESTED_START (FORM_END + 5) + "field1", NULL, NULL, NULL, "Jane Blow", + "pics", "file1.txt", "text/plain", NULL, "filedata1", + "pics", "file2.gif", "image/gif", "binary", "filedata2", +#define FORM_NESTED_END (FORM_NESTED_START + 15) + NULL, NULL, NULL, NULL, NULL, +#define URL_EMPTY_VALUE_DATA "key1=value1&key2=&key3=" +#define URL_EMPTY_VALUE_START (FORM_NESTED_END + 5) + "key1", NULL, NULL, NULL, "value1", + "key2", NULL, NULL, NULL, "", + "key3", NULL, NULL, NULL, "", +#define URL_EMPTY_VALUE_END (URL_EMPTY_VALUE_START + 15) + NULL, NULL, NULL, NULL, NULL +}; + +static int +mismatch (const char *a, const char *b) +{ + if (a == b) + return 0; + if ((a == NULL) || (b == NULL)) + return 1; + return 0 != strcmp (a, b); +} + +static int +value_checker (void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, uint64_t off, size_t size) +{ + int *want_off = cls; + int idx = *want_off; + +#if 0 + fprintf (stderr, + "VC: `%s' `%s' `%s' `%s' `%.*s'\n", + key, filename, content_type, transfer_encoding, + (int) size, + data); +#endif + if ( (0 != off) && (0 == size) ) + return MHD_YES; + if ((idx < 0) || + (want[idx] == NULL) || + (0 != strcmp (key, want[idx])) || + (mismatch (filename, want[idx + 1])) || + (mismatch (content_type, want[idx + 2])) || + (mismatch (transfer_encoding, want[idx + 3])) || + (0 != memcmp (data, &want[idx + 4][off], size))) + { + *want_off = -1; + return MHD_NO; + } + if (off + size == strlen (want[idx + 4])) + *want_off = idx + 5; + return MHD_YES; + +} + + +static int +test_urlencoding () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off = URL_START; + int i; + int delta; + size_t size; + + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + i = 0; + size = strlen (URL_DATA); + while (i < size) + { + delta = 1 + MHD_random_ () % (size - i); + MHD_post_process (pp, &URL_DATA[i], delta); + i += delta; + } + MHD_destroy_post_processor (pp); + if (want_off != URL_END) + return 1; + return 0; +} + + +static int +test_multipart_garbage () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off; + size_t size = strlen (FORM_DATA); + size_t splitpoint; + char xdata[size + 3]; + + /* fill in evil garbage at the beginning */ + xdata[0] = '-'; + xdata[1] = 'x'; + xdata[2] = '\r'; + memcpy (&xdata[3], FORM_DATA, size); + size += 3; + + size = strlen (FORM_DATA); + for (splitpoint = 1; splitpoint < size; splitpoint++) + { + want_off = FORM_START; + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + MHD_post_process (pp, xdata, splitpoint); + MHD_post_process (pp, &xdata[splitpoint], size - splitpoint); + MHD_destroy_post_processor (pp); + if (want_off != FORM_END) + return (int) splitpoint; + } + return 0; +} + + +static int +test_multipart_splits () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off; + size_t size; + size_t splitpoint; + + size = strlen (FORM_DATA); + for (splitpoint = 1; splitpoint < size; splitpoint++) + { + want_off = FORM_START; + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + MHD_post_process (pp, FORM_DATA, splitpoint); + MHD_post_process (pp, &FORM_DATA[splitpoint], size - splitpoint); + MHD_destroy_post_processor (pp); + if (want_off != FORM_END) + return (int) splitpoint; + } + return 0; +} + + +static int +test_multipart () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off = FORM_START; + int i; + int delta; + size_t size; + + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + i = 0; + size = strlen (FORM_DATA); + while (i < size) + { + delta = 1 + MHD_random_ () % (size - i); + MHD_post_process (pp, &FORM_DATA[i], delta); + i += delta; + } + MHD_destroy_post_processor (pp); + if (want_off != FORM_END) + return 2; + return 0; +} + + +static int +test_nested_multipart () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off = FORM_NESTED_START; + int i; + int delta; + size_t size; + + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + i = 0; + size = strlen (FORM_NESTED_DATA); + while (i < size) + { + delta = 1 + MHD_random_ () % (size - i); + MHD_post_process (pp, &FORM_NESTED_DATA[i], delta); + i += delta; + } + MHD_destroy_post_processor (pp); + if (want_off != FORM_NESTED_END) + return 4; + return 0; +} + + +static int +test_empty_value () +{ + struct MHD_Connection connection; + struct MHD_HTTP_Header header; + struct MHD_PostProcessor *pp; + unsigned int want_off = URL_EMPTY_VALUE_START; + int i; + int delta; + size_t size; + + memset (&connection, 0, sizeof (struct MHD_Connection)); + memset (&header, 0, sizeof (struct MHD_HTTP_Header)); + connection.headers_received = &header; + header.header = MHD_HTTP_HEADER_CONTENT_TYPE; + header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; + header.kind = MHD_HEADER_KIND; + pp = MHD_create_post_processor (&connection, + 1024, &value_checker, &want_off); + i = 0; + size = strlen (URL_EMPTY_VALUE_DATA); + while (i < size) + { + delta = 1 + MHD_random_ () % (size - i); + MHD_post_process (pp, &URL_EMPTY_VALUE_DATA[i], delta); + i += delta; + } + MHD_destroy_post_processor (pp); + if (want_off != URL_EMPTY_VALUE_END) + return 8; + return 0; +} + + + + +int +main (int argc, char *const *argv) +{ + unsigned int errorCount = 0; + + errorCount += test_multipart_splits (); + errorCount += test_multipart_garbage (); + errorCount += test_urlencoding (); + errorCount += test_multipart (); + errorCount += test_nested_multipart (); + errorCount += test_empty_value (); + if (errorCount != 0) + fprintf (stderr, "Error (code: %u)\n", errorCount); + return errorCount != 0; /* 0 == pass */ +} |