diff --git a/lib/binoculo/args.ex b/lib/binoculo/args.ex index 7fb58d2..990e74b 100644 --- a/lib/binoculo/args.ex +++ b/lib/binoculo/args.ex @@ -78,7 +78,13 @@ defmodule Binoculo.Args do value_name: "read", short: "-r", long: "--read", - help: "Save only responses that match with this string, e.g: Apache" + help: "Save only responses that match with this string, e.g: Apache | nginx,php", + parser: fn read_payload -> + case String.contains?(read_payload, ",") do + true -> {:ok, String.split(read_payload, ",")} + false -> {:ok, read_payload} + end + end ] ] ) diff --git a/lib/binoculo/cross_saver.ex b/lib/binoculo/cross_saver.ex index f09770c..6f72fc7 100644 --- a/lib/binoculo/cross_saver.ex +++ b/lib/binoculo/cross_saver.ex @@ -3,7 +3,7 @@ defmodule Binoculo.CrossSaver do Save to multiple sources """ - alias Binoculo.{Config, Msearch, Results, Util} + alias Binoculo.{Config, Msearch, Refiner, Results, Util} def save_results() do check_and_save_to_file() @@ -60,9 +60,7 @@ defmodule Binoculo.CrossSaver do results read_payload -> - Enum.filter(results, fn %{response: response} -> - Regex.match?(~r/#{read_payload}/i, response) - end) + Refiner.find_occurrences_in_responses(read_payload, results) end end end diff --git a/lib/binoculo/refiner.ex b/lib/binoculo/refiner.ex new file mode 100644 index 0000000..6015a7d --- /dev/null +++ b/lib/binoculo/refiner.ex @@ -0,0 +1,13 @@ +defmodule Binoculo.Refiner do + def find_occurrences_in_responses(patterns, responses) when is_list(patterns) do + Enum.filter(responses, fn %{response: response} -> + Enum.all?(patterns, fn pattern -> String.contains?(response, pattern) end) + end) + end + + def find_occurrences_in_responses(pattern, responses) do + Enum.filter(responses, fn %{response: response} -> + String.contains?(response, pattern) + end) + end +end diff --git a/test/args_test.exs b/test/args_test.exs index c0c9f10..8aa829e 100644 --- a/test/args_test.exs +++ b/test/args_test.exs @@ -3,7 +3,7 @@ defmodule ArgsTest do alias Binoculo.Args - describe "parse args" do + describe "parse_args/1" do test "should parse valid args" do args = ["--range", "192.168.101.1", "-p", "80", "--output", "my_file.txt"] parsed_args = Args.parse_args(args) |> Map.from_struct() @@ -11,5 +11,31 @@ defmodule ArgsTest do assert %{options: %{host_notation: "192.168.101.1", ports: [80], output: "my_file.txt"}} = parsed_args end + + test "should parse read payload with one pattern" do + args = ["--range", "192.168.101.1", "-p", "80", "--read", "nginx"] + parsed_args = Args.parse_args(args) |> Map.from_struct() + + assert %{ + options: %{ + host_notation: "192.168.101.1", + ports: [80], + read: "nginx" + } + } = parsed_args + end + + test "should parse read payload with multiple patterns" do + args = ["--range", "192.168.101.1", "-p", "80", "--read", "nginx,php"] + parsed_args = Args.parse_args(args) |> Map.from_struct() + + assert %{ + options: %{ + host_notation: "192.168.101.1", + ports: [80], + read: ["nginx", "php"] + } + } = parsed_args + end end end diff --git a/test/refiner_test.exs b/test/refiner_test.exs new file mode 100644 index 0000000..0bd67b8 --- /dev/null +++ b/test/refiner_test.exs @@ -0,0 +1,27 @@ +defmodule RefinerTest do + use ExUnit.Case, async: true + + alias Binoculo.Refiner + + @responses [ + %{response: "hello and world"}, + %{response: "world"}, + %{response: "test"}, + %{response: "test xoo"} + ] + + describe "Refiner.find_occurrences_in_responses/2" do + test "should find occurrences in responses with single pattern" do + assert [%{response: "test"}, %{response: "test xoo"}] == + Refiner.find_occurrences_in_responses("test", @responses) + end + + test "should find occurrences in responses with multiple patterns (AND)" do + assert [%{response: "hello and world"}] == + Refiner.find_occurrences_in_responses(["hello", "world"], @responses) + + assert [%{response: "test xoo"}] == + Refiner.find_occurrences_in_responses(["xoo"], @responses) + end + end +end