diff --git a/lib/plug/conn/cookies.ex b/lib/plug/conn/cookies.ex index 12257f16..525f987d 100644 --- a/lib/plug/conn/cookies.ex +++ b/lib/plug/conn/cookies.ex @@ -49,40 +49,49 @@ defmodule Plug.Conn.Cookies do defp decode_kv("", acc), do: acc defp decode_kv(<>, acc) when h in [?\s, ?\t], do: decode_kv(t, acc) - defp decode_kv(kv, acc) when is_binary(kv), do: decode_key(kv, "", acc) + defp decode_kv(kv, acc) when is_binary(kv), do: decode_key(kv, kv, 0, acc) - defp decode_key(<>, _key, acc) when h in [?\s, ?\t, ?\r, ?\n, ?\v, ?\f], - do: skip_until_cc(t, acc) + defp decode_key(<>, _key_rest, _len, acc) + when h in [?\s, ?\t, ?\r, ?\n, ?\v, ?\f], + do: skip_until_cc(t, acc) - defp decode_key(<>, _key, acc), do: decode_kv(t, acc) - defp decode_key(<>, "", acc), do: skip_until_cc(t, acc) - defp decode_key(<>, key, acc), do: decode_value(t, "", 0, key, acc) - defp decode_key(<>, key, acc), do: decode_key(t, <>, acc) - defp decode_key(<<>>, _key, acc), do: acc + defp decode_key(<>, _key_rest, _len, acc), do: decode_kv(t, acc) + defp decode_key(<>, _key_rest, 0, acc), do: skip_until_cc(t, acc) - defp decode_value(<>, value, spaces, key, acc), - do: decode_kv(t, [{key, trim_spaces(value, spaces)} | acc]) + defp decode_key(<>, key_rest, len, acc) do + key = binary_part(key_rest, 0, len) + decode_value(t, t, 0, 0, key, acc) + end - defp decode_value(<>, value, spaces, key, acc), - do: decode_value(t, <>, spaces + 1, key, acc) + defp decode_key(<<_, t::binary>>, key_rest, len, acc), do: decode_key(t, key_rest, len + 1, acc) + defp decode_key(<<>>, _key_rest, _len, acc), do: acc - defp decode_value(<>, _value, _spaces, _key, acc) + defp decode_value(<>, val_rest, len, spaces, key, acc) do + value = binary_part(val_rest, 0, len - spaces) + decode_kv(t, [{key, value} | acc]) + end + + defp decode_value(<>, val_rest, len, spaces, key, acc) do + decode_value(t, val_rest, len + 1, spaces + 1, key, acc) + end + + defp decode_value(<>, _val_rest, _len, _spaces, _key, acc) when h in [?\t, ?\r, ?\n, ?\v, ?\f], do: skip_until_cc(t, acc) - defp decode_value(<>, value, _spaces, key, acc), - do: decode_value(t, <>, 0, key, acc) + defp decode_value(<<_, t::binary>>, val_rest, len, _spaces, key, acc) do + decode_value(t, val_rest, len + 1, 0, key, acc) + end - defp decode_value(<<>>, value, spaces, key, acc), - do: [{key, trim_spaces(value, spaces)} | acc] + defp decode_value(<<>>, val_rest, len, spaces, key, acc) do + value = binary_part(val_rest, 0, len - spaces) + [{key, value} | acc] + end defp skip_until_cc(<>, acc), do: decode_kv(t, acc) defp skip_until_cc(<<_, t::binary>>, acc), do: skip_until_cc(t, acc) defp skip_until_cc(<<>>, acc), do: acc - defp trim_spaces(value, 0), do: value - defp trim_spaces(value, spaces), do: binary_part(value, 0, byte_size(value) - spaces) - @doc """ Encodes the given cookies as expected in a response header.