Index: src/OFHTTPResponse.h ================================================================== --- src/OFHTTPResponse.h +++ src/OFHTTPResponse.h @@ -68,7 +68,15 @@ * * @return The reply as a string */ - (OFString *)stringWithEncoding: (of_string_encoding_t)encoding; @end + +#ifdef __cplusplus +extern "C" { +#endif +extern OFString *_Nonnull of_http_status_code_to_string(short code); +#ifdef __cplusplus +} +#endif OF_ASSUME_NONNULL_END Index: src/OFHTTPResponse.m ================================================================== --- src/OFHTTPResponse.m +++ src/OFHTTPResponse.m @@ -26,10 +26,99 @@ #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedVersionException.h" + +OFString * +of_http_status_code_to_string(short code) +{ + switch (code) { + case 100: + return @"Continue"; + case 101: + return @"Switching Protocols"; + case 200: + return @"OK"; + case 201: + return @"Created"; + case 202: + return @"Accepted"; + case 203: + return @"Non-Authoritative Information"; + case 204: + return @"No Content"; + case 205: + return @"Reset Content"; + case 206: + return @"Partial Content"; + case 300: + return @"Multiple Choices"; + case 301: + return @"Moved Permanently"; + case 302: + return @"Found"; + case 303: + return @"See Other"; + case 304: + return @"Not Modified"; + case 305: + return @"Use Proxy"; + case 307: + return @"Temporary Redirect"; + case 400: + return @"Bad Request"; + case 401: + return @"Unauthorized"; + case 402: + return @"Payment Required"; + case 403: + return @"Forbidden"; + case 404: + return @"Not Found"; + case 405: + return @"Method Not Allowed"; + case 406: + return @"Not Acceptable"; + case 407: + return @"Proxy Authentication Required"; + case 408: + return @"Request Timeout"; + case 409: + return @"Conflict"; + case 410: + return @"Gone"; + case 411: + return @"Length Required"; + case 412: + return @"Precondition Failed"; + case 413: + return @"Request Entity Too Large"; + case 414: + return @"Request-URI Too Long"; + case 415: + return @"Unsupported Media Type"; + case 416: + return @"Requested Range Not Satisfiable"; + case 417: + return @"Expectation Failed"; + case 500: + return @"Internal Server Error"; + case 501: + return @"Not Implemented"; + case 502: + return @"Bad Gateway"; + case 503: + return @"Service Unavailable"; + case 504: + return @"Gateway Timeout"; + case 505: + return @"HTTP Version Not Supported"; + default: + return @"(unknown)"; + } +} static of_string_encoding_t encodingForContentType(OFString *contentType) { const char *UTF8String = contentType.UTF8String; Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -111,99 +111,10 @@ @interface OFHTTPServerThread: OFThread - (void)stop; @end #endif -static const char * -statusCodeToString(short code) -{ - switch (code) { - case 100: - return "Continue"; - case 101: - return "Switching Protocols"; - case 200: - return "OK"; - case 201: - return "Created"; - case 202: - return "Accepted"; - case 203: - return "Non-Authoritative Information"; - case 204: - return "No Content"; - case 205: - return "Reset Content"; - case 206: - return "Partial Content"; - case 300: - return "Multiple Choices"; - case 301: - return "Moved Permanently"; - case 302: - return "Found"; - case 303: - return "See Other"; - case 304: - return "Not Modified"; - case 305: - return "Use Proxy"; - case 307: - return "Temporary Redirect"; - case 400: - return "Bad Request"; - case 401: - return "Unauthorized"; - case 402: - return "Payment Required"; - case 403: - return "Forbidden"; - case 404: - return "Not Found"; - case 405: - return "Method Not Allowed"; - case 406: - return "Not Acceptable"; - case 407: - return "Proxy Authentication Required"; - case 408: - return "Request Timeout"; - case 409: - return "Conflict"; - case 410: - return "Gone"; - case 411: - return "Length Required"; - case 412: - return "Precondition Failed"; - case 413: - return "Request Entity Too Large"; - case 414: - return "Request-URI Too Long"; - case 415: - return "Unsupported Media Type"; - case 416: - return "Requested Range Not Satisfiable"; - case 417: - return "Expectation Failed"; - case 500: - return "Internal Server Error"; - case 501: - return "Not Implemented"; - case 502: - return "Bad Gateway"; - case 503: - return "Service Unavailable"; - case 504: - return "Gateway Timeout"; - case 505: - return "HTTP Version Not Supported"; - default: - return NULL; - } -} - static OF_INLINE OFString * normalizedKey(OFString *key) { char *cString = of_strdup(key.UTF8String); unsigned char *tmp = (unsigned char *)cString; @@ -263,13 +174,13 @@ void *pool = objc_autoreleasePoolPush(); OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers; OFEnumerator *keyEnumerator, *valueEnumerator; OFString *key, *value; - [_socket writeFormat: @"HTTP/%@ %d %s\r\n", + [_socket writeFormat: @"HTTP/%@ %d %@\r\n", self.protocolVersionString, _statusCode, - statusCodeToString(_statusCode)]; + of_http_status_code_to_string(_statusCode)]; headers = [[_headers mutableCopy] autorelease]; if ([headers objectForKey: @"Date"] == nil) { OFString *date = [[OFDate date] @@ -582,15 +493,16 @@ - (bool)sendErrorAndClose: (short)statusCode { OFString *date = [[OFDate date] dateStringWithFormat: @"%a, %d %b %Y %H:%M:%S GMT"]; - [_socket writeFormat: @"HTTP/1.1 %d %s\r\n" + [_socket writeFormat: @"HTTP/1.1 %d %@\r\n" @"Date: %@\r\n" @"Server: %@\r\n" @"\r\n", - statusCode, statusCodeToString(statusCode), + statusCode, + of_http_status_code_to_string(statusCode), date, _server.name]; return false; } Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -680,14 +680,19 @@ @"prog", [OFApplication programName], @"url", request.URL.string, @"error", error, @"exception", e)]; } else if ([e isKindOfClass: [OFHTTPRequestFailedException class]]) { + short statusCode = [[e response] statusCode]; + OFString *codeString = [OFString stringWithFormat: @"%d %@", + statusCode, of_http_status_code_to_string(statusCode)]; [of_stderr writeLine: OF_LOCALIZED(@"download_failed", - @"%[prog]: Failed to download <%[url]>!", + @"%[prog]: Failed to download <%[url]>!\n" + @" HTTP status code: %[code]", @"prog", [OFApplication programName], - @"url", request.URL.string)]; + @"url", request.URL.string, + @"code", codeString)]; } else @throw e; _errorCode = 1; [self performSelector: @selector(downloadNextURL) @@ -711,11 +716,12 @@ [of_stdout writeString: @"\n Error!\n"]; URL = [_URLs objectAtIndex: _URLIndex - 1]; [of_stderr writeLine: OF_LOCALIZED( @"download_failed_exception", - @"%[prog]: Failed to download <%[url]>: %[exception]", + @"%[prog]: Failed to download <%[url]>!\n" + @" %[exception]", @"prog", [OFApplication programName], @"url", URL, @"exception", exception)]; _errorCode = 1; Index: utils/ofhttp/lang/de.json ================================================================== --- utils/ofhttp/lang/de.json +++ utils/ofhttp/lang/de.json @@ -61,13 +61,17 @@ "download_failed_read_or_write_failed_write": "Schreiben", "download_failed_read_or_write_failed": [ "%[prog]: Fehler beim Download von <%[url]>!\n", " %[error]: %[exception]" ], - "download_failed": "%[prog]: Fehler beim Download von <%[url]>!", + "download_failed": [ + "%[prog]: Fehler beim Download von <%[url]>!\n", + " HTTP Status-Code: %[code]" + ], "download_failed_exception": [ - "%[prog]: Fehler beim Download von <%[url]>: %[exception]" + "%[prog]: Fehler beim Download von <%[url]>!\n", + " %[exception]" ], "download_done": "Fertig!", "invalid_url": "%[prog]: Ungültige URL: <%[url]>!", "invalid_scheme": "%[prog]: Ungültiges Schema: <%[url]>!", "type_unknown": "unbekannt",