aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http.c125
1 files changed, 84 insertions, 41 deletions
diff --git a/http.c b/http.c
index bc269a7..e9b50ac 100644
--- a/http.c
+++ b/http.c
@@ -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;