@@ -64,11 +64,11 @@ OFString *_outputPath, *_currentFileName; bool _continue, _force, _detectFileName, _detectFileNameRequest; bool _detectedFileName, _quiet, _verbose, _insecure, _ignoreStatus; bool _useUnicode; OFStream *_body; - of_http_request_method_t _method; + OFHTTPRequestMethod _method; OFMutableDictionary *_clientHeaders; OFHTTPClient *_HTTPClient; char *_buffer; OFStream *_output; unsigned long long _received, _length, _resumedFrom; @@ -81,11 +81,11 @@ OF_APPLICATION_DELEGATE(OFHTTP) static void help(OFStream *stream, bool full, int status) { - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"usage", @"Usage: %[prog] -[cehHmoOPqv] url1 [url2 ...]", @"prog", [OFApplication programName])]; if (full) { @@ -130,18 +130,18 @@ { void *pool; const char *UTF8String; size_t UTF8StringLength; enum { - DISPOSITION_TYPE, - DISPOSITION_TYPE_SEMICOLON, - DISPOSITION_PARAM_NAME_SKIP_SPACE, - DISPOSITION_PARAM_NAME, - DISPOSITION_PARAM_VALUE, - DISPOSITION_PARAM_QUOTED, - DISPOSITION_PARAM_UNQUOTED, - DISPOSITION_EXPECT_SEMICOLON + stateDispositionType, + stateDispositionTypeSemicolon, + stateDispositionParamNameSkipSpace, + stateDispositionParamName, + stateDispositionParamValue, + stateDispositionParamQuoted, + stateDispositionParamUnquoted, + stateDispositionExpectSemicolon } state; size_t last; OFString *type = nil, *paramName = nil, *paramValue; OFMutableDictionary *params; OFString *fileName; @@ -151,76 +151,76 @@ pool = objc_autoreleasePoolPush(); UTF8String = contentDisposition.UTF8String; UTF8StringLength = contentDisposition.UTF8StringLength; - state = DISPOSITION_TYPE; + state = stateDispositionType; params = [OFMutableDictionary dictionary]; last = 0; for (size_t i = 0; i < UTF8StringLength; i++) { switch (state) { - case DISPOSITION_TYPE: + case stateDispositionType: if (UTF8String[i] == ';' || UTF8String[i] == ' ') { type = [OFString stringWithUTF8String: UTF8String length: i]; state = (UTF8String[i] == ';' - ? DISPOSITION_PARAM_NAME_SKIP_SPACE - : DISPOSITION_TYPE_SEMICOLON); + ? stateDispositionParamNameSkipSpace + : stateDispositionTypeSemicolon); last = i + 1; } break; - case DISPOSITION_TYPE_SEMICOLON: + case stateDispositionTypeSemicolon: if (UTF8String[i] == ';') { - state = DISPOSITION_PARAM_NAME_SKIP_SPACE; + state = stateDispositionParamNameSkipSpace; last = i + 1; } else if (UTF8String[i] != ' ') { objc_autoreleasePoolPop(pool); return nil; } break; - case DISPOSITION_PARAM_NAME_SKIP_SPACE: + case stateDispositionParamNameSkipSpace: if (UTF8String[i] != ' ') { - state = DISPOSITION_PARAM_NAME; + state = stateDispositionParamName; last = i; i--; } break; - case DISPOSITION_PARAM_NAME: + case stateDispositionParamName: if (UTF8String[i] == '=') { paramName = [OFString stringWithUTF8String: UTF8String + last length: i - last]; - state = DISPOSITION_PARAM_VALUE; + state = stateDispositionParamValue; } break; - case DISPOSITION_PARAM_VALUE: + case stateDispositionParamValue: if (UTF8String[i] == '"') { - state = DISPOSITION_PARAM_QUOTED; + state = stateDispositionParamQuoted; last = i + 1; } else { - state = DISPOSITION_PARAM_UNQUOTED; + state = stateDispositionParamUnquoted; last = i; i--; } break; - case DISPOSITION_PARAM_QUOTED: + case stateDispositionParamQuoted: if (UTF8String[i] == '"') { paramValue = [OFString stringWithUTF8String: UTF8String + last length: i - last]; [params setObject: paramValue forKey: paramName.lowercaseString]; - state = DISPOSITION_EXPECT_SEMICOLON; + state = stateDispositionExpectSemicolon; } break; - case DISPOSITION_PARAM_UNQUOTED: + case stateDispositionParamUnquoted: if (UTF8String[i] <= 31 || UTF8String[i] >= 127) return nil; switch (UTF8String[i]) { case ' ': case '"': case '(': case ')': case ',': @@ -234,34 +234,34 @@ length: i - last]; [params setObject: paramValue forKey: paramName.lowercaseString]; - state = DISPOSITION_PARAM_NAME_SKIP_SPACE; + state = stateDispositionParamNameSkipSpace; break; } break; - case DISPOSITION_EXPECT_SEMICOLON: + case stateDispositionExpectSemicolon: if (UTF8String[i] == ';') { - state = DISPOSITION_PARAM_NAME_SKIP_SPACE; + state = stateDispositionParamNameSkipSpace; last = i + 1; } else if (UTF8String[i] != ' ') { objc_autoreleasePoolPop(pool); return nil; } break; } } - if (state == DISPOSITION_PARAM_UNQUOTED) { + if (state == stateDispositionParamUnquoted) { paramValue = [OFString stringWithUTF8String: UTF8String + last length: UTF8StringLength - last]; [params setObject: paramValue forKey: paramName.lowercaseString]; - } else if (state != DISPOSITION_EXPECT_SEMICOLON) { + } else if (state != stateDispositionExpectSemicolon) { objc_autoreleasePoolPop(pool); return nil; } if (![type isEqual: @"attachment"] || @@ -283,29 +283,29 @@ { if (self != [OFHTTP class]) return; /* Opportunistically try loading ObjOpenSSL and ignore any errors. */ - of_dlopen(@"objopenssl", OF_RTLD_LAZY); + OFDLOpen(@LIB_PREFIX @"objopenssl" @LIB_SUFFIX, OFDLOpenFlagLazy); } #endif - (instancetype)init { self = [super init]; @try { - _method = OF_HTTP_REQUEST_METHOD_GET; + _method = OFHTTPRequestMethodGet; _clientHeaders = [[OFMutableDictionary alloc] initWithObject: @"OFHTTP" forKey: @"User-Agent"]; _HTTPClient = [[OFHTTPClient alloc] init]; _HTTPClient.delegate = self; - _buffer = of_alloc(1, [OFSystemInfo pageSize]); + _buffer = OFAllocMemory(1, [OFSystemInfo pageSize]); } @catch (id e) { [self release]; @throw e; } @@ -315,12 +315,12 @@ - (void)addHeader: (OFString *)header { size_t pos = [header rangeOfString: @":"].location; OFString *name, *value; - if (pos == OF_NOT_FOUND) { - [of_stderr writeLine: OF_LOCALIZED(@"invalid_input_header", + if (pos == OFNotFound) { + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_header", @"%[prog]: Headers must to be in format name:value!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } @@ -328,12 +328,11 @@ .stringByDeletingEnclosingWhitespaces; value = [header substringFromIndex: pos + 1] .stringByDeletingEnclosingWhitespaces; - [_clientHeaders setObject: value - forKey: name]; + [_clientHeaders setObject: value forKey: name]; } - (void)setBody: (OFString *)path { OFString *contentLength = nil; @@ -340,14 +339,13 @@ [_body release]; _body = nil; if ([path isEqual: @"-"]) - _body = [of_stdin copy]; + _body = [OFStdIn copy]; else { - _body = [[OFFile alloc] initWithPath: path - mode: @"r"]; + _body = [[OFFile alloc] initWithPath: path mode: @"r"]; @try { unsigned long long fileSize = [[OFFileManager defaultManager] attributesOfItemAtPath: path].fileSize; @@ -370,13 +368,13 @@ void *pool = objc_autoreleasePoolPush(); method = method.uppercaseString; @try { - _method = of_http_request_method_from_string(method); + _method = OFHTTPRequestMethodParseName(method); } @catch (OFInvalidArgumentException *e) { - [of_stderr writeLine: OF_LOCALIZED(@"invalid_input_method", + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_method", @"%[prog]: Invalid request method %[method]!", @"prog", [OFApplication programName], @"method", method)]; [OFApplication terminateWithStatus: 1]; } @@ -387,15 +385,15 @@ - (void)setProxy: (OFString *)proxy { @try { size_t pos = [proxy rangeOfString: @":" - options: OF_STRING_SEARCH_BACKWARDS].location; + options: OFStringSearchBackwards].location; OFString *host; unsigned long long port; - if (pos == OF_NOT_FOUND) + if (pos == OFNotFound) @throw [OFInvalidFormatException exception]; host = [proxy substringToIndex: pos]; port = [proxy substringFromIndex: pos + 1] .unsignedLongLongValue; @@ -404,21 +402,21 @@ @throw [OFOutOfRangeException exception]; [OFTCPSocket setSOCKS5Host: host]; [OFTCPSocket setSOCKS5Port: (uint16_t)port]; } @catch (OFInvalidFormatException *e) { - [of_stderr writeLine: OF_LOCALIZED(@"invalid_input_proxy", + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_proxy", @"%[prog]: Proxy must to be in format host:port!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } } - (void)applicationDidFinishLaunching { OFString *outputPath; - const of_options_parser_option_t options[] = { + const OFOptionsParserOption options[] = { { 'b', @"body", 1, NULL, NULL }, { 'c', @"continue", 0, &_continue, NULL }, { 'f', @"force", 0, &_force, NULL }, { 'h', @"help", 0, NULL, NULL }, { 'H', @"header", 1, NULL, NULL }, @@ -431,11 +429,11 @@ { '\0', @"insecure", 0, &_insecure, NULL }, { '\0', @"ignore-status", 0, &_ignoreStatus, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser; - of_unichar_t option; + OFUnichar option; #ifdef OF_HAVE_SANDBOX OFSandbox *sandbox = [OFSandbox sandbox]; sandbox.allowsStdIO = true; sandbox.allowsReadingFiles = true; @@ -446,11 +444,11 @@ sandbox.allowsUserDatabaseReading = true; sandbox.allowsTTY = true; /* Dropped after parsing options */ sandbox.allowsUnveil = true; - [OFApplication activateSandbox: sandbox]; + [OFApplication of_activateSandbox: sandbox]; #endif #ifndef OF_AMIGAOS [OFLocale addLanguageDirectory: @LANGUAGE_DIR]; #else @@ -462,11 +460,11 @@ switch (option) { case 'b': [self setBody: optionsParser.argument]; break; case 'h': - help(of_stdout, true, 0); + help(OFStdOut, true, 0); break; case 'H': [self addHeader: optionsParser.argument]; break; case 'm': @@ -475,21 +473,21 @@ case 'P': [self setProxy: optionsParser.argument]; break; case ':': if (optionsParser.lastLongOption != nil) - [of_stderr writeLine: + [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]; - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"argument_missing", @"%[prog]: Argument for option -%[opt] " @"missing", @"prog", [OFApplication programName], @"opt", optStr)]; @@ -496,30 +494,30 @@ } [OFApplication terminateWithStatus: 1]; break; case '=': - [of_stderr writeLine: + [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) - [of_stderr writeLine: + [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]; - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @"opt", optStr)]; } @@ -528,46 +526,50 @@ break; } } #ifdef OF_HAVE_SANDBOX - [sandbox unveilPath: (outputPath != nil - ? outputPath : OF_PATH_CURRENT_DIRECTORY) - permissions: (_continue ? @"rwc" : @"wc")]; + if (outputPath != nil) + [sandbox unveilPath: outputPath + permissions: (_continue ? @"rwc" : @"wc")]; + else + [sandbox unveilPath: [[OFFileManager defaultManager] + currentDirectoryPath] + permissions: (_continue ? @"rwc" : @"wc")]; + /* In case we use ObjOpenSSL for https later */ - [sandbox unveilPath: @"/etc/ssl" - permissions: @"r"]; + [sandbox unveilPath: @"/etc/ssl" permissions: @"r"]; sandbox.allowsUnveil = false; - [OFApplication activateSandbox: sandbox]; + [OFApplication of_activateSandbox: sandbox]; #endif _outputPath = [outputPath copy]; _URLs = [optionsParser.remainingArguments copy]; if (_URLs.count < 1) - help(of_stderr, false, 1); + help(OFStdErr, false, 1); if (_quiet && _verbose) { - [of_stderr writeLine: OF_LOCALIZED(@"quiet_xor_verbose", + [OFStdErr writeLine: OF_LOCALIZED(@"quiet_xor_verbose", @"%[prog]: -q / --quiet and -v / --verbose are mutually " @"exclusive!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } if (_outputPath != nil && _detectFileName) { - [of_stderr writeLine: OF_LOCALIZED( + [OFStdErr writeLine: OF_LOCALIZED( @"output_xor_detect_filename", @"%[prog]: -o / --output and -O / --detect-filename are " @"mutually exclusive!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } if (_outputPath != nil && _URLs.count > 1) { - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"output_only_with_one_url", @"%[prog]: Cannot use -o / --output when more than one URL " @"has been specified!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; @@ -574,14 +576,13 @@ } if (_insecure) _HTTPClient.allowsInsecureRedirects = true; - _useUnicode = ([OFLocale encoding] == OF_STRING_ENCODING_UTF_8); + _useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8); - [self performSelector: @selector(downloadNextURL) - afterDelay: 0]; + [self performSelector: @selector(downloadNextURL) afterDelay: 0]; } - (void)client: (OFHTTPClient *)client didCreateSocket: (OFTCPSocket *)sock request: (OFHTTPRequest *)request @@ -596,16 +597,12 @@ request: (OFHTTPRequest *)request { /* TODO: Do asynchronously and print status */ while (!_body.atEndOfStream) { char buffer[4096]; - size_t length; - - length = [_body readIntoBuffer: buffer - length: 4096]; - [body writeBuffer: buffer - length: length]; + size_t length = [_body readIntoBuffer: buffer length: 4096]; + [body writeBuffer: buffer length: length]; } } - (bool)client: (OFHTTPClient *)client shouldFollowRedirect: (OFURL *)URL @@ -621,21 +618,20 @@ OFEnumerator *objectEnumerator = [headers objectEnumerator]; OFString *key, *object; while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) - [of_stdout writeFormat: @" %@: %@\n", - key, object]; + [OFStdOut writeFormat: @" %@: %@\n", key, object]; objc_autoreleasePoolPop(pool); } if (!_quiet) { if (_useUnicode) - [of_stdout writeFormat: @"☇ %@", URL.string]; + [OFStdOut writeFormat: @"☇ %@", URL.string]; else - [of_stdout writeFormat: @"< %@", URL.string]; + [OFStdOut writeFormat: @"< %@", URL.string]; } _length = 0; return true; @@ -653,17 +649,17 @@ [_progressBar draw]; [_progressBar release]; _progressBar = nil; if (!_quiet) { - [of_stdout writeString: @"\n "]; - [of_stdout writeLine: OF_LOCALIZED(@"download_error", + [OFStdOut writeString: @"\n "]; + [OFStdOut writeLine: OF_LOCALIZED(@"download_error", @"Error!")]; } URL = [_URLs objectAtIndex: _URLIndex - 1]; - [of_stderr writeLine: OF_LOCALIZED( + [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_exception", @"%[prog]: Failed to download <%[url]>!\n" @" %[exception]", @"prog", [OFApplication programName], @"url", URL, @@ -673,26 +669,24 @@ [self performSelector: @selector(downloadNextURL) afterDelay: 0]; return false; } - _received += length; + [_output writeBuffer: buffer length: length]; - [_output writeBuffer: buffer - length: length]; - + _received += length; [_progressBar setReceived: _received]; if (response.atEndOfStream) { [_progressBar stop]; [_progressBar draw]; [_progressBar release]; _progressBar = nil; if (!_quiet) { - [of_stdout writeString: @"\n "]; - [of_stdout writeLine: + [OFStdOut writeString: @"\n "]; + [OFStdOut writeLine: OF_LOCALIZED(@"download_done", @"Done!")]; } [self performSelector: @selector(downloadNextURL) afterDelay: 0]; @@ -714,13 +708,13 @@ OFString *lengthString = [headers objectForKey: @"Content-Length"]; OFString *type = [headers objectForKey: @"Content-Type"]; if (_useUnicode) - [of_stdout writeFormat: @" ➜ %hd\n", statusCode]; + [OFStdOut writeFormat: @" ➜ %hd\n", statusCode]; else - [of_stdout writeFormat: @" -> %hd\n", statusCode]; + [OFStdOut writeFormat: @" -> %hd\n", statusCode]; if (type == nil) type = OF_LOCALIZED(@"type_unknown", @"unknown"); if (lengthString != nil) { @@ -770,37 +764,37 @@ OFEnumerator OF_GENERIC(OFString *) *objectEnumerator = [headers objectEnumerator]; OFString *key, *object; if (statusCode / 100 == 2 && _currentFileName != nil) { - [of_stdout writeString: @" "]; - [of_stdout writeLine: OF_LOCALIZED( + [OFStdOut writeString: @" "]; + [OFStdOut writeLine: OF_LOCALIZED( @"info_name_unaligned", @"Name: %[name]", @"name", _currentFileName)]; } while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) - [of_stdout writeFormat: @" %@: %@\n", - key, object]; + [OFStdOut writeFormat: @" %@: %@\n", + key, object]; objc_autoreleasePoolPop(pool); } else if (statusCode / 100 == 2 && !_detectFileNameRequest) { - [of_stdout writeString: @" "]; + [OFStdOut writeString: @" "]; if (_currentFileName != nil) - [of_stdout writeLine: OF_LOCALIZED(@"info_name", + [OFStdOut writeLine: OF_LOCALIZED(@"info_name", @"Name: %[name]", @"name", _currentFileName)]; - [of_stdout writeString: @" "]; - [of_stdout writeLine: OF_LOCALIZED(@"info_type", + [OFStdOut writeString: @" "]; + [OFStdOut writeLine: OF_LOCALIZED(@"info_type", @"Type: %[type]", @"type", type)]; - [of_stdout writeString: @" "]; - [of_stdout writeLine: OF_LOCALIZED(@"info_size", + [OFStdOut writeString: @" "]; + [OFStdOut writeLine: OF_LOCALIZED(@"info_size", @"Size: %[size]", @"size", lengthString)]; } } } @@ -812,48 +806,48 @@ { if (exception != nil) { if ([exception isKindOfClass: [OFResolveHostFailedException class]]) { if (!_quiet) - [of_stdout writeString: @"\n"]; + [OFStdOut writeString: @"\n"]; - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"download_resolve_host_failed", @"%[prog]: Failed to download <%[url]>!\n" @" Failed to resolve host: %[exception]", @"prog", [OFApplication programName], @"url", request.URL.string, @"exception", exception)]; } else if ([exception isKindOfClass: [OFConnectionFailedException class]]) { if (!_quiet) - [of_stdout writeString: @"\n"]; + [OFStdOut writeString: @"\n"]; - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"download_failed_connection_failed", @"%[prog]: Failed to download <%[url]>!\n" @" Connection failed: %[exception]", @"prog", [OFApplication programName], @"url", request.URL.string, @"exception", exception)]; } else if ([exception isKindOfClass: [OFInvalidServerReplyException class]]) { if (!_quiet) - [of_stdout writeString: @"\n"]; + [OFStdOut writeString: @"\n"]; - [of_stderr writeLine: OF_LOCALIZED( + [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_invalid_server_reply", @"%[prog]: Failed to download <%[url]>!\n" @" Invalid server reply!", @"prog", [OFApplication programName], @"url", request.URL.string)]; } else if ([exception isKindOfClass: [OFUnsupportedProtocolException class]]) { if (!_quiet) - [of_stdout writeString: @"\n"]; + [OFStdOut writeString: @"\n"]; - [of_stderr writeLine: OF_LOCALIZED(@"no_ssl_library", + [OFStdErr writeLine: OF_LOCALIZED(@"no_ssl_library", @"%[prog]: No TLS library loaded!\n" @" In order to download via https, you need to " @"preload an TLS library for ObjFW\n" @" such as ObjOpenSSL!", @"prog", [OFApplication programName])]; @@ -862,11 +856,11 @@ OFString *error = OF_LOCALIZED( @"download_failed_read_or_write_failed_any", @"Read or write failed"); if (!_quiet) - [of_stdout writeString: @"\n"]; + [OFStdOut writeString: @"\n"]; if ([exception isKindOfClass: [OFReadFailedException class]]) error = OF_LOCALIZED( @"download_failed_read_or_write_failed_" @@ -877,11 +871,11 @@ error = OF_LOCALIZED( @"download_failed_read_or_write_failed_" @"write", @"Write failed"); - [of_stderr writeLine: OF_LOCALIZED( + [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_read_or_write_failed", @"%[prog]: Failed to download <%[url]>!\n" @" %[error]: %[exception]", @"prog", [OFApplication programName], @"url", request.URL.string, @@ -897,13 +891,12 @@ goto after_exception_handling; } statusCode = response.statusCode; codeString = [OFString stringWithFormat: @"%hd %@", - statusCode, - of_http_status_code_to_string(statusCode)]; - [of_stderr writeLine: OF_LOCALIZED(@"download_failed", + statusCode, OFHTTPStatusCodeString(statusCode)]; + [OFStdErr writeLine: OF_LOCALIZED(@"download_failed", @"%[prog]: Failed to download <%[url]>!\n" @" HTTP status code: %[code]", @"prog", [OFApplication programName], @"url", request.URL.string, @"code", codeString)]; @@ -915,11 +908,11 @@ afterDelay: 0]; return; } after_exception_handling: - if (_method == OF_HTTP_REQUEST_METHOD_HEAD) + if (_method == OFHTTPRequestMethodHead) goto next; if (_detectFileNameRequest) { _currentFileName = [fileNameFromContentDisposition( [response.headers objectForKey: @"Content-Disposition"]) @@ -933,15 +926,15 @@ afterDelay: 0]; return; } if ([_outputPath isEqual: @"-"]) - _output = of_stdout; + _output = [OFStdOut copy]; else { if (!_continue && !_force && [[OFFileManager defaultManager] fileExistsAtPath: _currentFileName]) { - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"output_already_exists", @"%[prog]: File %[filename] already exists!", @"prog", [OFApplication programName], @"filename", _currentFileName)]; @@ -953,11 +946,11 @@ OFString *mode = (response.statusCode == 206 ? @"a" : @"w"); _output = [[OFFile alloc] initWithPath: _currentFileName mode: mode]; } @catch (OFOpenItemFailedException *e) { - [of_stderr writeLine: + [OFStdErr writeLine: OF_LOCALIZED(@"failed_to_open_output", @"%[prog]: Failed to open file %[filename]: " @"%[exception]", @"prog", [OFApplication programName], @"filename", _currentFileName, @@ -979,20 +972,18 @@ [_currentFileName release]; _currentFileName = nil; response.delegate = self; - [response asyncReadIntoBuffer: _buffer - length: [OFSystemInfo pageSize]]; + [response asyncReadIntoBuffer: _buffer length: [OFSystemInfo pageSize]]; return; next: [_currentFileName release]; _currentFileName = nil; - [self performSelector: @selector(downloadNextURL) - afterDelay: 0]; + [self performSelector: @selector(downloadNextURL) afterDelay: 0]; } - (void)downloadNextURL { OFString *URLString = nil; @@ -1000,11 +991,11 @@ OFMutableDictionary *clientHeaders; OFHTTPRequest *request; _received = _length = _resumedFrom = 0; - if (_output != of_stdout) + if (_output != OFStdOut) [_output release]; _output = nil; if (_URLIndex >= _URLs.count) [OFApplication terminateWithStatus: _errorCode]; @@ -1011,21 +1002,21 @@ @try { URLString = [_URLs objectAtIndex: _URLIndex++]; URL = [OFURL URLWithString: URLString]; } @catch (OFInvalidFormatException *e) { - [of_stderr writeLine: OF_LOCALIZED(@"invalid_url", + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_url", @"%[prog]: Invalid URL: <%[url]>!", @"prog", [OFApplication programName], @"url", URLString)]; _errorCode = 1; goto next; } if (![URL.scheme isEqual: @"http"] && ![URL.scheme isEqual: @"https"]) { - [of_stderr writeLine: OF_LOCALIZED(@"invalid_scheme", + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_scheme", @"%[prog]: Invalid scheme: <%[url]>!", @"prog", [OFApplication programName], @"url", URLString)]; _errorCode = 1; @@ -1035,18 +1026,18 @@ clientHeaders = [[_clientHeaders mutableCopy] autorelease]; if (_detectFileName && !_detectedFileName) { if (!_quiet) { if (_useUnicode) - [of_stdout writeFormat: @"⠒ %@", URL.string]; + [OFStdOut writeFormat: @"⠒ %@", URL.string]; else - [of_stdout writeFormat: @"? %@", URL.string]; + [OFStdOut writeFormat: @"? %@", URL.string]; } request = [OFHTTPRequest requestWithURL: URL]; request.headers = clientHeaders; - request.method = OF_HTTP_REQUEST_METHOD_HEAD; + request.method = OFHTTPRequestMethodHead; _detectFileNameRequest = true; [_HTTPClient asyncPerformRequest: request]; return; } @@ -1061,10 +1052,18 @@ _currentFileName = [_outputPath copy]; if (_currentFileName == nil) _currentFileName = [URL.path.lastPathComponent copy]; + if ([_currentFileName isEqual: @"/"]) { + [_currentFileName release]; + _currentFileName = nil; + } + + if (_currentFileName == nil) + _currentFileName = @"unnamed"; + if (_continue) { @try { unsigned long long size = [[OFFileManager defaultManager] attributesOfItemAtPath: _currentFileName].fileSize; @@ -1075,21 +1074,20 @@ _resumedFrom = (unsigned long long)size; range = [OFString stringWithFormat: @"bytes=%jd-", _resumedFrom]; - [clientHeaders setObject: range - forKey: @"Range"]; + [clientHeaders setObject: range forKey: @"Range"]; } @catch (OFRetrieveItemAttributesFailedException *e) { } } if (!_quiet) { if (_useUnicode) - [of_stdout writeFormat: @"⇣ %@", URL.string]; + [OFStdOut writeFormat: @"⇣ %@", URL.string]; else - [of_stdout writeFormat: @"< %@", URL.string]; + [OFStdOut writeFormat: @"< %@", URL.string]; } request = [OFHTTPRequest requestWithURL: URL]; request.headers = clientHeaders; request.method = _method; @@ -1097,9 +1095,8 @@ _detectFileNameRequest = false; [_HTTPClient asyncPerformRequest: request]; return; next: - [self performSelector: @selector(downloadNextURL) - afterDelay: 0]; + [self performSelector: @selector(downloadNextURL) afterDelay: 0]; } @end