embox

Форк
0
/
multipart_formdata.c 
141 строка · 2.9 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @author  Anton Kozlov
6
 * @date    18.02.2015
7
 */
8

9
#include <stdlib.h>
10
#include <stdbool.h>
11
#include <string.h>
12
#include <errno.h>
13
#include <stdio.h>
14
#include <unistd.h>
15
#include <fcntl.h>
16
#include <util/math.h>
17
#include <framework/mod/options.h>
18

19
#define MPFD_BASE OPTION_STRING_GET(base)
20
#define MPFD_BASE_LEN strlen(MPFD_BASE)
21

22
#define BUFF_SZ 1024
23
static char mpfd_g_buf[BUFF_SZ];
24

25
struct parseenv {
26
	char *pb;
27
	int blen;
28
};
29

30
static char *strstrp(const char *s, const char *h) {
31
	char *f = strstr(s, h);
32
	if (f) {
33
		return f + strlen(h);
34
	}
35
	return f;
36
}
37

38
static int mpfd_expect(struct parseenv *pe, const char *s) {
39
	int slen = strlen(s);
40
	if (0 != strncmp(pe->pb, s, slen)) {
41
		return 0;
42
	}
43
	pe->pb += slen;
44
	pe->blen -= slen;
45
	return 1;
46
}
47

48
static char *mpfd_store_till(struct parseenv *pe, const char *s, size_t *ssize) {
49
	char *found = strstr(pe->pb, s);
50
	char *pb = pe->pb;
51
	int slen = strlen(s);
52

53
	if (!found) {
54
		return NULL;
55
	}
56

57
	if (*ssize) {
58
		*ssize = found - pb;
59
	}
60

61
	pe->blen -= found - pb + slen;
62
	pe->pb = found + slen;
63

64
	return pb;
65
}
66

67
static int mpfd_skip_till(struct parseenv *pe, const char *s) {
68
	return !!mpfd_store_till(pe, s, NULL);
69
}
70

71
static int mpfd_parse(struct parseenv *pe, const char *bound, char *fname, size_t fname_len) {
72
	char *filename;
73
	size_t filenamelen;
74
	int pres = mpfd_expect(pe, "--") &&
75
		mpfd_expect(pe, bound) &&
76
		mpfd_expect(pe, "\r\nContent-Disposition: form-data; name=\"") &&
77
		mpfd_store_till(pe, "\"; filename=\"", NULL) &&
78
		(filename = mpfd_store_till(pe, "\"\r\n", &filenamelen)) &&
79
		mpfd_skip_till(pe, "\r\n\r\n");
80

81
	if (pres) {
82
		*(filename + filenamelen) = '\0';
83
		strncat(fname, filename, fname_len);
84
	}
85

86
	return pres;
87
}
88

89
int main(int argc, char *argv[]) {
90
	char *method;
91

92
	method = getenv("REQUEST_METHOD");
93
	if (0 == strcmp("POST", method)) {
94
		struct parseenv _pe;
95
		char *bound = strstrp(getenv("CONTENT_TYPE"), "boundary=");
96
		int clen = atoi(getenv("CONTENT_LENGTH"));
97
		char path[64];
98
		int httpcode;
99
		int fd;
100

101
		/* not going to read footer */
102
		clen -= strlen("\r\n--") + strlen(bound) + strlen("--\r\n");
103

104
		_pe.pb = mpfd_g_buf;
105
		_pe.blen = read(STDIN_FILENO, mpfd_g_buf, min(BUFF_SZ, clen));
106
		clen -= _pe.blen;
107
		strncpy(path, MPFD_BASE, sizeof(path));
108

109
		if (!mpfd_parse(&_pe, bound, path + MPFD_BASE_LEN, sizeof(path) - MPFD_BASE_LEN)) {
110
			fprintf(stderr, "parse_error\n");
111
			httpcode = 500;
112
			goto out_header;
113
		}
114

115
		fd = open(path, O_WRONLY | O_CREAT, 0755);
116
		if (fd < 0) {
117
			fprintf(stderr, "can't open output file %s: %s\n", path, strerror(errno));
118
			httpcode = 500;
119
			goto out_header;
120
		}
121

122
		write(fd, _pe.pb, _pe.blen);
123
		while (clen > 0) {
124
			int len = read(STDIN_FILENO, mpfd_g_buf, min(BUFF_SZ, clen));
125
			write(fd, mpfd_g_buf, len);
126
			clen -= len;
127
			sleep(0);
128
		}
129
		close(fd);
130

131
		httpcode = 200;
132
out_header:
133
		printf("HTTP/1.1 %d %s\r\n"
134
			"Content-Type: %s\r\n"
135
			"Connection: close\r\n"
136
			"\r\n", httpcode, "OK", "text/plain");
137
		fflush(stdout);
138
	}
139

140
	return 0;
141
}
142

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.