Index: uspace/lib/http/src/headers.c
===================================================================
--- uspace/lib/http/src/headers.c	(revision 4d4f656ffc62186811fa02970d77df9e60512a39)
+++ uspace/lib/http/src/headers.c	(revision 4f086417d58e6722abb07d1b3ecedde65654bcfb)
@@ -94,55 +94,37 @@
 }
 
-int http_header_receive_name(receive_buffer_t *rb, char **out_name)
-{
-	receive_buffer_mark_t name_start;
-	receive_buffer_mark_t name_end;
-	
-	recv_mark(rb, &name_start);
-	recv_mark(rb, &name_end);
-	
+int http_header_receive_name(receive_buffer_t *rb,
+    receive_buffer_mark_t *name_end)
+{
 	char c = 0;
 	do {
-		recv_mark_update(rb, &name_end);
+		if (name_end)
+			recv_mark_update(rb, name_end);
 		
 		int rc = recv_char(rb, &c, true);
-		if (rc != EOK) {
-			recv_unmark(rb, &name_start);
-			recv_unmark(rb, &name_end);
-			return rc;
-		}
+		if (rc != EOK)
+			return rc;
 	} while (is_token(c));
 	
-	if (c != ':') {
-		recv_unmark(rb, &name_start);
-		recv_unmark(rb, &name_end);
+	if (c != ':')
 		return EINVAL;
-	}
-	
-	char *name = NULL;
-	int rc = recv_cut_str(rb, &name_start, &name_end, &name);
-	recv_unmark(rb, &name_start);
-	recv_unmark(rb, &name_end);
-	if (rc != EOK)
-		return rc;
-	
-	*out_name = name;
-	return EOK;
-}
-
-int http_header_receive_value(receive_buffer_t *rb, char **out_value)
+	
+	return EOK;
+}
+
+int http_header_receive_value(receive_buffer_t *rb,
+    receive_buffer_mark_t *value_start, receive_buffer_mark_t *value_end)
 {
 	int rc = EOK;
 	char c = 0;
 	
-	receive_buffer_mark_t value_start;
-	recv_mark(rb, &value_start);
-	
 	/* Ignore any inline LWS */
 	while (true) {
-		recv_mark_update(rb, &value_start);
+		if (value_start)
+			recv_mark_update(rb, value_start);
+		
 		rc = recv_char(rb, &c, false);
 		if (rc != EOK)
-			goto error;
+			return rc;
 		
 		if (c != ' ' && c != '\t')
@@ -151,16 +133,13 @@
 		rc = recv_char(rb, &c, true);
 		if (rc != EOK)
-			goto error;
-	}
-	
-	receive_buffer_mark_t value_end;
-	recv_mark(rb, &value_end);
+			return rc;
+	}
 	
 	while (true) {
-		recv_mark_update(rb, &value_end);
+		recv_mark_update(rb, value_end);
 		
 		rc = recv_char(rb, &c, true);
 		if (rc != EOK)
-			goto error_end;
+			return rc;
 		
 		if (c != '\r' && c != '\n')
@@ -169,9 +148,9 @@
 		rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
 		if (rc < 0)
-			goto error_end;
+			return rc;
 		
 		rc = recv_char(rb, &c, false);
 		if (rc != EOK)
-			goto error_end;
+			return rc;
 		
 		if (c != ' ' && c != '\t')
@@ -181,41 +160,61 @@
 		rc = recv_char(rb, &c, true);
 		if (rc != EOK)
-			goto error_end;
+			return rc;
+	}
+	
+	return EOK;
+}
+
+int http_header_receive(receive_buffer_t *rb, http_header_t *header,
+    size_t size_limit, size_t *out_bytes_used)
+{
+	receive_buffer_mark_t mark_start;
+	receive_buffer_mark_t mark_end;
+	
+	recv_mark(rb, &mark_start);
+	recv_mark(rb, &mark_end);
+	
+	int rc = http_header_receive_name(rb, &mark_end);
+	if (rc != EOK)
+		goto end;
+	
+	size_t name_size = mark_end.offset - mark_start.offset;
+	if (size_limit > 0 && name_size > size_limit) {
+		rc = ELIMIT;
+		goto end;
+	}
+	
+	char *name = NULL;
+	rc = recv_cut_str(rb, &mark_start, &mark_end, &name);
+	if (rc != EOK)
+		goto end;
+	
+	rc = http_header_receive_value(rb, &mark_start, &mark_end);
+	if (rc != EOK)
+		goto end_with_name;
+	
+	size_t value_size = mark_end.offset - mark_start.offset;
+	if (size_limit > 0 && (name_size + value_size) > size_limit) {
+		rc = ELIMIT;
+		goto end_with_name;
 	}
 	
 	char *value = NULL;
-	rc = recv_cut_str(rb, &value_start, &value_end, &value);
-	recv_unmark(rb, &value_start);
-	recv_unmark(rb, &value_end);
-	if (rc != EOK)
-		return rc;
-	
-	*out_value = value;
-	return EOK;
-error_end:
-	recv_unmark(rb, &value_end);
-error:
-	recv_unmark(rb, &value_start);
-	return rc;
-}
-
-int http_header_receive(receive_buffer_t *rb, http_header_t *header)
-{
-	char *name = NULL;
-	int rc = http_header_receive_name(rb, &name);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	char *value = NULL;
-	rc = http_header_receive_value(rb, &value);
-	if (rc != EOK) {
-		free(name);
-		return rc;
-	}
+	rc = recv_cut_str(rb, &mark_start, &mark_end, &value);
+	if (rc != EOK)
+		goto end_with_name;
+	
+	if (out_bytes_used)
+		*out_bytes_used = name_size + value_size;
 	
 	header->name = name;
 	header->value = value;
-	return EOK;
+	goto end;
+end_with_name:
+	free(name);
+end:
+	recv_unmark(rb, &mark_start);
+	recv_unmark(rb, &mark_end);
+	return rc;
 }
 
@@ -324,5 +323,6 @@
 }
 
-int http_headers_receive(receive_buffer_t *rb, http_headers_t *headers)
+int http_headers_receive(receive_buffer_t *rb, http_headers_t *headers,
+    size_t limit_alloc, unsigned limit_count)
 {
 	int rc = EOK;
@@ -337,4 +337,9 @@
 		if (c == '\n' || c == '\r')
 			break;
+		
+		if (limit_count > 0 && added >= limit_count) {
+			rc = ELIMIT;
+			goto error;
+		}
 		
 		http_header_t *header = malloc(sizeof(http_header_t));
@@ -345,9 +350,11 @@
 		http_header_init(header);
 		
-		rc = http_header_receive(rb, header);
+		size_t header_size;
+		rc = http_header_receive(rb, header, limit_alloc, &header_size);
 		if (rc != EOK) {
 			free(header);
 			goto error;
 		}
+		limit_alloc -= header_size;
 		
 		http_headers_append_header(headers, header);
