From ec800b43d5da06ece1b8be1dcbdb13b05810adae Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Latour Date: Fri, 4 Jan 2019 18:58:43 -0800 Subject: [PATCH] Added GCDWebServerNormalizePath() API --- Frameworks/Tests.m | 19 +++++++++++++++++++ GCDWebServer/Core/GCDWebServerFunctions.h | 5 +++++ GCDWebServer/Core/GCDWebServerFunctions.m | 15 +++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/Frameworks/Tests.m b/Frameworks/Tests.m index b1d69e7..8266450 100644 --- a/Frameworks/Tests.m +++ b/Frameworks/Tests.m @@ -1,6 +1,8 @@ #import #import +#pragma clang diagnostic ignored "-Weverything" // Prevent "messaging to unqualified id" warnings + @interface Tests : XCTestCase @end @@ -21,4 +23,21 @@ XCTAssertNotNil(server); } +- (void)testPaths { + XCTAssertEqualObjects(GCDWebServerNormalizePath(@""), @""); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/"), @"/foo"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar"), @"foo/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo//bar"), @"foo/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar//"), @"foo/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/./bar"), @"foo/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/bar/."), @"foo/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"foo/../bar"), @"bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/../bar"), @"/bar"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/foo/.."), @"/"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"/.."), @"/"); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"."), @""); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@".."), @""); + XCTAssertEqualObjects(GCDWebServerNormalizePath(@"../.."), @""); +} + @end diff --git a/GCDWebServer/Core/GCDWebServerFunctions.h b/GCDWebServer/Core/GCDWebServerFunctions.h index 6bf978f..7d9cd7f 100644 --- a/GCDWebServer/Core/GCDWebServerFunctions.h +++ b/GCDWebServer/Core/GCDWebServerFunctions.h @@ -102,6 +102,11 @@ NSString* GCDWebServerFormatISO8601(NSDate* date); */ NSDate* _Nullable GCDWebServerParseISO8601(NSString* string); +/** + * Removes "//", "/./" and "/../" components from path as well as any trailing slash. + */ +NSString* GCDWebServerNormalizePath(NSString* path); + #ifdef __cplusplus } #endif diff --git a/GCDWebServer/Core/GCDWebServerFunctions.m b/GCDWebServer/Core/GCDWebServerFunctions.m index df96a0d..c34c02e 100644 --- a/GCDWebServer/Core/GCDWebServerFunctions.m +++ b/GCDWebServer/Core/GCDWebServerFunctions.m @@ -314,3 +314,18 @@ NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) { buffer[2 * CC_MD5_DIGEST_LENGTH] = 0; return (NSString*)[NSString stringWithUTF8String:buffer]; } + +NSString* GCDWebServerNormalizePath(NSString* path) { + NSMutableArray* components = [[NSMutableArray alloc] init]; + for (NSString* component in [path componentsSeparatedByString:@"/"]) { + if ([component isEqualToString:@".."]) { + [components removeLastObject]; + } else if (component.length && ![component isEqualToString:@"."]) { + [components addObject:component]; + } + } + if (path.length && ([path characterAtIndex:0] == '/')) { + return [@"/" stringByAppendingString:[components componentsJoinedByString:@"/"]]; // Preserve initial slash + } + return [components componentsJoinedByString:@"/"]; +}