Support Exiftool for stripping EXIF data
authorMark Felder <feld@FreeBSD.org>
Fri, 10 Jul 2020 21:46:26 +0000 (16:46 -0500)
committerMark Felder <feld@FreeBSD.org>
Fri, 10 Jul 2020 21:46:26 +0000 (16:46 -0500)
We really only want to strip location data anyway, and mogrify strips color profiles.

.gitignore
.gitlab-ci.yml
CHANGELOG.md
Dockerfile
docs/configuration/cheatsheet.md
lib/pleroma/upload/filter/exiftool.ex [new file with mode: 0644]
test/fixtures/DSCN0010.jpg [new file with mode: 0644]
test/upload/filter/exiftool_test.exs [new file with mode: 0644]

index 198e801399757dda814145f3458d194f88bb363d..599b52b9e0b8f2084a889bb9aca56ca0dec76e01 100644 (file)
@@ -5,6 +5,7 @@
 /*.ez
 /test/uploads
 /.elixir_ls
+/test/fixtures/DSCN0010_tmp.jpg
 /test/fixtures/test_tmp.txt
 /test/fixtures/image_tmp.jpg
 /test/tmp/
index 6a2be879e6c803c6bac4076f62976a9cef73b209..c9ab848926f21debe460cee18509380aefdc3ffb 100644 (file)
@@ -58,6 +58,7 @@ unit-testing:
     alias: postgres
     command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
   script:
+    - apt-get update && apt-get install -y libimage-exiftool-perl
     - mix deps.get
     - mix ecto.create
     - mix ecto.migrate
@@ -89,6 +90,7 @@ unit-testing-rum:
     <<: *global_variables
     RUM_ENABLED: "true"
   script:
+    - apt-get update && apt-get install -y libimage-exiftool-perl
     - mix deps.get
     - mix ecto.create
     - mix ecto.migrate
index 9e928528a6cdca1a7d027d1e03f9be9ee7c91da0..5fed80a99e08775e4fdecbbfca297a964b311aea 100644 (file)
@@ -57,6 +57,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - MRF (`EmojiStealPolicy`): New MRF Policy which allows to automatically download emojis from remote instances
 - Support pagination in emoji packs API (for packs and for files in pack)
 - Support for viewing instances favicons next to posts and accounts
+- Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata.
 
 <details>
   <summary>API Changes</summary>
index 29931a5e3a398cd2fef9cb0e244da7db5725ce1f..0f4fcd0bb271c18fde7a9dbb30a319fc18e7f423 100644 (file)
@@ -33,7 +33,7 @@ ARG DATA=/var/lib/pleroma
 
 RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
        apk update &&\
-       apk add imagemagick ncurses postgresql-client &&\
+       apk add exiftool imagemagick ncurses postgresql-client &&\
        adduser --system --shell /bin/false --home ${HOME} pleroma &&\
        mkdir -p ${DATA}/uploads &&\
        mkdir -p ${DATA}/static &&\
index 1a06038925008d3bca3b29d18943b138cc1287ee..f796330f1080b10ee80fbaa3c9a9684ab5477ee5 100644 (file)
@@ -548,20 +548,26 @@ config :ex_aws, :s3,
 
 ### Upload filters
 
-#### Pleroma.Upload.Filter.Mogrify
+#### Pleroma.Upload.Filter.AnonymizeFilename
 
-* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
+This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
+`Pleroma.Upload.Filter.Dedupe` before AnonymizeFilename.
+
+* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used. You can get the original filename extension by using `{extension}`, for example `custom-file-name.{extension}`.
 
 #### Pleroma.Upload.Filter.Dedupe
 
 No specific configuration.
 
-#### Pleroma.Upload.Filter.AnonymizeFilename
+#### Pleroma.Upload.Filter.Exiftool
 
-This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
-`Pleroma.Upload.Filter.Dedupe` before AnonymizeFilename.
+This filter only strips the GPS and location metadata with Exiftool leaving color profiles and attributes intact.
 
-* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used. You can get the original filename extension by using `{extension}`, for example `custom-file-name.{extension}`.
+No specific configuration.
+
+#### Pleroma.Upload.Filter.Mogrify
+
+* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
 
 ## Email
 
diff --git a/lib/pleroma/upload/filter/exiftool.ex b/lib/pleroma/upload/filter/exiftool.ex
new file mode 100644 (file)
index 0000000..833d8ca
--- /dev/null
@@ -0,0 +1,17 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Upload.Filter.Exiftool do
+  @behaviour Pleroma.Upload.Filter
+
+  @type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()}
+  @type conversions :: conversion() | [conversion()]
+
+  def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do
+    System.cmd("exiftool", ["-overwrite_original", "-gps:all=", file], parallelism: true)
+    :ok
+  end
+
+  def filter(_), do: :ok
+end
diff --git a/test/fixtures/DSCN0010.jpg b/test/fixtures/DSCN0010.jpg
new file mode 100644 (file)
index 0000000..4a2c155
Binary files /dev/null and b/test/fixtures/DSCN0010.jpg differ
diff --git a/test/upload/filter/exiftool_test.exs b/test/upload/filter/exiftool_test.exs
new file mode 100644 (file)
index 0000000..a1b7e46
--- /dev/null
@@ -0,0 +1,31 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Upload.Filter.ExiftoolTest do
+  use Pleroma.DataCase
+  alias Pleroma.Upload.Filter
+
+  test "apply exiftool filter" do
+    File.cp!(
+      "test/fixtures/DSCN0010.jpg",
+      "test/fixtures/DSCN0010_tmp.jpg"
+    )
+
+    upload = %Pleroma.Upload{
+      name: "image_with_GPS_data.jpg",
+      content_type: "image/jpg",
+      path: Path.absname("test/fixtures/DSCN0010.jpg"),
+      tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg")
+    }
+
+    assert Filter.Exiftool.filter(upload) == :ok
+
+    {exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"])
+    {exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"])
+
+    refute exif_original == exif_filtered
+    assert String.match?(exif_original, ~r/GPS/)
+    refute String.match?(exif_filtered, ~r/GPS/)
+  end
+end