Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,10 +1,17 @@ Legend: * Changes of existing features or bugfixes + New features This file only contains the most significant changes. + +ObjFW 1.0.3 -> ObjFW 1.0.4, 2023-10-08 + * Fixes OFFile closing fd 0 when initialization fails + * Fixes -[stringByAppendingPathComponent:] on empty strings + * Fixes +[OFSystemInfo operatingSystemName] and + +[OFSystemInfo operatingSystemVersion] returning nil on some systems + * Adds a license for localizations ObjFW 1.0.2 -> ObjFW 1.0.3, 2023-09-14 * Fixes -[OFConcreteData initWithItemSize:] not setting freeWhenDone to true, which resulted in a memory leak * Fixes -[OFData initWithContentsOfIRI:] freeing the buffer in @catch instead Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,11 +1,11 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@ OBJFW_LIB_MAJOR = 1 OBJFW_LIB_MINOR = 0 -OBJFW_LIB_PATCH = 1 +OBJFW_LIB_PATCH = 2 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@ OBJFWRT_STATIC_LIB = @OBJFWRT_STATIC_LIB@ OBJFWRT_FRAMEWORK = @OBJFWRT_FRAMEWORK@ Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -37,11 +37,11 @@ #ifdef OF_FILE_HANDLE_IS_FD #endif { OFFileHandle _handle; - bool _atEndOfStream; + bool _initialized, _atEndOfStream; } /** * @brief Creates a new OFFile with the specified path and mode. * Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -339,10 +339,11 @@ - (instancetype)initWithHandle: (OFFileHandle)handle { self = [super init]; _handle = handle; + _initialized = true; return self; } - (instancetype)init @@ -554,11 +555,11 @@ [super close]; } - (void)dealloc { - if (_handle != OFInvalidFileHandle) + if (_initialized && _handle != OFInvalidFileHandle) [self close]; [super dealloc]; } @end Index: src/platform/AmigaOS/OFString+PathAdditions.m ================================================================== --- src/platform/AmigaOS/OFString+PathAdditions.m +++ src/platform/AmigaOS/OFString+PathAdditions.m @@ -253,10 +253,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"] || [self hasSuffix: @":"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; Index: src/platform/POSIX/OFString+PathAdditions.m ================================================================== --- src/platform/POSIX/OFString+PathAdditions.m +++ src/platform/POSIX/OFString+PathAdditions.m @@ -298,10 +298,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; Index: src/platform/Windows/OFString+PathAdditions.m ================================================================== --- src/platform/Windows/OFString+PathAdditions.m +++ src/platform/Windows/OFString+PathAdditions.m @@ -303,10 +303,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; Index: src/platform/libfat/OFString+PathAdditions.m ================================================================== --- src/platform/libfat/OFString+PathAdditions.m +++ src/platform/libfat/OFString+PathAdditions.m @@ -299,10 +299,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; Index: utils/ofarc/GZIPArchive.m ================================================================== --- utils/ofarc/GZIPArchive.m +++ utils/ofarc/GZIPArchive.m @@ -112,12 +112,12 @@ { OFString *fileName; OFFile *output; if (files.count != 0) { - [OFStdErr writeLine: - OF_LOCALIZED(@"cannot_extract_specific_file_from_gz", + [OFStdErr writeLine: OF_LOCALIZED( + @"cannot_extract_specific_file_from_gz", @"Cannot extract a specific file of a .gz archive!")]; app->_exitStatus = 1; return; } Index: utils/ofdns/OFDNS.m ================================================================== --- utils/ofdns/OFDNS.m +++ utils/ofdns/OFDNS.m @@ -34,12 +34,11 @@ OF_APPLICATION_DELEGATE(OFDNS) static void help(OFStream *stream, bool full, int status) { - [OFStdErr writeLine: - OF_LOCALIZED(@"usage", + [OFStdErr writeLine: OF_LOCALIZED(@"usage", @"Usage: %[prog] -[chst] domain1 [domain2 ...]", @"prog", [OFApplication programName])]; if (full) { [stream writeString: @"\n"]; @@ -70,12 +69,11 @@ _inFlight--; if (exception == nil) [OFStdOut writeFormat: @"%@\n", response]; else { - [OFStdErr writeLine: OF_LOCALIZED( - @"failed_to_resolve", + [OFStdErr writeLine: OF_LOCALIZED(@"failed_to_resolve", @"Failed to resolve: %[exception]", @"exception", exception)]; _errors++; } Index: utils/ofhash/OFHash.m ================================================================== --- utils/ofhash/OFHash.m +++ utils/ofhash/OFHash.m @@ -105,20 +105,20 @@ while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case '?': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_long_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_long_option", @"%[prog]: Unknown option: --%[opt]", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString stringWithFormat: @"%C", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @"opt", optStr)]; } Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -96,12 +96,11 @@ OF_APPLICATION_DELEGATE(OFHTTP) static void help(OFStream *stream, bool full, int status) { - [OFStdErr writeLine: - OF_LOCALIZED(@"usage", + [OFStdErr writeLine: OF_LOCALIZED(@"usage", @"Usage: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]", @"prog", [OFApplication programName])]; if (full) { [stream writeString: @"\n"]; @@ -479,52 +478,52 @@ case 'P': [self setProxy: optionsParser.argument]; break; case ':': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"long_argument_missing", + [OFStdErr writeLine: OF_LOCALIZED( + @"long_argument_missing", @"%[prog]: Argument for option --%[opt] " @"missing", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString stringWithFormat: @"%C", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"argument_missing", + [OFStdErr writeLine: OF_LOCALIZED( + @"argument_missing", @"%[prog]: Argument for option -%[opt] " @"missing", @"prog", [OFApplication programName], @"opt", optStr)]; } [OFApplication terminateWithStatus: 1]; break; case '=': - [OFStdErr writeLine: - OF_LOCALIZED(@"option_takes_no_argument", + [OFStdErr writeLine: OF_LOCALIZED( + @"option_takes_no_argument", @"%[prog]: Option --%[opt] takes no argument", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; [OFApplication terminateWithStatus: 1]; break; case '?': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_long_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_long_option", @"%[prog]: Unknown option: --%[opt]", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString stringWithFormat: @"%C", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @"opt", optStr)]; } @@ -571,12 +570,12 @@ @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } if (_outputPath != nil && _IRIs.count > 1) { - [OFStdErr writeLine: - OF_LOCALIZED(@"output_only_with_one_iri", + [OFStdErr writeLine: OF_LOCALIZED( + @"output_only_with_one_iri", @"%[prog]: Cannot use -o / --output when more than one IRI " @"has been specified!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } @@ -817,12 +816,12 @@ if ([exception isKindOfClass: [OFResolveHostFailedException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; - [OFStdErr writeLine: - OF_LOCALIZED(@"download_resolve_host_failed", + [OFStdErr writeLine: OF_LOCALIZED( + @"download_resolve_host_failed", @"%[prog]: Failed to download <%[iri]>!\n" @" Failed to resolve host: %[exception]", @"prog", [OFApplication programName], @"iri", request.IRI.string, @"exception", exception)]; @@ -829,12 +828,12 @@ } else if ([exception isKindOfClass: [OFConnectSocketFailedException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; - [OFStdErr writeLine: - OF_LOCALIZED(@"download_failed_connection_failed", + [OFStdErr writeLine: OF_LOCALIZED( + @"download_failed_connection_failed", @"%[prog]: Failed to download <%[iri]>!\n" @" Connection failed: %[exception]", @"prog", [OFApplication programName], @"iri", request.IRI.string, @"exception", exception)];