| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | #import "DAVConnection.h"#import "HTTPMessage.h"#import "HTTPFileResponse.h"#import "HTTPAsyncFileResponse.h"#import "PUTResponse.h"#import "DELETEResponse.h"#import "DAVResponse.h"#import "HTTPLogging.h"#define HTTP_BODY_MAX_MEMORY_SIZE (1024 * 1024)#define HTTP_ASYNC_FILE_RESPONSE_THRESHOLD (16 * 1024 * 1024)static const int httpLogLevel = HTTP_LOG_LEVEL_WARN;@implementation DAVConnection- (void) dealloc {  [requestContentStream close];  }- (BOOL) supportsMethod:(NSString*)method atPath:(NSString*)path {  // HTTPFileResponse & HTTPAsyncFileResponse  if ([method isEqualToString:@"GET"]) return YES;	if ([method isEqualToString:@"HEAD"]) return YES;    // PUTResponse  if ([method isEqualToString:@"PUT"]) return YES;    // DELETEResponse  if ([method isEqualToString:@"DELETE"]) return YES;	  // DAVResponse  if ([method isEqualToString:@"OPTIONS"]) return YES;  if ([method isEqualToString:@"PROPFIND"]) return YES;  if ([method isEqualToString:@"MKCOL"]) return YES;  if ([method isEqualToString:@"MOVE"]) return YES;  if ([method isEqualToString:@"COPY"]) return YES;  if ([method isEqualToString:@"LOCK"]) return YES;  if ([method isEqualToString:@"UNLOCK"]) return YES;    return NO;}- (BOOL) expectsRequestBodyFromMethod:(NSString*)method atPath:(NSString*)path {  // PUTResponse  if ([method isEqualToString:@"PUT"]) {    return YES;	}    // DAVResponse  if ([method isEqual:@"PROPFIND"] || [method isEqual:@"MKCOL"]) {    return [request headerField:@"Content-Length"] ? YES : NO;  }  if ([method isEqual:@"LOCK"]) {    return YES;  }    return NO;}- (void) prepareForBodyWithSize:(UInt64)contentLength {  NSAssert(requestContentStream == nil, @"requestContentStream should be nil");  NSAssert(requestContentBody == nil, @"requestContentBody should be nil");    if (contentLength > HTTP_BODY_MAX_MEMORY_SIZE) {    requestContentBody = [[NSTemporaryDirectory() stringByAppendingString:[[NSProcessInfo processInfo] globallyUniqueString]] copy];    requestContentStream = [[NSOutputStream alloc] initToFileAtPath:requestContentBody append:NO];    [requestContentStream open];  } else {    requestContentBody = [[NSMutableData alloc] initWithCapacity:(NSUInteger)contentLength];    requestContentStream = nil;  }}- (void) processBodyData:(NSData*)postDataChunk {	NSAssert(requestContentBody != nil, @"requestContentBody should not be nil");  if (requestContentStream) {    [requestContentStream write:[postDataChunk bytes] maxLength:[postDataChunk length]];  } else {    [(NSMutableData*)requestContentBody appendData:postDataChunk];  }}- (void) finishBody {  NSAssert(requestContentBody != nil, @"requestContentBody should not be nil");  if (requestContentStream) {    [requestContentStream close];    requestContentStream = nil;  }}- (void)finishResponse {  NSAssert(requestContentStream == nil, @"requestContentStream should be nil");  requestContentBody = nil;    [super finishResponse];}- (NSObject<HTTPResponse>*) httpResponseForMethod:(NSString*)method URI:(NSString*)path {  if ([method isEqualToString:@"HEAD"] || [method isEqualToString:@"GET"]) {    NSString* filePath = [self filePathForURI:path allowDirectory:NO];    if (filePath) {      NSDictionary* fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL];      if (fileAttributes) {        if ([[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue] > HTTP_ASYNC_FILE_RESPONSE_THRESHOLD) {          return [[HTTPAsyncFileResponse alloc] initWithFilePath:filePath forConnection:self];        } else {          return [[HTTPFileResponse alloc] initWithFilePath:filePath forConnection:self];        }      }    }  }		if ([method isEqualToString:@"PUT"]) {    NSString* filePath = [self filePathForURI:path allowDirectory:YES];    if (filePath) {      if ([requestContentBody isKindOfClass:[NSString class]]) {        return [[PUTResponse alloc] initWithFilePath:filePath headers:[request allHeaderFields] bodyFile:requestContentBody];      } else if ([requestContentBody isKindOfClass:[NSData class]]) {        return [[PUTResponse alloc] initWithFilePath:filePath headers:[request allHeaderFields] bodyData:requestContentBody];      } else {        HTTPLogError(@"Internal error");      }    }  }		if ([method isEqualToString:@"DELETE"]) {    NSString* filePath = [self filePathForURI:path allowDirectory:YES];    if (filePath) {      return [[DELETEResponse alloc] initWithFilePath:filePath];    }  }    if ([method isEqualToString:@"OPTIONS"] || [method isEqualToString:@"PROPFIND"] || [method isEqualToString:@"MKCOL"] ||    [method isEqualToString:@"MOVE"] || [method isEqualToString:@"COPY"] || [method isEqualToString:@"LOCK"] || [method isEqualToString:@"UNLOCK"]) {    NSString* filePath = [self filePathForURI:path allowDirectory:YES];    if (filePath) {      NSString* rootPath = [config documentRoot];      NSString* resourcePath = [filePath substringFromIndex:([rootPath length] + 1)];      if (requestContentBody) {        if ([requestContentBody isKindOfClass:[NSString class]]) {          requestContentBody = [NSData dataWithContentsOfFile:requestContentBody];        } else if (![requestContentBody isKindOfClass:[NSData class]]) {          HTTPLogError(@"Internal error");          return nil;        }      }      return [[DAVResponse alloc] initWithMethod:method                                          headers:[request allHeaderFields]                                         bodyData:requestContentBody                                     resourcePath:resourcePath                                         rootPath:rootPath];    }  }    return nil;}@end
 |