@@ -14,17 +14,20 @@ * file. */ #include "config.h" +#define OF_HTTP_REQUEST_M + #include #import "OFHTTPRequest.h" #import "OFString.h" #import "OFURL.h" #import "OFTCPSocket.h" #import "OFDictionary.h" +#import "OFDataArray.h" #import "OFAutoreleasePool.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidServerReplyException.h" #import "OFOutOfRangeException.h" @@ -129,10 +132,20 @@ - (BOOL)redirectsFromHTTPSToHTTPAllowed { return redirectsFromHTTPSToHTTPAllowed; } + +- (void)setDelegate: (id )delegate_ +{ + OF_SETTER(delegate, delegate_, YES, NO) +} + +- (id )delegate +{ + OF_GETTER(delegate, YES) +} - (OFHTTPRequestResult*)perform { return [self performWithRedirects: 10]; } @@ -166,10 +179,11 @@ OFDataArray *data; OFEnumerator *enumerator; OFString *key; int status; const char *t = NULL; + char *buf; [sock connectToHost: [URL host] onPort: [URL port]]; /* @@ -272,13 +286,25 @@ @"Location"] == OF_ORDERED_SAME) && (redirectsFromHTTPSToHTTPAllowed || [scheme isEqual: @"http"] || ![value hasPrefix: @"http://"])) { OFURL *new; + BOOL follow; + + new = [OFURL URLWithString: value + relativeToURL: URL]; + + follow = [delegate request: self + willFollowRedirectTo: new]; + + if (!follow && delegate != nil) { + [s_headers setObject: value + forKey: key]; + continue; + } - new = [[OFURL alloc] initWithString: value - relativeToURL: URL]; + new = [new retain]; [URL release]; URL = new; if (status == 303) { requestType = OF_HTTP_REQUEST_TYPE_GET; @@ -295,11 +321,30 @@ [s_headers setObject: value forKey: key]; } - data = [sock readDataArrayTillEndOfStream]; + [delegate request: self + didReceiveHeaders: s_headers + withStatusCode: status]; + + data = [OFDataArray dataArrayWithItemSize: 1]; + buf = [self allocMemoryWithSize: of_pagesize]; + @try { + size_t len; + + while ((len = [sock readNBytes: of_pagesize + intoBuffer: buf]) > 0) { + [data addNItems: len + fromCArray: buf]; + [delegate request: self + didReceiveData: buf + withLength: len]; + } + } @finally { + [self freeMemory: buf]; + } if ([s_headers objectForKey: @"Content-Length"] != nil) { intmax_t cl; cl = [[s_headers objectForKey: @"Content-Length"] @@ -369,5 +414,25 @@ - (OFDataArray*)data { return [[data retain] autorelease]; } @end + +@implementation OFObject (OFHTTPRequestDelegate) +- (void)request: (OFHTTPRequest*)request + didReceiveHeaders: (OFDictionary*)headers + withStatusCode: (int)statusCode +{ +} + +- (void)request: (OFHTTPRequest*)request + didReceiveData: (const char*)data + withLength: (size_t)len +{ +} + +- (BOOL)request: (OFHTTPRequest*)request + willFollowRedirectTo: (OFURL*)url +{ + return YES; +} +@end