ObjFW  Check-in [83d8f3e5f6]

Overview
Comment:Rename of_http_*
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | new-naming-convention
Files: files | file ages | folders
SHA3-256: 83d8f3e5f6673abd73cfadee2de836c169231a8453a0cb06daf51587a9fb3874
User & Date: js on 2021-04-17 14:33:49
Other Links: branch diff | manifest | tags
Context
2021-04-17
14:36
of_file_handle_t -> OFFileHandle check-in: 94ebfb3671 user: js tags: new-naming-convention
14:33
Rename of_http_* check-in: 83d8f3e5f6 user: js tags: new-naming-convention
14:24
of_plugin_handle_t -> OFPluginHandle check-in: cedc0cb75e user: js tags: new-naming-convention
Changes

Modified src/OFHTTPClient.m from [91e757df2d] to [7a0dc4013e].

112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+















-
+







			 redirects: (unsigned int)redirects;
@end

static OFString *
constructRequestString(OFHTTPRequest *request)
{
	void *pool = objc_autoreleasePoolPush();
	of_http_request_method_t method = request.method;
	OFHTTPRequestMethod method = request.method;
	OFURL *URL = request.URL;
	OFString *path;
	OFString *user = URL.user, *password = URL.password;
	OFMutableString *requestString;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	bool hasContentLength, chunked;
	OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator;
	OFString *key, *object;

	if (URL.path != nil)
		path = URL.URLEncodedPath;
	else
		path = @"/";

	requestString = [OFMutableString stringWithFormat:
	    @"%s %@", of_http_request_method_to_string(method), path];
	    @"%s %@", OFHTTPRequestMethodName(method), path];

	if (URL.query != nil) {
		[requestString appendString: @"?"];
		[requestString appendString: URL.URLEncodedQuery];
	}

	[requestString appendString: @" HTTP/"];
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248


249
250
251
252
253
254
255
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246


247
248
249
250
251
252
253
254
255







-
+








-
-
+
+








		firstLetter = false;
		str++;
	}
}

static bool
defaultShouldFollow(of_http_request_method_t method, short statusCode)
defaultShouldFollow(OFHTTPRequestMethod method, short statusCode)
{
	bool follow;

	/*
	 * 301, 302 and 307 should only redirect with user confirmation if the
	 * request method is not GET or HEAD. Asking the delegate and getting
	 * true returned is considered user confirmation.
	 */
	if (method == OF_HTTP_REQUEST_METHOD_GET ||
	    method == OF_HTTP_REQUEST_METHOD_HEAD)
	if (method == OFHTTPRequestMethodGet ||
	    method == OFHTTPRequestMethodHead)
		follow = true;
	/* 303 should always be redirected and converted to a GET request. */
	else if (statusCode == 303)
		follow = true;
	else
		follow = false;

328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342







-
+








	if (keepAlive) {
		response.of_keepAlive = true;

		_client->_socket = [sock retain];
		_client->_lastURL = [URL copy];
		_client->_lastWasHEAD =
		    (_request.method == OF_HTTP_REQUEST_METHOD_HEAD);
		    (_request.method == OFHTTPRequestMethodHead);
		_client->_lastResponse = [response retain];
	}

	if (_redirects > 0 && (_status == 301 || _status == 302 ||
	    _status == 303 || _status == 307) &&
	    (location = [_serverHeaders objectForKey: @"Location"]) != nil) {
		bool follow = true;
397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411







-
+







				    (object = [objectEnumerator nextObject]) !=
				    nil)
					if ([key hasPrefix: @"Content-"] ||
					    [key hasPrefix: @"Transfer-"])
						[newHeaders
						    removeObjectForKey: key];

				newRequest.method = OF_HTTP_REQUEST_METHOD_GET;
				newRequest.method = OFHTTPRequestMethodGet;
			}

			newRequest.URL = newURL;
			newRequest.headers = newHeaders;

			_client->_inProgress = false;

Modified src/OFHTTPRequest.h from [9c2534e693] to [c2fc6a197c].

26
27
28
29
30
31
32
33

34
35

36
37

38
39

40
41

42
43

44
45

46
47

48
49
50


51
52
53
54

55
56
57
58

59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
26
27
28
29
30
31
32

33
34

35
36

37
38

39
40

41
42

43
44

45
46

47
48


49
50
51
52


53
54
55
56

57
58
59
60
61
62

63

64
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
+
+


-
-
+



-
+





-
+
-









-
-
+
+














-
+









-
+







@class OFString;

/** @file */

/**
 * @brief The type of an HTTP request.
 */
typedef enum {
typedef enum OFHTTPRequestMethod {
	/** OPTIONS */
	OF_HTTP_REQUEST_METHOD_OPTIONS,
	OFHTTPRequestMethodOptions,
	/** GET */
	OF_HTTP_REQUEST_METHOD_GET,
	OFHTTPRequestMethodGet,
	/** HEAD */
	OF_HTTP_REQUEST_METHOD_HEAD,
	OFHTTPRequestMethodHead,
	/** POST */
	OF_HTTP_REQUEST_METHOD_POST,
	OFHTTPRequestMethodPost,
	/** PUT */
	OF_HTTP_REQUEST_METHOD_PUT,
	OFHTTPRequestMethodPut,
	/** DELETE */
	OF_HTTP_REQUEST_METHOD_DELETE,
	OFHTTPRequestMethodDelete,
	/** TRACE */
	OF_HTTP_REQUEST_METHOD_TRACE,
	OFHTTPRequestMethodTrace,
	/** CONNECT */
	OF_HTTP_REQUEST_METHOD_CONNECT
} of_http_request_method_t;
	OFHTTPRequestMethodConnect
} OFHTTPRequestMethod;

/**
 * @struct of_http_request_protocol_version_t \
 *	   OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 * @struct OFHTTPRequestProtocolVersion OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief The HTTP version of the HTTP request.
 */
struct OF_BOXABLE of_http_request_protocol_version_t {
struct OF_BOXABLE OFHTTPRequestProtocolVersion {
	/** The major of the HTTP version */
	unsigned char major;
	/** The minor of the HTTP version */
	unsigned char minor;
};
typedef struct of_http_request_protocol_version_t
typedef struct OFHTTPRequestProtocolVersion OFHTTPRequestProtocolVersion;
    of_http_request_protocol_version_t;

/**
 * @class OFHTTPRequest OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief A class for storing HTTP requests.
 */
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFURL *_URL;
	of_http_request_method_t _method;
	of_http_request_protocol_version_t _protocolVersion;
	OFHTTPRequestMethod _method;
	OFHTTPRequestProtocolVersion _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers;
	OFSocketAddress _remoteAddress;
	bool _hasRemoteAddress;
	OF_RESERVE_IVARS(OFHTTPRequest, 4)
}

/**
 * @brief The URL of the HTTP request.
 */
@property (copy, nonatomic) OFURL *URL;

/**
 * @brief The protocol version of the HTTP request.
 */
@property (nonatomic) of_http_request_protocol_version_t protocolVersion;
@property (nonatomic) OFHTTPRequestProtocolVersion protocolVersion;

/**
 * @brief The protocol version of the HTTP request as a string.
 */
@property (copy, nonatomic) OFString *protocolVersionString;

/**
 * @brief The request method of the HTTP request.
 */
@property (nonatomic) of_http_request_method_t method;
@property (nonatomic) OFHTTPRequestMethod method;

/**
 * @brief The headers for the HTTP request.
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic)
    OFDictionary OF_GENERIC(OFString *, OFString *) *headers;

142
143
144
145
146
147
148
149
150


151
152
153
154
155
156
157
158
159

160
161
162
163
164
140
141
142
143
144
145
146


147
148
149
150
151
152
153
154
155


156
157
158
159
160
161







-
-
+
+







-
-
+





#endif
/**
 * @brief Returns a C string describing the specified request method.
 *
 * @param method The request method which should be described as a C string
 * @return A C string describing the specified request method
 */
extern const char *_Nullable of_http_request_method_to_string(
    of_http_request_method_t method);
extern const char *_Nullable OFHTTPRequestMethodName(
    OFHTTPRequestMethod method);

/**
 * @brief Returns the request method for the specified string.
 *
 * @param string The string for which the request method should be returned
 * @return The request method for the specified string
 */
extern of_http_request_method_t of_http_request_method_from_string(
    OFString *string);
extern OFHTTPRequestMethod OFHTTPRequestMethodParseName(OFString *string);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFHTTPRequest.m from [46acd12d86] to [ef85fc1d98].

26
27
28
29
30
31
32
33

34
35
36

37
38

39
40

41
42

43
44

45
46

47
48

49
50

51
52
53
54
55
56
57
58


59
60
61

62
63

64
65

66
67

68
69

70
71

72
73

74
75

76
77
78
79
80
81
82
26
27
28
29
30
31
32

33
34
35

36
37

38
39

40
41

42
43

44
45

46
47

48
49

50
51
52
53
54
55
56


57
58
59
60

61
62

63
64

65
66

67
68

69
70

71
72

73
74

75
76
77
78
79
80
81
82







-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+






-
-
+
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+








#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"
#import "OFUnsupportedVersionException.h"

const char *
of_http_request_method_to_string(of_http_request_method_t method)
OFHTTPRequestMethodName(OFHTTPRequestMethod method)
{
	switch (method) {
	case OF_HTTP_REQUEST_METHOD_OPTIONS:
	case OFHTTPRequestMethodOptions:
		return "OPTIONS";
	case OF_HTTP_REQUEST_METHOD_GET:
	case OFHTTPRequestMethodGet:
		return "GET";
	case OF_HTTP_REQUEST_METHOD_HEAD:
	case OFHTTPRequestMethodHead:
		return "HEAD";
	case OF_HTTP_REQUEST_METHOD_POST:
	case OFHTTPRequestMethodPost:
		return "POST";
	case OF_HTTP_REQUEST_METHOD_PUT:
	case OFHTTPRequestMethodPut:
		return "PUT";
	case OF_HTTP_REQUEST_METHOD_DELETE:
	case OFHTTPRequestMethodDelete:
		return "DELETE";
	case OF_HTTP_REQUEST_METHOD_TRACE:
	case OFHTTPRequestMethodTrace:
		return "TRACE";
	case OF_HTTP_REQUEST_METHOD_CONNECT:
	case OFHTTPRequestMethodConnect:
		return "CONNECT";
	}

	return NULL;
}

of_http_request_method_t
of_http_request_method_from_string(OFString *string)
OFHTTPRequestMethod
OFHTTPRequestMethodParseName(OFString *string)
{
	if ([string isEqual: @"OPTIONS"])
		return OF_HTTP_REQUEST_METHOD_OPTIONS;
		return OFHTTPRequestMethodOptions;
	if ([string isEqual: @"GET"])
		return OF_HTTP_REQUEST_METHOD_GET;
		return OFHTTPRequestMethodGet;
	if ([string isEqual: @"HEAD"])
		return OF_HTTP_REQUEST_METHOD_HEAD;
		return OFHTTPRequestMethodHead;
	if ([string isEqual: @"POST"])
		return OF_HTTP_REQUEST_METHOD_POST;
		return OFHTTPRequestMethodPost;
	if ([string isEqual: @"PUT"])
		return OF_HTTP_REQUEST_METHOD_PUT;
		return OFHTTPRequestMethodPut;
	if ([string isEqual: @"DELETE"])
		return OF_HTTP_REQUEST_METHOD_DELETE;
		return OFHTTPRequestMethodDelete;
	if ([string isEqual: @"TRACE"])
		return OF_HTTP_REQUEST_METHOD_TRACE;
		return OFHTTPRequestMethodTrace;
	if ([string isEqual: @"CONNECT"])
		return OF_HTTP_REQUEST_METHOD_CONNECT;
		return OFHTTPRequestMethodConnect;

	@throw [OFInvalidArgumentException exception];
}

@implementation OFHTTPRequest
@synthesize URL = _URL, method = _method, headers = _headers;

90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







	return [[[self alloc] initWithURL: URL] autorelease];
}

- (instancetype)init
{
	self = [super init];

	_method = OF_HTTP_REQUEST_METHOD_GET;
	_method = OFHTTPRequestMethodGet;
	_protocolVersion.major = 1;
	_protocolVersion.minor = 1;

	return self;
}

- (instancetype)initWithURL: (OFURL *)URL
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







-
+










-
+









-
+







		OF_HASH_ADD_HASH(hash, OFSocketAddressHash(&_remoteAddress));

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (void)setProtocolVersion: (of_http_request_protocol_version_t)protocolVersion
- (void)setProtocolVersion: (OFHTTPRequestProtocolVersion)protocolVersion
{
	if (protocolVersion.major != 1 || protocolVersion.minor > 1)
		@throw [OFUnsupportedVersionException exceptionWithVersion:
		    [OFString stringWithFormat: @"%hhu.%hhu",
						protocolVersion.major,
						protocolVersion.minor]];

	_protocolVersion = protocolVersion;
}

- (of_http_request_protocol_version_t)protocolVersion
- (OFHTTPRequestProtocolVersion)protocolVersion
{
	return _protocolVersion;
}

- (void)setProtocolVersionString: (OFString *)string
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *components = [string componentsSeparatedByString: @"."];
	unsigned long long major, minor;
	of_http_request_protocol_version_t protocolVersion;
	OFHTTPRequestProtocolVersion protocolVersion;

	if (components.count != 2)
		@throw [OFInvalidFormatException exception];

	major = [components.firstObject unsignedLongLongValue];
	minor = [components.lastObject unsignedLongLongValue];

248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262







-
+







					   _protocolVersion.major,
					   _protocolVersion.minor];
}

- (OFString *)description
{
	void *pool = objc_autoreleasePoolPush();
	const char *method = of_http_request_method_to_string(_method);
	const char *method = OFHTTPRequestMethodName(_method);
	OFString *indentedHeaders, *remoteAddress, *ret;

	indentedHeaders = [_headers.description
	    stringByReplacingOccurrencesOfString: @"\n"
				      withString: @"\n\t"];

	if (_hasRemoteAddress)

Modified src/OFHTTPResponse.h from [ab5c38416c] to [a9e1fde80c].

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+








-
+







/**
 * @class OFHTTPResponse OFHTTPResponse.h ObjFW/OFHTTPResponse.h
 *
 * @brief A class for representing an HTTP request reply as a stream.
 */
@interface OFHTTPResponse: OFStream
{
	of_http_request_protocol_version_t _protocolVersion;
	OFHTTPRequestProtocolVersion _protocolVersion;
	short _statusCode;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_headers;
	OF_RESERVE_IVARS(OFHTTPResponse, 4)
}

/**
 * @brief The protocol version of the HTTP request reply.
 */
@property (nonatomic) of_http_request_protocol_version_t protocolVersion;
@property (nonatomic) OFHTTPRequestProtocolVersion protocolVersion;

/**
 * @brief The protocol version of the HTTP request reply as a string.
 */
@property (copy, nonatomic) OFString *protocolVersionString;

/**
74
75
76
77
78
79
80
81

82
83
84
85
86
74
75
76
77
78
79
80

81
82
83
84
85
86







-
+





#endif
/**
 * @brief Returns a description string for the specified HTTP status code.
 *
 * @param code The HTTP status code to return a description string for
 * @return A description string for the specified HTTP status code
 */
extern OFString *_Nonnull of_http_status_code_to_string(short code);
extern OFString *_Nonnull OFHTTPStatusCodeString(short code);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFHTTPResponse.m from [94b8fa5885] to [a079a8cd2f].

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedVersionException.h"

OFString *
of_http_status_code_to_string(short code)
OFHTTPStatusCodeString(short code)
{
	switch (code) {
	case 100:
		return @"Continue";
	case 101:
		return @"Switching Protocols";
	case 200:
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280







-
+










-
+









-
+







- (void)dealloc
{
	[_headers release];

	[super dealloc];
}

- (void)setProtocolVersion: (of_http_request_protocol_version_t)protocolVersion
- (void)setProtocolVersion: (OFHTTPRequestProtocolVersion)protocolVersion
{
	if (protocolVersion.major != 1 || protocolVersion.minor > 1)
		@throw [OFUnsupportedVersionException exceptionWithVersion:
		    [OFString stringWithFormat: @"%hhu.%hhu",
						protocolVersion.major,
						protocolVersion.minor]];

	_protocolVersion = protocolVersion;
}

- (of_http_request_protocol_version_t)protocolVersion
- (OFHTTPRequestProtocolVersion)protocolVersion
{
	return _protocolVersion;
}

- (void)setProtocolVersionString: (OFString *)string
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *components = [string componentsSeparatedByString: @"."];
	unsigned long long major, minor;
	of_http_request_protocol_version_t protocolVersion;
	OFHTTPRequestProtocolVersion protocolVersion;

	if (components.count != 2)
		@throw [OFInvalidFormatException exception];

	major = [components.firstObject unsignedLongLongValue];
	minor = [components.lastObject unsignedLongLongValue];

Modified src/OFHTTPServer.m from [c6a414493d] to [eb0e97662f].

78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







	OFTimer *_timer;
	enum {
		AWAITING_PROLOG,
		PARSING_HEADERS,
		SEND_RESPONSE
	} _state;
	uint8_t _HTTPMinorVersion;
	of_http_request_method_t _method;
	OFHTTPRequestMethod _method;
	OFString *_host, *_path;
	uint16_t _port;
	OFMutableDictionary *_headers;
	size_t _contentLength;
	OFStream *_requestBody;
}

185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199







-
+







	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	OFEnumerator *keyEnumerator, *valueEnumerator;
	OFString *key, *value;

	[_socket writeFormat: @"HTTP/%@ %hd %@\r\n",
			      self.protocolVersionString, _statusCode,
			      of_http_status_code_to_string(_statusCode)];
			      OFHTTPStatusCodeString(_statusCode)];

	headers = [[_headers mutableCopy] autorelease];

	if ([headers objectForKey: @"Date"] == nil) {
		OFString *date = [[OFDate date]
		    dateStringWithFormat: @"%a, %d %b %Y %H:%M:%S GMT"];
		[headers setObject: date forKey: @"Date"];
371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+








	pos = [line rangeOfString: @" "].location;
	if (pos == OFNotFound)
		return [self sendErrorAndClose: 400];

	method = [line substringToIndex: pos];
	@try {
		_method = of_http_request_method_from_string(method);
		_method = OFHTTPRequestMethodParseName(method);
	} @catch (OFInvalidArgumentException *e) {
		return [self sendErrorAndClose: 405];
	}

	@try {
		OFRange range = OFRangeMake(pos + 1, line.length - pos - 10);

495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510
495
496
497
498
499
500
501

502

503
504
505
506
507
508
509







-
+
-







{
	OFString *date = [[OFDate date]
	    dateStringWithFormat: @"%a, %d %b %Y %H:%M:%S GMT"];
	[_socket writeFormat: @"HTTP/1.1 %hd %@\r\n"
			      @"Date: %@\r\n"
			      @"Server: %@\r\n"
			      @"\r\n",
			      statusCode,
			      statusCode, OFHTTPStatusCodeString(statusCode),
			      of_http_status_code_to_string(statusCode),
			      date, _server.name];
	return false;
}

- (void)createResponse
{
	void *pool = objc_autoreleasePoolPush();
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559







-
+







		URL.URLEncodedPath = _path;

	[URL makeImmutable];

	request = [OFHTTPRequest requestWithURL: URL];
	request.method = _method;
	request.protocolVersion =
	    (of_http_request_protocol_version_t){ 1, _HTTPMinorVersion };
	    (OFHTTPRequestProtocolVersion){ 1, _HTTPMinorVersion };
	request.headers = _headers;
	request.remoteAddress = _socket.remoteAddress;

	response = [[[OFHTTPServerResponse alloc]
	    initWithSocket: _socket
		    server: _server
		   request: request] autorelease];

Modified src/exceptions/OFHTTPRequestFailedException.m from [5d6244b48f] to [e96bd6a5f5].

57
58
59
60
61
62
63
64

65
66
67
68
69
70
57
58
59
60
61
62
63

64
65
66
67
68
69
70







-
+






	[_response release];

	[super dealloc];
}

- (OFString *)description
{
	const char *method = of_http_request_method_to_string(_request.method);
	const char *method = OFHTTPRequestMethodName(_request.method);

	return [OFString stringWithFormat:
	    @"An HTTP %s request with URL %@ failed with code %hd!", method,
	    _request.URL, _response.statusCode];
}
@end

Modified utils/ofhttp/OFHTTP.m from [88b7d0694f] to [83d4f96412].

62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76







-
+







	size_t _URLIndex;
	int _errorCode;
	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;
	ProgressBar *_progressBar;
}
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304







-
+







#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;
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380







-
+







- (void)setMethod: (OFString *)method
{
	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",
		    @"%[prog]: Invalid request method %[method]!",
		    @"prog", [OFApplication programName],
		    @"method", method)];
		[OFApplication terminateWithStatus: 1];
	}
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
884
885
886
887
888
889
890

891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915







-
+
-
















-
+







			if (_ignoreStatus) {
				exception = nil;
				goto after_exception_handling;
			}

			statusCode = response.statusCode;
			codeString = [OFString stringWithFormat: @"%hd %@",
			    statusCode,
			    statusCode, OFHTTPStatusCodeString(statusCode)];
			    of_http_status_code_to_string(statusCode)];
			[of_stderr writeLine: OF_LOCALIZED(@"download_failed",
			    @"%[prog]: Failed to download <%[url]>!\n"
			    @"  HTTP status code: %[code]",
			    @"prog", [OFApplication programName],
			    @"url", request.URL.string,
			    @"code", codeString)];
		} else
			@throw exception;

		_errorCode = 1;
		[self performSelector: @selector(downloadNextURL)
			   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"])
		    copy];
		_detectedFileName = true;
1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040







-
+







				[of_stdout writeFormat: @"⠒ %@", URL.string];
			else
				[of_stdout 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;
	}

	if (!_detectedFileName) {