op-clamav-client 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ChangeLog.md +64 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +674 -0
- data/README.md +209 -0
- data/Rakefile +104 -0
- data/clamav-client.gemspec +25 -0
- data/lib/clamav/client.rb +182 -0
- data/lib/clamav/commands/command.rb +38 -0
- data/lib/clamav/commands/instream_command.rb +39 -0
- data/lib/clamav/commands/ping_command.rb +25 -0
- data/lib/clamav/commands/quit_command.rb +25 -0
- data/lib/clamav/commands/scan_command.rb +35 -0
- data/lib/clamav/connection.rb +129 -0
- data/lib/clamav/response.rb +28 -0
- data/lib/clamav/responses/error_response.rb +25 -0
- data/lib/clamav/responses/success_response.rb +25 -0
- data/lib/clamav/responses/virus_response.rb +26 -0
- data/lib/clamav/util.rb +32 -0
- data/lib/clamav/wrapper.rb +33 -0
- data/lib/clamav/wrappers/new_line_wrapper.rb +29 -0
- data/lib/clamav/wrappers/null_termination_wrapper.rb +29 -0
- data/lib/clamav.rb +1 -0
- data/test/Dockerfile +16 -0
- data/test/integration/clamav/client_test.rb +142 -0
- data/test/integration/clamav/util_test.rb +41 -0
- data/test/test_helper.rb +21 -0
- data/test/unit/clamav/client_test.rb +59 -0
- data/test/unit/clamav/commands/instream_command_test.rb +53 -0
- data/test/unit/clamav/commands/ping_command_test.rb +33 -0
- data/test/unit/clamav/commands/scan_command_test.rb +36 -0
- data/test/unit/clamav/connection_test.rb +46 -0
- data/test/unit/clamav/wrappers/new_line_wrapper_test.rb +38 -0
- data/test/unit/clamav/wrappers/null_termination_wrapper_test.rb +38 -0
- metadata +143 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'timeout'
|
18
|
+
|
19
|
+
module ClamAV
|
20
|
+
class Connection
|
21
|
+
class ReadTimeoutError < ::ClamAV::Client::ReadTimeoutError; end
|
22
|
+
class WriteTimeoutError < ::ClamAV::Client::WriteTimeoutError; end
|
23
|
+
|
24
|
+
attr_accessor :client
|
25
|
+
attr_accessor :socket
|
26
|
+
attr_accessor :wrapper
|
27
|
+
|
28
|
+
def initialize(attrs={})
|
29
|
+
attrs.each do |attr, value|
|
30
|
+
send("#{attr}=", value)
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
validate!
|
35
|
+
rescue => e
|
36
|
+
@client = nil
|
37
|
+
@socket = nil
|
38
|
+
@wrapper = nil
|
39
|
+
|
40
|
+
raise e
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate!
|
45
|
+
missing_required_argument(:client) if !client
|
46
|
+
missing_required_argument(:socket) if !socket
|
47
|
+
missing_required_argument(:wrapper) if !wrapper
|
48
|
+
end
|
49
|
+
|
50
|
+
[
|
51
|
+
:tcp?,
|
52
|
+
:file,
|
53
|
+
:connect_timeout,
|
54
|
+
:read_timeout,
|
55
|
+
:write_timeout,
|
56
|
+
].each do |m|
|
57
|
+
define_method(m) do
|
58
|
+
client.send(m)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def establish_connection
|
63
|
+
write_request("IDSESSION")
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_request(str)
|
67
|
+
return write_request_with_timeout(str) if write_timeout
|
68
|
+
|
69
|
+
write_request_without_timeout(str)
|
70
|
+
end
|
71
|
+
|
72
|
+
def write_request_without_timeout(str)
|
73
|
+
wrapped_request = @wrapper.wrap_request(str)
|
74
|
+
|
75
|
+
@socket.write wrapped_request
|
76
|
+
end
|
77
|
+
|
78
|
+
def write_request_with_timeout(str)
|
79
|
+
Timeout::timeout(connect_timeout) do
|
80
|
+
write_request_without_timeout(str)
|
81
|
+
end
|
82
|
+
rescue Timeout::Error => e
|
83
|
+
|
84
|
+
raise WriteTimeoutError.new(e.to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
def read_response
|
88
|
+
return read_response_with_timeout if read_timeout
|
89
|
+
|
90
|
+
read_response_without_timeout
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_response_without_timeout
|
94
|
+
@wrapper.read_response(@socket)
|
95
|
+
end
|
96
|
+
|
97
|
+
def read_response_with_timeout
|
98
|
+
Timeout::timeout(read_timeout) do
|
99
|
+
read_response_without_timeout
|
100
|
+
end
|
101
|
+
rescue Timeout::Error => e
|
102
|
+
raise ReadTimeoutError.new(e.to_s)
|
103
|
+
end
|
104
|
+
|
105
|
+
def disconnect!
|
106
|
+
return true if @socket.nil?
|
107
|
+
|
108
|
+
@socket.close
|
109
|
+
|
110
|
+
@socket.closed?.tap do
|
111
|
+
@socket = nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def send_request(str)
|
116
|
+
write_request(str)
|
117
|
+
read_response
|
118
|
+
end
|
119
|
+
|
120
|
+
def raw_write(str)
|
121
|
+
@socket.write str
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def missing_required_argument(key)
|
126
|
+
raise ArgumentError, "#{key} is required"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
class Response
|
19
|
+
|
20
|
+
attr_reader :file, :virus_name, :error_str
|
21
|
+
|
22
|
+
# Not sure if this is still required?
|
23
|
+
def ==(other)
|
24
|
+
@file == other.file && self.class == other.class
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
class ErrorResponse < Response
|
19
|
+
|
20
|
+
def initialize(error_str)
|
21
|
+
@error_str = error_str
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
class SuccessResponse < Response
|
19
|
+
|
20
|
+
def initialize(file)
|
21
|
+
@file = file
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
class VirusResponse < Response
|
19
|
+
|
20
|
+
def initialize(file, virus_name)
|
21
|
+
@file = file
|
22
|
+
@virus_name = virus_name
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/clamav/util.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
module Util
|
19
|
+
UnknownPathException = Class.new(RuntimeError)
|
20
|
+
|
21
|
+
def Util.path_to_files(path)
|
22
|
+
if Dir.exist?(path)
|
23
|
+
Dir.glob(path + '/*')
|
24
|
+
elsif File.exist?(path)
|
25
|
+
[path]
|
26
|
+
else
|
27
|
+
message =" (path = #{path})"
|
28
|
+
raise UnknownPathException.new("#{__FILE__}:#{__LINE__} path_to_files : path argument neither a file nor a directory. Aborting. #{message}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
class Wrapper
|
19
|
+
def wrap_request(request); raise NotImplementedError; end
|
20
|
+
def unwrap_response(response); raise NotImplementedError; end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def read_until(socket, delimiter)
|
24
|
+
buff = ""
|
25
|
+
while (char = socket.getc) != delimiter
|
26
|
+
buff << char
|
27
|
+
end
|
28
|
+
buff
|
29
|
+
rescue TypeError => e
|
30
|
+
raise ::ClamAV::Client::ConnectionError.new(e.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
module Wrappers
|
19
|
+
class NewLineWrapper < ::ClamAV::Wrapper
|
20
|
+
def wrap_request(request)
|
21
|
+
"n#{request}\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_response(socket)
|
25
|
+
read_until(socket, "\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
module ClamAV
|
18
|
+
module Wrappers
|
19
|
+
class NullTerminationWrapper < ::ClamAV::Wrapper
|
20
|
+
def wrap_request(request)
|
21
|
+
"z#{request}\0"
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_response(socket)
|
25
|
+
read_until(socket, "\0")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/clamav.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'clamav/client'
|
data/test/Dockerfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
ARG RUBY_VERSION
|
2
|
+
FROM ruby:${RUBY_VERSION}
|
3
|
+
LABEL maintainer="victor.pugin@lifen.fr"
|
4
|
+
|
5
|
+
WORKDIR /clamav-client
|
6
|
+
ADD Gemfile /clamav-client
|
7
|
+
ADD clamav-client.gemspec /clamav-client
|
8
|
+
|
9
|
+
RUN apt-get update -qq && \
|
10
|
+
apt-get install -y clamav-daemon clamav-freshclam clamav-unofficial-sigs && \
|
11
|
+
freshclam && \
|
12
|
+
bundle
|
13
|
+
|
14
|
+
ENTRYPOINT ["./start.sh"]
|
15
|
+
|
16
|
+
ADD . /clamav-client
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'test_helper'
|
18
|
+
|
19
|
+
describe "ClamAV::Client Integration Tests" do
|
20
|
+
describe "default new line delimiter" do
|
21
|
+
let(:client) { ClamAV::Client.new }
|
22
|
+
|
23
|
+
describe "any callable" do
|
24
|
+
it "can be used" do
|
25
|
+
assert client.execute(lambda { |conn| true })
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "ping" do
|
30
|
+
let(:ping_command) { ClamAV::Commands::PingCommand.new }
|
31
|
+
|
32
|
+
it "can be sent" do
|
33
|
+
assert client.execute(ping_command)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "can be sent multiple times" do
|
37
|
+
assert client.execute(ping_command)
|
38
|
+
assert client.execute(ping_command)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "can be used as #ping" do
|
42
|
+
assert_equal client.execute(ping_command), client.ping
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "scan" do
|
47
|
+
let(:base_path) { File.expand_path('../../../../', __FILE__) }
|
48
|
+
let(:dir) { File.join(base_path, 'test/fixtures') }
|
49
|
+
|
50
|
+
it "can be started" do
|
51
|
+
results = client.execute(ClamAV::Commands::ScanCommand.new(dir))
|
52
|
+
|
53
|
+
expected_results = {
|
54
|
+
"#{base_path}/test/fixtures/clamavtest.gz" => ClamAV::VirusResponse,
|
55
|
+
"#{base_path}/test/fixtures/clamavtest.txt" => ClamAV::VirusResponse,
|
56
|
+
"#{base_path}/test/fixtures/clamavtest.zip" => ClamAV::VirusResponse,
|
57
|
+
"#{base_path}/test/fixtures/innocent.txt" => ClamAV::SuccessResponse
|
58
|
+
}
|
59
|
+
|
60
|
+
results.each do |result|
|
61
|
+
expected_result = expected_results[result.file]
|
62
|
+
assert_equal expected_result, result.class
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can be used as #scan" do
|
67
|
+
assert_equal client.execute(ClamAV::Commands::ScanCommand.new(dir)), client.send(:scan, dir)
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "with timeout configuration" do
|
71
|
+
let(:client) { ClamAV::Client.new(connect_timeout: 1, write_timeout: 1, read_timeout: 1) }
|
72
|
+
|
73
|
+
it "can be started" do
|
74
|
+
results = client.execute(ClamAV::Commands::ScanCommand.new(dir))
|
75
|
+
|
76
|
+
expected_results = {
|
77
|
+
"#{base_path}/test/fixtures/clamavtest.gz" => ClamAV::VirusResponse,
|
78
|
+
"#{base_path}/test/fixtures/clamavtest.txt" => ClamAV::VirusResponse,
|
79
|
+
"#{base_path}/test/fixtures/clamavtest.zip" => ClamAV::VirusResponse,
|
80
|
+
"#{base_path}/test/fixtures/innocent.txt" => ClamAV::SuccessResponse
|
81
|
+
}
|
82
|
+
|
83
|
+
results.each do |result|
|
84
|
+
expected_result = expected_results[result.file]
|
85
|
+
assert_equal expected_result, result.class
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "instream" do
|
92
|
+
let(:dir) { File.expand_path('../../../../test/fixtures', __FILE__) }
|
93
|
+
|
94
|
+
it "can recognize a sane file" do
|
95
|
+
command = build_command_for_file('innocent.txt')
|
96
|
+
client.execute(command).must_equal ClamAV::SuccessResponse.new("stream")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "can recognize an infected file" do
|
100
|
+
command = build_command_for_file('clamavtest.txt')
|
101
|
+
client.execute(command).must_equal ClamAV::VirusResponse.new("stream", "ClamAV-Test-Signature")
|
102
|
+
end
|
103
|
+
|
104
|
+
it "can be used as #instream" do
|
105
|
+
io = File.open(File.join(dir, 'innocent.txt'))
|
106
|
+
assert_equal client.execute(ClamAV::Commands::InstreamCommand.new(io)), client.send(:instream, io)
|
107
|
+
end
|
108
|
+
|
109
|
+
def build_command_for_file(file)
|
110
|
+
io = File.open(File.join(dir, file))
|
111
|
+
ClamAV::Commands::InstreamCommand.new(io)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'safe?' do
|
116
|
+
let(:dir) { File.expand_path('../../../../test/fixtures', __FILE__) }
|
117
|
+
|
118
|
+
it 'returns true if the given io is safe' do
|
119
|
+
io = build_io_obj('innocent.txt')
|
120
|
+
assert client.safe?(io)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'returns false if the given io is infected' do
|
124
|
+
io = build_io_obj('clamavtest.txt')
|
125
|
+
refute client.safe?(io)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'returns false if there is any infected file in the given files' do
|
129
|
+
refute client.safe?(dir)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'returns true if all the give file is safe' do
|
133
|
+
assert client.safe?("#{dir}/innocent.txt")
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_io_obj(file)
|
137
|
+
content = File.read(File.join(dir, file))
|
138
|
+
io = StringIO.new(content)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'test_helper'
|
18
|
+
describe "ClamAV::Client Integration Tests" do
|
19
|
+
describe "Util" do
|
20
|
+
describe "absolute_path" do
|
21
|
+
it "transforms a single file to an array of one element" do
|
22
|
+
expected_path = File.absolute_path(__FILE__)
|
23
|
+
actual_path = ClamAV::Util.path_to_files(__FILE__).first
|
24
|
+
assert_equal expected_path, actual_path
|
25
|
+
end
|
26
|
+
|
27
|
+
it "transforms a directory to an array of N element" do
|
28
|
+
files = %w(
|
29
|
+
clamav-client/test/integration/clamav/client_test.rb
|
30
|
+
clamav-client/test/integration/clamav/util_test.rb
|
31
|
+
).sort
|
32
|
+
actual_files = ClamAV::Util.path_to_files(File.dirname(__FILE__)).sort
|
33
|
+
|
34
|
+
files.each_with_index do |file, index|
|
35
|
+
path = Regexp.new(".*/#{file}")
|
36
|
+
assert path.match(actual_files[index])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
gem 'minitest'
|
18
|
+
|
19
|
+
require 'minitest/autorun'
|
20
|
+
require 'clamav/client'
|
21
|
+
require 'pry'
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# clamav-client - ClamAV client
|
2
|
+
# Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
|
3
|
+
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'test_helper'
|
18
|
+
|
19
|
+
describe "ClamAV::Client" do
|
20
|
+
describe "connect!" do
|
21
|
+
let(:conn_mock) { Minitest::Mock.new }
|
22
|
+
let(:client) { ClamAV::Client.new }
|
23
|
+
|
24
|
+
it "opens the connection" do
|
25
|
+
conn_mock.expect(:establish_connection, nil)
|
26
|
+
|
27
|
+
client.connect!(conn_mock)
|
28
|
+
|
29
|
+
conn_mock.verify
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'raises an custom error if connection times out' do
|
33
|
+
conn_mock.expect(:establish_connection, nil) do
|
34
|
+
raise Errno::ETIMEDOUT
|
35
|
+
end
|
36
|
+
|
37
|
+
assert_raises(ClamAV::Client::ConnectTimeoutError) { client.connect!(conn_mock) }
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'raises an custom error if something goes wrong' do
|
41
|
+
conn_mock.expect(:establish_connection, nil) do
|
42
|
+
raise SocketError
|
43
|
+
end
|
44
|
+
|
45
|
+
assert_raises(ClamAV::Client::ConnectionError) { client.connect!(conn_mock) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "tcp?" do
|
50
|
+
it "returns true when config is tcp" do
|
51
|
+
assert client = ClamAV::Client.new(tcp_host: 'example', tcp_port: 3310).tcp?
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns false when config is not tcp" do
|
55
|
+
refute client = ClamAV::Client.new.tcp?
|
56
|
+
refute client = ClamAV::Client.new(unix_socket: '/some.sock').tcp?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|