|
|
|
@ -961,6 +961,15 @@ static char *next_line(char *str) {
|
|
|
|
|
return nextline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *parse_header(char *line) {
|
|
|
|
|
char *value = strchr(line, ':');
|
|
|
|
|
if (value != NULL) {
|
|
|
|
|
*value++ = '\0';
|
|
|
|
|
while (*value == ' ') value++;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int http_serve_index(struct http_request *req) {
|
|
|
|
|
write_buf(req->fd, "HTTP/1.0 200 OK\r\nConnection: close\r\n\r\n");
|
|
|
|
|
close(req->fd);
|
|
|
|
@ -990,42 +999,48 @@ static int parse_multipart(struct http_request *req) {
|
|
|
|
|
req->len = len;
|
|
|
|
|
}
|
|
|
|
|
req->data[req->len] = '\0';
|
|
|
|
|
char *boundary_start = NULL;
|
|
|
|
|
while (req->len > 0) {
|
|
|
|
|
boundary_start = strstr(req->data, req->multipart_boundary);
|
|
|
|
|
if (boundary_start == NULL) return -1;
|
|
|
|
|
boundary_start += boundary_len;
|
|
|
|
|
char *line = boundary_start;
|
|
|
|
|
|
|
|
|
|
// iterate through parts
|
|
|
|
|
char *part, *next;
|
|
|
|
|
const char *boundary = req->multipart_boundary;
|
|
|
|
|
for (part = strstr(req->data, boundary); part != NULL; part = next) {
|
|
|
|
|
part += boundary_len;
|
|
|
|
|
if (part[0] == '-' && part[1] == '-') break; // end of parts
|
|
|
|
|
if (*part == '\r') part++;
|
|
|
|
|
if (*part == '\n') part++;
|
|
|
|
|
next = strstr(part, req->multipart_boundary);
|
|
|
|
|
char *end = next;
|
|
|
|
|
if (end != NULL) {
|
|
|
|
|
if (end[-1] == '\n') end--;
|
|
|
|
|
if (end[-1] == '\r') end--;
|
|
|
|
|
*end = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// iterate through headers in part
|
|
|
|
|
char *line, *nextline;
|
|
|
|
|
char *cdisp = NULL;
|
|
|
|
|
bool is_text = false;
|
|
|
|
|
if (*line == '\r') line++;
|
|
|
|
|
if (*line == '\n') line++;
|
|
|
|
|
char *nextline;
|
|
|
|
|
while (line != NULL) {
|
|
|
|
|
for (line = part; line != NULL; line = nextline) {
|
|
|
|
|
nextline = next_line(line);
|
|
|
|
|
if (!line[0]) break;
|
|
|
|
|
if (!*line) break; // end of headers
|
|
|
|
|
char *name = line;
|
|
|
|
|
char *value = strchr(line, ':');
|
|
|
|
|
if (value != NULL) {
|
|
|
|
|
*value++ = '\0';
|
|
|
|
|
while (*value == ' ') value++;
|
|
|
|
|
}
|
|
|
|
|
char *value = parse_header(line);
|
|
|
|
|
if (!strncmp(name, "Content-Disposition", 3)) cdisp = value;
|
|
|
|
|
line = nextline;
|
|
|
|
|
}
|
|
|
|
|
if (cdisp != NULL && !strcmp(cdisp, "form-data; name=\"text\"")) {
|
|
|
|
|
is_text = true;
|
|
|
|
|
char *name = NULL;
|
|
|
|
|
if (cdisp != NULL && !strncmp(cdisp, "form-data; name=\"", 17)) {
|
|
|
|
|
name = cdisp + 17;
|
|
|
|
|
char *end = strchr(name, '"');
|
|
|
|
|
if (end != NULL) *end = '\0';
|
|
|
|
|
}
|
|
|
|
|
req->len -= nextline - req->data;
|
|
|
|
|
req->data = nextline;
|
|
|
|
|
|
|
|
|
|
char *end = strstr(nextline, req->multipart_boundary);
|
|
|
|
|
if (end == NULL || strncmp(end + boundary_len, "--", 2)) return -1;
|
|
|
|
|
if (end[-1] == '\n') end--;
|
|
|
|
|
if (end[-1] == '\r') end--;
|
|
|
|
|
*end = '\0';
|
|
|
|
|
req->len = end - nextline;
|
|
|
|
|
if (is_text) break;
|
|
|
|
|
// handle part body
|
|
|
|
|
char *body = nextline;
|
|
|
|
|
if (body == NULL) continue;
|
|
|
|
|
|
|
|
|
|
if (!strcmp(name, "text")) {
|
|
|
|
|
req->data = body;
|
|
|
|
|
req->len = end == NULL ? strlen(body) : end - body;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -1181,11 +1196,7 @@ static int handle_http_client(int fd, int firstchar) {
|
|
|
|
|
nextline = next_line(line);
|
|
|
|
|
if (!line[0]) break;
|
|
|
|
|
char *name = line;
|
|
|
|
|
char *value = strchr(line, ':');
|
|
|
|
|
if (value != NULL) {
|
|
|
|
|
*value++ = '\0';
|
|
|
|
|
while (*value == ' ') value++;
|
|
|
|
|
}
|
|
|
|
|
char *value = parse_header(line);
|
|
|
|
|
if (!strncmp(name, "Host", 3)) req.host = value;
|
|
|
|
|
else if (!strncmp(name, "Referer", 7)) req.referer = value;
|
|
|
|
|
else if (!strncmp(name, "Content-Length", 14)) req.content_length = atoi(value);
|
|
|
|
|