aboutsummaryrefslogtreecommitdiff
path: root/http.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-09-09 00:19:39 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-09-09 00:21:42 +0200
commit09909c0a3b326efd6a2b87df95d0e73c1e394c29 (patch)
treef7ec05f2bb1e9b621d5d2af10354c8ffe31f0ce4 /http.c
parent6c7faa7f9063aca15345c9aeb95d651a5fe983f9 (diff)
http: Allow multiple non-file Content-Disposition
Now, slweb accepts requests such as: --boundary Content-Disposition: form-data; name="field1" value1 --boundary Content-Disposition: form-data; name="field2" value2 --boundary Content-Disposition: form-data; name="field3"; filename="example.txt" The following breaking changes have been introduced: Member "dir" from struct http_post was a leftover from the days where slcl and slweb were one project. It did not make sense for slweb, since it should not decide which Content-Disposition names are allowed. In other words, "dir" was only relevant in the scope of slcl. Member "n" from struct http_post used to have two meanings: - The length of a URL-encoded request. - The number of files on a multipart/form-data request. Since "npairs" had to be introduced to struct http_post, it did not make sense to keep this dual meaning any more. Therefore, "n" has been restricted to the former, whereas a new member, called "nfiles", has been introduced for the latter.
Diffstat (limited to 'http.c')
-rw-r--r--http.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/http.c b/http.c
index 13790b8..e239972 100644
--- a/http.c
+++ b/http.c
@@ -75,10 +75,10 @@ struct http_ctx
off_t len, written;
char *boundary;
- const char *dir;
- size_t blen, nforms, nfiles;
+ size_t blen, nforms, nfiles, npairs;
int fd;
struct http_post_file *files;
+ struct http_post_pair *pairs;
struct form
{
@@ -435,6 +435,7 @@ static void ctx_free(struct ctx *const c)
struct multiform *const m = &c->u.mf;
free(m->files);
+ free(m->pairs);
free(m->boundary);
if (m->fd >= 0 && close(m->fd))
@@ -1338,9 +1339,10 @@ static int end_boundary_line(struct http_ctx *const h)
.resource = c->resource,
.u.post =
{
- .dir = m->dir,
.files = m->files,
- .n = m->nfiles
+ .pairs = m->pairs,
+ .nfiles = m->nfiles,
+ .npairs = m->npairs
}
};
@@ -1495,26 +1497,52 @@ static int apply_from_file(struct http_ctx *const h, struct form *const f)
return 0;
}
+static bool name_exists(const struct multiform *const m,
+ const struct form *const f)
+{
+ for (size_t i = 0; i < m->npairs; i++)
+ {
+ const struct http_post_pair *const p = &m->pairs[i];
+
+ if (!strcmp(f->name, p->name))
+ {
+ fprintf(stderr, "%s: \"%s\" defined more than once\n",
+ f->name, __func__);
+ return true;
+ }
+ }
+
+ return false;
+}
+
static int apply_from_mem(struct http_ctx *const h, struct form *const f)
{
struct multiform *const m = &h->ctx.u.mf;
+ if (name_exists(m, f))
+ return 1;
+
+ struct http_post_pair *pairs, *p;
+ const size_t n = m->npairs + 1;
+
if (!(f->value = strndup(h->line, m->written)))
{
fprintf(stderr, "%s: strndup(3): %s\n", __func__, strerror(errno));
return -1;
}
- else if (!strcmp(f->name, "dir"))
+ else if (!(pairs = realloc(m->pairs, n * sizeof *m->pairs)))
{
- if (m->dir)
- {
- fprintf(stderr, "%s: \"dir\" defined more than once\n", __func__);
- return 1;
- }
-
- m->dir = f->value;
+ fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
+ return -1;
}
+ pairs[m->npairs++] = (const struct http_post_pair)
+ {
+ .name = f->name,
+ .value = f->value
+ };
+
+ m->pairs = pairs;
return 0;
}