X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpleroma%2Fupload.ex;h=6547113514b15fe3d74770f2fde3869930265223;hb=caadde3b04cf4c6509cc0841a338503e646221a0;hp=c47d6524111b3c40014b71b49a2a4d8d090f842d;hpb=f4e2595592ccca6cedd64669baef7bdd2a6547d0;p=akkoma
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index c47d65241..654711351 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2021 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload do
@@ -31,12 +31,14 @@ defmodule Pleroma.Upload do
"""
alias Ecto.UUID
+ alias Pleroma.Config
require Logger
@type source ::
Plug.Upload.t()
| (data_uri_string :: String.t())
| {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
+ | map()
@type option ::
{:type, :avatar | :banner | :background}
@@ -55,17 +57,32 @@ defmodule Pleroma.Upload do
}
defstruct [:id, :name, :tempfile, :content_type, :path]
+ defp get_description(opts, upload) do
+ case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do
+ {description, _} when is_binary(description) -> description
+ {_, :filename} -> upload.name
+ {_, str} when is_binary(str) -> str
+ _ -> ""
+ end
+ end
+
@spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()}
+ @doc "Store a file. If using a `Plug.Upload{}` as the source, be sure to use `Majic.Plug` to ensure its content_type and filename is correct."
def store(upload, opts \\ []) do
opts = get_opts(opts)
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),
+ {_, true} <-
+ {:description_limit,
+ String.length(description) <= Pleroma.Config.get([:instance, :description_limit])},
{:ok, url_spec} <- Pleroma.Uploaders.Uploader.put_file(opts.uploader, upload) do
{:ok,
%{
"type" => opts.activity_type,
+ "mediaType" => upload.content_type,
"url" => [
%{
"type" => "Link",
@@ -73,9 +90,12 @@ defmodule Pleroma.Upload do
"href" => url_from_spec(upload, opts.base_url, url_spec)
}
],
- "name" => Map.get(opts, :description) || upload.name
+ "name" => description
}}
else
+ {:description_limit, _} ->
+ {:error, :description_too_long}
+
{:error, error} ->
Logger.error(
"#{__MODULE__} store (using #{inspect(opts.uploader)}) failed: #{inspect(error)}"
@@ -105,78 +125,42 @@ defmodule Pleroma.Upload do
{Pleroma.Config.get!([:instance, :upload_limit]), "Document"}
end
- opts = %{
+ %{
activity_type: Keyword.get(opts, :activity_type, activity_type),
size_limit: Keyword.get(opts, :size_limit, size_limit),
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
description: Keyword.get(opts, :description),
- base_url:
- Keyword.get(
- opts,
- :base_url,
- Pleroma.Config.get([__MODULE__, :base_url], Pleroma.Web.base_url())
- )
+ base_url: base_url()
}
-
- # TODO: 1.0+ : remove old config compatibility
- opts =
- if Pleroma.Config.get([__MODULE__, :strip_exif]) == true &&
- !Enum.member?(opts.filters, Pleroma.Upload.Filter.Mogrify) do
- Logger.warn("""
- Pleroma: configuration `:instance, :strip_exif` is deprecated, please instead set:
-
- :pleroma, Pleroma.Upload, [filters: [Pleroma.Upload.Filter.Mogrify]]
-
- :pleroma, Pleroma.Upload.Filter.Mogrify, args: ["strip", "auto-orient"]
- """)
-
- Pleroma.Config.put([Pleroma.Upload.Filter.Mogrify], args: ["strip", "auto-orient"])
- Map.put(opts, :filters, opts.filters ++ [Pleroma.Upload.Filter.Mogrify])
- else
- opts
- end
-
- if Pleroma.Config.get([:instance, :dedupe_media]) == true &&
- !Enum.member?(opts.filters, Pleroma.Upload.Filter.Dedupe) do
- Logger.warn("""
- Pleroma: configuration `:instance, :dedupe_media` is deprecated, please instead set:
-
- :pleroma, Pleroma.Upload, [filters: [Pleroma.Upload.Filter.Dedupe]]
- """)
-
- Map.put(opts, :filters, opts.filters ++ [Pleroma.Upload.Filter.Dedupe])
- else
- opts
- end
end
defp prepare_upload(%Plug.Upload{} = file, opts) do
- with :ok <- check_file_size(file.path, opts.size_limit),
- {:ok, content_type, name} <- Pleroma.MIME.file_mime_type(file.path, file.filename) do
+ with :ok <- check_file_size(file.path, opts.size_limit) do
{:ok,
%__MODULE__{
id: UUID.generate(),
- name: name,
+ name: file.filename,
tempfile: file.path,
- content_type: content_type
+ content_type: file.content_type
}}
end
end
- defp prepare_upload(%{"img" => "data:image/" <> image_data}, opts) do
+ defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do
parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data)
data = Base.decode64!(parsed["data"], ignore: :whitespace)
- hash = String.downcase(Base.encode16(:crypto.hash(:sha256, data)))
+ hash = Base.encode16(:crypto.hash(:sha256, data), lower: true)
with :ok <- check_binary_size(data, opts.size_limit),
tmp_path <- tempfile_for_image(data),
- {:ok, content_type, name} <-
- Pleroma.MIME.bin_mime_type(data, hash <> "." <> parsed["filetype"]) do
+ {:ok, %{mime_type: content_type}} <-
+ Majic.perform({:bytes, data}, pool: Pleroma.MajicPool),
+ [ext | _] <- MIME.extensions(content_type) do
{:ok,
%__MODULE__{
id: UUID.generate(),
- name: name,
+ name: hash <> "." <> ext,
tempfile: tmp_path,
content_type: content_type
}}
@@ -185,7 +169,7 @@ defmodule Pleroma.Upload do
# For Mix.Tasks.MigrateLocalUploads
defp prepare_upload(%__MODULE__{tempfile: path} = upload, _opts) do
- with {:ok, content_type} <- Pleroma.MIME.file_mime_type(path) do
+ with {:ok, %{mime_type: content_type}} <- Majic.perform(path, pool: Pleroma.MajicPool) do
{:ok, %__MODULE__{upload | content_type: content_type}}
end
end
@@ -228,9 +212,46 @@ defmodule Pleroma.Upload do
""
end
- [base_url, "media", path]
+ [base_url, path]
|> Path.join()
end
defp url_from_spec(_upload, _base_url, {:url, url}), do: url
+
+ def base_url do
+ uploader = Config.get([Pleroma.Upload, :uploader])
+ upload_base_url = Config.get([Pleroma.Upload, :base_url])
+ public_endpoint = Config.get([uploader, :public_endpoint])
+
+ case uploader do
+ Pleroma.Uploaders.Local ->
+ upload_base_url || Pleroma.Web.base_url() <> "/media/"
+
+ Pleroma.Uploaders.S3 ->
+ bucket = Config.get([Pleroma.Uploaders.S3, :bucket])
+ truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace])
+ namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace])
+
+ bucket_with_namespace =
+ cond do
+ !is_nil(truncated_namespace) ->
+ truncated_namespace
+
+ !is_nil(namespace) ->
+ namespace <> ":" <> bucket
+
+ true ->
+ bucket
+ end
+
+ if public_endpoint do
+ Path.join([public_endpoint, bucket_with_namespace])
+ else
+ Path.join([upload_base_url, bucket_with_namespace])
+ end
+
+ _ ->
+ public_endpoint || upload_base_url || Pleroma.Web.base_url() <> "/media/"
+ end
+ end
end