aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Marinelli <stefano@dragas.it>2026-01-06 11:02:36 +0100
committerStefano Marinelli <stefano@dragas.it>2026-01-06 11:02:36 +0100
commit688c54c87355b5424f33f7b089814460a74af594 (patch)
tree03bbe3779173b3d90aede93ea6e41e64869b415b
parentb84b92df74ed0e8f92617e37fdcb2f0aba2138cf (diff)
Implement configurable EXIF stripping for uploaded media
- Add `strip_exif` configuration option to enable metadata removal. - Add `mogrify_path` configuration to specify external tool location. - Implement strip_media using `mogrify -strip`. - Support multiple image formats: jpg, png, webp, heic, heif, avif, tiff, gif, bmp. - Add strict startup check: fail to start if `strip_exif` is enabled but `mogrify` is missing/broken. - Update documentation in `doc/snac.8`.
-rw-r--r--data.c13
-rw-r--r--doc/snac.88
-rw-r--r--snac.c64
-rw-r--r--snac.h3
4 files changed, 86 insertions, 2 deletions
diff --git a/data.c b/data.c
index 22ea7b0..f32dc81 100644
--- a/data.c
+++ b/data.c
@@ -89,8 +89,15 @@ int srv_open(const char *basedir, int auto_upgrade)
else {
if (xs_number_get(xs_dict_get(srv_config, "layout")) < disk_layout)
error = xs_fmt("ERROR: disk layout changed - execute 'snac upgrade' first");
- else
- ret = 1;
+ else {
+ if (!check_strip_tool()) {
+ const char *mp = xs_dict_get(srv_config, "mogrify_path");
+ if (mp == NULL) mp = "mogrify";
+ error = xs_fmt("ERROR: strip_exif enabled but '%s' not found or not working (set 'mogrify_path' in server.json)", mp);
+ }
+ else
+ ret = 1;
+ }
}
}
@@ -2710,6 +2717,8 @@ void static_put(snac *snac, const char *id, const char *data, int size)
if (fn && (f = fopen(fn, "wb")) != NULL) {
fwrite(data, size, 1, f);
fclose(f);
+
+ strip_media(fn);
}
}
diff --git a/doc/snac.8 b/doc/snac.8
index b8a75fa..8283ac6 100644
--- a/doc/snac.8
+++ b/doc/snac.8
@@ -296,6 +296,14 @@ outgoing messages (default: 15). Anyway, whenever any incoming activity from a
failed instance is detected, this counter is reset for it.
.It Ic vkey
Public vapid key. Used for notification on some client.
+.It Ic strip_exif
+If set to true, EXIF metadata will be stripped from uploaded images (jpg, png, webp, heic, avif, tiff, gif, bmp). This requires the
+.Nm mogrify
+tool to be installed. If
+.Nm snac
+cannot find or execute the tool at startup, it will refuse to run.
+.It Ic mogrify_path
+Overrides the default "mogrify" command name or path. Use this if the tool is not in the system PATH or has a different name.
.El
.Pp
You must restart the server to make effective these changes.
diff --git a/snac.c b/snac.c
index 965edbb..f4528cd 100644
--- a/snac.c
+++ b/snac.c
@@ -32,6 +32,7 @@
#include <sys/time.h>
#include <sys/stat.h>
+#include <sys/wait.h>
xs_str *srv_basedir = NULL;
xs_dict *srv_config = NULL;
@@ -170,3 +171,66 @@ int check_password(const char *uid, const char *passwd, const char *hash)
return ret;
}
+
+
+int strip_media(const char *fn)
+/* strips EXIF data from a file */
+{
+ int ret = 0;
+ const xs_val *v = xs_dict_get(srv_config, "strip_exif");
+
+ if (xs_type(v) == XSTYPE_TRUE) {
+ xs *l_fn = xs_tolower_i(xs_dup(fn));
+
+ /* check extensions */
+ if (xs_endswith(l_fn, ".jpg") || xs_endswith(l_fn, ".jpeg") ||
+ xs_endswith(l_fn, ".png") || xs_endswith(l_fn, ".webp") ||
+ xs_endswith(l_fn, ".heic") || xs_endswith(l_fn, ".heif") ||
+ xs_endswith(l_fn, ".avif") || xs_endswith(l_fn, ".tiff") ||
+ xs_endswith(l_fn, ".gif") || xs_endswith(l_fn, ".bmp")) {
+
+ const char *mp = xs_dict_get(srv_config, "mogrify_path");
+ if (mp == NULL)
+ mp = "mogrify";
+
+ xs *cmd = xs_fmt("%s -strip \"%s\" 2>/dev/null", mp, fn);
+
+ ret = system(cmd);
+
+ if (ret != 0) {
+ int code = 0;
+ if (WIFEXITED(ret))
+ code = WEXITSTATUS(ret);
+
+ if (code == 127)
+ srv_log(xs_fmt("strip_media: error stripping %s. '%s' not found (exit 127). Set 'mogrify_path' in server.json.", fn, mp));
+ else
+ srv_log(xs_fmt("strip_media: error stripping %s %d", fn, ret));
+ }
+ else
+ srv_debug(1, xs_fmt("strip_media: stripped %s", fn));
+ }
+ }
+
+ return ret;
+}
+
+
+int check_strip_tool(void)
+{
+ const xs_val *v = xs_dict_get(srv_config, "strip_exif");
+ int ret = 1;
+
+ if (xs_type(v) == XSTYPE_TRUE) {
+ const char *mp = xs_dict_get(srv_config, "mogrify_path");
+ if (mp == NULL)
+ mp = "mogrify";
+
+ xs *cmd = xs_fmt("%s -version 2>/dev/null >/dev/null", mp);
+
+ if (system(cmd) != 0)
+ ret = 0;
+ }
+
+ return ret;
+}
diff --git a/snac.h b/snac.h
index 8a7dad6..c307dbd 100644
--- a/snac.h
+++ b/snac.h
@@ -105,6 +105,9 @@ int validate_uid(const char *uid);
xs_str *hash_password(const char *uid, const char *passwd, const char *nonce);
int check_password(const char *uid, const char *passwd, const char *hash);
+int strip_media(const char *fn);
+int check_strip_tool(void);
+
void srv_archive(const char *direction, const char *url, xs_dict *req,
const char *payload, int p_size,
int status, xs_dict *headers,