summaryrefslogtreecommitdiff
path: root/http_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'http_parser.c')
-rw-r--r--http_parser.c81
1 files changed, 41 insertions, 40 deletions
diff --git a/http_parser.c b/http_parser.c
index 03d8d91..fb891cc 100644
--- a/http_parser.c
+++ b/http_parser.c
@@ -36,6 +36,7 @@
36*/ 36*/
37 37
38#include "main.h" 38#include "main.h"
39#include <string.h>
39 40
40static inline char * handle_colon(char ** start, char ** end, char ** search) { 41static inline char * handle_colon(char ** start, char ** end, char ** search) {
41 // HTTP headers and content are separated by an empty line (which is two 42 // HTTP headers and content are separated by an empty line (which is two
@@ -64,10 +65,11 @@ static inline char * handle_semicolon(char ** start, char ** end, char ** searc
64 *end = *end + sizeof(s_multipart_form_data) + 1; 65 *end = *end + sizeof(s_multipart_form_data) + 1;
65 *end += strspn(*end, "-"); 66 *end += strspn(*end, "-");
66 *start = *end; 67 *start = *end;
67 DEBUG("> Boundary found, now looking where it ends...\n");
68 68
69 *end += strcspn(*end, "\r\n "); 69 *end += strcspn(*end, "\r\n ");
70 *end[0] = '\0'; 70 *end[0] = '\0';
71
72 DEBUG("> Boundary found: %s\n", *start);
71 } 73 }
72 74
73 *search = "\r\n"; // do not search further semicolons 75 *search = "\r\n"; // do not search further semicolons
@@ -84,11 +86,30 @@ void parse_http(size_t new_socket, char * request, size_t request_length) {
84 // generic and only requires content length bounary checks. 86 // generic and only requires content length bounary checks.
85 87
86 char * start = request; 88 char * start = request;
87 char * end = NULL; 89 char * end = "\0";
88 char * search = "\r\n"; 90 char * search = "\r\n";
89 91
90 Http_Header http_header = {0}; 92 Http_Header http_header = {0};
91 93
94 request[request_length] = '\0';
95
96 // {{{ Parse the request line (e.g. "POST / HTTP/1.1")
97 http_header.method = start;
98 start += strcspn(start, " ");
99 start[0] = '\0';
100 http_header.url = ++start;
101 start += strcspn(start, " ");
102 start[0] = '\0';
103 http_header.protocol = ++start;
104 start += strcspn(start, "\r\n");
105 http_header.newline_length = strspn(start, "\r\n");
106 start[0] = '\0';
107 start += http_header.newline_length;
108
109 DEBUG("%% Request line: method='%s' url='%s' protocol='%s' newline_length=%ld\n",
110 http_header.method, http_header.url, http_header.protocol, http_header.newline_length);
111 // }}}
112
92 char * name = NULL; 113 char * name = NULL;
93 while(NULL != (end = strpbrk(start, search))) { // TODO: try harder to break things (are SEGFAULTs possible?) 114 while(NULL != (end = strpbrk(start, search))) { // TODO: try harder to break things (are SEGFAULTs possible?)
94 115
@@ -96,61 +117,39 @@ void parse_http(size_t new_socket, char * request, size_t request_length) {
96 switch(end[0]) { 117 switch(end[0]) {
97 case ':': 118 case ':':
98 name = handle_colon(&start, &end, &search); 119 name = handle_colon(&start, &end, &search);
99 break; 120 break;
100 case ';': 121 case ';':
101 http_header.boundary = handle_semicolon(&start, &end, &search); 122 http_header.boundary = handle_semicolon(&start, &end, &search);
102 http_header.boundary_size = end - start; 123 http_header.boundary_size = end - start;
103 break; 124 break;
104 case '\r': // fallthrough 125 case '\r': // fallthrough
105 case '\n': 126 case '\n':
106 // {{{ newlines are special: sometimes content parts follow and sometimes headers, guess what...
107 end[0] = '\0'; 127 end[0] = '\0';
108 search = ":"; // we will continue to search for headers 128 search = ":"; // we will continue to search for headers
109 if(NULL == name) { 129
110 if(NULL == http_header.method) { 130 // {{{ NAME AND VALUE OF A HEADER FIELD KNOWN
111 DEBUG("[%ld]> HTTP REQUEST LINE :: %s \n", matchlen, start); 131 if(NULL != name) {
112 end[0] = '\0'; 132 DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start);
113 133
114 while(NULL != (start = memchr(start, ' ', end - start))) {
115 if(NULL == http_header.url)
116 http_header.url = ++start;
117 else
118 start[0] = '\0';
119 }
120 http_header.method = start;
121 http_header.newline_length = matchlen;
122 } else {
123 DEBUG("[...]\n"); // if we want to intentially skip something, we land here by setting name = NUL;
124 break;
125 }
126 } else { // we know that name is not NULL and can work with it
127 if (0 == strcasecmp("Content-Disposition", name)) 134 if (0 == strcasecmp("Content-Disposition", name))
128 { http_header.content_disposition = start; } 135 { http_header.content_disposition = start; }
129 } // }}} 136 } // }}}
130 137 // {{{ END OF A HTTP HEADER (two newlines)
131 // {{{ DEBUG
132 DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start);
133 // }}}
134
135 // check if a http header ended (e.g. two newlines)
136 if(matchlen > http_header.newline_length) { 138 if(matchlen > http_header.newline_length) {
137 end += matchlen; // go behind the double line break... 139 end += matchlen; // go behind the double line break...
138 140
139 //{{{ DEBUG 141 DEBUG("%% END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n",
140 DEBUG("> END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n", 142 matchlen / http_header.newline_length,
141 matchlen / http_header.newline_length, 143 http_header.boundary,
142 http_header.boundary, 144 http_header.boundary_size
143 http_header.boundary_size 145 );
144 ); // }}}
145 146
146 start = end; 147 start = end;
147 for(; ; ) 148 for(; ; )
148 { 149 {
149 size_t size_remaining = (size_t) request_length - (end - request) - 1; 150 size_t size_remaining = (size_t) request_length - (end - request) - 1;
150 151
151 // {{{ DEBUG
152 DEBUG("%ld remaining.\n", size_remaining); 152 DEBUG("%ld remaining.\n", size_remaining);
153 // }}}
154 153
155 matchlen = strspn(end, "-"); 154 matchlen = strspn(end, "-");
156 if(0 == strncmp(end + matchlen, http_header.boundary, http_header.boundary_size)) { 155 if(0 == strncmp(end + matchlen, http_header.boundary, http_header.boundary_size)) {
@@ -170,16 +169,18 @@ void parse_http(size_t new_socket, char * request, size_t request_length) {
170 if(!http_header.boundary 169 if(!http_header.boundary
171 || size_remaining <= 0 170 || size_remaining <= 0
172 || NULL == (end = memchr((void*) end, '-', size_remaining))) { 171 || NULL == (end = memchr((void*) end, '-', size_remaining))) {
173 // {{{ DEBUG
174 DEBUG("EOF reached or no further '-' found\n"); 172 DEBUG("EOF reached or no further '-' found\n");
175 // }}}
176 break; 173 break;
177 } 174 }
178 // end++; 175 // end++;
179 } 176 }
180 } 177 }
181 break; 178 } // }}} if condition after a header
182 } // if condition after a header 179 break;
180
181 default:
182 DEBUG("Unknown char found: '%c'\n ", end[0]);
183 break;
183 } // switch 184 } // switch
184 185
185 if(NULL == end) 186 if(NULL == end)
..