Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -182,10 +182,11 @@ OFBytesValue.m \ OFCRC16.m \ OFCRC32.m \ OFCountedMapTableSet.m \ OFEmbeddedURIHandler.m \ + OFGZIPURIHandler.m \ OFHuffmanTree.m \ OFINIFileSettings.m \ OFInvertedCharacterSet.m \ OFLHADecompressingStream.m \ OFMapTableDictionary.m \ ADDED src/OFGZIPURIHandler.h Index: src/OFGZIPURIHandler.h ================================================================== --- src/OFGZIPURIHandler.h +++ src/OFGZIPURIHandler.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 OFGZIPURIHandler: OFURIHandler +@end + +OF_ASSUME_NONNULL_END ADDED src/OFGZIPURIHandler.m Index: src/OFGZIPURIHandler.m ================================================================== --- src/OFGZIPURIHandler.m +++ src/OFGZIPURIHandler.m @@ -0,0 +1,48 @@ +/* + * 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 "OFURI.h" +#import "OFGZIPStream.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 Index: src/OFTarArchive.h ================================================================== --- src/OFTarArchive.h +++ src/OFTarArchive.h @@ -83,11 +83,11 @@ * @brief Creates a URI for accessing a the specified file within the specified * tar archive. * * @param path The path of the file within the archive * @param archive The URI of the archive - * @return A URI for accessing the specified file within the specified Tar + * @return A URI for accessing the specified file within the specified tar * archive */ + (OFURI *)URIForFile: (OFString *)path inArchive: (OFURI *)archive; - (instancetype)init OF_UNAVAILABLE; Index: src/OFTarURIHandler.m ================================================================== --- src/OFTarURIHandler.m +++ src/OFTarURIHandler.m @@ -25,10 +25,11 @@ #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; @@ -59,14 +60,21 @@ archive = [OFTarArchive archiveWithURI: [OFURI URIWithString: archiveURI] mode: @"r"]; - while ((entry = [archive nextEntry]) != nil) - if ([entry.fileName isEqual: path]) - return [archive streamForReadingCurrentEntry]; + 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 @@ -26,10 +26,11 @@ #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 "OFTarURIHandler.h" #import "OFZIPURIHandler.h" @@ -64,10 +65,11 @@ [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: [OFTarURIHandler class] forScheme: @"of-tar"]; Index: src/OFZIPURIHandler.m ================================================================== --- src/OFZIPURIHandler.m +++ src/OFZIPURIHandler.m @@ -22,13 +22,15 @@ #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]; @@ -54,9 +56,14 @@ .stringByRemovingPercentEncoding; archive = [OFZIPArchive archiveWithURI: [OFURI URIWithString: archiveURI] mode: @"r"]; + stream = [archive streamForReadingFile: path]; + + [stream retain]; + + objc_autoreleasePoolPop(pool); - return [archive streamForReadingFile: path]; + return [stream autorelease]; } @end