defmodule Pleroma.Web.Salmon do
+ @httpoison Application.get_env(:pleroma, :httpoison)
+
use Bitwise
alias Pleroma.Web.XML
alias Pleroma.Web.OStatus.ActivityRepresenter
[modulus, exponent] = magickey
|> String.split(".")
- |> Enum.map(&Base.url_decode64!/1)
+ |> Enum.map(fn (n) -> Base.url_decode64!(n, padding: false) end)
|> Enum.map(make_integer)
{:RSAPublicKey, modulus, exponent}
"RSA.#{modulus_enc}.#{exponent_enc}"
end
- def generate_rsa_pem do
- port = Port.open({:spawn, "openssl genrsa"}, [:binary])
- {:ok, pem} = receive do
- {^port, {:data, pem}} -> {:ok, pem}
- end
- Port.close(port)
- if Regex.match?(~r/RSA PRIVATE KEY/, pem) do
+ # Native generation of RSA keys is only available since OTP 20+ and in default build conditions
+ # We try at compile time to generate natively an RSA key otherwise we fallback on the old way.
+ try do
+ _ = :public_key.generate_key({:rsa, 2048, 65537})
+ def generate_rsa_pem do
+ key = :public_key.generate_key({:rsa, 2048, 65537})
+ entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
+ pem = :public_key.pem_encode([entry]) |> String.trim_trailing
{:ok, pem}
- else
- :error
end
+ rescue
+ _ ->
+ def generate_rsa_pem do
+ port = Port.open({:spawn, "openssl genrsa"}, [:binary])
+ {:ok, pem} = receive do
+ {^port, {:data, pem}} -> {:ok, pem}
+ end
+ Port.close(port)
+ if Regex.match?(~r/RSA PRIVATE KEY/, pem) do
+ {:ok, pem}
+ else
+ :error
+ end
+ end
end
def keys_from_pem(pem) do
end
defp send_to_user(%{info: %{"salmon" => salmon}}, feed, poster) do
- poster.(salmon, feed, [{"Content-Type", "application/magic-envelope+xml"}])
+ with {:ok, %{status_code: code}} <- poster.(salmon, feed, [{"Content-Type", "application/magic-envelope+xml"}], timeout: 10000, recv_timeout: 20000) do
+ Logger.debug(fn -> "Pushed to #{salmon}, code #{code}" end)
+ else
+ e -> Logger.debug(fn -> "Pushing salmon to #{salmon} failed, #{inspect(e)}" end)
+ end
end
defp send_to_user(_,_,_), do: nil
- def publish(user, activity, poster \\ &HTTPoison.post/3)
- def publish(%{info: %{"keys" => keys}} = user, activity, poster) do
+ @supported_activities [
+ "Create",
+ "Follow",
+ "Like",
+ "Announce",
+ "Undo",
+ "Delete"
+ ]
+ def publish(user, activity, poster \\ &@httpoison.post/4)
+ def publish(%{info: %{"keys" => keys}} = user, %{data: %{"type" => type}} = activity, poster) when type in @supported_activities do
feed = ActivityRepresenter.to_simple_form(activity, user, true)
|> ActivityRepresenter.wrap_with_entry
|> :xmerl.export_simple(:xmerl_xml)
remote_users(activity)
|> Enum.each(fn(remote_user) ->
- Logger.debug(fn -> "sending salmon to #{remote_user.ap_id}" end)
- send_to_user(remote_user, feed, poster)
+ Task.start(fn ->
+ Logger.debug(fn -> "sending salmon to #{remote_user.ap_id}" end)
+ send_to_user(remote_user, feed, poster)
+ end)
end)
end
end