diff --git a/lib/plug/conn/utils.ex b/lib/plug/conn/utils.ex index aee135f31..105b8c49d 100644 --- a/lib/plug/conn/utils.ex +++ b/lib/plug/conn/utils.ex @@ -239,23 +239,42 @@ defmodule Plug.Conn.Utils do """ @spec token(binary) :: binary | false - def token(""), do: false - def token(<>), do: quoted_token(quoted, "") - def token(token), do: unquoted_token(token, "") + def token(token) when is_binary(token), do: do_token(token, token) + + defp do_token(<>, original), do: unquoted_token(token, original, 0) - defp quoted_token(<<>>, _acc), do: false defp quoted_token(<>, acc), do: strip_spaces(t) == "" and acc - defp quoted_token(<>, acc), do: quoted_token(t, <>) + + defp quoted_token(<>, acc) do + case rest do + <> -> quoted_token(t, <>) + <<>> -> false + end + end + defp quoted_token(<>, acc), do: quoted_token(t, <>) + defp quoted_token(<<>>, _acc), do: false + + defp unquoted_token(<>, _token, len), + do: len == 0 and quoted_token(quoted, "") + + defp unquoted_token(<>, token, len) do + case rest do + <> -> strip_spaces(t) == "" and binary_part(token, 0, len) + _ -> false + end + end - defp unquoted_token(<<>>, acc), do: acc - defp unquoted_token("\r\n" <> t, acc), do: strip_spaces(t) == "" and acc - defp unquoted_token(<>, acc) when h in @space, do: strip_spaces(t) == "" and acc + defp unquoted_token(<>, token, len) when h in @space, + do: strip_spaces(t) == "" and binary_part(token, 0, len) - defp unquoted_token(<>, _acc) when h in @specials or h < 32 or h === 127, + defp unquoted_token(<>, _token, _len) when h in @specials or h < 32 or h === 127, do: false - defp unquoted_token(<>, acc), do: unquoted_token(t, <>) + defp unquoted_token(<<_, t::binary>>, token, len), + do: unquoted_token(t, token, len + 1) + + defp unquoted_token(<<>>, token, len), do: len != 0 and token @doc """ Parses a comma-separated list of header values.