Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -242,11 +242,12 @@ scheme = [URL scheme]; # ifdef OF_HAVE_FILES if ([scheme isEqual: @"file"]) - self = [self initWithContentsOfFile: [URL path]]; + self = [self initWithContentsOfFile: + [URL fileSystemRepresentation]]; else # endif @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; objc_autoreleasePoolPop(pool); Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -299,10 +299,14 @@ path = [[[self currentDirectoryPath] pathComponents] componentsJoinedByString: @"/"]; #else path = [self currentDirectoryPath]; #endif + +#ifndef OF_PATH_STARTS_WITH_SLASH + path = [path stringByPrependingString: @"/"]; +#endif [URL setPath: [path stringByAppendingString: @"/"]]; [URL makeImmutable]; Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1039,12 +1039,13 @@ # ifdef OF_HAVE_FILES if ([scheme isEqual: @"file"]) { if (encoding == OF_STRING_ENCODING_AUTODETECT) encoding = OF_STRING_ENCODING_UTF_8; - self = [self initWithContentsOfFile: [URL path] - encoding: encoding]; + self = [self + initWithContentsOfFile: [URL fileSystemRepresentation] + encoding: encoding]; } else # endif @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; objc_autoreleasePoolPop(pool); @@ -2205,24 +2206,12 @@ of_range(last, i - last)]]; last = i + 1; } } - [ret addObject: [self substringWithRange: of_range(last, i - last)]]; -#ifdef OF_WINDOWS - if ([ret count] >= 2 && [[ret objectAtIndex: 0] hasSuffix: @":"]) { - OFString *first = [[ret objectAtIndex: 0] - stringByAppendingPathComponent: [ret objectAtIndex: 1]]; - - [ret removeObjectAtIndex: 0]; - [ret replaceObjectAtIndex: 0 - withObject: first]; - } -#endif - [ret makeImmutable]; objc_autoreleasePoolPop(pool); return ret; Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -1167,25 +1167,13 @@ [OFString stringWithUTF8String: _s->cString + last length: i - last]]; last = i + 1; } } - [ret addObject: [OFString stringWithUTF8String: _s->cString + last length: i - last]]; -#ifdef OF_WINDOWS - if ([ret count] >= 2 && [[ret objectAtIndex: 0] hasSuffix: @":"]) { - OFString *first = [[ret objectAtIndex: 0] - stringByAppendingPathComponent: [ret objectAtIndex: 1]]; - - [ret removeObjectAtIndex: 0]; - [ret replaceObjectAtIndex: 0 - withObject: first]; - } -#endif - [ret makeImmutable]; objc_autoreleasePoolPop(pool); return ret; Index: src/OFURL.h ================================================================== --- src/OFURL.h +++ src/OFURL.h @@ -135,10 +135,20 @@ * @brief Returns the URL as a string. * * @return The URL as a string */ - (OFString *)string; + +/*! + * @brief Returns the local file system representation for a file URL. + * + * This only exists for URLs with the file scheme and throws an exception + * otherwise. + * + * @return The local file system representation for a file URL + */ +- (nullable OFString *)fileSystemRepresentation; @end OF_ASSUME_NONNULL_END #import "OFMutableURL.h" Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -480,10 +480,43 @@ [ret makeImmutable]; return ret; } + +- (OFString *)fileSystemRepresentation +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + + if (![_scheme isEqual: @"file"]) + @throw [OFInvalidArgumentException exception]; + + if (![_path hasPrefix: @"/"]) + @throw [OFInvalidFormatException exception]; + + path = [[_path copy] autorelease]; + + if ([path hasSuffix: @"/"]) + path = [path substringWithRange: + of_range(0, [path length] - 1)]; + +#ifndef OF_PATH_STARTS_WITH_SLASH + path = [path substringWithRange: of_range(1, [path length] - 1)]; +#endif + +#if OF_PATH_DELIMITER != '/' + path = [OFString pathWithComponents: + [path componentsSeparatedByString: @"/"]]; +#endif + + [path retain]; + + objc_autoreleasePoolPop(pool); + + return [path autorelease]; +} - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>", [self class], [self string]]; Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -326,10 +326,11 @@ #if !defined(OF_WINDOWS) && !defined(OF_MSDOS) # define OF_PATH_DELIMITER '/' # define OF_PATH_DELIMITER_STRING @"/" # define OF_IS_PATH_DELIMITER(c) (c == '/') +# define OF_PATH_STARTS_WITH_SLASH #else # define OF_PATH_DELIMITER '\\' # define OF_PATH_DELIMITER_STRING @"\\" # define OF_IS_PATH_DELIMITER(c) (c == '\\' || c == '/') #endif