ObjFW  Check-in [d2487bc7e1]

Overview
Comment:OFURL: Don't include the leading "/" in path

While Cocoa includes it, RFC 1738 explicitly states that the "/" between
host / port and path is not part of the path.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d2487bc7e1277800c127e8601e6510d7aefaf32186a8b6e5b75b98af993b77c6
User & Date: js on 2014-07-07 00:50:01
Other Links: manifest | tags
Context
2014-07-07
22:05
Add OFUnknownXMLEntityException check-in: 6e5a920567 user: js tags: trunk
00:50
OFURL: Don't include the leading "/" in path check-in: d2487bc7e1 user: js tags: trunk
2014-07-06
11:04
OFString+*.m: Add a few missing autorelease pools check-in: b5c8b62533 user: js tags: trunk
Changes

Modified src/OFHTTPClient.m from [d38e8f0fed] to [ab4c72054a].

324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338







-
+







	of_http_request_method_t method = [request method];
	OFMutableString *requestString;
	OFString *user, *password;
	OFDictionary *headers = [request headers];
	OFDataArray *entity = [request entity];
	OFTCPSocket *socket;
	OFHTTPClientResponse *response;
	OFString *line, *path, *version, *redirect, *keepAlive;
	OFString *line, *version, *redirect, *keepAlive;
	OFMutableDictionary *serverHeaders;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFString *key, *object;
	int status;

	if (![scheme isEqual: @"http"] && ![scheme isEqual: @"https"])
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380



381
382
383
384


385
386
387
388
389
390
391
361
362
363
364
365
366
367



368
369
370
371
372
373
374



375
376
377
378
379


380
381
382
383
384
385
386
387
388







-
-
-







-
-
-
+
+
+


-
-
+
+







		}

		[_lastResponse release];
		_lastResponse = nil;
	} else
		socket = [self OF_createSocketForRequest: request];

	if ([(path = [URL path]) length] == 0)
		path = @"/";

	/*
	 * As a work around for a bug with split packets in lighttpd when using
	 * HTTPS, we construct the complete request in a buffer string and then
	 * send it all at once.
	 */
	if ([URL query] != nil)
		requestString = [OFMutableString stringWithFormat:
		    @"%s %@?%@ HTTP/%@\r\n",
		    of_http_request_method_to_string(method), path, [URL query],
		    [request protocolVersionString]];
		    @"%s /%@?%@ HTTP/%@\r\n",
		    of_http_request_method_to_string(method), [URL path],
		    [URL query], [request protocolVersionString]];
	else
		requestString = [OFMutableString stringWithFormat:
		    @"%s %@ HTTP/%@\r\n",
		    of_http_request_method_to_string(method), path,
		    @"%s /%@ HTTP/%@\r\n",
		    of_http_request_method_to_string(method), [URL path],
		    [request protocolVersionString]];

	if ([URL port] == 80)
		[requestString appendFormat: @"Host: %@\r\n", [URL host]];
	else
		[requestString appendFormat: @"Host: %@:%d\r\n", [URL host],
		    [URL port]];

Modified src/OFHTTPServer.m from [79b7aacf76] to [3efdaebeee].

381
382
383
384
385
386
387

388
389
390
391
392
393
394
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395







+








	abort();
}

- (bool)parseProlog: (OFString*)line
{
	OFString *method;
	OFMutableString *path;
	size_t pos;

	@try {
		OFString *version = [line
		    substringWithRange: of_range([line length] - 9, 9)];
		of_unichar_t tmp;

413
414
415
416
417
418
419


420
421


422
423
424

425

426
427

428
429



430

431
432
433
434
435
436
437
414
415
416
417
418
419
420
421
422


423
424
425
426
427
428

429
430

431
432
433
434
435
436
437
438
439
440
441
442
443
444
445







+
+
-
-
+
+



+
-
+

-
+


+
+
+

+







		_method = of_http_request_method_from_string(
		    [method UTF8String]);
	} @catch (OFInvalidFormatException *e) {
		return [self sendErrorAndClose: 405];
	}

	@try {
		of_range_t range = of_range(pos + 1, [line length] - pos - 10);

		_path = [line substringWithRange:
		    of_range(pos + 1, [line length] - pos - 10)];
		path = [[[line substringWithRange:
		    range] mutableCopy] autorelease];
	} @catch (OFOutOfRangeException *e) {
		return [self sendErrorAndClose: 400];
	}

	_path = [[_path stringByDeletingEnclosingWhitespaces] retain];
	[path deleteEnclosingWhitespaces];

	if (![_path hasPrefix: @"/"])
	if (![path hasPrefix: @"/"])
		return [self sendErrorAndClose: 400];

	[path deleteCharactersInRange: of_range(0, 1)];
	[path makeImmutable];

	_headers = [[OFMutableDictionary alloc] init];
	_path = [path copy];
	_state = PARSING_HEADERS;

	return true;
}

- (bool)parseHeaders: (OFString*)line
{

Modified src/OFURL.m from [bcc6187243] to [2209074f5b].

154
155
156
157
158
159
160
161
162


163
164

165
166
167
168
169
170
171
154
155
156
157
158
159
160


161
162


163
164
165
166
167
168
169
170







-
-
+
+
-
-
+







			if ((tmp = strchr(UTF8String, ';')) != NULL) {
				*tmp = '\0';

				_parameters = [[OFString alloc]
				    initWithUTF8String: tmp + 1];
			}

			_path = [[OFString alloc] initWithFormat: @"/%s",
								  UTF8String];
			_path = [[OFString alloc]
			    initWithUTF8String: UTF8String];
		} else
			_path = @"";
		}
	} @catch (id e) {
		[self release];
		@throw e;
	} @finally {
		free(UTF8String2);
	}

213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226







-
+







			*tmp = '\0';
			_parameters = [[OFString alloc]
			    initWithUTF8String: tmp + 1];
		}

		if (*UTF8String == '/')
			_path = [[OFString alloc]
			    initWithUTF8String: UTF8String];
			    initWithUTF8String: UTF8String + 1];
		else {
			void *pool;
			OFString *s;

			pool = objc_autoreleasePoolPush();

			if ([URL->_path hasSuffix: @"/"])
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







		[ret appendString: _host];

	if (([_scheme isEqual: @"http"] && _port != 80) ||
	    ([_scheme isEqual: @"https"] && _port != 443))
		[ret appendFormat: @":%u", _port];

	if (_path != nil)
		[ret appendString: _path];
		[ret appendFormat: @"/%@", _path];

	if (_parameters != nil)
		[ret appendFormat: @";%@", _parameters];

	if (_query != nil)
		[ret appendFormat: @"?%@", _query];

Modified tests/OFURLTests.m from [3641e79d58] to [d80e8f78e3].

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







-
+







	    [[u1 scheme] isEqual: @"http"] && [[u4 scheme] isEqual: @"file"])
	TEST(@"-[user]", [[u1 user] isEqual: @"u"] && [u4 user] == nil)
	TEST(@"-[password]",
	    [[u1 password] isEqual: @"p"] && [u4 password] == nil)
	TEST(@"-[host]", [[u1 host] isEqual: @"h"] && [u4 port] == 0)
	TEST(@"-[port]", [u1 port] == 1234)
	TEST(@"-[path]",
	    [[u1 path] isEqual: @"/f"] && [[u4 path] isEqual: @"/etc/passwd"])
	    [[u1 path] isEqual: @"f"] && [[u4 path] isEqual: @"/etc/passwd"])
	TEST(@"-[parameters]",
	    [[u1 parameters] isEqual: @"p"] && [u4 parameters] == nil)
	TEST(@"-[query]", [[u1 query] isEqual: @"q"] && [u4 query] == nil)
	TEST(@"-[fragment]",
	    [[u1 fragment] isEqual: @"f"] && [u4 fragment] == nil)

	TEST(@"-[copy]", R(u4 = [[u1 copy] autorelease]))

Modified tests/serialization.xml from [2be1e47e3a] to [d1cce18711].

1
2
3
4
5
6
7
8
9



















10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://webkeks.org/objfw/serialization' version='1'>
  <OFMutableDictionary>
    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
    <key>
      <OFDataArray>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFDataArray>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='double'>40934a456d5cfaad</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate>40934a456d5cfaad</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
    <key>
      <OFList>
        <OFString>Hello</OFString>
        <OFString>Wo&#xD;ld!
How are you?</OFString>
        <OFURL>https://webkeks.org/</OFURL>
        <OFXMLElement name='x'>
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
53
54
55
56
57
58
59



















60
61







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


          </object>
        </OFCountedSet>
      </OFList>
    </key>
    <object>
      <OFString>list</OFString>
    </object>
    <key>
      <OFDataArray>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFDataArray>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='double'>40934a456d5cfaad</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate>40934a456d5cfaad</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
  </OFMutableDictionary>
</serialization>