Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -326,11 +326,11 @@ OFString *user, *password; OFDictionary *headers = [request headers]; OFDataArray *entity = [request entity]; OFTCPSocket *socket; OFHTTPClientResponse *response; - OFString *line, *path, *version, *redirect, *keepAlive; + OFString *line, *version, *redirect, *keepAlive; OFMutableDictionary *serverHeaders; OFEnumerator *keyEnumerator, *objectEnumerator; OFString *key, *object; int status; @@ -363,27 +363,24 @@ [_lastResponse release]; _lastResponse = nil; } else socket = [self OF_createSocketForRequest: request]; - if ([(path = [URL path]) length] == 0) - path = @"/"; - /* * As a work around for a bug with split packets in lighttpd when using * HTTPS, we construct the complete request in a buffer string and then * send it all at once. */ if ([URL query] != nil) requestString = [OFMutableString stringWithFormat: - @"%s %@?%@ HTTP/%@\r\n", - of_http_request_method_to_string(method), path, [URL query], - [request protocolVersionString]]; + @"%s /%@?%@ HTTP/%@\r\n", + of_http_request_method_to_string(method), [URL path], + [URL query], [request protocolVersionString]]; else requestString = [OFMutableString stringWithFormat: - @"%s %@ HTTP/%@\r\n", - of_http_request_method_to_string(method), path, + @"%s /%@ HTTP/%@\r\n", + of_http_request_method_to_string(method), [URL path], [request protocolVersionString]]; if ([URL port] == 80) [requestString appendFormat: @"Host: %@\r\n", [URL host]]; else Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -383,10 +383,11 @@ } - (bool)parseProlog: (OFString*)line { OFString *method; + OFMutableString *path; size_t pos; @try { OFString *version = [line substringWithRange: of_range([line length] - 9, 9)]; @@ -415,21 +416,28 @@ } @catch (OFInvalidFormatException *e) { return [self sendErrorAndClose: 405]; } @try { - _path = [line substringWithRange: - of_range(pos + 1, [line length] - pos - 10)]; + of_range_t range = of_range(pos + 1, [line length] - pos - 10); + + path = [[[line substringWithRange: + range] mutableCopy] autorelease]; } @catch (OFOutOfRangeException *e) { return [self sendErrorAndClose: 400]; } - _path = [[_path stringByDeletingEnclosingWhitespaces] retain]; - if (![_path hasPrefix: @"/"]) + [path deleteEnclosingWhitespaces]; + + if (![path hasPrefix: @"/"]) return [self sendErrorAndClose: 400]; + + [path deleteCharactersInRange: of_range(0, 1)]; + [path makeImmutable]; _headers = [[OFMutableDictionary alloc] init]; + _path = [path copy]; _state = PARSING_HEADERS; return true; } Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -156,14 +156,13 @@ _parameters = [[OFString alloc] initWithUTF8String: tmp + 1]; } - _path = [[OFString alloc] initWithFormat: @"/%s", - UTF8String]; - } else - _path = @""; + _path = [[OFString alloc] + initWithUTF8String: UTF8String]; + } } @catch (id e) { [self release]; @throw e; } @finally { free(UTF8String2); @@ -215,11 +214,11 @@ initWithUTF8String: tmp + 1]; } if (*UTF8String == '/') _path = [[OFString alloc] - initWithUTF8String: UTF8String]; + initWithUTF8String: UTF8String + 1]; else { void *pool; OFString *s; pool = objc_autoreleasePoolPush(); @@ -480,11 +479,11 @@ if (([_scheme isEqual: @"http"] && _port != 80) || ([_scheme isEqual: @"https"] && _port != 443)) [ret appendFormat: @":%u", _port]; if (_path != nil) - [ret appendString: _path]; + [ret appendFormat: @"/%@", _path]; if (_parameters != nil) [ret appendFormat: @";%@", _parameters]; if (_query != nil) Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -64,11 +64,11 @@ TEST(@"-[password]", [[u1 password] isEqual: @"p"] && [u4 password] == nil) TEST(@"-[host]", [[u1 host] isEqual: @"h"] && [u4 port] == 0) TEST(@"-[port]", [u1 port] == 1234) TEST(@"-[path]", - [[u1 path] isEqual: @"/f"] && [[u4 path] isEqual: @"/etc/passwd"]) + [[u1 path] isEqual: @"f"] && [[u4 path] isEqual: @"/etc/passwd"]) TEST(@"-[parameters]", [[u1 parameters] isEqual: @"p"] && [u4 parameters] == nil) TEST(@"-[query]", [[u1 query] isEqual: @"q"] && [u4 query] == nil) TEST(@"-[fragment]", [[u1 fragment] isEqual: @"f"] && [u4 fragment] == nil) Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ tests/serialization.xml @@ -5,10 +5,29 @@ Blub B"la + + MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla + + + data + + + + Qu"xbar +test + 1234 + 40934a456d5cfaad + asd + 40934a456d5cfaad + + + + Hello + Hello Wo ld! How are you? @@ -36,26 +55,7 @@ list - - MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla - - - data - - - - Qu"xbar -test - 1234 - 40934a456d5cfaad - asd - 40934a456d5cfaad - - - - Hello -