Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -645,23 +645,40 @@ if (*UTF8String == '/') _URLEncodedPath = [[OFString alloc] initWithUTF8String: UTF8String]; else { - OFString *path, *s; - - path = [OFString stringWithUTF8String: UTF8String]; + OFString *relativePath = + [OFString stringWithUTF8String: UTF8String]; if ([URL->_URLEncodedPath hasSuffix: @"/"]) - s = [URL->_URLEncodedPath - stringByAppendingString: path]; - else - s = [OFString stringWithFormat: - @"%@/../%@", URL->_URLEncodedPath, path]; - - _URLEncodedPath = - [[s stringByStandardizingURLPath] copy]; + _URLEncodedPath = [[URL->_URLEncodedPath + stringByAppendingString: relativePath] + copy]; + else { + OFMutableString *path = [OFMutableString + stringWithString: + (URL->_URLEncodedPath != nil + ? URL->_URLEncodedPath + : @"/")]; + of_range_t range = [path + rangeOfString: @"/" + options: OF_STRING_SEARCH_BACKWARDS]; + + if (range.location == OF_NOT_FOUND) + @throw [OFInvalidFormatException + exception]; + + range.location++; + range.length = [path length] - range.location; + + [path replaceCharactersInRange: range + withString: relativePath]; + [path makeImmutable]; + + _URLEncodedPath = [path copy]; + } } of_url_verify_escaped(_URLEncodedPath, [OFCharacterSet URLPathAllowedCharacterSet]); Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -76,11 +76,17 @@ string] isEqual: @"http://h/qux/foo/bar?q"] && [[[OFURL URLWithString: @"foo/bar" relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]] string] isEqual: @"http://h/qux/foo/bar"] && [[[OFURL URLWithString: @"http://foo/?q" - relativeToURL: u1] string] isEqual: @"http://foo/?q"]) + relativeToURL: u1] string] isEqual: @"http://foo/?q"] && + [[[OFURL URLWithString: @"foo" + relativeToURL: [OFURL URLWithString: @"http://foo/bar"]] + string] isEqual: @"http://foo/foo"] && + [[[OFURL URLWithString: @"foo" + relativeToURL: [OFURL URLWithString: @"http://foo"]] + string] isEqual: @"http://foo/foo"]) EXPECT_EXCEPTION( @"+[URLWithString:relativeToURL:] fails with invalid characters #1", OFInvalidFormatException, [OFURL URLWithString: @"`"