aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/pleroma/instance.ex26
-rw-r--r--lib/pleroma/application_requirements.ex1
-rw-r--r--lib/pleroma/upload.ex27
-rw-r--r--lib/pleroma/upload/filter/exiftool_read_data.ex47
4 files changed, 94 insertions, 7 deletions
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index f292fc762..d206e1622 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -35,6 +35,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
listen_ip: :string,
listen_port: :string,
strip_uploads: :string,
+ read_uploads_data: :string,
anonymize_uploads: :string,
dedupe_uploads: :string
],
@@ -178,6 +179,23 @@ defmodule Mix.Tasks.Pleroma.Instance do
strip_uploads_default
) === "y"
+ {read_uploads_data_message, read_uploads_data_default} =
+ if Pleroma.Utils.command_available?("exiftool") do
+ {"Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as installed. (y/n)",
+ "y"}
+ else
+ {"Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as not installed, please install it if you answer yes. (y/n)",
+ "n"}
+ end
+
+ read_uploads_data =
+ get_option(
+ options,
+ :read_uploads_data,
+ read_uploads_data_message,
+ read_uploads_data_default
+ ) === "y"
+
anonymize_uploads =
get_option(
options,
@@ -230,6 +248,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
upload_filters:
upload_filters(%{
strip: strip_uploads,
+ read_data: read_uploads_data,
anonymize: anonymize_uploads,
dedupe: dedupe_uploads
})
@@ -304,6 +323,13 @@ defmodule Mix.Tasks.Pleroma.Instance do
end
enabled_filters =
+ if filters.read_data do
+ enabled_filters ++ [Pleroma.Upload.Filter.ExiftoolReadData]
+ else
+ enabled_filters
+ end
+
+ enabled_filters =
if filters.anonymize do
enabled_filters ++ [Pleroma.Upload.Filter.AnonymizeFilename]
else
diff --git a/lib/pleroma/application_requirements.ex b/lib/pleroma/application_requirements.ex
index 06d388694..ea1ee71c0 100644
--- a/lib/pleroma/application_requirements.ex
+++ b/lib/pleroma/application_requirements.ex
@@ -165,6 +165,7 @@ defmodule Pleroma.ApplicationRequirements do
defp check_system_commands!(:ok) do
filter_commands_statuses = [
check_filter(Pleroma.Upload.Filter.Exiftool, "exiftool"),
+ check_filter(Pleroma.Upload.Filter.ExiftoolReadData, "exiftool"),
check_filter(Pleroma.Upload.Filter.Mogrify, "mogrify"),
check_filter(Pleroma.Upload.Filter.Mogrifun, "mogrify"),
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "mogrify"),
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 242813dcd..db2909276 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -60,12 +60,23 @@ defmodule Pleroma.Upload do
width: integer(),
height: integer(),
blurhash: String.t(),
+ description: String.t(),
path: String.t()
}
- defstruct [:id, :name, :tempfile, :content_type, :width, :height, :blurhash, :path]
-
- defp get_description(opts, upload) do
- case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do
+ defstruct [
+ :id,
+ :name,
+ :tempfile,
+ :content_type,
+ :width,
+ :height,
+ :blurhash,
+ :description,
+ :path
+ ]
+
+ defp get_description(upload) do
+ case {upload.description, Pleroma.Config.get([Pleroma.Upload, :default_description])} do
{description, _} when is_binary(description) -> description
{_, :filename} -> upload.name
{_, str} when is_binary(str) -> str
@@ -81,7 +92,7 @@ defmodule Pleroma.Upload do
with {:ok, upload} <- prepare_upload(upload, opts),
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
- description = get_description(opts, upload),
+ description = get_description(upload),
{_, true} <-
{:description_limit,
String.length(description) <= Pleroma.Config.get([:instance, :description_limit])},
@@ -152,7 +163,8 @@ defmodule Pleroma.Upload do
id: UUID.generate(),
name: file.filename,
tempfile: file.path,
- content_type: file.content_type
+ content_type: file.content_type,
+ description: opts.description
}}
end
end
@@ -172,7 +184,8 @@ defmodule Pleroma.Upload do
id: UUID.generate(),
name: hash <> "." <> ext,
tempfile: tmp_path,
- content_type: content_type
+ content_type: content_type,
+ description: opts.description
}}
end
end
diff --git a/lib/pleroma/upload/filter/exiftool_read_data.ex b/lib/pleroma/upload/filter/exiftool_read_data.ex
new file mode 100644
index 000000000..c8bedfbf8
--- /dev/null
+++ b/lib/pleroma/upload/filter/exiftool_read_data.ex
@@ -0,0 +1,47 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Upload.Filter.ExiftoolReadData do
+ @moduledoc """
+ Gets the description from the related EXIF tags and provides them in the response if no description is provided yet.
+ It will first check ImageDescription, when that's too long or empty, it will check iptc:Caption-Abstract.
+ When the description is too long (see `:instance, :description_limit`), an empty string is returned.
+ """
+ @behaviour Pleroma.Upload.Filter
+
+ @spec filter(Pleroma.Upload.t()) :: {:ok, any()} | {:error, String.t()}
+
+ def filter(%Pleroma.Upload{description: description})
+ when is_binary(description),
+ do: {:ok, :noop}
+
+ def filter(%Pleroma.Upload{tempfile: file} = upload),
+ do: {:ok, :filtered, upload |> Map.put(:description, read_description_from_exif_data(file))}
+
+ def filter(_, _), do: {:ok, :noop}
+
+ defp read_description_from_exif_data(file) do
+ nil
+ |> read_when_empty(file, "-ImageDescription")
+ |> read_when_empty(file, "-iptc:Caption-Abstract")
+ end
+
+ defp read_when_empty(current_description, _, _) when is_binary(current_description),
+ do: current_description
+
+ defp read_when_empty(_, file, tag) do
+ try do
+ {tag_content, 0} =
+ System.cmd("exiftool", ["-b", "-s3", tag, file], stderr_to_stdout: true, parallelism: true)
+
+ if tag_content != "" and
+ String.length(tag_content) <=
+ Pleroma.Config.get([:instance, :description_limit]),
+ do: tag_content,
+ else: nil
+ rescue
+ _ in ErlangError -> nil
+ end
+ end
+end