diff options
author | Max Christian Pohle | 2021-11-29 16:14:37 +0100 |
---|---|---|
committer | Max Christian Pohle | 2021-11-29 16:14:37 +0100 |
commit | 512c406b4fb3bc4054073608707ae07f65a65890 (patch) | |
tree | 4352c5587cbc4fd185b2cfc76bb68df53bf43b89 | |
parent | 7fd1bbc1abafee0f1db19118d127c5bd744f1b67 (diff) | |
download | ohmycgi-512c406b4fb3bc4054073608707ae07f65a65890.tar.bz2 ohmycgi-512c406b4fb3bc4054073608707ae07f65a65890.zip |
still getting this code shorter
-rw-r--r-- | http_parser.c | 81 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | main.h | 1 |
3 files changed, 43 insertions, 41 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 | ||
40 | static inline char * handle_colon(char ** start, char ** end, char ** search) { | 41 | static 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) |
@@ -70,7 +70,7 @@ static void * answer_request(size_t new_socket) { | |||
70 | fflush(output); | 70 | fflush(output); |
71 | // shutdown(new_socket, SHUT_RD); // shutdown the reading half of the connection | 71 | // shutdown(new_socket, SHUT_RD); // shutdown the reading half of the connection |
72 | 72 | ||
73 | DEBUG("output buffer has a length of %ld bytes\n", output_buffer_length); | 73 | DEBUG("> Output buffer has a length of %ld bytes\n", output_buffer_length); |
74 | 74 | ||
75 | // TODO: make parsing function abstract (e.g. parse(...) function point with dlsym) | 75 | // TODO: make parsing function abstract (e.g. parse(...) function point with dlsym) |
76 | parse_http(new_socket, output_buffer, output_buffer_length); | 76 | parse_http(new_socket, output_buffer, output_buffer_length); |
@@ -73,6 +73,7 @@ static inline int verbose(const char * format, ...) { | |||
73 | typedef struct { | 73 | typedef struct { |
74 | int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) | 74 | int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) |
75 | char * method; // GET/POST or something like that | 75 | char * method; // GET/POST or something like that |
76 | char * protocol; // mostly HTTP/1.0 or HTTP/1.1 | ||
76 | char * url; // request URL (e.g. /index.html) | 77 | char * url; // request URL (e.g. /index.html) |
77 | char * boundary; // usually looks similar to ------1234 | 78 | char * boundary; // usually looks similar to ------1234 |
78 | size_t boundary_size; // size in bytes, calculated after first header complete; is an indicator for the first header | 79 | size_t boundary_size; // size in bytes, calculated after first header complete; is an indicator for the first header |