Current section
Files
Jump to
Current section
Files
lib/peon.ex
defmodule Peon do
def from_file(filename), do: load_file(filename, false, nil)
def from_file!(filename), do: load_file(filename, true, [])
def from_file!(filename, bindings), do: load_file(filename, true, bindings)
def load_file(filename, allow_unsafe, bindings) do
{:ok, file} = File.read filename
safe = check_if_safe(file)
cond do
allow_unsafe ->
{contents, results} = Code.eval_string(file, bindings)
map = Map.merge %{}, contents
{:ok, map}
safe ->
{contents, results} = Code.eval_string(file, [])
map = Map.merge %{}, contents
{:ok, map}
true ->
{:error, "#{filename} contains unsafe data. Load with Peon.from_file! to ignore this."}
end
end
def to_file(map, filename) do
map = Map.merge(%{}, map)
contents = Macro.to_string(quote do: unquote(map))
{:ok, file} = File.open filename, [:write]
IO.binwrite file, contents
{:ok, filename}
end
def check_if_safe(file) do
{:ok, contents} = Code.string_to_quoted(file)
root = elem(contents, 2)
root |> Enum.map(&is_safe?/1)
|> List.flatten
|> Enum.all?(&(&1))
end
def is_safe?(value) do
case value do
{key, {expression, line, value}} ->
if expression != :{} and expression != :%{} do
false
else
result = value |> Enum.filter(&(is_tuple(&1)))
|> Enum.map(&is_safe?/1)
end
{key, value} when is_list(value) ->
only_tuples = value |> Enum.filter(&(is_tuple(&1)))
results = only_tuples |> Enum.map(&is_safe?/1)
Enum.all?(results, &(&1))
{expression, line, value} ->
expression == :{} or expression == :%{}
_ ->
true
end
end
end