clamav-client 1.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: adce3820c1acb8ee407dfe43d13cc0fbff8871ca
4
- data.tar.gz: ba5be7eb98e86a26030a7da773f46c6abeb096a6
3
+ metadata.gz: 0e16bf843318d1ae3aec44e522c278143affc3d2
4
+ data.tar.gz: 100e606c288e5a6a3a46a0537e4d4f6f0d989b9c
5
5
  SHA512:
6
- metadata.gz: 9249db0df3fde3b800dfb47dae0aae73884f7d6db27a764bee4df9bb30dba67fba1cfe94098b863eafd999c78a1652c7a04f3b4f3b9ff40d58dc5f3475c96bb4
7
- data.tar.gz: fdde76cc4230eb0577f1637c9d5d1e72ff0a3e41bbcbc3f8e1e9d7939018f2ba90fe45f71252e8425419cd02a2fef2ff3dc8794bdea4addc71b6ba92bcbb6a6e
6
+ metadata.gz: 06d3e9d069ff7875b6f499c78adfbdaae9a29a030fd38f68435393e322cfa3c407c0d53a72d4067550cfa0b09c3da73858c4d944b8ce46f31c95ccb4d3484a0e
7
+ data.tar.gz: 141d5420ccd5fc6a90332b77184b5c1c593d2b27ce297a2b498677cc7b176a87aa3dffdd86f13173492912f47ed2906faba88daa17280407fbffb092d11df4a4
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - 1.9.2
7
+ - ruby-head
8
+ - jruby-19mode
9
+ - jruby-head
10
+ - rbx
11
+ script: rake unit_tests
data/README.md CHANGED
@@ -22,7 +22,7 @@ Alternatively, you can spawn a `pry` console right away by just running:
22
22
 
23
23
  ## Requirements
24
24
 
25
- * Ruby >= 2 (and Ruby >= 2.1 to be able to contribute to the project as it's making use of required keyword arguments)
25
+ * Ruby >= 1.9.2
26
26
  * clamd
27
27
 
28
28
  ## Usage
@@ -30,15 +30,17 @@ Alternatively, you can spawn a `pry` console right away by just running:
30
30
  The `ClamAV::Client` class is responsible for opening a connection to a remote
31
31
  ClamAV clam daemon.
32
32
 
33
- You will find below the implemented commands.
33
+ See the implemented commands below.
34
34
 
35
35
  ### PING => Boolean
36
36
 
37
37
  Pings the daemon to check whether it is alive.
38
38
 
39
- client = ClamAV::Client.new
40
- client.execute(ClamAV::Commands::PingCommand.new)
41
- => true
39
+ ```ruby
40
+ client = ClamAV::Client.new
41
+ client.execute(ClamAV::Commands::PingCommand.new)
42
+ # => true
43
+ ```
42
44
 
43
45
  ### SCAN <file_or_directory> => Array[Response]
44
46
 
@@ -46,56 +48,73 @@ Scans a file or a directory for the existence of a virus.
46
48
 
47
49
  The absolute path must be given to that command.
48
50
 
49
- client = ClamAV::Client.new
51
+ ```ruby
52
+ client = ClamAV::Client.new
50
53
 
51
- client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path/foo.c')
52
- => [#<ClamAV::SuccessResponse:0x007fbf314b9478 @file="/tmp/foo.c">]
54
+ client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path/foo.c'))
55
+ # => [#<ClamAV::SuccessResponse:0x007fbf314b9478 @file="/tmp/foo.c">]
53
56
 
54
- client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path')
55
- => [#<ClamAV::SuccessResponse:0x007fc30c273298 @file="/tmp/path/foo.c">,
56
- #<ClamAV::SuccessResponse:0x007fc30c272910 @file="/tmp/path/foo.cpp">]
57
+ client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path'))
58
+ # => [#<ClamAV::SuccessResponse:0x007fc30c273298 @file="/tmp/path/foo.c">,
59
+ # #<ClamAV::SuccessResponse:0x007fc30c272910 @file="/tmp/path/foo.cpp">]
60
+ ```
57
61
 
62
+ ### INSTREAM => Response
63
+
64
+ Scans an IO-like object for the existence of a virus.
65
+
66
+ ```ruby
67
+ client = ClamAV::Client.new
68
+
69
+ io = StringIO.new('some data')
70
+ client.execute(ClamAV::Commands::InstreamCommand.new(io))
71
+ # => [#<ClamAV::SuccessResponse:0x007fe471cabe50 @file="stream">]
72
+ ```
58
73
 
59
74
  ### Custom commands
60
75
 
61
76
  Custom commands can be given to the client. The contract between the client
62
- and the command is thru the `call` method call. The `call` method is being
63
- passed a `Connection` object.
64
-
65
- Here's a simple example that implements the `VERSION` command:
77
+ and the command is through the `Command#call` method. The `call` method will
78
+ receive a `Connection` object.
66
79
 
67
- # Build the client
68
- client = ClamAV::Client.new
80
+ Here's a simple example implementing the `VERSION` command:
69
81
 
70
- # Create the command lambda
71
- version_command = lambda { |conn| conn.send_request("VERSION") }
72
- => #<Proc:0x007fc0d0c14b28>
82
+ ```ruby
83
+ # Build the client
84
+ client = ClamAV::Client.new
73
85
 
74
- # Execute the command
75
- client.execute(version_command)
76
- => "1: ClamAV 0.98.1/18489/Tue Feb 18 16:00:05 2014"
86
+ # Create the command lambda
87
+ version_command = lambda { |conn| conn.send_request("VERSION") }
88
+ # => #<Proc:0x007fc0d0c14b28>
77
89
 
90
+ # Execute the command
91
+ client.execute(version_command)
92
+ # => "1: ClamAV 0.98.1/18489/Tue Feb 18 16:00:05 2014"
93
+ ```
78
94
 
79
95
  ## Defaults
80
96
 
81
97
  The default values in use are:
82
98
 
83
- * clamd socket: UNIX Socket, located at `/tmp/clamd/socket`;
99
+ * clamd socket: UNIX Socket, located at `/var/run/clamav/clamd.ctl`;
84
100
  * New-line terminated commands.
85
101
 
86
- These defaults can be changed by injecting new defaults.
102
+ These defaults can be changed:
87
103
 
88
- ## Injecting dependencies
104
+ * by creating the object graph manually;
105
+ * by setting environment variables.
89
106
 
90
- ### Client
107
+ ### The object graph
108
+
109
+ #### Client
91
110
 
92
111
  The main object is the `Client` object. It is responsible for executing the commands.
93
- This object can receive a custom connection object.
112
+ It can receive a custom connection object.
94
113
 
95
- ### Connection
114
+ #### Connection
96
115
 
97
- The connection object is the bridge between the raw socket object and the
98
- protocol being used between the client and the daemon.
116
+ The `Connection` object is the bridge between the raw socket object and the
117
+ protocol used between the client and the daemon.
99
118
 
100
119
  `clamd` supports two kinds of delimiters:
101
120
 
@@ -104,12 +123,43 @@ protocol being used between the client and the daemon.
104
123
 
105
124
  The management of those delimiters is done with the wrapper argument.
106
125
 
107
- ### Wrapper
126
+ #### Wrapper
108
127
 
109
128
  The wrapper is responsible for taking the incoming request with the
110
129
  `wrap_request` method, and parsing the response with the `read_response`
111
130
  method.
112
131
 
132
+ ### Environment variables
133
+
134
+ The variables can be set programmatically in your Ruby programs like
135
+
136
+ ```ruby
137
+ # from a ruby script
138
+ ENV['CLAMD_UNIX_SOCKET'] = '/some/path'
139
+
140
+ # Now the defaults are changed for any new ClamAV::Client instantiation
141
+ ```
142
+
143
+ or by setting the variables before starting the Ruby process:
144
+
145
+ ```
146
+ # from the command-line
147
+ export CLAMD_UNIX_SOCKET = '/some/path'
148
+ ruby my_program.rb
149
+ # or
150
+ CLAMD_UNIX_SOCKET = '/some/path' ruby my_program.rb
151
+ ```
152
+
153
+ Please note that setting the `CLAMD_TCP_*` variables will have the precedence
154
+ over the `CLAMD_UNIX_SOCKET`.
155
+
156
+ #### CLAMD_UNIX_SOCKET
157
+
158
+ Sets the socket path of the ClamAV daemon.
159
+
160
+ #### CLAMD_TCP_HOST and CLAMD_TCP_PORT
161
+
162
+ Sets the host and port of the ClamAV daemon.
113
163
 
114
164
  ## Contributing
115
165
 
@@ -3,7 +3,7 @@ $:<< 'lib'
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "clamav-client"
6
- spec.version = "1.0.0"
6
+ spec.version = "2.0.1"
7
7
  spec.authors = ["Franck Verrot"]
8
8
  spec.email = ["franck@verrot.fr"]
9
9
  spec.summary = %q{ClamAV::Client connects to a Clam Anti-Virus clam daemon and send commands.}
@@ -19,4 +19,5 @@ Gem::Specification.new do |spec|
19
19
  spec.add_development_dependency "bundler", "~> 1.5"
20
20
  spec.add_development_dependency "rake"
21
21
  spec.add_development_dependency "pry"
22
+ spec.add_development_dependency "minitest"
22
23
  end
@@ -18,6 +18,7 @@ require "clamav/connection"
18
18
  require "clamav/commands/ping_command"
19
19
  require "clamav/commands/quit_command"
20
20
  require "clamav/commands/scan_command"
21
+ require "clamav/commands/instream_command"
21
22
  require "clamav/util"
22
23
  require "clamav/wrappers/new_line_wrapper"
23
24
  require "clamav/wrappers/null_termination_wrapper"
@@ -30,14 +31,23 @@ module ClamAV
30
31
  end
31
32
 
32
33
  def execute(command)
33
- command.(@connection)
34
+ command.call(@connection)
34
35
  end
35
36
 
36
37
  def default_connection
37
38
  ClamAV::Connection.new(
38
- socket: ::UNIXSocket.new('/tmp/clamd.socket'),
39
+ socket: resolve_default_socket,
39
40
  wrapper: ::ClamAV::Wrappers::NewLineWrapper.new
40
41
  )
41
42
  end
43
+
44
+ def resolve_default_socket
45
+ unix_socket, tcp_host, tcp_port = ENV.values_at('CLAMD_UNIX_SOCKET', 'CLAMD_TCP_HOST', 'CLAMD_TCP_PORT')
46
+ if tcp_host && tcp_port
47
+ ::TCPSocket.new(tcp_host, tcp_port)
48
+ else
49
+ ::UNIXSocket.new(unix_socket || '/var/run/clamav/clamd.ctl')
50
+ end
51
+ end
42
52
  end
43
53
  end
@@ -13,20 +13,34 @@
13
13
 
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'clamav/responses/error_response'
18
+ require 'clamav/responses/success_response'
19
+ require 'clamav/responses/virus_response'
20
+
16
21
  module ClamAV
17
22
  module Commands
18
23
  class Command
19
- def call
20
- raise NotImplementedError.new
21
- end
24
+ Statuses = {
25
+ 'OK' => ClamAV::SuccessResponse,
26
+ 'ERROR' => ClamAV::ErrorResponse,
27
+ 'ClamAV-Test-Signature FOUND' => ClamAV::VirusResponse
28
+ }
29
+
30
+ def call; raise NotImplementedError.new; end
22
31
 
23
32
  protected
24
- def execute
25
- conn.puts data + "\n"
26
- response = conn.gets.chomp
27
- conn.close
28
- response
29
- end
33
+
34
+ def get_status_from_response(str)
35
+ case str
36
+ when 'Error processing command. ERROR'
37
+ ErrorResponse.new(str)
38
+ else
39
+ /(?<id>\d+): (?<filepath>.*): (?<status>.*)/ =~ str
40
+ Statuses[status].new(filepath)
41
+ end
42
+ end
43
+
30
44
  end
31
45
  end
32
46
  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 'clamav/commands/command'
18
+
19
+ module ClamAV
20
+ module Commands
21
+ class InstreamCommand < Command
22
+
23
+ def initialize(io, max_chunk_size = 1024)
24
+ @io = begin io rescue raise ArgumentError, 'io is required', caller; end
25
+ @max_chunk_size = max_chunk_size
26
+ end
27
+
28
+ def call(conn)
29
+ conn.write_request("INSTREAM")
30
+
31
+ while(packet = @io.read(@max_chunk_size))
32
+ packet_size = [packet.size].pack("N")
33
+ conn.raw_write("#{packet_size}#{packet}")
34
+ end
35
+ conn.raw_write("\x00\x00\x00\x00")
36
+ get_status_from_response(conn.read_response)
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -15,17 +15,10 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'clamav/commands/command'
18
- require 'clamav/responses/error_response'
19
- require 'clamav/responses/success_response'
20
- require 'clamav/responses/virus_response'
18
+
21
19
  module ClamAV
22
20
  module Commands
23
21
  class ScanCommand < Command
24
- Statuses = {
25
- 'ERROR' => ClamAV::ErrorResponse,
26
- 'OK' => ClamAV::SuccessResponse,
27
- 'ClamAV-Test-Signature FOUND' => ClamAV::VirusResponse
28
- }
29
22
 
30
23
  def initialize(path, path_finder = Util)
31
24
  @path, @path_finder = path, path_finder
@@ -35,20 +28,10 @@ module ClamAV
35
28
  @path_finder.path_to_files(@path).map { |file| scan_file(conn, file) }
36
29
  end
37
30
 
38
- protected
39
31
  def scan_file(conn, file)
40
32
  get_status_from_response(conn.send_request("SCAN #{file}"))
41
33
  end
42
34
 
43
- def get_status_from_response(str)
44
- case str
45
- when 'Error processing command. ERROR'
46
- ErrorResponse.new(str)
47
- else
48
- /(?<id>\d+): (?<filepath>.*): (?<status>.*)/ =~ str
49
- Statuses[status].new(filepath)
50
- end
51
- end
52
35
  end
53
36
  end
54
37
  end
@@ -18,9 +18,16 @@ require 'socket'
18
18
 
19
19
  module ClamAV
20
20
  class Connection
21
- def initialize(socket:, wrapper:)
22
- @socket = socket
23
- @wrapper = wrapper
21
+ def initialize(args)
22
+ socket = args.fetch(:socket) { missing_required_argument(:socket) }
23
+ wrapper = args.fetch(:wrapper) { missing_required_argument(:wrapper) }
24
+
25
+ if socket && wrapper
26
+ @socket = socket
27
+ @wrapper = wrapper
28
+ else
29
+ raise ArgumentError
30
+ end
24
31
  end
25
32
 
26
33
  def establish_connection
@@ -28,10 +35,27 @@ module ClamAV
28
35
  @socket.write wrapped_request
29
36
  end
30
37
 
31
- def send_request(str)
38
+ def write_request(str)
32
39
  wrapped_request = @wrapper.wrap_request(str)
33
40
  @socket.write wrapped_request
41
+ end
42
+
43
+ def read_response
34
44
  @wrapper.read_response(@socket)
35
45
  end
46
+
47
+ def send_request(str)
48
+ write_request(str)
49
+ read_response
50
+ end
51
+
52
+ def raw_write(str)
53
+ @socket.write str
54
+ end
55
+
56
+ private
57
+ def missing_required_argument(key)
58
+ raise ArgumentError, "#{key} is required"
59
+ end
36
60
  end
37
61
  end
@@ -21,10 +21,12 @@ module ClamAV
21
21
  end
22
22
 
23
23
  def ==(other)
24
- @file == other.file
24
+ @file == other.file && self.class == other.class
25
25
  end
26
26
 
27
27
  protected
28
+
28
29
  attr_reader :file
30
+
29
31
  end
30
32
  end
@@ -15,6 +15,7 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'clamav/responses'
18
+
18
19
  module ClamAV
19
20
  class ErrorResponse < Response
20
21
  end
@@ -15,6 +15,7 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'clamav/responses'
18
+
18
19
  module ClamAV
19
20
  class SuccessResponse < Response
20
21
  end
@@ -15,6 +15,7 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'clamav/responses'
18
+
18
19
  module ClamAV
19
20
  class VirusResponse < Response
20
21
  end
@@ -18,5 +18,14 @@ module ClamAV
18
18
  class Wrapper
19
19
  def wrap_request(request); raise NotImplementedError; end
20
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
+ end
21
30
  end
22
31
  end
@@ -24,11 +24,7 @@ module ClamAV
24
24
  end
25
25
 
26
26
  def read_response(socket)
27
- buff = ""
28
- while (char = socket.getc) != "\n"
29
- buff << char
30
- end
31
- buff
27
+ read_until(socket, "\n")
32
28
  end
33
29
  end
34
30
  end
@@ -24,11 +24,7 @@ module ClamAV
24
24
  end
25
25
 
26
26
  def read_response(socket)
27
- buff = ""
28
- while (char = socket.getc) != "\0"
29
- buff << char
30
- end
31
- buff
27
+ read_until(socket, "\0")
32
28
  end
33
29
  end
34
30
  end
@@ -53,5 +53,20 @@ describe "ClamAV::Client Integration Tests" do
53
53
  assert_equal expected_results, results
54
54
  end
55
55
  end
56
+
57
+ describe "instream" do
58
+ it "can be started" do
59
+ dir = File.expand_path('../../../../test/fixtures', __FILE__)
60
+
61
+ [
62
+ ['clamavtest.txt', ClamAV::VirusResponse],
63
+ ['innocent.txt', ClamAV::SuccessResponse]
64
+ ].each do |file, response_class|
65
+ io = File.open(File.join(dir, file))
66
+ command = ClamAV::Commands::InstreamCommand.new(io)
67
+ client.execute(command).must_equal response_class.new("stream")
68
+ end
69
+ end
70
+ end
56
71
  end
57
72
  end
@@ -14,6 +14,8 @@
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
- require 'minitest/autorun'
17
+ gem 'minitest'
18
18
 
19
+ require 'minitest/autorun'
19
20
  require 'clamav/client'
21
+ require 'pry'
@@ -0,0 +1,53 @@
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 "INSTREAM command" do
20
+ before do
21
+ @conn = Minitest::Mock.new
22
+ @io = ::StringIO.new('hello')
23
+ end
24
+
25
+ after do
26
+ @conn.verify
27
+ end
28
+
29
+ it "can process an IO object" do
30
+ @conn.expect(:write_request, nil, ["INSTREAM"])
31
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x05hello"])
32
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x00"])
33
+ @conn.expect(:read_response, '1: stream: OK', [])
34
+
35
+ assert ClamAV::Commands::InstreamCommand.new(@io).call(@conn)
36
+ end
37
+
38
+ it "can specify the size of read chunks" do
39
+ chunk_size = 1
40
+
41
+ @conn.expect(:write_request, nil, ["INSTREAM"])
42
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x01h"])
43
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x01e"])
44
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x01l"])
45
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x01l"])
46
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x01o"])
47
+ @conn.expect(:raw_write, nil, ["\x00\x00\x00\x00"])
48
+ @conn.expect(:read_response, '1: stream: OK', [])
49
+
50
+ assert ClamAV::Commands::InstreamCommand.
51
+ new(@io, chunk_size).call(@conn)
52
+ end
53
+ end
@@ -18,7 +18,7 @@ require 'test_helper'
18
18
 
19
19
  describe "ClamAV::Connection" do
20
20
  let(:wrapper_mock) { Minitest::Mock.new }
21
- let(:socket_mock) { Minitest::Mock.new }
21
+ let(:socket_mock) { Minitest::Mock.new }
22
22
 
23
23
  it "requires a port and a wrapper" do
24
24
  assert_raises(ArgumentError) { ClamAV::Connection.new }
@@ -29,4 +29,11 @@ describe "ClamAV::Connection" do
29
29
  it "can be constructed with a port and wrapper class" do
30
30
  ClamAV::Connection.new(socket: socket_mock, wrapper: wrapper_mock)
31
31
  end
32
+
33
+ it "support raw writes" do
34
+ socket_mock.expect(:write, nil, ["foo"])
35
+
36
+ conn = ClamAV::Connection.new(socket: socket_mock, wrapper: wrapper_mock)
37
+ conn.raw_write("foo")
38
+ end
32
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clamav-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franck Verrot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-20 00:00:00.000000000 Z
11
+ date: 2014-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: ClamAV::Client connects to a Clam Anti-Virus clam daemon and send commands.
56
70
  email:
57
71
  - franck@verrot.fr
@@ -60,6 +74,7 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - ".gitignore"
77
+ - ".travis.yml"
63
78
  - Gemfile
64
79
  - LICENSE.txt
65
80
  - README.md
@@ -67,6 +82,7 @@ files:
67
82
  - clamav-client.gemspec
68
83
  - lib/clamav/client.rb
69
84
  - lib/clamav/commands/command.rb
85
+ - lib/clamav/commands/instream_command.rb
70
86
  - lib/clamav/commands/ping_command.rb
71
87
  - lib/clamav/commands/quit_command.rb
72
88
  - lib/clamav/commands/scan_command.rb
@@ -87,6 +103,7 @@ files:
87
103
  - test/integration/clamav/util_test.rb
88
104
  - test/test_helper.rb
89
105
  - test/unit/clamav/client_test.rb
106
+ - test/unit/clamav/commands/instream_command_test.rb
90
107
  - test/unit/clamav/commands/ping_command_test.rb
91
108
  - test/unit/clamav/commands/scan_command_test.rb
92
109
  - test/unit/clamav/connection_test.rb
@@ -125,6 +142,7 @@ test_files:
125
142
  - test/integration/clamav/util_test.rb
126
143
  - test/test_helper.rb
127
144
  - test/unit/clamav/client_test.rb
145
+ - test/unit/clamav/commands/instream_command_test.rb
128
146
  - test/unit/clamav/commands/ping_command_test.rb
129
147
  - test/unit/clamav/commands/scan_command_test.rb
130
148
  - test/unit/clamav/connection_test.rb