Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -175,23 +175,22 @@ ${USE_INCLUDES_ATOMIC} SRCS += OFASPrintF.m \ OFAdjacentArray.m \ OFAdjacentSubarray.m \ + OFArchiveURIHandler.m \ OFBase64.m \ OFBitSetCharacterSet.m \ OFBytesValue.m \ OFCRC16.m \ OFCRC32.m \ OFCountedMapTableSet.m \ OFEmbeddedURIHandler.m \ - OFGZIPURIHandler.m \ OFHuffmanTree.m \ OFINIFileSettings.m \ OFInvertedCharacterSet.m \ OFLHADecompressingStream.m \ - OFLHAURIHandler.m \ OFMapTableDictionary.m \ OFMapTableSet.m \ OFMutableAdjacentArray.m \ OFMutableMapTableDictionary.m \ OFMutableMapTableSet.m \ @@ -204,13 +203,11 @@ OFRectValue.m \ OFSandbox.m \ OFSizeValue.m \ OFStrPTime.m \ OFSubarray.m \ - OFTarURIHandler.m \ OFUTF8String.m \ - OFZIPURIHandler.m \ ${LIBBASES_M} \ ${RUNTIME_AUTORELEASE_M} \ ${RUNTIME_INSTANCE_M} \ ${UNICODE_M} SRCS_FILES += OFFileURIHandler.m ADDED src/OFArchiveURIHandler.h Index: src/OFArchiveURIHandler.h ================================================================== --- src/OFArchiveURIHandler.h +++ src/OFArchiveURIHandler.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFURIHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFArchiveURIHandler: OFURIHandler +@end + +OF_ASSUME_NONNULL_END ADDED src/OFArchiveURIHandler.m Index: src/OFArchiveURIHandler.m ================================================================== --- src/OFArchiveURIHandler.m +++ src/OFArchiveURIHandler.m @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFArchiveURIHandler.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" + +@implementation OFArchiveURIHandler +- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode +{ + void *pool = objc_autoreleasePoolPush(); + OFString *scheme = URI.scheme; + OFString *percentEncodedPath, *path; + size_t pos; + OFURI *archiveURI; + OFStream *stream; + + if (URI.host != nil || URI.port != nil || URI.user != nil || + URI.password != nil || URI.query != nil || URI.fragment != nil) + @throw [OFInvalidArgumentException exception]; + + if (![mode isEqual: @"r"]) + /* + * Writing has some implications that are not decided yet: Will + * it always append to an archive? What happens if the file + * already exists? + */ + @throw [OFInvalidArgumentException exception]; + + /* + * GZIP only compresses one file and thus has no path inside an + * archive. + */ + if ([scheme isEqual: @"of-gzip"]) { + stream = [OFURIHandler openItemAtURI: [OFURI URIWithString: + URI.path] + mode: @"r"]; + stream = [OFGZIPStream streamWithStream: stream mode: @"r"]; + goto end; + } + + percentEncodedPath = URI.percentEncodedPath; + pos = [percentEncodedPath rangeOfString: @"!"].location; + + if (pos == OFNotFound) + @throw [OFInvalidArgumentException exception]; + + archiveURI = [OFURI URIWithString: + [percentEncodedPath substringWithRange: OFMakeRange(0, pos)] + .stringByRemovingPercentEncoding]; + path = [percentEncodedPath substringWithRange: + OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] + .stringByRemovingPercentEncoding; + + if ([scheme isEqual: @"of-lha"]) { + OFLHAArchive *archive = [OFLHAArchive archiveWithURI: archiveURI + mode: @"r"]; + OFLHAArchiveEntry *entry; + + while ((entry = [archive nextEntry]) != nil) { + if ([entry.fileName isEqual: path]) { + stream = [archive streamForReadingCurrentEntry]; + goto end; + } + } + + @throw [OFOpenItemFailedException exceptionWithURI: URI + mode: mode + errNo: ENOENT]; + } else if ([scheme isEqual: @"of-tar"]) { + OFTarArchive *archive = [OFTarArchive archiveWithURI: archiveURI + mode: @"r"]; + OFTarArchiveEntry *entry; + + while ((entry = [archive nextEntry]) != nil) { + if ([entry.fileName isEqual: path]) { + stream = [archive streamForReadingCurrentEntry]; + goto end; + } + } + + @throw [OFOpenItemFailedException exceptionWithURI: URI + mode: mode + errNo: ENOENT]; + } else if ([scheme isEqual: @"of-zip"]) { + OFZIPArchive *archive = [OFZIPArchive archiveWithURI: archiveURI + mode: @"r"]; + + stream = [archive streamForReadingFile: path]; + } else + @throw [OFInvalidArgumentException exception]; + +end: + stream = [stream retain]; + + objc_autoreleasePoolPop(pool); + + return [stream autorelease]; +} +@end DELETED src/OFGZIPURIHandler.h Index: src/OFGZIPURIHandler.h ================================================================== --- src/OFGZIPURIHandler.h +++ src/OFGZIPURIHandler.h @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFGZIPURIHandler: OFURIHandler -@end - -OF_ASSUME_NONNULL_END DELETED src/OFGZIPURIHandler.m Index: src/OFGZIPURIHandler.m ================================================================== --- src/OFGZIPURIHandler.m +++ src/OFGZIPURIHandler.m @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFGZIPURIHandler.h" -#import "OFGZIPStream.h" -#import "OFStream.h" -#import "OFURI.h" - -#import "OFInvalidArgumentException.h" - -@implementation OFGZIPURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFStream *stream; - - if (![URI.scheme isEqual: @"of-gzip"] || URI.host != nil || - URI.port != nil || URI.user != nil || URI.password != nil || - URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - @throw [OFInvalidArgumentException exception]; - - stream = [OFURIHandler openItemAtURI: [OFURI URIWithString: URI.path] - mode: @"r"]; - stream = [OFGZIPStream streamWithStream: stream mode: @"r"]; - - [stream retain]; - - objc_autoreleasePoolPop(pool); - - return [stream autorelease]; -} -@end DELETED src/OFLHAURIHandler.h Index: src/OFLHAURIHandler.h ================================================================== --- src/OFLHAURIHandler.h +++ src/OFLHAURIHandler.h @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFLHAURIHandler: OFURIHandler -@end - -OF_ASSUME_NONNULL_END DELETED src/OFLHAURIHandler.m Index: src/OFLHAURIHandler.m ================================================================== --- src/OFLHAURIHandler.m +++ src/OFLHAURIHandler.m @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFLHAURIHandler.h" -#import "OFLHAArchive.h" -#import "OFStream.h" -#import "OFURI.h" - -#import "OFInvalidArgumentException.h" -#import "OFOpenItemFailedException.h" - -@implementation OFLHAURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFString *percentEncodedPath, *archiveURI, *path; - size_t pos; - OFLHAArchive *archive; - OFLHAArchiveEntry *entry; - - if (![URI.scheme isEqual: @"of-lha"] || URI.host != nil || - URI.port != nil || URI.user != nil || URI.password != nil || - URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - /* - * Writing has some implications that are not decided yet: Will - * it always append to an archive? What happens if the file - * already exists? - */ - @throw [OFInvalidArgumentException exception]; - - percentEncodedPath = URI.percentEncodedPath; - pos = [percentEncodedPath rangeOfString: @"!"].location; - - if (pos == OFNotFound) - @throw [OFInvalidArgumentException exception]; - - archiveURI = [percentEncodedPath substringWithRange: - OFMakeRange(0, pos)].stringByRemovingPercentEncoding; - path = [percentEncodedPath substringWithRange: - OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] - .stringByRemovingPercentEncoding; - - archive = [OFLHAArchive - archiveWithURI: [OFURI URIWithString: archiveURI] - mode: @"r"]; - - while ((entry = [archive nextEntry]) != nil) { - if ([entry.fileName isEqual: path]) { - OFStream *stream = - [[archive streamForReadingCurrentEntry] retain]; - - objc_autoreleasePoolPop(pool); - - return [stream autorelease]; - } - } - - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: ENOENT]; -} -@end DELETED src/OFTarURIHandler.m Index: src/OFTarURIHandler.m ================================================================== --- src/OFTarURIHandler.m +++ src/OFTarURIHandler.m @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFTarURIHandler.h" -#import "OFStream.h" -#import "OFTarArchive.h" -#import "OFURI.h" - -#import "OFInvalidArgumentException.h" -#import "OFOpenItemFailedException.h" - -@implementation OFTarURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFString *percentEncodedPath, *archiveURI, *path; - size_t pos; - OFTarArchive *archive; - OFTarArchiveEntry *entry; - - if (![URI.scheme isEqual: @"of-tar"] || URI.host != nil || - URI.port != nil || URI.user != nil || URI.password != nil || - URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - /* - * Writing has some implications that are not decided yet: Will - * it always append to an archive? What happens if the file - * already exists? - */ - @throw [OFInvalidArgumentException exception]; - - percentEncodedPath = URI.percentEncodedPath; - pos = [percentEncodedPath rangeOfString: @"!"].location; - - if (pos == OFNotFound) - @throw [OFInvalidArgumentException exception]; - - archiveURI = [percentEncodedPath substringWithRange: - OFMakeRange(0, pos)].stringByRemovingPercentEncoding; - path = [percentEncodedPath substringWithRange: - OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] - .stringByRemovingPercentEncoding; - - archive = [OFTarArchive - archiveWithURI: [OFURI URIWithString: archiveURI] - mode: @"r"]; - - while ((entry = [archive nextEntry]) != nil) { - if ([entry.fileName isEqual: path]) { - OFStream *stream = - [[archive streamForReadingCurrentEntry] retain]; - - objc_autoreleasePoolPop(pool); - - return [stream autorelease]; - } - } - - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: ENOENT]; -} -@end Index: src/OFURIHandler.m ================================================================== --- src/OFURIHandler.m +++ src/OFURIHandler.m @@ -22,21 +22,18 @@ #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif +#import "OFArchiveURIHandler.h" #import "OFEmbeddedURIHandler.h" #ifdef OF_HAVE_FILES # import "OFFileURIHandler.h" #endif -#import "OFGZIPURIHandler.h" #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) # import "OFHTTPURIHandler.h" #endif -#import "OFLHAURIHandler.h" -#import "OFTarURIHandler.h" -#import "OFZIPURIHandler.h" #import "OFUnsupportedProtocolException.h" static OFMutableDictionary OF_GENERIC(OFString *, OFURIHandler *) *handlers; #ifdef OF_HAVE_THREADS @@ -66,18 +63,18 @@ [self registerClass: [OFEmbeddedURIHandler class] forScheme: @"of-embedded"]; #ifdef OF_HAVE_FILES [self registerClass: [OFFileURIHandler class] forScheme: @"file"]; #endif - [self registerClass: [OFGZIPURIHandler class] forScheme: @"of-gzip"]; #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) [self registerClass: [OFHTTPURIHandler class] forScheme: @"http"]; [self registerClass: [OFHTTPURIHandler class] forScheme: @"https"]; #endif - [self registerClass: [OFLHAURIHandler class] forScheme: @"of-lha"]; - [self registerClass: [OFTarURIHandler class] forScheme: @"of-tar"]; - [self registerClass: [OFZIPURIHandler class] forScheme: @"of-zip"]; + [self registerClass: [OFArchiveURIHandler class] forScheme: @"of-gzip"]; + [self registerClass: [OFArchiveURIHandler class] forScheme: @"of-lha"]; + [self registerClass: [OFArchiveURIHandler class] forScheme: @"of-tar"]; + [self registerClass: [OFArchiveURIHandler class] forScheme: @"of-zip"]; } + (bool)registerClass: (Class)class forScheme: (OFString *)scheme { #ifdef OF_HAVE_THREADS DELETED src/OFZIPURIHandler.h Index: src/OFZIPURIHandler.h ================================================================== --- src/OFZIPURIHandler.h +++ src/OFZIPURIHandler.h @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFZIPURIHandler: OFURIHandler -@end - -OF_ASSUME_NONNULL_END DELETED src/OFZIPURIHandler.m Index: src/OFZIPURIHandler.m ================================================================== --- src/OFZIPURIHandler.m +++ src/OFZIPURIHandler.m @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFZIPURIHandler.h" -#import "OFStream.h" -#import "OFURI.h" -#import "OFZIPArchive.h" - -#import "OFInvalidArgumentException.h" - -@implementation OFZIPURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFString *percentEncodedPath, *archiveURI, *path; - size_t pos; - OFZIPArchive *archive; - OFStream *stream; - - if (![URI.scheme isEqual: @"of-zip"] || URI.host != nil || - URI.port != nil || URI.user != nil || URI.password != nil || - URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - /* - * Writing has some implications that are not decided yet: Will - * it always append to an archive? What happens if the file - * already exists? - */ - @throw [OFInvalidArgumentException exception]; - - percentEncodedPath = URI.percentEncodedPath; - pos = [percentEncodedPath rangeOfString: @"!"].location; - - if (pos == OFNotFound) - @throw [OFInvalidArgumentException exception]; - - archiveURI = [percentEncodedPath substringWithRange: - OFMakeRange(0, pos)].stringByRemovingPercentEncoding; - path = [percentEncodedPath substringWithRange: - OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] - .stringByRemovingPercentEncoding; - - archive = [OFZIPArchive - archiveWithURI: [OFURI URIWithString: archiveURI] - mode: @"r"]; - stream = [archive streamForReadingFile: path]; - - [stream retain]; - - objc_autoreleasePoolPop(pool); - - return [stream autorelease]; -} -@end