aboutsummaryrefslogtreecommitdiff
path: root/page.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-10-06 23:02:51 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-10-08 02:03:05 +0200
commit00dd37604d50cbf3fb27ec0631b4d4b6d2ee893a (patch)
tree81f9546b168078aa9bf54d4298aa76e99bb229af /page.c
parent4ab3ee681607f0cc75cf56e4fcbeae85594bb630 (diff)
downloadslcl-00dd37604d50cbf3fb27ec0631b4d4b6d2ee893a.tar.gz
Implement directory download as ZIP
Thanks to the fdzipstream library [1] and zlib [2], it is possible to generate ZIP files on-the-fly, therefore requiring no extra disk space usage and only a small amount of memory. Unfortunately, as of the time of this writing fdzipstream is not packaged by any distributions yet [3], so it had to be imported as a git submodule as a workaround. While libarchive [4] could be an interesting alternative, writing ZIP files is only supported by very recent versions (>= 3.8.0), which are still not packaged by many distributions [5], either. Moreover, libarchive is a package with several dependencies other than zlib and is significantly larger compared to fdzipstreams, so fdzipstreams was ultimately considered a better fit for this purpose. [1]: https://github.com/CTrabant/fdzipstream.git [2]: http://zlib.net/ [3]: https://repology.org/projects/?search=fdzipstream [4]: https://www.libarchive.org/ [5]: https://repology.org/project/libarchive/versions
Diffstat (limited to 'page.c')
-rw-r--r--page.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/page.c b/page.c
index af24e70..9d1ea8e 100644
--- a/page.c
+++ b/page.c
@@ -1,6 +1,7 @@
#define _POSIX_C_SOURCE 200809L
#include "page.h"
+#include "zip.h"
#include <libweb/html.h>
#include <libweb/http.h>
#include <dynstr.h>
@@ -1812,6 +1813,21 @@ static bool preview(const struct page_resource *const pr)
return false;
}
+static bool download(const struct page_resource *const pr)
+{
+ for (size_t i = 0; i < pr->n_args; i++)
+ {
+ const struct http_arg *const a = &pr->args[i];
+
+ if (!strcmp(a->key, "download")
+ && (!strcmp(a->value, "1")
+ || !strcasecmp(a->value, "true")))
+ return true;
+ }
+
+ return false;
+}
+
int page_resource(const struct page_resource *const pr)
{
int ret = -1;
@@ -1840,7 +1856,15 @@ int page_resource(const struct page_resource *const pr)
if (S_ISDIR(m))
{
- if ((ret = list_dir(pr)))
+ if (download(pr))
+ {
+ if ((ret = zip(pr->res, pr->r)))
+ {
+ fprintf(stderr, "%s: zip_dir failed\n", __func__);
+ goto end;
+ }
+ }
+ else if ((ret = list_dir(pr)))
{
if (ret < 0)
{