@@ -11,11 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#define OF_HTTPCLIENT_M +#define OF_HTTP_CLIENT_M #include "config.h" #include #include @@ -29,18 +29,18 @@ #import "OFNumber.h" #import "OFRunLoop.h" #import "OFString.h" #import "OFTCPSocket.h" #import "OFTLSStream.h" -#import "OFURL.h" +#import "OFURI.h" #import "OFAlreadyConnectedException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" -#import "OFInvalidServerReplyException.h" +#import "OFInvalidServerResponseException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" @@ -115,30 +115,30 @@ static OFString * constructRequestString(OFHTTPRequest *request) { void *pool = objc_autoreleasePoolPush(); OFHTTPRequestMethod method = request.method; - OFURL *URL = request.URL; + OFURI *URI = request.URI; OFString *path; - OFString *user = URL.user, *password = URL.password; + OFString *user = URI.user, *password = URI.password; OFMutableString *requestString; OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers; bool hasContentLength, chunked; OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator; OFString *key, *object; - if (URL.path != nil) - path = URL.URLEncodedPath; + if (URI.path.length > 0) + path = URI.percentEncodedPath; else path = @"/"; requestString = [OFMutableString stringWithFormat: @"%s %@", OFHTTPRequestMethodName(method), path]; - if (URL.query != nil) { + if (URI.query != nil) { [requestString appendString: @"?"]; - [requestString appendString: URL.URLEncodedQuery]; + [requestString appendString: URI.percentEncodedQuery]; } [requestString appendString: @" HTTP/"]; [requestString appendString: request.protocolVersionString]; [requestString appendString: @"\r\n"]; @@ -146,19 +146,20 @@ headers = [[request.headers mutableCopy] autorelease]; if (headers == nil) headers = [OFMutableDictionary dictionary]; if ([headers objectForKey: @"Host"] == nil) { - OFNumber *port = URL.port; + OFNumber *port = URI.port; if (port != nil) { OFString *host = [OFString stringWithFormat: - @"%@:%@", URL.URLEncodedHost, port]; + @"%@:%@", URI.percentEncodedHost, port]; [headers setObject: host forKey: @"Host"]; } else - [headers setObject: URL.URLEncodedHost forKey: @"Host"]; + [headers setObject: URI.percentEncodedHost + forKey: @"Host"]; } if ((user.length > 0 || password.length > 0) && [headers objectForKey: @"Authorization"] == nil) { OFMutableData *authorizationData = [OFMutableData data]; @@ -296,11 +297,11 @@ exception: exception]; } - (void)createResponseWithStreamOrThrow: (OFStream *)stream { - OFURL *URL = _request.URL; + OFURI *URI = _request.URI; OFHTTPClientResponse *response; OFString *connectionHeader; bool keepAlive; OFString *location; id exception; @@ -327,44 +328,44 @@ if (keepAlive) { response.of_keepAlive = true; _client->_stream = [stream retain]; - _client->_lastURL = [URL copy]; + _client->_lastURI = [URI copy]; _client->_lastWasHEAD = (_request.method == OFHTTPRequestMethodHead); _client->_lastResponse = [response retain]; } if (_redirects > 0 && (_status == 301 || _status == 302 || _status == 303 || _status == 307) && (location = [_serverHeaders objectForKey: @"Location"]) != nil) { bool follow = true; - OFURL *newURL; - OFString *newURLScheme; - - newURL = [OFURL URLWithString: location - relativeToURL: URL]; - newURLScheme = newURL.scheme; - - if ([newURLScheme caseInsensitiveCompare: @"http"] != + OFURI *newURI; + OFString *newURIScheme; + + newURI = [OFURI URIWithString: location relativeToURI: URI]; + newURIScheme = newURI.scheme; + + if ([newURIScheme caseInsensitiveCompare: @"http"] != OFOrderedSame && - [newURLScheme caseInsensitiveCompare: @"https"] != + [newURIScheme caseInsensitiveCompare: @"https"] != OFOrderedSame) follow = false; if (!_client->_allowsInsecureRedirects && - [URL.scheme caseInsensitiveCompare: @"https"] == + [URI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame && - [newURLScheme caseInsensitiveCompare: @"http"] == + [newURIScheme caseInsensitiveCompare: @"http"] == OFOrderedSame) follow = false; - if (follow && [_client->_delegate respondsToSelector: @selector( - client:shouldFollowRedirect:statusCode:request:response:)]) + if (follow && [_client->_delegate respondsToSelector: + @selector(client:shouldFollowRedirectToURI:statusCode: + request:response:)]) follow = [_client->_delegate client: _client - shouldFollowRedirect: newURL + shouldFollowRedirectToURI: newURI statusCode: _status request: _request response: response]; else if (follow) follow = defaultShouldFollow(_request.method, _status); @@ -375,11 +376,11 @@ OFHTTPRequest *newRequest = [[_request copy] autorelease]; OFMutableDictionary *newHeaders = [[headers mutableCopy] autorelease]; - if (![newURL.host isEqual: URL.host]) + if (![newURI.host isEqual: URI.host]) [newHeaders removeObjectForKey: @"Host"]; /* * 303 means the request should be converted to a GET * request before redirection. This also means stripping @@ -401,11 +402,11 @@ removeObjectForKey: key]; newRequest.method = OFHTTPRequestMethodGet; } - newRequest.URL = newURL; + newRequest.URI = newURI; newRequest.headers = newHeaders; _client->_inProgress = false; [_client asyncPerformRequest: newRequest @@ -455,21 +456,21 @@ return false; } if (![line hasPrefix: @"HTTP/"] || line.length < 9 || [line characterAtIndex: 8] != ' ') - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; - _version = [[line substringWithRange: OFRangeMake(5, 3)] copy]; + _version = [[line substringWithRange: OFMakeRange(5, 3)] copy]; if (![_version isEqual: @"1.0"] && ![_version isEqual: @"1.1"]) @throw [OFUnsupportedVersionException exceptionWithVersion: _version]; - status = [line substringWithRange: OFRangeMake(9, 3)].longLongValue; + status = [line substringWithRange: OFMakeRange(9, 3)].longLongValue; if (status < 0 || status > 599) - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; _status = (short)status; return true; } @@ -479,11 +480,11 @@ OFString *key, *value, *old; const char *lineC, *tmp; char *keyC; if (line == nil) - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; if (line.length == 0) { [_serverHeaders makeImmutable]; if ([_client->_delegate respondsToSelector: @selector(client: @@ -503,11 +504,11 @@ } lineC = line.UTF8String; if ((tmp = strchr(lineC, ':')) == NULL) - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; keyC = OFAllocMemory(tmp - lineC + 1, 1); memcpy(keyC, lineC, tmp - lineC); keyC[tmp - lineC] = '\0'; normalizeKey(keyC); @@ -542,11 +543,12 @@ bool ret; if (exception != nil) { if ([exception isKindOfClass: [OFInvalidEncodingException class]]) - exception = [OFInvalidServerReplyException exception]; + exception = + [OFInvalidServerResponseException exception]; [self raiseException: exception]; return false; } @@ -644,19 +646,19 @@ @selector(client:didCreateTCPSocket:request:)]) [_client->_delegate client: _client didCreateTCPSocket: sock request: _request]; - if ([_request.URL.scheme caseInsensitiveCompare: @"https"] == + if ([_request.URI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame) { OFTLSStream *stream; @try { stream = [OFTLSStream streamWithStream: sock]; } @catch (OFNotImplementedException *e) { [self raiseException: [OFUnsupportedProtocolException - exceptionWithURL: _request.URL]]; + exceptionWithURI: _request.URI]]; return; } if ([_client->_delegate respondsToSelector: @selector(client:didCreateTLSStream:request:)]) @@ -663,11 +665,11 @@ [_client->_delegate client: _client didCreateTLSStream: stream request: _request]; stream.delegate = self; - [stream asyncPerformClientHandshakeWithHost: _request.URL.host]; + [stream asyncPerformClientHandshakeWithHost: _request.URI.host]; } else { sock.delegate = self; [self performSelector: @selector(handleStream:) withObject: sock afterDelay: 0]; @@ -688,30 +690,30 @@ afterDelay: 0]; } - (void)start { - OFURL *URL = _request.URL; + OFURI *URI = _request.URI; OFStream *stream; /* Can we reuse the last socket? */ if (_client->_stream != nil && !_client->_stream.atEndOfStream && - [_client->_lastURL.scheme isEqual: URL.scheme] && - [_client->_lastURL.host isEqual: URL.host] && - (_client->_lastURL.port == URL.port || - [_client->_lastURL.port isEqual: URL.port]) && + [_client->_lastURI.scheme isEqual: URI.scheme] && + [_client->_lastURI.host isEqual: URI.host] && + (_client->_lastURI.port == URI.port || + [_client->_lastURI.port isEqual: URI.port]) && (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) { /* * Set _stream to nil, so that in case of an error it won't be * reused. If everything is successful, we set _stream again * at the end. */ stream = [_client->_stream autorelease]; _client->_stream = nil; - [_client->_lastURL release]; - _client->_lastURL = nil; + [_client->_lastURI release]; + _client->_lastURI = nil; [_client->_lastResponse release]; _client->_lastResponse = nil; stream.delegate = self; @@ -724,31 +726,31 @@ } - (void)closeAndReconnect { @try { - OFURL *URL = _request.URL; + OFURI *URI = _request.URI; OFTCPSocket *sock; uint16_t port; - OFNumber *URLPort; + OFNumber *URIPort; [_client close]; sock = [OFTCPSocket socket]; - if ([URL.scheme caseInsensitiveCompare: @"https"] == + if ([URI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame) port = 443; else port = 80; - URLPort = URL.port; - if (URLPort != nil) - port = URLPort.unsignedShortValue; + URIPort = URI.port; + if (URIPort != nil) + port = URIPort.unsignedShortValue; sock.delegate = self; - [sock asyncConnectToHost: URL.host port: port]; + [sock asyncConnectToHost: URI.host port: port]; } @catch (id e) { [self raiseException: e]; } } @end @@ -899,11 +901,11 @@ isEqual: @"chunked"]; contentLength = [headers objectForKey: @"Content-Length"]; if (contentLength != nil) { if (_chunked || contentLength.length == 0) - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; _hasContentLength = true; @try { unsigned long long toRead = @@ -912,11 +914,11 @@ if (toRead > LLONG_MAX) @throw [OFOutOfRangeException exception]; _toRead = (long long)toRead; } @catch (OFInvalidFormatException *e) { - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; } } } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length @@ -958,16 +960,16 @@ switch ([_stream readIntoBuffer: tmp length: 2]) { case 2: _toRead++; if (tmp[1] != '\n') - @throw [OFInvalidServerReplyException + @throw [OFInvalidServerResponseException exception]; case 1: _toRead++; if (tmp[0] != '\r') - @throw [OFInvalidServerReplyException + @throw [OFInvalidServerResponseException exception]; } if (_setAtEndOfStream && _toRead == 0) _atEndOfStream = true; @@ -977,11 +979,11 @@ char tmp; if ([_stream readIntoBuffer: &tmp length: 1] == 1) { _toRead++; if (tmp != '\n') - @throw [OFInvalidServerReplyException + @throw [OFInvalidServerResponseException exception]; } if (_setAtEndOfStream && _toRead == 0) _atEndOfStream = true; @@ -1004,11 +1006,11 @@ size_t pos; @try { line = [_stream tryReadLine]; } @catch (OFInvalidEncodingException *e) { - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; } if (line == nil) return 0; @@ -1022,11 +1024,11 @@ * at end of stream. */ if (_stream.atEndOfStream && pos == OFNotFound) @throw [OFTruncatedDataException exception]; else - @throw [OFInvalidServerReplyException + @throw [OFInvalidServerResponseException exception]; } @try { unsigned long long toRead = @@ -1035,11 +1037,11 @@ if (toRead > LLONG_MAX) @throw [OFOutOfRangeException exception]; _toRead = (long long)toRead; } @catch (OFInvalidFormatException *e) { - @throw [OFInvalidServerReplyException exception]; + @throw [OFInvalidServerResponseException exception]; } if (_toRead == 0) { _setAtEndOfStream = true; _toRead = -2; @@ -1198,23 +1200,23 @@ didReceiveHeaders: headers statusCode: statusCode request: request]; } -- (bool)client: (OFHTTPClient *)client - shouldFollowRedirect: (OFURL *)URL - statusCode: (short)statusCode - request: (OFHTTPRequest *)request - response: (OFHTTPResponse *)response -{ - if ([_delegate respondsToSelector: @selector(client: - shouldFollowRedirect:statusCode:request:response:)]) - return [_delegate client: client - shouldFollowRedirect: URL - statusCode: statusCode - request: request - response: response]; +- (bool)client: (OFHTTPClient *)client + shouldFollowRedirectToURI: (OFURI *)URI + statusCode: (short)statusCode + request: (OFHTTPRequest *)request + response: (OFHTTPResponse *)response +{ + if ([_delegate respondsToSelector: @selector( + client:shouldFollowRedirectToURI:statusCode:request:response:)]) + return [_delegate client: client + shouldFollowRedirectToURI: URI + statusCode: statusCode + request: request + response: response]; else return defaultShouldFollow(request.method, statusCode); } @end @@ -1263,19 +1265,18 @@ - (void)asyncPerformRequest: (OFHTTPRequest *)request redirects: (unsigned int)redirects { void *pool = objc_autoreleasePoolPush(); - OFURL *URL = request.URL; - OFString *scheme = URL.scheme; + OFURI *URI = request.URI; + OFString *scheme = URI.scheme; if ([scheme caseInsensitiveCompare: @"http"] != OFOrderedSame && [scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) - @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; + @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; if (_inProgress) - /* TODO: Find a better exception */ @throw [OFAlreadyConnectedException exception]; _inProgress = true; [[[[OFHTTPClientRequestHandler alloc] @@ -1289,12 +1290,12 @@ - (void)close { [_stream release]; _stream = nil; - [_lastURL release]; - _lastURL = nil; + [_lastURI release]; + _lastURI = nil; [_lastResponse release]; _lastResponse = nil; } @end