summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Christian Pohle2021-11-17 21:54:56 +0100
committerMax Christian Pohle2021-11-17 21:54:56 +0100
commit316d434ea8c0e7de1359dd04644cdc9dc955c839 (patch)
tree4c09cd89420178356f23825975afef20cb3499c1
parente2f46e15df9ef19be4f05583b5a9513cdbf09720 (diff)
downloadohmycgi-316d434ea8c0e7de1359dd04644cdc9dc955c839.tar.bz2
ohmycgi-316d434ea8c0e7de1359dd04644cdc9dc955c839.zip
That is much better now
-rw-r--r--main.c178
1 files changed, 95 insertions, 83 deletions
diff --git a/main.c b/main.c
index 2bf2e14..7fef5f3 100644
--- a/main.c
+++ b/main.c
@@ -54,12 +54,16 @@ void read_everything(FILE * f_r, FILE * output) {
54 if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) { 54 if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) {
55 usleep(EWOULDBLOCK_DELAY); // try again a little later 55 usleep(EWOULDBLOCK_DELAY); // try again a little later
56 continue; 56 continue;
57 } else if (1 != size) { // I expect one nmemb of data
58 break;
59 } 57 }
60 58
61 fwrite(read_buffer, read_buffer_length, 1, output); 59 fwrite(read_buffer, read_buffer_length, 1, output);
60 fwrite(read_buffer, read_buffer_length, 1, stdout);
61
62 if (1 != size) { // I expect one nmemb of data
63 break;
64 }
62 } 65 }
66 fflush(stdout);
63 fflush(output); 67 fflush(output);
64} 68}
65 69
@@ -83,6 +87,14 @@ void header_next(const char * key, const char * value) {
83 } 87 }
84} 88}
85 89
90typedef struct {
91 int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2)
92 char * method;
93 char * boundary;
94 char * content_type;
95 char * content_disposition;
96} Http_Header;
97
86void * next_customer(size_t new_socket) { 98void * next_customer(size_t new_socket) {
87 FILE * f_r = fdopen((size_t) new_socket, "r"); 99 FILE * f_r = fdopen((size_t) new_socket, "r");
88 FILE * f_w = fdopen((size_t) new_socket, "w"); 100 FILE * f_w = fdopen((size_t) new_socket, "w");
@@ -93,111 +105,111 @@ void * next_customer(size_t new_socket) {
93 105
94 verbose("\n\n########################################## Content Reader [%d]\n", f_r); 106 verbose("\n\n########################################## Content Reader [%d]\n", f_r);
95 read_everything(f_r, output); 107 read_everything(f_r, output);
96 verbose("\n\n########################################## Content Parser"); 108 verbose("\n\n########################################## Content Parser\n");
97 109
98 110
99 // token parser... 111 // token parser...
100 const char * boundary = NULL;
101 size_t boundary_length = 0;
102 char * search = NULL;
103 char * key = output_buffer; 112 char * key = output_buffer;
104 113
105 char * saveptr = NULL; 114 char * saveptr = NULL;
106 char * content_start = NULL; 115 char * content_start = NULL;
107 char * content_end = NULL; 116 char * content_end = NULL;
108 117
109 while(key ? key[0] != '\0' : 1) { 118 char * start = output_buffer;
110 verbose("> [!] Next iteration with search '%s'\n", search); 119 char * end;
111 for(char * 120 char * search = "\r\n";
112 token = strtok_r(NULL == saveptr ? output_buffer : saveptr, NULL == search ? "\n\r" : search, &saveptr); 121
113 token != NULL; 122 Http_Header http_header;
114 token = strtok_r(NULL, search, &saveptr)) 123 http_header.newline_length = 1;
115 { 124 http_header.method = NULL;
116 125 http_header.boundary = NULL;
117 if(!search) { // first round: HTTP status code 126 http_header.content_disposition = NULL;
118 verbose("> First Iteration: HTTP sanity check of: %s\n", token); 127 http_header.content_type = NULL;
119 search = ":"; 128
120 continue; 129 char * name = NULL;
121 } 130 while(NULL != (end = strpbrk(start, search))) {
122 131
123 if(!key) { 132 size_t matchlen = strspn(end, search);
124 search = "\r\n"; // we found a key and expect the value to be between here and EOL 133 switch(end[0]) {
125 key = &token[strspn(token, search)]; // also remove leading spaces 134 case ':':
135 end[0] = '\0';
136 end++;
126 137
127 if(0 == strncmp(token, "\n\r\n", 3) 138 name = start;
128 || 0 == strncmp(token, "\n\n", 2)) { 139
140 if (0 == strcasecmp("Content-Type", start)) {
141 search = "\r\n;";
142 } else {
129 search = "\r\n"; 143 search = "\r\n";
144 }
145 break;
146 case ';':
147 {
148 start += strspn(start, "; ");
149
150 const char s_multipart_form_data[] = "boundary=";
151 if(NULL == http_header.boundary && 0 < strcasecmp(start, s_multipart_form_data))
152 {
153 http_header.boundary = end + sizeof(s_multipart_form_data) + 1;
154 http_header.boundary += strspn(http_header.boundary, "-");
155 // verbose("GESCHAFFT %s QQQQ %s\n", http_header.boundary, end);
156 search = "\r\n";
157 continue;
158 }
130 break; 159 break;
131 } 160 }
132 } else { // value 161 case '\r': // fallthrough
133 162 case '\n':
134 token += strspn(token, ": "); 163 end[0] = '\0';
135 const char * value = token; 164 search = ":"; // we will continue to search for headers
136 165
137 const char pattern[] = "multipart/form-data; boundary="; 166
138 if(!boundary && strstr(key, "Content-Type") && strncmp(value, pattern, sizeof(pattern))) { 167 if(NULL == name) {
139 boundary = &value[sizeof(pattern) + strspn(&value[sizeof(pattern)], "-")]; 168 if(NULL == http_header.method) {
140 boundary_length = strlen(boundary); 169 verbose("[%ld]> HTTP REQUEST LINE :: %s \n", matchlen, start);
141 verbose("> [!] boundary detected '%s' ", boundary); 170 http_header.method = start;
171 http_header.newline_length = matchlen;
172 } else {
173 verbose("[...]\n"); // if we want to intentially skip something, we land here by setting name = NUL;
174 break;
175 }
176 } else { // we know that name is not NULL and can work with it
177 if (0 == strcasecmp("Content-Disposition", name))
178 { http_header.content_disposition = start; }
142 } 179 }
143 180
144 header_next(key, value); 181 verbose("\033[0;32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start);
145
146 verbose("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout);
147 182
148 search = ":"; 183 if(matchlen > http_header.newline_length) {
149 key = NULL; 184 verbose("END HEADERS, boundary='%s'\n", http_header.boundary);
150 } 185 // start = strstr(end, http_header.boundary);
151 } 186 search = "-";
152 187 }
153 if(!key)
154 break;
155 // printf("We are now here: %ld\n", key - output_buffer);
156 verbose("We are now here: %s\n", key);
157
158 // jump over the content...
159 content_start = key;
160 while((key = memchr(key, '\n', output_buffer_length - (key - output_buffer)))) {
161 if(!key) {
162 verbose("out at %p\n", key);
163 break; 188 break;
164 } else { 189 case '-':
165 key++; 190 {
166 } 191 char * content_start = end;
167 192 content_start += strspn(content_start, "-");
168 if(key[0] == '-') { 193 // verbose("CONTENT: %s\n", content_start);
169 if(0 == strncmp(&key[strspn(key, "-")], boundary, boundary_length)) { 194 if(0 <= strcmp(content_start, http_header.boundary)) {
170 verbose("> boundary found."); 195 verbose("MATCH\n");
171 196 search = "\r\n";
172 if(key[-1] == '\n') key--; 197 start = content_start + strlen(http_header.boundary);
173 if(key[-1] == '\r') key--; 198 name = NULL;
174 199 continue;
175 content_end = key; 200 } else {
176 key += strspn(key, "\r\n-"); 201 verbose("NO MATCH\n");
177 key += boundary_length; 202 }
178 key += strspn(key, "\r\n");
179 saveptr = key;
180 key = NULL;
181 search = ":";
182 break; 203 break;
183 } 204 }
184 }
185 } 205 }
186 206
187 verbose("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); 207 start = end + matchlen;
188 if(content_end - content_start > 1000) { 208 }
189 FILE * f_w = fopen("/tmp/test.gif", "w");
190 fwrite(content_start, content_end - content_start, 1, f_w);
191 fclose(f_w);
192 puts("FILE WRITTEN");
193 }
194 209
195 // printf("We have gone to %ld\n", key - output_buffer); fflush(stdout); 210 if(http_header.boundary)
196 if(key && key[0] == '\0') // final boundary reached? 211 verbose("http-boundary: %s", http_header.boundary);
197 break;
198 212
199 // usleep(100000);
200 }
201 213
202 verbose("> sending answer..."); 214 verbose("> sending answer...");
203 send_answer(f_w); 215 send_answer(f_w);
..