Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F113629
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/remote_ip/headers/forwarded.ex b/lib/remote_ip/headers/forwarded.ex
index 263362a..1fc3fbb 100644
--- a/lib/remote_ip/headers/forwarded.ex
+++ b/lib/remote_ip/headers/forwarded.ex
@@ -1,166 +1,166 @@
defmodule RemoteIp.Headers.Forwarded do
@moduledoc """
[RFC 7239](https://tools.ietf.org/html/rfc7239) compliant parser for
`Forwarded` headers.
"""
use Combine
@doc """
Given a `Forwarded` header's string value, parses out IP addresses from the
`for=` parameter.
## Examples
iex> RemoteIp.Headers.Forwarded.parse("for=1.2.3.4;by=2.3.4.5")
[{1, 2, 3, 4}]
iex> RemoteIp.Headers.Forwarded.parse("for=\\"[::1]\\", for=\\"[::2]\\"")
[{0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 2}]
iex> RemoteIp.Headers.Forwarded.parse("invalid")
[]
"""
@type header :: String.t
@type ip :: :inet.ip_address
@spec parse(header) :: [ip]
def parse(header) when is_binary(header) do
case Combine.parse(header, forwarded()) do
[elements] -> Enum.flat_map(elements, &parse_forwarded_for/1)
_ -> []
end
end
defp parse_forwarded_for(pairs) do
case pairs |> fors do
[string] -> parse_ip(string)
_ -> [] # no `for=`s or multiple `for=`s
end
end
defp fors(pairs) do
for {key, val} <- pairs, String.downcase(key) == "for", do: val
end
defp parse_ip(string) do
case Combine.parse(string, ip_address()) do
[ip] -> [ip]
_ -> []
end
end
# https://tools.ietf.org/html/rfc7239#section-4
defp forwarded do
sep_by(forwarded_element(), comma()) |> eof
end
defp forwarded_element do
sep_by1(forwarded_pair(), char(";"))
end
defp forwarded_pair do
pair = [token(), ignore(char("=")), value()]
pipe(pair, &List.to_tuple/1)
end
defp value do
either(token(), quoted_string())
end
# https://tools.ietf.org/html/rfc7230#section-3.2.6
defp token do
word_of(~r/[!#$%&'*+\-.^_`|~0-9a-zA-Z]/)
end
defp quoted_string do
quoted(string_of(either(qdtext(), quoted_pair())))
end
defp quoted(parser) do
between(char("\""), parser, char("\""))
end
defp string_of(parser) do
map(many(parser), &Enum.join/1)
end
defp qdtext do
word_of(~r/[\t \x21\x23-\x5B\x5D-\x7E\x80-\xFF]/)
end
@quotable [?\t]
++ Enum.to_list(0x21..0x7E)
++ Enum.to_list(0x80..0xFF)
|> Enum.map(&<<&1::utf8>>)
defp quoted_pair do
ignore(char("\\")) |> one_of(char(), @quotable)
end
# https://tools.ietf.org/html/rfc7230#section-7
defp comma do
skip(many(either(space(), tab())))
|> char(",")
|> skip(many(either(space(), tab())))
end
# https://tools.ietf.org/html/rfc7239#section-6
defp ip_address do
node_name()
|> ignore(option(ignore(char(":")) |> node_port))
|> eof
end
defp node_name do
choice [
ipv4_address(),
between(char("["), ipv6_address(), char("]")),
ignore(string("unknown")),
ignore(obfuscated()),
]
end
defp node_port(previous) do
previous |> either(port(), obfuscated())
end
defp port do
# Have to try to parse the wider integers first due to greediness. For
# example, the port "12345" would be matched by fixed_integer(1) and the
# remaining "2345" would cause a parse error for the eof in ip_address/0.
choice(Enum.map(5..1, &fixed_integer/1))
end
defp obfuscated do
word_of(~r/^_[a-zA-Z0-9._\-]+/)
end
# Could follow the ABNF described in
# https://tools.ietf.org/html/rfc3986#section-3.2.2, but prefer to lean on
# the existing :inet parser - we want its output anyway.
defp ipv4_address do
map(word_of(~r/[0-9.]/), fn string ->
- case :inet.parse_ipv4strict_address(string |> to_char_list) do
+ case :inet.parse_ipv4strict_address(string |> to_charlist) do
{:ok, ip} -> ip
{:error, :einval} -> {:error, "Invalid IPv4 address"}
end
end)
end
defp ipv6_address do
map(word_of(~r/[0-9a-f:.]/i), fn string ->
- case :inet.parse_ipv6strict_address(string |> to_char_list) do
+ case :inet.parse_ipv6strict_address(string |> to_charlist) do
{:ok, ip} -> ip
{:error, :einval} -> {:error, "Invalid IPv6 address"}
end
end)
end
end
diff --git a/lib/remote_ip/headers/generic.ex b/lib/remote_ip/headers/generic.ex
index 1431aeb..641b80b 100644
--- a/lib/remote_ip/headers/generic.ex
+++ b/lib/remote_ip/headers/generic.ex
@@ -1,55 +1,55 @@
defmodule RemoteIp.Headers.Generic do
@moduledoc """
Generic parser for forwarding headers.
When there is no other special `RemoteIp.Headers.*` parser submodule,
`RemoteIp.Headers.parse/2` will use this module to parse the header value.
So, `RemoteIp.Headers.Generic` is used to parse `X-Forwarded-For`,
`X-Real-IP`, `X-Client-IP`, and generally unrecognized headers.
"""
@doc """
Parses a comma-separated list of IPs.
Any amount of whitespace is allowed before and after the commas, as well as
at the beginning/end of the input.
## Examples
iex> RemoteIp.Headers.Generic.parse("1.2.3.4, 5.6.7.8")
[{1, 2, 3, 4}, {5, 6, 7, 8}]
iex> RemoteIp.Headers.Generic.parse(" ::1 ")
[{0, 0, 0, 0, 0, 0, 0, 1}]
iex> RemoteIp.Headers.Generic.parse("invalid")
[]
"""
@type header :: String.t
@type ip :: :inet.ip_address
@spec parse(header) :: [ip]
def parse(header) when is_binary(header) do
header
|> split_commas
|> parse_ips
end
defp split_commas(header) do
header |> String.trim |> String.split(~r/\s*,\s*/)
end
defp parse_ips(strings) do
Enum.reduce(strings, [], fn string, ips ->
case parse_ip(string) do
{:ok, ip} -> [ip | ips]
{:error, :einval} -> ips
end
end) |> Enum.reverse
end
defp parse_ip(string) do
- string |> to_char_list |> :inet.parse_strict_address
+ string |> to_charlist |> :inet.parse_strict_address
end
end
diff --git a/mix.lock b/mix.lock
index 0b25b1e..b392e9a 100644
--- a/mix.lock
+++ b/mix.lock
@@ -1,6 +1,6 @@
-%{"combine": {:hex, :combine, "0.9.2", "cd3c8721f378ebe032487d8a4fa2ced3181a456a3c21b16464da8c46904bb552", [:mix], []},
+%{"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.0.2", "a0b0904d74ecc14da8bd2e6e0248e1a409a2bc91aade75fcf428125603de3853", [:mix], []},
"ex_doc": {:hex, :ex_doc, "0.14.3", "e61cec6cf9731d7d23d254266ab06ac1decbb7651c3d1568402ec535d387b6f7", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]},
"inet_cidr": {:hex, :inet_cidr, "1.0.1", "9038d0598eb2f7f4b4347c566b773c79e10edfb038633de9f55d538ba2703ac3", [:mix], []},
"mime": {:hex, :mime, "1.0.1", "05c393850524767d13a53627df71beeebb016205eb43bfbd92d14d24ec7a1b51", [:mix], []},
"plug": {:hex, :plug, "1.2.2", "cfbda521b54c92ab8ddffb173fbaabed8d8fc94bec07cd9bb58a84c1c501b0bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:mime, "~> 1.0", [hex: :mime, optional: false]}]}}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 1:54 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39812
Default Alt Text
(7 KB)
Attached To
Mode
R27 remote_ip
Attached
Detach File
Event Timeline
Log In to Comment