diff --git a/GCDWebDAVServer/GCDWebDAVServer.m b/GCDWebDAVServer/GCDWebDAVServer.m index 5d8e6c2..a78d291 100644 --- a/GCDWebDAVServer/GCDWebDAVServer.m +++ b/GCDWebDAVServer/GCDWebDAVServer.m @@ -84,7 +84,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { - (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - BOOL isDirectory = YES; + BOOL isDirectory = NO; if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -92,6 +92,11 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"\"%@\" is not a file", relativePath]; } + NSString* fileName = [absolutePath lastPathComponent]; + if (([fileName hasPrefix:@"."] && !_showHidden) || ![self _checkFileExtension:fileName]) { + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Downlading file name \"%@\" is not allowed", fileName]; + } + if ([_delegate respondsToSelector:@selector(davServer:didDownloadFileAtPath:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [_delegate davServer:self didDownloadFileAtPath:absolutePath]; @@ -122,7 +127,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* fileName = [absolutePath lastPathComponent]; if (([fileName hasPrefix:@"."] && !_showHidden) || ![self _checkFileExtension:fileName]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploaded file name \"%@\" is not allowed", fileName]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file name \"%@\" is not allowed", fileName]; } if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:request.temporaryPath]) { @@ -151,12 +156,18 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![absolutePath hasPrefix:_uploadDirectory]) { + BOOL isDirectory = NO; + if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } + NSString* itemName = [absolutePath lastPathComponent]; + if (([itemName hasPrefix:@"."] && !_showHidden) || (!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 allowed", relativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting \"%@\" is not permitted", relativePath]; } NSError* error = nil; @@ -189,11 +200,11 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* directoryName = [absolutePath lastPathComponent]; if (!_showHidden && [directoryName hasPrefix:@"."]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Directory name \"%@\" is not allowed", directoryName]; + 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 allowed", relativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory \"%@\" is not permitted", relativePath]; } NSError* error = nil; @@ -239,9 +250,9 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Invalid destination \"%@\"", dstRelativePath]; } - NSString* fileName = [dstAbsolutePath lastPathComponent]; - if ((!_showHidden && [fileName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:fileName])) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Destination name \"%@\" is not allowed", fileName]; + NSString* itemName = [dstAbsolutePath lastPathComponent]; + if ((!_showHidden && [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"]; @@ -252,11 +263,11 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { if (isMove) { if (![self shouldMoveItemFromPath:srcAbsolutePath toPath:dstAbsolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not allowed", srcRelativePath, dstRelativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath]; } } else { if (![self shouldCopyItemFromPath:srcAbsolutePath toPath:dstAbsolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Copying \"%@\" to \"%@\" is not allowed", srcRelativePath, dstRelativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Copying \"%@\" to \"%@\" is not permitted", srcRelativePath, dstRelativePath]; } } @@ -411,6 +422,11 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } + NSString* itemName = [absolutePath lastPathComponent]; + if (([itemName hasPrefix:@"."] && !_showHidden) || (!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; @@ -451,7 +467,8 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath]) { + BOOL isDirectory = NO; + if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -500,6 +517,11 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking request \"%@/%@/%@\" for \"%@\" is not allowed", scope, type, depthHeader, relativePath]; } + NSString* itemName = [absolutePath lastPathComponent]; + if ((!_showHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Locking item name \"%@\" is not allowed", itemName]; + } + if (!token) { CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); CFStringRef string = CFUUIDCreateString(kCFAllocatorDefault, uuid); @@ -539,7 +561,8 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath]) { + BOOL isDirectory = NO; + if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -548,6 +571,11 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Missing 'Lock-Token' header"]; } + NSString* itemName = [absolutePath lastPathComponent]; + if ((!_showHidden && [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]; } diff --git a/GCDWebUploader/GCDWebUploader.m b/GCDWebUploader/GCDWebUploader.m index 1f28c74..466c041 100644 --- a/GCDWebUploader/GCDWebUploader.m +++ b/GCDWebUploader/GCDWebUploader.m @@ -94,6 +94,11 @@ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"\"%@\" is not a directory", relativePath]; } + NSString* directoryName = [absolutePath lastPathComponent]; + if (!_showHidden && [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) { @@ -133,6 +138,11 @@ return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"\"%@\" is a directory", relativePath]; } + NSString* fileName = [absolutePath lastPathComponent]; + if (([fileName hasPrefix:@"."] && !_showHidden) || ![self _checkFileExtension:fileName]) { + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Downlading file name \"%@\" is not allowed", fileName]; + } + if ([_delegate respondsToSelector:@selector(webUploader:didDownloadFileAtPath: )]) { dispatch_async(dispatch_get_main_queue(), ^{ [_delegate webUploader:self didDownloadFileAtPath:absolutePath]; @@ -153,7 +163,7 @@ NSString* absolutePath = [self _uniquePathForPath:[[_uploadDirectory stringByAppendingPathComponent:relativePath] stringByAppendingPathComponent:file.fileName]]; if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not allowed", file.fileName, relativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath]; } NSError* error = nil; @@ -179,22 +189,16 @@ NSString* newRelativePath = [request.arguments objectForKey:@"newPath"]; NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:newRelativePath]]; - if (!_showHidden) { - for (NSString* component in [newRelativePath pathComponents]) { - if ([component hasPrefix:@"."]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_BadRequest message:@"Item path \"%@\" is not allowed", newRelativePath]; - } - } - } - if (!isDirectory && ![self _checkFileExtension:newRelativePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Item path \"%@\" is not allowed", newRelativePath]; + + NSString* itemName = [newAbsolutePath lastPathComponent]; + if ((!_showHidden && [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 allowed", oldRelativePath, newRelativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Moving \"%@\" to \"%@\" is not permitted", oldRelativePath, newRelativePath]; } - [[NSFileManager defaultManager] createDirectoryAtPath:[newAbsolutePath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:NULL]; 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]; @@ -211,12 +215,18 @@ - (GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request { NSString* relativePath = [request.arguments objectForKey:@"path"]; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath]) { + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } + NSString* itemName = [absolutePath lastPathComponent]; + if (([itemName hasPrefix:@"."] && !_showHidden) || (!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 allowed", relativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Deleting \"%@\" is not permitted", relativePath]; } NSError* error = nil; @@ -235,20 +245,18 @@ - (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)request { NSString* relativePath = [request.arguments objectForKey:@"path"]; NSString* absolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:relativePath]]; - if (!_showHidden) { - for (NSString* component in [relativePath pathComponents]) { - if ([component hasPrefix:@"."]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Directory path \"%@\" is not allowed", relativePath]; - } - } + + NSString* directoryName = [absolutePath lastPathComponent]; + if (!_showHidden && [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 allowed", relativePath]; + return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Creating directory \"%@\" is not permitted", relativePath]; } NSError* error = nil; - if (![[NSFileManager defaultManager] createDirectoryAtPath:absolutePath withIntermediateDirectories:YES attributes:nil error:&error]) { + if (![[NSFileManager defaultManager] createDirectoryAtPath:absolutePath withIntermediateDirectories:NO attributes:nil error:&error]) { return [GCDWebServerErrorResponse responseWithServerError:kGCDWebServerHTTPStatusCode_InternalServerError underlyingError:error message:@"Failed creating directory \"%@\"", relativePath]; }