diff options
| -rw-r--r-- | http.c | 125 |
1 files changed, 84 insertions, 41 deletions
@@ -63,6 +63,7 @@ struct http_ctx MF_START_BOUNDARY, MF_HEADER_CR_LINE, MF_BODY_BOUNDARY_LINE, + MF_END_BOUNDARY, MF_END_BOUNDARY_CR_LINE } state; @@ -1590,46 +1591,32 @@ static int mf_header_cr_line(struct http_ctx *const h) return 0; } -static int end_boundary_line(struct http_ctx *const h) +static int end_boundary(struct http_ctx *const h) { - const char *const line = h->line; + /* Found end boundary. */ + struct ctx *const c = &h->ctx; + struct multiform *const m = &c->u.mf; - if (!*line) + const struct http_payload p = { - h->ctx.u.mf.state = MF_HEADER_CR_LINE; - return 0; - } - else if (!strcmp(line, "--")) - { - /* Found end boundary. */ - struct ctx *const c = &h->ctx; - struct multiform *const m = &c->u.mf; - - const struct http_payload p = + .cookie = { - .cookie = - { - .field = c->field, - .value = c->value - }, - - .op = c->op, - .resource = c->resource, - .u.post = - { - .files = m->files, - .pairs = m->pairs, - .nfiles = m->nfiles, - .npairs = m->npairs - } - }; + .field = c->field, + .value = c->value + }, - return send_payload(h, &p); - } + .op = c->op, + .resource = c->resource, + .u.post = + { + .files = m->files, + .pairs = m->pairs, + .nfiles = m->nfiles, + .npairs = m->npairs + } + }; - fprintf(stderr, "%s: unexpected line after boundary: %s\n", - __func__, line); - return 1; + return send_payload(h, &p); } static int process_mf_line(struct http_ctx *const h) @@ -1637,8 +1624,7 @@ static int process_mf_line(struct http_ctx *const h) static int (*const state[])(struct http_ctx *) = { [MF_START_BOUNDARY] = start_boundary_line, - [MF_HEADER_CR_LINE] = mf_header_cr_line, - [MF_END_BOUNDARY_CR_LINE] = end_boundary_line + [MF_HEADER_CR_LINE] = mf_header_cr_line }; h->ctx.payload.read += strlen(h->line) + strlen("\r\n"); @@ -1827,7 +1813,7 @@ static bool name_exists(const struct multiform *const m, if (!strcmp(f->name, p->name)) { fprintf(stderr, "%s: \"%s\" defined more than once\n", - f->name, __func__); + __func__, f->name); return true; } } @@ -1893,7 +1879,7 @@ static int read_mf_body_boundary_byte(struct http_ctx *const h, const char b, memset(m->boundary, '\0', clen); m->blen = 0; - m->state = MF_END_BOUNDARY_CR_LINE; + m->state = MF_END_BOUNDARY; m->written = 0; return ret; } @@ -1991,6 +1977,53 @@ static int read_mf_body_boundary(struct http_ctx *const h, return 0; } +static int read_mf_end_boundary(struct http_ctx *const h, + const char *const buf, size_t *const n) +{ + struct ctx *const c = &h->ctx; + struct multiform *const m = &c->u.mf; + static const char end[] = "--", crlf[] = "\r\n"; + const bool check = c->len >= strlen(end) || c->len >= strlen(crlf); + + h->line[c->len++] = *buf; + (*n)--; + + if (c->len >= strlen(end) && !strncmp(h->line, end, strlen(end))) + { + c->len = 0; + + /* Found end boundary. */ + if (!*n) + return end_boundary(h); + else + m->state = MF_END_BOUNDARY_CR_LINE; + } + else if (c->len >= strlen(crlf) && !strncmp(h->line, crlf, strlen(crlf))) + { + c->len = 0; + m->state = MF_HEADER_CR_LINE; + } + else if (check) + { + fprintf(stderr, "%s: unexpected boundary delimiter: %.*s\n", + __func__, (int)c->len, h->line); + return 1; + } + + return 0; +} + +static int process_mf_end_crlf(struct http_ctx *const h) +{ + if (*h->line) + { + fprintf(stderr, "%s: expected empty line\n", __func__); + return 1; + } + + return end_boundary(h); +} + static int read_multiform(struct http_ctx *const h, const char *const buf, size_t *const sz) { @@ -2002,9 +2035,7 @@ static int read_multiform(struct http_ctx *const h, const char *const buf, case MF_START_BOUNDARY: /* Fall through. */ case MF_HEADER_CR_LINE: - /* Fall through. */ - case MF_END_BOUNDARY_CR_LINE: - if ((res = update_lstate(h, close, process_mf_line, buf, sz))) + if ((res = update_lstate(h, process_mf_line, buf, sz))) return res; break; @@ -2014,6 +2045,18 @@ static int read_multiform(struct http_ctx *const h, const char *const buf, return res; break; + + case MF_END_BOUNDARY: + if ((res = read_mf_end_boundary(h, buf, sz))) + return res; + + break; + + case MF_END_BOUNDARY_CR_LINE: + if ((res = update_lstate(h, process_mf_end_crlf, buf, sz))) + return res; + + break; } return 0; |
