aboutsummaryrefslogtreecommitdiff
path: root/page.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-03-20 03:32:00 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-03-20 10:57:20 +0100
commitd9bb874591c63f2efbfc1c4c953934251c700e9f (patch)
tree88254b346628a22ece5a4ede5f411458969720c0 /page.c
parentd51b191ab7005de6679a00dd200ad5502ecff5ac (diff)
downloadslcl-d9bb874591c63f2efbfc1c4c953934251c700e9f.tar.gz
Send response on quota exceeded
So far, slcl would just close the connection with a client when the Content-Length of an incoming request exceeded the user quota, without any meaningful information given back to the user. Now, slcl responds with a HTML file with meaningful information about the error. Limitations: - While this commits has been successfully tested on ungoogled-chromium, LibreWolf (and I assume Firefox and any other derivates too) does not seem to receive the response from the server. - However, this issue only occurred during local testing, but not on remote instances.
Diffstat (limited to 'page.c')
-rw-r--r--page.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/page.c b/page.c
index 17adb8a..5cbb0a7 100644
--- a/page.c
+++ b/page.c
@@ -1311,3 +1311,93 @@ end:
return ret;
}
+
+int page_quota_exceeded(struct http_response *const r,
+ const unsigned long long len, const unsigned long long quota)
+{
+ int ret = -1;
+ struct dynstr msg, out;
+ char q[sizeof MAXSIZEFMT], l[sizeof q];
+ struct html_node *const html = html_node_alloc("html"),
+ *head, *body;
+
+ dynstr_init(&msg);
+ dynstr_init(&out);
+
+ if (!html)
+ {
+ fprintf(stderr, "%s: html_node_alloc failed\n", __func__);
+ goto end;
+ }
+ else if (!(head = html_node_add_child(html, "head")))
+ {
+ fprintf(stderr, "%s: html_node_add_child head failed\n", __func__);
+ goto end;
+ }
+ else if (!(body = html_node_add_child(html, "body")))
+ {
+ fprintf(stderr, "%s: html_node_add_child body failed\n", __func__);
+ goto end;
+ }
+ else if (common_head(head, NULL))
+ {
+ fprintf(stderr, "%s: common_head failed\n", __func__);
+ goto end;
+ }
+ else if (size_units(quota, q, sizeof q))
+ {
+ fprintf(stderr, "%s: size_units quota failed\n", __func__);
+ goto end;
+ }
+ else if (size_units(len, l, sizeof l))
+ {
+ fprintf(stderr, "%s: size_units len failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_append(&msg, "Maximum quota exceeded: %s "
+ "(requested size: %s)", q, l))
+ {
+ fprintf(stderr, "%s: dynstr_append msg failed\n", __func__);
+ goto end;
+ }
+ else if (html_node_set_value(body, msg.str))
+ {
+ fprintf(stderr, "%s: html_node_set_value msg failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_append(&out, DOCTYPE_TAG))
+ {
+ fprintf(stderr, "%s: dynstr_prepend failed\n", __func__);
+ goto end;
+ }
+ else if (html_serialize(html, &out))
+ {
+ fprintf(stderr, "%s: html_serialize failed\n", __func__);
+ goto end;
+ }
+
+ *r = (const struct http_response)
+ {
+ .status = HTTP_STATUS_PAYLOAD_TOO_LARGE,
+ .buf.rw = out.str,
+ .n = out.len,
+ .free = free
+ };
+
+ if (http_response_add_header(r, "Content-Type", "text/html"))
+ {
+ fprintf(stderr, "%s: http_response_add_header failed\n", __func__);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ html_node_free(html);
+ dynstr_free(&msg);
+
+ if (ret)
+ dynstr_free(&out);
+
+ return ret;
+}