Index: src/OFMutableURL.h ================================================================== --- src/OFMutableURL.h +++ src/OFMutableURL.h @@ -141,12 +141,17 @@ * * @return A new, autoreleased OFMutableURL */ + (instancetype)URL; +/*! + * @brief Resolves relative sub paths. + */ +- (void)standardizePath; + /*! * @brief Converts the mutable URL to an immutable URL. */ - (void)makeImmutable; @end OF_ASSUME_NONNULL_END Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -253,11 +253,73 @@ [copy makeImmutable]; return copy; } + +- (void)standardizePath +{ + void *pool; + OFMutableArray OF_GENERIC(OFString *) *array; + bool done = false, endsWithEmpty; + OFString *path; + + if (_URLEncodedPath == nil) + return; + + pool = objc_autoreleasePoolPush(); + + array = [[[_URLEncodedPath + componentsSeparatedByString: @"/"] mutableCopy] autorelease]; + + if ([[array firstObject] length] != 0) + @throw [OFInvalidFormatException exception]; + + endsWithEmpty = ([[array lastObject] length] == 0); + + while (!done) { + size_t length = [array count]; + + done = true; + + for (size_t i = 0; i < length; i++) { + id object = [array objectAtIndex: i]; + id parent = + (i > 0 ? [array objectAtIndex: i - 1] : nil); + + if ([object isEqual: @"."] || [object length] == 0) { + [array removeObjectAtIndex: i]; + + done = false; + break; + } + + if ([object isEqual: @".."] && parent != nil && + ![parent isEqual: @".."]) { + [array removeObjectsInRange: + of_range(i - 1, 2)]; + + done = false; + break; + } + } + } + + [array insertObject: @"" + atIndex: 0]; + if (endsWithEmpty) + [array addObject: @""]; + + path = [array componentsJoinedByString: @"/"]; + if ([path length] == 0) + path = @"/"; + + [self setURLEncodedPath: path]; + + objc_autoreleasePoolPop(pool); +} - (void)makeImmutable { object_setClass(self, [OFURL class]); } @end Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -1139,73 +1139,16 @@ return ret; } - (OFURL *)URLByStandardizingPath { - void *pool; - OFMutableArray OF_GENERIC(OFString *) *array; - bool done = false, endsWithEmpty; - OFString *path; - OFMutableURL *URL; - - if (_URLEncodedPath == nil) - return self; - - pool = objc_autoreleasePoolPush(); - - array = [[[_URLEncodedPath - componentsSeparatedByString: @"/"] mutableCopy] autorelease]; - - if ([[array firstObject] length] != 0) - @throw [OFInvalidFormatException exception]; - - endsWithEmpty = ([[array lastObject] length] == 0); - - while (!done) { - size_t length = [array count]; - - done = true; - - for (size_t i = 0; i < length; i++) { - id object = [array objectAtIndex: i]; - id parent = - (i > 0 ? [array objectAtIndex: i - 1] : nil); - - if ([object isEqual: @"."] || [object length] == 0) { - [array removeObjectAtIndex: i]; - - done = false; - break; - } - - if ([object isEqual: @".."] && parent != nil && - ![parent isEqual: @".."]) { - [array removeObjectsInRange: - of_range(i - 1, 2)]; - - done = false; - break; - } - } - } - - [array insertObject: @"" - atIndex: 0]; - if (endsWithEmpty) - [array addObject: @""]; - - path = [array componentsJoinedByString: @"/"]; - if ([path length] == 0) - path = @"/"; - - URL = [[self mutableCopy] autorelease]; - [URL setURLEncodedPath: path]; + OFMutableURL *URL = [[self mutableCopy] autorelease]; + + [URL standardizePath]; [URL makeImmutable]; - [URL retain]; - objc_autoreleasePoolPop(pool); - return [URL autorelease]; + return URL; } - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>",