Subversion Repositories Tewi

Rev

Rev 187 | Rev 213 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 187 Rev 212
Line 1... Line 1...
1
/* $Id: http.c 187 2024-09-28 00:07:34Z nishi $ */
1
/* $Id: http.c 212 2024-10-02 17:44:55Z nishi $ */
2
 
2
 
3
#define SOURCE
3
#define SOURCE
4
 
4
 
5
#include "../config.h"
5
#include "../config.h"
6
 
6
 
Line 13... Line 13...
13
 
13
 
14
#include <stdbool.h>
14
#include <stdbool.h>
15
#include <stdlib.h>
15
#include <stdlib.h>
16
#include <string.h>
16
#include <string.h>
17
 
17
 
18
#ifdef __MINGW32__
18
#if defined(__MINGW32__) || defined(_MSC_VER)
19
#include <winsock2.h>
19
#include <winsock2.h>
20
#else
20
#else
21
#ifdef USE_POLL
21
#ifdef USE_POLL
22
#ifdef __PPU__
22
#ifdef __PPU__
23
#include <net/poll.h>
23
#include <net/poll.h>
Line 51... Line 51...
51
 
51
 
52
int tw_http_parse(SSL* ssl, int sock, struct tw_http_request* req) {
52
int tw_http_parse(SSL* ssl, int sock, struct tw_http_request* req) {
53
	char buffer[512];
53
	char buffer[512];
54
	char cbuf[2];
54
	char cbuf[2];
55
	int phase = 0;
55
	int phase = 0;
-
 
56
	char* header;
-
 
57
	int nl;
56
 
58
 
57
#ifdef USE_POLL
59
#ifdef USE_POLL
58
	struct pollfd pollfds[1];
60
	struct pollfd pollfds[1];
59
	pollfds[0].fd = sock;
61
	pollfds[0].fd = sock;
60
	pollfds[0].events = POLLIN | POLLPRI;
62
	pollfds[0].events = POLLIN | POLLPRI;
Line 71... Line 73...
71
	req->query = NULL;
73
	req->query = NULL;
72
	req->headers = NULL;
74
	req->headers = NULL;
73
	req->body = NULL;
75
	req->body = NULL;
74
	req->version = NULL;
76
	req->version = NULL;
75
 
77
 
76
	char* header = malloc(1);
78
	header = malloc(1);
77
	header[0] = 0;
79
	header[0] = 0;
78
	int nl = 0;
80
	nl = 0;
79
 
81
 
80
	while(1) {
82
	while(1) {
-
 
83
		int i;
-
 
84
		int len;
-
 
85
			int n;
81
#ifndef USE_POLL
86
#ifndef USE_POLL
-
 
87
		struct timeval tv;
82
		FD_ZERO(&fds);
88
		FD_ZERO(&fds);
83
		FD_SET(sock, &fds);
89
		FD_SET(sock, &fds);
84
		struct timeval tv;
-
 
85
		tv.tv_sec = 5;
90
		tv.tv_sec = 5;
86
		tv.tv_usec = 0;
91
		tv.tv_usec = 0;
87
#endif
92
#endif
88
#ifndef NO_SSL
93
#ifndef NO_SSL
89
		if(ssl == NULL || !SSL_has_pending(ssl)) {
94
		if(ssl == NULL || !SSL_has_pending(ssl)) {
90
#endif
95
#endif
91
#ifdef USE_POLL
96
#ifdef USE_POLL
92
			int n = poll(pollfds, 1, 5000);
97
			n = poll(pollfds, 1, 5000);
93
#else
98
#else
94
#ifdef __HAIKU__
99
#ifdef __HAIKU__
95
		int n = select(32, &fds, NULL, NULL, &tv);
100
		n = select(32, &fds, NULL, NULL, &tv);
96
#else
101
#else
97
		int n = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
102
		n = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
98
#endif
103
#endif
99
#endif
104
#endif
100
			if(n <= 0) {
105
			if(n <= 0) {
101
				cm_log("HTTP", "Timeout, disconnecting");
106
				cm_log("HTTP", "Timeout, disconnecting");
102
				free(header);
107
				free(header);
Line 104... Line 109...
104
				return -1;
109
				return -1;
105
			}
110
			}
106
#ifndef NO_SSL
111
#ifndef NO_SSL
107
		}
112
		}
108
#endif
113
#endif
109
		int len = tw_read(ssl, sock, buffer, 512);
114
		len = tw_read(ssl, sock, buffer, 512);
110
		if(len <= 0) {
115
		if(len <= 0) {
111
			bad = true;
116
			bad = true;
112
			break;
117
			break;
113
		}
118
		}
114
		int i;
-
 
115
		for(i = 0; i < len; i++) {
119
		for(i = 0; i < len; i++) {
116
			char c = buffer[i];
120
			char c = buffer[i];
117
			if(phase == 0) {
121
			if(phase == 0) {
118
				if(c == ' ') {
122
				if(c == ' ') {
119
					if(req->method == NULL) {
123
					if(req->method == NULL) {
Line 122... Line 126...
122
						goto getout;
126
						goto getout;
123
					} else {
127
					} else {
124
						phase++;
128
						phase++;
125
					}
129
					}
126
				} else {
130
				} else {
-
 
131
					char* tmp;
127
					if(req->method == NULL) {
132
					if(req->method == NULL) {
128
						req->method = malloc(1);
133
						req->method = malloc(1);
129
						req->method[0] = 0;
134
						req->method[0] = 0;
130
					}
135
					}
131
					cbuf[0] = c;
136
					cbuf[0] = c;
132
					char* tmp = req->method;
137
					tmp = req->method;
133
					req->method = cm_strcat(tmp, cbuf);
138
					req->method = cm_strcat(tmp, cbuf);
134
					free(tmp);
139
					free(tmp);
135
				}
140
				}
136
			} else if(phase == 1) {
141
			} else if(phase == 1) {
137
				if(c == ' ') {
142
				if(c == ' ') {
Line 141... Line 146...
141
						goto getout;
146
						goto getout;
142
					} else {
147
					} else {
143
						phase++;
148
						phase++;
144
					}
149
					}
145
				} else {
150
				} else {
-
 
151
					char* tmp;
146
					if(req->path == NULL) {
152
					if(req->path == NULL) {
147
						req->path = malloc(1);
153
						req->path = malloc(1);
148
						req->path[0] = 0;
154
						req->path[0] = 0;
149
					}
155
					}
150
					cbuf[0] = c;
156
					cbuf[0] = c;
151
					char* tmp = req->path;
157
					tmp = req->path;
152
					req->path = cm_strcat(tmp, cbuf);
158
					req->path = cm_strcat(tmp, cbuf);
153
					free(tmp);
159
					free(tmp);
154
				}
160
				}
155
			} else if(phase == 2) {
161
			} else if(phase == 2) {
156
				if(c == '\n') {
162
				if(c == '\n') {
Line 158... Line 164...
158
						tw_free_request(req);
164
						tw_free_request(req);
159
						bad = true;
165
						bad = true;
160
						goto getout;
166
						goto getout;
161
					} else {
167
					} else {
162
						/* We have Method, Path, Version now */
168
						/* We have Method, Path, Version now */
163
 
169
						int j;
-
 
170
						char* p;
-
 
171
						int incr;
164
						if(strcmp(req->version, "HTTP/1.1") != 0 && strcmp(req->version, "HTTP/1.0") != 0) {
172
						if(strcmp(req->version, "HTTP/1.1") != 0 && strcmp(req->version, "HTTP/1.0") != 0) {
165
							cm_log("HTTP", "Bad HTTP Version");
173
							cm_log("HTTP", "Bad HTTP Version");
166
							bad = true;
174
							bad = true;
167
							goto getout;
175
							goto getout;
168
						}
176
						}
169
 
177
 
170
						int j;
-
 
171
						char* p = malloc(1);
178
						p = malloc(1);
172
						p[0] = 0;
179
						p[0] = 0;
173
						for(j = 0; req->path[j] != 0; j++) {
180
						for(j = 0; req->path[j] != 0; j++) {
-
 
181
							char* tmp;
174
							if(req->path[j] == '/') {
182
							if(req->path[j] == '/') {
175
								cbuf[0] = '/';
183
								cbuf[0] = '/';
176
								for(; req->path[j] != 0 && req->path[j] == '/'; j++)
184
								for(; req->path[j] != 0 && req->path[j] == '/'; j++)
177
									;
185
									;
178
								j--;
186
								j--;
179
							} else {
187
							} else {
180
								cbuf[0] = req->path[j];
188
								cbuf[0] = req->path[j];
181
							}
189
							}
182
							char* tmp = p;
190
							tmp = p;
183
							p = cm_strcat(tmp, cbuf);
191
							p = cm_strcat(tmp, cbuf);
184
							free(tmp);
192
							free(tmp);
185
						}
193
						}
186
						free(req->path);
194
						free(req->path);
187
						req->path = p;
195
						req->path = p;
188
 
196
 
189
						int incr = 0;
197
						incr = 0;
190
						p = malloc(1);
198
						p = malloc(1);
191
						p[0] = 0;
199
						p[0] = 0;
192
						for(j = 0;; j++) {
200
						for(j = 0;; j++) {
193
							if(req->path[j] == '/' || req->path[j] == 0) {
201
							if(req->path[j] == '/' || req->path[j] == 0) {
194
								char oldc = req->path[j];
202
								char oldc = req->path[j];
-
 
203
								char* pth;
195
								cbuf[0] = oldc;
204
								cbuf[0] = oldc;
196
								req->path[j] = 0;
205
								req->path[j] = 0;
197
 
206
 
198
								char* pth = req->path + incr;
207
								pth = req->path + incr;
199
 
208
 
200
								if(strcmp(pth, "..") == 0) {
209
								if(strcmp(pth, "..") == 0) {
201
									int k;
210
									int k;
202
									if(p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0;
211
									if(p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0;
203
									for(k = strlen(p) - 1; k >= 0; k--) {
212
									for(k = strlen(p) - 1; k >= 0; k--) {
Line 227... Line 236...
227
						cm_log("HTTP", "Request: %s %s %s", req->method, req->path, req->version);
236
						cm_log("HTTP", "Request: %s %s %s", req->method, req->path, req->version);
228
 
237
 
229
						phase++;
238
						phase++;
230
					}
239
					}
231
				} else if(c != '\r') {
240
				} else if(c != '\r') {
-
 
241
					char* tmp;
232
					if(req->version == NULL) {
242
					if(req->version == NULL) {
233
						req->version = malloc(1);
243
						req->version = malloc(1);
234
						req->version[0] = 0;
244
						req->version[0] = 0;
235
					}
245
					}
236
					cbuf[0] = c;
246
					cbuf[0] = c;
237
					char* tmp = req->version;
247
					tmp = req->version;
238
					req->version = cm_strcat(tmp, cbuf);
248
					req->version = cm_strcat(tmp, cbuf);
239
					free(tmp);
249
					free(tmp);
240
				}
250
				}
241
			} else if(phase == 3) {
251
			} else if(phase == 3) {
242
				if(c == '\n') {
252
				if(c == '\n') {
243
					nl++;
253
					nl++;
244
					if(nl == 2) {
254
					if(nl == 2) {
245
						phase++;
255
						phase++;
246
						goto getout;
256
						goto getout;
247
					} else {
257
					} else {
-
 
258
						int j;
248
						if(req->headers == NULL) {
259
						if(req->headers == NULL) {
249
							req->headers = malloc(sizeof(*req->headers));
260
							req->headers = malloc(sizeof(*req->headers));
250
							req->headers[0] = NULL;
261
							req->headers[0] = NULL;
251
						}
262
						}
252
						int j;
-
 
253
						for(j = 0; header[j] != 0; j++) {
263
						for(j = 0; header[j] != 0; j++) {
254
							if(header[j] == ':') {
264
							if(header[j] == ':') {
-
 
265
								char* kv;
-
 
266
								char* vv;
-
 
267
								char** old;
-
 
268
								int k;
255
								header[j] = 0;
269
								header[j] = 0;
256
								j++;
270
								j++;
257
								for(; header[j] != 0 && (header[j] == ' ' || header[j] == '\t'); j++)
271
								for(; header[j] != 0 && (header[j] == ' ' || header[j] == '\t'); j++)
258
									;
272
									;
259
								char* kv = header;
273
								kv = header;
260
								char* vv = header + j;
274
								vv = header + j;
261
 
275
 
262
								char** old = req->headers;
276
								old = req->headers;
263
								int k;
-
 
264
								for(k = 0; old[k] != NULL; k++)
277
								for(k = 0; old[k] != NULL; k++)
265
									;
278
									;
266
								req->headers = malloc(sizeof(*req->headers) * (k + 3));
279
								req->headers = malloc(sizeof(*req->headers) * (k + 3));
267
								for(k = 0; old[k] != NULL; k++) req->headers[k] = old[k];
280
								for(k = 0; old[k] != NULL; k++) req->headers[k] = old[k];
268
								req->headers[k] = cm_strdup(kv);
281
								req->headers[k] = cm_strdup(kv);
Line 278... Line 291...
278
						free(header);
291
						free(header);
279
						header = malloc(1);
292
						header = malloc(1);
280
						header[0] = 0;
293
						header[0] = 0;
281
					}
294
					}
282
				} else if(c != '\r') {
295
				} else if(c != '\r') {
-
 
296
					char* tmp;
283
					nl = 0;
297
					nl = 0;
284
					cbuf[0] = c;
298
					cbuf[0] = c;
285
					char* tmp = header;
299
					tmp = header;
286
					header = cm_strcat(tmp, cbuf);
300
					header = cm_strcat(tmp, cbuf);
287
					free(tmp);
301
					free(tmp);
288
				}
302
				}
289
			}
303
			}
290
		}
304
		}
Line 293... Line 307...
293
	free(header);
307
	free(header);
294
	if(bad) {
308
	if(bad) {
295
		tw_free_request(req);
309
		tw_free_request(req);
296
		return 1;
310
		return 1;
297
	}
311
	}
-
 
312
	{
298
	char* result = malloc(1);
313
		char* result = malloc(1);
299
	result[0] = 0;
314
		int i;
300
	int i;
315
		int j;
-
 
316
		int incr;
-
 
317
		char* p;
-
 
318
		result[0] = 0;
301
	for(i = 0; req->path[i] != 0; i++) {
319
		for(i = 0; req->path[i] != 0; i++) {
302
		if(req->path[i] == '?') {
320
			if(req->path[i] == '?') {
303
			req->path[i] = 0;
321
				req->path[i] = 0;
304
			req->query = cm_strdup(req->path + i + 1);
322
				req->query = cm_strdup(req->path + i + 1);
305
			break;
323
				break;
-
 
324
			}
306
		}
325
		}
307
	}
-
 
308
	for(i = 0; req->path[i] != 0; i++) {
326
		for(i = 0; req->path[i] != 0; i++) {
309
		if(req->path[i] == '%') {
327
			if(req->path[i] == '%') {
310
			if(req->path[i + 1] == 0) continue;
328
				if(req->path[i + 1] == 0) continue;
311
			cbuf[0] = cm_hex(req->path + i + 1, 2);
329
				cbuf[0] = cm_hex(req->path + i + 1, 2);
312
			if(cbuf[0] != '\\') {
330
				if(cbuf[0] != '\\') {
313
				char* tmp = result;
331
					char* tmp = result;
-
 
332
					result = cm_strcat(tmp, cbuf);
-
 
333
					free(tmp);
-
 
334
				}
-
 
335
				i += 2;
-
 
336
			} else if(req->path[i] != '\\') {
-
 
337
				char* tmp;
-
 
338
				cbuf[0] = req->path[i];
-
 
339
				tmp = result;
314
				result = cm_strcat(tmp, cbuf);
340
				result = cm_strcat(tmp, cbuf);
315
				free(tmp);
341
				free(tmp);
316
			}
342
			}
317
			i += 2;
-
 
318
		} else if(req->path[i] != '\\') {
-
 
319
			cbuf[0] = req->path[i];
-
 
320
			char* tmp = result;
-
 
321
			result = cm_strcat(tmp, cbuf);
-
 
322
			free(tmp);
-
 
323
		}
343
		}
324
	}
-
 
325
	free(req->path);
344
		free(req->path);
326
	req->path = result;
345
		req->path = result;
327
 
346
	
328
	int incr = 0;
347
		incr = 0;
329
	char* p = malloc(1);
348
		p = malloc(1);
330
	p[0] = 0;
349
		p[0] = 0;
331
	int j;
-
 
332
	for(j = 0;; j++) {
350
		for(j = 0;; j++) {
333
		if(req->path[j] == '/' || req->path[j] == 0) {
351
			if(req->path[j] == '/' || req->path[j] == 0) {
334
			char oldc = req->path[j];
352
				char oldc = req->path[j];
-
 
353
				char* pth;
335
			cbuf[0] = oldc;
354
				cbuf[0] = oldc;
336
			req->path[j] = 0;
355
				req->path[j] = 0;
337
 
356
	
338
			char* pth = req->path + incr;
357
				pth = req->path + incr;
339
 
358
	
340
			if(strcmp(pth, "..") == 0) {
359
				if(strcmp(pth, "..") == 0) {
341
				int k;
360
					int k;
342
				if(p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0;
361
					if(p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0;
343
				for(k = strlen(p) - 1; k >= 0; k--) {
362
					for(k = strlen(p) - 1; k >= 0; k--) {
344
					if(p[k] == '/') {
363
						if(p[k] == '/') {
345
						p[k + 1] = 0;
364
							p[k + 1] = 0;
346
						break;
365
							break;
-
 
366
						}
347
					}
367
					}
-
 
368
					if(strlen(p) == 0) {
-
 
369
						free(p);
-
 
370
						p = cm_strdup("/");
-
 
371
					}
-
 
372
				} else if(strcmp(pth, ".") == 0) {
-
 
373
				} else {
-
 
374
					char* tmp = p;
-
 
375
					p = cm_strcat3(tmp, pth, cbuf);
-
 
376
					free(tmp);
348
				}
377
				}
349
				if(strlen(p) == 0) {
-
 
350
					free(p);
-
 
351
					p = cm_strdup("/");
-
 
352
				}
378
	
353
			} else if(strcmp(pth, ".") == 0) {
-
 
354
			} else {
-
 
355
				char* tmp = p;
379
				incr = j + 1;
356
				p = cm_strcat3(tmp, pth, cbuf);
-
 
357
				free(tmp);
380
				if(oldc == 0) break;
358
			}
381
			}
359
 
-
 
360
			incr = j + 1;
-
 
361
			if(oldc == 0) break;
-
 
362
		}
382
		}
-
 
383
		free(req->path);
-
 
384
		req->path = p;
-
 
385
		return 0;
363
	}
386
	}
364
	free(req->path);
-
 
365
	req->path = p;
-
 
366
	return 0;
-
 
367
}
387
}