Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -16,11 +16,11 @@ OFCharacterSet.m \ OFColor.m \ OFConstantString.m \ OFCountedSet.m \ OFData.m \ - OFData+CryptoHashing.m \ + OFData+CryptographicHashing.m \ OFData+MessagePackParsing.m \ OFDate.m \ OFDictionary.m \ OFEnumerator.m \ OFFileManager.m \ @@ -69,11 +69,11 @@ OFSHA512Hash.m \ OFSortedList.m \ OFStdIOStream.m \ OFStream.m \ OFString.m \ - OFString+CryptoHashing.m \ + OFString+CryptographicHashing.m \ OFString+JSONParsing.m \ OFString+PropertyListParsing.m \ OFString+Serialization.m \ OFString+URLEncoding.m \ OFString+XMLEscaping.m \ @@ -158,11 +158,11 @@ atomic_powerpc.h \ atomic_sync_builtins.h \ atomic_x86.h INCLUDES := ${SRCS:.m=.h} \ OFCollection.h \ - OFCryptoHash.h \ + OFCryptographicHash.h \ OFJSONRepresentation.h \ OFKernelEventObserver.h \ OFKeyValueCoding.h \ OFLocking.h \ OFMessagePackRepresentation.h \ Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -215,10 +215,17 @@ * @return An initialized OFArray */ - (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects count: (size_t)count; +/** + * @brief Returns an OFEnumerator to enumerate through all objects of the array. + * + * @return An OFEnumerator to enumerate through all objects of the array + */ +- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator; + /** * @brief Returns the object at the specified index in the array. * * @warning The returned object is *not* retained and autoreleased for * performance reasons! Index: src/OFCollection.h ================================================================== --- src/OFCollection.h +++ src/OFCollection.h @@ -20,11 +20,11 @@ /** * @protocol OFCollection OFCollection.h ObjFW/OFCollection.h * * @brief A protocol with methods common for all collections. */ -@protocol OFCollection +@protocol OFCollection /** * @brief The number of objects in the collection */ @property (readonly, nonatomic) size_t count; Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -176,12 +176,12 @@ { [self finishInitialization]; return [self mutableCopy]; } -/* From protocol OFComparing */ -- (of_comparison_result_t)compare: (id )object +/* From protocol OFComparing, but overridden in OFString */ +- (of_comparison_result_t)compare: (OFString *)object { [self finishInitialization]; return [self compare: object]; } DELETED src/OFCryptoHash.h Index: src/OFCryptoHash.h ================================================================== --- src/OFCryptoHash.h +++ src/OFCryptoHash.h @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2008-2021 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 "OFObject.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @protocol OFCryptoHash OFCryptoHash.h ObjFW/OFCryptoHash.h - * - * @brief A protocol for classes providing cryptographic hash functions. - * - * A cryptographic hash implementing this protocol can be copied. The entire - * state is copied, allowing to calculate a new hash from there. This is - * especially useful for generating many hashes with a common prefix. - */ -@protocol OFCryptoHash -#ifdef OF_HAVE_CLASS_PROPERTIES -@property (class, readonly, nonatomic) size_t digestSize; -@property (class, readonly, nonatomic) size_t blockSize; -#endif - -/** - * @brief The digest size of the cryptographic hash, in bytes. - */ -@property (readonly, nonatomic) size_t digestSize; - -/** - * @brief The block size of the cryptographic hash, in bytes. - */ -@property (readonly, nonatomic) size_t blockSize; - -/** - * @brief Whether data may be stored in swappable memory. - */ -@property (readonly, nonatomic) bool allowsSwappableMemory; - -/** - * @brief A boolean whether the hash has already been calculated. - */ -@property (readonly, nonatomic, getter=isCalculated) bool calculated; - -/** - * @brief A buffer containing the cryptographic hash. - * - * The size of the buffer depends on the hash used. The buffer is part of the - * receiver's memory pool. - */ -@property (readonly, nonatomic) const unsigned char *digest - OF_RETURNS_INNER_POINTER; - -/** - * @brief Creates a new cryptographic hash. - * - * @return A new autoreleased cryptographic hash - */ -+ (instancetype)cryptoHashWithAllowsSwappableMemory: - (bool)allowsSwappableMemory; - -/** - * @brief Returns the digest size of the cryptographic hash, in bytes. - * - * @return The digest size of the cryptographic hash, in bytes - */ -+ (size_t)digestSize; - -/** - * @brief Returns the block size of the cryptographic hash, in bytes. - * - * @return The block size of the cryptographic hash, in bytes - */ -+ (size_t)blockSize; - -/** - * @brief Initializes an already allocated cryptographic hash. - * - * @return An initialized cryptographic hash - */ -- (instancetype)initWithAllowsSwappableMemory: (bool)allowsSwappableMemory; - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Adds a buffer to the cryptographic hash to be calculated. - * - * @param buffer The buffer which should be included into the calculation - * @param length The length of the buffer - */ -- (void)updateWithBuffer: (const void *)buffer length: (size_t)length; - -/** - * @brief Resets all state so that a new hash can be calculated. - * - * @warning This invalidates any pointer previously returned by @ref digest. If - * you are still interested in the previous digest, you need to memcpy - * it yourself before calling @ref reset! - */ -- (void)reset; -@end - -OF_ASSUME_NONNULL_END ADDED src/OFCryptographicHash.h Index: src/OFCryptographicHash.h ================================================================== --- src/OFCryptographicHash.h +++ src/OFCryptographicHash.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2008-2021 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 "OFObject.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @protocol OFCryptographicHash \ + * OFCryptographicHash.h ObjFW/OFCryptographicHash.h + * + * @brief A protocol for classes providing cryptographic hash functions. + * + * A cryptographic hash implementing this protocol can be copied. The entire + * state is copied, allowing to calculate a new hash from there. This is + * especially useful for generating many hashes with a common prefix. + */ +@protocol OFCryptographicHash +#ifdef OF_HAVE_CLASS_PROPERTIES +@property (class, readonly, nonatomic) size_t digestSize; +@property (class, readonly, nonatomic) size_t blockSize; +#endif + +/** + * @brief The digest size of the cryptographic hash, in bytes. + */ +@property (readonly, nonatomic) size_t digestSize; + +/** + * @brief The block size of the cryptographic hash, in bytes. + */ +@property (readonly, nonatomic) size_t blockSize; + +/** + * @brief Whether data may be stored in swappable memory. + */ +@property (readonly, nonatomic) bool allowsSwappableMemory; + +/** + * @brief A boolean whether the hash has already been calculated. + */ +@property (readonly, nonatomic, getter=isCalculated) bool calculated; + +/** + * @brief A buffer containing the cryptographic hash. + * + * The size of the buffer depends on the hash used. The buffer is part of the + * receiver's memory pool. + */ +@property (readonly, nonatomic) const unsigned char *digest + OF_RETURNS_INNER_POINTER; + +/** + * @brief Creates a new cryptographic hash. + * + * @return A new autoreleased cryptographic hash + */ ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory; + +/** + * @brief Returns the digest size of the cryptographic hash, in bytes. + * + * @return The digest size of the cryptographic hash, in bytes + */ ++ (size_t)digestSize; + +/** + * @brief Returns the block size of the cryptographic hash, in bytes. + * + * @return The block size of the cryptographic hash, in bytes + */ ++ (size_t)blockSize; + +/** + * @brief Initializes an already allocated cryptographic hash. + * + * @return An initialized cryptographic hash + */ +- (instancetype)initWithAllowsSwappableMemory: (bool)allowsSwappableMemory; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Adds a buffer to the cryptographic hash to be calculated. + * + * @param buffer The buffer which should be included into the calculation + * @param length The length of the buffer + */ +- (void)updateWithBuffer: (const void *)buffer length: (size_t)length; + +/** + * @brief Resets all state so that a new hash can be calculated. + * + * @warning This invalidates any pointer previously returned by @ref digest. If + * you are still interested in the previous digest, you need to memcpy + * it yourself before calling @ref reset! + */ +- (void)reset; +@end + +OF_ASSUME_NONNULL_END DELETED src/OFData+CryptoHashing.h Index: src/OFData+CryptoHashing.h ================================================================== --- src/OFData+CryptoHashing.h +++ src/OFData+CryptoHashing.h @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2008-2021 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 "OFData.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFString; - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFData_CryptoHashing_reference; -#ifdef __cplusplus -} -#endif - -@interface OFData (CryptoHashing) -/** - * @brief The MD5 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *MD5Hash; - -/** - * @brief The RIPEMD-160 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *RIPEMD160Hash; - -/** - * @brief The SHA-1 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *SHA1Hash; - -/** - * @brief The SHA-224 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *SHA224Hash; - -/** - * @brief The SHA-256 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *SHA256Hash; - -/** - * @brief The SHA-384 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *SHA384Hash; - -/** - * @brief The SHA-512 hash of the data as a string. - */ -@property (readonly, nonatomic) OFString *SHA512Hash; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFData+CryptoHashing.m Index: src/OFData+CryptoHashing.m ================================================================== --- src/OFData+CryptoHashing.m +++ src/OFData+CryptoHashing.m @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2008-2021 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 "OFData+CryptoHashing.h" -#import "OFString.h" -#import "OFCryptoHash.h" -#import "OFMD5Hash.h" -#import "OFRIPEMD160Hash.h" -#import "OFSHA1Hash.h" -#import "OFSHA224Hash.h" -#import "OFSHA256Hash.h" -#import "OFSHA384Hash.h" -#import "OFSHA512Hash.h" - -int _OFData_CryptoHashing_reference; - -@implementation OFData (CryptoHashing) -- (OFString *)of_cryptoHashWithClass: (Class )class OF_DIRECT -{ - void *pool = objc_autoreleasePoolPush(); - id hash = - [class cryptoHashWithAllowsSwappableMemory: true]; - size_t digestSize = [class digestSize]; - const unsigned char *digest; - char cString[digestSize * 2]; - - [hash updateWithBuffer: _items length: _count * _itemSize]; - digest = hash.digest; - - for (size_t i = 0; i < digestSize; i++) { - uint8_t high, low; - - high = digest[i] >> 4; - low = digest[i] & 0x0F; - - cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0'); - cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0'); - } - - objc_autoreleasePoolPop(pool); - - return [OFString stringWithCString: cString - encoding: OF_STRING_ENCODING_ASCII - length: digestSize * 2]; -} - -- (OFString *)MD5Hash -{ - return [self of_cryptoHashWithClass: [OFMD5Hash class]]; -} - -- (OFString *)RIPEMD160Hash -{ - return [self of_cryptoHashWithClass: [OFRIPEMD160Hash class]]; -} - -- (OFString *)SHA1Hash -{ - return [self of_cryptoHashWithClass: [OFSHA1Hash class]]; -} - -- (OFString *)SHA224Hash -{ - return [self of_cryptoHashWithClass: [OFSHA224Hash class]]; -} - -- (OFString *)SHA256Hash -{ - return [self of_cryptoHashWithClass: [OFSHA256Hash class]]; -} - -- (OFString *)SHA384Hash -{ - return [self of_cryptoHashWithClass: [OFSHA384Hash class]]; -} - -- (OFString *)SHA512Hash -{ - return [self of_cryptoHashWithClass: [OFSHA512Hash class]]; -} -@end ADDED src/OFData+CryptographicHashing.h Index: src/OFData+CryptographicHashing.h ================================================================== --- src/OFData+CryptographicHashing.h +++ src/OFData+CryptographicHashing.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008-2021 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 "OFData.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFString; + +#ifdef __cplusplus +extern "C" { +#endif +extern int _OFData_CryptographicHashing_reference; +#ifdef __cplusplus +} +#endif + +@interface OFData (CryptographicHashing) +/** + * @brief The MD5 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringByMD5Hashing; + +/** + * @brief The RIPEMD-160 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringByRIPEMD160Hashing; + +/** + * @brief The SHA-1 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA1Hashing; + +/** + * @brief The SHA-224 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA224Hashing; + +/** + * @brief The SHA-256 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA256Hashing; + +/** + * @brief The SHA-384 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA384Hashing; + +/** + * @brief The SHA-512 hash of the data as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA512Hashing; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFData+CryptographicHashing.m Index: src/OFData+CryptographicHashing.m ================================================================== --- src/OFData+CryptographicHashing.m +++ src/OFData+CryptographicHashing.m @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2008-2021 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 "OFData+CryptographicHashing.h" +#import "OFString.h" +#import "OFCryptographicHash.h" +#import "OFMD5Hash.h" +#import "OFRIPEMD160Hash.h" +#import "OFSHA1Hash.h" +#import "OFSHA224Hash.h" +#import "OFSHA256Hash.h" +#import "OFSHA384Hash.h" +#import "OFSHA512Hash.h" + +int _OFData_CryptographicHashing_reference; + +@implementation OFData (CryptographicHashing) +static OFString * +stringByHashing(Class class, OFData *self) +{ + void *pool = objc_autoreleasePoolPush(); + id hash = + [class hashWithAllowsSwappableMemory: true]; + size_t digestSize = [class digestSize]; + const unsigned char *digest; + char cString[digestSize * 2]; + + [hash updateWithBuffer: self->_items + length: self->_count * self->_itemSize]; + digest = hash.digest; + + for (size_t i = 0; i < digestSize; i++) { + uint8_t high, low; + + high = digest[i] >> 4; + low = digest[i] & 0x0F; + + cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0'); + cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0'); + } + + objc_autoreleasePoolPop(pool); + + return [OFString stringWithCString: cString + encoding: OF_STRING_ENCODING_ASCII + length: digestSize * 2]; +} + +- (OFString *)stringByMD5Hashing +{ + return stringByHashing([OFMD5Hash class], self); +} + +- (OFString *)stringByRIPEMD160Hashing +{ + return stringByHashing([OFRIPEMD160Hash class], self); +} + +- (OFString *)stringBySHA1Hashing +{ + return stringByHashing([OFSHA1Hash class], self); +} + +- (OFString *)stringBySHA224Hashing +{ + return stringByHashing([OFSHA224Hash class], self); +} + +- (OFString *)stringBySHA256Hashing +{ + return stringByHashing([OFSHA256Hash class], self); +} + +- (OFString *)stringBySHA384Hashing +{ + return stringByHashing([OFSHA384Hash class], self); +} + +- (OFString *)stringBySHA512Hashing +{ + return stringByHashing([OFSHA512Hash class], self); +} +@end Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -268,10 +268,18 @@ * @param string The string with the Base64-encoded data * @return An initialized OFData */ - (instancetype)initWithBase64EncodedString: (OFString *)string; +/** + * @brief Compares the data to other data. + * + * @param data Data to compare the data to + * @return The result of the comparison + */ +- (of_comparison_result_t)compare: (OFData *)data; + /** * @brief Returns a specific item of the OFData. * * @param index The number of the item to return * @return The specified item of the OFData @@ -321,7 +329,7 @@ @end OF_ASSUME_NONNULL_END #import "OFMutableData.h" -#import "OFData+CryptoHashing.h" +#import "OFData+CryptographicHashing.h" #import "OFData+MessagePackParsing.h" Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -44,11 +44,11 @@ /* References for static linking */ void _references_to_categories_of_OFData(void) { - _OFData_CryptoHashing_reference = 1; + _OFData_CryptographicHashing_reference = 1; _OFData_MessagePackParsing_reference = 1; } @implementation OFData @synthesize itemSize = _itemSize; Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -265,10 +265,18 @@ * @return An initialized OFDate with the specified date and time */ - (instancetype)initWithLocalDateString: (OFString *)string format: (OFString *)format; +/** + * @brief Compares the date to another date. + * + * @param date The date to compare the date to + * @return The result of the comparison + */ +- (of_comparison_result_t)compare: (OFDate *)date; + /** * @brief Creates a string of the date with the specified format. * * See the man page for `strftime` for information on the format. * Index: src/OFEnumerator.h ================================================================== --- src/OFEnumerator.h +++ src/OFEnumerator.h @@ -19,15 +19,19 @@ @class OFArray OF_GENERIC(ObjectType); @class OFEnumerator OF_GENERIC(ObjectType); /** - * @protocol OFEnumerating OFEnumerator.h ObjFW/OFEnumerator.h + * @protocol OFEnumeration OFEnumerator.h ObjFW/OFEnumerator.h * * @brief A protocol for getting an enumerator for the object. + * + * If the class conforming to OFEnumeration is using lightweight generics, the + * only method, @ref objectEnumerator, should be overridden to use lightweight + * generics. */ -@protocol OFEnumerating +@protocol OFEnumeration /** * @brief Returns an OFEnumerator to enumerate through all objects of the * collection. * * @return An OFEnumerator to enumerate through all objects of the collection Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -389,18 +389,19 @@ */ - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path; #endif /** - * @brief Returns an array with the items in the specified directory. + * @brief Returns an array with the URLs of the items in the specified + * directory. * * @note `.` and `..` are not part of the returned array. * * @param URL The URL to the directory whose items should be returned - * @return An array of OFString with the items in the specified directory + * @return An array with the URLs of the items in the specified directory */ -- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL; +- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL; #ifdef OF_HAVE_FILES /** * @brief Changes the current working directory. * Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -454,11 +454,11 @@ objc_autoreleasePoolPop(pool); } #endif -- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL +- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL { OFURLHandler *URLHandler; if (URL == nil) @throw [OFInvalidArgumentException exception]; @@ -471,13 +471,18 @@ #ifdef OF_HAVE_FILES - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *ret; + OFArray OF_GENERIC(OFURL *) *URLs; + OFMutableArray OF_GENERIC(OFString *) *ret; - ret = [self contentsOfDirectoryAtURL: [OFURL fileURLWithPath: path]]; + URLs = [self contentsOfDirectoryAtURL: [OFURL fileURLWithPath: path]]; + ret = [OFMutableArray arrayWithCapacity: URLs.count]; + + for (OFURL *URL in URLs) + [ret addObject: URL.lastPathComponent]; [ret retain]; objc_autoreleasePoolPop(pool); @@ -595,11 +600,11 @@ } type = attributes.fileType; if ([type isEqual: of_file_type_directory]) { - OFArray *contents; + OFArray OF_GENERIC(OFURL *) *contents; @try { [self createDirectoryAtURL: destination]; @try { @@ -635,20 +640,17 @@ errNo: [e errNo]]; @throw e; } - for (OFString *item in contents) { + for (OFURL *item in contents) { void *pool2 = objc_autoreleasePoolPush(); - OFURL *sourceURL, *destinationURL; - - sourceURL = - [source URLByAppendingPathComponent: item]; - destinationURL = - [destination URLByAppendingPathComponent: item]; - - [self copyItemAtURL: sourceURL toURL: destinationURL]; + OFURL *destinationURL = [destination + URLByAppendingPathComponent: + item.lastPathComponent]; + + [self copyItemAtURL: item toURL: destinationURL]; objc_autoreleasePoolPop(pool2); } } else if ([type isEqual: of_file_type_regular]) { size_t pageSize = [OFSystemInfo pageSize]; Index: src/OFFileURLHandler.m ================================================================== --- src/OFFileURLHandler.m +++ src/OFFileURLHandler.m @@ -1010,13 +1010,13 @@ #endif objc_autoreleasePoolPop(pool); } -- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL +- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL { - OFMutableArray *files = [OFMutableArray array]; + OFMutableArray *URLs = [OFMutableArray array]; void *pool = objc_autoreleasePoolPush(); OFString *path; if (URL == nil) @throw [OFInvalidArgumentException exception]; @@ -1050,11 +1050,12 @@ continue; file = [[OFString alloc] initWithUTF16String: fd.cFileName]; @try { - [files addObject: file]; + [URLs addObject: [URL + URLByAppendingPathComponent: file]]; } @finally { [file release]; } } while (FindNextFileW(handle, &fd)); @@ -1088,11 +1089,12 @@ file = [[OFString alloc] initWithCString: fd.cFileName encoding: encoding]; @try { - [files addObject: file]; + [URLs addObject: [URL + URLByAppendingPathComponent: file]]; } @finally { [file release]; } } while (FindNextFileA(handle, &fd)); @@ -1134,11 +1136,12 @@ OFString *file = [[OFString alloc] initWithCString: ed->Name encoding: encoding]; @try { - [files addObject: file]; + [URLs addObject: [URL + URLByAppendingPathComponent: file]]; } @finally { [file release]; } } } @finally { @@ -1156,11 +1159,12 @@ while (ExNext(lock, &fib)) { OFString *file = [[OFString alloc] initWithCString: fib.fib_FileName encoding: encoding]; @try { - [files addObject: file]; + [URLs addObject: + [URL URLByAppendingPathComponent: file]]; } @finally { [file release]; } } # endif @@ -1225,11 +1229,12 @@ continue; file = [[OFString alloc] initWithCString: dirent->d_name encoding: encoding]; @try { - [files addObject: file]; + [URLs addObject: + [URL URLByAppendingPathComponent: file]]; } @finally { [file release]; } } } @finally { @@ -1238,15 +1243,15 @@ [readdirMutex unlock]; # endif } #endif - [files makeImmutable]; + [URLs makeImmutable]; objc_autoreleasePoolPop(pool); - return files; + return URLs; } - (void)removeItemAtURL: (OFURL *)URL { void *pool = objc_autoreleasePoolPush(); @@ -1265,11 +1270,11 @@ if ((error = of_lstat(path, &s)) != 0) @throw [OFRemoveItemFailedException exceptionWithURL: URL errNo: error]; if (S_ISDIR(s.st_mode)) { - OFArray *contents; + OFArray OF_GENERIC(OFURL *) *contents; @try { contents = [self contentsOfDirectoryAtURL: URL]; } @catch (id e) { /* @@ -1285,15 +1290,14 @@ errNo: [e errNo]]; @throw e; } - for (OFString *item in contents) { + for (OFURL *item in contents) { void *pool2 = objc_autoreleasePoolPush(); - [self removeItemAtURL: [OFURL fileURLWithPath: - [path stringByAppendingPathComponent: item]]]; + [self removeItemAtURL: item]; objc_autoreleasePoolPop(pool2); } #ifndef OF_AMIGAOS Index: src/OFHMAC.h ================================================================== --- src/OFHMAC.h +++ src/OFHMAC.h @@ -12,11 +12,11 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" -#import "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN /** * @class OFHMAC OFHMAC.h ObjFW/OFHMAC.h @@ -24,21 +24,21 @@ * @brief A class which provides methods to calculate an HMAC. */ OF_SUBCLASSING_RESTRICTED @interface OFHMAC: OFObject { - Class _hashClass; + Class _hashClass; bool _allowsSwappableMemory; - id _Nullable _outerHash, _innerHash; - id _Nullable _outerHashCopy, _innerHashCopy; + id _Nullable _outerHash, _innerHash; + id _Nullable _outerHashCopy, _innerHashCopy; bool _calculated; } /** * @brief The class for the cryptographic hash used by the HMAC. */ -@property (readonly, nonatomic) Class hashClass; +@property (readonly, nonatomic) Class hashClass; /** * @brief Whether data may be stored in swappable memory. */ @property (readonly, nonatomic) bool allowsSwappableMemory; @@ -62,11 +62,11 @@ * * @param hashClass The class of the hashing algorithm * @param allowsSwappableMemory Whether data may be stored in swappable memory * @return A new, autoreleased OFHMAC */ -+ (instancetype)HMACWithHashClass: (Class )hashClass ++ (instancetype)HMACWithHashClass: (Class )hashClass allowsSwappableMemory: (bool)allowsSwappableMemory; - (instancetype)init OF_UNAVAILABLE; /** @@ -75,11 +75,11 @@ * * @param hashClass The class of the hashing algorithm * @param allowsSwappableMemory Whether data may be stored in swappable memory * @return An initialized OFHMAC */ -- (instancetype)initWithHashClass: (Class )hashClass +- (instancetype)initWithHashClass: (Class )hashClass allowsSwappableMemory: (bool)allowsSwappableMemory OF_DESIGNATED_INITIALIZER; /** * @brief Sets the key for the HMAC. Index: src/OFHMAC.m ================================================================== --- src/OFHMAC.m +++ src/OFHMAC.m @@ -23,11 +23,11 @@ @implementation OFHMAC @synthesize hashClass = _hashClass; @synthesize allowsSwappableMemory = _allowsSwappableMemory; -+ (instancetype)HMACWithHashClass: (Class )class ++ (instancetype)HMACWithHashClass: (Class )class allowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithHashClass: class allowsSwappableMemory: allowsSwappableMemory] autorelease]; @@ -36,11 +36,11 @@ - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithHashClass: (Class )class +- (instancetype)initWithHashClass: (Class )class allowsSwappableMemory: (bool)allowsSwappableMemory { self = [super init]; _hashClass = class; @@ -78,12 +78,12 @@ [_innerHashCopy release]; _outerHash = _innerHash = _outerHashCopy = _innerHashCopy = nil; @try { if (length > blockSize) { - id hash = [_hashClass - cryptoHashWithAllowsSwappableMemory: + id hash = [_hashClass + hashWithAllowsSwappableMemory: _allowsSwappableMemory]; [hash updateWithBuffer: key length: length]; length = hash.digestSize; if OF_UNLIKELY (length > blockSize) @@ -102,13 +102,13 @@ for (size_t i = 0; i < blockSize; i++) { outerKeyPadItems[i] ^= 0x5C; innerKeyPadItems[i] ^= 0x36; } - _outerHash = [[_hashClass cryptoHashWithAllowsSwappableMemory: + _outerHash = [[_hashClass hashWithAllowsSwappableMemory: _allowsSwappableMemory] retain]; - _innerHash = [[_hashClass cryptoHashWithAllowsSwappableMemory: + _innerHash = [[_hashClass hashWithAllowsSwappableMemory: _allowsSwappableMemory] retain]; [_outerHash updateWithBuffer: outerKeyPadItems length: blockSize]; [_innerHash updateWithBuffer: innerKeyPadItems Index: src/OFMD5Hash.h ================================================================== --- src/OFMD5Hash.h +++ src/OFMD5Hash.h @@ -11,11 +11,11 @@ * 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 "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN @class OFSecureData; @@ -23,11 +23,11 @@ * @class OFMD5Hash OFMD5Hash.h ObjFW/OFMD5Hash.h * * @brief A class which provides methods to create an MD5 hash. */ OF_SUBCLASSING_RESTRICTED -@interface OFMD5Hash: OFObject +@interface OFMD5Hash: OFObject { OFSecureData *_iVarsData; struct of_md5_hash_ivars { uint32_t state[4]; uint64_t bits; Index: src/OFMD5Hash.m ================================================================== --- src/OFMD5Hash.m +++ src/OFMD5Hash.m @@ -133,11 +133,11 @@ + (size_t)blockSize { return BLOCK_SIZE; } -+ (instancetype)cryptoHashWithAllowsSwappableMemory: (bool)allowsSwappableMemory ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithAllowsSwappableMemory: allowsSwappableMemory] autorelease]; } Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -359,13 +359,21 @@ * * @param value The `double` value which the OFNumber should contain * @return An initialized OFNumber */ - (instancetype)initWithDouble: (double)value; + +/** + * @brief Compares the number to another number. + * + * @param number The number to compare the number to + * @return The result of the comparison + */ +- (of_comparison_result_t)compare: (OFNumber *)number; @end OF_ASSUME_NONNULL_END #if !defined(NSINTEGER_DEFINED) && !__has_feature(modules) /* Required for number literals to work */ @compatibility_alias NSNumber OFNumber; #endif Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -1216,15 +1216,15 @@ /** * @protocol OFComparing OFObject.h ObjFW/OFObject.h * * @brief A protocol for comparing objects. * - * This protocol is implemented by objects that can be compared. + * This protocol is implemented by objects that can be compared. Its only method, @ref compare:, should be overridden with a stronger type. */ @protocol OFComparing /** - * @brief Compares the object with another object. + * @brief Compares the object to another object. * * @param object An object to compare the object to * @return The result of the comparison */ - (of_comparison_result_t)compare: (id )object; Index: src/OFPlugin.h ================================================================== --- src/OFPlugin.h +++ src/OFPlugin.h @@ -46,11 +46,11 @@ * @brief Loads a plugin from a file. * * @param path Path to the plugin file. The suffix is appended automatically. * @return The loaded plugin */ -+ (OF_KINDOF(OFPlugin *))pluginFromFile: (OFString *)path; ++ (OF_KINDOF(OFPlugin *))pluginWithPath: (OFString *)path; @end #ifdef __cplusplus extern "C" { #endif Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -79,11 +79,11 @@ return nil; #endif } @implementation OFPlugin -+ (id)pluginFromFile: (OFString *)path ++ (id)pluginWithPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); of_plugin_handle_t handle; init_plugin_t initPlugin; OFPlugin *plugin; Index: src/OFRIPEMD160Hash.h ================================================================== --- src/OFRIPEMD160Hash.h +++ src/OFRIPEMD160Hash.h @@ -11,11 +11,11 @@ * 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 "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN @class OFSecureData; @@ -23,11 +23,11 @@ * @class OFRIPEMD160Hash OFRIPEMD160Hash.h ObjFW/OFRIPEMD160Hash.h * * @brief A class which provides methods to create a RIPEMD-160 hash. */ OF_SUBCLASSING_RESTRICTED -@interface OFRIPEMD160Hash: OFObject +@interface OFRIPEMD160Hash: OFObject { OFSecureData *_iVarsData; struct of_ripemd160_hash_ivars { uint32_t state[5]; uint64_t bits; Index: src/OFRIPEMD160Hash.m ================================================================== --- src/OFRIPEMD160Hash.m +++ src/OFRIPEMD160Hash.m @@ -147,11 +147,11 @@ + (size_t)blockSize { return BLOCK_SIZE; } -+ (instancetype)cryptoHashWithAllowsSwappableMemory: (bool)allowsSwappableMemory ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithAllowsSwappableMemory: allowsSwappableMemory] autorelease]; } Index: src/OFSHA1Hash.h ================================================================== --- src/OFSHA1Hash.h +++ src/OFSHA1Hash.h @@ -11,11 +11,11 @@ * 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 "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN @class OFSecureData; @@ -23,11 +23,11 @@ * @class OFSHA1Hash OFSHA1Hash.h ObjFW/OFSHA1Hash.h * * @brief A class which provides methods to create an SHA-1 hash. */ OF_SUBCLASSING_RESTRICTED -@interface OFSHA1Hash: OFObject +@interface OFSHA1Hash: OFObject { OFSecureData *_iVarsData; struct of_sha1_hash_ivars { uint32_t state[5]; uint64_t bits; Index: src/OFSHA1Hash.m ================================================================== --- src/OFSHA1Hash.m +++ src/OFSHA1Hash.m @@ -107,11 +107,11 @@ + (size_t)blockSize { return BLOCK_SIZE; } -+ (instancetype)cryptoHashWithAllowsSwappableMemory: (bool)allowsSwappableMemory ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithAllowsSwappableMemory: allowsSwappableMemory] autorelease]; } Index: src/OFSHA224Or256Hash.h ================================================================== --- src/OFSHA224Or256Hash.h +++ src/OFSHA224Or256Hash.h @@ -11,11 +11,11 @@ * 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 "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN @class OFSecureData; @@ -22,11 +22,11 @@ /** * @class OFSHA224Or256Hash OFSHA224Or256Hash.h ObjFW/OFSHA224Or256Hash.h * * @brief A base class for SHA-224 and SHA-256. */ -@interface OFSHA224Or256Hash: OFObject +@interface OFSHA224Or256Hash: OFObject { @private OFSecureData *_iVarsData; @protected struct of_sha224_or_256_hash_ivars { Index: src/OFSHA224Or256Hash.m ================================================================== --- src/OFSHA224Or256Hash.m +++ src/OFSHA224Or256Hash.m @@ -127,11 +127,11 @@ + (size_t)blockSize { return BLOCK_SIZE; } -+ (instancetype)cryptoHashWithAllowsSwappableMemory: (bool)allowsSwappableMemory ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithAllowsSwappableMemory: allowsSwappableMemory] autorelease]; } Index: src/OFSHA384Or512Hash.h ================================================================== --- src/OFSHA384Or512Hash.h +++ src/OFSHA384Or512Hash.h @@ -11,11 +11,11 @@ * 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 "OFCryptoHash.h" +#import "OFCryptographicHash.h" OF_ASSUME_NONNULL_BEGIN @class OFSecureData; @@ -22,11 +22,11 @@ /** * @class OFSHA384Or512Hash OFSHA384Or512Hash.h ObjFW/OFSHA384Or512Hash.h * * @brief A base class for SHA-384 and SHA-512. */ -@interface OFSHA384Or512Hash: OFObject +@interface OFSHA384Or512Hash: OFObject { @private OFSecureData *_iVarsData; @protected struct of_sha384_or_512_hash_ivars { Index: src/OFSHA384Or512Hash.m ================================================================== --- src/OFSHA384Or512Hash.m +++ src/OFSHA384Or512Hash.m @@ -138,11 +138,11 @@ + (size_t)blockSize { return BLOCK_SIZE; } -+ (instancetype)cryptoHashWithAllowsSwappableMemory: (bool)allowsSwappableMemory ++ (instancetype)hashWithAllowsSwappableMemory: (bool)allowsSwappableMemory { return [[[self alloc] initWithAllowsSwappableMemory: allowsSwappableMemory] autorelease]; } Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -161,10 +161,17 @@ * @return An initialized set with the specified object and va_list */ - (instancetype)initWithObject: (ObjectType)firstObject arguments: (va_list)arguments; +/** + * @brief Returns an OFEnumerator to enumerate through all objects of the set. + * + * @return An OFEnumerator to enumerate through all objects of the set + */ +- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator; + /** * @brief Returns whether the receiver is a subset of the specified set. * * @return Whether the receiver is a subset of the specified set */ DELETED src/OFString+CryptoHashing.h Index: src/OFString+CryptoHashing.h ================================================================== --- src/OFString+CryptoHashing.h +++ src/OFString+CryptoHashing.h @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2008-2021 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 "OFString.h" - -OF_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFString_CryptoHashing_reference; -#ifdef __cplusplus -} -#endif - -@interface OFString (CryptoHashing) -/** - * @brief The MD5 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *MD5Hash; - -/** - * @brief The RIPEMD-160 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *RIPEMD160Hash; - -/** - * @brief The SHA-1 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *SHA1Hash; - -/** - * @brief The SHA-224 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *SHA224Hash; - -/** - * @brief The SHA-256 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *SHA256Hash; - -/** - * @brief The SHA-384 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *SHA384Hash; - -/** - * @brief The SHA-512 hash of the string as a string. - */ -@property (readonly, nonatomic) OFString *SHA512Hash; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFString+CryptoHashing.m Index: src/OFString+CryptoHashing.m ================================================================== --- src/OFString+CryptoHashing.m +++ src/OFString+CryptoHashing.m @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2008-2021 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 "OFString.h" -#import "OFCryptoHash.h" -#import "OFMD5Hash.h" -#import "OFRIPEMD160Hash.h" -#import "OFSHA1Hash.h" -#import "OFSHA224Hash.h" -#import "OFSHA256Hash.h" -#import "OFSHA384Hash.h" -#import "OFSHA512Hash.h" - -int _OFString_CryptoHashing_reference; - -@implementation OFString (CryptoHashing) -- (OFString *)of_cryptoHashWithClass: (Class )class -{ - void *pool = objc_autoreleasePoolPush(); - id hash = [class - cryptoHashWithAllowsSwappableMemory: true]; - size_t digestSize = [class digestSize]; - const unsigned char *digest; - char cString[digestSize * 2]; - - [hash updateWithBuffer: self.UTF8String length: self.UTF8StringLength]; - digest = hash.digest; - - for (size_t i = 0; i < digestSize; i++) { - uint8_t high, low; - - high = digest[i] >> 4; - low = digest[i] & 0x0F; - - cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0'); - cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0'); - } - - objc_autoreleasePoolPop(pool); - - return [OFString stringWithCString: cString - encoding: OF_STRING_ENCODING_ASCII - length: digestSize * 2]; -} - -- (OFString *)MD5Hash -{ - return [self of_cryptoHashWithClass: [OFMD5Hash class]]; -} - -- (OFString *)RIPEMD160Hash -{ - return [self of_cryptoHashWithClass: [OFRIPEMD160Hash class]]; -} - -- (OFString *)SHA1Hash -{ - return [self of_cryptoHashWithClass: [OFSHA1Hash class]]; -} - -- (OFString *)SHA224Hash -{ - return [self of_cryptoHashWithClass: [OFSHA224Hash class]]; -} - -- (OFString *)SHA256Hash -{ - return [self of_cryptoHashWithClass: [OFSHA256Hash class]]; -} - -- (OFString *)SHA384Hash -{ - return [self of_cryptoHashWithClass: [OFSHA384Hash class]]; -} - -- (OFString *)SHA512Hash -{ - return [self of_cryptoHashWithClass: [OFSHA512Hash class]]; -} -@end ADDED src/OFString+CryptographicHashing.h Index: src/OFString+CryptographicHashing.h ================================================================== --- src/OFString+CryptographicHashing.h +++ src/OFString+CryptographicHashing.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2008-2021 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 "OFString.h" + +OF_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif +extern int _OFString_CryptographicHashing_reference; +#ifdef __cplusplus +} +#endif + +@interface OFString (CryptographicHashing) +/** + * @brief The MD5 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringByMD5Hashing; + +/** + * @brief The RIPEMD-160 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringByRIPEMD160Hashing; + +/** + * @brief The SHA-1 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA1Hashing; + +/** + * @brief The SHA-224 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA224Hashing; + +/** + * @brief The SHA-256 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA256Hashing; + +/** + * @brief The SHA-384 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA384Hashing; + +/** + * @brief The SHA-512 hash of the string as a string. + */ +@property (readonly, nonatomic) OFString *stringBySHA512Hashing; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFString+CryptographicHashing.m Index: src/OFString+CryptographicHashing.m ================================================================== --- src/OFString+CryptographicHashing.m +++ src/OFString+CryptographicHashing.m @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2008-2021 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 "OFString.h" +#import "OFCryptographicHash.h" +#import "OFMD5Hash.h" +#import "OFRIPEMD160Hash.h" +#import "OFSHA1Hash.h" +#import "OFSHA224Hash.h" +#import "OFSHA256Hash.h" +#import "OFSHA384Hash.h" +#import "OFSHA512Hash.h" + +int _OFString_CryptographicHashing_reference; + +@implementation OFString (CryptographicHashing) +static OFString * +stringByHashing(Class class, OFString *self) +{ + void *pool = objc_autoreleasePoolPush(); + id hash = + [class hashWithAllowsSwappableMemory: true]; + size_t digestSize = [class digestSize]; + const unsigned char *digest; + char cString[digestSize * 2]; + + [hash updateWithBuffer: self.UTF8String length: self.UTF8StringLength]; + digest = hash.digest; + + for (size_t i = 0; i < digestSize; i++) { + uint8_t high, low; + + high = digest[i] >> 4; + low = digest[i] & 0x0F; + + cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0'); + cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0'); + } + + objc_autoreleasePoolPop(pool); + + return [OFString stringWithCString: cString + encoding: OF_STRING_ENCODING_ASCII + length: digestSize * 2]; +} + +- (OFString *)stringByMD5Hashing +{ + return stringByHashing([OFMD5Hash class], self); +} + +- (OFString *)stringByRIPEMD160Hashing +{ + return stringByHashing([OFRIPEMD160Hash class], self); +} + +- (OFString *)stringBySHA1Hashing +{ + return stringByHashing([OFSHA1Hash class], self); +} + +- (OFString *)stringBySHA224Hashing +{ + return stringByHashing([OFSHA224Hash class], self); +} + +- (OFString *)stringBySHA256Hashing +{ + return stringByHashing([OFSHA256Hash class], self); +} + +- (OFString *)stringBySHA384Hashing +{ + return stringByHashing([OFSHA384Hash class], self); +} + +- (OFString *)stringBySHA512Hashing +{ + return stringByHashing([OFSHA512Hash class], self); +} +@end Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -882,17 +882,24 @@ * @return The number of bytes the string needs in the specified encoding. */ - (size_t)cStringLengthWithEncoding: (of_string_encoding_t)encoding; /** - * @brief Compares the OFString to another OFString without caring about the - * case. + * @brief Compares the string to another string. + * + * @param string The string to compare the string to + * @return The result of the comparison + */ +- (of_comparison_result_t)compare: (OFString *)string; + +/** + * @brief Compares the string to another string without caring about the case. * - * @param otherString A string to compare with - * @return An of_comparison_result_t + * @param string The string to compare the string to + * @return The result of the comparison */ -- (of_comparison_result_t)caseInsensitiveCompare: (OFString *)otherString; +- (of_comparison_result_t)caseInsensitiveCompare: (OFString *)string; /** * @brief Returns the Unicode character at the specified index. * * @param index The index of the Unicode character to return @@ -1285,11 +1292,11 @@ OF_ASSUME_NONNULL_END #include "OFConstantString.h" #include "OFMutableString.h" #ifdef __OBJC__ -# import "OFString+CryptoHashing.h" +# import "OFString+CryptographicHashing.h" # import "OFString+JSONParsing.h" # ifdef OF_HAVE_FILES # import "OFString+PathAdditions.h" # endif # import "OFString+PropertyListParsing.h" Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -125,11 +125,11 @@ /* References for static linking */ void _references_to_categories_of_OFString(void) { - _OFString_CryptoHashing_reference = 1; + _OFString_CryptographicHashing_reference = 1; _OFString_JSONParsing_reference = 1; #ifdef OF_HAVE_FILES _OFString_PathAdditions_reference = 1; #endif _OFString_PropertyListParsing_reference = 1; Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -451,10 +451,18 @@ interval: (of_time_interval_t)interval repeats: (bool)repeats block: (of_timer_block_t)block; #endif +/** + * @brief Compares the timer to another timer. + * + * @param timer The timer to compare the string to + * @return The result of the comparison + */ +- (of_comparison_result_t)compare: (OFTimer *)timer; + /** * @brief Fires the timer, meaning it will execute the specified selector on the * target. */ - (void)fire; Index: src/OFURLHandler.h ================================================================== --- src/OFURLHandler.h +++ src/OFURLHandler.h @@ -135,18 +135,19 @@ * @param URL The URL of the directory to create */ - (void)createDirectoryAtURL: (OFURL *)URL; /** - * @brief Returns an array with the items in the specified directory. + * @brief Returns an array with the URLs of the items in the specified + * directory. * * @note `.` and `..` are not part of the returned array. * * @param URL The URL to the directory whose items should be returned - * @return An array of OFString with the items in the specified directory + * @return An array with the URLs of the items in the specified directory */ -- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL; +- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL; /** * @brief Removes the item at the specified URL. * * If the item at the specified URL is a directory, it is removed recursively. Index: src/OFURLHandler.m ================================================================== --- src/OFURLHandler.m +++ src/OFURLHandler.m @@ -164,11 +164,11 @@ - (void)createDirectoryAtURL: (OFURL *)URL { OF_UNRECOGNIZED_SELECTOR } -- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL +- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL { OF_UNRECOGNIZED_SELECTOR } - (void)removeItemAtURL: (OFURL *)URL Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -97,11 +97,11 @@ #ifdef OF_HAVE_SUBPROCESSES # import "OFSubprocess.h" #endif -#import "OFCryptoHash.h" +#import "OFCryptographicHash.h" #import "OFMD5Hash.h" #import "OFRIPEMD160Hash.h" #import "OFSHA1Hash.h" #import "OFSHA224Hash.h" #import "OFSHA256Hash.h" Index: tests/OFDataTests.m ================================================================== --- tests/OFDataTests.m +++ tests/OFDataTests.m @@ -166,28 +166,35 @@ OFOutOfRangeException, [immutable subdataWithRange: of_range(7, 1)]) EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2", OFOutOfRangeException, [mutable subdataWithRange: of_range(6, 1)]) - TEST(@"-[MD5Hash]", [mutable.MD5Hash isEqual: @"abcde".MD5Hash]) - - TEST(@"-[RIPEMD160Hash]", [mutable.RIPEMD160Hash - isEqual: @"abcde".RIPEMD160Hash]) - - TEST(@"-[SHA1Hash]", [mutable.SHA1Hash isEqual: @"abcde".SHA1Hash]) - - TEST(@"-[SHA224Hash]", [mutable.SHA224Hash - isEqual: @"abcde".SHA224Hash]) - - TEST(@"-[SHA256Hash]", [mutable.SHA256Hash - isEqual: @"abcde".SHA256Hash]) - - TEST(@"-[SHA384Hash]", [mutable.SHA384Hash - isEqual: @"abcde".SHA384Hash]) - - TEST(@"-[SHA512Hash]", [mutable.SHA512Hash - isEqual: @"abcde".SHA512Hash]) + TEST(@"-[stringByMD5Hashing]", [mutable.stringByMD5Hashing + isEqual: @"ab56b4d92b40713acc5af89985d4b786"]) + + TEST(@"-[stringByRIPEMD160Hashing]", [mutable.stringByRIPEMD160Hashing + isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"]) + + TEST(@"-[stringBySHA1Hashing]", [mutable.stringBySHA1Hashing + isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"]) + + TEST(@"-[stringBySHA224Hashing]", [mutable.stringBySHA224Hashing + isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6" + ]) + + TEST(@"-[stringBySHA256Hashing]", [mutable.stringBySHA256Hashing + isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0" + @"c44ca42c"]) + + TEST(@"-[stringBySHA384Hashing]", [mutable.stringBySHA384Hashing + isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813" + @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"]) + + TEST(@"-[stringBySHA512Hashing]", [mutable.stringBySHA512Hashing + isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3" + @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665" + @"bef2289a5c70b0a1"]) TEST(@"-[stringByBase64Encoding]", [mutable.stringByBase64Encoding isEqual: @"YWJjZGU="]) TEST(@"+[dataWithBase64EncodedString:]", Index: tests/OFMD5HashTests.m ================================================================== --- tests/OFMD5HashTests.m +++ tests/OFMD5HashTests.m @@ -29,12 +29,12 @@ { void *pool = objc_autoreleasePoolPush(); OFMD5Hash *md5, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (md5 = [OFMD5Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (md5 = [OFMD5Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[64]; size_t len = [f readIntoBuffer: buf length: 64]; [md5 updateWithBuffer: buf length: len]; Index: tests/OFPluginTests.m ================================================================== --- tests/OFPluginTests.m +++ tests/OFPluginTests.m @@ -31,13 +31,13 @@ - (void)pluginTests { void *pool = objc_autoreleasePoolPush(); TestPlugin *plugin; - TEST(@"+[pluginFromFile:]", - (plugin = [OFPlugin pluginFromFile: PLUGIN_PATH])) + TEST(@"+[pluginWithPath:]", + (plugin = [OFPlugin pluginWithPath: PLUGIN_PATH])) TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468) objc_autoreleasePoolPop(pool); } @end Index: tests/OFRIPEMD160HashTests.m ================================================================== --- tests/OFRIPEMD160HashTests.m +++ tests/OFRIPEMD160HashTests.m @@ -30,13 +30,12 @@ { void *pool = objc_autoreleasePoolPush(); OFRIPEMD160Hash *rmd160, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (rmd160 = [OFRIPEMD160Hash - cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (rmd160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[64]; size_t len = [f readIntoBuffer: buf length: 64]; [rmd160 updateWithBuffer: buf length: len]; Index: tests/OFSHA1HashTests.m ================================================================== --- tests/OFSHA1HashTests.m +++ tests/OFSHA1HashTests.m @@ -30,12 +30,12 @@ { void *pool = objc_autoreleasePoolPush(); OFSHA1Hash *sha1, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (sha1 = [OFSHA1Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (sha1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[64]; size_t len = [f readIntoBuffer: buf length: 64]; [sha1 updateWithBuffer: buf length: len]; Index: tests/OFSHA224HashTests.m ================================================================== --- tests/OFSHA224HashTests.m +++ tests/OFSHA224HashTests.m @@ -30,12 +30,12 @@ { void *pool = objc_autoreleasePoolPush(); OFSHA224Hash *sha224, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (sha224 = [OFSHA224Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (sha224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[64]; size_t len = [f readIntoBuffer: buf length: 64]; [sha224 updateWithBuffer: buf length: len]; Index: tests/OFSHA256HashTests.m ================================================================== --- tests/OFSHA256HashTests.m +++ tests/OFSHA256HashTests.m @@ -30,12 +30,12 @@ { void *pool = objc_autoreleasePoolPush(); OFSHA256Hash *sha256, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (sha256 = [OFSHA256Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (sha256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[64]; size_t len = [f readIntoBuffer: buf length: 64]; [sha256 updateWithBuffer: buf length: len]; Index: tests/OFSHA384HashTests.m ================================================================== --- tests/OFSHA384HashTests.m +++ tests/OFSHA384HashTests.m @@ -31,12 +31,12 @@ { void *pool = objc_autoreleasePoolPush(); OFSHA384Hash *sha384, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (sha384 = [OFSHA384Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (sha384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[128]; size_t len = [f readIntoBuffer: buf length: 128]; [sha384 updateWithBuffer: buf length: len]; Index: tests/OFSHA512HashTests.m ================================================================== --- tests/OFSHA512HashTests.m +++ tests/OFSHA512HashTests.m @@ -32,12 +32,12 @@ { void *pool = objc_autoreleasePoolPush(); OFSHA512Hash *sha512, *copy; OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - TEST(@"+[cryptoHashWithAllowsSwappableMemory:]", - (sha512 = [OFSHA512Hash cryptoHashWithAllowsSwappableMemory: true])) + TEST(@"+[hashWithAllowsSwappableMemory:]", + (sha512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true])) while (!f.atEndOfStream) { char buf[128]; size_t len = [f readIntoBuffer: buf length: 128]; [sha512 updateWithBuffer: buf length: len]; Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -1206,34 +1206,36 @@ (ua = [C(@"fรถรถbรคr๐Ÿ€บ") UTF32StringWithByteOrder: SWAPPED_BYTE_ORDER]) && !memcmp(ua, sucstr + 1, of_string_utf32_length(sucstr) * 4)) #undef SWAPPED_BYTE_ORDER - TEST(@"-[MD5Hash]", [C(@"asdfoobar").MD5Hash + TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) - TEST(@"-[RIPEMD160Hash]", [C(@"asdfoobar").RIPEMD160Hash + TEST(@"-[stringByRIPEMD160Hashing]", + [C(@"asdfoobar").stringByRIPEMD160Hashing isEqual: @"021d773b0fac06eb6755ca6aa58a580c980f7f13"]) - TEST(@"-[SHA1Hash]", [C(@"asdfoobar").SHA1Hash + TEST(@"-[stringBySHA1Hashing]", [C(@"asdfoobar").stringBySHA1Hashing isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"]) - TEST(@"-[SHA224Hash]", [C(@"asdfoobar").SHA224Hash - isEqual: - @"5a06822dcbd5a874f67d062b80b9d8a9cb9b5b303960b9da9290c192"]) - - TEST(@"-[SHA256Hash]", [C(@"asdfoobar").SHA256Hash isEqual: - @"28e65b1dcd7f6ce2ea6277b15f87b913" - @"628b5500bf7913a2bbf4cedcfa1215f6"]) - - TEST(@"-[SHA384Hash]", [C(@"asdfoobar").SHA384Hash isEqual: - @"73286da882ffddca2f45e005cfa6b44f3fc65bfb26db1d08" - @"7ded2f9c279e5addf8be854044bca0cece073fce28eec7d9"]) - - TEST(@"-[SHA512Hash]", [C(@"asdfoobar").SHA512Hash isEqual: - @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56412a9247c" - @"3579a329e53a5dc74676b106755e3394f9454a2d42273242615d32f80437d61"]) + TEST(@"-[stringBySHA224Hashing]", [C(@"asdfoobar").stringBySHA224Hashing + isEqual: @"5a06822dcbd5a874f67d062b80b9d8a9cb9b5b303960b9da9290c192" + ]) + + TEST(@"-[stringBySHA256Hashing]", [C(@"asdfoobar").stringBySHA256Hashing + isEqual: @"28e65b1dcd7f6ce2ea6277b15f87b913628b5500bf7913a2bbf4cedc" + @"fa1215f6"]) + + TEST(@"-[stringBySHA384Hashing]", [C(@"asdfoobar").stringBySHA384Hashing + isEqual: @"73286da882ffddca2f45e005cfa6b44f3fc65bfb26db1d087ded2f9c" + @"279e5addf8be854044bca0cece073fce28eec7d9"]) + + TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing + isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56" + @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324" + @"2615d32f80437d61"]) cs = [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$๐Ÿ"]; TEST(@"-[stringByURLEncodingWithAllowedCharacters:]", [[C(@"foo\"ba'_~$]๐Ÿ๐ŸŒ") stringByURLEncodingWithAllowedCharacters: cs] isEqual: @"foo%22ba'_~$%5D๐Ÿ%F0%9F%8D%8C"]) Index: utils/ofhash/OFHash.m ================================================================== --- utils/ofhash/OFHash.m +++ utils/ofhash/OFHash.m @@ -49,11 +49,11 @@ [OFApplication terminateWithStatus: 1]; } static void -printHash(OFString *algo, OFString *path, id hash) +printHash(OFString *algo, OFString *path, id hash) { const unsigned char *digest = hash.digest; size_t digestSize = hash.digestSize; [of_stdout writeFormat: @"%@ ", algo]; @@ -146,29 +146,24 @@ if (optionsParser.remainingArguments.count < 1) help(); if (calculateMD5) - MD5Hash = [OFMD5Hash cryptoHashWithAllowsSwappableMemory: true]; + MD5Hash = [OFMD5Hash hashWithAllowsSwappableMemory: true]; if (calculateRIPEMD160) RIPEMD160Hash = - [OFRIPEMD160Hash cryptoHashWithAllowsSwappableMemory: true]; + [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]; if (calculateSHA1) - SHA1Hash = - [OFSHA1Hash cryptoHashWithAllowsSwappableMemory: true]; + SHA1Hash = [OFSHA1Hash hashWithAllowsSwappableMemory: true]; if (calculateSHA224) - SHA224Hash = - [OFSHA224Hash cryptoHashWithAllowsSwappableMemory: true]; + SHA224Hash = [OFSHA224Hash hashWithAllowsSwappableMemory: true]; if (calculateSHA256) - SHA256Hash = - [OFSHA256Hash cryptoHashWithAllowsSwappableMemory: true]; + SHA256Hash = [OFSHA256Hash hashWithAllowsSwappableMemory: true]; if (calculateSHA384) - SHA384Hash = - [OFSHA384Hash cryptoHashWithAllowsSwappableMemory: true]; + SHA384Hash = [OFSHA384Hash hashWithAllowsSwappableMemory: true]; if (calculateSHA512) - SHA512Hash = - [OFSHA512Hash cryptoHashWithAllowsSwappableMemory: true]; + SHA512Hash = [OFSHA512Hash hashWithAllowsSwappableMemory: true]; for (OFString *path in optionsParser.remainingArguments) { void *pool = objc_autoreleasePoolPush(); OFStream *file; Index: utils/ofhttp/Makefile ================================================================== --- utils/ofhttp/Makefile +++ utils/ofhttp/Makefile @@ -14,11 +14,13 @@ CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../.. \ - -DLANGUAGE_DIR=\"${datadir}/ofhttp/lang\" + -DLANGUAGE_DIR='"${datadir}/ofhttp/lang"' \ + -DLIB_PREFIX='"${LIB_PREFIX}"' \ + -DLIB_SUFFIX='"${LIB_SUFFIX}"' LIBS := -L../../src -lobjfw \ -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -283,11 +283,11 @@ { if (self != [OFHTTP class]) return; /* Opportunistically try loading ObjOpenSSL and ignore any errors. */ - of_dlopen(@"objopenssl", OF_RTLD_LAZY); + of_dlopen(@LIB_PREFIX @"objopenssl" @LIB_SUFFIX, OF_RTLD_LAZY); } #endif - (instancetype)init {