You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jr...@apache.org on 2019/01/29 20:31:09 UTC
[trafficserver] branch master updated: Add normalization the URI
before cdniuc validation
This is an automated email from the ASF dual-hosted git repository.
jrushford pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new b39b0f7 Add normalization the URI before cdniuc validation
b39b0f7 is described below
commit b39b0f7dd74b66dd11b7d62f49f3432a10dc7fbd
Author: Dylan Souza <dy...@comcast.com>
AuthorDate: Tue Jan 8 20:33:53 2019 +0000
Add normalization the URI before cdniuc validation
---
plugins/experimental/uri_signing/Makefile.inc | 2 +
plugins/experimental/uri_signing/common.h | 1 +
plugins/experimental/uri_signing/jwt.c | 37 +-
plugins/experimental/uri_signing/match.c | 2 +-
plugins/experimental/uri_signing/match.h | 2 +-
plugins/experimental/uri_signing/normalize.c | 382 +++++++++++++++++++++
.../uri_signing/{match.h => normalize.h} | 5 +-
.../uri_signing/unit_tests/uri_signing_test.cc | 182 ++++++++++
8 files changed, 593 insertions(+), 20 deletions(-)
diff --git a/plugins/experimental/uri_signing/Makefile.inc b/plugins/experimental/uri_signing/Makefile.inc
index e9807ba..864d2b4 100644
--- a/plugins/experimental/uri_signing/Makefile.inc
+++ b/plugins/experimental/uri_signing/Makefile.inc
@@ -23,6 +23,7 @@ experimental_uri_signing_uri_signing_la_SOURCES = \
experimental/uri_signing/jwt.c \
experimental/uri_signing/match.c \
experimental/uri_signing/parse.c \
+ experimental/uri_signing/normalize.c \
experimental/uri_signing/timing.c
experimental_uri_signing_uri_signing_la_LIBADD = @LIBJANSSON@ @LIBCJOSE@ @LIBPCRE@ -lm -lcrypto
@@ -39,4 +40,5 @@ experimental_uri_signing_test_uri_signing_SOURCES = \
experimental/uri_signing/cookie.c \
experimental/uri_signing/config.c \
experimental/uri_signing/timing.c \
+ experimental/uri_signing/normalize.c \
experimental/uri_signing/match.c
diff --git a/plugins/experimental/uri_signing/common.h b/plugins/experimental/uri_signing/common.h
index c930408..10505fa 100644
--- a/plugins/experimental/uri_signing/common.h
+++ b/plugins/experimental/uri_signing/common.h
@@ -28,6 +28,7 @@ void PrintToStdErr(const char *fmt, ...);
#else
+#include "ts/ts.h"
#define PluginDebug(...) TSDebug("uri_signing", PLUGIN_NAME " " __VA_ARGS__)
#define PluginError(...) PluginDebug(__VA_ARGS__), TSError(PLUGIN_NAME " " __VA_ARGS__)
diff --git a/plugins/experimental/uri_signing/jwt.c b/plugins/experimental/uri_signing/jwt.c
index 997448b..a38565c 100644
--- a/plugins/experimental/uri_signing/jwt.c
+++ b/plugins/experimental/uri_signing/jwt.c
@@ -19,6 +19,7 @@
#include "common.h"
#include "jwt.h"
#include "match.h"
+#include "normalize.h"
#include "ts/ts.h"
#include <jansson.h>
#include <cjose/cjose.h>
@@ -161,14 +162,26 @@ jwt_validate(struct jwt *jwt)
bool
jwt_check_uri(const char *cdniuc, const char *uri)
{
- static const char CONT_URI_STR[] = "uri";
- static const char CONT_URI_PATTERN_STR[] = "uri-pattern";
- static const char CONT_URI_REGEX_STR[] = "uri-regex";
+ static const char CONT_URI_HASH_STR[] = "hash";
+ static const char CONT_URI_REGEX_STR[] = "regex";
if (!cdniuc || !*cdniuc || !uri) {
return false;
}
+ /* Normalize the URI */
+ int uri_ct = strlen(uri);
+ int buff_ct = uri_ct + 2;
+ int err;
+ char normal_uri[buff_ct];
+
+ memset(normal_uri, 0, buff_ct);
+ err = normalize_uri(uri, uri_ct, normal_uri, buff_ct);
+
+ if (err) {
+ return false;
+ }
+
const char *kind = cdniuc, *container = cdniuc;
while (*container && *container != ':') {
++container;
@@ -179,23 +192,17 @@ jwt_check_uri(const char *cdniuc, const char *uri)
++container;
size_t len = container - kind;
- PluginDebug("Comparing with match kind \"%.*s\" on \"%s\" to \"%s\"", (int)len - 1, kind, container, uri);
+ PluginDebug("Comparing with match kind \"%.*s\" on \"%s\" to normalized URI \"%s\"", (int)len - 1, kind, container, normal_uri);
switch (len) {
- case sizeof CONT_URI_STR:
- if (!strncmp(CONT_URI_STR, kind, len - 1)) {
- return !strcmp(container, uri);
- }
- PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_STR, (int)len - 1, kind);
- break;
- case sizeof CONT_URI_PATTERN_STR:
- if (!strncmp(CONT_URI_PATTERN_STR, kind, len - 1)) {
- return match_glob(container, uri);
+ case sizeof CONT_URI_HASH_STR:
+ if (!strncmp(CONT_URI_HASH_STR, kind, len - 1)) {
+ return match_hash(container, normal_uri);
}
- PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_PATTERN_STR, (int)len - 1, kind);
+ PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_HASH_STR, (int)len - 1, kind);
break;
case sizeof CONT_URI_REGEX_STR:
if (!strncmp(CONT_URI_REGEX_STR, kind, len - 1)) {
- return match_regex(container, uri);
+ return match_regex(container, normal_uri);
}
PluginDebug("Expected kind %s, but did not find it in \"%.*s\"", CONT_URI_REGEX_STR, (int)len - 1, kind);
break;
diff --git a/plugins/experimental/uri_signing/match.c b/plugins/experimental/uri_signing/match.c
index b665dc4..18fb31a 100644
--- a/plugins/experimental/uri_signing/match.c
+++ b/plugins/experimental/uri_signing/match.c
@@ -23,7 +23,7 @@
#include <string.h>
bool
-match_glob(const char *needle, const char *haystack)
+match_hash(const char *needle, const char *haystack)
{
return false;
}
diff --git a/plugins/experimental/uri_signing/match.h b/plugins/experimental/uri_signing/match.h
index 92b906d..38f3eb2 100644
--- a/plugins/experimental/uri_signing/match.h
+++ b/plugins/experimental/uri_signing/match.h
@@ -17,5 +17,5 @@
*/
#include <stdbool.h>
-bool match_glob(const char *needle, const char *haystack);
+bool match_hash(const char *needle, const char *haystack);
bool match_regex(const char *pattern, const char *uri);
diff --git a/plugins/experimental/uri_signing/normalize.c b/plugins/experimental/uri_signing/normalize.c
new file mode 100644
index 0000000..e514111
--- /dev/null
+++ b/plugins/experimental/uri_signing/normalize.c
@@ -0,0 +1,382 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "normalize.h"
+#include "common.h"
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+/* Remove Dot Algorithm outlined in RFC3986 section 5.2.4
+ * Function writes normalizes path and writes to ret_buffer */
+int
+remove_dot_segments(const char *path, int path_ct, char *ret_buffer, int buff_ct)
+{
+ /* Ensure buffer is at least the size of the path */
+ if (buff_ct < path_ct) {
+ PluginDebug("Path buffer not large enough");
+ return -1;
+ }
+
+ /* Create an input buffer that we can change */
+ char inBuff[path_ct + 1];
+ memset(inBuff, 0, path_ct + 1);
+ strcpy(inBuff, path);
+
+ const char *path_end = inBuff + path_ct;
+ char *seg_start = inBuff;
+ char *seg_end;
+ char *write_buffer = ret_buffer;
+ int seg_len;
+
+ for (;;) {
+ if (seg_start == path_end) {
+ break;
+ }
+ seg_end = seg_start + 1;
+
+ /* Parse such that Seg start/end contain the next full path segment */
+ while (seg_end != path_end && *seg_end != '/') {
+ seg_end++;
+ }
+
+ seg_len = seg_end - seg_start + 1;
+
+ /* Remove starting ../ or ./ from input buffer */
+ if (!strncmp(seg_start, "../", seg_len) || !strncmp(seg_start, "./", seg_len)) {
+ if (seg_end != path_end) {
+ seg_end++;
+ }
+ }
+
+ /* Remove starting /./ or /. from input buffer and replace with '/' in output buffer */
+ else if (!strncmp(seg_start, "/./", seg_len) || !strncmp(seg_start, "/.", seg_len)) {
+ *write_buffer = '/';
+ write_buffer++;
+ if (seg_end != path_end) {
+ seg_end++;
+ }
+ }
+
+ /* Replace /../ or /.. with / in write_buffer and remove preceding segment */
+ else if (!strncmp(seg_start, "/../", seg_len) || !strncmp(seg_start, "/..", seg_len)) {
+ int prev_len = 0;
+ while (*write_buffer != '/' && write_buffer != ret_buffer) {
+ prev_len++;
+ write_buffer--;
+ }
+ memset(write_buffer, 0, prev_len);
+
+ /* Replace segment with '/' in input buffer */
+ if (seg_end != path_end) {
+ seg_start[seg_len - 1] = '/';
+ } else {
+ seg_start[seg_len - 2] = '/';
+ seg_end--;
+ }
+ }
+
+ /* Remove starting '.' or '..' from input buffer */
+ else if (!strncmp(seg_start, ".", seg_len) || !strncmp(seg_start, "..", seg_len)) {
+ if (seg_end != path_end) {
+ seg_end++;
+ }
+ }
+ /* Place the current path segment to the output buffer including initial '/' but not the next '/' */
+ else {
+ /* Write first forward slash to buffer */
+ if (*seg_start == '/') {
+ *write_buffer = *seg_start;
+ write_buffer++;
+ seg_start++;
+ }
+
+ /* Write subsequent characters to buffer */
+ while (*seg_start != '/') {
+ *write_buffer = *seg_start;
+ write_buffer++;
+ if (*seg_start == 0) {
+ break;
+ }
+ seg_start++;
+ }
+ }
+ seg_start = seg_end;
+ }
+
+ PluginDebug("Normalized Path: %s", ret_buffer);
+ return strlen(ret_buffer);
+}
+
+/* Function percent decodes uri_ct characters of the string uri and writes it to the decoded_uri
+ * buffer. If lower is true, it sets all characters including decoded ones to lower case.
+ * The function returns the length of the decoded string or -1 if there was a parsing error
+ * TODO: ADD functionality to ignore unicode non-standard characters and leave them encoded. Read RFC regarding normalization and
+ * determine if this is compliant.
+ */
+int
+percent_decode(const char *uri, int uri_ct, char *decoded_uri, bool lower)
+{
+ static const char *reserved_string = ":/?#[]@!$&\'()*+,;=";
+
+ if (uri_ct <= 0) {
+ return 0;
+ }
+
+ int offset = 0;
+ int i;
+ for (i = 0; i < uri_ct; i++) {
+ if (uri[i] == '%') {
+ /* The next two characters are interpreted as the hex encoded value. Store in encodedVal */
+ if (uri_ct < i + 2) {
+ goto decode_failure;
+ }
+ char encodedVal[2] = {0};
+ int j;
+ for (j = 0; j < 2; j++) {
+ if (isxdigit(uri[i + j + 1])) {
+ encodedVal[j] = uri[i + j + 1];
+ } else {
+ goto decode_failure;
+ }
+ }
+ int hexVal = 0;
+ char decodeChar;
+ sscanf(encodedVal, "%2x", &hexVal);
+ decodeChar = (char)hexVal;
+ /* If encoded value is a reserved char, leave encoded*/
+ if (strchr(reserved_string, decodeChar)) {
+ decoded_uri[i - offset] = uri[i];
+ decoded_uri[i + 1 - offset] = toupper(uri[i + 1]);
+ decoded_uri[i + 2 - offset] = toupper(uri[i + 2]);
+ }
+ /* If not a reserved char, decode using the decoded_uri buffer */
+ else {
+ if (lower) {
+ decoded_uri[i - offset] = tolower(decodeChar);
+ } else {
+ decoded_uri[i - offset] = decodeChar;
+ }
+ offset = offset + 2;
+ }
+ i = i + 2;
+ }
+ /* Write non-encoded values to decoded buffer */
+ else {
+ if (lower) {
+ decoded_uri[i - offset] = tolower(uri[i]);
+ } else {
+ decoded_uri[i - offset] = uri[i];
+ }
+ }
+ }
+
+ /* Return the size of the newly decoded string */
+ return uri_ct - offset;
+
+decode_failure:
+ PluginDebug("ERROR Decoding URI");
+ return -1;
+}
+
+/* This function takes a uri and an initialized buffer to populate with the normalized uri.
+ * Returns non zero for error
+ *
+ * The buffer provided must be at least the length of the uri + 1 as the normalized uri will
+ * potentially be one char larger than the original uri if a backslash is added to the path.
+ *
+ * The normalization function returns a string with the following modifications
+ * 1. Lowecase protocol/domain
+ * 2. Path segments .. and . are removed from path
+ * 3. Alphabetical percent encoded octet values are toupper
+ * 4. Non-reserved percent encoded octet values are decoded
+ * 5. The Port is removed if it is default
+ * 6. Defaults to a single backslash for the path segment if path segment is empty
+ */
+int
+normalize_uri(const char *uri, int uri_ct, char *normal_uri, int normal_ct)
+{
+ PluginDebug("Normalizing URI: %s", uri);
+
+ /* Buffer provided must be large enough to store the uri plus one additional char */
+ const char *uri_end = uri + uri_ct;
+ const char *buff_end = normal_uri + normal_ct;
+
+ if (normal_uri && normal_ct < uri_ct + 1) {
+ PluginDebug("Buffer to Normalize URI not large enough.");
+ return -1;
+ }
+
+ /* Initialize a path buffer to pass to path normalization function later on */
+ char path_buffer[normal_ct];
+ memset(path_buffer, 0, normal_ct);
+
+ /* Comp variables store starting/ending indexes for each uri component as uri is parsed.
+ * Write buffer traverses the normalized uri buffer as we build the normalized string.
+ */
+ const char *comp_start = uri;
+ const char *comp_end = uri;
+ char *write_buffer = normal_uri;
+ bool https = false;
+
+ /* Parse the protocol which will end with a colon */
+ while (*comp_end != ':' && comp_end != uri_end) {
+ *write_buffer = tolower(*comp_end);
+ comp_end++;
+ write_buffer++;
+ }
+
+ if (comp_end == uri_end) {
+ PluginDebug("Reached End of String prematurely");
+ goto normalize_failure;
+ }
+
+ /* Copy the colon */
+ *write_buffer = *comp_end;
+ comp_end++;
+ write_buffer++;
+
+ /* Ensure the protocol is either http or https */
+ if (strcmp("https:", normal_uri) == 0) {
+ https = true;
+ } else if (strcmp("http:", normal_uri)) {
+ PluginDebug("String is neither http or https");
+ goto normalize_failure;
+ }
+
+ /* Protocol must be terminated by two forward slashes */
+ int i;
+ for (i = 0; i < 2; i++) {
+ if (comp_end == uri_end || *comp_end != '/') {
+ goto normalize_failure;
+ }
+ *write_buffer = *comp_end;
+ comp_end++;
+ write_buffer++;
+ }
+
+ if (comp_end == uri_end) {
+ goto normalize_failure;
+ }
+
+ /* Comp_start is index of start of authority component */
+ int comp_ct;
+ comp_start = comp_end;
+
+ /* Set comp start/end to contain authority component */
+ bool userInfo = false;
+ while (comp_end != uri_end && *comp_end != '/' && *comp_end != '?' && *comp_end != '#') {
+ /* If we encounter userinfo, decode it without altering case and set comp_start/end to only include hostname/port */
+ if (*comp_end == '@' && userInfo == false) {
+ comp_ct = comp_end - comp_start;
+ comp_ct = percent_decode(comp_start, comp_ct, write_buffer, false);
+ if (comp_ct < 0) {
+ goto normalize_failure;
+ }
+ comp_start = comp_end;
+ userInfo = true;
+ write_buffer = write_buffer + comp_ct;
+ }
+ comp_end++;
+ }
+
+ /* UserInfo without a hostname is invalid */
+ if (userInfo == true && comp_end == uri_end) {
+ goto normalize_failure;
+ }
+
+ comp_ct = comp_end - comp_start;
+
+ /* - comp start/end holds indices in original uri of hostname/port
+ * - write_buffer holds pointer to start of hostname/port written to the decode buffer
+ * - comp_ct holds size of hostname/port in original uri
+ */
+
+ /* Parse and decode the hostname and port and set to lower case */
+ comp_ct = percent_decode(comp_start, comp_ct, write_buffer, true);
+
+ if (comp_ct < 0) {
+ goto normalize_failure;
+ }
+
+ /* Remove the port from the buffer if default */
+ while (*write_buffer != 0) {
+ if (*write_buffer == ':') {
+ if (https == true && !strncmp(write_buffer, ":443", 5)) {
+ memset(write_buffer, 0, 4);
+ break;
+ } else if (https == false && !strncmp(write_buffer, ":80", 4)) {
+ memset(write_buffer, 0, 3);
+ break;
+ }
+ }
+ write_buffer++;
+ }
+
+ comp_start = comp_end;
+
+ /* If we have reached the end of the authority section with an empty path component, add a trailing backslash */
+ if (*comp_end == 0 || *comp_end == '?' || *comp_end == '#') {
+ *write_buffer = '/';
+ write_buffer++;
+ }
+
+ /* If there is a path component, normalize it */
+ else {
+ /* Set comp start/end pointers to contain the path component */
+ while (*comp_end != '?' && *comp_end != '#' && *comp_end != 0) {
+ comp_end++;
+ }
+ /* Decode the path component without altering case and store it to the path_buffer*/
+ comp_ct = comp_end - comp_start;
+ comp_ct = percent_decode(comp_start, comp_ct, path_buffer, false);
+
+ if (comp_ct < 0) {
+ goto normalize_failure;
+ }
+
+ /* Remove the . and .. segments from the path and write the now normalized path to the output buffer */
+ PluginDebug("Removing Dot Segments");
+ int buff_ct = buff_end - write_buffer;
+ comp_ct = remove_dot_segments(path_buffer, comp_ct, write_buffer, buff_ct);
+
+ if (comp_ct < 0) {
+ PluginDebug("Failure removing dot segments from path");
+ goto normalize_failure;
+ }
+ write_buffer = write_buffer + comp_ct;
+ }
+
+ /* If there is any uri remaining after the path, decode and set case to lower */
+ if (comp_end != uri_end) {
+ comp_start = comp_end;
+ comp_ct = uri_end - comp_start;
+ comp_ct = percent_decode(comp_start, comp_ct, write_buffer, false);
+ if (comp_ct < 0) {
+ goto normalize_failure;
+ }
+ }
+
+ PluginDebug("Normalized URI: %s", normal_uri);
+ return 0;
+
+normalize_failure:
+ PluginDebug("URI Normalization Failure. URI does not fit http or https schemes.");
+ return -1;
+}
diff --git a/plugins/experimental/uri_signing/match.h b/plugins/experimental/uri_signing/normalize.h
similarity index 82%
copy from plugins/experimental/uri_signing/match.h
copy to plugins/experimental/uri_signing/normalize.h
index 92b906d..a84c997 100644
--- a/plugins/experimental/uri_signing/match.h
+++ b/plugins/experimental/uri_signing/normalize.h
@@ -16,6 +16,5 @@
* limitations under the License.
*/
-#include <stdbool.h>
-bool match_glob(const char *needle, const char *haystack);
-bool match_regex(const char *pattern, const char *uri);
+int normalize_uri(const char *uri, int uri_ct, char *uri_normal, int buffer_size);
+int remove_dot_segments(const char *path, int path_ct, char *ret_buffer, int buff_ct);
diff --git a/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc b/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
index d89bf9c..30b8681 100644
--- a/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
+++ b/plugins/experimental/uri_signing/unit_tests/uri_signing_test.cc
@@ -27,6 +27,7 @@ extern "C" {
#include <jansson.h>
#include <cjose/cjose.h>
#include "../jwt.h"
+#include "../normalize.h"
}
bool
@@ -48,6 +49,49 @@ jwt_parsing_helper(const char *jwt_string)
return resp;
}
+bool
+normalize_uri_helper(const char *uri, const char *expected_normal)
+{
+ size_t uri_ct = strlen(uri);
+ int buff_size = uri_ct + 2;
+ int err;
+ char uri_normal[buff_size];
+ memset(uri_normal, 0, buff_size);
+
+ err = normalize_uri(uri, uri_ct, uri_normal, buff_size);
+
+ if (err) {
+ return false;
+ }
+
+ if (expected_normal && strcmp(expected_normal, uri_normal) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+remove_dot_helper(const char *path, const char *expected_path)
+{
+ fprintf(stderr, "Removing Dot Segments from Path: %s\n", path);
+ size_t path_ct = strlen(path);
+ path_ct++;
+ int new_ct;
+ char path_buffer[path_ct];
+ memset(path_buffer, 0, path_ct);
+
+ new_ct = remove_dot_segments(path, path_ct, path_buffer, path_ct);
+
+ if (new_ct < 0) {
+ return false;
+ } else if (strcmp(expected_path, path_buffer) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
TEST_CASE("1", "[JWSParsingTest]")
{
INFO("TEST 1, Test JWT Parsing From Token Strings");
@@ -89,4 +133,142 @@ TEST_CASE("1", "[JWSParsingTest]")
REQUIRE(!jwt_parsing_helper("{\"cdniets\":30,\"cdnistt\":1,\"cdnistd\":4,\"iss\":\"Content Access "
"Manager\",\"cdniuc\":\"uri-regex:http://foobar.local/testDir/*\"}"));
}
+ fprintf(stderr, "\n");
+}
+
+TEST_CASE("3", "[RemoveDotSegmentsTest]")
+{
+ INFO("TEST 3, Test Removal of Dot Segments From Paths");
+
+ SECTION("../bar test") { REQUIRE(remove_dot_helper("../bar", "bar")); }
+
+ SECTION("./bar test") { REQUIRE(remove_dot_helper("./bar", "bar")); }
+
+ SECTION(".././bar test") { REQUIRE(remove_dot_helper(".././bar", "bar")); }
+
+ SECTION("./../bar test") { REQUIRE(remove_dot_helper("./../bar", "bar")); }
+
+ SECTION("/foo/./bar test") { REQUIRE(remove_dot_helper("/foo/./bar", "/foo/bar")); }
+
+ SECTION("/bar/./ test") { REQUIRE(remove_dot_helper("/bar/./", "/bar/")); }
+
+ SECTION("/. test") { REQUIRE(remove_dot_helper("/.", "/")); }
+
+ SECTION("/bar/. test") { REQUIRE(remove_dot_helper("/bar/.", "/bar/")); }
+
+ SECTION("/foo/../bar test") { REQUIRE(remove_dot_helper("/foo/../bar", "/bar")); }
+
+ SECTION("/bar/../ test") { REQUIRE(remove_dot_helper("/bar/../", "/")); }
+
+ SECTION("/.. test") { REQUIRE(remove_dot_helper("/..", "/")); }
+
+ SECTION("/bar/.. test") { REQUIRE(remove_dot_helper("/bar/..", "/")); }
+
+ SECTION("/foo/bar/.. test") { REQUIRE(remove_dot_helper("/foo/bar/..", "/foo/")); }
+
+ SECTION("Single . test") { REQUIRE(remove_dot_helper(".", "")); }
+
+ SECTION("Single .. test") { REQUIRE(remove_dot_helper("..", "")); }
+
+ SECTION("Test foo/bar/.. test") { REQUIRE(remove_dot_helper("foo/bar/..", "foo/")); }
+
+ SECTION("Test Empty Path Segment") { REQUIRE(remove_dot_helper("", "")); }
+
+ SECTION("Test mixed operations") { REQUIRE(remove_dot_helper("/foo/bar/././something/../foobar", "/foo/bar/foobar")); }
+ fprintf(stderr, "\n");
+}
+
+TEST_CASE("4", "[NormalizeTest]")
+{
+ INFO("TEST 4, Test Normalization of URIs");
+
+ SECTION("Testing passing too small of a URI to normalize") { REQUIRE(!normalize_uri_helper("ht", NULL)); }
+
+ SECTION("Testing passing non http/https protocol") { REQUIRE(!normalize_uri_helper("ht:", NULL)); }
+
+ SECTION("Passing a uri with half encoded value at end") { REQUIRE(!normalize_uri_helper("http://www.foobar.co%4", NULL)); }
+
+ SECTION("Passing a uri with half encoded value in the middle")
+ {
+ REQUIRE(!normalize_uri_helper("http://www.foobar.co%4psomethin/Path", NULL));
+ }
+
+ SECTION("Passing a uri with an empty path parameter")
+ {
+ REQUIRE(normalize_uri_helper("http://www.foobar.com", "http://www.foobar.com/"));
+ }
+
+ SECTION("Passing a uri with an empty path parameter and additional query params")
+ {
+ REQUIRE(normalize_uri_helper("http://www.foobar.com?query1=foo&query2=bar", "http://www.foobar.com/?query1=foo&query2=bar"));
+ }
+
+ SECTION("Empty path parameter with port")
+ {
+ REQUIRE(normalize_uri_helper("http://www.foobar.com:9301?query1=foo&query2=bar",
+ "http://www.foobar.com:9301/?query1=foo&query2=bar"));
+ }
+
+ SECTION("Passing a uri with a username and password")
+ {
+ REQUIRE(normalize_uri_helper("http://foo%40:PaSsword@www.Foo%42ar.coM:80/", "http://foo%40:PaSsword@www.foobar.com/"));
+ }
+
+ SECTION("Testing Removal of standard http Port")
+ {
+ REQUIRE(normalize_uri_helper("http://foobar.com:80/Something/Here", "http://foobar.com/Something/Here"));
+ }
+
+ SECTION("Testing Removal of standard https Port")
+ {
+ REQUIRE(normalize_uri_helper("https://foobar.com:443/Something/Here", "https://foobar.com/Something/Here"));
+ }
+
+ SECTION("Testing passing of non-standard http Port")
+ {
+ REQUIRE(normalize_uri_helper("http://foobar.com:443/Something/Here", "http://foobar.com:443/Something/Here"));
+ }
+
+ SECTION("Testing passing of non-standard https Port")
+ {
+ REQUIRE(normalize_uri_helper("https://foobar.com:80/Something/Here", "https://foobar.com:80/Something/Here"));
+ }
+
+ SECTION("Testing the removal of . and .. in the path ")
+ {
+ REQUIRE(
+ normalize_uri_helper("https://foobar.com:80/Something/Here/././foobar/../foo", "https://foobar.com:80/Something/Here/foo"));
+ }
+
+ SECTION("Testing . and .. segments in non path components")
+ {
+ REQUIRE(normalize_uri_helper("https://foobar.com:80/Something/Here?query1=/././foo/../bar",
+ "https://foobar.com:80/Something/Here?query1=/././foo/../bar"));
+ }
+
+ SECTION("Testing standard decdoing of multiple characters")
+ {
+ REQUIRE(normalize_uri_helper("https://kelloggs%54ester.com/%53omething/Here", "https://kelloggstester.com/Something/Here"));
+ }
+
+ SECTION("Testing passing encoded reserved characters")
+ {
+ REQUIRE(
+ normalize_uri_helper("https://kelloggs%54ester.com/%53omething/Here%3f", "https://kelloggstester.com/Something/Here%3F"));
+ }
+
+ SECTION("Mixed Bag Test case")
+ {
+ REQUIRE(normalize_uri_helper("https://foo:something@kellogs%54ester.com:443/%53omething/.././here",
+ "https://foo:something@kellogstester.com/here"));
+ }
+
+ SECTION("Testing empty hostname with userinfon") { REQUIRE(!normalize_uri_helper("https://foo:something@", NULL)); }
+
+ SECTION("Testing empty uri after http://") { REQUIRE(!normalize_uri_helper("http://", NULL)); }
+
+ SECTION("Testing http:///////") { REQUIRE(!normalize_uri_helper("http:///////", NULL)); }
+
+ SECTION("Testing empty uri after http://?/") { REQUIRE(!normalize_uri_helper("http://?/", NULL)); }
+ fprintf(stderr, "\n");
}