diff --git a/src/ios/GCDWebServer/.clang-format b/src/ios/GCDWebServer/.clang-format new file mode 100644 index 0000000..b0b6cbe --- /dev/null +++ b/src/ios/GCDWebServer/.clang-format @@ -0,0 +1,16 @@ +--- +BasedOnStyle: Google +Standard: Cpp11 +ColumnLimit: 0 +AlignTrailingComments: false +NamespaceIndentation: All +DerivePointerAlignment: false +AlwaysBreakBeforeMultilineStrings: false +AccessModifierOffset: -2 +ObjCSpaceBeforeProtocolList: true +SortIncludes: false +--- +Language: Cpp +--- +Language: ObjC +... diff --git a/src/ios/GCDWebServer/.travis.yml b/src/ios/GCDWebServer/.travis.yml index 05cfcb6..204499b 100644 --- a/src/ios/GCDWebServer/.travis.yml +++ b/src/ios/GCDWebServer/.travis.yml @@ -1,3 +1,3 @@ language: objective-c script: ./Run-Tests.sh -osx_image: xcode7.1 +osx_image: xcode8.2 diff --git a/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h b/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h index 84914db..4fc53a0 100644 --- a/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h +++ b/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.h @@ -27,6 +27,8 @@ #import "GCDWebServer.h" +NS_ASSUME_NONNULL_BEGIN + @class GCDWebDAVServer; /** @@ -86,7 +88,7 @@ /** * Sets the delegate for the server. */ -@property(nonatomic, assign) id delegate; +@property(nonatomic, weak, nullable) id delegate; /** * Sets which files are allowed to be operated on depending on their extension. @@ -154,3 +156,5 @@ - (BOOL)shouldCreateDirectoryAtPath:(NSString*)path; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m b/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m index 079607b..54e9f3c 100644 --- a/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m +++ b/src/ios/GCDWebServer/GCDWebDAVServer/GCDWebDAVServer.m @@ -55,12 +55,104 @@ typedef NS_ENUM(NSInteger, DAVProperties) { kDAVAllProperties = kDAVProperty_ResourceType | kDAVProperty_CreationDate | kDAVProperty_LastModified | kDAVProperty_ContentLength }; -@interface GCDWebDAVServer () { -@private - NSString* _uploadDirectory; - NSArray* _allowedExtensions; - BOOL _allowHidden; +NS_ASSUME_NONNULL_BEGIN + +@interface GCDWebDAVServer (Methods) +- (nullable GCDWebServerResponse*)performOPTIONS:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)performPUT:(GCDWebServerFileRequest*)request; +- (nullable GCDWebServerResponse*)performDELETE:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)performMKCOL:(GCDWebServerDataRequest*)request; +- (nullable GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL)isMove; +- (nullable GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request; +- (nullable GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request; +- (nullable GCDWebServerResponse*)performUNLOCK:(GCDWebServerRequest*)request; +@end + +NS_ASSUME_NONNULL_END + +@implementation GCDWebDAVServer + +@dynamic delegate; + +- (instancetype)initWithUploadDirectory:(NSString*)path { + if ((self = [super init])) { + _uploadDirectory = [[path stringByStandardizingPath] copy]; + GCDWebDAVServer* __unsafe_unretained server = self; + + // 9.1 PROPFIND method + [self addDefaultHandlerForMethod:@"PROPFIND" + requestClass:[GCDWebServerDataRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performPROPFIND:(GCDWebServerDataRequest*)request]; + }]; + + // 9.3 MKCOL Method + [self addDefaultHandlerForMethod:@"MKCOL" + requestClass:[GCDWebServerDataRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performMKCOL:(GCDWebServerDataRequest*)request]; + }]; + + // 9.4 GET & HEAD methods + [self addDefaultHandlerForMethod:@"GET" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performGET:request]; + }]; + + // 9.6 DELETE method + [self addDefaultHandlerForMethod:@"DELETE" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performDELETE:request]; + }]; + + // 9.7 PUT method + [self addDefaultHandlerForMethod:@"PUT" + requestClass:[GCDWebServerFileRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performPUT:(GCDWebServerFileRequest*)request]; + }]; + + // 9.8 COPY method + [self addDefaultHandlerForMethod:@"COPY" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performCOPY:request isMove:NO]; + }]; + + // 9.9 MOVE method + [self addDefaultHandlerForMethod:@"MOVE" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performCOPY:request isMove:YES]; + }]; + + // 9.10 LOCK method + [self addDefaultHandlerForMethod:@"LOCK" + requestClass:[GCDWebServerDataRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performLOCK:(GCDWebServerDataRequest*)request]; + }]; + + // 9.11 UNLOCK method + [self addDefaultHandlerForMethod:@"UNLOCK" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performUNLOCK:request]; + }]; + + // 10.1 OPTIONS method / DAV Header + [self addDefaultHandlerForMethod:@"OPTIONS" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server performOPTIONS:request]; + }]; + } + return self; } + @end @implementation GCDWebDAVServer (Methods) @@ -71,7 +163,7 @@ - (BOOL)_checkSandboxedPath:(NSString*)path { } - (BOOL)_checkFileExtension:(NSString*)fileName { - if (_allowedExtensions && ![_allowedExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { + if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; } return YES; @@ -99,22 +191,27 @@ - (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request { if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if (([itemName hasPrefix:@"."] && !_allowHiddenItems) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Downlading item name \"%@\" is not allowed", itemName]; } - + // Because HEAD requests are mapped to GET ones, we need to handle directories but it's OK to return nothing per http://webdav.org/specs/rfc4918.html#rfc.section.9.4 if (isDirectory) { return [GCDWebServerResponse response]; } - + if ([self.delegate respondsToSelector:@selector(davServer:didDownloadFileAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate davServer:self didDownloadFileAtPath:absolutePath]; }); } + + if ([request hasByteRange]) { + return [GCDWebServerFileResponse responseWithFile:absolutePath byteRange:request.byteRange]; + } + return [GCDWebServerFileResponse responseWithFile:absolutePath]; } @@ -122,7 +219,7 @@ - (GCDWebServerResponse*)performPUT:(GCDWebServerFileRequest*)request { if ([request hasByteRange]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Range uploads not supported"]; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; if (![self _checkSandboxedPath:absolutePath]) { @@ -132,27 +229,27 @@ - (GCDWebServerResponse*)performPUT:(GCDWebServerFileRequest*)request { if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath]; } - + BOOL existing = [[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]; if (existing && isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"PUT not allowed on existing collection \"%@\"", relativePath]; } - + NSString* fileName = [absolutePath lastPathComponent]; - if (([fileName hasPrefix:@"."] && !_allowHidden) || ![self _checkFileExtension:fileName]) { + if (([fileName hasPrefix:@"."] && !_allowHiddenItems) || ![self _checkFileExtension:fileName]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file name \"%@\" is not allowed", fileName]; } - + if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:request.temporaryPath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file to \"%@\" is not permitted", relativePath]; } - + [[NSFileManager defaultManager] removeItemAtPath:absolutePath error:NULL]; NSError* error = nil; if (![[NSFileManager defaultManager] moveItemAtPath:request.temporaryPath toPath:absolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed moving uploaded file to \"%@\"", relativePath]; } - + if ([self.delegate respondsToSelector:@selector(davServer:didUploadFileAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate davServer:self didUploadFileAtPath:absolutePath]; @@ -166,28 +263,28 @@ - (GCDWebServerResponse*)performDELETE:(GCDWebServerRequest*)request { if (depthHeader && ![depthHeader isEqualToString:@"infinity"]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader]; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if (([itemName hasPrefix:@"."] && !_allowHiddenItems) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting item name \"%@\" is not allowed", itemName]; } - + if (![self shouldDeleteItemAtPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting \"%@\" is not permitted", relativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] removeItemAtPath:absolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed deleting \"%@\"", relativePath]; } - + if ([self.delegate respondsToSelector:@selector(davServer:didDeleteItemAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate davServer:self didDeleteItemAtPath:absolutePath]; @@ -200,7 +297,7 @@ - (GCDWebServerResponse*)performMKCOL:(GCDWebServerDataRequest*)request { if ([request hasBody] && (request.contentLength > 0)) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_UnsupportedMediaType message:@"Unexpected request body for MKCOL method"]; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; if (![self _checkSandboxedPath:absolutePath]) { @@ -210,16 +307,16 @@ - (GCDWebServerResponse*)performMKCOL:(GCDWebServerDataRequest*)request { if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath]; } - + NSString* directoryName = [absolutePath lastPathComponent]; - if (!_allowHidden && [directoryName hasPrefix:@"."]) { + if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory name \"%@\" is not allowed", directoryName]; } - + if (![self shouldCreateDirectoryAtPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory \"%@\" is not permitted", relativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] createDirectoryAtPath:absolutePath withIntermediateDirectories:NO attributes:nil error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed creating directory \"%@\"", relativePath]; @@ -228,12 +325,12 @@ - (GCDWebServerResponse*)performMKCOL:(GCDWebServerDataRequest*)request { NSString* creationDateHeader = [request.headers objectForKey:@"X-GCDWebServer-CreationDate"]; if (creationDateHeader) { NSDate* date = GCDWebServerParseISO8601(creationDateHeader); - if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:absolutePath error:&error]) { + if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate : date} ofItemAtPath:absolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed setting creation date for directory \"%@\"", relativePath]; } } #endif - + if ([self.delegate respondsToSelector:@selector(davServer:didCreateDirectoryAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate davServer:self didCreateDirectoryAtPath:absolutePath]; @@ -249,15 +346,15 @@ - (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL) return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader]; } } - + NSString* srcRelativePath = request.path; NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:srcRelativePath]; if (![self _checkSandboxedPath:srcAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; } - + NSString* dstRelativePath = [request.headers objectForKey:@"Destination"]; - NSRange range = [dstRelativePath rangeOfString:[request.headers objectForKey:@"Host"]]; + NSRange range = [dstRelativePath rangeOfString:(NSString*)[request.headers objectForKey:@"Host"]]; if ((dstRelativePath == nil) || (range.location == NSNotFound)) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Malformed 'Destination' header: %@", dstRelativePath]; } @@ -269,23 +366,23 @@ - (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL) if (![self _checkSandboxedPath:dstAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; } - + BOOL isDirectory; if (![[NSFileManager defaultManager] fileExistsAtPath:[dstAbsolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Invalid destination \"%@\"", dstRelativePath]; } - + NSString* itemName = [dstAbsolutePath lastPathComponent]; - if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"%@ to item name \"%@\" is not allowed", isMove ? @"Moving" : @"Copying", itemName]; } - + NSString* overwriteHeader = [request.headers objectForKey:@"Overwrite"]; BOOL existing = [[NSFileManager defaultManager] fileExistsAtPath:dstAbsolutePath]; if (existing && ((isMove && ![overwriteHeader isEqualToString:@"T"]) || (!isMove && [overwriteHeader isEqualToString:@"F"]))) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_PreconditionFailed message:@"Destination \"%@\" already exists", dstRelativePath]; } - + if (isMove) { if (![self shouldMoveItemFromPath:srcAbsolutePath toPath:dstAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath]; @@ -295,7 +392,7 @@ - (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL) return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Copying \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath]; } } - + NSError* error = nil; if (isMove) { [[NSFileManager defaultManager] removeItemAtPath:dstAbsolutePath error:NULL]; @@ -307,7 +404,7 @@ - (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL) return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden underlyingError:error message:@"Failed copying \"%@\" to \"%@\"", srcRelativePath, dstRelativePath]; } } - + if (isMove) { if ([self.delegate respondsToSelector:@selector(davServer:didMoveItemFromPath:toPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -321,7 +418,7 @@ - (GCDWebServerResponse*)performCOPY:(GCDWebServerRequest*)request isMove:(BOOL) }); } } - + return [GCDWebServerResponse responseWithStatusCode:(existing ? kGCDWebServerHTTPStatusCode_NoContent : kGCDWebServerHTTPStatusCode_Created)]; } @@ -350,7 +447,7 @@ - (void)_addPropertyResponseForItem:(NSString*)itemPath resource:(NSString*)reso [xmlString appendFormat:@"%@", escapedPath]; [xmlString appendString:@""]; [xmlString appendString:@""]; - + if (properties & kDAVProperty_ResourceType) { if (isDirectory) { [xmlString appendString:@""]; @@ -358,19 +455,19 @@ - (void)_addPropertyResponseForItem:(NSString*)itemPath resource:(NSString*)reso [xmlString appendString:@""]; } } - + if ((properties & kDAVProperty_CreationDate) && [attributes objectForKey:NSFileCreationDate]) { - [xmlString appendFormat:@"%@", GCDWebServerFormatISO8601([attributes fileCreationDate])]; + [xmlString appendFormat:@"%@", GCDWebServerFormatISO8601((NSDate*)[attributes fileCreationDate])]; } - + if ((properties & kDAVProperty_LastModified) && isFile && [attributes objectForKey:NSFileModificationDate]) { // Last modification date is not useful for directories as it changes implicitely and 'Last-Modified' header is not provided for directories anyway - [xmlString appendFormat:@"%@", GCDWebServerFormatRFC822([attributes fileModificationDate])]; + [xmlString appendFormat:@"%@", GCDWebServerFormatRFC822((NSDate*)[attributes fileModificationDate])]; } - + if ((properties & kDAVProperty_ContentLength) && !isDirectory && [attributes objectForKey:NSFileSize]) { [xmlString appendFormat:@"%llu", [attributes fileSize]]; } - + [xmlString appendString:@""]; [xmlString appendString:@"HTTP/1.1 200 OK"]; [xmlString appendString:@""]; @@ -392,7 +489,7 @@ - (GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request { } else { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Unsupported 'Depth' header: %@", depthHeader]; // TODO: Return 403 / propfind-finite-depth for "infinity" depth } - + DAVProperties properties = 0; if (request.data.length) { BOOL success = YES; @@ -433,19 +530,19 @@ - (GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request { } else { properties = kDAVAllProperties; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if (([itemName hasPrefix:@"."] && !_allowHiddenItems) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Retrieving properties for item name \"%@\" is not allowed", itemName]; } - + NSArray* items = nil; if (isDirectory) { NSError* error = nil; @@ -454,7 +551,7 @@ - (GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath]; } } - + NSMutableString* xmlString = [NSMutableString stringWithString:@""]; [xmlString appendString:@"\n"]; if (![relativePath hasPrefix:@"/"]) { @@ -466,14 +563,14 @@ - (GCDWebServerResponse*)performPROPFIND:(GCDWebServerDataRequest*)request { relativePath = [relativePath stringByAppendingString:@"/"]; } for (NSString* item in items) { - if (_allowHidden || ![item hasPrefix:@"."]) { + if (_allowHiddenItems || ![item hasPrefix:@"."]) { [self _addPropertyResponseForItem:[absolutePath stringByAppendingPathComponent:item] resource:[relativePath stringByAppendingString:item] properties:properties xmlString:xmlString]; } } } [xmlString appendString:@""]; - - GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding] + + GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:(NSData*)[xmlString dataUsingEncoding:NSUTF8StringEncoding] contentType:@"application/xml; charset=\"utf-8\""]; response.statusCode = kGCDWebServerHTTPStatusCode_MultiStatus; return response; @@ -483,14 +580,14 @@ - (GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request { if (!_IsMacFinder(request)) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"LOCK method only allowed for Mac Finder"]; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* depthHeader = [request.headers objectForKey:@"Depth"]; NSString* timeoutHeader = [request.headers objectForKey:@"Timeout"]; NSString* scope = nil; @@ -528,16 +625,16 @@ - (GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request { NSString* string = [[NSString alloc] initWithData:request.data encoding:NSUTF8StringEncoding]; return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Invalid DAV properties:\n%@", string]; } - + if (![scope isEqualToString:@"exclusive"] || ![type isEqualToString:@"write"] || ![depthHeader isEqualToString:@"0"]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking request \"%@/%@/%@\" for \"%@\" is not allowed", scope, type, depthHeader, relativePath]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking item name \"%@\" is not allowed", itemName]; } - + #ifdef __GCDWEBSERVER_ENABLE_TESTING__ NSString* lockTokenHeader = [request.headers objectForKey:@"X-GCDWebServer-LockToken"]; if (lockTokenHeader) { @@ -551,7 +648,7 @@ - (GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request { CFRelease(string); CFRelease(uuid); } - + NSMutableString* xmlString = [NSMutableString stringWithString:@""]; [xmlString appendString:@"\n"]; [xmlString appendString:@"\n\n"]; @@ -565,13 +662,13 @@ - (GCDWebServerResponse*)performLOCK:(GCDWebServerDataRequest*)request { [xmlString appendFormat:@"%@\n", timeoutHeader]; } [xmlString appendFormat:@"%@\n", token]; - NSString* lockroot = [@"http://" stringByAppendingString:[[request.headers objectForKey:@"Host"] stringByAppendingString:[@"/" stringByAppendingString:relativePath]]]; + NSString* lockroot = [@"http://" stringByAppendingString:[(NSString*)[request.headers objectForKey:@"Host"] stringByAppendingString:[@"/" stringByAppendingString:relativePath]]]; [xmlString appendFormat:@"%@\n", lockroot]; [xmlString appendString:@"\n\n"]; [xmlString appendString:@""]; - + [self logVerbose:@"WebDAV pretending to lock \"%@\"", relativePath]; - GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding] + GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:(NSData*)[xmlString dataUsingEncoding:NSUTF8StringEncoding] contentType:@"application/xml; charset=\"utf-8\""]; return response; } @@ -580,97 +677,30 @@ - (GCDWebServerResponse*)performUNLOCK:(GCDWebServerRequest*)request { if (!_IsMacFinder(request)) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_MethodNotAllowed message:@"UNLOCK method only allowed for Mac Finder"]; } - + NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* tokenHeader = [request.headers objectForKey:@"Lock-Token"]; if (!tokenHeader.length) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Missing 'Lock-Token' header"]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Unlocking item name \"%@\" is not allowed", itemName]; } - + [self logVerbose:@"WebDAV pretending to unlock \"%@\"", relativePath]; return [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NoContent]; } @end -@implementation GCDWebDAVServer - -@synthesize uploadDirectory=_uploadDirectory, allowedFileExtensions=_allowedExtensions, allowHiddenItems=_allowHidden; - -@dynamic delegate; - -- (instancetype)initWithUploadDirectory:(NSString*)path { - if ((self = [super init])) { - _uploadDirectory = [[path stringByStandardizingPath] copy]; - GCDWebDAVServer* __unsafe_unretained server = self; - - // 9.1 PROPFIND method - [self addDefaultHandlerForMethod:@"PROPFIND" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performPROPFIND:(GCDWebServerDataRequest*)request]; - }]; - - // 9.3 MKCOL Method - [self addDefaultHandlerForMethod:@"MKCOL" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performMKCOL:(GCDWebServerDataRequest*)request]; - }]; - - // 9.4 GET & HEAD methods - [self addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performGET:request]; - }]; - - // 9.6 DELETE method - [self addDefaultHandlerForMethod:@"DELETE" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performDELETE:request]; - }]; - - // 9.7 PUT method - [self addDefaultHandlerForMethod:@"PUT" requestClass:[GCDWebServerFileRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performPUT:(GCDWebServerFileRequest*)request]; - }]; - - // 9.8 COPY method - [self addDefaultHandlerForMethod:@"COPY" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performCOPY:request isMove:NO]; - }]; - - // 9.9 MOVE method - [self addDefaultHandlerForMethod:@"MOVE" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performCOPY:request isMove:YES]; - }]; - - // 9.10 LOCK method - [self addDefaultHandlerForMethod:@"LOCK" requestClass:[GCDWebServerDataRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performLOCK:(GCDWebServerDataRequest*)request]; - }]; - - // 9.11 UNLOCK method - [self addDefaultHandlerForMethod:@"UNLOCK" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performUNLOCK:request]; - }]; - - // 10.1 OPTIONS method / DAV Header - [self addDefaultHandlerForMethod:@"OPTIONS" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server performOPTIONS:request]; - }]; - - } - return self; -} - -@end - @implementation GCDWebDAVServer (Subclassing) - (BOOL)shouldUploadFileAtPath:(NSString*)path withTemporaryFile:(NSString*)tempPath { diff --git a/src/ios/GCDWebServer/GCDWebServer.podspec b/src/ios/GCDWebServer/GCDWebServer.podspec index 3fd4b9e..6ec0367 100644 --- a/src/ios/GCDWebServer/GCDWebServer.podspec +++ b/src/ios/GCDWebServer/GCDWebServer.podspec @@ -2,19 +2,19 @@ # http://guides.cocoapods.org/making/getting-setup-with-trunk.html # $ sudo gem update cocoapods # (optional) $ pod trunk register {email} {name} --description={computer} -# $ pod trunk push +# $ pod trunk --verbose push # DELETE THIS SECTION BEFORE PROCEEDING! Pod::Spec.new do |s| s.name = 'GCDWebServer' - s.version = '3.3.1' + s.version = '3.4' s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' } s.license = { :type => 'BSD', :file => 'LICENSE' } s.homepage = 'https://github.com/swisspol/GCDWebServer' s.summary = 'Lightweight GCD based HTTP server for OS X & iOS (includes web based uploader & WebDAV server)' s.source = { :git => 'https://github.com/swisspol/GCDWebServer.git', :tag => s.version.to_s } - s.ios.deployment_target = '5.0' + s.ios.deployment_target = '8.0' s.tvos.deployment_target = '9.0' s.osx.deployment_target = '10.7' s.requires_arc = true @@ -33,21 +33,39 @@ Pod::Spec.new do |s| cs.osx.framework = 'SystemConfiguration' end - s.subspec 'WebDAV' do |cs| + s.subspec "CocoaLumberjack" do |cs| cs.dependency 'GCDWebServer/Core' - cs.source_files = 'GCDWebDAVServer/*.{h,m}' - cs.requires_arc = true - cs.ios.library = 'xml2' - cs.tvos.library = 'xml2' - cs.osx.library = 'xml2' - cs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2' + cs.dependency 'CocoaLumberjack', '~> 3' end - s.subspec 'WebUploader' do |cs| - cs.dependency 'GCDWebServer/Core' - cs.source_files = 'GCDWebUploader/*.{h,m}' - cs.requires_arc = true - cs.resource = "GCDWebUploader/GCDWebUploader.bundle" + s.subspec 'WebDAV' do |cs| + cs.subspec "Core" do |ccs| + ccs.dependency 'GCDWebServer/Core' + ccs.source_files = 'GCDWebDAVServer/*.{h,m}' + ccs.requires_arc = true + ccs.ios.library = 'xml2' + ccs.tvos.library = 'xml2' + ccs.osx.library = 'xml2' + ccs.compiler_flags = '-I$(SDKROOT)/usr/include/libxml2' + end + + cs.subspec "CocoaLumberjack" do |cscl| + cscl.dependency 'GCDWebServer/WebDAV/Core' + cscl.dependency 'GCDWebServer/CocoaLumberjack' + end end + s.subspec 'WebUploader' do |cs| + cs.subspec "Core" do |ccs| + ccs.dependency 'GCDWebServer/Core' + ccs.source_files = 'GCDWebUploader/*.{h,m}' + ccs.requires_arc = true + ccs.resource = "GCDWebUploader/GCDWebUploader.bundle" + end + + cs.subspec "CocoaLumberjack" do |cscl| + cscl.dependency 'GCDWebServer/WebUploader/Core' + cscl.dependency 'GCDWebServer/CocoaLumberjack' + end + end end diff --git a/src/ios/GCDWebServer/GCDWebServer.xcodeproj/project.pbxproj b/src/ios/GCDWebServer/GCDWebServer.xcodeproj/project.pbxproj index 2977a13..9e380b1 100644 --- a/src/ios/GCDWebServer/GCDWebServer.xcodeproj/project.pbxproj +++ b/src/ios/GCDWebServer/GCDWebServer.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 48; objects = { /* Begin PBXAggregateTarget section */ @@ -465,8 +465,10 @@ E2DDD1B81BE6952F002CE867 /* tvOS Frameworks and Libraries */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); + indentWidth = 2; name = LittleCMS; sourceTree = ""; + tabWidth = 2; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; @@ -854,14 +856,13 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0830; TargetAttributes = { CEE28CD01AE004D800F4023C = { CreatedOnToolsVersion = 6.3; }; CEE28CEE1AE0051F00F4023C = { CreatedOnToolsVersion = 6.3; - DevelopmentTeam = 88W3E55T4B; }; E24039241BA09207000B7089 = { CreatedOnToolsVersion = 6.4; @@ -871,7 +872,6 @@ }; E2DDD1C61BE698A8002CE867 = { CreatedOnToolsVersion = 7.1; - DevelopmentTeam = 88W3E55T4B; }; E2DDD1F51BE69EE4002CE867 = { CreatedOnToolsVersion = 7.1; @@ -879,7 +879,7 @@ }; }; buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "GCDWebServer" */; - compatibilityVersion = "Xcode 3.2"; + compatibilityVersion = "Xcode 8.0"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -1208,7 +1208,7 @@ 1DEB928A08733DD80010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_VERSION_STRING = 3.3.1; + BUNDLE_VERSION_STRING = 3.3.4; CLANG_ENABLE_OBJC_ARC = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -1237,7 +1237,7 @@ "-Wno-cstring-format-directive", "-Wno-reserved-id-macro", "-Wno-cast-qual", - "-Wno-nullable-to-nonnull-conversion", + "-Wno-partial-availability", ); }; name = Debug; @@ -1245,7 +1245,7 @@ 1DEB928B08733DD80010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_VERSION_STRING = 3.3.1; + BUNDLE_VERSION_STRING = 3.3.4; CLANG_ENABLE_OBJC_ARC = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = __GCDWEBSERVER_ENABLE_TESTING__; @@ -1268,6 +1268,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = GCDWebServers; SDKROOT = macosx; + SKIP_INSTALL = YES; }; name = Debug; }; @@ -1283,13 +1284,13 @@ MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = GCDWebServers; SDKROOT = macosx; + SKIP_INSTALL = YES; }; name = Release; }; CEE28D031AE0052000F4023C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1298,15 +1299,14 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = GCDWebServers; - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; + SKIP_INSTALL = YES; }; name = Debug; }; CEE28D041AE0052000F4023C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1315,8 +1315,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = GCDWebServers; - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; + SKIP_INSTALL = YES; }; name = Release; }; @@ -1373,7 +1373,6 @@ E2DDD1901BE69404002CE867 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1381,8 +1380,8 @@ INFOPLIST_FILE = Frameworks/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = GCDWebServers; - PROVISIONING_PROFILE = ""; SDKROOT = appletvos; + SKIP_INSTALL = YES; TVOS_DEPLOYMENT_TARGET = 9.0; }; name = Debug; @@ -1390,7 +1389,6 @@ E2DDD1911BE69404002CE867 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1398,8 +1396,8 @@ INFOPLIST_FILE = Frameworks/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = GCDWebServers; - PROVISIONING_PROFILE = ""; SDKROOT = appletvos; + SKIP_INSTALL = YES; TVOS_DEPLOYMENT_TARGET = 9.0; }; name = Release; @@ -1407,7 +1405,6 @@ E2DDD1D91BE698A8002CE867 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; INFOPLIST_FILE = tvOS/Info.plist; PRODUCT_NAME = GCDWebServer; PROVISIONING_PROFILE = ""; @@ -1419,7 +1416,6 @@ E2DDD1DA1BE698A8002CE867 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; INFOPLIST_FILE = tvOS/Info.plist; PRODUCT_NAME = GCDWebServer; PROVISIONING_PROFILE = ""; @@ -1431,10 +1427,9 @@ E2DDD20B1BE69EE5002CE867 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_BITCODE = YES; INFOPLIST_FILE = iOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_NAME = GCDWebServer; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; @@ -1445,10 +1440,9 @@ E2DDD20C1BE69EE5002CE867 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; ENABLE_BITCODE = YES; INFOPLIST_FILE = iOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_NAME = GCDWebServer; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; diff --git a/src/ios/GCDWebServer/GCDWebServer.xcodeproj/xcshareddata/xcschemes/GCDWebServers (Mac).xcscheme b/src/ios/GCDWebServer/GCDWebServer.xcodeproj/xcshareddata/xcschemes/GCDWebServers (Mac).xcscheme index 0086ec7..563acb3 100644 --- a/src/ios/GCDWebServer/GCDWebServer.xcodeproj/xcshareddata/xcschemes/GCDWebServers (Mac).xcscheme +++ b/src/ios/GCDWebServer/GCDWebServer.xcodeproj/xcshareddata/xcschemes/GCDWebServers (Mac).xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES" + enableAddressSanitizer = "YES"> @@ -50,7 +51,6 @@ useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" - enableAddressSanitizer = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES"> @@ -63,11 +63,6 @@ - - @@ -62,11 +61,6 @@ - - @@ -62,11 +61,6 @@ - - delegate; +@property(nonatomic, weak, nullable) id delegate; /** * Returns YES if the server is currently running. @@ -306,7 +317,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * @warning This property is only valid if the server is running and Bonjour * registration has successfully completed, which can take up to a few seconds. */ -@property(nonatomic, readonly) NSString* bonjourName; +@property(nonatomic, readonly, nullable) NSString* bonjourName; /** * Returns the Bonjour service type used by the server. @@ -314,7 +325,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * @warning This property is only valid if the server is running and Bonjour * registration has successfully completed, which can take up to a few seconds. */ -@property(nonatomic, readonly) NSString* bonjourType; +@property(nonatomic, readonly, nullable) NSString* bonjourType; /** * This method is the designated initializer for the class. @@ -354,7 +365,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * Returns NO if the server failed to start and sets "error" argument if not NULL. */ -- (BOOL)startWithOptions:(NSDictionary*)options error:(NSError**)error; +- (BOOL)startWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error; /** * Stops the server and prevents it to accepts new HTTP requests. @@ -374,7 +385,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * @warning This property is only valid if the server is running. */ -@property(nonatomic, readonly) NSURL* serverURL; +@property(nonatomic, readonly, nullable) NSURL* serverURL; /** * Returns the server's Bonjour URL. @@ -384,7 +395,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * Also be aware this property will not automatically update if the Bonjour hostname * has been dynamically changed after the server started running (this should be rare). */ -@property(nonatomic, readonly) NSURL* bonjourServerURL; +@property(nonatomic, readonly, nullable) NSURL* bonjourServerURL; /** * Returns the server's public URL. @@ -392,7 +403,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * @warning This property is only valid if the server is running and NAT port * mapping is active. */ -@property(nonatomic, readonly) NSURL* publicServerURL; +@property(nonatomic, readonly, nullable) NSURL* publicServerURL; /** * Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS) @@ -409,7 +420,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * Returns NO if the server failed to start. */ -- (BOOL)startWithPort:(NSUInteger)port bonjourName:(NSString*)name; +- (BOOL)startWithPort:(NSUInteger)port bonjourName:(nullable NSString*)name; #if !TARGET_OS_IPHONE @@ -422,7 +433,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * @warning This method must be used from the main thread only. */ -- (BOOL)runWithPort:(NSUInteger)port bonjourName:(NSString*)name; +- (BOOL)runWithPort:(NSUInteger)port bonjourName:(nullable NSString*)name; /** * Runs the server synchronously using -startWithOptions: until a SIGTERM or @@ -433,7 +444,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * @warning This method must be used from the main thread only. */ -- (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error; +- (BOOL)runWithOptions:(nullable NSDictionary*)options error:(NSError** _Nullable)error; #endif @@ -489,7 +500,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * Adds a handler to the server to respond to incoming "GET" HTTP requests * with a specific case-insensitive path with in-memory data. */ -- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge; +- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(nullable NSString*)contentType cacheAge:(NSUInteger)cacheAge; /** * Adds a handler to the server to respond to incoming "GET" HTTP requests @@ -506,7 +517,7 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * The "indexFilename" argument allows to specify an "index" file name to use * when the request path corresponds to a directory. */ -- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; +- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(nullable NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; @end @@ -537,12 +548,10 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * GWS_LOG_INFO(...) * GWS_LOG_WARNING(...) * GWS_LOG_ERROR(...) - * GWS_LOG_EXCEPTION(__EXCEPTION__) * - * IMPORTANT: Except for GWS_LOG_EXCEPTION() which gets passed an NSException, - * these macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG() macro - * should not do anything unless the preprocessor constant "DEBUG" evaluates to - * non-zero. + * IMPORTANT: These macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG() + * macro should not do anything unless the preprocessor constant "DEBUG" evaluates + * to non-zero. * * The logging methods below send log messages to the same logging facility * used by GCDWebServer. They can be used for consistency wherever you interact @@ -562,34 +571,28 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * INFO = 2 * WARNING = 3 * ERROR = 4 - * EXCEPTION = 5 */ + (void)setLogLevel:(int)level; /** * Logs a message to the logging facility at the VERBOSE level. */ -- (void)logVerbose:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); +- (void)logVerbose:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); /** * Logs a message to the logging facility at the INFO level. */ -- (void)logInfo:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); +- (void)logInfo:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); /** * Logs a message to the logging facility at the WARNING level. */ -- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); +- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); /** * Logs a message to the logging facility at the ERROR level. */ -- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); - -/** - * Logs an exception to the logging facility at the EXCEPTION level. - */ -- (void)logException:(NSException*)exception; +- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1, 2); @end @@ -611,8 +614,10 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess; * * Returns the number of failed tests or -1 if server failed to start. */ -- (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path; +- (NSInteger)runTestsWithOptions:(nullable NSDictionary*)options inDirectory:(NSString*)path; @end #endif + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServer.m b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServer.m index 7a1d0d1..837c083 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServer.m +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServer.m @@ -63,6 +63,7 @@ NSString* const GCDWebServerOption_ConnectionClass = @"ConnectionClass"; NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET = @"AutomaticallyMapHEADToGET"; NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval = @"ConnectedStateCoalescingInterval"; +NSString* const GCDWebServerOption_DispatchQueuePriority = @"DispatchQueuePriority"; #if TARGET_OS_IPHONE NSString* const GCDWebServerOption_AutomaticallySuspendInBackground = @"AutomaticallySuspendInBackground"; #endif @@ -91,7 +92,7 @@ #ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__ void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) { - static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR", "EXCEPTION"}; + static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR"}; static int enableLogging = -1; if (enableLogging < 0) { enableLogging = (isatty(STDERR_FILENO) ? 1 : 0); @@ -131,18 +132,9 @@ static void _ExecuteMainThreadRunLoopSources() { #endif -@interface GCDWebServerHandler () { -@private - GCDWebServerMatchBlock _matchBlock; - GCDWebServerAsyncProcessBlock _asyncProcessBlock; -} -@end - @implementation GCDWebServerHandler -@synthesize matchBlock=_matchBlock, asyncProcessBlock=_asyncProcessBlock; - -- (id)initWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock { +- (instancetype)initWithMatchBlock:(GCDWebServerMatchBlock _Nonnull)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock _Nonnull)processBlock { if ((self = [super init])) { _matchBlock = [matchBlock copy]; _asyncProcessBlock = [processBlock copy]; @@ -152,25 +144,19 @@ - (id)initWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(G @end -@interface GCDWebServer () { -@private - id __unsafe_unretained _delegate; +@implementation GCDWebServer { dispatch_queue_t _syncQueue; dispatch_group_t _sourceGroup; NSMutableArray* _handlers; NSInteger _activeConnections; // Accessed through _syncQueue only BOOL _connected; // Accessed on main thread only CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only - + NSDictionary* _options; - NSString* _serverName; - NSString* _authenticationRealm; NSMutableDictionary* _authenticationBasicAccounts; NSMutableDictionary* _authenticationDigestAccounts; Class _connectionClass; - BOOL _mapHEADToGET; CFTimeInterval _disconnectDelay; - NSUInteger _port; dispatch_source_t _source4; dispatch_source_t _source6; CFNetServiceRef _registrationService; @@ -189,13 +175,6 @@ @interface GCDWebServer () { BOOL _recording; #endif } -@end - -@implementation GCDWebServer - -@synthesize delegate=_delegate, handlers=_handlers, port=_port, serverName=_serverName, authenticationRealm=_authenticationRealm, - authenticationBasicAccounts=_authenticationBasicAccounts, authenticationDigestAccounts=_authenticationDigestAccounts, - shouldAutomaticallyMapHEADToGET=_mapHEADToGET; + (void)initialize { GCDWebServerInitializeFunctions(); @@ -218,7 +197,7 @@ - (void)dealloc { GWS_DCHECK(_activeConnections == 0); GWS_DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source GWS_DCHECK(_disconnectTimer == NULL); // The server can never be dealloc'ed while the disconnect timer is pending because of the retain-cycle - + #if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE dispatch_release(_sourceGroup); dispatch_release(_syncQueue); @@ -233,10 +212,10 @@ - (void)_startBackgroundTask { if (_backgroundTask == UIBackgroundTaskInvalid) { GWS_LOG_DEBUG(@"Did start background task"); _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - + GWS_LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]); [self _endBackgroundTask]; - + }]; } else { GWS_DNOT_REACHED(); @@ -251,13 +230,13 @@ - (void)_didConnect { GWS_DCHECK(_connected == NO); _connected = YES; GWS_LOG_DEBUG(@"Did connect"); - + #if TARGET_OS_IPHONE if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) { [self _startBackgroundTask]; } #endif - + if ([_delegate respondsToSelector:@selector(webServerDidConnect:)]) { [_delegate webServerDidConnect:self]; } @@ -265,7 +244,7 @@ - (void)_didConnect { - (void)willStartConnection:(GCDWebServerConnection*)connection { dispatch_sync(_syncQueue, ^{ - + GWS_DCHECK(_activeConnections >= 0); if (_activeConnections == 0) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -280,7 +259,7 @@ - (void)willStartConnection:(GCDWebServerConnection*)connection { }); } _activeConnections += 1; - + }); } @@ -307,11 +286,11 @@ - (void)_didDisconnect { GWS_DCHECK(_connected == YES); _connected = NO; GWS_LOG_DEBUG(@"Did disconnect"); - + #if TARGET_OS_IPHONE [self _endBackgroundTask]; #endif - + if ([_delegate respondsToSelector:@selector(webServerDidDisconnect:)]) { [_delegate webServerDidDisconnect:self]; } @@ -354,9 +333,10 @@ - (NSString*)bonjourType { } - (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)processBlock { - [self addHandlerWithMatchBlock:matchBlock asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(processBlock(request)); - }]; + [self addHandlerWithMatchBlock:matchBlock + asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { + completionBlock(processBlock(request)); + }]; } - (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock { @@ -462,7 +442,7 @@ - (int)_createListeningSocket:(BOOL)useIPv6 if (listeningSocket > 0) { int yes = 1; setsockopt(listeningSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - + if (bind(listeningSocket, address, length) == 0) { if (listen(listeningSocket, (int)maxPendingConnections) == 0) { GWS_LOG_DEBUG(@"Did open %s listening socket %i", useIPv6 ? "IPv6" : "IPv4", listeningSocket); @@ -481,7 +461,7 @@ - (int)_createListeningSocket:(BOOL)useIPv6 GWS_LOG_ERROR(@"Failed binding %s listening socket: %s (%i)", useIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); close(listeningSocket); } - + } else { if (error) { *error = GCDWebServerMakePosixError(errno); @@ -493,9 +473,9 @@ - (int)_createListeningSocket:(BOOL)useIPv6 - (dispatch_source_t)_createDispatchSourceWithListeningSocket:(int)listeningSocket isIPv6:(BOOL)isIPv6 { dispatch_group_enter(_sourceGroup); - dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, kGCDWebServerGCDQueue); + dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, listeningSocket, 0, dispatch_get_global_queue(_dispatchQueuePriority, 0)); dispatch_source_set_cancel_handler(source, ^{ - + @autoreleasepool { int result = close(listeningSocket); if (result != 0) { @@ -505,17 +485,17 @@ - (dispatch_source_t)_createDispatchSourceWithListeningSocket:(int)listeningSock } } dispatch_group_leave(_sourceGroup); - + }); dispatch_source_set_event_handler(source, ^{ - + @autoreleasepool { struct sockaddr_storage remoteSockAddr; socklen_t remoteAddrLen = sizeof(remoteSockAddr); int socket = accept(listeningSocket, (struct sockaddr*)&remoteSockAddr, &remoteAddrLen); if (socket > 0) { NSData* remoteAddress = [NSData dataWithBytes:&remoteSockAddr length:remoteAddrLen]; - + struct sockaddr_storage localSockAddr; socklen_t localAddrLen = sizeof(localSockAddr); NSData* localAddress = nil; @@ -525,28 +505,28 @@ - (dispatch_source_t)_createDispatchSourceWithListeningSocket:(int)listeningSock } else { GWS_DNOT_REACHED(); } - + int noSigPipe = 1; setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &noSigPipe, sizeof(noSigPipe)); // Make sure this socket cannot generate SIG_PIPE - + GCDWebServerConnection* connection = [[_connectionClass alloc] initWithServer:self localAddress:localAddress remoteAddress:remoteAddress socket:socket]; // Connection will automatically retain itself while opened [connection self]; // Prevent compiler from complaining about unused variable / useless statement } else { GWS_LOG_ERROR(@"Failed accepting %s socket: %s (%i)", isIPv6 ? "IPv6" : "IPv4", strerror(errno), errno); } } - + }); return source; } - (BOOL)_start:(NSError**)error { GWS_DCHECK(_source4 == NULL); - + NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue]; BOOL bindToLocalhost = [_GetOption(_options, GCDWebServerOption_BindToLocalhost, @NO) boolValue]; NSUInteger maxPendingConnections = [_GetOption(_options, GCDWebServerOption_MaxPendingConnections, @16) unsignedIntegerValue]; - + struct sockaddr_in addr4; bzero(&addr4, sizeof(addr4)); addr4.sin_len = sizeof(addr4); @@ -566,7 +546,7 @@ - (BOOL)_start:(NSError**)error { GWS_LOG_ERROR(@"Failed retrieving socket address: %s (%i)", strerror(errno), errno); } } - + struct sockaddr_in6 addr6; bzero(&addr6, sizeof(addr6)); addr6.sin6_len = sizeof(addr6); @@ -578,7 +558,7 @@ - (BOOL)_start:(NSError**)error { close(listeningSocket4); return NO; } - + _serverName = [_GetOption(_options, GCDWebServerOption_ServerName, NSStringFromClass([self class])) copy]; NSString* authenticationMethod = _GetOption(_options, GCDWebServerOption_AuthenticationMethod, nil); if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_Basic]) { @@ -597,26 +577,27 @@ - (BOOL)_start:(NSError**)error { }]; } _connectionClass = _GetOption(_options, GCDWebServerOption_ConnectionClass, [GCDWebServerConnection class]); - _mapHEADToGET = [_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue]; + _shouldAutomaticallyMapHEADToGET = [_GetOption(_options, GCDWebServerOption_AutomaticallyMapHEADToGET, @YES) boolValue]; _disconnectDelay = [_GetOption(_options, GCDWebServerOption_ConnectedStateCoalescingInterval, @1.0) doubleValue]; - + _dispatchQueuePriority = [_GetOption(_options, GCDWebServerOption_DispatchQueuePriority, @(DISPATCH_QUEUE_PRIORITY_DEFAULT)) longValue]; + _source4 = [self _createDispatchSourceWithListeningSocket:listeningSocket4 isIPv6:NO]; _source6 = [self _createDispatchSourceWithListeningSocket:listeningSocket6 isIPv6:YES]; _port = port; _bindToLocalhost = bindToLocalhost; - + NSString* bonjourName = _GetOption(_options, GCDWebServerOption_BonjourName, nil); NSString* bonjourType = _GetOption(_options, GCDWebServerOption_BonjourType, @"_http._tcp"); if (bonjourName) { _registrationService = CFNetServiceCreate(kCFAllocatorDefault, CFSTR("local."), (__bridge CFStringRef)bonjourType, (__bridge CFStringRef)(bonjourName.length ? bonjourName : _serverName), (SInt32)_port); if (_registrationService) { CFNetServiceClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL}; - + CFNetServiceSetClient(_registrationService, _NetServiceRegisterCallBack, &context); CFNetServiceScheduleWithRunLoop(_registrationService, CFRunLoopGetMain(), kCFRunLoopCommonModes); CFStreamError streamError = {0}; CFNetServiceRegisterWithOptions(_registrationService, 0, &streamError); - + _resolutionService = CFNetServiceCreateCopy(kCFAllocatorDefault, _registrationService); if (_resolutionService) { CFNetServiceSetClient(_resolutionService, _NetServiceResolveCallBack, &context); @@ -628,7 +609,7 @@ - (BOOL)_start:(NSError**)error { GWS_LOG_ERROR(@"Failed creating CFNetService for registration"); } } - + if ([_GetOption(_options, GCDWebServerOption_RequestNATPortMapping, @NO) boolValue]) { DNSServiceErrorType status = DNSServiceNATPortMappingCreate(&_dnsService, 0, 0, kDNSServiceProtocol_TCP, htons(port), htons(port), 0, _DNSServiceCallBack, (__bridge void*)self); if (status == kDNSServiceErr_NoError) { @@ -651,7 +632,7 @@ - (BOOL)_start:(NSError**)error { GWS_LOG_ERROR(@"Failed creating NAT port mapping (%i)", status); } } - + dispatch_resume(_source4); dispatch_resume(_source6); GWS_LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL); @@ -660,13 +641,13 @@ - (BOOL)_start:(NSError**)error { [_delegate webServerDidStart:self]; }); } - + return YES; } - (void)_stop { GWS_DCHECK(_source4 != NULL); - + if (_dnsService) { _dnsAddress = nil; _dnsPort = 0; @@ -682,7 +663,7 @@ - (void)_stop { DNSServiceRefDeallocate(_dnsService); _dnsService = NULL; } - + if (_registrationService) { if (_resolutionService) { CFNetServiceUnscheduleFromRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes); @@ -697,7 +678,7 @@ - (void)_stop { CFRelease(_registrationService); _registrationService = NULL; } - + dispatch_source_cancel(_source6); dispatch_source_cancel(_source4); dispatch_group_wait(_sourceGroup, DISPATCH_TIME_FOREVER); // Wait until the cancellation handlers have been called which guarantees the listening sockets are closed @@ -711,12 +692,12 @@ - (void)_stop { _source4 = NULL; _port = 0; _bindToLocalhost = NO; - + _serverName = nil; _authenticationRealm = nil; _authenticationBasicAccounts = nil; _authenticationDigestAccounts = nil; - + dispatch_async(dispatch_get_main_queue(), ^{ if (_disconnectTimer) { CFRunLoopTimerInvalidate(_disconnectTimer); @@ -725,7 +706,7 @@ - (void)_stop { [self _didDisconnect]; } }); - + GWS_LOG_INFO(@"%@ stopped", [self class]); if ([_delegate respondsToSelector:@selector(webServerDidStop:)]) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -893,32 +874,38 @@ - (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error { @implementation GCDWebServer (Handlers) - (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addDefaultHandlerForMethod:method requestClass:aClass asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; + [self addDefaultHandlerForMethod:method + requestClass:aClass + asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { + completionBlock(block(request)); + }]; } - (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { - [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - + [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { + if (![requestMethod isEqualToString:method]) { return nil; } return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } asyncProcessBlock:block]; + + } + asyncProcessBlock:block]; } - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addHandlerForMethod:method path:path requestClass:aClass asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; + [self addHandlerForMethod:method + path:path + requestClass:aClass + asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { + completionBlock(block(request)); + }]; } - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { if ([path hasPrefix:@"/"] && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) { - [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - + [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { + if (![requestMethod isEqualToString:method]) { return nil; } @@ -926,24 +913,28 @@ - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass: return nil; } return [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } asyncProcessBlock:block]; + + } + asyncProcessBlock:block]; } else { GWS_DNOT_REACHED(); } } - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { - [self addHandlerForMethod:method pathRegex:regex requestClass:aClass asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - completionBlock(block(request)); - }]; + [self addHandlerForMethod:method + pathRegex:regex + requestClass:aClass + asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { + completionBlock(block(request)); + }]; } - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass asyncProcessBlock:(GCDWebServerAsyncProcessBlock)block { NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:NULL]; if (expression && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) { - [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - + [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { + if (![requestMethod isEqualToString:method]) { return nil; } @@ -957,15 +948,21 @@ - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex request for (NSTextCheckingResult* result in matches) { // Start at 1; index 0 is the whole string for (NSUInteger i = 1; i < result.numberOfRanges; i++) { - [captures addObject:[urlPath substringWithRange:[result rangeAtIndex:i]]]; + NSRange range = [result rangeAtIndex:i]; + // range is {NSNotFound, 0} "if one of the capture groups did not participate in this particular match" + // see discussion in -[NSRegularExpression firstMatchInString:options:range:] + if (range.location != NSNotFound) { + [captures addObject:[urlPath substringWithRange:range]]; + } } } GCDWebServerRequest* request = [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; [request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures]; return request; - - } asyncProcessBlock:block]; + + } + asyncProcessBlock:block]; } else { GWS_DNOT_REACHED(); } @@ -976,29 +973,35 @@ - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex request @implementation GCDWebServer (GETHandlers) - (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge { - [self addHandlerForMethod:@"GET" path:path requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType]; - response.cacheControlMaxAge = cacheAge; - return response; - - }]; + [self addHandlerForMethod:@"GET" + path:path + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType]; + response.cacheControlMaxAge = cacheAge; + return response; + + }]; } - (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { - [self addHandlerForMethod:@"GET" path:path requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = nil; - if (allowRangeRequests) { - response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment]; - [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; - } else { - response = [GCDWebServerFileResponse responseWithFile:filePath isAttachment:isAttachment]; - } - response.cacheControlMaxAge = cacheAge; - return response; - - }]; + [self addHandlerForMethod:@"GET" + path:path + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + GCDWebServerResponse* response = nil; + if (allowRangeRequests) { + response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment]; + [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; + } else { + response = [GCDWebServerFileResponse responseWithFile:filePath isAttachment:isAttachment]; + } + response.cacheControlMaxAge = cacheAge; + return response; + + }]; } - (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { @@ -1034,8 +1037,8 @@ - (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { - (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) { GCDWebServer* __unsafe_unretained server = self; - [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - + [self addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { + if (![requestMethod isEqualToString:@"GET"]) { return nil; } @@ -1043,39 +1046,40 @@ - (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)di return nil; } return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]; - - } processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = nil; - NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; - NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType]; - if (fileType) { - if ([fileType isEqualToString:NSFileTypeDirectory]) { - if (indexFilename) { - NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; - NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType]; - if ([indexType isEqualToString:NSFileTypeRegular]) { - return [GCDWebServerFileResponse responseWithFile:indexPath]; + + } + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + GCDWebServerResponse* response = nil; + NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; + NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType]; + if (fileType) { + if ([fileType isEqualToString:NSFileTypeDirectory]) { + if (indexFilename) { + NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; + NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType]; + if ([indexType isEqualToString:NSFileTypeRegular]) { + return [GCDWebServerFileResponse responseWithFile:indexPath]; + } + } + response = [server _responseWithContentsOfDirectory:filePath]; + } else if ([fileType isEqualToString:NSFileTypeRegular]) { + if (allowRangeRequests) { + response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange]; + [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; + } else { + response = [GCDWebServerFileResponse responseWithFile:filePath]; + } } } - response = [server _responseWithContentsOfDirectory:filePath]; - } else if ([fileType isEqualToString:NSFileTypeRegular]) { - if (allowRangeRequests) { - response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange]; - [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; + if (response) { + response.cacheControlMaxAge = cacheAge; } else { - response = [GCDWebServerFileResponse responseWithFile:filePath]; + response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound]; } - } - } - if (response) { - response.cacheControlMaxAge = cacheAge; - } else { - response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound]; - } - return response; - - }]; + return response; + + }]; } else { GWS_DNOT_REACHED(); } @@ -1123,10 +1127,6 @@ - (void)logError:(NSString*)format, ... { va_end(arguments); } -- (void)logException:(NSException*)exception { - GWS_LOG_EXCEPTION(exception); -} - @end #ifdef __GCDWEBSERVER_ENABLE_TESTING__ @@ -1200,11 +1200,11 @@ static void _LogResult(NSString* format, ...) { - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path { GWS_DCHECK([NSThread isMainThread]); - NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs + NSArray* ignoredHeaders = @[ @"Date", @"Etag" ]; // Dates are always different by definition and ETags depend on file system node IDs NSInteger result = -1; if ([self startWithOptions:options error:NULL]) { _ExecuteMainThreadRunLoopSources(); - + result = 0; NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL]; for (NSString* requestFile in files) { @@ -1226,19 +1226,19 @@ - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)p if ([responseFile hasPrefix:prefix] && [responseFile hasSuffix:@".response"]) { NSData* responseData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:responseFile]]; if (responseData) { - CFHTTPMessageRef expectedResponse = _CreateHTTPMessageFromData(responseData, NO); + CFHTTPMessageRef expectedResponse = _CreateHTTPMessageFromData(responseData, NO); if (expectedResponse) { CFHTTPMessageRef actualResponse = _CreateHTTPMessageFromPerformingRequest(requestData, self.port); if (actualResponse) { success = YES; - + CFIndex expectedStatusCode = CFHTTPMessageGetResponseStatusCode(expectedResponse); CFIndex actualStatusCode = CFHTTPMessageGetResponseStatusCode(actualResponse); if (actualStatusCode != expectedStatusCode) { _LogResult(@" Status code not matching:\n Expected: %i\n Actual: %i", (int)expectedStatusCode, (int)actualStatusCode); success = NO; } - + NSDictionary* expectedHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(expectedResponse)); NSDictionary* actualHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(actualResponse)); for (NSString* expectedHeader in expectedHeaders) { @@ -1258,7 +1258,7 @@ - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)p success = NO; } } - + NSString* expectedContentLength = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(expectedResponse, CFSTR("Content-Length"))); NSData* expectedBody = CFBridgingRelease(CFHTTPMessageCopyBody(expectedResponse)); NSString* actualContentLength = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(actualResponse, CFSTR("Content-Length"))); @@ -1271,20 +1271,20 @@ - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)p success = NO; #if !TARGET_OS_IPHONE #if DEBUG - if (GCDWebServerIsTextContentType([expectedHeaders objectForKey:@"Content-Type"])) { - NSString* expectedPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; - NSString* actualPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; + if (GCDWebServerIsTextContentType((NSString*)[expectedHeaders objectForKey:@"Content-Type"])) { + NSString* expectedPath = [NSTemporaryDirectory() stringByAppendingPathComponent:(NSString*)[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; + NSString* actualPath = [NSTemporaryDirectory() stringByAppendingPathComponent:(NSString*)[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]]; if ([expectedBody writeToFile:expectedPath atomically:YES] && [actualBody writeToFile:actualPath atomically:YES]) { NSTask* task = [[NSTask alloc] init]; [task setLaunchPath:@"/usr/bin/opendiff"]; - [task setArguments:@[expectedPath, actualPath]]; + [task setArguments:@[ expectedPath, actualPath ]]; [task launch]; } } #endif #endif } - + CFRelease(actualResponse); } CFRelease(expectedResponse); @@ -1307,9 +1307,9 @@ - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)p } _ExecuteMainThreadRunLoopSources(); } - + [self stop]; - + _ExecuteMainThreadRunLoopSources(); } return result; diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h index d353c8b..420d12a 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.h @@ -27,6 +27,8 @@ #import "GCDWebServer.h" +NS_ASSUME_NONNULL_BEGIN + @class GCDWebServerHandler; /** @@ -139,7 +141,7 @@ * The default implementation checks for HTTP authentication if applicable * and returns a barebone 401 status code response if authentication failed. */ -- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request; /** * Assuming a valid HTTP request was received and -preflightRequest: returned nil, @@ -169,7 +171,7 @@ * @warning If the request was invalid (e.g. the HTTP headers were malformed), * the "request" argument will be nil. */ -- (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode; +- (void)abortRequest:(nullable GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode; /** * Called when the connection is closed. @@ -177,3 +179,5 @@ - (void)close; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m index d6c369e..b59f3f4 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerConnection.m @@ -57,23 +57,34 @@ static int32_t _connectionCounter = 0; #endif -@interface GCDWebServerConnection () { -@private - GCDWebServer* _server; - NSData* _localAddress; - NSData* _remoteAddress; +NS_ASSUME_NONNULL_BEGIN + +@interface GCDWebServerConnection (Read) +- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block; +- (void)readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block; +- (void)readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block; +- (void)readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block; +@end + +@interface GCDWebServerConnection (Write) +- (void)writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block; +- (void)writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block; +- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block; +@end + +NS_ASSUME_NONNULL_END + +@implementation GCDWebServerConnection { CFSocketNativeHandle _socket; - NSUInteger _bytesRead; - NSUInteger _bytesWritten; BOOL _virtualHEAD; - + CFHTTPMessageRef _requestMessage; GCDWebServerRequest* _request; GCDWebServerHandler* _handler; CFHTTPMessageRef _responseMessage; GCDWebServerResponse* _response; NSInteger _statusCode; - + BOOL _opened; #ifdef __GCDWEBSERVER_ENABLE_TESTING__ NSUInteger _connectionIndex; @@ -83,258 +94,6 @@ @interface GCDWebServerConnection () { int _responseFD; #endif } -@end - -@implementation GCDWebServerConnection (Read) - -- (void)_readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block { - dispatch_read(_socket, length, kGCDWebServerGCDQueue, ^(dispatch_data_t buffer, int error) { - - @autoreleasepool { - if (error == 0) { - size_t size = dispatch_data_get_size(buffer); - if (size > 0) { - NSUInteger originalLength = data.length; - dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) { - [data appendBytes:chunkBytes length:chunkSize]; - return true; - }); - [self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)]; - block(YES); - } else { - if (_bytesRead > 0) { - GWS_LOG_ERROR(@"No more data available on socket %i", _socket); - } else { - GWS_LOG_WARNING(@"No data received from socket %i", _socket); - } - block(NO); - } - } else { - GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error); - block(NO); - } - } - - }); -} - -- (void)_readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block { - GWS_DCHECK(_requestMessage); - [self _readData:headersData withLength:NSUIntegerMax completionBlock:^(BOOL success) { - - if (success) { - NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)]; - if (range.location == NSNotFound) { - [self _readHeaders:headersData withCompletionBlock:block]; - } else { - NSUInteger length = range.location + range.length; - if (CFHTTPMessageAppendBytes(_requestMessage, headersData.bytes, length)) { - if (CFHTTPMessageIsHeaderComplete(_requestMessage)) { - block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]); - } else { - GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket); - block(nil); - } - } else { - GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket); - block(nil); - } - } - } else { - block(nil); - } - - }]; -} - -- (void)_readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block { - GWS_DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]); - NSMutableData* bodyData = [[NSMutableData alloc] initWithCapacity:kBodyReadCapacity]; - [self _readData:bodyData withLength:length completionBlock:^(BOOL success) { - - if (success) { - if (bodyData.length <= length) { - NSError* error = nil; - if ([_request performWriteData:bodyData error:&error]) { - NSUInteger remainingLength = length - bodyData.length; - if (remainingLength) { - [self _readBodyWithRemainingLength:remainingLength completionBlock:block]; - } else { - block(YES); - } - } else { - GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); - block(NO); - } - } else { - GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket); - block(NO); - GWS_DNOT_REACHED(); - } - } else { - block(NO); - } - - }]; -} - -static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { - char buffer[size + 1]; - bcopy(bytes, buffer, size); - buffer[size] = 0; - char* end = NULL; - long result = strtol(buffer, &end, 16); - return ((end != NULL) && (*end == 0) && (result >= 0) ? result : NSNotFound); -} - -- (void)_readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block { - GWS_DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]); - - while (1) { - NSRange range = [chunkData rangeOfData:_CRLFData options:0 range:NSMakeRange(0, chunkData.length)]; - if (range.location == NSNotFound) { - break; - } - NSRange extensionRange = [chunkData rangeOfData:[NSData dataWithBytes:";" length:1] options:0 range:NSMakeRange(0, range.location)]; // Ignore chunk extensions - NSUInteger length = _ScanHexNumber((char*)chunkData.bytes, extensionRange.location != NSNotFound ? extensionRange.location : range.location); - if (length != NSNotFound) { - if (length) { - if (chunkData.length < range.location + range.length + length + 2) { - break; - } - const char* ptr = (char*)chunkData.bytes + range.location + range.length + length; - if ((*ptr == '\r') && (*(ptr + 1) == '\n')) { - NSError* error = nil; - if ([_request performWriteData:[chunkData subdataWithRange:NSMakeRange(range.location + range.length, length)] error:&error]) { - [chunkData replaceBytesInRange:NSMakeRange(0, range.location + range.length + length + 2) withBytes:NULL length:0]; - } else { - GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); - block(NO); - return; - } - } else { - GWS_LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket); - block(NO); - return; - } - } else { - NSRange trailerRange = [chunkData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(range.location, chunkData.length - range.location)]; // Ignore trailers - if (trailerRange.location != NSNotFound) { - block(YES); - return; - } - } - } else { - GWS_LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket); - block(NO); - return; - } - } - - [self _readData:chunkData withLength:NSUIntegerMax completionBlock:^(BOOL success) { - - if (success) { - [self _readNextBodyChunk:chunkData completionBlock:block]; - } else { - block(NO); - } - - }]; -} - -@end - -@implementation GCDWebServerConnection (Write) - -- (void)_writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block { - dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, kGCDWebServerGCDQueue, ^{ - [data self]; // Keeps ARC from releasing data too early - }); - dispatch_write(_socket, buffer, kGCDWebServerGCDQueue, ^(dispatch_data_t remainingData, int error) { - - @autoreleasepool { - if (error == 0) { - GWS_DCHECK(remainingData == NULL); - [self didWriteBytes:data.bytes length:data.length]; - block(YES); - } else { - GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error); - block(NO); - } - } - - }); -#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE - dispatch_release(buffer); -#endif -} - -- (void)_writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block { - GWS_DCHECK(_responseMessage); - CFDataRef data = CFHTTPMessageCopySerializedMessage(_responseMessage); - [self _writeData:(__bridge NSData*)data withCompletionBlock:block]; - CFRelease(data); -} - -- (void)_writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block { - GWS_DCHECK([_response hasBody]); - [_response performReadDataWithCompletion:^(NSData* data, NSError* error) { - - if (data) { - if (data.length) { - if (_response.usesChunkedTransferEncoding) { - const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String]; - size_t hexLength = strlen(hexString); - NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)]; - if (chunk == nil) { - GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error); - block(NO); - return; - } - char* ptr = (char*)[(NSMutableData*)chunk mutableBytes]; - bcopy(hexString, ptr, hexLength); - ptr += hexLength; - *ptr++ = '\r'; - *ptr++ = '\n'; - bcopy(data.bytes, ptr, data.length); - ptr += data.length; - *ptr++ = '\r'; - *ptr = '\n'; - data = chunk; - } - [self _writeData:data withCompletionBlock:^(BOOL success) { - - if (success) { - [self _writeBodyWithCompletionBlock:block]; - } else { - block(NO); - } - - }]; - } else { - if (_response.usesChunkedTransferEncoding) { - [self _writeData:_lastChunkData withCompletionBlock:^(BOOL success) { - - block(success); - - }]; - } else { - block(YES); - } - } - } else { - GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error); - block(NO); - } - - }]; -} - -@end - -@implementation GCDWebServerConnection - -@synthesize server=_server, localAddressData=_localAddress, remoteAddressData=_remoteAddress, totalBytesRead=_bytesRead, totalBytesWritten=_bytesWritten; + (void)initialize { if (_CRLFData == nil) { @@ -362,7 +121,7 @@ + (void)initialize { } - (BOOL)isUsingIPv6 { - const struct sockaddr* localSockAddr = _localAddress.bytes; + const struct sockaddr* localSockAddr = _localAddressData.bytes; return (localSockAddr->sa_family == AF_INET6); } @@ -376,14 +135,15 @@ - (void)_initializeResponseHeadersWithStatusCode:(NSInteger)statusCode { - (void)_startProcessingRequest { GWS_DCHECK(_responseMessage == NULL); - + GCDWebServerResponse* preflightResponse = [self preflightRequest:_request]; if (preflightResponse) { [self _finishProcessingRequest:preflightResponse]; } else { - [self processRequest:_request completion:^(GCDWebServerResponse* processResponse) { - [self _finishProcessingRequest:processResponse]; - }]; + [self processRequest:_request + completion:^(GCDWebServerResponse* processResponse) { + [self _finishProcessingRequest:processResponse]; + }]; } } @@ -391,7 +151,7 @@ - (void)_startProcessingRequest { - (void)_finishProcessingRequest:(GCDWebServerResponse*)response { GWS_DCHECK(_responseMessage == NULL); BOOL hasBody = NO; - + if (response) { response = [self overrideResponse:response forRequest:_request]; } @@ -407,11 +167,11 @@ - (void)_finishProcessingRequest:(GCDWebServerResponse*)response { _response = response; } } - + if (_response) { [self _initializeResponseHeadersWithStatusCode:_response.statusCode]; if (_response.lastModifiedDate) { - CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (__bridge CFStringRef)GCDWebServerFormatRFC822(_response.lastModifiedDate)); + CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (__bridge CFStringRef)GCDWebServerFormatRFC822((NSDate*)_response.lastModifiedDate)); } if (_response.eTag) { CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("ETag"), (__bridge CFStringRef)_response.eTag); @@ -435,25 +195,24 @@ - (void)_finishProcessingRequest:(GCDWebServerResponse*)response { [_response.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) { CFHTTPMessageSetHeaderFieldValue(_responseMessage, (__bridge CFStringRef)key, (__bridge CFStringRef)obj); }]; - [self _writeHeadersWithCompletionBlock:^(BOOL success) { - + [self writeHeadersWithCompletionBlock:^(BOOL success) { + if (success) { if (hasBody) { - [self _writeBodyWithCompletionBlock:^(BOOL successInner) { - + [self writeBodyWithCompletionBlock:^(BOOL successInner) { + [_response performClose]; // TODO: There's nothing we can do on failure as headers have already been sent - + }]; } } else if (hasBody) { [_response performClose]; } - + }]; } else { [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } - } - (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData { @@ -463,7 +222,7 @@ - (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; return; } - + if (initialData.length) { if (![_request performWriteData:initialData error:&error]) { GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); @@ -475,19 +234,20 @@ - (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData } length -= initialData.length; } - + if (length) { - [self _readBodyWithRemainingLength:length completionBlock:^(BOOL success) { - - NSError* localError = nil; - if ([_request performClose:&localError]) { - [self _startProcessingRequest]; - } else { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; + [self readBodyWithRemainingLength:length + completionBlock:^(BOOL success) { + + NSError* localError = nil; + if ([_request performClose:&localError]) { + [self _startProcessingRequest]; + } else { + GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; + } + + }]; } else { if ([_request performClose:&error]) { [self _startProcessingRequest]; @@ -505,129 +265,133 @@ - (void)_readChunkedBodyWithInitialData:(NSData*)initialData { [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; return; } - + NSMutableData* chunkData = [[NSMutableData alloc] initWithData:initialData]; - [self _readNextBodyChunk:chunkData completionBlock:^(BOOL success) { - - NSError* localError = nil; - if ([_request performClose:&localError]) { - [self _startProcessingRequest]; - } else { - GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; + [self readNextBodyChunk:chunkData + completionBlock:^(BOOL success) { + + NSError* localError = nil; + if ([_request performClose:&localError]) { + [self _startProcessingRequest]; + } else { + GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; + } + + }]; } - (void)_readRequestHeaders { _requestMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, true); NSMutableData* headersData = [[NSMutableData alloc] initWithCapacity:kHeadersReadCapacity]; - [self _readHeaders:headersData withCompletionBlock:^(NSData* extraData) { - - if (extraData) { - NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(_requestMessage)); // Method verbs are case-sensitive and uppercase - if (_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) { - requestMethod = @"GET"; - _virtualHEAD = YES; - } - NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones - NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(_requestMessage)); - if (requestURL) { - requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders]; - GWS_DCHECK(requestURL); - } - NSString* requestPath = requestURL ? GCDWebServerUnescapeURLString(CFBridgingRelease(CFURLCopyPath((CFURLRef)requestURL))) : nil; // Don't use -[NSURL path] which strips the ending slash - NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped; - NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{}; - if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) { - for (_handler in _server.handlers) { - _request = _handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery); - if (_request) { - break; + [self readHeaders:headersData + withCompletionBlock:^(NSData* extraData) { + + if (extraData) { + NSString* requestMethod = CFBridgingRelease(CFHTTPMessageCopyRequestMethod(_requestMessage)); // Method verbs are case-sensitive and uppercase + if (_server.shouldAutomaticallyMapHEADToGET && [requestMethod isEqualToString:@"HEAD"]) { + requestMethod = @"GET"; + _virtualHEAD = YES; } - } - if (_request) { - _request.localAddressData = self.localAddressData; - _request.remoteAddressData = self.remoteAddressData; - if ([_request hasBody]) { - [_request prepareForWriting]; - if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) { - NSString* expectHeader = [requestHeaders objectForKey:@"Expect"]; - if (expectHeader) { - if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { // TODO: Actually validate request before continuing - [self _writeData:_continueData withCompletionBlock:^(BOOL success) { - - if (success) { - if (_request.usesChunkedTransferEncoding) { - [self _readChunkedBodyWithInitialData:extraData]; - } else { - [self _readBodyWithLength:_request.contentLength initialData:extraData]; - } + NSDictionary* requestHeaders = CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones + NSURL* requestURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(_requestMessage)); + if (requestURL) { + requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders]; + GWS_DCHECK(requestURL); + } + NSString* urlPath = requestURL ? CFBridgingRelease(CFURLCopyPath((CFURLRef)requestURL)) : nil; // Don't use -[NSURL path] which strips the ending slash + NSString* requestPath = urlPath ? GCDWebServerUnescapeURLString(urlPath) : nil; + NSString* queryString = requestURL ? CFBridgingRelease(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped; + NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{}; + if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) { + for (_handler in _server.handlers) { + _request = _handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery); + if (_request) { + break; + } + } + if (_request) { + _request.localAddressData = self.localAddressData; + _request.remoteAddressData = self.remoteAddressData; + if ([_request hasBody]) { + [_request prepareForWriting]; + if (_request.usesChunkedTransferEncoding || (extraData.length <= _request.contentLength)) { + NSString* expectHeader = [requestHeaders objectForKey:@"Expect"]; + if (expectHeader) { + if ([expectHeader caseInsensitiveCompare:@"100-continue"] == NSOrderedSame) { // TODO: Actually validate request before continuing + [self writeData:_continueData + withCompletionBlock:^(BOOL success) { + + if (success) { + if (_request.usesChunkedTransferEncoding) { + [self _readChunkedBodyWithInitialData:extraData]; + } else { + [self _readBodyWithLength:_request.contentLength initialData:extraData]; + } + } + + }]; + } else { + GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket); + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed]; } - - }]; + } else { + if (_request.usesChunkedTransferEncoding) { + [self _readChunkedBodyWithInitialData:extraData]; + } else { + [self _readBodyWithLength:_request.contentLength initialData:extraData]; + } + } } else { - GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed]; + GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket); + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest]; } } else { - if (_request.usesChunkedTransferEncoding) { - [self _readChunkedBodyWithInitialData:extraData]; - } else { - [self _readBodyWithLength:_request.contentLength initialData:extraData]; - } + [self _startProcessingRequest]; } } else { - GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest]; + _request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery]; + GWS_DCHECK(_request); + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed]; } } else { - [self _startProcessingRequest]; + [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; + GWS_DNOT_REACHED(); } } else { - _request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery]; - GWS_DCHECK(_request); - [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed]; + [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } - } else { - [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - GWS_DNOT_REACHED(); - } - } else { - [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; - } - - }]; + + }]; } -- (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket { +- (instancetype)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket { if ((self = [super init])) { _server = server; - _localAddress = localAddress; - _remoteAddress = remoteAddress; + _localAddressData = localAddress; + _remoteAddressData = remoteAddress; _socket = socket; GWS_LOG_DEBUG(@"Did open connection on socket %i", _socket); - + [_server willStartConnection:self]; - + if (![self open]) { close(_socket); return nil; } _opened = YES; - + [self _readRequestHeaders]; } return self; } - (NSString*)localAddressString { - return GCDWebServerStringFromSockAddr(_localAddress.bytes, YES); + return GCDWebServerStringFromSockAddr(_localAddressData.bytes, YES); } - (NSString*)remoteAddressString { - return GCDWebServerStringFromSockAddr(_remoteAddress.bytes, YES); + return GCDWebServerStringFromSockAddr(_remoteAddressData.bytes, YES); } - (void)dealloc { @@ -637,17 +401,17 @@ - (void)dealloc { } else { GWS_LOG_DEBUG(@"Did close connection on socket %i", _socket); } - + if (_opened) { [self close]; } - + [_server didEndConnection:self]; - + if (_requestMessage) { CFRelease(_requestMessage); } - + if (_responseMessage) { CFRelease(_responseMessage); } @@ -655,30 +419,288 @@ - (void)dealloc { @end +@implementation GCDWebServerConnection (Read) + +- (void)readData:(NSMutableData*)data withLength:(NSUInteger)length completionBlock:(ReadDataCompletionBlock)block { + dispatch_read(_socket, length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t buffer, int error) { + + @autoreleasepool { + if (error == 0) { + size_t size = dispatch_data_get_size(buffer); + if (size > 0) { + NSUInteger originalLength = data.length; + dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) { + [data appendBytes:chunkBytes length:chunkSize]; + return true; + }); + [self didReadBytes:((char*)data.bytes + originalLength) length:(data.length - originalLength)]; + block(YES); + } else { + if (_totalBytesRead > 0) { + GWS_LOG_ERROR(@"No more data available on socket %i", _socket); + } else { + GWS_LOG_WARNING(@"No data received from socket %i", _socket); + } + block(NO); + } + } else { + GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error); + block(NO); + } + } + + }); +} + +- (void)readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block { + GWS_DCHECK(_requestMessage); + [self readData:headersData + withLength:NSUIntegerMax + completionBlock:^(BOOL success) { + + if (success) { + NSRange range = [headersData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(0, headersData.length)]; + if (range.location == NSNotFound) { + [self readHeaders:headersData withCompletionBlock:block]; + } else { + NSUInteger length = range.location + range.length; + if (CFHTTPMessageAppendBytes(_requestMessage, headersData.bytes, length)) { + if (CFHTTPMessageIsHeaderComplete(_requestMessage)) { + block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]); + } else { + GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket); + block(nil); + } + } else { + GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket); + block(nil); + } + } + } else { + block(nil); + } + + }]; +} + +- (void)readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block { + GWS_DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]); + NSMutableData* bodyData = [[NSMutableData alloc] initWithCapacity:kBodyReadCapacity]; + [self readData:bodyData + withLength:length + completionBlock:^(BOOL success) { + + if (success) { + if (bodyData.length <= length) { + NSError* error = nil; + if ([_request performWriteData:bodyData error:&error]) { + NSUInteger remainingLength = length - bodyData.length; + if (remainingLength) { + [self readBodyWithRemainingLength:remainingLength completionBlock:block]; + } else { + block(YES); + } + } else { + GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); + block(NO); + } + } else { + GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket); + block(NO); + GWS_DNOT_REACHED(); + } + } else { + block(NO); + } + + }]; +} + +static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { + char buffer[size + 1]; + bcopy(bytes, buffer, size); + buffer[size] = 0; + char* end = NULL; + long result = strtol(buffer, &end, 16); + return ((end != NULL) && (*end == 0) && (result >= 0) ? result : NSNotFound); +} + +- (void)readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block { + GWS_DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]); + + while (1) { + NSRange range = [chunkData rangeOfData:_CRLFData options:0 range:NSMakeRange(0, chunkData.length)]; + if (range.location == NSNotFound) { + break; + } + NSRange extensionRange = [chunkData rangeOfData:[NSData dataWithBytes:";" length:1] options:0 range:NSMakeRange(0, range.location)]; // Ignore chunk extensions + NSUInteger length = _ScanHexNumber((char*)chunkData.bytes, extensionRange.location != NSNotFound ? extensionRange.location : range.location); + if (length != NSNotFound) { + if (length) { + if (chunkData.length < range.location + range.length + length + 2) { + break; + } + const char* ptr = (char*)chunkData.bytes + range.location + range.length + length; + if ((*ptr == '\r') && (*(ptr + 1) == '\n')) { + NSError* error = nil; + if ([_request performWriteData:[chunkData subdataWithRange:NSMakeRange(range.location + range.length, length)] error:&error]) { + [chunkData replaceBytesInRange:NSMakeRange(0, range.location + range.length + length + 2) withBytes:NULL length:0]; + } else { + GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error); + block(NO); + return; + } + } else { + GWS_LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket); + block(NO); + return; + } + } else { + NSRange trailerRange = [chunkData rangeOfData:_CRLFCRLFData options:0 range:NSMakeRange(range.location, chunkData.length - range.location)]; // Ignore trailers + if (trailerRange.location != NSNotFound) { + block(YES); + return; + } + } + } else { + GWS_LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket); + block(NO); + return; + } + } + + [self readData:chunkData + withLength:NSUIntegerMax + completionBlock:^(BOOL success) { + + if (success) { + [self readNextBodyChunk:chunkData completionBlock:block]; + } else { + block(NO); + } + + }]; +} + +@end + +@implementation GCDWebServerConnection (Write) + +- (void)writeData:(NSData*)data withCompletionBlock:(WriteDataCompletionBlock)block { + dispatch_data_t buffer = dispatch_data_create(data.bytes, data.length, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^{ + [data self]; // Keeps ARC from releasing data too early + }); + dispatch_write(_socket, buffer, dispatch_get_global_queue(_server.dispatchQueuePriority, 0), ^(dispatch_data_t remainingData, int error) { + + @autoreleasepool { + if (error == 0) { + GWS_DCHECK(remainingData == NULL); + [self didWriteBytes:data.bytes length:data.length]; + block(YES); + } else { + GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error); + block(NO); + } + } + + }); +#if !OS_OBJECT_USE_OBJC_RETAIN_RELEASE + dispatch_release(buffer); +#endif +} + +- (void)writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block { + GWS_DCHECK(_responseMessage); + CFDataRef data = CFHTTPMessageCopySerializedMessage(_responseMessage); + [self writeData:(__bridge NSData*)data withCompletionBlock:block]; + CFRelease(data); +} + +- (void)writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block { + GWS_DCHECK([_response hasBody]); + [_response performReadDataWithCompletion:^(NSData* data, NSError* error) { + + if (data) { + if (data.length) { + if (_response.usesChunkedTransferEncoding) { + const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String]; + size_t hexLength = strlen(hexString); + NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)]; + if (chunk == nil) { + GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error); + block(NO); + return; + } + char* ptr = (char*)[(NSMutableData*)chunk mutableBytes]; + bcopy(hexString, ptr, hexLength); + ptr += hexLength; + *ptr++ = '\r'; + *ptr++ = '\n'; + bcopy(data.bytes, ptr, data.length); + ptr += data.length; + *ptr++ = '\r'; + *ptr = '\n'; + data = chunk; + } + [self writeData:data + withCompletionBlock:^(BOOL success) { + + if (success) { + [self writeBodyWithCompletionBlock:block]; + } else { + block(NO); + } + + }]; + } else { + if (_response.usesChunkedTransferEncoding) { + [self writeData:_lastChunkData + withCompletionBlock:^(BOOL success) { + + block(success); + + }]; + } else { + block(YES); + } + } + } else { + GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error); + block(NO); + } + + }]; +} + +@end + @implementation GCDWebServerConnection (Subclassing) - (BOOL)open { #ifdef __GCDWEBSERVER_ENABLE_TESTING__ if (_server.recordingEnabled) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" _connectionIndex = OSAtomicIncrement32(&_connectionCounter); - +#pragma clang diagnostic pop + _requestPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; _requestFD = open([_requestPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); GWS_DCHECK(_requestFD > 0); - + _responsePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; _responseFD = open([_responsePath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); GWS_DCHECK(_responseFD > 0); } #endif - + return YES; } - (void)didReadBytes:(const void*)bytes length:(NSUInteger)length { GWS_LOG_DEBUG(@"Connection received %lu bytes on socket %i", (unsigned long)length, _socket); - _bytesRead += length; - + _totalBytesRead += length; + #ifdef __GCDWEBSERVER_ENABLE_TESTING__ if ((_requestFD > 0) && (write(_requestFD, bytes, length) != (ssize_t)length)) { GWS_LOG_ERROR(@"Failed recording request data: %s (%i)", strerror(errno), errno); @@ -690,8 +712,8 @@ - (void)didReadBytes:(const void*)bytes length:(NSUInteger)length { - (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length { GWS_LOG_DEBUG(@"Connection sent %lu bytes on socket %i", (unsigned long)length, _socket); - _bytesWritten += length; - + _totalBytesWritten += length; + #ifdef __GCDWEBSERVER_ENABLE_TESTING__ if ((_responseFD > 0) && (write(_responseFD, bytes, length) != (ssize_t)length)) { GWS_LOG_ERROR(@"Failed recording response data: %s (%i)", strerror(errno), errno); @@ -707,7 +729,7 @@ - (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NS // https://tools.ietf.org/html/rfc2617 - (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request { - GWS_LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead); + GWS_LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead); GCDWebServerResponse* response = nil; if (_server.authenticationBasicAccounts) { __block BOOL authenticated = NO; @@ -757,13 +779,8 @@ - (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request { } - (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion { - GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead); - @try { - _handler.asyncProcessBlock(request, [completion copy]); - } - @catch (NSException* exception) { - GWS_LOG_EXCEPTION(exception); - } + GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead); + _handler.asyncProcessBlock(request, [completion copy]); } // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 @@ -802,7 +819,7 @@ - (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)sta GWS_DCHECK(_responseMessage == NULL); GWS_DCHECK((statusCode >= 400) && (statusCode < 600)); [self _initializeResponseHeadersWithStatusCode:statusCode]; - [self _writeHeadersWithCompletionBlock:^(BOOL success) { + [self writeHeadersWithCompletionBlock:^(BOOL success) { ; // Nothing more to do }]; GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket); @@ -824,7 +841,7 @@ - (void)close { } unlink([_requestPath fileSystemRepresentation]); } - + if (_responsePath) { BOOL success = NO; NSError* error = nil; @@ -840,11 +857,11 @@ - (void)close { unlink([_responsePath fileSystemRepresentation]); } #endif - + if (_request) { - GWS_LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead, (unsigned long)_bytesWritten); + GWS_LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_totalBytesRead, (unsigned long)_totalBytesWritten); } else { - GWS_LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_bytesRead, (unsigned long)_bytesWritten); + GWS_LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_totalBytesRead, (unsigned long)_totalBytesWritten); } } diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h index e5be05c..4235ecc 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + #ifdef __cplusplus extern "C" { #endif @@ -34,20 +36,24 @@ extern "C" { /** * Converts a file extension to the corresponding MIME type. * If there is no match, "application/octet-stream" is returned. + * + * Overrides allow to customize the built-in mapping from extensions to MIME + * types. Keys of the dictionary must be lowercased file extensions without + * the period, and the values must be the corresponding MIME types. */ -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension); +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* _Nullable overrides); /** * Add percent-escapes to a string so it can be used in a URL. * The legal characters ":@/?&=+" are also escaped to ensure compatibility * with URL encoded forms and URL queries. */ -NSString* GCDWebServerEscapeURLString(NSString* string); +NSString* _Nullable GCDWebServerEscapeURLString(NSString* string); /** * Unescapes a URL percent-encoded string. */ -NSString* GCDWebServerUnescapeURLString(NSString* string); +NSString* _Nullable GCDWebServerUnescapeURLString(NSString* string); /** * Extracts the unescaped names and values from an @@ -63,7 +69,7 @@ NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form); * On iOS, returns the IPv4 or IPv6 address as a string of the WiFi * interface if connected or nil otherwise. */ -NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6); +NSString* _Nullable GCDWebServerGetPrimaryIPAddress(BOOL useIPv6); /** * Converts a date into a string using RFC822 formatting. @@ -79,7 +85,7 @@ NSString* GCDWebServerFormatRFC822(NSDate* date); * * @warning Timezones other than GMT are not supported by this function. */ -NSDate* GCDWebServerParseRFC822(NSString* string); +NSDate* _Nullable GCDWebServerParseRFC822(NSString* string); /** * Converts a date into a string using IOS 8601 formatting. @@ -94,8 +100,10 @@ NSString* GCDWebServerFormatISO8601(NSDate* date); * @warning Only "calendar" variant is supported at this time and timezones * other than GMT are not supported either. */ -NSDate* GCDWebServerParseISO8601(NSString* string); +NSDate* _Nullable GCDWebServerParseISO8601(NSString* string); #ifdef __cplusplus } #endif + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m index 291167d..ec50086 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerFunctions.m @@ -83,21 +83,28 @@ void GCDWebServerInitializeFunctions() { } NSString* GCDWebServerTruncateHeaderValue(NSString* value) { - NSRange range = [value rangeOfString:@";"]; - return range.location != NSNotFound ? [value substringToIndex:range.location] : value; + if (value) { + NSRange range = [value rangeOfString:@";"]; + if (range.location != NSNotFound) { + return [value substringToIndex:range.location]; + } + } + return value; } NSString* GCDWebServerExtractHeaderValueParameter(NSString* value, NSString* name) { NSString* parameter = nil; - NSScanner* scanner = [[NSScanner alloc] initWithString:value]; - [scanner setCaseSensitive:NO]; // Assume parameter names are case-insensitive - NSString* string = [NSString stringWithFormat:@"%@=", name]; - if ([scanner scanUpToString:string intoString:NULL]) { - [scanner scanString:string intoString:NULL]; - if ([scanner scanString:@"\"" intoString:NULL]) { - [scanner scanUpToString:@"\"" intoString:¶meter]; - } else { - [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:¶meter]; + if (value) { + NSScanner* scanner = [[NSScanner alloc] initWithString:value]; + [scanner setCaseSensitive:NO]; // Assume parameter names are case-insensitive + NSString* string = [NSString stringWithFormat:@"%@=", name]; + if ([scanner scanUpToString:string intoString:NULL]) { + [scanner scanString:string intoString:NULL]; + if ([scanner scanString:@"\"" intoString:NULL]) { + [scanner scanUpToString:@"\"" intoString:¶meter]; + } else { + [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:¶meter]; + } } } return parameter; @@ -159,17 +166,15 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length]; } -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension) { - static NSDictionary* _overrides = nil; - if (_overrides == nil) { - _overrides = [[NSDictionary alloc] initWithObjectsAndKeys: - @"text/css", @"css", - nil]; - } +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* overrides) { + NSDictionary* builtInOverrides = @{@"css": @"text/css"}; NSString* mimeType = nil; extension = [extension lowercaseString]; if (extension.length) { - mimeType = [_overrides objectForKey:extension]; + mimeType = [overrides objectForKey:extension]; + if (mimeType == nil) { + mimeType = [builtInOverrides objectForKey:extension]; + } if (mimeType == nil) { CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL); if (uti) { @@ -205,13 +210,13 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { break; } [scanner setScanLocation:([scanner scanLocation] + 1)]; - + NSString* value = nil; [scanner scanUpToString:@"&" intoString:&value]; if (value == nil) { value = @""; } - + key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "]; NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil; value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; @@ -222,7 +227,7 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { GWS_LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value); GWS_DNOT_REACHED(); } - + if ([scanner isAtEnd]) { break; } @@ -232,21 +237,22 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { } NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService) { - NSString* string = nil; char hostBuffer[NI_MAXHOST]; char serviceBuffer[NI_MAXSERV]; - if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) >= 0) { - string = includeService ? [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer] : [NSString stringWithUTF8String:hostBuffer]; - } else { + if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) != 0) { +#if DEBUG GWS_DNOT_REACHED(); +#else + return @""; +#endif } - return string; + return includeService ? [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer] : (NSString*)[NSString stringWithUTF8String:hostBuffer]; } NSString* GCDWebServerGetPrimaryIPAddress(BOOL useIPv6) { NSString* address = nil; #if TARGET_OS_IPHONE -#if !TARGET_IPHONE_SIMULATOR +#if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_TV const char* primaryInterface = "en0"; // WiFi interface on iOS #endif #else @@ -255,7 +261,10 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { if (store) { CFPropertyListRef info = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4")); // There is no equivalent for IPv6 but the primary interface should be the same if (info) { - primaryInterface = [[NSString stringWithString:[(__bridge NSDictionary*)info objectForKey:@"PrimaryInterface"]] UTF8String]; + NSString* interface = [(__bridge NSDictionary*)info objectForKey:@"PrimaryInterface"]; + if (interface) { + primaryInterface = [[NSString stringWithString:interface] UTF8String]; // Copy string to auto-release pool + } CFRelease(info); } CFRelease(store); @@ -267,9 +276,9 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { struct ifaddrs* list; if (getifaddrs(&list) >= 0) { for (struct ifaddrs* ifap = list; ifap; ifap = ifap->ifa_next) { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_TV - // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator - // Assumption holds for Apple TV running tvOS +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_TV + // Assume en0 is Ethernet and en1 is WiFi since there is no way to use SystemConfiguration framework in iOS Simulator + // Assumption holds for Apple TV running tvOS if (strcmp(ifap->ifa_name, "en0") && strcmp(ifap->ifa_name, "en1")) #else if (strcmp(ifap->ifa_name, primaryInterface)) @@ -303,5 +312,5 @@ BOOL GCDWebServerIsTextContentType(NSString* type) { buffer[2 * i + 1] = byteLo >= 10 ? 'a' + byteLo - 10 : '0' + byteLo; } buffer[2 * CC_MD5_DIGEST_LENGTH] = 0; - return [NSString stringWithUTF8String:buffer]; + return (NSString*)[NSString stringWithUTF8String:buffer]; } diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h index c9c6868..e1e6353 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerPrivate.h @@ -48,6 +48,8 @@ #import "GCDWebServerFileResponse.h" #import "GCDWebServerStreamedResponse.h" +NS_ASSUME_NONNULL_BEGIN + /** * Check if a custom logging facility should be used instead. */ @@ -77,7 +79,6 @@ #define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__) #define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__) #define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__) -#define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__) #define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__) #define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE() @@ -102,7 +103,6 @@ extern DDLogLevel GCDWebServerLogLevel; #define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__) #define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__) #define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__) -#define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__) /** * If all of the above fail, then use GCDWebServer built-in @@ -118,23 +118,36 @@ typedef NS_ENUM(int, GCDWebServerLoggingLevel) { kGCDWebServerLoggingLevel_Verbose, kGCDWebServerLoggingLevel_Info, kGCDWebServerLoggingLevel_Warning, - kGCDWebServerLoggingLevel_Error, - kGCDWebServerLoggingLevel_Exception + kGCDWebServerLoggingLevel_Error }; extern GCDWebServerLoggingLevel GCDWebServerLogLevel; extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3); #if DEBUG -#define GWS_LOG_DEBUG(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); } while (0) +#define GWS_LOG_DEBUG(...) \ + do { \ + if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); \ + } while (0) #else #define GWS_LOG_DEBUG(...) #endif -#define GWS_LOG_VERBOSE(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); } while (0) -#define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0) -#define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0) -#define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0) -#define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0) +#define GWS_LOG_VERBOSE(...) \ + do { \ + if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); \ + } while (0) +#define GWS_LOG_INFO(...) \ + do { \ + if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); \ + } while (0) +#define GWS_LOG_WARNING(...) \ + do { \ + if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); \ + } while (0) +#define GWS_LOG_ERROR(...) \ + do { \ + if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); \ + } while (0) #endif @@ -147,10 +160,10 @@ extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* for #if DEBUG #define GWS_DCHECK(__CONDITION__) \ - do { \ - if (!(__CONDITION__)) { \ - abort(); \ - } \ + do { \ + if (!(__CONDITION__)) { \ + abort(); \ + } \ } while (0) #define GWS_DNOT_REACHED() abort() @@ -168,7 +181,6 @@ extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* for */ #define kGCDWebServerDefaultMimeType @"application/octet-stream" -#define kGCDWebServerGCDQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) #define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain" static inline BOOL GCDWebServerIsValidByteRange(NSRange range) { @@ -176,30 +188,31 @@ static inline BOOL GCDWebServerIsValidByteRange(NSRange range) { } static inline NSError* GCDWebServerMakePosixError(int code) { - return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:strerror(code)]}]; + return [NSError errorWithDomain:NSPOSIXErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithUTF8String:strerror(code)]}]; } extern void GCDWebServerInitializeFunctions(); -extern NSString* GCDWebServerNormalizeHeaderValue(NSString* value); -extern NSString* GCDWebServerTruncateHeaderValue(NSString* value); -extern NSString* GCDWebServerExtractHeaderValueParameter(NSString* header, NSString* attribute); +extern NSString* _Nullable GCDWebServerNormalizeHeaderValue(NSString* _Nullable value); +extern NSString* _Nullable GCDWebServerTruncateHeaderValue(NSString* _Nullable value); +extern NSString* _Nullable GCDWebServerExtractHeaderValueParameter(NSString* _Nullable value, NSString* attribute); extern NSStringEncoding GCDWebServerStringEncodingFromCharset(NSString* charset); extern BOOL GCDWebServerIsTextContentType(NSString* type); extern NSString* GCDWebServerDescribeData(NSData* data, NSString* contentType); -extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1,2); +extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_FUNCTION(1, 2); extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOOL includeService); @interface GCDWebServerConnection () -- (id)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket; +- (instancetype)initWithServer:(GCDWebServer*)server localAddress:(NSData*)localAddress remoteAddress:(NSData*)remoteAddress socket:(CFSocketNativeHandle)socket; @end @interface GCDWebServer () -@property(nonatomic, readonly) NSArray* handlers; +@property(nonatomic, readonly) NSMutableArray* handlers; @property(nonatomic, readonly) NSString* serverName; @property(nonatomic, readonly) NSString* authenticationRealm; -@property(nonatomic, readonly) NSDictionary* authenticationBasicAccounts; -@property(nonatomic, readonly) NSDictionary* authenticationDigestAccounts; +@property(nonatomic, readonly) NSMutableDictionary* authenticationBasicAccounts; +@property(nonatomic, readonly) NSMutableDictionary* authenticationDigestAccounts; @property(nonatomic, readonly) BOOL shouldAutomaticallyMapHEADToGET; +@property(nonatomic, readonly) dispatch_queue_priority_t dispatchQueuePriority; - (void)willStartConnection:(GCDWebServerConnection*)connection; - (void)didEndConnection:(GCDWebServerConnection*)connection; @end @@ -211,13 +224,13 @@ extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOO @interface GCDWebServerRequest () @property(nonatomic, readonly) BOOL usesChunkedTransferEncoding; -@property(nonatomic, readwrite) NSData* localAddressData; -@property(nonatomic, readwrite) NSData* remoteAddressData; +@property(nonatomic) NSData* localAddressData; +@property(nonatomic) NSData* remoteAddressData; - (void)prepareForWriting; - (BOOL)performOpen:(NSError**)error; - (BOOL)performWriteData:(NSData*)data error:(NSError**)error; - (BOOL)performClose:(NSError**)error; -- (void)setAttribute:(id)attribute forKey:(NSString*)key; +- (void)setAttribute:(nullable id)attribute forKey:(NSString*)key; @end @interface GCDWebServerResponse () @@ -228,3 +241,5 @@ extern NSString* GCDWebServerStringFromSockAddr(const struct sockaddr* addr, BOO - (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block; - (void)performClose; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h index c7bc31b..3fe9029 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest * with the contents of any regular expression captures done on the request path. @@ -112,7 +114,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; * * @warning This property will be nil if there is no query in the URL. */ -@property(nonatomic, readonly) NSDictionary* query; +@property(nonatomic, readonly, nullable) NSDictionary* query; /** * Returns the content type for the body of the request parsed from the @@ -122,7 +124,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; * "application/octet-stream" if a body is present but there was no * "Content-Type" header. */ -@property(nonatomic, readonly) NSString* contentType; +@property(nonatomic, readonly, nullable) NSString* contentType; /** * Returns the content length for the body of the request parsed from the @@ -137,12 +139,12 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; /** * Returns the parsed "If-Modified-Since" header or nil if absent or malformed. */ -@property(nonatomic, readonly) NSDate* ifModifiedSince; +@property(nonatomic, readonly, nullable) NSDate* ifModifiedSince; /** * Returns the parsed "If-None-Match" header or nil if absent or malformed. */ -@property(nonatomic, readonly) NSString* ifNoneMatch; +@property(nonatomic, readonly, nullable) NSString* ifNoneMatch; /** * Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed. @@ -184,7 +186,7 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; /** * This method is the designated initializer for the class. */ -- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query; +- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(nullable NSDictionary*)query; /** * Convenience method that checks if the contentType property is defined. @@ -201,6 +203,8 @@ extern NSString* const GCDWebServerRequestAttribute_RegexCaptures; * * @return The attribute value for the key. */ -- (id)attributeForKey:(NSString*)key; +- (nullable id)attributeForKey:(NSString*)key; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.m b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.m index dc929a7..05988cd 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.m +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerRequest.m @@ -39,22 +39,17 @@ #define kGZipInitialBufferSize (256 * 1024) @interface GCDWebServerBodyDecoder : NSObject -- (id)initWithRequest:(GCDWebServerRequest*)request writer:(id)writer; @end @interface GCDWebServerGZipDecoder : GCDWebServerBodyDecoder @end -@interface GCDWebServerBodyDecoder () { -@private +@implementation GCDWebServerBodyDecoder { GCDWebServerRequest* __unsafe_unretained _request; id __unsafe_unretained _writer; } -@end - -@implementation GCDWebServerBodyDecoder -- (id)initWithRequest:(GCDWebServerRequest*)request writer:(id)writer { +- (instancetype)initWithRequest:(GCDWebServerRequest* _Nonnull)request writer:(id _Nonnull)writer { if ((self = [super init])) { _request = request; _writer = writer; @@ -76,14 +71,10 @@ - (BOOL)close:(NSError**)error { @end -@interface GCDWebServerGZipDecoder () { -@private +@implementation GCDWebServerGZipDecoder { z_stream _stream; BOOL _finished; } -@end - -@implementation GCDWebServerGZipDecoder - (BOOL)open:(NSError**)error { int result = inflateInit2(&_stream, 15 + 16); @@ -94,7 +85,7 @@ - (BOOL)open:(NSError**)error { return NO; } if (![super open:error]) { - deflateEnd(&_stream); + inflateEnd(&_stream); return NO; } return YES; @@ -143,77 +134,55 @@ - (BOOL)close:(NSError**)error { @end -@interface GCDWebServerRequest () { -@private - NSString* _method; - NSURL* _url; - NSDictionary* _headers; - NSString* _path; - NSDictionary* _query; - NSString* _type; - BOOL _chunked; - NSUInteger _length; - NSDate* _modifiedSince; - NSString* _noneMatch; - NSRange _range; - BOOL _gzipAccepted; - NSData* _localAddress; - NSData* _remoteAddress; - +@implementation GCDWebServerRequest { BOOL _opened; NSMutableArray* _decoders; - NSMutableDictionary* _attributes; id __unsafe_unretained _writer; + NSMutableDictionary* _attributes; } -@end - -@implementation GCDWebServerRequest : NSObject - -@synthesize method=_method, URL=_url, headers=_headers, path=_path, query=_query, contentType=_type, contentLength=_length, ifModifiedSince=_modifiedSince, ifNoneMatch=_noneMatch, - byteRange=_range, acceptsGzipContentEncoding=_gzipAccepted, usesChunkedTransferEncoding=_chunked, localAddressData=_localAddress, remoteAddressData=_remoteAddress; - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { if ((self = [super init])) { _method = [method copy]; - _url = url; + _URL = url; _headers = headers; _path = [path copy]; _query = query; - - _type = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Content-Type"]); - _chunked = [GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Transfer-Encoding"]) isEqualToString:@"chunked"]; + + _contentType = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Content-Type"]); + _usesChunkedTransferEncoding = [GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Transfer-Encoding"]) isEqualToString:@"chunked"]; NSString* lengthHeader = [_headers objectForKey:@"Content-Length"]; if (lengthHeader) { NSInteger length = [lengthHeader integerValue]; - if (_chunked || (length < 0)) { - GWS_LOG_WARNING(@"Invalid 'Content-Length' header '%@' for '%@' request on \"%@\"", lengthHeader, _method, _url); + if (_usesChunkedTransferEncoding || (length < 0)) { + GWS_LOG_WARNING(@"Invalid 'Content-Length' header '%@' for '%@' request on \"%@\"", lengthHeader, _method, _URL); GWS_DNOT_REACHED(); return nil; } - _length = length; - if (_type == nil) { - _type = kGCDWebServerDefaultMimeType; + _contentLength = length; + if (_contentType == nil) { + _contentType = kGCDWebServerDefaultMimeType; } - } else if (_chunked) { - if (_type == nil) { - _type = kGCDWebServerDefaultMimeType; + } else if (_usesChunkedTransferEncoding) { + if (_contentType == nil) { + _contentType = kGCDWebServerDefaultMimeType; } - _length = NSUIntegerMax; + _contentLength = NSUIntegerMax; } else { - if (_type) { - GWS_LOG_WARNING(@"Ignoring 'Content-Type' header for '%@' request on \"%@\"", _method, _url); - _type = nil; // Content-Type without Content-Length or chunked-encoding doesn't make sense + if (_contentType) { + GWS_LOG_WARNING(@"Ignoring 'Content-Type' header for '%@' request on \"%@\"", _method, _URL); + _contentType = nil; // Content-Type without Content-Length or chunked-encoding doesn't make sense } - _length = NSUIntegerMax; + _contentLength = NSUIntegerMax; } - + NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"]; if (modifiedHeader) { - _modifiedSince = [GCDWebServerParseRFC822(modifiedHeader) copy]; + _ifModifiedSince = [GCDWebServerParseRFC822(modifiedHeader) copy]; } - _noneMatch = [_headers objectForKey:@"If-None-Match"]; - - _range = NSMakeRange(NSUIntegerMax, 0); + _ifNoneMatch = [_headers objectForKey:@"If-None-Match"]; + + _byteRange = NSMakeRange(NSUIntegerMax, 0); NSString* rangeHeader = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Range"]); if (rangeHeader) { if ([rangeHeader hasPrefix:@"bytes="]) { @@ -226,27 +195,27 @@ - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDict NSString* endString = [components objectAtIndex:1]; NSInteger endValue = [endString integerValue]; if (startString.length && (startValue >= 0) && endString.length && (endValue >= startValue)) { // The second 500 bytes: "500-999" - _range.location = startValue; - _range.length = endValue - startValue + 1; + _byteRange.location = startValue; + _byteRange.length = endValue - startValue + 1; } else if (startString.length && (startValue >= 0)) { // The bytes after 9500 bytes: "9500-" - _range.location = startValue; - _range.length = NSUIntegerMax; + _byteRange.location = startValue; + _byteRange.length = NSUIntegerMax; } else if (endString.length && (endValue > 0)) { // The final 500 bytes: "-500" - _range.location = NSUIntegerMax; - _range.length = endValue; + _byteRange.location = NSUIntegerMax; + _byteRange.length = endValue; } } } } - if ((_range.location == NSUIntegerMax) && (_range.length == 0)) { // Ignore "Range" header if syntactically invalid + if ((_byteRange.location == NSUIntegerMax) && (_byteRange.length == 0)) { // Ignore "Range" header if syntactically invalid GWS_LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url); } } - + if ([[_headers objectForKey:@"Accept-Encoding"] rangeOfString:@"gzip"].location != NSNotFound) { - _gzipAccepted = YES; + _acceptsGzipContentEncoding = YES; } - + _decoders = [[NSMutableArray alloc] init]; _attributes = [[NSMutableDictionary alloc] init]; } @@ -254,11 +223,11 @@ - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDict } - (BOOL)hasBody { - return _type ? YES : NO; + return _contentType ? YES : NO; } - (BOOL)hasByteRange { - return GCDWebServerIsValidByteRange(_range); + return GCDWebServerIsValidByteRange(_byteRange); } - (id)attributeForKey:(NSString*)key { @@ -287,7 +256,7 @@ - (void)prepareForWriting { } - (BOOL)performOpen:(NSError**)error { - GWS_DCHECK(_type); + GWS_DCHECK(_contentType); GWS_DCHECK(_writer); if (_opened) { GWS_DNOT_REACHED(); @@ -312,11 +281,11 @@ - (void)setAttribute:(id)attribute forKey:(NSString*)key { } - (NSString*)localAddressString { - return GCDWebServerStringFromSockAddr(_localAddress.bytes, YES); + return GCDWebServerStringFromSockAddr(_localAddressData.bytes, YES); } - (NSString*)remoteAddressString { - return GCDWebServerStringFromSockAddr(_remoteAddress.bytes, YES); + return GCDWebServerStringFromSockAddr(_remoteAddressData.bytes, YES); } - (NSString*)description { diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h index 2ec2dee..1e5e8c9 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.h @@ -27,11 +27,13 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerBodyReaderCompletionBlock is passed by GCDWebServer to the * GCDWebServerBodyReader object when reading data from it asynchronously. */ -typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* error); +typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* _Nullable error); /** * This protocol is used by the GCDWebServerConnection to communicate with @@ -62,7 +64,7 @@ typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* err * or an empty NSData there is no more body data, or nil on error and set * the "error" argument which is guaranteed to be non-NULL. */ -- (NSData*)readData:(NSError**)error; +- (nullable NSData*)readData:(NSError**)error; /** * This method is called after all body data has been sent. @@ -102,7 +104,7 @@ typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* err * * @warning This property must be set if a body is present. */ -@property(nonatomic, copy) NSString* contentType; +@property(nonatomic, copy, nullable) NSString* contentType; /** * Sets the content length for the body of the response. If a body is present @@ -136,14 +138,14 @@ typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* err * * The default value is nil. */ -@property(nonatomic, retain) NSDate* lastModifiedDate; +@property(nonatomic, nullable) NSDate* lastModifiedDate; /** * Sets the ETag for the response using the "ETag" header. * * The default value is nil. */ -@property(nonatomic, copy) NSString* eTag; +@property(nonatomic, copy, nullable) NSString* eTag; /** * Enables gzip encoding for the response body. @@ -174,7 +176,7 @@ typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* err * @warning Do not attempt to override the primary headers used * by GCDWebServerResponse like "Content-Type", "ETag", etc... */ -- (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header; +- (void)setValue:(nullable NSString*)value forAdditionalHeader:(NSString*)header; /** * Convenience method that checks if the contentType property is defined. @@ -206,3 +208,5 @@ typedef void (^GCDWebServerBodyReaderCompletionBlock)(NSData* data, NSError* err - (instancetype)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.m b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.m index 8357ab7..9153ff6 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.m +++ b/src/ios/GCDWebServer/GCDWebServer/Core/GCDWebServerResponse.m @@ -37,22 +37,17 @@ #define kGZipInitialBufferSize (256 * 1024) @interface GCDWebServerBodyEncoder : NSObject -- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader; @end @interface GCDWebServerGZipEncoder : GCDWebServerBodyEncoder @end -@interface GCDWebServerBodyEncoder () { -@private +@implementation GCDWebServerBodyEncoder { GCDWebServerResponse* __unsafe_unretained _response; id __unsafe_unretained _reader; } -@end - -@implementation GCDWebServerBodyEncoder -- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader { +- (instancetype)initWithResponse:(GCDWebServerResponse* _Nonnull)response reader:(id _Nonnull)reader { if ((self = [super init])) { _response = response; _reader = reader; @@ -74,16 +69,12 @@ - (void)close { @end -@interface GCDWebServerGZipEncoder () { -@private +@implementation GCDWebServerGZipEncoder { z_stream _stream; BOOL _finished; } -@end - -@implementation GCDWebServerGZipEncoder -- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id)reader { +- (instancetype)initWithResponse:(GCDWebServerResponse* _Nonnull)response reader:(id _Nonnull)reader { if ((self = [super initWithResponse:response reader:reader])) { response.contentLength = NSUIntegerMax; // Make sure "Content-Length" header is not set since we don't know it [response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"]; @@ -157,28 +148,11 @@ - (void)close { @end -@interface GCDWebServerResponse () { -@private - NSString* _type; - NSUInteger _length; - NSInteger _status; - NSUInteger _maxAge; - NSDate* _lastModified; - NSString* _eTag; - NSMutableDictionary* _headers; - BOOL _chunked; - BOOL _gzipped; - +@implementation GCDWebServerResponse { BOOL _opened; NSMutableArray* _encoders; id __unsafe_unretained _reader; } -@end - -@implementation GCDWebServerResponse - -@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified, eTag=_eTag, - gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers; + (instancetype)response { return [[[self class] alloc] init]; @@ -186,26 +160,26 @@ + (instancetype)response { - (instancetype)init { if ((self = [super init])) { - _type = nil; - _length = NSUIntegerMax; - _status = kGCDWebServerHTTPStatusCode_OK; - _maxAge = 0; - _headers = [[NSMutableDictionary alloc] init]; + _contentType = nil; + _contentLength = NSUIntegerMax; + _statusCode = kGCDWebServerHTTPStatusCode_OK; + _cacheControlMaxAge = 0; + _additionalHeaders = [[NSMutableDictionary alloc] init]; _encoders = [[NSMutableArray alloc] init]; } return self; } - (void)setValue:(NSString*)value forAdditionalHeader:(NSString*)header { - [_headers setValue:value forKey:header]; + [_additionalHeaders setValue:value forKey:header]; } - (BOOL)hasBody { - return _type ? YES : NO; + return _contentType ? YES : NO; } - (BOOL)usesChunkedTransferEncoding { - return (_type != nil) && (_length == NSUIntegerMax); + return (_contentType != nil) && (_contentLength == NSUIntegerMax); } - (BOOL)open:(NSError**)error { @@ -222,7 +196,7 @@ - (void)close { - (void)prepareForReading { _reader = self; - if (_gzipped) { + if (_gzipContentEncodingEnabled) { GCDWebServerGZipEncoder* encoder = [[GCDWebServerGZipEncoder alloc] initWithResponse:self reader:_reader]; [_encoders addObject:encoder]; _reader = encoder; @@ -230,7 +204,7 @@ - (void)prepareForReading { } - (BOOL)performOpen:(NSError**)error { - GWS_DCHECK(_type); + GWS_DCHECK(_contentType); GWS_DCHECK(_reader); if (_opened) { GWS_DNOT_REACHED(); @@ -241,6 +215,7 @@ - (BOOL)performOpen:(NSError**)error { } - (void)performReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block { + GWS_DCHECK(_opened); if ([_reader respondsToSelector:@selector(asyncReadDataWithCompletion:)]) { [_reader asyncReadDataWithCompletion:[block copy]]; } else { @@ -256,24 +231,24 @@ - (void)performClose { } - (NSString*)description { - NSMutableString* description = [NSMutableString stringWithFormat:@"Status Code = %i", (int)_status]; - if (_type) { - [description appendFormat:@"\nContent Type = %@", _type]; + NSMutableString* description = [NSMutableString stringWithFormat:@"Status Code = %i", (int)_statusCode]; + if (_contentType) { + [description appendFormat:@"\nContent Type = %@", _contentType]; } - if (_length != NSUIntegerMax) { - [description appendFormat:@"\nContent Length = %lu", (unsigned long)_length]; + if (_contentLength != NSUIntegerMax) { + [description appendFormat:@"\nContent Length = %lu", (unsigned long)_contentLength]; } - [description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_maxAge]; - if (_lastModified) { - [description appendFormat:@"\nLast Modified Date = %@", _lastModified]; + [description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_cacheControlMaxAge]; + if (_lastModifiedDate) { + [description appendFormat:@"\nLast Modified Date = %@", _lastModifiedDate]; } if (_eTag) { [description appendFormat:@"\nETag = %@", _eTag]; } - if (_headers.count) { + if (_additionalHeaders.count) { [description appendString:@"\n"]; - for (NSString* header in [[_headers allKeys] sortedArrayUsingSelector:@selector(compare:)]) { - [description appendFormat:@"\n%@: %@", header, [_headers objectForKey:header]]; + for (NSString* header in [[_additionalHeaders allKeys] sortedArrayUsingSelector:@selector(compare:)]) { + [description appendFormat:@"\n%@: %@", header, [_additionalHeaders objectForKey:header]]; } } return description; diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h index 5048d08..f21a4b7 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.h @@ -27,6 +27,8 @@ #import "GCDWebServerRequest.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body * of the HTTP request in memory. @@ -49,12 +51,14 @@ * The text encoding used to interpret the data is extracted from the * "Content-Type" header or defaults to UTF-8. */ -@property(nonatomic, readonly) NSString* text; +@property(nonatomic, readonly, nullable) NSString* text; /** * Returns the data for the request body interpreted as a JSON object. If the * content type of the body is not JSON, or if an error occurs, nil is returned. */ -@property(nonatomic, readonly) id jsonObject; +@property(nonatomic, readonly, nullable) id jsonObject; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.m b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.m index 840e985..3ea9bba 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.m +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerDataRequest.m @@ -31,18 +31,14 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerDataRequest () { -@private - NSMutableData* _data; - +@interface GCDWebServerDataRequest () +@property(nonatomic) NSMutableData* data; +@end + +@implementation GCDWebServerDataRequest { NSString* _text; id _jsonObject; } -@end - -@implementation GCDWebServerDataRequest - -@synthesize data=_data; - (BOOL)open:(NSError**)error { if (self.contentLength != NSUIntegerMax) { @@ -52,7 +48,7 @@ - (BOOL)open:(NSError**)error { } if (_data == nil) { if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed allocating memory"}]; + *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed allocating memory" }]; } return NO; } @@ -72,7 +68,7 @@ - (NSString*)description { NSMutableString* description = [NSMutableString stringWithString:[super description]]; if (_data) { [description appendString:@"\n\n"]; - [description appendString:GCDWebServerDescribeData(_data, self.contentType)]; + [description appendString:GCDWebServerDescribeData(_data, (NSString*)self.contentType)]; } return description; } diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h index ad29eab..8aceae4 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.h @@ -27,6 +27,8 @@ #import "GCDWebServerRequest.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body * of the HTTP request to a file on disk. @@ -43,3 +45,5 @@ @property(nonatomic, readonly) NSString* temporaryPath; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.m b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.m index adf67a5..8a47fcc 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.m +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerFileRequest.m @@ -31,16 +31,9 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerFileRequest () { -@private - NSString* _temporaryPath; +@implementation GCDWebServerFileRequest { int _file; } -@end - -@implementation GCDWebServerFileRequest - -@synthesize temporaryPath=_temporaryPath; - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { if ((self = [super initWithMethod:method url:url headers:headers path:path query:query])) { @@ -85,14 +78,14 @@ - (BOOL)close:(NSError**)error { NSString* creationDateHeader = [self.headers objectForKey:@"X-GCDWebServer-CreationDate"]; if (creationDateHeader) { NSDate* date = GCDWebServerParseISO8601(creationDateHeader); - if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate: date} ofItemAtPath:_temporaryPath error:error]) { + if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileCreationDate : date} ofItemAtPath:_temporaryPath error:error]) { return NO; } } NSString* modifiedDateHeader = [self.headers objectForKey:@"X-GCDWebServer-ModifiedDate"]; if (modifiedDateHeader) { NSDate* date = GCDWebServerParseRFC822(modifiedDateHeader); - if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate: date} ofItemAtPath:_temporaryPath error:error]) { + if (!date || ![[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate : date} ofItemAtPath:_temporaryPath error:error]) { return NO; } } diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h index 832c2e7..93ac179 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h @@ -27,6 +27,8 @@ #import "GCDWebServerRequest.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerMultiPart class is an abstract class that wraps the content * of a part. @@ -69,7 +71,7 @@ * The text encoding used to interpret the data is extracted from the * "Content-Type" header or defaults to UTF-8. */ -@property(nonatomic, readonly) NSString* string; +@property(nonatomic, readonly, nullable) NSString* string; @end @@ -122,11 +124,13 @@ /** * Returns the first argument for a given control name or nil if not found. */ -- (GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name; +- (nullable GCDWebServerMultiPartArgument*)firstArgumentForControlName:(NSString*)name; /** * Returns the first file for a given control name or nil if not found. */ -- (GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name; +- (nullable GCDWebServerMultiPartFile*)firstFileForControlName:(NSString*)name; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m index c2fc9bf..4e6bf09 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m @@ -42,53 +42,31 @@ } ParserState; @interface GCDWebServerMIMEStreamParser : NSObject -- (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files; -- (BOOL)appendBytes:(const void*)bytes length:(NSUInteger)length; -- (BOOL)isAtEnd; @end static NSData* _newlineData = nil; static NSData* _newlinesData = nil; static NSData* _dashNewlineData = nil; -@interface GCDWebServerMultiPart () { -@private - NSString* _controlName; - NSString* _contentType; - NSString* _mimeType; -} -@end - @implementation GCDWebServerMultiPart -@synthesize controlName=_controlName, contentType=_contentType, mimeType=_mimeType; - -- (id)initWithControlName:(NSString*)name contentType:(NSString*)type { +- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type { if ((self = [super init])) { _controlName = [name copy]; _contentType = [type copy]; - _mimeType = GCDWebServerTruncateHeaderValue(_contentType); + _mimeType = (NSString*)GCDWebServerTruncateHeaderValue(_contentType); } return self; } @end -@interface GCDWebServerMultiPartArgument () { -@private - NSData* _data; - NSString* _string; -} -@end - @implementation GCDWebServerMultiPartArgument -@synthesize data=_data, string=_string; - -- (id)initWithControlName:(NSString*)name contentType:(NSString*)type data:(NSData*)data { +- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type data:(NSData* _Nonnull)data { if ((self = [super initWithControlName:name contentType:type])) { _data = data; - + if ([self.contentType hasPrefix:@"text/"]) { NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); _string = [[NSString alloc] initWithData:_data encoding:GCDWebServerStringEncodingFromCharset(charset)]; @@ -103,18 +81,9 @@ - (NSString*)description { @end -@interface GCDWebServerMultiPartFile () { -@private - NSString* _fileName; - NSString* _temporaryPath; -} -@end - @implementation GCDWebServerMultiPartFile -@synthesize fileName=_fileName, temporaryPath=_temporaryPath; - -- (id)initWithControlName:(NSString*)name contentType:(NSString*)type fileName:(NSString*)fileName temporaryPath:(NSString*)temporaryPath { +- (instancetype)initWithControlName:(NSString* _Nonnull)name contentType:(NSString* _Nonnull)type fileName:(NSString* _Nonnull)fileName temporaryPath:(NSString* _Nonnull)temporaryPath { if ((self = [super initWithControlName:name contentType:type])) { _fileName = [fileName copy]; _temporaryPath = [temporaryPath copy]; @@ -132,15 +101,14 @@ - (NSString*)description { @end -@interface GCDWebServerMIMEStreamParser () { -@private +@implementation GCDWebServerMIMEStreamParser { NSData* _boundary; NSString* _defaultcontrolName; ParserState _state; NSMutableData* _data; NSMutableArray* _arguments; NSMutableArray* _files; - + NSString* _controlName; NSString* _fileName; NSString* _contentType; @@ -148,9 +116,6 @@ @interface GCDWebServerMIMEStreamParser () { int _tmpFile; GCDWebServerMIMEStreamParser* _subParser; } -@end - -@implementation GCDWebServerMIMEStreamParser + (void)initialize { if (_newlineData == nil) { @@ -167,7 +132,7 @@ + (void)initialize { } } -- (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files { +- (instancetype)initWithBoundary:(NSString* _Nonnull)boundary defaultControlName:(NSString* _Nullable)name arguments:(NSMutableArray* _Nonnull)arguments files:(NSMutableArray* _Nonnull)files { NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil; if (data == nil) { GWS_DNOT_REACHED(); @@ -194,11 +159,10 @@ - (void)dealloc { // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 - (BOOL)_parseData { BOOL success = YES; - + if (_state == kParserState_Headers) { NSRange range = [_data rangeOfData:_newlinesData options:0 range:NSMakeRange(0, _data.length)]; if (range.location != NSNotFound) { - _controlName = nil; _fileName = nil; _contentType = nil; @@ -256,12 +220,12 @@ - (BOOL)_parseData { GWS_DNOT_REACHED(); success = NO; } - + [_data replaceBytesInRange:NSMakeRange(0, range.location + range.length) withBytes:NULL length:0]; _state = kParserState_Content; } } - + if ((_state == kParserState_Start) || (_state == kParserState_Content)) { NSRange range = [_data rangeOfData:_boundary options:0 range:NSMakeRange(0, _data.length)]; if (range.location != NSNotFound) { @@ -269,7 +233,6 @@ - (BOOL)_parseData { NSRange subRange1 = [_data rangeOfData:_newlineData options:NSDataSearchAnchored range:subRange]; NSRange subRange2 = [_data rangeOfData:_dashNewlineData options:NSDataSearchAnchored range:subRange]; if ((subRange1.location != NSNotFound) || (subRange2.location != NSNotFound)) { - if (_state == kParserState_Content) { const void* dataBytes = _data.bytes; NSUInteger dataLength = range.location - 2; @@ -301,7 +264,7 @@ - (BOOL)_parseData { [_arguments addObject:argument]; } } - + if (subRange1.location != NSNotFound) { [_data replaceBytesInRange:NSMakeRange(0, subRange1.location + subRange1.length) withBytes:NULL length:0]; _state = kParserState_Headers; @@ -333,7 +296,7 @@ - (BOOL)_parseData { } } } - + return success; } @@ -348,17 +311,14 @@ - (BOOL)isAtEnd { @end -@interface GCDWebServerMultiPartFormRequest () { -@private - GCDWebServerMIMEStreamParser* _parser; - NSMutableArray* _arguments; - NSMutableArray* _files; -} +@interface GCDWebServerMultiPartFormRequest () +@property(nonatomic) NSMutableArray* arguments; +@property(nonatomic) NSMutableArray* files; @end -@implementation GCDWebServerMultiPartFormRequest - -@synthesize arguments=_arguments, files=_files; +@implementation GCDWebServerMultiPartFormRequest { + GCDWebServerMIMEStreamParser* _parser; +} + (NSString*)mimeType { return @"multipart/form-data"; @@ -377,7 +337,7 @@ - (BOOL)open:(NSError**)error { _parser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:nil arguments:_arguments files:_files]; if (_parser == nil) { if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed starting to parse multipart form data"}]; + *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed starting to parse multipart form data" }]; } return NO; } @@ -387,7 +347,7 @@ - (BOOL)open:(NSError**)error { - (BOOL)writeData:(NSData*)data error:(NSError**)error { if (![_parser appendBytes:data.bytes length:data.length]) { if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed continuing to parse multipart form data"}]; + *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed continuing to parse multipart form data" }]; } return NO; } @@ -399,7 +359,7 @@ - (BOOL)close:(NSError**)error { _parser = nil; if (!atEnd) { if (error) { - *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed finishing to parse multipart form data"}]; + *error = [NSError errorWithDomain:kGCDWebServerErrorDomain code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Failed finishing to parse multipart form data" }]; } return NO; } diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h index 9735380..fcf177e 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h @@ -27,6 +27,8 @@ #import "GCDWebServerDataRequest.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest * parses the body of the HTTP request as a URL encoded form using @@ -49,3 +51,5 @@ + (NSString*)mimeType; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m index 2c5fcc5..7e0137f 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m +++ b/src/ios/GCDWebServer/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m @@ -31,16 +31,8 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerURLEncodedFormRequest () { -@private - NSDictionary* _arguments; -} -@end - @implementation GCDWebServerURLEncodedFormRequest -@synthesize arguments=_arguments; - + (NSString*)mimeType { return @"application/x-www-form-urlencoded"; } @@ -49,12 +41,10 @@ - (BOOL)close:(NSError**)error { if (![super close:error]) { return NO; } - + NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset"); NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)]; _arguments = GCDWebServerParseURLEncodedForm(string); - GWS_DCHECK(_arguments); - return YES; } diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h index 6e06cd8..783f596 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.h @@ -27,11 +27,14 @@ #import "GCDWebServerResponse.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body * of the HTTP response from memory. */ @interface GCDWebServerDataResponse : GCDWebServerResponse +@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null /** * Creates a response with data in memory and a given content type. @@ -50,40 +53,40 @@ /** * Creates a data response from text encoded using UTF-8. */ -+ (instancetype)responseWithText:(NSString*)text; ++ (nullable instancetype)responseWithText:(NSString*)text; /** * Creates a data response from HTML encoded using UTF-8. */ -+ (instancetype)responseWithHTML:(NSString*)html; ++ (nullable instancetype)responseWithHTML:(NSString*)html; /** * Creates a data response from an HTML template encoded using UTF-8. * See -initWithHTMLTemplate:variables: for details. */ -+ (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; ++ (nullable instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; /** * Creates a data response from a serialized JSON object and the default * "application/json" content type. */ -+ (instancetype)responseWithJSONObject:(id)object; ++ (nullable instancetype)responseWithJSONObject:(id)object; /** * Creates a data response from a serialized JSON object and a custom * content type. */ -+ (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; ++ (nullable instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; /** * Initializes a data response from text encoded using UTF-8. */ -- (instancetype)initWithText:(NSString*)text; +- (nullable instancetype)initWithText:(NSString*)text; /** * Initializes a data response from HTML encoded using UTF-8. */ -- (instancetype)initWithHTML:(NSString*)html; +- (nullable instancetype)initWithHTML:(NSString*)html; /** * Initializes a data response from an HTML template encoded using UTF-8. @@ -91,18 +94,20 @@ * All occurences of "%variable%" within the HTML template are replaced with * their corresponding values. */ -- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; +- (nullable instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; /** * Initializes a data response from a serialized JSON object and the default * "application/json" content type. */ -- (instancetype)initWithJSONObject:(id)object; +- (nullable instancetype)initWithJSONObject:(id)object; /** * Initializes a data response from a serialized JSON object and a custom * content type. */ -- (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; +- (nullable instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.m b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.m index 12cd12b..b496847 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.m +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerDataResponse.m @@ -31,28 +31,21 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerDataResponse () { -@private +@implementation GCDWebServerDataResponse { NSData* _data; BOOL _done; } -@end -@implementation GCDWebServerDataResponse +@dynamic contentType; + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type { return [[[self class] alloc] initWithData:data contentType:type]; } - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type { - if (data == nil) { - GWS_DNOT_REACHED(); - return nil; - } - if ((self = [super init])) { _data = data; - + self.contentType = type; self.contentLength = data.length; } @@ -124,8 +117,7 @@ - (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)va [variables enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) { [html replaceOccurrencesOfString:[NSString stringWithFormat:@"%%%@%%", key] withString:value options:0 range:NSMakeRange(0, html.length)]; }]; - id response = [self initWithHTML:html]; - return response; + return [self initWithHTML:html]; } - (instancetype)initWithJSONObject:(id)object { @@ -135,6 +127,7 @@ - (instancetype)initWithJSONObject:(id)object { - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type { NSData* data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL]; if (data == nil) { + GWS_DNOT_REACHED(); return nil; } return [self initWithData:data contentType:type]; diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h index dad0114..92c834c 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.h @@ -28,6 +28,8 @@ #import "GCDWebServerDataResponse.h" #import "GCDWebServerHTTPStatusCodes.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates * an HTML body from an HTTP status code and an error message. @@ -37,45 +39,47 @@ /** * Creates a client error response with the corresponding HTTP status code. */ -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); ++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); /** * Creates a server error response with the corresponding HTTP status code. */ -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); ++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); /** * Creates a client error response with the corresponding HTTP status code * and an underlying NSError. */ -+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); ++ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); /** * Creates a server error response with the corresponding HTTP status code * and an underlying NSError. */ -+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); ++ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); /** * Initializes a client error response with the corresponding HTTP status code. */ -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); +- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); /** * Initializes a server error response with the corresponding HTTP status code. */ -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); +- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3); /** * Initializes a client error response with the corresponding HTTP status code * and an underlying NSError. */ -- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); +- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); /** * Initializes a server error response with the corresponding HTTP status code * and an underlying NSError. */ -- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); +- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(nullable NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3, 4); @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.m b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.m index ef6a991..f1cd202 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.m +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerErrorResponse.m @@ -31,10 +31,6 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerErrorResponse () -- (instancetype)initWithStatusCode:(NSInteger)statusCode underlyingError:(NSError*)underlyingError messageFormat:(NSString*)format arguments:(va_list)arguments; -@end - @implementation GCDWebServerErrorResponse + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... { diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h index 050e92f..9403835 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.h @@ -27,6 +27,8 @@ #import "GCDWebServerResponse.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body * of the HTTP response from a file on disk. @@ -36,17 +38,20 @@ * metadata. */ @interface GCDWebServerFileResponse : GCDWebServerResponse +@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null +@property(nonatomic) NSDate* lastModifiedDate; // Redeclare as non-null +@property(nonatomic, copy) NSString* eTag; // Redeclare as non-null /** * Creates a response with the contents of a file. */ -+ (instancetype)responseWithFile:(NSString*)path; ++ (nullable instancetype)responseWithFile:(NSString*)path; /** * Creates a response like +responseWithFile: and sets the "Content-Disposition" * HTTP header for a download if the "attachment" argument is YES. */ -+ (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; ++ (nullable instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; /** * Creates a response like +responseWithFile: but restricts the file contents @@ -54,26 +59,26 @@ * * See -initWithFile:byteRange: for details. */ -+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; ++ (nullable instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; /** * Creates a response like +responseWithFile:byteRange: and sets the * "Content-Disposition" HTTP header for a download if the "attachment" * argument is YES. */ -+ (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; ++ (nullable instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; /** * Initializes a response with the contents of a file. */ -- (instancetype)initWithFile:(NSString*)path; +- (nullable instancetype)initWithFile:(NSString*)path; /** * Initializes a response like +responseWithFile: and sets the * "Content-Disposition" HTTP header for a download if the "attachment" * argument is YES. */ -- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; +- (nullable instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; /** * Initializes a response like -initWithFile: but restricts the file contents @@ -86,11 +91,18 @@ * This argument would typically be set to the value of the byteRange property * of the current GCDWebServerRequest. */ -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; +- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; /** * This method is the designated initializer for the class. + * + * If MIME type overrides are specified, they allow to customize the built-in + * mapping from extensions to MIME types. Keys of the dictionary must be lowercased + * file extensions without the period, and the values must be the corresponding + * MIME types. */ -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; +- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(nullable NSDictionary*)overrides; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.m b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.m index a2b7c3c..bd07518 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.m +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerFileResponse.m @@ -35,16 +35,14 @@ #define kFileReadBufferSize (32 * 1024) -@interface GCDWebServerFileResponse () { -@private +@implementation GCDWebServerFileResponse { NSString* _path; NSUInteger _offset; NSUInteger _size; int _file; } -@end -@implementation GCDWebServerFileResponse +@dynamic contentType, lastModifiedDate, eTag; + (instancetype)responseWithFile:(NSString*)path { return [[[self class] alloc] initWithFile:path]; @@ -59,26 +57,26 @@ + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range { } + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { - return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment]; + return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO]; + return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment]; + return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range { - return [self initWithFile:path byteRange:range isAttachment:NO]; + return [self initWithFile:path byteRange:range isAttachment:NO mimeTypeOverrides:nil]; } static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) { return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)]; } -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { +- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(NSDictionary*)overrides { struct stat info; if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) { GWS_DNOT_REACHED(); @@ -91,7 +89,7 @@ - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachme } #endif NSUInteger fileSize = (NSUInteger)info.st_size; - + BOOL hasByteRange = GCDWebServerIsValidByteRange(range); if (hasByteRange) { if (range.location != NSUIntegerMax) { @@ -108,7 +106,7 @@ - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachme range.location = 0; range.length = fileSize; } - + if ((self = [super init])) { _path = [path copy]; _offset = range.location; @@ -118,7 +116,7 @@ - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachme [self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"]; GWS_LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path); } - + if (attachment) { NSString* fileName = [path lastPathComponent]; NSData* data = [[fileName stringByReplacingOccurrencesOfString:@"\"" withString:@""] dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:YES]; @@ -130,8 +128,8 @@ - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachme GWS_DNOT_REACHED(); } } - - self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension]); + + self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension], overrides); self.contentLength = _size; self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec); self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec]; diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h index 2731b7c..bb48e66 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.h @@ -27,12 +27,14 @@ #import "GCDWebServerResponse.h" +NS_ASSUME_NONNULL_BEGIN + /** * The GCDWebServerStreamBlock is called to stream the data for the HTTP body. * The block must return either a chunk of data, an empty NSData when done, or * nil on error and set the "error" argument which is guaranteed to be non-NULL. */ -typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); +typedef NSData* _Nullable (^GCDWebServerStreamBlock)(NSError** error); /** * The GCDWebServerAsyncStreamBlock works like the GCDWebServerStreamBlock @@ -51,6 +53,7 @@ typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlo * the body of the HTTP response using a GCD block. */ @interface GCDWebServerStreamedResponse : GCDWebServerResponse +@property(nonatomic, copy) NSString* contentType; // Redeclare as non-null /** * Creates a response with streamed data and a given content type. @@ -73,3 +76,5 @@ typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlo - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.m b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.m index 4669617..9387263 100644 --- a/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.m +++ b/src/ios/GCDWebServer/GCDWebServer/Responses/GCDWebServerStreamedResponse.m @@ -31,13 +31,11 @@ #import "GCDWebServerPrivate.h" -@interface GCDWebServerStreamedResponse () { -@private +@implementation GCDWebServerStreamedResponse { GCDWebServerAsyncStreamBlock _block; } -@end -@implementation GCDWebServerStreamedResponse +@dynamic contentType; + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { return [[[self class] alloc] initWithContentType:type streamBlock:block]; @@ -48,19 +46,20 @@ + (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWeb } - (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block { - return [self initWithContentType:type asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { - - NSError* error = nil; - NSData* data = block(&error); - completionBlock(data, error); - - }]; + return [self initWithContentType:type + asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { + + NSError* error = nil; + NSData* data = block(&error); + completionBlock(data, error); + + }]; } - (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block { if ((self = [super init])) { _block = [block copy]; - + self.contentType = type; } return self; diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Info.plist b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Info.plist similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Info.plist rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Info.plist diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/bootstrap-theme.css b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/bootstrap-theme.css similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/bootstrap-theme.css rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/bootstrap-theme.css diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/bootstrap.css b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/bootstrap.css similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/bootstrap.css rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/bootstrap.css diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/index.css b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/index.css similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/index.css rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/index.css diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/jquery.fileupload.css b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/jquery.fileupload.css similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/css/jquery.fileupload.css rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/css/jquery.fileupload.css diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/en.lproj/Localizable.strings b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/en.lproj/Localizable.strings similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/en.lproj/Localizable.strings rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/en.lproj/Localizable.strings diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.eot b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.eot rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.eot diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.svg b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.svg rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.svg diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.ttf b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.ttf rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.ttf diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.woff b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/fonts/glyphicons-halflings-regular.woff rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/fonts/glyphicons-halflings-regular.woff diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/index.html b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/index.html similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/index.html rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/index.html diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/bootstrap.min.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/bootstrap.min.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/bootstrap.min.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/bootstrap.min.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/html5shiv.min.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/html5shiv.min.js old mode 100755 new mode 100644 similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/html5shiv.min.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/html5shiv.min.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/index.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/index.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/index.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/index.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.fileupload.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.fileupload.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.fileupload.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.fileupload.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.iframe-transport.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.iframe-transport.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.iframe-transport.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.iframe-transport.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.jeditable.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.jeditable.js old mode 100755 new mode 100644 similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.jeditable.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.jeditable.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.min.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.min.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.min.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.min.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.ui.widget.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.ui.widget.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/jquery.ui.widget.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/jquery.ui.widget.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/respond.min.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/respond.min.js old mode 100755 new mode 100644 similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/respond.min.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/respond.min.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/tmpl.min.js b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/tmpl.min.js similarity index 100% rename from src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/js/tmpl.min.js rename to src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.bundle/Contents/Resources/js/tmpl.min.js diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.h b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.h index d2c92e9..2332ba1 100644 --- a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.h +++ b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.h @@ -27,6 +27,8 @@ #import "GCDWebServer.h" +NS_ASSUME_NONNULL_BEGIN + @class GCDWebUploader; /** @@ -84,7 +86,7 @@ /** * Sets the delegate for the uploader. */ -@property(nonatomic, assign) id delegate; +@property(nonatomic, weak, nullable) id delegate; /** * Sets which files are allowed to be operated on depending on their extension. @@ -195,3 +197,5 @@ - (BOOL)shouldCreateDirectoryAtPath:(NSString*)path; @end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.m b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.m index 9bb4453..ada6417 100644 --- a/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.m +++ b/src/ios/GCDWebServer/GCDWebUploader/GCDWebUploader.m @@ -46,17 +46,149 @@ #import "GCDWebServerErrorResponse.h" #import "GCDWebServerFileResponse.h" -@interface GCDWebUploader () { -@private - NSString* _uploadDirectory; - NSArray* _allowedExtensions; - BOOL _allowHidden; - NSString* _title; - NSString* _header; - NSString* _prologue; - NSString* _epilogue; - NSString* _footer; +NS_ASSUME_NONNULL_BEGIN + +@interface GCDWebUploader (Methods) +- (nullable GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request; +- (nullable GCDWebServerResponse*)uploadFile:(GCDWebServerMultiPartFormRequest*)request; +- (nullable GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request; +- (nullable GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request; +- (nullable GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)request; +@end + +NS_ASSUME_NONNULL_END + +@implementation GCDWebUploader + +@dynamic delegate; + +- (instancetype)initWithUploadDirectory:(NSString*)path { + if ((self = [super init])) { + NSString* bundlePath = [[NSBundle bundleForClass:[GCDWebUploader class]] pathForResource:@"GCDWebUploader" ofType:@"bundle"]; + if (bundlePath == nil) { + return nil; + } + NSBundle* siteBundle = [NSBundle bundleWithPath:bundlePath]; + if (siteBundle == nil) { + return nil; + } + _uploadDirectory = [[path stringByStandardizingPath] copy]; + GCDWebUploader* __unsafe_unretained server = self; + + // Resource files + [self addGETHandlerForBasePath:@"/" directoryPath:(NSString*)[siteBundle resourcePath] indexFilename:nil cacheAge:3600 allowRangeRequests:NO]; + + // Web page + [self addHandlerForMethod:@"GET" + path:@"/" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + +#if TARGET_OS_IPHONE + NSString* device = [[UIDevice currentDevice] name]; +#else + NSString* device = CFBridgingRelease(SCDynamicStoreCopyComputerName(NULL, NULL)); +#endif + NSString* title = server.title; + if (title == nil) { + title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + if (title == nil) { + title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; + } +#if !TARGET_OS_IPHONE + if (title == nil) { + title = [[NSProcessInfo processInfo] processName]; + } +#endif + } + NSString* header = server.header; + if (header == nil) { + header = title; + } + NSString* prologue = server.prologue; + if (prologue == nil) { + prologue = [siteBundle localizedStringForKey:@"PROLOGUE" value:@"" table:nil]; + } + NSString* epilogue = server.epilogue; + if (epilogue == nil) { + epilogue = [siteBundle localizedStringForKey:@"EPILOGUE" value:@"" table:nil]; + } + NSString* footer = server.footer; + if (footer == nil) { + NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; +#if !TARGET_OS_IPHONE + if (!name && !version) { + name = @"OS X"; + version = [[NSProcessInfo processInfo] operatingSystemVersionString]; + } +#endif + footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil], name, version]; + } + return [GCDWebServerDataResponse responseWithHTMLTemplate:(NSString*)[siteBundle pathForResource:@"index" ofType:@"html"] + variables:@{ + @"device" : device, + @"title" : title, + @"header" : header, + @"prologue" : prologue, + @"epilogue" : epilogue, + @"footer" : footer + }]; + + }]; + + // File listing + [self addHandlerForMethod:@"GET" + path:@"/list" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server listDirectory:request]; + }]; + + // File download + [self addHandlerForMethod:@"GET" + path:@"/download" + requestClass:[GCDWebServerRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server downloadFile:request]; + }]; + + // File upload + [self addHandlerForMethod:@"POST" + path:@"/upload" + requestClass:[GCDWebServerMultiPartFormRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server uploadFile:(GCDWebServerMultiPartFormRequest*)request]; + }]; + + // File and folder moving + [self addHandlerForMethod:@"POST" + path:@"/move" + requestClass:[GCDWebServerURLEncodedFormRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server moveItem:(GCDWebServerURLEncodedFormRequest*)request]; + }]; + + // File and folder deletion + [self addHandlerForMethod:@"POST" + path:@"/delete" + requestClass:[GCDWebServerURLEncodedFormRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server deleteItem:(GCDWebServerURLEncodedFormRequest*)request]; + }]; + + // Directory creation + [self addHandlerForMethod:@"POST" + path:@"/create" + requestClass:[GCDWebServerURLEncodedFormRequest class] + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + return [server createDirectory:(GCDWebServerURLEncodedFormRequest*)request]; + }]; + } + return self; } + @end @implementation GCDWebUploader (Methods) @@ -67,13 +199,13 @@ - (BOOL)_checkSandboxedPath:(NSString*)path { } - (BOOL)_checkFileExtension:(NSString*)fileName { - if (_allowedExtensions && ![_allowedExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { + if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; } return YES; } -- (NSString*) _uniquePathForPath:(NSString*)path { +- (NSString*)_uniquePathForPath:(NSString*)path { if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { NSString* directory = [path stringByDeletingLastPathComponent]; NSString* file = [path lastPathComponent]; @@ -82,7 +214,7 @@ - (NSString*) _uniquePathForPath:(NSString*)path { int retries = 0; do { if (extension.length) { - path = [directory stringByAppendingPathComponent:[[base stringByAppendingFormat:@" (%i)", ++retries] stringByAppendingPathExtension:extension]]; + path = [directory stringByAppendingPathComponent:(NSString*)[[base stringByAppendingFormat:@" (%i)", ++retries] stringByAppendingPathExtension:extension]]; } else { path = [directory stringByAppendingPathComponent:[base stringByAppendingFormat:@" (%i)", ++retries]]; } @@ -101,34 +233,34 @@ - (GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request { if (!isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"\"%@\" is not a directory", relativePath]; } - + NSString* directoryName = [absolutePath lastPathComponent]; - if (!_allowHidden && [directoryName hasPrefix:@"."]) { + if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Listing directory name \"%@\" is not allowed", directoryName]; } - + NSError* error = nil; NSArray* contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:absolutePath error:&error]; if (contents == nil) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed listing directory \"%@\"", relativePath]; } - + NSMutableArray* array = [NSMutableArray array]; for (NSString* item in [contents sortedArrayUsingSelector:@selector(localizedStandardCompare:)]) { - if (_allowHidden || ![item hasPrefix:@"."]) { + if (_allowHiddenItems || ![item hasPrefix:@"."]) { NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[absolutePath stringByAppendingPathComponent:item] error:NULL]; NSString* type = [attributes objectForKey:NSFileType]; if ([type isEqualToString:NSFileTypeRegular] && [self _checkFileExtension:item]) { [array addObject:@{ - @"path": [relativePath stringByAppendingPathComponent:item], - @"name": item, - @"size": [attributes objectForKey:NSFileSize] - }]; + @"path" : [relativePath stringByAppendingPathComponent:item], + @"name" : item, + @"size" : [attributes objectForKey:NSFileSize] + }]; } else if ([type isEqualToString:NSFileTypeDirectory]) { [array addObject:@{ - @"path": [[relativePath stringByAppendingPathComponent:item] stringByAppendingString:@"/"], - @"name": item - }]; + @"path" : [[relativePath stringByAppendingPathComponent:item] stringByAppendingString:@"/"], + @"name" : item + }]; } } } @@ -145,13 +277,13 @@ - (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request { if (isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"\"%@\" is a directory", relativePath]; } - + NSString* fileName = [absolutePath lastPathComponent]; - if (([fileName hasPrefix:@"."] && !_allowHidden) || ![self _checkFileExtension:fileName]) { + if (([fileName hasPrefix:@"."] && !_allowHiddenItems) || ![self _checkFileExtension:fileName]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Downlading file name \"%@\" is not allowed", fileName]; } - - if ([self.delegate respondsToSelector:@selector(webUploader:didDownloadFileAtPath: )]) { + + if ([self.delegate respondsToSelector:@selector(webUploader:didDownloadFileAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate webUploader:self didDownloadFileAtPath:absolutePath]; }); @@ -162,9 +294,9 @@ - (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request { - (GCDWebServerResponse*)uploadFile:(GCDWebServerMultiPartFormRequest*)request { NSRange range = [[request.headers objectForKey:@"Accept"] rangeOfString:@"application/json" options:NSCaseInsensitiveSearch]; NSString* contentType = (range.location != NSNotFound ? @"application/json" : @"text/plain; charset=utf-8"); // Required when using iFrame transport (see https://github.com/blueimp/jQuery-File-Upload/wiki/Setup) - + GCDWebServerMultiPartFile* file = [request firstFileForControlName:@"files[]"]; - if ((!_allowHidden && [file.fileName hasPrefix:@"."]) || ![self _checkFileExtension:file.fileName]) { + if ((!_allowHiddenItems && [file.fileName hasPrefix:@"."]) || ![self _checkFileExtension:file.fileName]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploaded file name \"%@\" is not allowed", file.fileName]; } NSString* relativePath = [[request firstArgumentForControlName:@"path"] string]; @@ -172,16 +304,16 @@ - (GCDWebServerResponse*)uploadFile:(GCDWebServerMultiPartFormRequest*)request { if (![self _checkSandboxedPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] moveItemAtPath:file.temporaryPath toPath:absolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed moving uploaded file to \"%@\"", relativePath]; } - + if ([self.delegate respondsToSelector:@selector(webUploader:didUploadFileAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate webUploader:self didUploadFileAtPath:absolutePath]; @@ -197,27 +329,27 @@ - (GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request { if (![self _checkSandboxedPath:oldAbsolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", oldRelativePath]; } - + NSString* newRelativePath = [request.arguments objectForKey:@"newPath"]; NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:newRelativePath]]; if (![self _checkSandboxedPath:newAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", newRelativePath]; } - + NSString* itemName = [newAbsolutePath lastPathComponent]; - if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving to item name \"%@\" is not allowed", itemName]; } - + if (![self shouldMoveItemFromPath:oldAbsolutePath toPath:newAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not permitted", oldRelativePath, newRelativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] moveItemAtPath:oldAbsolutePath toPath:newAbsolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed moving \"%@\" to \"%@\"", oldRelativePath, newRelativePath]; } - + if ([self.delegate respondsToSelector:@selector(webUploader:didMoveItemFromPath:toPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate webUploader:self didMoveItemFromPath:oldAbsolutePath toPath:newAbsolutePath]; @@ -233,21 +365,21 @@ - (GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* itemName = [absolutePath lastPathComponent]; - if (([itemName hasPrefix:@"."] && !_allowHidden) || (!isDirectory && ![self _checkFileExtension:itemName])) { + if (([itemName hasPrefix:@"."] && !_allowHiddenItems) || (!isDirectory && ![self _checkFileExtension:itemName])) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting item name \"%@\" is not allowed", itemName]; } - + if (![self shouldDeleteItemAtPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting \"%@\" is not permitted", relativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] removeItemAtPath:absolutePath error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed deleting \"%@\"", relativePath]; } - + if ([self.delegate respondsToSelector:@selector(webUploader:didDeleteItemAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate webUploader:self didDeleteItemAtPath:absolutePath]; @@ -262,21 +394,21 @@ - (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)req if (![self _checkSandboxedPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } - + NSString* directoryName = [absolutePath lastPathComponent]; - if (!_allowHidden && [directoryName hasPrefix:@"."]) { + if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory name \"%@\" is not allowed", directoryName]; } - + if (![self shouldCreateDirectoryAtPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory \"%@\" is not permitted", relativePath]; } - + NSError* error = nil; if (![[NSFileManager defaultManager] createDirectoryAtPath:absolutePath withIntermediateDirectories:NO attributes:nil error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed creating directory \"%@\"", relativePath]; } - + if ([self.delegate respondsToSelector:@selector(webUploader:didCreateDirectoryAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate webUploader:self didCreateDirectoryAtPath:absolutePath]; @@ -287,117 +419,6 @@ - (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)req @end -@implementation GCDWebUploader - -@synthesize uploadDirectory=_uploadDirectory, allowedFileExtensions=_allowedExtensions, allowHiddenItems=_allowHidden, - title=_title, header=_header, prologue=_prologue, epilogue=_epilogue, footer=_footer; - -@dynamic delegate; - -- (instancetype)initWithUploadDirectory:(NSString*)path { - if ((self = [super init])) { - NSBundle* siteBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[GCDWebUploader class]] pathForResource:@"GCDWebUploader" ofType:@"bundle"]]; - if (siteBundle == nil) { - return nil; - } - _uploadDirectory = [[path stringByStandardizingPath] copy]; - GCDWebUploader* __unsafe_unretained server = self; - - // Resource files - [self addGETHandlerForBasePath:@"/" directoryPath:[siteBundle resourcePath] indexFilename:nil cacheAge:3600 allowRangeRequests:NO]; - - // Web page - [self addHandlerForMethod:@"GET" path:@"/" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - -#if TARGET_OS_IPHONE - NSString* device = [[UIDevice currentDevice] name]; -#else - NSString* device = CFBridgingRelease(SCDynamicStoreCopyComputerName(NULL, NULL)); -#endif - NSString* title = server.title; - if (title == nil) { - title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; - if (title == nil) { - title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; - } -#if !TARGET_OS_IPHONE - if (title == nil) { - title = [[NSProcessInfo processInfo] processName]; - } -#endif - } - NSString* header = server.header; - if (header == nil) { - header = title; - } - NSString* prologue = server.prologue; - if (prologue == nil) { - prologue = [siteBundle localizedStringForKey:@"PROLOGUE" value:@"" table:nil]; - } - NSString* epilogue = server.epilogue; - if (epilogue == nil) { - epilogue = [siteBundle localizedStringForKey:@"EPILOGUE" value:@"" table:nil]; - } - NSString* footer = server.footer; - if (footer == nil) { - NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; - NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; -#if !TARGET_OS_IPHONE - if (!name && !version) { - name = @"OS X"; - version = [[NSProcessInfo processInfo] operatingSystemVersionString]; - } -#endif - footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil], name, version]; - } - return [GCDWebServerDataResponse responseWithHTMLTemplate:[siteBundle pathForResource:@"index" ofType:@"html"] - variables:@{ - @"device": device, - @"title": title, - @"header": header, - @"prologue": prologue, - @"epilogue": epilogue, - @"footer": footer - }]; - - }]; - - // File listing - [self addHandlerForMethod:@"GET" path:@"/list" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server listDirectory:request]; - }]; - - // File download - [self addHandlerForMethod:@"GET" path:@"/download" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server downloadFile:request]; - }]; - - // File upload - [self addHandlerForMethod:@"POST" path:@"/upload" requestClass:[GCDWebServerMultiPartFormRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server uploadFile:(GCDWebServerMultiPartFormRequest*)request]; - }]; - - // File and folder moving - [self addHandlerForMethod:@"POST" path:@"/move" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server moveItem:(GCDWebServerURLEncodedFormRequest*)request]; - }]; - - // File and folder deletion - [self addHandlerForMethod:@"POST" path:@"/delete" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server deleteItem:(GCDWebServerURLEncodedFormRequest*)request]; - }]; - - // Directory creation - [self addHandlerForMethod:@"POST" path:@"/create" requestClass:[GCDWebServerURLEncodedFormRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - return [server createDirectory:(GCDWebServerURLEncodedFormRequest*)request]; - }]; - - } - return self; -} - -@end - @implementation GCDWebUploader (Subclassing) - (BOOL)shouldUploadFileAtPath:(NSString*)path withTemporaryFile:(NSString*)tempPath { diff --git a/src/ios/GCDWebServer/Mac/main.m b/src/ios/GCDWebServer/Mac/main.m index 33b25e5..780f5da 100644 --- a/src/ios/GCDWebServer/Mac/main.m +++ b/src/ios/GCDWebServer/Mac/main.m @@ -147,7 +147,7 @@ int main(int argc, const char* argv[]) { NSString* authenticationPassword = nil; BOOL bindToLocalhost = NO; BOOL requestNATPortMapping = NO; - + if (argc == 1) { fprintf(stdout, "Usage: %s [-mode webServer | htmlPage | htmlForm | htmlFileUpload | webDAV | webUploader | streamingResponse | asyncResponse] [-record] [-root directory] [-tests directory] [-authenticationMethod Basic | Digest] [-authenticationRealm realm] [-authenticationUser user] [-authenticationPassword password] [--localhost]\n\n", basename((char*)argv[0])); } else { @@ -201,10 +201,9 @@ int main(int argc, const char* argv[]) { } } } - + GCDWebServer* webServer = nil; switch (mode) { - // Simply serve contents of home directory case kMode_WebServer: { fprintf(stdout, "Running in Web Server mode from \"%s\"", [rootDirectory UTF8String]); @@ -212,21 +211,21 @@ int main(int argc, const char* argv[]) { [webServer addGETHandlerForBasePath:@"/" directoryPath:rootDirectory indexFilename:nil cacheAge:0 allowRangeRequests:YES]; break; } - + // Renders a HTML page case kMode_HTMLPage: { fprintf(stdout, "Running in HTML Page mode"); webServer = [[GCDWebServer alloc] init]; [webServer addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - return [GCDWebServerDataResponse responseWithHTML:@"

Hello World

"]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + return [GCDWebServerDataResponse responseWithHTML:@"

Hello World

"]; + + }]; break; } - + // Implements an HTML form case kMode_HTMLForm: { fprintf(stdout, "Running in HTML Form mode"); @@ -234,9 +233,9 @@ int main(int argc, const char* argv[]) { [webServer addHandlerForMethod:@"GET" path:@"/" requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - NSString* html = @" \ + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + NSString* html = @" \ \
\ Value: \ @@ -244,22 +243,22 @@ int main(int argc, const char* argv[]) {
\ \ "; - return [GCDWebServerDataResponse responseWithHTML:html]; - - }]; + return [GCDWebServerDataResponse responseWithHTML:html]; + + }]; [webServer addHandlerForMethod:@"POST" path:@"/" requestClass:[GCDWebServerURLEncodedFormRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - NSString* value = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:@"value"]; - NSString* html = [NSString stringWithFormat:@"

%@

", value]; - return [GCDWebServerDataResponse responseWithHTML:html]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + NSString* value = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:@"value"]; + NSString* html = [NSString stringWithFormat:@"

%@

", value]; + return [GCDWebServerDataResponse responseWithHTML:html]; + + }]; break; } - + // Implements HTML file upload case kMode_HTMLFileUpload: { fprintf(stdout, "Running in HTML File Upload mode"); @@ -274,48 +273,48 @@ int main(int argc, const char* argv[]) { [webServer addHandlerForMethod:@"GET" path:@"/" requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - NSString* html = [NSString stringWithFormat:@"%@", formHTML]; - return [GCDWebServerDataResponse responseWithHTML:html]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + NSString* html = [NSString stringWithFormat:@"%@", formHTML]; + return [GCDWebServerDataResponse responseWithHTML:html]; + + }]; [webServer addHandlerForMethod:@"POST" path:@"/" requestClass:[GCDWebServerMultiPartFormRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - NSMutableString* string = [NSMutableString string]; - for (GCDWebServerMultiPartArgument* argument in [(GCDWebServerMultiPartFormRequest*)request arguments]) { - [string appendFormat:@"%@ = %@
", argument.controlName, argument.string]; - } - for (GCDWebServerMultiPartFile* file in [(GCDWebServerMultiPartFormRequest*)request files]) { - NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:file.temporaryPath error:NULL]; - [string appendFormat:@"%@ = "%@" (%@ | %llu %@)
", file.controlName, file.fileName, file.mimeType, - attributes.fileSize >= 1000 ? attributes.fileSize / 1000 : attributes.fileSize, - attributes.fileSize >= 1000 ? @"KB" : @"Bytes"]; - }; - NSString* html = [NSString stringWithFormat:@"

%@


%@", string, formHTML]; - return [GCDWebServerDataResponse responseWithHTML:html]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + NSMutableString* string = [NSMutableString string]; + for (GCDWebServerMultiPartArgument* argument in [(GCDWebServerMultiPartFormRequest*)request arguments]) { + [string appendFormat:@"%@ = %@
", argument.controlName, argument.string]; + } + for (GCDWebServerMultiPartFile* file in [(GCDWebServerMultiPartFormRequest*)request files]) { + NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:file.temporaryPath error:NULL]; + [string appendFormat:@"%@ = "%@" (%@ | %llu %@)
", file.controlName, file.fileName, file.mimeType, + attributes.fileSize >= 1000 ? attributes.fileSize / 1000 : attributes.fileSize, + attributes.fileSize >= 1000 ? @"KB" : @"Bytes"]; + }; + NSString* html = [NSString stringWithFormat:@"

%@


%@", string, formHTML]; + return [GCDWebServerDataResponse responseWithHTML:html]; + + }]; break; } - + // Serve home directory through WebDAV case kMode_WebDAV: { fprintf(stdout, "Running in WebDAV mode from \"%s\"", [rootDirectory UTF8String]); webServer = [[GCDWebDAVServer alloc] initWithUploadDirectory:rootDirectory]; break; } - + // Serve home directory through web uploader case kMode_WebUploader: { fprintf(stdout, "Running in Web Uploader mode from \"%s\"", [rootDirectory UTF8String]); webServer = [[GCDWebUploader alloc] initWithUploadDirectory:rootDirectory]; break; } - + // Test streaming responses case kMode_StreamingResponse: { fprintf(stdout, "Running in Streaming Response mode"); @@ -323,42 +322,44 @@ int main(int argc, const char* argv[]) { [webServer addHandlerForMethod:@"GET" path:@"/sync" requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - __block int countDown = 10; - return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" streamBlock:^NSData *(NSError** error) { - - usleep(100 * 1000); - if (countDown) { - return [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding]; - } else { - return [NSData data]; - } - - }]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + __block int countDown = 10; + return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" + streamBlock:^NSData*(NSError** error) { + + usleep(100 * 1000); + if (countDown) { + return [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding]; + } else { + return [NSData data]; + } + + }]; + + }]; [webServer addHandlerForMethod:@"GET" path:@"/async" requestClass:[GCDWebServerRequest class] - processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - __block int countDown = 10; - return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - - NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data]; - completionBlock(data, nil); - - }); - - }]; - - }]; + processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { + + __block int countDown = 10; + return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" + asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data]; + completionBlock(data, nil); + + }); + + }]; + + }]; break; } - + // Test async responses case kMode_AsyncResponse: { fprintf(stdout, "Running in Async Response mode"); @@ -367,41 +368,41 @@ int main(int argc, const char* argv[]) { path:@"/async" requestClass:[GCDWebServerRequest class] asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:[@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding] contentType:@"text/plain"]; - completionBlock(response); - }); - - }]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:(NSData*)[@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding] contentType:@"text/plain"]; + completionBlock(response); + }); + + }]; [webServer addHandlerForMethod:@"GET" path:@"/async2" requestClass:[GCDWebServerRequest class] asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock handlerCompletionBlock) { - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - - __block int countDown = 10; - GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock readerCompletionBlock) { - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - - NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data]; - readerCompletionBlock(data, nil); - - }); - - }]; - handlerCompletionBlock(response); - - }); - - }]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + __block int countDown = 10; + GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" + asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock readerCompletionBlock) { + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data]; + readerCompletionBlock(data, nil); + + }); + + }]; + handlerCompletionBlock(response); + + }); + + }]; break; } - } - + if (webServer) { Delegate* delegate = [[Delegate alloc] init]; if (testDirectory) { @@ -409,7 +410,7 @@ int main(int argc, const char* argv[]) { webServer.delegate = delegate; #endif fprintf(stdout, "\n\n", [testDirectory UTF8String]); - result = (int)[webServer runTestsWithOptions:@{GCDWebServerOption_Port: @8080} inDirectory:testDirectory]; + result = (int)[webServer runTestsWithOptions:@{ GCDWebServerOption_Port : @8080 } inDirectory:testDirectory]; } else { webServer.delegate = delegate; if (recording) { @@ -424,7 +425,7 @@ int main(int argc, const char* argv[]) { [options setObject:@"" forKey:GCDWebServerOption_BonjourName]; if (authenticationUser && authenticationPassword) { [options setValue:authenticationRealm forKey:GCDWebServerOption_AuthenticationRealm]; - [options setObject:@{authenticationUser: authenticationPassword} forKey:GCDWebServerOption_AuthenticationAccounts]; + [options setObject:@{authenticationUser : authenticationPassword} forKey:GCDWebServerOption_AuthenticationAccounts]; if ([authenticationMethod isEqualToString:@"Basic"]) { [options setObject:GCDWebServerAuthenticationMethod_Basic forKey:GCDWebServerOption_AuthenticationMethod]; } else if ([authenticationMethod isEqualToString:@"Digest"]) { diff --git a/src/ios/GCDWebServer/README.md b/src/ios/GCDWebServer/README.md index b18020d..84545c4 100644 --- a/src/ios/GCDWebServer/README.md +++ b/src/ios/GCDWebServer/README.md @@ -36,7 +36,7 @@ What's not supported (but not really required from an embedded HTTP server): Requirements: * OS X 10.7 or later (x86_64) -* iOS 5.0 or later (armv7, armv7s or arm64) +* iOS 8.0 or later (armv7, armv7s or arm64) * ARC memory management only (if you need MRC support use GCDWebServer 3.1 and earlier) Getting Started @@ -71,9 +71,9 @@ Then run `$ carthage update` and add the generated frameworks to your Xcode proj Help & Support ============== -For help with using GCDWebServer, it's best to ask your question on Stack Overflow with the [`gcdwebserver`](http://stackoverflow.com/questions/tagged/gcdwebserver) tag. Be sure to read this entire README first though! +For help with using GCDWebServer, it's best to ask your question on Stack Overflow with the [`gcdwebserver`](http://stackoverflow.com/questions/tagged/gcdwebserver) tag. For bug reports and enhancement requests you can use [issues](https://github.com/swisspol/GCDWebServer/issues) in this project. -For bug reports or enhancement requests, please use [GitHub issues](https://github.com/swisspol/GCDWebServer/issues) instead. +Be sure to read this entire README first though! Hello World =========== @@ -153,7 +153,7 @@ int main(int argc, const char* argv[]) { ***webServer.swift*** ```swift import Foundation -import GCDWebServers +import GCDWebServer func initWebServer() { @@ -172,8 +172,8 @@ func initWebServer() { ***WebServer-Bridging-Header.h*** ```objectivec -#import -#import +#import +#import ``` Web Based Uploads in iOS Apps @@ -276,7 +276,7 @@ GCDWebServer's architecture consists of only 4 core classes: Implementing Handlers ===================== -GCDWebServer relies on "handlers" to process incoming web requests and generating responses. Handlers are implemented with GCD blocks which makes it very easy to provide your owns. However, they are executed on arbitrary threads within GCD so __special attention must be paid to thread-safety and re-entrancy__. +GCDWebServer relies on "handlers" to process incoming web requests and generating responses. Handlers are implemented with GCD blocks which makes it very easy to provide your own. However, they are executed on arbitrary threads within GCD so __special attention must be paid to thread-safety and re-entrancy__. Handlers require 2 GCD blocks: * The ```GCDWebServerMatchBlock``` is called on every handler added to the ```GCDWebServer``` instance whenever a web request has started (i.e. HTTP headers have been received). It is passed the basic info for the web request (HTTP method, URL, headers...) and must decide if it wants to handle it or not. If yes, it must return a new ```GCDWebServerRequest``` instance (see above) created with this info. Otherwise, it simply returns nil. @@ -287,7 +287,7 @@ Note that most methods on ```GCDWebServer``` to add handlers only require the `` Asynchronous HTTP Responses =========================== -New in GCDWebServer 3.0 is the ability to process HTTP requests aysnchronously i.e. add handlers to the server which generate their ```GCDWebServerResponse``` asynchronously. This is achieved by adding handlers that use a ```GCDWebServerAsyncProcessBlock``` instead of a ```GCDWebServerProcessBlock```. Here's an example: +New in GCDWebServer 3.0 is the ability to process HTTP requests asynchronously i.e. add handlers to the server which generate their ```GCDWebServerResponse``` asynchronously. This is achieved by adding handlers that use a ```GCDWebServerAsyncProcessBlock``` instead of a ```GCDWebServerProcessBlock```. Here's an example: **(Synchronous version)** The handler blocks while generating the HTTP response: ```objectivec diff --git a/src/ios/GCDWebServer/Run-Tests.sh b/src/ios/GCDWebServer/Run-Tests.sh index 0e180fe..3119d88 100755 --- a/src/ios/GCDWebServer/Run-Tests.sh +++ b/src/ios/GCDWebServer/Run-Tests.sh @@ -58,7 +58,7 @@ xcodebuild build -sdk "$OSX_SDK" -target "$OSX_TARGET" -configuration "$CONFIGUR # Build for iOS for oldest supported deployment target rm -rf "$BUILD_DIR" -xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=6.0" > /dev/null +xcodebuild build -sdk "$IOS_SDK" -target "$IOS_TARGET" -configuration "$CONFIGURATION" "SYMROOT=$BUILD_DIR" "IPHONEOS_DEPLOYMENT_TARGET=8.0" > /dev/null # Build for iOS for current deployment target rm -rf "$BUILD_DIR" diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/001-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/001-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/001-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/001-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/002-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/002-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/002-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/002-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/003-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/003-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/003-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/003-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/004-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/004-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/004-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/004-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/005-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/005-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/005-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/005-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/006-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/006-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/006-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/006-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/007-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/007-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/007-COPY.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/007-COPY.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/008-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/008-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/008-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/008-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/009-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/009-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/009-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/009-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/010-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/010-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/010-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/010-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/011-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/011-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/011-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/011-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/012-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/012-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/012-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/012-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/013-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/013-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/013-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/013-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/014-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/014-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/014-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/014-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/015-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/015-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/015-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/015-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/016-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/016-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/016-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/016-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/017-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/017-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/017-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/017-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/018-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/018-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/018-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/018-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/019-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/019-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/019-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/019-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/020-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/020-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/020-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/020-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/021-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/021-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/021-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/021-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/022-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/022-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/022-HEAD.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/022-HEAD.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/023-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/023-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/023-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/023-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/024-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/024-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/024-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/024-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/025-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/025-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/025-MKCOL.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/025-MKCOL.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/026-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/026-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/026-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/026-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/027-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/027-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/027-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/027-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/028-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/028-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/028-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/028-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/029-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/029-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/029-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/029-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/030-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/030-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/030-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/030-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/031-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/031-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/031-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/031-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/032-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/032-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/032-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/032-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/033-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/033-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/033-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/033-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/034-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/034-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/034-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/034-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/035-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/035-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/035-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/035-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/036-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/036-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/036-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Cyberduck/036-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/001-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/001-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/001-OPTIONS.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/001-OPTIONS.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/002-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/002-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/002-OPTIONS.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/002-OPTIONS.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/003-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/003-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/003-OPTIONS.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/003-OPTIONS.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/004-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/004-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/004-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/004-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/005-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/005-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/005-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/005-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/006-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/006-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/006-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/006-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/007-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/007-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/007-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/007-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/008-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/008-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/008-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/008-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/009-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/009-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/009-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/009-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/010-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/010-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/010-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/010-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/011-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/011-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/011-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/011-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/012-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/012-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/012-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/012-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/013-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/013-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/013-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/013-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/014-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/014-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/014-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/014-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/015-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/015-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/015-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/015-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/016-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/016-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/016-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/016-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/017-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/017-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/017-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/017-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/018-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/018-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/018-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/018-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/019-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/019-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/019-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/019-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/020-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/020-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/020-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/020-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/021-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/021-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/021-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/021-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/022-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/022-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/022-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/022-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/023-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/023-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/023-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/023-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/024-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/024-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/024-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/024-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/025-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/025-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/025-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/025-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/026-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/026-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/026-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/026-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/027-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/027-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/027-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/027-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/028-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/028-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/028-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/028-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/029-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/029-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/029-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/029-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/030-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/030-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/030-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/030-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/031-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/031-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/031-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/031-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/032-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/032-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/032-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/032-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/033-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/033-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/033-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/033-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/034-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/034-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/034-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/034-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/035-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/035-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/035-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/035-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/036-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/036-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/036-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/036-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/037-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/037-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/037-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/037-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/038-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/038-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/038-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/038-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/039-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/039-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/039-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/039-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/040-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/040-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/040-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/040-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/041-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/041-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/041-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/041-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/042-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/042-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/042-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/042-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/043-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/043-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/043-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/043-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/044-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/044-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/044-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/044-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/045-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/045-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/045-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/045-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/046-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/046-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/046-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/046-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/047-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/047-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/047-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/047-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/048-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/048-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/048-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/048-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/049-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/049-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/049-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/049-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/050-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/050-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/050-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/050-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/051-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/051-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/051-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/051-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/052-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/052-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/052-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/052-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/053-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/053-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/053-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/053-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/054-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/054-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/054-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/054-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/055-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/055-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/055-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/055-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/056-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/056-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/056-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/056-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/057-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/057-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/057-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/057-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/058-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/058-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/058-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/058-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-200.response deleted file mode 100755 index 92ae6ab..0000000 Binary files a/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-200.response and /dev/null differ diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-206.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-206.response new file mode 100644 index 0000000..a2a7c8c Binary files /dev/null and b/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-206.response differ diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/059-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/060-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/060-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/060-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/060-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/061-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/061-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/061-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/061-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-200.response deleted file mode 100755 index 313335e..0000000 Binary files a/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-200.response and /dev/null differ diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-206.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-206.response new file mode 100644 index 0000000..79f364e Binary files /dev/null and b/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-206.response differ diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/062-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/063-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/063-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/063-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/063-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/064-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/064-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/064-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/064-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/065-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/065-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/065-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/065-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/066-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/066-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/066-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/066-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/067-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/067-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/067-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/067-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/068-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/068-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/068-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/068-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/069-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/069-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/069-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/069-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/070-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/070-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/070-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/070-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/071-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/071-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/071-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/071-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/072-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/072-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/072-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/072-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/073-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/073-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/073-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/073-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/074-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/074-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/074-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/074-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/075-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/075-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/075-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/075-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/076-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/076-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/076-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/076-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/077-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/077-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/077-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/077-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/078-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/078-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/078-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/078-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/079-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/079-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/079-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/079-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/080-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/080-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/080-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/080-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/081-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/081-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/081-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/081-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/082-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/082-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/082-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/082-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/083-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/083-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/083-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/083-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/084-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/084-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/084-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/084-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/085-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/085-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/085-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/085-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/086-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/086-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/086-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/086-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/087-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/087-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/087-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/087-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/088-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/088-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/088-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/088-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/089-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/089-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/089-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/089-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/090-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/090-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/090-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/090-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/091-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/091-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/091-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/091-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/092-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/092-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/092-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/092-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/093-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/093-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/093-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/093-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/094-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/094-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/094-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/094-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/095-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/095-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/095-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/095-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/096-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/096-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/096-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/096-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/097-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/097-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/097-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/097-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/098-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/098-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/098-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/098-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/099-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/099-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/099-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/099-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/100-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/100-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/100-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/100-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/101-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/101-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/101-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/101-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/102-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/102-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/102-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/102-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/103-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/103-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/103-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/103-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/104-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/104-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/104-LOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/104-LOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/105-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/105-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/105-UNLOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/105-UNLOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/106-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/106-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/106-LOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/106-LOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/107-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/107-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/107-UNLOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/107-UNLOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/108-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/108-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/108-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/108-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/109-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/109-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/109-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/109-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/110-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/110-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/110-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/110-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/111-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/111-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/111-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/111-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/112-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/112-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/112-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/112-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/113-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/113-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/113-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/113-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/114-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/114-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/114-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/114-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/115-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/115-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/115-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/115-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/116-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/116-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/116-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/116-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/117-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/117-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/117-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/117-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/118-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/118-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/118-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/118-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/119-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/119-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/119-LOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/119-LOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/120-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/120-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/120-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/120-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/121-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/121-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/121-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/121-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/122-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/122-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/122-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/122-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/123-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/123-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/123-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/123-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/124-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/124-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/124-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/124-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/125-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/125-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/125-UNLOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/125-UNLOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/126-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/126-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/126-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/126-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/127-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/127-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/127-LOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/127-LOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/128-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/128-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/128-UNLOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/128-UNLOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/129-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/129-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/129-LOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/129-LOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/130-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/130-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/130-UNLOCK.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/130-UNLOCK.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/131-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/131-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/131-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/131-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/132-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/132-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/132-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/132-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/133-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/133-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/133-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/133-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/134-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/134-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/134-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/134-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/135-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/135-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/135-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/135-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/136-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/136-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/136-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/136-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/137-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/137-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/137-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/137-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/138-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/138-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/138-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/138-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/139-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/139-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/139-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/139-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/140-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/140-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/140-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/140-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/141-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/141-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/141-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/141-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/142-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/142-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/142-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/142-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/143-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/143-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/143-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/143-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/144-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/144-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/144-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/144-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/145-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/145-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/145-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/145-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/146-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/146-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/146-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/146-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/147-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/147-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/147-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/147-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/148-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/148-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/148-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/148-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/149-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/149-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/149-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/149-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/150-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/150-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/150-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/150-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/151-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/151-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/151-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/151-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/152-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/152-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/152-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/152-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/153-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/153-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/153-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/153-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/154-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/154-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/154-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/154-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/155-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/155-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/155-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/155-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/156-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/156-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/156-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/156-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/157-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/157-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/157-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/157-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/158-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/158-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/158-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/158-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/159-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/159-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/159-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/159-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/160-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/160-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/160-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/160-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/161-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/161-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/161-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/161-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/162-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/162-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/162-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/162-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/163-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/163-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/163-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/163-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/164-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/164-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/164-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/164-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/165-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/165-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/165-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/165-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/166-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/166-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/166-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/166-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/167-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/167-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/167-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/167-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/168-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/168-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/168-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/168-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/169-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/169-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/169-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/169-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/170-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/170-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/170-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/170-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/171-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/171-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/171-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/171-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/172-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/172-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/172-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/172-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/173-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/173-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/173-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/173-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/174-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/174-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/174-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/174-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/175-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/175-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/175-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/175-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/176-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/176-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/176-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/176-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/177-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/177-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/177-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/177-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/178-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/178-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/178-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/178-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/179-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/179-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/179-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/179-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/180-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/180-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/180-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/180-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/181-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/181-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/181-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/181-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/182-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/182-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/182-MKCOL.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/182-MKCOL.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/183-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/183-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/183-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/183-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/184-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/184-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/184-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/184-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/185-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/185-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/185-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/185-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/186-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/186-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/186-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/186-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/187-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/187-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/187-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/187-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/188-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/188-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/188-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/188-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/189-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/189-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/189-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/189-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/190-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/190-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/190-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/190-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/191-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/191-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/191-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/191-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/192-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/192-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/192-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/192-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/193-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/193-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/193-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/193-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/194-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/194-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/194-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/194-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/195-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/195-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/195-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/195-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/196-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/196-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/196-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/196-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/197-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/197-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/197-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/197-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/198-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/198-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/198-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/198-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/199-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/199-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/199-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/199-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/200-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/200-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/200-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/200-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/201-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/201-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/201-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/201-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/202-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/202-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/202-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/202-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/203-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/203-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/203-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/203-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/204-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/204-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/204-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/204-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/205-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/205-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/205-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/205-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/206-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/206-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/206-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/206-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/207-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/207-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/207-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/207-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/208-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/208-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/208-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/208-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/209-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/209-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/209-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/209-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/210-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/210-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/210-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/210-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/211-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/211-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/211-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/211-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/212-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/212-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/212-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/212-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/213-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/213-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/213-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/213-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/214-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/214-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/214-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/214-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/215-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/215-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/215-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/215-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/216-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/216-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/216-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/216-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/217-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/217-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/217-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/217-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/218-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/218-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/218-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/218-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/219-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/219-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/219-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/219-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/220-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/220-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/220-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/220-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/221-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/221-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/221-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/221-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/222-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/222-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/222-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/222-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/223-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/223-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/223-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/223-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/224-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/224-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/224-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/224-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/225-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/225-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/225-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/225-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/226-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/226-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/226-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/226-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/227-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/227-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/227-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/227-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/228-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/228-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/228-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/228-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/229-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/229-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/229-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/229-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/230-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/230-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/230-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/230-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/231-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/231-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/231-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/231-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/232-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/232-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/232-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/232-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/233-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/233-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/233-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/233-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/234-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/234-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/234-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/234-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/235-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/235-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/235-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/235-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/236-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/236-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/236-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/236-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/237-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/237-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/237-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/237-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/238-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/238-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/238-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/238-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/239-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/239-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/239-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/239-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/240-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/240-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/240-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/240-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/241-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/241-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/241-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/241-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/242-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/242-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/242-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/242-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/243-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/243-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/243-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/243-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/244-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/244-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/244-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/244-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/245-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/245-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/245-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/245-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/246-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/246-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/246-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/246-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/247-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/247-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/247-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/247-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/248-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/248-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/248-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/248-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/249-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/249-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/249-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/249-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/250-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/250-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/250-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/250-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/251-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/251-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/251-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/251-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/252-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/252-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/252-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/252-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/253-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/253-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/253-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/253-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/254-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/254-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/254-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/254-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/255-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/255-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/255-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/255-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/256-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/256-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/256-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/256-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/257-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/257-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/257-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/257-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/258-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/258-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/258-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/258-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/259-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/259-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/259-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/259-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/260-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/260-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/260-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/260-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/261-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/261-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/261-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/261-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/262-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/262-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/262-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/262-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/263-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/263-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/263-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/263-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/264-403.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/264-403.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/264-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/264-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/265-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/265-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/265-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/265-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/266-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/266-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/266-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/266-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/267-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/267-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/267-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/267-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/268-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/268-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/268-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/268-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/269-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/269-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/269-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/269-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/270-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/270-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/270-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/270-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/271-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/271-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/271-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/271-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/272-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/272-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/272-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/272-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/273-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/273-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/273-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/273-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/274-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/274-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/274-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/274-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/275-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/275-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/275-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/275-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/276-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/276-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/276-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/276-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/277-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/277-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/277-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/277-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/278-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/278-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/278-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/278-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/279-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/279-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/279-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/279-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/280-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/280-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/280-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/280-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/281-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/281-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/281-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/281-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/282-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/282-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/282-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/282-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/283-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/283-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/283-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/283-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/284-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/284-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/284-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/284-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/285-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/285-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/285-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/285-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/286-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/286-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/286-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/286-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/287-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/287-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/287-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/287-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/288-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/288-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/288-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/288-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/289-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/289-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/289-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/289-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/290-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/290-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/290-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/290-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/291-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/291-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/291-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/291-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/292-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/292-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/292-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/292-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/293-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/293-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/293-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/293-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/294-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/294-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/294-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/294-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/295-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/295-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/295-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/295-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/296-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/296-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/296-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/296-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/297-404.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/297-404.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/297-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/297-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/298-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Finder/298-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Finder/298-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Finder/298-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/001-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/001-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/001-OPTIONS.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/001-OPTIONS.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/002-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/002-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/002-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/002-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/003-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/003-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/003-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/003-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/004-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/004-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/004-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/004-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/005-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/005-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/005-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/005-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/006-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/006-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/006-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/006-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/007-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/007-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/007-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/007-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/008-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/008-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/008-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/008-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/009-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/009-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/009-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/009-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/010-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/010-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/010-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/010-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/011-200.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/011-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/011-GET.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/011-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/012-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/012-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/012-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/012-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/013-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/013-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/013-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/013-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/014-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/014-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/014-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/014-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/015-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/015-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/015-PUT.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/015-PUT.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/016-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/016-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/016-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/016-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/017-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/017-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/017-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/017-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/018-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/018-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/018-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/018-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/019-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/019-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/019-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/019-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/020-207.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/020-207.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/020-PROPFIND.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/020-PROPFIND.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/021-204.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/021-204.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/021-DELETE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/021-DELETE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/022-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/022-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/022-MKCOL.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/022-MKCOL.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/023-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/023-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/023-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/023-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/024-201.response b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/024-201.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebDAV-Transmit/024-MOVE.request b/src/ios/GCDWebServer/Tests/WebDAV-Transmit/024-MOVE.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/018-200.response b/src/ios/GCDWebServer/Tests/WebUploader/018-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/018-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/018-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/019-200.response b/src/ios/GCDWebServer/Tests/WebUploader/019-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/019-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/019-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/020-200.response b/src/ios/GCDWebServer/Tests/WebUploader/020-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/020-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/020-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/022-200.response b/src/ios/GCDWebServer/Tests/WebUploader/022-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/022-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/022-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/023-200.response b/src/ios/GCDWebServer/Tests/WebUploader/023-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/023-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/023-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/024-200.response b/src/ios/GCDWebServer/Tests/WebUploader/024-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/024-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/024-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/025-200.response b/src/ios/GCDWebServer/Tests/WebUploader/025-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/025-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/025-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/026-200.response b/src/ios/GCDWebServer/Tests/WebUploader/026-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/026-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/026-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/027-200.response b/src/ios/GCDWebServer/Tests/WebUploader/027-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/027-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/027-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/028-200.response b/src/ios/GCDWebServer/Tests/WebUploader/028-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/028-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/028-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/029-200.response b/src/ios/GCDWebServer/Tests/WebUploader/029-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/029-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/029-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/030-200.response b/src/ios/GCDWebServer/Tests/WebUploader/030-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/030-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/030-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/031-200.response b/src/ios/GCDWebServer/Tests/WebUploader/031-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/031-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/031-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/032-200.response b/src/ios/GCDWebServer/Tests/WebUploader/032-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/032-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/032-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/033-200.response b/src/ios/GCDWebServer/Tests/WebUploader/033-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/033-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/033-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/034-200.response b/src/ios/GCDWebServer/Tests/WebUploader/034-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/034-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/034-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/035-200.response b/src/ios/GCDWebServer/Tests/WebUploader/035-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/035-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/035-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/036-200.response b/src/ios/GCDWebServer/Tests/WebUploader/036-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/036-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/036-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/037-200.response b/src/ios/GCDWebServer/Tests/WebUploader/037-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/037-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/037-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/038-200.response b/src/ios/GCDWebServer/Tests/WebUploader/038-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/038-POST.request b/src/ios/GCDWebServer/Tests/WebUploader/038-POST.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/039-200.response b/src/ios/GCDWebServer/Tests/WebUploader/039-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/039-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/039-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/040-200.response b/src/ios/GCDWebServer/Tests/WebUploader/040-200.response old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/Tests/WebUploader/040-GET.request b/src/ios/GCDWebServer/Tests/WebUploader/040-GET.request old mode 100755 new mode 100644 diff --git a/src/ios/GCDWebServer/format-source.sh b/src/ios/GCDWebServer/format-source.sh new file mode 100755 index 0000000..b7f7d7c --- /dev/null +++ b/src/ios/GCDWebServer/format-source.sh @@ -0,0 +1,40 @@ +#!/bin/sh -ex + +# brew install clang-format + +CLANG_FORMAT_VERSION=`clang-format -version | awk '{ print $3 }'` +if [[ "$CLANG_FORMAT_VERSION" != "5.0.0" ]]; then + echo "Unsupported clang-format version" + exit 1 +fi + +pushd "GCDWebServer/Core" +clang-format -style=file -i *.h *.m +popd +pushd "GCDWebServer/Requests" +clang-format -style=file -i *.h *.m +popd +pushd "GCDWebServer/Responses" +clang-format -style=file -i *.h *.m +popd +pushd "GCDWebUploader" +clang-format -style=file -i *.h *.m +popd +pushd "GCDWebDAVServer" +clang-format -style=file -i *.h *.m +popd + +pushd "Frameworks" +clang-format -style=file -i *.h *.m +popd +pushd "Mac" +clang-format -style=file -i *.m +popd +pushd "iOS" +clang-format -style=file -i *.h *.m +popd +pushd "tvOS" +clang-format -style=file -i *.h *.m +popd + +echo "OK" diff --git a/src/ios/GCDWebServer/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/src/ios/GCDWebServer/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json index 36d2c80..1d060ed 100644 --- a/src/ios/GCDWebServer/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/src/ios/GCDWebServer/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -59,6 +79,11 @@ "idiom" : "ipad", "size" : "76x76", "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" } ], "info" : { diff --git a/src/ios/GCDWebServer/iOS/ViewController.m b/src/ios/GCDWebServer/iOS/ViewController.m index 2f7d79d..fbeae6b 100644 --- a/src/ios/GCDWebServer/iOS/ViewController.m +++ b/src/ios/GCDWebServer/iOS/ViewController.m @@ -39,7 +39,7 @@ @implementation ViewController { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - + NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; _webServer = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath]; _webServer.delegate = self; @@ -53,7 +53,7 @@ - (void)viewWillAppear:(BOOL)animated { - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; - + [_webServer stop]; _webServer = nil; } diff --git a/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json index 6a3dcfa..dea6e49 100644 --- a/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +++ b/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -12,6 +12,12 @@ "filename" : "App Icon - Small.imagestack", "role" : "primary-app-icon" }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, { "size" : "1920x720", "idiom" : "tv", @@ -23,4 +29,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/src/ios/GCDWebServer/tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/src/ios/GCDWebServer/tvOS/ViewController.m b/src/ios/GCDWebServer/tvOS/ViewController.m index 2f7d79d..fbeae6b 100644 --- a/src/ios/GCDWebServer/tvOS/ViewController.m +++ b/src/ios/GCDWebServer/tvOS/ViewController.m @@ -39,7 +39,7 @@ @implementation ViewController { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - + NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; _webServer = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath]; _webServer.delegate = self; @@ -53,7 +53,7 @@ - (void)viewWillAppear:(BOOL)animated { - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; - + [_webServer stop]; _webServer = nil; }