Index: src/OFArchiveURIHandler.h ================================================================== --- src/OFArchiveURIHandler.h +++ src/OFArchiveURIHandler.h @@ -17,7 +17,16 @@ OF_ASSUME_NONNULL_BEGIN @interface OFArchiveURIHandler: OFURIHandler @end + +#ifdef __cplusplus +extern "C" { +#endif +extern OFURI *OFArchiveURIHandlerURIForFileInArchive(OFString *, OFString *, + OFURI *); +#ifdef __cplusplus +} +#endif OF_ASSUME_NONNULL_END Index: src/OFArchiveURIHandler.m ================================================================== --- src/OFArchiveURIHandler.m +++ src/OFArchiveURIHandler.m @@ -16,19 +16,36 @@ #include "config.h" #include #import "OFArchiveURIHandler.h" +#import "OFCharacterSet.h" #import "OFGZIPStream.h" #import "OFLHAArchive.h" #import "OFStream.h" #import "OFTarArchive.h" #import "OFURI.h" #import "OFZIPArchive.h" #import "OFInvalidArgumentException.h" #import "OFOpenItemFailedException.h" + +@interface OFArchiveURIHandlerPathAllowedCharacterSet: OFCharacterSet +{ + OFCharacterSet *_characterSet; + bool (*_characterIsMember)(id, SEL, OFUnichar); +} +@end + +static OFCharacterSet *pathAllowedCharacters; + +static void +initPathAllowedCharacters(void) +{ + pathAllowedCharacters = + [[OFArchiveURIHandlerPathAllowedCharacterSet alloc] init]; +} @implementation OFArchiveURIHandler - (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode { void *pool = objc_autoreleasePoolPush(); @@ -119,5 +136,66 @@ objc_autoreleasePoolPop(pool); return [stream autorelease]; } @end + +@implementation OFArchiveURIHandlerPathAllowedCharacterSet +- (instancetype)init +{ + self = [super init]; + + @try { + _characterSet = + [[OFCharacterSet URIPathAllowedCharacterSet] retain]; + _characterIsMember = (bool (*)(id, SEL, OFUnichar)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_characterSet release]; + + [super dealloc]; +} + +- (bool)characterIsMember: (OFUnichar)character +{ + return (character != '!' && _characterIsMember(_characterSet, + @selector(characterIsMember:), character)); +} +@end + +OFURI * +OFArchiveURIHandlerURIForFileInArchive(OFString *scheme, + OFString *pathInArchive, OFURI *archiveURI) +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFMutableURI *ret = [OFMutableURI URI]; + void *pool = objc_autoreleasePoolPush(); + OFString *archiveURIString; + + OFOnce(&onceControl, initPathAllowedCharacters); + + pathInArchive = [pathInArchive + stringByAddingPercentEncodingWithAllowedCharacters: + pathAllowedCharacters]; + archiveURIString = [archiveURI.string + stringByAddingPercentEncodingWithAllowedCharacters: + pathAllowedCharacters]; + + ret.scheme = scheme; + ret.percentEncodedPath = [OFString + stringWithFormat: @"%@!%@", archiveURIString, pathInArchive]; + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} Index: src/OFLHAArchive.m ================================================================== --- src/OFLHAArchive.m +++ src/OFLHAArchive.m @@ -20,10 +20,11 @@ #include #import "OFLHAArchive.h" #import "OFLHAArchiveEntry.h" #import "OFLHAArchiveEntry+Private.h" +#import "OFArchiveURIHandler.h" #import "OFCRC16.h" #import "OFLHADecompressingStream.h" #import "OFSeekableStream.h" #import "OFStream.h" #import "OFString.h" @@ -92,11 +93,11 @@ return [[[self alloc] initWithURI: URI mode: mode] autorelease]; } + (OFURI *)URIForFile: (OFString *)path inArchive: (OFURI *)archive { - return OFURIForFileInArchive(@"of-lha", path, archive); + return OFArchiveURIHandlerURIForFileInArchive(@"of-lha", path, archive); } - (instancetype)init { OF_INVALID_INIT_METHOD Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -20,10 +20,11 @@ #include #import "OFTarArchive.h" #import "OFTarArchiveEntry.h" #import "OFTarArchiveEntry+Private.h" +#import "OFArchiveURIHandler.h" #import "OFDate.h" #import "OFSeekableStream.h" #import "OFStream.h" #import "OFURI.h" #import "OFURIHandler.h" @@ -78,11 +79,11 @@ return [[[self alloc] initWithURI: URI mode: mode] autorelease]; } + (OFURI *)URIForFile: (OFString *)path inArchive: (OFURI *)archive { - return OFURIForFileInArchive(@"of-tar", path, archive); + return OFArchiveURIHandlerURIForFileInArchive(@"of-tar", path, archive); } - (instancetype)init { OF_INVALID_INIT_METHOD Index: src/OFURI.h ================================================================== --- src/OFURI.h +++ src/OFURI.h @@ -380,13 +380,12 @@ #ifdef __cplusplus extern "C" { #endif extern bool OFURIIsIPv6Host(OFString *host); extern void OFURIVerifyIsEscaped(OFString *, OFCharacterSet *); -extern OFURI *OFURIForFileInArchive(OFString *, OFString *, OFURI *); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END #import "OFMutableURI.h" Index: src/OFURI.m ================================================================== --- src/OFURI.m +++ src/OFURI.m @@ -51,18 +51,10 @@ @end @interface OFURIQueryKeyValueAllowedCharacterSet: OFURIAllowedCharacterSetBase @end -@interface OFURIPathAllowedCharacterSetWithoutExclamationMark: - OFURIPathAllowedCharacterSet -{ - OFCharacterSet *_characterSet; - bool (*_characterIsMember)(id, SEL, OFUnichar); -} -@end - OF_DIRECT_MEMBERS @interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet { OFCharacterSet *_characterSet; bool (*_characterIsMember)(id, SEL, OFUnichar); @@ -74,11 +66,10 @@ static OFCharacterSet *URIAllowedCharacterSet = nil; static OFCharacterSet *URISchemeAllowedCharacterSet = nil; static OFCharacterSet *URIPathAllowedCharacterSet = nil; static OFCharacterSet *URIQueryOrFragmentAllowedCharacterSet = nil; static OFCharacterSet *URIQueryKeyValueAllowedCharacterSet = nil; -static OFCharacterSet *URIPathAllowedCharacterSetWithoutExclamationMark = nil; static OFOnceControl URIAllowedCharacterSetOnce = OFOnceControlInitValue; static OFOnceControl URIQueryOrFragmentAllowedCharacterSetOnce = OFOnceControlInitValue; @@ -114,17 +105,10 @@ { URIQueryKeyValueAllowedCharacterSet = [[OFURIQueryKeyValueAllowedCharacterSet alloc] init]; } -static void -initURIPathAllowedCharacterSetWithoutExclamationMark(void) -{ - URIPathAllowedCharacterSetWithoutExclamationMark = - [[OFURIPathAllowedCharacterSetWithoutExclamationMark alloc] init]; -} - bool OFURIIsIPv6Host(OFString *host) { const char *UTF8String = host.UTF8String; bool hasColon = false; @@ -142,38 +126,10 @@ } return hasColon; } -OFURI * -OFURIForFileInArchive(OFString *scheme, OFString *path, OFURI *archive) -{ - static OFOnceControl onceControl = OFOnceControlInitValue; - OFMutableURI *URI = [OFMutableURI URI]; - void *pool = objc_autoreleasePoolPush(); - OFString *archiveURI; - - OFOnce(&onceControl, - initURIPathAllowedCharacterSetWithoutExclamationMark); - - path = [path stringByAddingPercentEncodingWithAllowedCharacters: - URIPathAllowedCharacterSetWithoutExclamationMark]; - archiveURI = [archive.string - stringByAddingPercentEncodingWithAllowedCharacters: - URIPathAllowedCharacterSetWithoutExclamationMark]; - - URI.scheme = scheme; - URI.percentEncodedPath = [OFString stringWithFormat: @"%@!%@", - archiveURI, path]; - - [URI makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return URI; -} - @implementation OFURIAllowedCharacterSetBase - (instancetype)autorelease { return self; } @@ -331,43 +287,10 @@ return true; default: return false; } } -@end - -@implementation OFURIPathAllowedCharacterSetWithoutExclamationMark -- (instancetype)init -{ - self = [super init]; - - @try { - _characterSet = [[OFCharacterSet URIPathAllowedCharacterSet] - retain]; - _characterIsMember = (bool (*)(id, SEL, OFUnichar)) - [_characterSet methodForSelector: - @selector(characterIsMember:)]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_characterSet release]; - - [super dealloc]; -} - -- (bool)characterIsMember: (OFUnichar)character -{ - return (character != '!' && _characterIsMember(_characterSet, - @selector(characterIsMember:), character)); -} @end @implementation OFInvertedCharacterSetWithoutPercent - (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet { Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -18,10 +18,11 @@ #include #import "OFZIPArchive.h" #import "OFZIPArchiveEntry.h" #import "OFZIPArchiveEntry+Private.h" +#import "OFArchiveURIHandler.h" #import "OFArray.h" #import "OFCRC32.h" #import "OFData.h" #import "OFDictionary.h" #import "OFInflate64Stream.h" @@ -168,11 +169,11 @@ return [[[self alloc] initWithURI: URI mode: mode] autorelease]; } + (OFURI *)URIForFile: (OFString *)path inArchive: (OFURI *)archive { - return OFURIForFileInArchive(@"of-zip", path, archive); + return OFArchiveURIHandlerURIForFileInArchive(@"of-zip", path, archive); } - (instancetype)init { OF_INVALID_INIT_METHOD