ObjFW  Diff

Differences From Artifact [7e47217e14]:

To Artifact [a4708f3429]:


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}

static OF_INLINE OFString*
normalized_key(OFString *key)
{
	char *cString = strdup([key UTF8String]);
	uint8_t *tmp = (uint8_t*)cString;
	BOOL firstLetter = YES;

	if (cString == NULL)
		@throw [OFOutOfMemoryException
		    exceptionWithClass: nil
			 requestedSize: strlen([key UTF8String])];

	while (*tmp != '\0') {
		if (!isalnum(*tmp)) {
			firstLetter = YES;
			tmp++;
			continue;
		}

		*tmp = (firstLetter ? toupper(*tmp) : tolower(*tmp));

		firstLetter = NO;
		tmp++;
	}

	return [OFString stringWithUTF8StringNoCopy: cString
				       freeWhenDone: YES];
}

@interface OFHTTPServerReply: OFHTTPRequestReply
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	BOOL _chunked, _headersSent, _closed;
}

- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server;
@end

@implementation OFHTTPServerReply







|








|






|




|






|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}

static OF_INLINE OFString*
normalized_key(OFString *key)
{
	char *cString = strdup([key UTF8String]);
	uint8_t *tmp = (uint8_t*)cString;
	bool firstLetter = true;

	if (cString == NULL)
		@throw [OFOutOfMemoryException
		    exceptionWithClass: nil
			 requestedSize: strlen([key UTF8String])];

	while (*tmp != '\0') {
		if (!isalnum(*tmp)) {
			firstLetter = true;
			tmp++;
			continue;
		}

		*tmp = (firstLetter ? toupper(*tmp) : tolower(*tmp));

		firstLetter = false;
		tmp++;
	}

	return [OFString stringWithUTF8StringNoCopy: cString
				       freeWhenDone: true];
}

@interface OFHTTPServerReply: OFHTTPRequestReply
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	bool _chunked, _headersSent, _closed;
}

- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server;
@end

@implementation OFHTTPServerReply
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	while ((key = [keyEnumerator nextObject]) != nil &&
	    (value = [valueEnumerator nextObject]) != nil)
		if (![key isEqual: @"Server"] && ![key isEqual: @"Date"])
			[_socket writeFormat: @"%@: %@\r\n", key, value];

	[_socket writeString: @"\r\n"];

	_headersSent = YES;
	_chunked = [[_headers objectForKey: @"Transfer-Encoding"]
	    isEqual: @"chunked"];

	objc_autoreleasePoolPop(pool);
}

- (void)lowlevelWriteBuffer: (const void*)buffer







|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	while ((key = [keyEnumerator nextObject]) != nil &&
	    (value = [valueEnumerator nextObject]) != nil)
		if (![key isEqual: @"Server"] && ![key isEqual: @"Date"])
			[_socket writeFormat: @"%@: %@\r\n", key, value];

	[_socket writeString: @"\r\n"];

	_headersSent = true;
	_chunked = [[_headers objectForKey: @"Transfer-Encoding"]
	    isEqual: @"chunked"];

	objc_autoreleasePoolPop(pool);
}

- (void)lowlevelWriteBuffer: (const void*)buffer
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

	if (_chunked)
		[_socket writeBuffer: "0\r\n\r\n"
			      length: 5];

	[_socket close];

	_closed = YES;
}

- (int)fileDescriptorForWriting
{
	return [_socket fileDescriptorForWriting];
}
@end







|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

	if (_chunked)
		[_socket writeBuffer: "0\r\n\r\n"
			      length: 5];

	[_socket close];

	_closed = true;
}

- (int)fileDescriptorForWriting
{
	return [_socket fileDescriptorForWriting];
}
@end
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
	OFMutableDictionary *_headers;
	size_t _contentLength;
	OFDataArray *_POSTData;
}

- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server;
- (BOOL)socket: (OFTCPSocket*)socket
   didReadLine: (OFString*)line
     exception: (OFException*)exception;
- (BOOL)parseProlog: (OFString*)line;
- (BOOL)parseHeaders: (OFString*)line;
-      (BOOL)socket: (OFTCPSocket*)socket
  didReadIntoBuffer: (const char*)buffer
	     length: (size_t)length
	  exception: (OFException*)exception;
- (BOOL)sendErrorAndClose: (short)statusCode;
- (void)createReply;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server
{
	self = [super init];

	@try {
		_socket = [socket retain];
		_server = [server retain];
		_timer = [[OFTimer
		    scheduledTimerWithTimeInterval: 10
					    target: socket
					  selector: @selector(
							cancelAsyncRequests)
					   repeats: NO] retain];
		_state = AWAITING_PROLOG;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







|


|
|
|



|

















|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
	OFMutableDictionary *_headers;
	size_t _contentLength;
	OFDataArray *_POSTData;
}

- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server;
- (bool)socket: (OFTCPSocket*)socket
   didReadLine: (OFString*)line
     exception: (OFException*)exception;
- (bool)parseProlog: (OFString*)line;
- (bool)parseHeaders: (OFString*)line;
-      (bool)socket: (OFTCPSocket*)socket
  didReadIntoBuffer: (const char*)buffer
	     length: (size_t)length
	  exception: (OFException*)exception;
- (bool)sendErrorAndClose: (short)statusCode;
- (void)createReply;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket*)socket
	  server: (OFHTTPServer*)server
{
	self = [super init];

	@try {
		_socket = [socket retain];
		_server = [server retain];
		_timer = [[OFTimer
		    scheduledTimerWithTimeInterval: 10
					    target: socket
					  selector: @selector(
							cancelAsyncRequests)
					   repeats: false] retain];
		_state = AWAITING_PROLOG;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
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
	[_path release];
	[_headers release];
	[_POSTData release];

	[super dealloc];
}

- (BOOL)socket: (OFTCPSocket*)socket
   didReadLine: (OFString*)line
     exception: (OFException*)exception
{
	if (line == nil || exception != nil)
		return NO;

	@try {
		switch (_state) {
		case AWAITING_PROLOG:
			return [self parseProlog: line];
		case PARSING_HEADERS:
			if (![self parseHeaders: line])
				return NO;

			if (_state == SEND_REPLY) {
				[self createReply];
				return NO;
			}

			return YES;
		default:
			return NO;
		}
	} @catch (OFWriteFailedException *e) {
		return NO;
	}

	abort();
}

- (BOOL)parseProlog: (OFString*)line
{
	OFString *type;
	size_t pos;

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







|




|







|



|


|

|


|





|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
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
	[_path release];
	[_headers release];
	[_POSTData release];

	[super dealloc];
}

- (bool)socket: (OFTCPSocket*)socket
   didReadLine: (OFString*)line
     exception: (OFException*)exception
{
	if (line == nil || exception != nil)
		return false;

	@try {
		switch (_state) {
		case AWAITING_PROLOG:
			return [self parseProlog: line];
		case PARSING_HEADERS:
			if (![self parseHeaders: line])
				return false;

			if (_state == SEND_REPLY) {
				[self createReply];
				return false;
			}

			return true;
		default:
			return false;
		}
	} @catch (OFWriteFailedException *e) {
		return false;
	}

	abort();
}

- (bool)parseProlog: (OFString*)line
{
	OFString *type;
	size_t pos;

	@try {
		OFString *version = [line
		    substringWithRange: of_range([line length] - 9, 9)];
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

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

	_headers = [[OFMutableDictionary alloc] init];
	_state = PARSING_HEADERS;

	return YES;
}

- (BOOL)parseHeaders: (OFString*)line
{
	OFString *key, *value;
	size_t pos;

	if ([line length] == 0) {
		switch (_requestType) {
		case OF_HTTP_REQUEST_TYPE_GET:







|


|







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

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

	_headers = [[OFMutableDictionary alloc] init];
	_state = PARSING_HEADERS;

	return true;
}

- (bool)parseHeaders: (OFString*)line
{
	OFString *key, *value;
	size_t pos;

	if ([line length] == 0) {
		switch (_requestType) {
		case OF_HTTP_REQUEST_TYPE_GET:
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
					      target: self
					    selector: @selector(socket:
							  didReadIntoBuffer:
							  length:exception:)];
			[_timer setFireDate:
			    [OFDate dateWithTimeIntervalSinceNow: 5]];

			return NO;
		}

		return YES;
	}

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

	key = [line substringWithRange: of_range(0, pos)];







|


|







466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
					      target: self
					    selector: @selector(socket:
							  didReadIntoBuffer:
							  length:exception:)];
			[_timer setFireDate:
			    [OFDate dateWithTimeIntervalSinceNow: 5]];

			return false;
		}

		return true;
	}

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

	key = [line substringWithRange: of_range(0, pos)];
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
		} else {
			[_host release];
			_host = [value retain];
			_port = 80;
		}
	}

	return YES;
}

-      (BOOL)socket: (OFTCPSocket*)socket
  didReadIntoBuffer: (const char*)buffer
	     length: (size_t)length
	  exception: (OFException*)exception
{
	if ([socket isAtEndOfStream] || exception != nil)
		return NO;

	[_POSTData addItems: buffer
		      count: length];

	if ([_POSTData count] >= _contentLength) {
		@try {
			[self createReply];
		} @catch (OFWriteFailedException *e) {
			return NO;
		}

		return NO;
	}

	[_timer setFireDate: [OFDate dateWithTimeIntervalSinceNow: 5]];

	return YES;
}

- (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"
			      @"Date: %@\r\n"
			      @"Server: %@\r\n"
			      @"\r\n",
			      statusCode, status_code_to_string(statusCode),
			      date, [_server name]];
	[_socket close];

	return NO;
}

- (void)createReply
{
	OFURL *URL;
	OFHTTPRequest *request;
	OFHTTPServerReply *reply;







|


|





|








|


|




|


|












|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
		} else {
			[_host release];
			_host = [value retain];
			_port = 80;
		}
	}

	return true;
}

-      (bool)socket: (OFTCPSocket*)socket
  didReadIntoBuffer: (const char*)buffer
	     length: (size_t)length
	  exception: (OFException*)exception
{
	if ([socket isAtEndOfStream] || exception != nil)
		return false;

	[_POSTData addItems: buffer
		      count: length];

	if ([_POSTData count] >= _contentLength) {
		@try {
			[self createReply];
		} @catch (OFWriteFailedException *e) {
			return false;
		}

		return false;
	}

	[_timer setFireDate: [OFDate dateWithTimeIntervalSinceNow: 5]];

	return true;
}

- (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"
			      @"Date: %@\r\n"
			      @"Server: %@\r\n"
			      @"\r\n",
			      statusCode, status_code_to_string(statusCode),
			      date, [_server name]];
	[_socket close];

	return false;
}

- (void)createReply
{
	OFURL *URL;
	OFHTTPRequest *request;
	OFHTTPServerReply *reply;
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
	[_name release];

	[super dealloc];
}

- (void)setHost: (OFString*)host
{
	OF_SETTER(_host, host, YES, 1)
}

- (OFString*)host
{
	OF_GETTER(_host, YES)
}

- (void)setPort: (uint16_t)port
{
	_port = port;
}








|




|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
	[_name release];

	[super dealloc];
}

- (void)setHost: (OFString*)host
{
	OF_SETTER(_host, host, true, 1)
}

- (OFString*)host
{
	OF_GETTER(_host, true)
}

- (void)setPort: (uint16_t)port
{
	_port = port;
}

675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
- (id <OFHTTPServerDelegate>)delegate
{
	return _delegate;
}

- (void)setName: (OFString*)name
{
	OF_SETTER(_name, name, YES, 1)
}

- (OFString*)name
{
	OF_GETTER(_name, YES)
}

- (void)start
{
	if (_host == nil || _port == 0)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]







|




|







675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
- (id <OFHTTPServerDelegate>)delegate
{
	return _delegate;
}

- (void)setName: (OFString*)name
{
	OF_SETTER(_name, name, true, 1)
}

- (OFString*)name
{
	OF_GETTER(_name, true)
}

- (void)start
{
	if (_host == nil || _port == 0)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (BOOL)OF_socket: (OFTCPSocket*)socket
  didAcceptSocket: (OFTCPSocket*)clientSocket
	exception: (OFException*)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:
		    @selector(server:didReceiveExceptionOnListeningSocket:)])
			return [_delegate		  server: self
			    didReceiveExceptionOnListeningSocket: exception];

		return NO;
	}

	connection = [[[OFHTTPServer_Connection alloc]
	    initWithSocket: clientSocket
		    server: self] autorelease];

	[clientSocket asyncReadLineWithTarget: connection
				     selector: @selector(socket:didReadLine:
						  exception:)];

	return YES;
}
@end







|











|










|


713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (bool)OF_socket: (OFTCPSocket*)socket
  didAcceptSocket: (OFTCPSocket*)clientSocket
	exception: (OFException*)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:
		    @selector(server:didReceiveExceptionOnListeningSocket:)])
			return [_delegate		  server: self
			    didReceiveExceptionOnListeningSocket: exception];

		return false;
	}

	connection = [[[OFHTTPServer_Connection alloc]
	    initWithSocket: clientSocket
		    server: self] autorelease];

	[clientSocket asyncReadLineWithTarget: connection
				     selector: @selector(socket:didReadLine:
						  exception:)];

	return true;
}
@end