Index: src/OFMutableURL.h ================================================================== --- src/OFMutableURL.h +++ src/OFMutableURL.h @@ -141,10 +141,27 @@ * * @return A new, autoreleased OFMutableURL */ + (instancetype)URL; +/*! + * @brief Appends the specified path component. + * + * @param component The component to append + */ +- (void)appendPathComponent: (OFString *)component; + +/*! + * @brief Appends the specified path component. + * + * @param component The component to append + * @param isDirectory Whether the path is a directory, in which case a slash is + * appened if there is no slash yet + */ +- (void)appendPathComponent: (OFString *)component + isDirectory: (bool)isDirectory; + /*! * @brief Resolves relative sub paths. */ - (void)standardizePath; Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -17,10 +17,13 @@ #include "config.h" #import "OFMutableURL.h" #import "OFArray.h" +#ifdef OF_HAVE_FILES +# import "OFFileManager.h" +#endif #import "OFNumber.h" #import "OFString.h" #import "OFInvalidFormatException.h" @@ -253,10 +256,65 @@ [copy makeImmutable]; return copy; } + +- (void)appendPathComponent: (OFString *)component +{ + [self appendPathComponent: component + isDirectory: false]; + +#ifdef OF_HAVE_FILES + if ([_URLEncodedScheme isEqual: @"file"] && + ![_URLEncodedPath hasSuffix: @"/"] && + [[OFFileManager defaultManager] directoryExistsAtURL: self]) { + void *pool = objc_autoreleasePoolPush(); + OFString *path = [_URLEncodedPath + stringByAppendingString: @"/"]; + + [_URLEncodedPath release]; + _URLEncodedPath = [path retain]; + + objc_autoreleasePoolPop(pool); + } +#endif +} + +- (void)appendPathComponent: (OFString *)component + isDirectory: (bool)isDirectory +{ + void *pool; + OFString *path; + + if ([component isEqual: @"/"] && [_URLEncodedPath hasSuffix: @"/"]) + return; + + pool = objc_autoreleasePoolPush(); + component = [component stringByURLEncodingWithAllowedCharacters: + [OFCharacterSet URLPathAllowedCharacterSet]]; + +#if defined(OF_WINDOWS) || defined(OF_MSDOS) + if ([_URLEncodedPath hasSuffix: @"/"] || + ([_URLEncodedScheme isEqual: @"file"] && + [_URLEncodedPath hasSuffix: @":"])) +#else + if ([_URLEncodedPath hasSuffix: @"/"]) +#endif + path = [_URLEncodedPath stringByAppendingString: component]; + else + path = [_URLEncodedPath + stringByAppendingFormat: @"/%@", component]; + + if (isDirectory && ![path hasSuffix: @"/"]) + path = [path stringByAppendingString: @"/"]; + + [_URLEncodedPath release]; + _URLEncodedPath = [path retain]; + + objc_autoreleasePoolPop(pool); +} - (void)standardizePath { void *pool; OFMutableArray OF_GENERIC(OFString *) *array; Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -1138,76 +1138,30 @@ return [path autorelease]; } #endif -- (OFMutableURL *)of_URLByAppendingPathComponent: (OFString *)component -{ - OFMutableURL *ret = [[self mutableCopy] autorelease]; - void *pool; - OFMutableString *URLEncodedPath; - - if ([component hasPrefix: @"/"]) { - ret.path = component; - return ret; - } - - pool = objc_autoreleasePoolPush(); - URLEncodedPath = [[self.URLEncodedPath mutableCopy] autorelease]; - - if (![URLEncodedPath hasSuffix: @"/"]) - [URLEncodedPath appendString: @"/"]; - - [URLEncodedPath appendString: - [component stringByURLEncodingWithAllowedCharacters: - [OFCharacterSet URLPathAllowedCharacterSet]]]; - - ret.URLEncodedPath = URLEncodedPath; - - objc_autoreleasePoolPop(pool); - - return ret; -} - - (OFURL *)URLByAppendingPathComponent: (OFString *)component { - OFMutableURL *ret = [self of_URLByAppendingPathComponent: component]; - -#ifdef OF_HAVE_FILES - if ([ret.scheme isEqual: @"file"]) { - void *pool = objc_autoreleasePoolPush(); - - if ([[OFFileManager defaultManager] directoryExistsAtURL: ret]) - ret.URLEncodedPath = - [ret.URLEncodedPath stringByAppendingString: @"/"]; - - objc_autoreleasePoolPop(pool); - } -#endif - - [ret makeImmutable]; - - return ret; + OFMutableURL *URL = [[self mutableCopy] autorelease]; + + [URL appendPathComponent: component]; + [URL makeImmutable]; + + return URL; } - (OFURL *)URLByAppendingPathComponent: (OFString *)component isDirectory: (bool)isDirectory { - OFMutableURL *ret = [self of_URLByAppendingPathComponent: component]; - - if (isDirectory) { - void *pool = objc_autoreleasePoolPush(); - - ret.URLEncodedPath = - [ret.URLEncodedPath stringByAppendingString: @"/"]; - - objc_autoreleasePoolPop(pool); - } - - [ret makeImmutable]; - - return ret; + OFMutableURL *URL = [[self mutableCopy] autorelease]; + + [URL appendPathComponent: component + isDirectory: isDirectory]; + [URL makeImmutable]; + + return URL; } - (OFURL *)URLByStandardizingPath { OFMutableURL *URL = [[self mutableCopy] autorelease]; Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -264,23 +264,11 @@ isDirectory: false] isEqual: [OFURL URLWithString: @"file:///foo/bar/qu%3Fx"]] && [[[OFURL URLWithString: @"file:///foo/bar/"] URLByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual: - [OFURL URLWithString: @"file:///foo/bar/qu%3Fx/"]] && - [[[OFURL URLWithString: @"file:///foo/bar/"] - URLByAppendingPathComponent: @"/qux" - isDirectory: false] isEqual: - [OFURL URLWithString: @"file:///qux"]] && - [[[OFURL URLWithString: @"file:///foo/bar/"] - URLByAppendingPathComponent: @"/qu?x" - isDirectory: false] isEqual: - [OFURL URLWithString: @"file:///qu%3Fx"]] && - [[[OFURL URLWithString: @"file:///foo/bar/"] - URLByAppendingPathComponent: @"/qu?x" - isDirectory: true] isEqual: - [OFURL URLWithString: @"file:///qu%3Fx/"]]) + [OFURL URLWithString: @"file:///foo/bar/qu%3Fx/"]]) TEST(@"-[URLByStandardizingPath]", [[[OFURL URLWithString: @"http://foo/bar/.."] URLByStandardizingPath] isEqual: [OFURL URLWithString: @"http://foo/"]] &&