Send decrypted upload response as chunked
This commit is contained in:
parent
0d51f9de3d
commit
fd8bf97459
|
@ -98,6 +98,40 @@ defmodule Wiki.Content.Upload do
|
|||
:crypto.crypto_one_time(:aes_256_ctr, key, iv, encrypted_data, false)
|
||||
end
|
||||
|
||||
@spec decrypt_stream(t(), binary()) :: Enumerable.t()
|
||||
def decrypt_stream(%__MODULE__{relative_path: filename, encryption_iv: iv}, key) do
|
||||
start_fun = fn ->
|
||||
state = :crypto.crypto_init(:aes_256_ctr, key, iv, false)
|
||||
path = Path.join(upload_dir(), filename)
|
||||
{:ok, input} = File.open(path, [:read, :binary])
|
||||
{state, input, false}
|
||||
end
|
||||
|
||||
next_fun = fn {state, input_dev, halt} ->
|
||||
if halt do
|
||||
{:halt, {state, input_dev}}
|
||||
else
|
||||
# why 4k?
|
||||
{halt, data} =
|
||||
case IO.binread(input_dev, 4096) do
|
||||
:eof ->
|
||||
{true, :crypto.crypto_final(state)}
|
||||
|
||||
data ->
|
||||
{false, :crypto.crypto_update(state, data)}
|
||||
end
|
||||
|
||||
{[data], {state, input_dev, halt}}
|
||||
end
|
||||
end
|
||||
|
||||
after_fun = fn {state, input_dev} ->
|
||||
File.close(input_dev)
|
||||
end
|
||||
|
||||
Stream.resource(start_fun, next_fun, after_fun)
|
||||
end
|
||||
|
||||
@spec delete_file(upload :: t()) :: :ok
|
||||
def delete_file(%__MODULE__{relative_path: filename}) do
|
||||
File.rm(Path.join(upload_dir(), filename))
|
||||
|
|
|
@ -141,11 +141,22 @@ defmodule WikiWeb.PageController do
|
|||
key = get_session(conn, :content_encryption_key)
|
||||
key = Base.decode16!(key, case: :lower)
|
||||
|
||||
data = Upload.decrypt_content(upload, key)
|
||||
conn =
|
||||
conn
|
||||
|> put_resp_header("content-type", upload.content_type)
|
||||
|> send_chunked(200)
|
||||
|
||||
conn
|
||||
|> put_resp_header("content-type", upload.content_type)
|
||||
|> send_resp(200, data)
|
||||
upload
|
||||
|> Upload.decrypt_stream(key)
|
||||
|> Enum.reduce_while(conn, fn decrypted_chunk, conn ->
|
||||
case chunk(conn, decrypted_chunk) do
|
||||
{:ok, conn} ->
|
||||
{:cont, conn}
|
||||
|
||||
{:error, :closed} ->
|
||||
{:halt, {:halt, conn}}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def delete_upload(conn, _params) do
|
||||
|
|
Loading…
Reference in New Issue