Current section
Files
Jump to
Current section
Files
src/clamav.erl
-module(clamav).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new/1, port/2, connection_timeout/2, reply_timeout/2, logger/2, ping/1, stats/1, version/1, instream/2]).
-export_type([clam_scan_result/0, infected_file/0, clam_error/0, clam_response_parsing_error/0, clam_version_response/0]).
-type clam_scan_result() :: clean | {virus_detected, list(infected_file())}.
-type infected_file() :: {infected_file, binary(), binary()}.
-type clam_error() :: {scan_error, binary()} |
{cannot_parse_response, clam_response_parsing_error()} |
{connection_error, mug:error()}.
-type clam_response_parsing_error() :: {unexpected_response, binary()} |
invalid_binary_data.
-type clam_version_response() :: {clam_version_response, binary(), binary()}.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 39).
-spec new(binary()) -> client_options:clam_av_client_options().
new(Host) ->
{clam_av_client_options,
Host,
3310,
10000,
10000,
{logger,
fun client_options:nil_log/1,
fun client_options:nil_log/1,
fun client_options:nil_log/1}}.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 50).
-spec port(client_options:clam_av_client_options(), integer()) -> client_options:clam_av_client_options().
port(Client, Port) ->
erlang:setelement(3, Client, Port).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 55).
-spec connection_timeout(client_options:clam_av_client_options(), integer()) -> client_options:clam_av_client_options().
connection_timeout(Client, Connection_timeout) ->
erlang:setelement(4, Client, Connection_timeout).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 63).
-spec reply_timeout(client_options:clam_av_client_options(), integer()) -> client_options:clam_av_client_options().
reply_timeout(Client, Reply_timeout) ->
erlang:setelement(5, Client, Reply_timeout).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 68).
-spec logger(client_options:clam_av_client_options(), client_options:logger()) -> client_options:clam_av_client_options().
logger(Client, Logger) ->
erlang:setelement(6, Client, Logger).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 74).
-spec execute_adhoc_command(client_options:clam_av_client_options(), binary()) -> {ok,
bitstring()} |
{error, clam_error()}.
execute_adhoc_command(Options, Command) ->
_pipe = (common@internal:execute_command(
Options,
Command,
fun(Socket) ->
common@tcp:receive_bytes(Socket, Options, fun(Res) -> {ok, Res} end)
end
)),
gleam@result:try_recover(
_pipe,
fun(E) -> {error, {connection_error, E}} end
).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 89).
-spec ping(client_options:clam_av_client_options()) -> {ok, nil} |
{error, clam_error()}.
ping(Options) ->
Res = execute_adhoc_command(Options, <<"PING"/utf8>>),
case Res of
{ok, Bits} ->
Response_text = begin
_pipe = Bits,
gleam@bit_array:to_string(_pipe)
end,
case Response_text of
{ok, <<"PONG"/utf8>>} ->
{ok, nil};
{ok, Text} ->
{error,
{cannot_parse_response, {unexpected_response, Text}}};
_ ->
{error, {cannot_parse_response, invalid_binary_data}}
end;
{error, Error} ->
{error, Error}
end.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 128).
-spec stats(client_options:clam_av_client_options()) -> {ok, binary()} |
{error, clam_error()}.
stats(Options) ->
Res = execute_adhoc_command(Options, <<"STATS"/utf8>>),
case Res of
{ok, Bits} ->
case begin
_pipe = Bits,
gleam@bit_array:to_string(_pipe)
end of
{ok, Text} ->
{ok, Text};
_ ->
{error, {cannot_parse_response, invalid_binary_data}}
end;
{error, Error} ->
{error, Error}
end.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 141).
-spec parse_version_response(binary()) -> {ok, clam_version_response()} |
{error, clam_error()}.
parse_version_response(Response_text) ->
Split = begin
_pipe = Response_text,
gleam@string:split(_pipe, <<"/"/utf8>>)
end,
case Split of
[Version, Database_version, _] ->
{ok,
{clam_version_response,
begin
_pipe@1 = Version,
gleam@string:trim(_pipe@1)
end,
begin
_pipe@2 = Database_version,
gleam@string:trim(_pipe@2)
end}};
_ ->
{error,
{cannot_parse_response, {unexpected_response, Response_text}}}
end.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 110).
-spec version(client_options:clam_av_client_options()) -> {ok,
clam_version_response()} |
{error, clam_error()}.
version(Options) ->
Res = execute_adhoc_command(Options, <<"VERSION"/utf8>>),
case Res of
{ok, Bits} ->
Response_text = begin
_pipe = Bits,
gleam@bit_array:to_string(_pipe)
end,
case Response_text of
{ok, Text} ->
parse_version_response(Text);
_ ->
{error, {cannot_parse_response, invalid_binary_data}}
end;
{error, Error} ->
{error, Error}
end.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 235).
-spec get_length_indicator(integer()) -> bitstring().
get_length_indicator(Length) ->
<<Length:32/big>>.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 268).
-spec parse_virus_detected(
binary(),
client_options:logger(),
fun((clam_scan_result()) -> {ok, clam_scan_result()} | {error, clam_error()})
) -> {ok, clam_scan_result()} | {error, clam_error()}.
parse_virus_detected(Response, Logger, Callback) ->
Files = begin
_pipe = Response,
_pipe@1 = gleam@string:split(_pipe, <<"FOUND"/utf8>>),
_pipe@3 = gleam@list:filter(
_pipe@1,
fun(X) ->
begin
_pipe@2 = X,
gleam@string:trim(_pipe@2)
end
/= <<""/utf8>>
end
),
gleam@list:map(
_pipe@3,
fun(File_result) ->
File_parts = begin
_pipe@4 = File_result,
gleam@string:split(_pipe@4, <<":"/utf8>>)
end,
case File_parts of
[File_name, Virus_name] ->
{infected_file,
begin
_pipe@5 = File_name,
gleam@string:trim(_pipe@5)
end,
begin
_pipe@6 = Virus_name,
gleam@string:trim(_pipe@6)
end};
_ ->
(erlang:element(2, Logger))(
<<"Could not parse file result"/utf8>>
),
{infected_file, <<"UNKNOWN"/utf8>>, <<"UNKNOWN"/utf8>>}
end
end
)
end,
Callback({virus_detected, Files}).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 240).
-spec parse_scan_result(
binary(),
client_options:logger(),
fun((clam_scan_result()) -> {ok, clam_scan_result()} | {error, clam_error()})
) -> {ok, clam_scan_result()} | {error, clam_error()}.
parse_scan_result(Response, Logger, Callback) ->
Formatted_lower = begin
_pipe = Response,
string:lowercase(_pipe)
end,
case begin
_pipe@1 = Formatted_lower,
gleam_stdlib:string_ends_with(_pipe@1, <<"ok"/utf8>>)
end of
true ->
Callback(clean);
false ->
case begin
_pipe@2 = Formatted_lower,
gleam_stdlib:string_ends_with(_pipe@2, <<"error"/utf8>>)
end of
true ->
{error, {scan_error, Response}};
false ->
case begin
_pipe@3 = Formatted_lower,
gleam_stdlib:string_ends_with(_pipe@3, <<"found"/utf8>>)
end of
true ->
parse_virus_detected(
Response,
Logger,
fun(Virus_detected) ->
Callback(Virus_detected)
end
);
false ->
{error,
{cannot_parse_response,
{unexpected_response, Response}}}
end
end
end.
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 208).
-spec send_file(
mug:socket(),
bitstring(),
client_options:clam_av_client_options(),
fun(() -> {ok, GPH} | {error, mug:error()})
) -> {ok, GPH} | {error, mug:error()}.
send_file(Socket, File_contents, Options, Callback) ->
Byte_size = erlang:byte_size(File_contents),
Packet = begin
_pipe = Byte_size,
_pipe@1 = get_length_indicator(_pipe),
_pipe@2 = gleam@bit_array:append(_pipe@1, File_contents),
gleam@bit_array:append(_pipe@2, <<0:32/little>>)
end,
(erlang:element(4, erlang:element(6, Options)))(
<<<<<<<<":: Uploading file of size "/utf8,
(begin
_pipe@3 = Byte_size,
erlang:integer_to_binary(_pipe@3)
end)/binary>>/binary,
"B. (Total packet size "/utf8>>/binary,
(begin
_pipe@4 = Packet,
_pipe@5 = erlang:byte_size(_pipe@4),
erlang:integer_to_binary(_pipe@5)
end)/binary>>/binary,
"B)"/utf8>>
),
common@tcp:send_bytes(Socket, Packet, Options, fun() -> Callback() end).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 186).
-spec tcp_instream(client_options:clam_av_client_options(), bitstring()) -> {ok,
bitstring()} |
{error, mug:error()}.
tcp_instream(Options, File_content) ->
common@internal:execute_command(
Options,
<<"INSTREAM"/utf8>>,
fun(Socket) ->
(erlang:element(4, erlang:element(6, Options)))(
<<":: Socket acquired"/utf8>>
),
send_file(
Socket,
File_content,
Options,
fun() ->
(erlang:element(4, erlang:element(6, Options)))(
<<":: File upload complete"/utf8>>
),
common@tcp:receive_bytes(
Socket,
Options,
fun(Response_bytes) ->
(erlang:element(4, erlang:element(6, Options)))(
<<":: Received response"/utf8>>
),
{ok, Response_bytes}
end
)
end
)
end
).
-file("/home/runner/work/gleam-clamav/gleam-clamav/src/clamav.gleam", 159).
-spec instream(client_options:clam_av_client_options(), bitstring()) -> {ok,
clam_scan_result()} |
{error, clam_error()}.
instream(Options, File_content) ->
Padded_file_content = gleam_stdlib:bit_array_pad_to_bytes(File_content),
case tcp_instream(Options, Padded_file_content) of
{ok, Response} ->
case gleam@bit_array:to_string(Response) of
{ok, Response_text} ->
parse_scan_result(
Response_text,
erlang:element(6, Options),
fun(Scan_result) -> {ok, Scan_result} end
);
{error, _} ->
{error, {cannot_parse_response, invalid_binary_data}}
end;
{error, Error} ->
{error, {connection_error, Error}}
end.