summaryrefslogtreecommitdiffstats
path: root/test/test_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_utils.cpp')
-rw-r--r--test/test_utils.cpp1839
1 files changed, 1839 insertions, 0 deletions
diff --git a/test/test_utils.cpp b/test/test_utils.cpp
new file mode 100644
index 0000000..8eb1352
--- /dev/null
+++ b/test/test_utils.cpp
@@ -0,0 +1,1839 @@
+/***************************************************************************
+ * Copyright (c) 2009-2010 Open Information Security Foundation
+ * Copyright (c) 2010-2013 Qualys, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+
+ * - Neither the name of the Qualys, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ***************************************************************************/
+
+/**
+ * @file
+ * @brief Tests for various utility functions.
+ *
+ * @author Craig Forbes <cforbes@qualys.com>
+ * @author Ivan Ristic <ivanr@webkreator.com>
+ */
+
+#include <iostream>
+#include <gtest/gtest.h>
+#include <htp/htp_private.h>
+
+TEST(Base64, Single) {
+ EXPECT_EQ(62, htp_base64_decode_single('+'));
+ EXPECT_EQ(63, htp_base64_decode_single('/'));
+ EXPECT_EQ(-1, htp_base64_decode_single(','));
+ EXPECT_EQ(-1, htp_base64_decode_single(0));
+ EXPECT_EQ(-1, htp_base64_decode_single('~'));
+ EXPECT_EQ(26, htp_base64_decode_single('a'));
+ EXPECT_EQ(0, htp_base64_decode_single('A'));
+}
+
+TEST(Base64, Decode) {
+ const char *input = "dGhpcyBpcyBhIHRlc3QuLg==";
+ bstr *out = htp_base64_decode_mem(input, strlen(input));
+ EXPECT_EQ(0, bstr_cmp_c(out, "this is a test.."));
+ bstr_free(out);
+}
+
+TEST(UtilTest, Separator) {
+ EXPECT_EQ(0, htp_is_separator('a'));
+ EXPECT_EQ(0, htp_is_separator('^'));
+ EXPECT_EQ(0, htp_is_separator('-'));
+ EXPECT_EQ(0, htp_is_separator('_'));
+ EXPECT_EQ(0, htp_is_separator('&'));
+ EXPECT_EQ(1, htp_is_separator('('));
+ EXPECT_EQ(1, htp_is_separator('\\'));
+ EXPECT_EQ(1, htp_is_separator('/'));
+ EXPECT_EQ(1, htp_is_separator('='));
+ EXPECT_EQ(1, htp_is_separator('\t'));
+}
+
+TEST(UtilTest, Text) {
+ EXPECT_EQ(1, htp_is_text('\t'));
+ EXPECT_EQ(1, htp_is_text('a'));
+ EXPECT_EQ(1, htp_is_text('~'));
+ EXPECT_EQ(1, htp_is_text(' '));
+ EXPECT_EQ(0, htp_is_text('\n'));
+ EXPECT_EQ(0, htp_is_text('\r'));
+ EXPECT_EQ(0, htp_is_text('\r'));
+ EXPECT_EQ(0, htp_is_text(31));
+}
+
+TEST(UtilTest, Token) {
+ EXPECT_EQ(1, htp_is_token('a'));
+ EXPECT_EQ(1, htp_is_token('&'));
+ EXPECT_EQ(1, htp_is_token('+'));
+ EXPECT_EQ(0, htp_is_token('\t'));
+ EXPECT_EQ(0, htp_is_token('\n'));
+}
+
+TEST(UtilTest, Chomp) {
+ char data[100];
+ size_t len;
+ int result;
+
+ strcpy(data, "test\r\n");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(2, result);
+ EXPECT_EQ(4, len);
+
+ strcpy(data, "test\r\n\n");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(2, result);
+ EXPECT_EQ(4, len);
+
+ strcpy(data, "test\r\n\r\n");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(2, result);
+ EXPECT_EQ(4, len);
+
+ strcpy(data, "te\nst");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(5, len);
+
+ strcpy(data, "foo\n");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(1, result);
+ EXPECT_EQ(3, len);
+
+ strcpy(data, "arfarf");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(6, len);
+
+ strcpy(data, "");
+ len = strlen(data);
+ result = htp_chomp((unsigned char *) data, &len);
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(0, len);
+}
+
+TEST(UtilTest, Space) {
+ EXPECT_EQ(0, htp_is_space('a'));
+ EXPECT_EQ(1, htp_is_space(' '));
+ EXPECT_EQ(1, htp_is_space('\f'));
+ EXPECT_EQ(1, htp_is_space('\n'));
+ EXPECT_EQ(1, htp_is_space('\r'));
+ EXPECT_EQ(1, htp_is_space('\t'));
+ EXPECT_EQ(1, htp_is_space('\v'));
+}
+
+TEST(UtilTest, Method) {
+ bstr *method = bstr_dup_c("GET");
+
+ EXPECT_EQ(HTP_M_GET, htp_convert_method_to_number(method));
+
+ bstr_free(method);
+}
+
+TEST(UtilTest, IsLineEmpty) {
+ char data[100];
+ strcpy(data, "arfarf");
+ EXPECT_EQ(0, htp_is_line_empty((unsigned char*) data, 6));
+
+ strcpy(data, "\r\n");
+ EXPECT_EQ(1, htp_is_line_empty((unsigned char*) data, 2));
+ strcpy(data, "\r");
+ EXPECT_EQ(1, htp_is_line_empty((unsigned char*) data, 1));
+ EXPECT_EQ(0, htp_is_line_empty((unsigned char*) data, 0));
+
+}
+
+TEST(UtilTest, IsLineWhitespace) {
+ char data[100];
+ strcpy(data, "arfarf");
+ EXPECT_EQ(0, htp_is_line_whitespace((unsigned char*) data, 6));
+
+ strcpy(data, "\r\n");
+ EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 2));
+ strcpy(data, "\r");
+ EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 1));
+ EXPECT_EQ(1, htp_is_line_whitespace((unsigned char*) data, 0));
+}
+
+TEST(UtilTest, ParsePositiveIntegerWhitespace) {
+ EXPECT_EQ(123, htp_parse_positive_integer_whitespace(
+ (unsigned char*) "123 ", 6, 10));
+ EXPECT_EQ(123, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " 123", 6, 10));
+ EXPECT_EQ(123, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " 123 ", 9, 10));
+ EXPECT_EQ(-1, htp_parse_positive_integer_whitespace(
+ (unsigned char*) "a123", 4, 10));
+ EXPECT_EQ(-1001, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " \t", 4, 10));
+ EXPECT_EQ(-1002, htp_parse_positive_integer_whitespace(
+ (unsigned char*) "123b ", 5, 10));
+
+ EXPECT_EQ(-1, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " a123 ", 9, 10));
+ EXPECT_EQ(-1002, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " 123b ", 9, 10));
+
+ EXPECT_EQ(0x123, htp_parse_positive_integer_whitespace(
+ (unsigned char*) " 123 ", 9, 16));
+}
+
+TEST(UtilTest, ParseContentLength) {
+ bstr *str = bstr_dup_c("134");
+
+ EXPECT_EQ(134, htp_parse_content_length(str, NULL));
+
+ bstr_free(str);
+}
+
+TEST(UtilTest, ParseChunkedLength) {
+ EXPECT_EQ(0x12a5, htp_parse_chunked_length((unsigned char*) "12a5", 4, NULL));
+}
+
+TEST(UtilTest, IsLineFolded) {
+ EXPECT_EQ(-1, htp_connp_is_line_folded((unsigned char*) "", 0));
+ EXPECT_EQ(1, htp_connp_is_line_folded((unsigned char*) "\tline", 5));
+ EXPECT_EQ(1, htp_connp_is_line_folded((unsigned char*) " line", 5));
+ EXPECT_EQ(0, htp_connp_is_line_folded((unsigned char*) "line ", 5));
+}
+
+static void free_htp_uri_t(htp_uri_t **urip) {
+ htp_uri_t *uri = *urip;
+
+ if (uri == NULL) {
+ return;
+ }
+ bstr_free(uri->scheme);
+ bstr_free(uri->username);
+ bstr_free(uri->password);
+ bstr_free(uri->hostname);
+ bstr_free(uri->port);
+ bstr_free(uri->path);
+ bstr_free(uri->query);
+ bstr_free(uri->fragment);
+
+ free(uri);
+ *urip = NULL;
+}
+
+struct uri_expected {
+ const char *scheme;
+ const char *username;
+ const char *password;
+ const char *hostname;
+ const char *port;
+ const char *path;
+ const char *query;
+ const char *fragment;
+};
+
+struct uri_test {
+ const char *uri;
+ uri_expected expected;
+};
+
+bool bstr_equal_c(const bstr *b, const char *c) {
+ if ((c == NULL) || (b == NULL)) {
+ return (c == NULL) && (b == NULL);
+ } else {
+ return (0 == bstr_cmp_c(b, c));
+ }
+}
+
+void append_message(std::ostream & o,
+ const char *label, const char *expected, bstr *actual) {
+ o << label << " missmatch: ";
+ if (expected != NULL) {
+ o << "'" << expected << "'";
+ } else {
+ o << "<NULL>";
+ }
+ o << " != ";
+ if (actual != NULL) {
+ o << "'";
+ o.write((const char *) bstr_ptr(actual), bstr_len(actual));
+ o << "'";
+ } else {
+ o << "<NULL>";
+ }
+ o << std::endl;
+}
+
+static ::testing::AssertionResult UriIsExpected(const char *expected_var,
+ const char *actual_var,
+ const uri_expected &expected,
+ const htp_uri_t *actual) {
+ std::stringstream msg;
+ bool equal = true;
+
+ if (!bstr_equal_c(actual->scheme, expected.scheme)) {
+ equal = false;
+ append_message(msg, "scheme", expected.scheme, actual->scheme);
+ }
+
+ if (!bstr_equal_c(actual->username, expected.username)) {
+ equal = false;
+ append_message(msg, "username", expected.username, actual->username);
+ }
+
+ if (!bstr_equal_c(actual->password, expected.password)) {
+ equal = false;
+ append_message(msg, "password", expected.password, actual->password);
+ }
+
+ if (!bstr_equal_c(actual->hostname, expected.hostname)) {
+ equal = false;
+ append_message(msg, "hostname", expected.hostname, actual->hostname);
+ }
+
+ if (!bstr_equal_c(actual->port, expected.port)) {
+ equal = false;
+ append_message(msg, "port", expected.port, actual->port);
+ }
+
+ if (!bstr_equal_c(actual->path, expected.path)) {
+ equal = false;
+ append_message(msg, "path", expected.path, actual->path);
+ }
+
+ if (!bstr_equal_c(actual->query, expected.query)) {
+ equal = false;
+ append_message(msg, "query", expected.query, actual->query);
+ }
+
+ if (!bstr_equal_c(actual->fragment, expected.fragment)) {
+ equal = false;
+ append_message(msg, "fragment", expected.fragment, actual->fragment);
+ }
+
+ if (equal) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure() << msg.str();
+ }
+}
+
+struct uri_test uri_tests[] = {
+ {"http://user:pass@www.example.com:1234/path1/path2?a=b&c=d#frag",
+ {"http", "user", "pass", "www.example.com", "1234", "/path1/path2", "a=b&c=d", "frag"}},
+ {"http://host.com/path",
+ {"http", NULL, NULL, "host.com", NULL, "/path", NULL, NULL}},
+ {"http://",
+ {"http", NULL, NULL, NULL, NULL, "//", NULL, NULL}},
+ {"/path",
+ {NULL, NULL, NULL, NULL, NULL, "/path", NULL, NULL}},
+ {"://",
+ {"", NULL, NULL, NULL, NULL, "//", NULL, NULL}},
+ {"",
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
+ {"http://user@host.com",
+ {"http", "user", NULL, "host.com", NULL, "", NULL, NULL}},
+ {NULL,
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}
+};
+
+TEST(UtilTest, HtpParseUri) {
+ bstr *input = NULL;
+ htp_uri_t *uri = NULL;
+ uri_test *test;
+
+ input = bstr_dup_c("");
+ EXPECT_EQ(HTP_OK, htp_parse_uri(input, &uri));
+ bstr_free(input);
+ free_htp_uri_t(&uri);
+
+ test = uri_tests;
+ while (test->uri != NULL) {
+ input = bstr_dup_c(test->uri);
+ EXPECT_EQ(HTP_OK, htp_parse_uri(input, &uri));
+ EXPECT_PRED_FORMAT2(UriIsExpected, test->expected, uri)
+ << "Failed URI = " << test->uri << std::endl;
+
+ bstr_free(input);
+ free_htp_uri_t(&uri);
+ ++test;
+ }
+}
+
+TEST(UtilTest, ParseHostPort1) {
+ bstr *i = bstr_dup_c("www.example.com");
+ bstr *host;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(bstr_cmp(i, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort2) {
+ bstr *i = bstr_dup_c(" www.example.com ");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort3) {
+ bstr *i = bstr_dup_c(" www.example.com:8001 ");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(8001, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort4) {
+ bstr *i = bstr_dup_c(" www.example.com : 8001 ");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(8001, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort5) {
+ bstr *i = bstr_dup_c("www.example.com.");
+ bstr *e = bstr_dup_c("www.example.com.");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort6) {
+ bstr *i = bstr_dup_c("www.example.com.:8001");
+ bstr *e = bstr_dup_c("www.example.com.");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(8001, port);
+ ASSERT_EQ(0, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort7) {
+ bstr *i = bstr_dup_c("www.example.com:");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort8) {
+ bstr *i = bstr_dup_c("www.example.com:ff");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort9) {
+ bstr *i = bstr_dup_c("www.example.com:0");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort10) {
+ bstr *i = bstr_dup_c("www.example.com:65536");
+ bstr *e = bstr_dup_c("www.example.com");
+ bstr *host = NULL;
+ int port;
+ int flag = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &flag));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, flag);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort11) {
+ bstr *i = bstr_dup_c("[::1]:8080");
+ bstr *e = bstr_dup_c("[::1]");
+ bstr *host = NULL;
+ int port;
+ int invalid = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(8080, port);
+ ASSERT_EQ(0, invalid);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort12) {
+ bstr *i = bstr_dup_c("[::1]:");
+ bstr *e = bstr_dup_c("[::1]");
+ bstr *host = NULL;
+ int port;
+ int invalid = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, invalid);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort13) {
+ bstr *i = bstr_dup_c("[::1]x");
+ bstr *e = bstr_dup_c("[::1]");
+ bstr *host = NULL;
+ int port;
+ int invalid = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid));
+
+ ASSERT_TRUE(host != NULL);
+ ASSERT_TRUE(bstr_cmp(e, host) == 0);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, invalid);
+
+ bstr_free(host);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseHostPort14) {
+ bstr *i = bstr_dup_c("[::1");
+ bstr *host = NULL;
+ int port;
+ int invalid = 0;
+
+ ASSERT_EQ(HTP_OK, htp_parse_hostport(i, &host, NULL, &port, &invalid));
+
+ ASSERT_TRUE(host == NULL);
+ ASSERT_EQ(-1, port);
+ ASSERT_EQ(1, invalid);
+
+ bstr_free(host);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType1) {
+ bstr *i = bstr_dup_c("multipart/form-data");
+ bstr *e = bstr_dup_c("multipart/form-data");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType2) {
+ bstr *i = bstr_dup_c("multipart/form-data;boundary=X");
+ bstr *e = bstr_dup_c("multipart/form-data");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType3) {
+ bstr *i = bstr_dup_c("multipart/form-data boundary=X");
+ bstr *e = bstr_dup_c("multipart/form-data");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType4) {
+ bstr *i = bstr_dup_c("multipart/form-data,boundary=X");
+ bstr *e = bstr_dup_c("multipart/form-data");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType5) {
+ bstr *i = bstr_dup_c("multipart/FoRm-data");
+ bstr *e = bstr_dup_c("multipart/form-data");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ParseContentType6) {
+ bstr *i = bstr_dup_c("multipart/form-data\t boundary=X");
+ bstr *e = bstr_dup_c("multipart/form-data\t");
+ bstr *ct = NULL;
+
+ ASSERT_EQ(HTP_OK, htp_parse_ct_header(i, &ct));
+
+ ASSERT_TRUE(ct != NULL);
+ ASSERT_TRUE(bstr_cmp(e, ct) == 0);
+
+ bstr_free(ct);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname1) {
+ bstr *i = bstr_dup_c("www.example.com");
+ ASSERT_EQ(1, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname2) {
+ bstr *i = bstr_dup_c(".www.example.com");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname3) {
+ bstr *i = bstr_dup_c("www..example.com");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname4) {
+ bstr *i = bstr_dup_c("www.example.com..");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname5) {
+ bstr *i = bstr_dup_c("www example com");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname6) {
+ bstr *i = bstr_dup_c("");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname7) {
+ // Label over 63 characters.
+ bstr *i = bstr_dup_c("www.exampleexampleexampleexampleexampleexampleexampleexampleexampleexample.com");
+ ASSERT_EQ(0, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+TEST(UtilTest, ValidateHostname8) {
+ bstr *i = bstr_dup_c("www.ExAmplE-1984.com");
+ ASSERT_EQ(1, htp_validate_hostname(i));
+ bstr_free(i);
+}
+
+class DecodingTest : public testing::Test {
+protected:
+
+ virtual void SetUp() {
+ testing::Test::SetUp();
+
+ cfg = htp_config_create();
+ connp = htp_connp_create(cfg);
+ htp_connp_open(connp, "127.0.0.1", 32768, "127.0.0.1", 80, NULL);
+ tx = htp_connp_tx_create(connp);
+ }
+
+ virtual void TearDown() {
+ htp_connp_destroy_all(connp);
+ htp_config_destroy(cfg);
+
+ testing::Test::TearDown();
+ }
+
+ htp_connp_t *connp;
+
+ htp_cfg_t *cfg;
+
+ htp_tx_t *tx;
+};
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace1_Identity) {
+ bstr *i = bstr_dup_c("/dest");
+ bstr *e = bstr_dup_c("/dest");
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace2_Urlencoded) {
+ bstr *i = bstr_dup_c("/%64est");
+ bstr *e = bstr_dup_c("/dest");
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace3_UrlencodedInvalidPreserve) {
+ bstr *i = bstr_dup_c("/%xxest");
+ bstr *e = bstr_dup_c("/%xxest");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace4_UrlencodedInvalidRemove) {
+ bstr *i = bstr_dup_c("/%xxest");
+ bstr *e = bstr_dup_c("/xxest");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace5_UrlencodedInvalidDecode) {
+ bstr *i = bstr_dup_c("/%}9est");
+ bstr *e = bstr_dup_c("/iest");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace6_UrlencodedInvalidNotEnoughBytes) {
+ bstr *i = bstr_dup_c("/%a");
+ bstr *e = bstr_dup_c("/%a");
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace7_UrlencodedInvalidNotEnoughBytes) {
+ bstr *i = bstr_dup_c("/%");
+ bstr *e = bstr_dup_c("/%");
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace8_Uencoded) {
+ bstr *i = bstr_dup_c("/%u0064");
+ bstr *e = bstr_dup_c("/d");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace9_UencodedDoNotDecode) {
+ bstr *i = bstr_dup_c("/%u0064");
+ bstr *e = bstr_dup_c("/%u0064");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 0);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace10_UencodedInvalidNotEnoughBytes) {
+ bstr *i = bstr_dup_c("/%u006");
+ bstr *e = bstr_dup_c("/%u006");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace11_UencodedInvalidPreserve) {
+ bstr *i = bstr_dup_c("/%u006");
+ bstr *e = bstr_dup_c("/%u006");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace12_UencodedInvalidRemove) {
+ bstr *i = bstr_dup_c("/%uXXXX");
+ bstr *e = bstr_dup_c("/uXXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace13_UencodedInvalidDecode) {
+ bstr *i = bstr_dup_c("/%u00}9");
+ bstr *e = bstr_dup_c("/i");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace14_UencodedInvalidPreserve) {
+ bstr *i = bstr_dup_c("/%u00");
+ bstr *e = bstr_dup_c("/%u00");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace15_UencodedInvalidPreserve) {
+ bstr *i = bstr_dup_c("/%u0");
+ bstr *e = bstr_dup_c("/%u0");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace16_UencodedInvalidPreserve) {
+ bstr *i = bstr_dup_c("/%u");
+ bstr *e = bstr_dup_c("/%u");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace17_UrlencodedNul) {
+ bstr *i = bstr_dup_c("/%00");
+ bstr *e = bstr_dup_mem("/\0", 2);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace18_UrlencodedNulTerminates) {
+ bstr *i = bstr_dup_c("/%00ABC");
+ bstr *e = bstr_dup_c("/");
+ htp_config_set_nul_encoded_terminates(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace19_RawNulTerminates) {
+ bstr *i = bstr_dup_mem("/\0ABC", 5);
+ bstr *e = bstr_dup_c("/");
+ htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodeUrlencodedInplace20_UencodedBestFit) {
+ bstr *i = bstr_dup_c("/%u0107");
+ bstr *e = bstr_dup_c("/c");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_tx_urldecode_params_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace1_UrlencodedInvalidNotEnoughBytes) {
+ bstr *i = bstr_dup_c("/%a");
+ bstr *e = bstr_dup_c("/%a");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace2_UencodedInvalidNotEnoughBytes) {
+ bstr *i = bstr_dup_c("/%uX");
+ bstr *e = bstr_dup_c("/%uX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace3_UencodedValid) {
+ bstr *i = bstr_dup_c("/%u0107");
+ bstr *e = bstr_dup_c("/c");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace4_UencodedInvalidNotHexDigits_Remove) {
+ bstr *i = bstr_dup_c("/%uXXXX");
+ bstr *e = bstr_dup_c("/uXXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace5_UencodedInvalidNotHexDigits_Preserve) {
+ bstr *i = bstr_dup_c("/%uXXXX");
+ bstr *e = bstr_dup_c("/%uXXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace6_UencodedInvalidNotHexDigits_Process) {
+ bstr *i = bstr_dup_c("/%u00}9");
+ bstr *e = bstr_dup_c("/i");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace7_UencodedNul) {
+ bstr *i = bstr_dup_c("/%u0000");
+ bstr *e = bstr_dup_mem("/\0", 2);
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace8_UencodedNotEnough_Remove) {
+ bstr *i = bstr_dup_c("/%uXXX");
+ bstr *e = bstr_dup_c("/uXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace9_UencodedNotEnough_Preserve) {
+ bstr *i = bstr_dup_c("/%uXXX");
+ bstr *e = bstr_dup_c("/%uXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace10_UrlencodedNul) {
+ bstr *i = bstr_dup_c("/%00123");
+ bstr *e = bstr_dup_mem("/\000123", 5);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace11_UrlencodedNul_Terminates) {
+ bstr *i = bstr_dup_c("/%00123");
+ bstr *e = bstr_dup_mem("/", 1);
+ htp_config_set_nul_encoded_terminates(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_NUL);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace12_EncodedSlash) {
+ bstr *i = bstr_dup_c("/one%2ftwo");
+ bstr *e = bstr_dup_c("/one%2ftwo");
+ htp_config_set_path_separators_decode(cfg, HTP_DECODER_DEFAULTS, 0);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_SEPARATOR);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace13_EncodedSlash_Decode) {
+ bstr *i = bstr_dup_c("/one%2ftwo");
+ bstr *e = bstr_dup_c("/one/two");
+ htp_config_set_path_separators_decode(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_ENCODED_SEPARATOR);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace14_Urlencoded_Invalid_Preserve) {
+ bstr *i = bstr_dup_c("/%HH");
+ bstr *e = bstr_dup_c("/%HH");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace15_Urlencoded_Invalid_Remove) {
+ bstr *i = bstr_dup_c("/%HH");
+ bstr *e = bstr_dup_c("/HH");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace16_Urlencoded_Invalid_Process) {
+ bstr *i = bstr_dup_c("/%}9");
+ bstr *e = bstr_dup_c("/i");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace17_Urlencoded_NotEnough_Remove) {
+ bstr *i = bstr_dup_c("/%H");
+ bstr *e = bstr_dup_c("/H");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace18_Urlencoded_NotEnough_Preserve) {
+ bstr *i = bstr_dup_c("/%H");
+ bstr *e = bstr_dup_c("/%H");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace19_Urlencoded_NotEnough_Process) {
+ bstr *i = bstr_dup_c("/%H");
+ bstr *e = bstr_dup_c("/%H");
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_DEFAULTS, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ ASSERT_TRUE(tx->flags & HTP_PATH_INVALID_ENCODING);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace20_RawNul1) {
+ bstr *i = bstr_dup_mem("/\000123", 5);
+ bstr *e = bstr_dup_c("/");
+ htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace21_RawNul1) {
+ bstr *i = bstr_dup_mem("/\000123", 5);
+ bstr *e = bstr_dup_mem("/\000123", 5);
+ htp_config_set_nul_raw_terminates(cfg, HTP_DECODER_DEFAULTS, 0);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace22_ConvertBackslash1) {
+ bstr *i = bstr_dup_c("/one\\two");
+ bstr *e = bstr_dup_c("/one/two");
+ htp_config_set_backslash_convert_slashes(cfg, HTP_DECODER_DEFAULTS, 1);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, DecodePathInplace23_ConvertBackslash2) {
+ bstr *i = bstr_dup_c("/one\\two");
+ bstr *e = bstr_dup_c("/one\\two");
+ htp_config_set_backslash_convert_slashes(cfg, HTP_DECODER_DEFAULTS, 0);
+ htp_decode_path_inplace(tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+TEST_F(DecodingTest, InvalidUtf8) {
+ bstr *i = bstr_dup_c("\xf1.");
+ bstr *e = bstr_dup_c("?.");
+ htp_config_set_utf8_convert_bestfit(cfg, HTP_DECODER_URL_PATH, 1);
+ htp_utf8_decode_path_inplace(cfg, tx, i);
+ ASSERT_TRUE(bstr_cmp(i, e) == 0);
+ bstr_free(e);
+ bstr_free(i);
+}
+
+class UrlencodedParser : public testing::Test {
+protected:
+
+ virtual void SetUp() {
+ cfg = htp_config_create();
+ connp = htp_connp_create(cfg);
+ htp_connp_open(connp, "127.0.0.1", 32768, "127.0.0.1", 80, NULL);
+ tx = htp_connp_tx_create(connp);
+ urlenp = htp_urlenp_create(tx);
+ }
+
+ virtual void TearDown() {
+ htp_urlenp_destroy(urlenp);
+ htp_connp_destroy_all(connp);
+ htp_config_destroy(cfg);
+ }
+
+ htp_connp_t *connp;
+
+ htp_cfg_t *cfg;
+
+ htp_tx_t *tx;
+
+ htp_urlenp_t *urlenp;
+};
+
+TEST_F(UrlencodedParser, Empty) {
+ htp_urlenp_parse_complete(urlenp, "", 0);
+
+ ASSERT_EQ(0, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, EmptyKey1) {
+ htp_urlenp_parse_complete(urlenp, "&", 1);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, EmptyKey2) {
+ htp_urlenp_parse_complete(urlenp, "=&", 2);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, EmptyKey3) {
+ htp_urlenp_parse_complete(urlenp, "=1&", 3);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, "1"));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, EmptyKeyAndValue) {
+ htp_urlenp_parse_complete(urlenp, "=", 1);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "", 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, OnePairEmptyValue) {
+ htp_urlenp_parse_complete(urlenp, "p=", 2);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, OnePair) {
+ htp_urlenp_parse_complete(urlenp, "p=1", 3);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, "1"));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, TwoPairs) {
+ htp_urlenp_parse_complete(urlenp, "p=1&q=2", 7);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(p, "1"));
+
+ bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1);
+ ASSERT_TRUE(q != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(q, "2"));
+
+ ASSERT_EQ(2, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, KeyNoValue1) {
+ htp_urlenp_parse_complete(urlenp, "p", 1);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, KeyNoValue2) {
+ htp_urlenp_parse_complete(urlenp, "p&", 2);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, KeyNoValue3) {
+ htp_urlenp_parse_complete(urlenp, "p&q", 3);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1);
+ ASSERT_TRUE(q != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(q, ""));
+
+ ASSERT_EQ(2, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, KeyNoValue4) {
+ htp_urlenp_parse_complete(urlenp, "p&q=2", 5);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "q", 1);
+ ASSERT_TRUE(q != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(q, "2"));
+
+ ASSERT_EQ(2, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial1) {
+ htp_urlenp_parse_partial(urlenp, "p", 1);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial2) {
+ htp_urlenp_parse_partial(urlenp, "p", 1);
+ htp_urlenp_parse_partial(urlenp, "x", 1);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "px", 2);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial3) {
+ htp_urlenp_parse_partial(urlenp, "p", 1);
+ htp_urlenp_parse_partial(urlenp, "x&", 2);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "px", 2);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial4) {
+ htp_urlenp_parse_partial(urlenp, "p", 1);
+ htp_urlenp_parse_partial(urlenp, "=", 1);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial5) {
+ htp_urlenp_parse_partial(urlenp, "p", 1);
+ htp_urlenp_parse_partial(urlenp, "", 0);
+ htp_urlenp_parse_partial(urlenp, "", 0);
+ htp_urlenp_parse_partial(urlenp, "", 0);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "p", 1);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, ""));
+
+ ASSERT_EQ(1, htp_table_size(urlenp->params));
+}
+
+TEST_F(UrlencodedParser, Partial6) {
+ htp_urlenp_parse_partial(urlenp, "px", 2);
+ htp_urlenp_parse_partial(urlenp, "n", 1);
+ htp_urlenp_parse_partial(urlenp, "", 0);
+ htp_urlenp_parse_partial(urlenp, "=", 1);
+ htp_urlenp_parse_partial(urlenp, "1", 1);
+ htp_urlenp_parse_partial(urlenp, "2", 1);
+ htp_urlenp_parse_partial(urlenp, "&", 1);
+ htp_urlenp_parse_partial(urlenp, "qz", 2);
+ htp_urlenp_parse_partial(urlenp, "n", 1);
+ htp_urlenp_parse_partial(urlenp, "", 0);
+ htp_urlenp_parse_partial(urlenp, "=", 1);
+ htp_urlenp_parse_partial(urlenp, "2", 1);
+ htp_urlenp_parse_partial(urlenp, "3", 1);
+ htp_urlenp_parse_partial(urlenp, "&", 1);
+ htp_urlenp_finalize(urlenp);
+
+ bstr *p = (bstr *) htp_table_get_mem(urlenp->params, "pxn", 3);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(p, "12"));
+
+ bstr *q = (bstr *) htp_table_get_mem(urlenp->params, "qzn", 3);
+ ASSERT_TRUE(p != NULL);
+
+ ASSERT_EQ(0, bstr_cmp_c(q, "23"));
+
+ ASSERT_EQ(2, htp_table_size(urlenp->params));
+}
+
+TEST(List, Misc) {
+ htp_list_t *l = htp_list_create(16);
+
+ htp_list_push(l, (void *) "1");
+ htp_list_push(l, (void *) "2");
+ htp_list_push(l, (void *) "3");
+
+ ASSERT_EQ(3, htp_list_size(l));
+
+ char *p = (char *) htp_list_pop(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("3", p));
+
+ ASSERT_EQ(2, htp_list_size(l));
+
+ p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("1", p));
+
+ ASSERT_EQ(1, htp_list_size(l));
+
+ p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("2", p));
+
+ p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p == NULL);
+
+ p = (char *) htp_list_pop(l);
+ ASSERT_TRUE(p == NULL);
+
+ htp_list_destroy(l);
+}
+
+TEST(List, Misc2) {
+ htp_list_t *l = htp_list_create(1);
+
+ htp_list_push(l, (void *) "1");
+
+ char *p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("1", p));
+
+ htp_list_push(l, (void *) "2");
+
+ p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("2", p));
+
+ ASSERT_EQ(0, htp_list_size(l));
+
+ htp_list_destroy(l);
+}
+
+TEST(List, Misc3) {
+ htp_list_t *l = htp_list_create(2);
+
+ htp_list_push(l, (void *) "1");
+ htp_list_push(l, (void *) "2");
+
+ char *p = (char *) htp_list_shift(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("1", p));
+
+ htp_list_push(l, (void *) "3");
+
+ p = (char *) htp_list_get(l, 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("3", p));
+
+ ASSERT_EQ(2, htp_list_size(l));
+
+ htp_list_replace(l, 1, (void *) "4");
+
+ p = (char *) htp_list_pop(l);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("4", p));
+
+ htp_list_destroy(l);
+}
+
+TEST(List, Expand1) {
+ htp_list_t *l = htp_list_create(2);
+
+ htp_list_push(l, (void *) "1");
+ htp_list_push(l, (void *) "2");
+
+ ASSERT_EQ(2, htp_list_size(l));
+
+ htp_list_push(l, (void *) "3");
+
+ ASSERT_EQ(3, htp_list_size(l));
+
+ char *p = (char *) htp_list_get(l, 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("1", p));
+
+ p = (char *) htp_list_get(l, 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("2", p));
+
+ p = (char *) htp_list_get(l, 2);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("3", p));
+
+ htp_list_destroy(l);
+}
+
+TEST(List, Expand2) {
+ htp_list_t *l = htp_list_create(2);
+
+ htp_list_push(l, (void *) "1");
+ htp_list_push(l, (void *) "2");
+
+ ASSERT_EQ(2, htp_list_size(l));
+
+ htp_list_shift(l);
+
+ ASSERT_EQ(1, htp_list_size(l));
+
+ htp_list_push(l, (void *) "3");
+ htp_list_push(l, (void *) "4");
+
+ ASSERT_EQ(3, htp_list_size(l));
+
+ char *p = (char *) htp_list_get(l, 0);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("2", p));
+
+ p = (char *) htp_list_get(l, 1);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("3", p));
+
+ p = (char *) htp_list_get(l, 2);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("4", p));
+
+ htp_list_destroy(l);
+}
+
+TEST(Table, Misc) {
+ htp_table_t *t = htp_table_create(2);
+
+ bstr *pkey = bstr_dup_c("p");
+ bstr *qkey = bstr_dup_c("q");
+
+ htp_table_addk(t, pkey, "1");
+ htp_table_addk(t, qkey, "2");
+
+ char *p = (char *) htp_table_get_mem(t, "z", 1);
+ ASSERT_TRUE(p == NULL);
+
+ p = (char *) htp_table_get(t, pkey);
+ ASSERT_TRUE(p != NULL);
+ ASSERT_EQ(0, strcmp("1", p));
+
+ htp_table_clear_ex(t);
+
+ bstr_free(qkey);
+ bstr_free(pkey);
+
+ htp_table_destroy(t);
+}
+
+TEST(Util, ExtractQuotedString) {
+ bstr *s;
+ size_t end_offset;
+
+ htp_status_t rc = htp_extract_quoted_string_as_bstr((unsigned char *) "\"test\"", 6, &s, &end_offset);
+ ASSERT_EQ(HTP_OK, rc);
+ ASSERT_TRUE(s != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(s, "test"));
+ ASSERT_EQ(5, end_offset);
+ bstr_free(s);
+
+ rc = htp_extract_quoted_string_as_bstr((unsigned char *) "\"te\\\"st\"", 8, &s, &end_offset);
+ ASSERT_EQ(HTP_OK, rc);
+ ASSERT_TRUE(s != NULL);
+ ASSERT_EQ(0, bstr_cmp_c(s, "te\"st"));
+ ASSERT_EQ(7, end_offset);
+ bstr_free(s);
+}
+
+TEST(Util, NormalizeUriPath) {
+ bstr *s = NULL;
+
+ s = bstr_dup_c("/a/b/c/./../../g");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/a/g"));
+ bstr_free(s);
+
+ s = bstr_dup_c("mid/content=5/../6");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, "mid/6"));
+ bstr_free(s);
+
+ s = bstr_dup_c("./one");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, "one"));
+ bstr_free(s);
+
+ s = bstr_dup_c("../one");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, "one"));
+ bstr_free(s);
+
+ s = bstr_dup_c(".");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, ""));
+ bstr_free(s);
+
+ s = bstr_dup_c("..");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, ""));
+ bstr_free(s);
+
+ s = bstr_dup_c("one/.");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, "one"));
+ bstr_free(s);
+
+ s = bstr_dup_c("one/..");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, ""));
+ bstr_free(s);
+
+ s = bstr_dup_c("one/../");
+ htp_normalize_uri_path_inplace(s);
+ ASSERT_EQ(0, bstr_cmp_c(s, ""));
+ bstr_free(s);
+}
+
+TEST_F(UrlencodedParser, UrlDecode1) {
+ bstr *s = NULL;
+ uint64_t flags;
+
+ s = bstr_dup_c("/one/tw%u006f/three/%u123");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%u123"));
+ bstr_free(s);
+
+ s = bstr_dup_c("/one/tw%u006f/three/%uXXXX");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PRESERVE_PERCENT);
+ htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%uXXXX"));
+ bstr_free(s);
+
+ s = bstr_dup_c("/one/tw%u006f/three/%u123");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/u123"));
+ bstr_free(s);
+
+ s = bstr_dup_c("/one/tw%u006f/three/%3");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_REMOVE_PERCENT);
+ htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/3"));
+ bstr_free(s);
+
+ s = bstr_dup_c("/one/tw%u006f/three/%3");
+ htp_config_set_u_encoding_decode(cfg, HTP_DECODER_URLENCODED, 1);
+ htp_config_set_url_encoding_invalid_handling(cfg, HTP_DECODER_URLENCODED, HTP_URL_DECODE_PROCESS_INVALID);
+ htp_urldecode_inplace(cfg, HTP_DECODER_URLENCODED, s, &flags);
+ ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%3"));
+ bstr_free(s);
+}
+
+TEST(UtilTest, HeaderHasToken) {
+ char data[100];
+
+ // Basic
+ strcpy(data, "chunked");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+
+ // Negative
+ strcpy(data, "notchunked");
+ EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunkednot");
+ EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunk,ed");
+ EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunk ed");
+ EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+
+ // Positive
+ strcpy(data, " notchunked , chunked , yetanother");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunked,yetanother");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "not,chunked");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunk,chunked");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, " chunked");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunked ");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, "chunked,");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+ strcpy(data, ",chunked");
+ EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
+}