Skip to content

Commit 498057c

Browse files
Daniel PerezJosé Valim
authored andcommitted
Add option to ignore whitespace to base64 decoding. Close #4186.
Signed-off-by: José Valim <[email protected]>
1 parent b3c26a8 commit 498057c

File tree

2 files changed

+50
-20
lines changed

2 files changed

+50
-20
lines changed

lib/elixir/lib/base.ex

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ defmodule Base do
246246
247247
"""
248248
@spec decode64(binary) :: {:ok, binary} | :error
249-
def decode64(string) when is_binary(string) do
250-
{:ok, decode64!(string)}
249+
@spec decode64(binary, Keyword.t) :: {:ok, binary} | :error
250+
def decode64(string, opts \\ []) when is_binary(string) do
251+
{:ok, decode64!(string, opts)}
251252
rescue
252253
ArgumentError -> :error
253254
end
@@ -267,12 +268,9 @@ defmodule Base do
267268
268269
"""
269270
@spec decode64!(binary) :: binary
270-
def decode64!(string) when is_binary(string) and rem(byte_size(string), 4) == 0 do
271-
do_decode64(string)
272-
end
273-
274-
def decode64!(string) when is_binary(string) do
275-
raise ArgumentError, "incorrect padding"
271+
@spec decode64!(binary, Keyword.t) :: binary
272+
def decode64!(string, opts \\ []) when is_binary(string) do
273+
string |> filter_ignored(opts[:ignore]) |> do_decode64()
276274
end
277275

278276
@doc """
@@ -301,8 +299,9 @@ defmodule Base do
301299
302300
"""
303301
@spec url_decode64(binary) :: {:ok, binary} | :error
304-
def url_decode64(string) when is_binary(string) do
305-
{:ok, url_decode64!(string)}
302+
@spec url_decode64(binary, Keyword.t) :: {:ok, binary} | :error
303+
def url_decode64(string, opts \\ []) when is_binary(string) do
304+
{:ok, url_decode64!(string, opts)}
306305
rescue
307306
ArgumentError -> :error
308307
end
@@ -321,12 +320,9 @@ defmodule Base do
321320
322321
"""
323322
@spec url_decode64!(binary) :: binary
324-
def url_decode64!(string) when is_binary(string) and rem(byte_size(string), 4) == 0 do
325-
do_decode64url(string)
326-
end
327-
328-
def url_decode64!(string) when is_binary(string) do
329-
raise ArgumentError, "incorrect padding"
323+
@spec url_decode64!(binary, Keyword.t) :: binary
324+
def url_decode64!(string, opts \\ []) when is_binary(string) do
325+
string |> filter_ignored(opts[:ignore]) |> do_decode64url()
330326
end
331327

332328
@doc """
@@ -500,6 +496,11 @@ defmodule Base do
500496
raise ArgumentError, "incorrect padding"
501497
end
502498

499+
defp filter_ignored(string, nil), do: string
500+
defp filter_ignored(string, :whitespace) do
501+
for <<c::8 <- string>>, not c in '\s\t\r\n', into: <<>>, do: <<c::8>>
502+
end
503+
503504
defp do_encode16(_, <<>>), do: <<>>
504505
defp do_encode16(:upper, data) do
505506
for <<c::4 <- data>>, into: <<>>, do: <<enc16(c)::8>>
@@ -541,7 +542,7 @@ defmodule Base do
541542
end
542543

543544
defp do_decode64(<<>>), do: <<>>
544-
defp do_decode64(string) do
545+
defp do_decode64(string) when rem(byte_size(string), 4) == 0 do
545546
split = byte_size(string) - 4
546547
<<main::size(split)-binary, rest::binary>> = string
547548
main = for <<c::8 <- main>>, into: <<>>, do: <<dec64(c)::6>>
@@ -556,6 +557,9 @@ defmodule Base do
556557
main
557558
end
558559
end
560+
defp do_decode64(_) do
561+
raise ArgumentError, "incorrect padding"
562+
end
559563

560564
defp do_encode64url(<<>>), do: <<>>
561565
defp do_encode64url(data) do
@@ -573,7 +577,7 @@ defmodule Base do
573577
end
574578

575579
defp do_decode64url(<<>>), do: <<>>
576-
defp do_decode64url(string) do
580+
defp do_decode64url(string) when rem(byte_size(string), 4) == 0 do
577581
split = byte_size(string) - 4
578582
<<main::size(split)-binary, rest::binary>> = string
579583
main = for <<c::8 <- main>>, into: <<>>, do: <<dec64url(c)::6>>
@@ -588,8 +592,9 @@ defmodule Base do
588592
main
589593
end
590594
end
591-
592-
595+
defp do_decode64url(_) do
596+
raise ArgumentError, "incorrect padding"
597+
end
593598

594599
defp do_encode32(_, <<>>), do: <<>>
595600

lib/elixir/test/elixir/base_test.exs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ defmodule BaseTest do
135135
end
136136
end
137137

138+
test "decode64 whitespace" do
139+
assert :error == decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
140+
assert {:ok, "Aladdin:open sesam"} == decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
141+
end
142+
143+
test "decode64! whitespace" do
144+
assert_raise ArgumentError, "non-alphabet digit found: \"\\n\" (byte 10)", fn ->
145+
decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
146+
end
147+
assert "Aladdin:open sesam" == decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
148+
end
149+
138150
test "decode64 incorrect padding" do
139151
assert :error == decode64("SGVsbG8gV29ybGQ")
140152
end
@@ -199,6 +211,19 @@ defmodule BaseTest do
199211
assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft")
200212
end
201213

214+
test "url_decode64 whitespace" do
215+
assert :error == url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
216+
assert {:ok, "Aladdin:open sesam"} == url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
217+
end
218+
219+
test "url_decode64! whitespace" do
220+
assert_raise ArgumentError, "non-alphabet digit found: \"\\n\" (byte 10)", fn ->
221+
url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
222+
end
223+
assert "Aladdin:open sesam" == url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
224+
end
225+
226+
202227
test "url_decode64 non-alphabet digit" do
203228
assert :error == url_decode64("Zm9)")
204229
end

0 commit comments

Comments
 (0)