ddr-antivirus 1.3.3 → 2.0.0.rc1
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 +4 -4
- data/.rspec +0 -1
- data/.travis.yml +3 -10
- data/Gemfile +0 -2
- data/README.md +41 -53
- data/ddr-antivirus.gemspec +0 -2
- data/lib/ddr/antivirus.rb +40 -34
- data/lib/ddr/antivirus/adapters/clamd_scanner_adapter.rb +66 -51
- data/lib/ddr/antivirus/adapters/null_scanner_adapter.rb +10 -22
- data/lib/ddr/antivirus/scan_result.rb +35 -0
- data/lib/ddr/antivirus/scanner.rb +9 -29
- data/lib/ddr/antivirus/scanner_adapter.rb +29 -0
- data/lib/ddr/antivirus/version.rb +1 -1
- data/spec/spec_helper.rb +2 -20
- data/spec/unit/clamd_scanner_adapter_spec.rb +63 -57
- metadata +6 -46
- data/lib/ddr/antivirus/adapters.rb +0 -14
- data/lib/ddr/antivirus/adapters/clamav_scanner_adapter.rb +0 -82
- data/lib/ddr/antivirus/adapters/scan_result.rb +0 -61
- data/lib/ddr/antivirus/adapters/scanner_adapter.rb +0 -25
- data/spec/shared_examples_for_scan_results.rb +0 -53
- data/spec/unit/clamav_scanner_adapter_spec.rb +0 -66
- data/spec/unit/null_scanner_adapter_spec.rb +0 -24
- data/spec/unit/scan_result_spec.rb +0 -27
- data/spec/unit/scanner_spec.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e16210de6035eef0c49f80ce61c7f2dee7b3fc88
|
4
|
+
data.tar.gz: bb79eb5e1a8aa063773e160855589f28e54f4dfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d7e101d5f4d85ff8067c2ccc8a98e88cb763cc96df60f719ca6831048058aed7c3b36fa18a68fa4acb65099b78b393ff6fc1b09da5992bbd00e9a9c5d2ff1d5
|
7
|
+
data.tar.gz: 7c48dd3ef7c397e26ac8fa3a0b7860336b6af332ade18327e5be016b1b98b79136f4aa8d445edeb5cdc50a139a3185ae274d9a22e2512baecf751aa283fb0e59
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -1,15 +1,8 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
2
|
-
before_install:
|
3
|
-
- sudo apt-get update -qq
|
4
|
-
- sudo apt-get install -y libclamav-dev clamav clamav-daemon clamav-freshclam
|
5
|
-
before_script:
|
6
|
-
- sudo freshclam
|
7
|
-
- sudo /etc/init.d/clamav-daemon start
|
8
3
|
rvm:
|
9
4
|
- 2.1
|
5
|
+
- 2.2
|
10
6
|
cache:
|
11
7
|
- bundler
|
12
|
-
|
13
|
-
notifications:
|
14
|
-
email:
|
15
|
-
- lib-drs@duke.edu
|
8
|
+
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,8 +4,6 @@ Pluggable antivirus service for Ruby applications.
|
|
4
4
|
|
5
5
|
[](http://badge.fury.io/rb/ddr-antivirus)
|
6
6
|
[](https://travis-ci.org/duke-libraries/ddr-antivirus)
|
7
|
-
[](https://coveralls.io/r/duke-libraries/ddr-antivirus?branch=develop)
|
8
|
-
[](https://codeclimate.com/github/duke-libraries/ddr-antivirus)
|
9
7
|
|
10
8
|
## Installation
|
11
9
|
|
@@ -21,74 +19,57 @@ Or install it yourself as:
|
|
21
19
|
|
22
20
|
$ gem install ddr-antivirus
|
23
21
|
|
24
|
-
## How It Works
|
25
|
-
|
26
|
-
Ddr::Antivirus does *not* provide a virus scanning engine as a runtime dependency. Instead, it will select a scanner adapter class for the software it finds in your environment following this procedure:
|
27
|
-
|
28
|
-
- If the [clamav](https://github.com/eagleas/clamav) gem is available, it will select the `ClamavScannerAdapter`.
|
29
|
-
- If the ClamAV Daemon client `clamdscan` is on the user's path, it will select the `ClamdScannerAdapter`. Ddr::Antivirus *does not* manage clamd -- i.e., checking its status, starting or reloading the database. These tasks must be managed externally.
|
30
|
-
- Otherwise, it will select the [`NullScannerAdapter`](#the-nullscanneradapter).
|
31
|
-
|
32
|
-
The auto-selection process may be overridden by configuration:
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
Ddr::Antivirus.configure do |config|
|
36
|
-
config.scanner_adapter = :clamd # or :clamav, or :null
|
37
|
-
end
|
38
|
-
```
|
39
|
-
|
40
|
-
## Usage
|
41
|
-
|
42
22
|
### Scanning ###
|
43
23
|
|
44
|
-
Class: `Ddr::Antivirus::Scanner`
|
45
|
-
|
46
24
|
```ruby
|
47
25
|
require "ddr-antivirus"
|
48
26
|
|
49
|
-
|
50
|
-
result = Ddr::Antivirus::Scanner.scan(path)
|
27
|
+
result = Ddr::Antivirus.scan(path)
|
51
28
|
|
52
|
-
|
53
|
-
Ddr::Antivirus::Scanner.new do |scanner|
|
29
|
+
Ddr::Antivirus.scanner do |scanner|
|
54
30
|
result = scanner.scan(path)
|
55
31
|
end
|
56
32
|
```
|
57
33
|
|
58
|
-
|
34
|
+
### Exceptions
|
59
35
|
|
60
|
-
|
36
|
+
All exceptions under the `Ddr::Antivirus` namespace.
|
61
37
|
|
62
|
-
|
38
|
+
`Error` - Parent exception class.
|
63
39
|
|
64
|
-
A
|
40
|
+
`VirusFoundError` - A virus was found. The message includes the original output from the scanner.
|
65
41
|
|
66
|
-
|
67
|
-
>> require "ddr-antivirus"
|
68
|
-
=> true
|
42
|
+
`ScannerError` - The scanner encountered an error (e.g., error exit status).
|
69
43
|
|
70
|
-
|
71
|
-
=> #<Ddr::Antivirus::Adapters::ClamavScanResult:0x007f98fb169cc0 ...
|
44
|
+
### Example
|
72
45
|
|
73
|
-
|
74
|
-
|
75
|
-
=>
|
46
|
+
```
|
47
|
+
> require 'ddr/antivirus'
|
48
|
+
=> true
|
49
|
+
|
50
|
+
> Ddr::Antivirus.scanner_adapter = :clamd
|
51
|
+
=> :clamd
|
52
|
+
|
53
|
+
> result = Ddr::Antivirus.scan "/path/to/image.jpg"
|
54
|
+
=> #<Ddr::Antivirus::ScanResult:0x007f98f8b95670 @file_path="/path/to/image.jpg", @output="/path/to/image.jpg: OK\n\n----------- SCAN SUMMARY -----------\nInfected files: 0\nTime: 0.001 sec (0 m 0 s)\n", @scanned_at=2015-09-11 20:41:17 UTC, @version="ClamAV 0.98.7/20903/Fri Sep 11 08:42:07 2015">
|
55
|
+
|
56
|
+
> result.version
|
57
|
+
=> "ClamAV 0.98.7/20903/Fri Sep 11 08:42:07 2015"
|
76
58
|
|
77
|
-
|
78
|
-
|
79
|
-
=> false
|
59
|
+
> result.scanned_at
|
60
|
+
=> 2015-09-11 20:41:17 UTC
|
80
61
|
|
81
|
-
|
82
|
-
|
83
|
-
=> true
|
62
|
+
> result.output
|
63
|
+
=> "/path/to/image.jpg: OK\n\n----------- SCAN SUMMARY -----------\nInfected files: 0\nTime: 0.001 sec (0 m 0 s)\n"
|
84
64
|
|
85
|
-
|
86
|
-
|
87
|
-
=> 0 # ClamAV example
|
65
|
+
> puts result.to_s
|
66
|
+
/path/to/image.jpg: OK
|
88
67
|
|
89
|
-
|
90
|
-
|
91
|
-
|
68
|
+
----------- SCAN SUMMARY -----------
|
69
|
+
Infected files: 0
|
70
|
+
Time: 0.001 sec (0 m 0 s)
|
71
|
+
|
72
|
+
[ClamAV 0.98.7/20903/Fri Sep 11 08:42:07 2015]
|
92
73
|
```
|
93
74
|
|
94
75
|
### Logging
|
@@ -104,12 +85,19 @@ Ddr::Antivirus.logger = Logger.new("/path/to/custom.log")
|
|
104
85
|
|
105
86
|
In order to avoid the overhead of ClamAV in test and/or development environments, the package provides a no-op adapter:
|
106
87
|
|
107
|
-
```
|
88
|
+
```
|
108
89
|
>> Ddr::Antivirus.scanner_adapter = :null
|
109
90
|
=> :null
|
110
91
|
>> Ddr::Antivirus::Scanner.scan("/path/to/blue-devil.png")
|
111
|
-
|
112
|
-
|
92
|
+
=> #<Ddr::Antivirus::NullScanResult:0x007f9e2ba1af38 @output="/path/to/blue-devil.png: NOT SCANNED - using :null scanner adapter.", @file_path="/path/to/blue-devil.png", @scanned_at=2014-11-07 20:58:17 UTC, @version="ddr-antivirus 1.2.0">
|
93
|
+
```
|
94
|
+
|
95
|
+
### Test Mode
|
96
|
+
|
97
|
+
To easily configure `Ddr::Antivirus` to use the `NullScannerAdapter` and log to the null device, turn on test mode:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
Ddr::Antivirus.test_mode!
|
113
101
|
```
|
114
102
|
|
115
103
|
## Contributing
|
data/ddr-antivirus.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activesupport", "~> 4.0"
|
22
21
|
spec.add_development_dependency "bundler", "~> 1.6"
|
23
22
|
spec.add_development_dependency "rake"
|
24
|
-
spec.add_development_dependency "clamav"
|
25
23
|
spec.add_development_dependency "rspec", "~> 3.0"
|
26
24
|
end
|
data/lib/ddr/antivirus.rb
CHANGED
@@ -2,50 +2,56 @@ require "logger"
|
|
2
2
|
|
3
3
|
require_relative "antivirus/version"
|
4
4
|
require_relative "antivirus/scanner"
|
5
|
-
require_relative "antivirus/
|
6
|
-
|
7
|
-
|
5
|
+
require_relative "antivirus/scan_result"
|
6
|
+
require_relative "antivirus/scanner_adapter"
|
7
|
+
require_relative "antivirus/adapters/null_scanner_adapter"
|
8
8
|
|
9
9
|
module Ddr
|
10
10
|
module Antivirus
|
11
11
|
|
12
|
-
class
|
12
|
+
class Error < ::StandardError; end
|
13
|
+
class VirusFoundError < Error; end
|
14
|
+
class ScannerError < Error; end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
end
|
16
|
+
class << self
|
17
|
+
attr_accessor :logger, :scanner_adapter
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if defined?(Rails) && Rails.logger
|
25
|
-
Rails.logger
|
26
|
-
else
|
27
|
-
Logger.new(STDERR)
|
19
|
+
def configure
|
20
|
+
yield self
|
21
|
+
end
|
22
|
+
|
23
|
+
def scan(path)
|
24
|
+
Scanner.scan(path)
|
28
25
|
end
|
29
|
-
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
27
|
+
def scanner
|
28
|
+
s = Scanner.new
|
29
|
+
block_given? ? yield(s) : s
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_mode!
|
33
|
+
configure do |config|
|
34
|
+
config.logger = Logger.new(File::NULL)
|
35
|
+
config.scanner_adapter = :null
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Class] the scanner adapter class
|
40
|
+
def get_adapter
|
41
|
+
if scanner_adapter.nil?
|
42
|
+
raise Error, "`Ddr::Antivirus.scanner_adapter` is not configured."
|
43
|
+
end
|
44
|
+
require_relative "antivirus/adapters/#{scanner_adapter}_scanner_adapter"
|
45
|
+
adapter_name = scanner_adapter.to_s.capitalize + "ScannerAdapter"
|
46
|
+
self.const_get(adapter_name, false)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
self.logger = if defined?(Rails) && Rails.logger
|
51
|
+
Rails.logger
|
52
|
+
else
|
53
|
+
Logger.new(STDERR)
|
54
|
+
end
|
55
|
+
|
50
56
|
end
|
51
57
|
end
|
@@ -1,69 +1,84 @@
|
|
1
|
+
require "open3"
|
1
2
|
require "fileutils"
|
2
|
-
|
3
|
-
require_relative "scan_result"
|
3
|
+
require "shellwords"
|
4
4
|
|
5
|
-
module Ddr
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
class ClamdScannerAdapter < ScannerAdapter
|
5
|
+
module Ddr::Antivirus
|
6
|
+
#
|
7
|
+
# Adapter for clamd client (clamdscan)
|
8
|
+
#
|
9
|
+
class ClamdScannerAdapter < ScannerAdapter
|
12
10
|
|
13
|
-
|
14
|
-
raw = clamdscan(path)
|
15
|
-
ClamdScanResult.new(raw, path)
|
16
|
-
end
|
17
|
-
|
18
|
-
def clamdscan(path)
|
19
|
-
original_mode = File.stat(path).mode
|
20
|
-
FileUtils.chmod("a+r", path) unless File.world_readable?(path)
|
21
|
-
result = command(path)
|
22
|
-
FileUtils.chmod(original_mode, path) if File.stat(path).mode != original_mode
|
23
|
-
result
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def command(path)
|
29
|
-
`clamdscan --no-summary "#{path}"`.strip
|
30
|
-
end
|
11
|
+
SCANNER = "clamdscan".freeze
|
31
12
|
|
13
|
+
def scan(path)
|
14
|
+
output, status = clamdscan(path)
|
15
|
+
result = ScanResult.new(path, output, version: version, scanned_at: Time.now.utc)
|
16
|
+
case status.exitstatus
|
17
|
+
when 0
|
18
|
+
result
|
19
|
+
when 1
|
20
|
+
raise VirusFoundError, result.to_s
|
21
|
+
when 2
|
22
|
+
raise ScannerError, result.to_s
|
32
23
|
end
|
24
|
+
end
|
33
25
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
26
|
+
def clamdscan(path)
|
27
|
+
make_readable(path) do
|
28
|
+
command(path)
|
29
|
+
end
|
30
|
+
end
|
38
31
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
32
|
+
def version
|
33
|
+
out, err, status = Open3.capture3(SCANNER, "-V")
|
34
|
+
out.strip
|
35
|
+
end
|
44
36
|
|
45
|
-
|
46
|
-
raw =~ / FOUND$/
|
47
|
-
end
|
37
|
+
private
|
48
38
|
|
49
|
-
|
50
|
-
|
51
|
-
|
39
|
+
def command(path)
|
40
|
+
safe_path = Shellwords.shellescape(path)
|
41
|
+
Open3.capture2e(SCANNER, safe_path)
|
42
|
+
end
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
def make_readable(path)
|
45
|
+
changed = false
|
46
|
+
original = File.stat(path).mode # raises Errno::ENOENT
|
47
|
+
if !File.world_readable?(path)
|
48
|
+
changed = FileUtils.chmod("a+r", path)
|
49
|
+
logger.info "File #{path} made world-readable for virus scanning."
|
50
|
+
end
|
51
|
+
result = yield
|
52
|
+
if changed
|
53
|
+
FileUtils.chmod(original, path)
|
54
|
+
logger.info "Mode reset to original #{original} on file #{path}."
|
55
|
+
end
|
56
|
+
result
|
57
|
+
end
|
56
58
|
|
57
|
-
|
58
|
-
"#{raw} (#{version})"
|
59
|
-
end
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
# Result of a scan with the ClamdScannerAdapter
|
62
|
+
# @api private
|
63
|
+
class ClamdScanResult < ScanResult
|
64
64
|
|
65
|
+
def virus_found
|
66
|
+
if m = /: ([^\s]+) FOUND$/.match(output)
|
67
|
+
m[1]
|
65
68
|
end
|
69
|
+
end
|
66
70
|
|
71
|
+
def ok?
|
72
|
+
status.exitstatus == 0
|
67
73
|
end
|
74
|
+
|
75
|
+
def has_virus?
|
76
|
+
status.exitstatus == 1
|
77
|
+
end
|
78
|
+
|
79
|
+
def error?
|
80
|
+
status.exitstatus == 2
|
81
|
+
end
|
82
|
+
|
68
83
|
end
|
69
84
|
end
|
@@ -1,25 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
#
|
10
|
-
class NullScannerAdapter < ScannerAdapter
|
11
|
-
|
12
|
-
def scan(path)
|
13
|
-
NullScanResult.new("#{path}: NOT SCANNED - using :null scanner adapter.", path)
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
#
|
19
|
-
# The result of the scan with the NullScannerAdapter.
|
20
|
-
#
|
21
|
-
class NullScanResult < ScanResult; end
|
22
|
-
|
1
|
+
module Ddr::Antivirus
|
2
|
+
#
|
3
|
+
# A no-op adapter, primarily for testing and development.
|
4
|
+
#
|
5
|
+
class NullScannerAdapter < ScannerAdapter
|
6
|
+
|
7
|
+
def scan(path)
|
8
|
+
ScanResult.new(path, "#{path}: NOT SCANNED - using :null scanner adapter.")
|
23
9
|
end
|
10
|
+
|
24
11
|
end
|
12
|
+
|
25
13
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Ddr::Antivirus
|
2
|
+
#
|
3
|
+
# The result of a virus scan.
|
4
|
+
#
|
5
|
+
class ScanResult
|
6
|
+
|
7
|
+
attr_reader :file_path, :output, :scanned_at, :version
|
8
|
+
|
9
|
+
def initialize(file_path, output, scanned_at: nil, version: nil)
|
10
|
+
@file_path = file_path
|
11
|
+
@output = output
|
12
|
+
@scanned_at = scanned_at || default_time
|
13
|
+
@version = version || default_version
|
14
|
+
end
|
15
|
+
|
16
|
+
# Default time of virus scan - i.e., now.
|
17
|
+
# @return [Time] the time.
|
18
|
+
def default_time
|
19
|
+
Time.now.utc
|
20
|
+
end
|
21
|
+
|
22
|
+
# Default anti-virus software version information.
|
23
|
+
# @return [String] the version.
|
24
|
+
def default_version
|
25
|
+
"ddr-antivirus #{Ddr::Antivirus::VERSION}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# String representation of the result
|
29
|
+
# @return [String] the representation.
|
30
|
+
def to_s
|
31
|
+
"#{output}\n[#{version}]"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -1,36 +1,16 @@
|
|
1
|
-
require "
|
1
|
+
require "delegate"
|
2
2
|
|
3
|
-
module Ddr
|
4
|
-
|
5
|
-
class Scanner
|
3
|
+
module Ddr::Antivirus
|
4
|
+
class Scanner < SimpleDelegator
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def self.scan(path)
|
11
|
-
new { |scanner| return scanner.scan(path) }
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@adapter = Ddr::Antivirus::Adapters.get_adapter
|
16
|
-
yield self if block_given?
|
17
|
-
end
|
18
|
-
|
19
|
-
def scan(path)
|
20
|
-
result = adapter.scan(path)
|
21
|
-
raise Ddr::Antivirus::VirusFoundError, result if result.has_virus?
|
22
|
-
logger.error("Antivirus scanner error (#{result.version})") if result.error?
|
23
|
-
logger.info(result.to_s)
|
24
|
-
result
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def logger
|
30
|
-
Ddr::Antivirus.logger
|
31
|
-
end
|
6
|
+
def self.scan(path)
|
7
|
+
new.scan(path)
|
8
|
+
end
|
32
9
|
|
10
|
+
def initialize
|
11
|
+
super Ddr::Antivirus.get_adapter.new
|
33
12
|
end
|
13
|
+
|
34
14
|
end
|
35
15
|
end
|
36
16
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "scan_result"
|
2
|
+
|
3
|
+
module Ddr::Antivirus
|
4
|
+
#
|
5
|
+
# @abstract Subclass and override {#scan} to implement a scanner adapter.
|
6
|
+
#
|
7
|
+
class ScannerAdapter
|
8
|
+
|
9
|
+
# Scan a file path for viruses.
|
10
|
+
#
|
11
|
+
# @param path [String] file path to scan.
|
12
|
+
# @return [Ddr::Antivirus::Adapters::ScanResult] the result of the scan.
|
13
|
+
def scan(path)
|
14
|
+
raise NotImplementedError, "Adapters must implement the `scan' method."
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return the adapter configuration options
|
18
|
+
def config
|
19
|
+
Ddr::Antivirus.adapter_config
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def logger
|
25
|
+
Ddr::Antivirus.logger
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,25 +1,7 @@
|
|
1
|
-
require "coveralls"
|
2
|
-
Coveralls.wear!
|
3
|
-
|
4
|
-
# This file was generated by the `rspec --init` command. Conventionally, all
|
5
|
-
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
6
|
-
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
7
|
-
# file to always be loaded, without a need to explicitly require it in any files.
|
8
|
-
#
|
9
|
-
# Given that it is always loaded, you are encouraged to keep this file as
|
10
|
-
# light-weight as possible. Requiring heavyweight dependencies from this file
|
11
|
-
# will add to the boot time of your test suite on EVERY test run, even for an
|
12
|
-
# individual file that may not need all of that loaded. Instead, make a
|
13
|
-
# separate helper file that requires this one and then use it only in the specs
|
14
|
-
# that actually need it.
|
15
|
-
#
|
16
|
-
# The `.rspec` file also contains a few flags that are not defaults but that
|
17
|
-
# users commonly want.
|
18
|
-
#
|
19
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
20
|
-
|
21
1
|
require 'ddr/antivirus'
|
22
2
|
|
3
|
+
Ddr::Antivirus.test_mode!
|
4
|
+
|
23
5
|
RSpec.configure do |config|
|
24
6
|
# The settings below are suggested to provide a good initial experience
|
25
7
|
# with RSpec, but feel free to customize to your heart's content.
|
@@ -1,66 +1,72 @@
|
|
1
|
-
require "
|
1
|
+
require "tempfile"
|
2
2
|
require "ddr/antivirus/adapters/clamd_scanner_adapter"
|
3
3
|
|
4
|
-
module Ddr
|
5
|
-
|
6
|
-
module Adapters
|
7
|
-
RSpec.describe ClamdScannerAdapter do
|
4
|
+
module Ddr::Antivirus
|
5
|
+
RSpec.describe ClamdScannerAdapter do
|
8
6
|
|
9
|
-
|
10
|
-
let(:adapter) { described_class.new }
|
7
|
+
let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@file.write("Scan me!")
|
16
|
-
@file.close
|
17
|
-
allow(adapter).to receive(:command).with(@file.path) { "#{@file.path}: OK" }
|
18
|
-
end
|
19
|
-
after { @file.unlink }
|
20
|
-
describe "when the file is not world readable" do
|
21
|
-
it "should temporarily change the permissions" do
|
22
|
-
original_mode = File.stat(@file.path).mode
|
23
|
-
expect(FileUtils).to receive(:chmod).with("a+r", @file.path)
|
24
|
-
adapter.scan(@file.path)
|
25
|
-
expect(File.stat(@file.path).mode).to eq(original_mode)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
describe "when the file is world readable" do
|
29
|
-
before { FileUtils.chmod("a+r", @file.path) }
|
30
|
-
it "should not change the permissions" do
|
31
|
-
original_mode = File.stat(@file.path).mode
|
32
|
-
expect(FileUtils).not_to receive(:chmod)
|
33
|
-
adapter.scan(@file.path)
|
34
|
-
expect(File.stat(@file.path).mode).to eq(original_mode)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
9
|
+
before do
|
10
|
+
allow(subject).to receive(:version) { "version" }
|
11
|
+
end
|
38
12
|
|
39
|
-
|
40
|
-
|
13
|
+
describe "permissions" do
|
14
|
+
before do
|
15
|
+
@file = Tempfile.new("test")
|
16
|
+
@file.write("Scan me!")
|
17
|
+
@file.close
|
18
|
+
allow(subject).to receive(:command).with(@file.path) { ["#{@file.path}: OK", double(exitstatus: 0)] }
|
19
|
+
end
|
20
|
+
after { @file.unlink }
|
21
|
+
describe "when the file is not world readable" do
|
22
|
+
it "should temporarily change the permissions" do
|
23
|
+
FileUtils.chmod("a-r", @file.path)
|
24
|
+
original_mode = File.stat(@file.path).mode
|
25
|
+
expect(FileUtils).to receive(:chmod).with("a+r", @file.path)
|
26
|
+
subject.scan(@file.path)
|
27
|
+
expect(File.stat(@file.path).mode).to eq(original_mode)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
describe "when the file is world readable" do
|
31
|
+
before { FileUtils.chmod("a+r", @file.path) }
|
32
|
+
it "should not change the permissions" do
|
33
|
+
original_mode = File.stat(@file.path).mode
|
34
|
+
expect(FileUtils).not_to receive(:chmod)
|
35
|
+
subject.scan(@file.path)
|
36
|
+
expect(File.stat(@file.path).mode).to eq(original_mode)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
41
|
+
describe "result" do
|
42
|
+
before do
|
43
|
+
allow(subject).to receive(:command).with(path) { ["output", status] }
|
44
|
+
end
|
45
|
+
describe "when a virus is found" do
|
46
|
+
let(:status) { double(exitstatus: 1) }
|
47
|
+
it "should raise a VirusFoundError" do
|
48
|
+
expect { subject.scan(path) }.to raise_error(VirusFoundError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
describe "when there is an error" do
|
52
|
+
let(:status) { double(exitstatus: 2) }
|
53
|
+
it "should raise a ScannerError" do
|
54
|
+
expect { subject.scan(path) }.to raise_error(ScannerError)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
describe "success" do
|
58
|
+
let(:status) { double(exitstatus: 0) }
|
59
|
+
it "should have output" do
|
60
|
+
expect(subject.scan(path).output).to eq("output")
|
61
|
+
end
|
62
|
+
it "should have a scanned_at time" do
|
63
|
+
expect(subject.scan(path).scanned_at).to be_a(Time)
|
64
|
+
end
|
65
|
+
it "should have a version" do
|
66
|
+
expect(subject.scan(path).version).to eq("version")
|
67
|
+
end
|
68
|
+
it "should have the file_path" do
|
69
|
+
expect(subject.scan(path).file_path).to eq(path)
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddr-antivirus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Chandek-Stark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '4.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '4.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,20 +38,6 @@ dependencies:
|
|
52
38
|
- - ">="
|
53
39
|
- !ruby/object:Gem::Version
|
54
40
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: clamav
|
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'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
42
|
name: rspec
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,22 +69,15 @@ files:
|
|
97
69
|
- ddr-antivirus.gemspec
|
98
70
|
- lib/ddr-antivirus.rb
|
99
71
|
- lib/ddr/antivirus.rb
|
100
|
-
- lib/ddr/antivirus/adapters.rb
|
101
|
-
- lib/ddr/antivirus/adapters/clamav_scanner_adapter.rb
|
102
72
|
- lib/ddr/antivirus/adapters/clamd_scanner_adapter.rb
|
103
73
|
- lib/ddr/antivirus/adapters/null_scanner_adapter.rb
|
104
|
-
- lib/ddr/antivirus/
|
105
|
-
- lib/ddr/antivirus/adapters/scanner_adapter.rb
|
74
|
+
- lib/ddr/antivirus/scan_result.rb
|
106
75
|
- lib/ddr/antivirus/scanner.rb
|
76
|
+
- lib/ddr/antivirus/scanner_adapter.rb
|
107
77
|
- lib/ddr/antivirus/version.rb
|
108
78
|
- spec/fixtures/blue-devil.png
|
109
|
-
- spec/shared_examples_for_scan_results.rb
|
110
79
|
- spec/spec_helper.rb
|
111
|
-
- spec/unit/clamav_scanner_adapter_spec.rb
|
112
80
|
- spec/unit/clamd_scanner_adapter_spec.rb
|
113
|
-
- spec/unit/null_scanner_adapter_spec.rb
|
114
|
-
- spec/unit/scan_result_spec.rb
|
115
|
-
- spec/unit/scanner_spec.rb
|
116
81
|
homepage: https://github.com/duke-libraries/ddr-antivirus
|
117
82
|
licenses:
|
118
83
|
- BSD-3-Clause
|
@@ -128,9 +93,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
93
|
version: '0'
|
129
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
95
|
requirements:
|
131
|
-
- - "
|
96
|
+
- - ">"
|
132
97
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
98
|
+
version: 1.3.1
|
134
99
|
requirements: []
|
135
100
|
rubyforge_project:
|
136
101
|
rubygems_version: 2.4.6
|
@@ -139,10 +104,5 @@ specification_version: 4
|
|
139
104
|
summary: Pluggable antivirus scanning service.
|
140
105
|
test_files:
|
141
106
|
- spec/fixtures/blue-devil.png
|
142
|
-
- spec/shared_examples_for_scan_results.rb
|
143
107
|
- spec/spec_helper.rb
|
144
|
-
- spec/unit/clamav_scanner_adapter_spec.rb
|
145
108
|
- spec/unit/clamd_scanner_adapter_spec.rb
|
146
|
-
- spec/unit/null_scanner_adapter_spec.rb
|
147
|
-
- spec/unit/scan_result_spec.rb
|
148
|
-
- spec/unit/scanner_spec.rb
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Ddr
|
2
|
-
module Antivirus
|
3
|
-
module Adapters
|
4
|
-
|
5
|
-
def self.get_adapter
|
6
|
-
require_relative "adapters/#{Ddr::Antivirus.scanner_adapter}_scanner_adapter"
|
7
|
-
adapter_name = "#{Ddr::Antivirus.scanner_adapter.to_s.capitalize}ScannerAdapter"
|
8
|
-
klass = self.const_get(adapter_name.to_sym, false)
|
9
|
-
klass.new
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require "clamav"
|
2
|
-
|
3
|
-
require_relative "scanner_adapter"
|
4
|
-
require_relative "scan_result"
|
5
|
-
|
6
|
-
module Ddr
|
7
|
-
module Antivirus
|
8
|
-
module Adapters
|
9
|
-
#
|
10
|
-
# Scanner adapter for the 'clamav' gem (Ruby libclamav bindings).
|
11
|
-
#
|
12
|
-
class ClamavScannerAdapter < ScannerAdapter
|
13
|
-
|
14
|
-
def scan(path)
|
15
|
-
reload!
|
16
|
-
raw = engine.scanfile(path)
|
17
|
-
ClamavScanResult.new(raw, path)
|
18
|
-
end
|
19
|
-
|
20
|
-
# Load or reload the database of virus signatures.
|
21
|
-
def reload!
|
22
|
-
#
|
23
|
-
# ClamAV.instance.reload is supposed to reload the database if changed and return:
|
24
|
-
#
|
25
|
-
# 0 => unnecessary
|
26
|
-
# 1 => successful
|
27
|
-
# 2 => error (undocumented)
|
28
|
-
#
|
29
|
-
# However, reload raises a RuntimeError when the db needs to be reloaded,
|
30
|
-
# in which case, loaddb must be called.
|
31
|
-
#
|
32
|
-
engine.loaddb unless [0, 1].include?(engine.reload)
|
33
|
-
rescue RuntimeError
|
34
|
-
engine.loaddb
|
35
|
-
end
|
36
|
-
|
37
|
-
def engine
|
38
|
-
ClamAV.instance
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# Result of a scan with the ClamavScannerAdapter.
|
45
|
-
#
|
46
|
-
class ClamavScanResult < ScanResult
|
47
|
-
|
48
|
-
def virus_found
|
49
|
-
raw if has_virus?
|
50
|
-
end
|
51
|
-
|
52
|
-
def has_virus?
|
53
|
-
![0, 1].include?(raw)
|
54
|
-
end
|
55
|
-
|
56
|
-
def error?
|
57
|
-
raw == 1
|
58
|
-
end
|
59
|
-
|
60
|
-
# A formatted status message (for consistency with clamdscan output).
|
61
|
-
# @return [String] the result status.
|
62
|
-
def status
|
63
|
-
return "FOUND #{virus_found}" if has_virus?
|
64
|
-
return "ERROR" if error?
|
65
|
-
"OK"
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_s
|
69
|
-
"#{file_path}: #{status} (#{version})"
|
70
|
-
end
|
71
|
-
|
72
|
-
def default_version
|
73
|
-
# Engine and database versions
|
74
|
-
# E.g., ClamAV 0.98.3/19010/Tue May 20 21:46:01 2014
|
75
|
-
`sigtool --version`.strip
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module Ddr
|
2
|
-
module Antivirus
|
3
|
-
module Adapters
|
4
|
-
#
|
5
|
-
# The result of a virus scan.
|
6
|
-
#
|
7
|
-
class ScanResult
|
8
|
-
|
9
|
-
attr_reader :raw, :file_path, :scanned_at, :version
|
10
|
-
|
11
|
-
def initialize(raw, file_path, opts={})
|
12
|
-
@raw = raw
|
13
|
-
@file_path = file_path
|
14
|
-
@scanned_at = opts.fetch(:scanned_at, default_time)
|
15
|
-
@version = opts.fetch(:version, default_version)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Default time of virus scan - i.e., now.
|
19
|
-
# @return [Time] the time.
|
20
|
-
def default_time
|
21
|
-
Time.now.utc
|
22
|
-
end
|
23
|
-
|
24
|
-
# Default anti-virus software version information.
|
25
|
-
# @return [String] the version.
|
26
|
-
def default_version
|
27
|
-
"ddr-antivirus #{Ddr::Antivirus::VERSION}"
|
28
|
-
end
|
29
|
-
|
30
|
-
# the name of virus found.
|
31
|
-
# @return [String] the virus name.
|
32
|
-
def virus_found; end
|
33
|
-
|
34
|
-
# Was a virus found?
|
35
|
-
# @return [true, false] whether a virus was found.
|
36
|
-
def has_virus?
|
37
|
-
!virus_found.nil?
|
38
|
-
end
|
39
|
-
|
40
|
-
# Was there an error (reported by the scanner, not necessarily an exception)?
|
41
|
-
# @return [true, false] whether there was an error.
|
42
|
-
def error?
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
# Was the result OK - i.e., not an error and virus not found.
|
47
|
-
# @return [true, false] whether the result was OK.
|
48
|
-
def ok?
|
49
|
-
!(has_virus? || error?)
|
50
|
-
end
|
51
|
-
|
52
|
-
# String representation of the result
|
53
|
-
# @return [String] the representation.
|
54
|
-
def to_s
|
55
|
-
"#{raw} (#{version})"
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Ddr
|
2
|
-
module Antivirus
|
3
|
-
module Adapters
|
4
|
-
#
|
5
|
-
# @abstract Subclass and override {#scan} to implement a scanner adapter.
|
6
|
-
#
|
7
|
-
class ScannerAdapter
|
8
|
-
|
9
|
-
# Scan a file path for viruses.
|
10
|
-
#
|
11
|
-
# @param path [String] file path to scan.
|
12
|
-
# @return [Ddr::Antivirus::Adapters::ScanResult] the result of the scan.
|
13
|
-
def scan(path)
|
14
|
-
raise NotImplementedError, "Adapters must implement the `scan' method."
|
15
|
-
end
|
16
|
-
|
17
|
-
# Return the adapter configuration options
|
18
|
-
def config
|
19
|
-
Ddr::Antivirus.adapter_config
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
shared_examples "a scan result" do
|
2
|
-
it "should have a raw result" do
|
3
|
-
expect(subject.raw).not_to be_nil
|
4
|
-
end
|
5
|
-
it "should have a version" do
|
6
|
-
expect(subject.version).not_to be_nil
|
7
|
-
end
|
8
|
-
it "should have a scanned_at time" do
|
9
|
-
expect(subject.scanned_at).to be_a(Time)
|
10
|
-
end
|
11
|
-
it "should have a string representation" do
|
12
|
-
expect(subject.to_s).not_to be_nil
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
shared_examples "a successful scan result" do
|
17
|
-
it "should not have a virus" do
|
18
|
-
expect(subject.virus_found).to be_nil
|
19
|
-
expect(subject).not_to have_virus
|
20
|
-
end
|
21
|
-
it "should not have an error" do
|
22
|
-
expect(subject).not_to be_error
|
23
|
-
end
|
24
|
-
it "should be ok" do
|
25
|
-
expect(subject).to be_ok
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
shared_examples "an error scan result" do
|
30
|
-
it "should have an error" do
|
31
|
-
expect(subject).to be_error
|
32
|
-
end
|
33
|
-
it "shoud not have a virus" do
|
34
|
-
expect(subject.virus_found).to be_nil
|
35
|
-
expect(subject).not_to have_virus
|
36
|
-
end
|
37
|
-
it "should not be ok" do
|
38
|
-
expect(subject).not_to be_ok
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
shared_examples "a virus scan result" do
|
43
|
-
it "shoud have a virus" do
|
44
|
-
expect(subject.virus_found).not_to be_nil
|
45
|
-
expect(subject).to have_virus
|
46
|
-
end
|
47
|
-
it "should not have an error" do
|
48
|
-
expect(subject).not_to be_error
|
49
|
-
end
|
50
|
-
it "should not be ok" do
|
51
|
-
expect(subject).not_to be_ok
|
52
|
-
end
|
53
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require "shared_examples_for_scan_results"
|
2
|
-
require "ddr/antivirus/adapters/clamav_scanner_adapter"
|
3
|
-
|
4
|
-
module Ddr
|
5
|
-
module Antivirus
|
6
|
-
module Adapters
|
7
|
-
RSpec.describe ClamavScannerAdapter do
|
8
|
-
|
9
|
-
let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
|
10
|
-
|
11
|
-
describe "#scan" do
|
12
|
-
context "when the db is already loaded" do
|
13
|
-
before { subject.engine.loaddb }
|
14
|
-
it "should reload the db" do
|
15
|
-
expect(subject.engine).to receive(:reload).and_call_original
|
16
|
-
expect(subject.engine).not_to receive(:loaddb)
|
17
|
-
subject.scan(path)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
context "when the db is not already loaded" do
|
21
|
-
before { allow(subject.engine).to receive(:reload).and_raise(RuntimeError) }
|
22
|
-
it "should load the db" do
|
23
|
-
expect(subject.engine).to receive(:loaddb).and_call_original
|
24
|
-
subject.scan(path)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
context "when the db is not reloaded successfully" do
|
28
|
-
before { allow(subject.engine).to receive(:reload) { 2 } }
|
29
|
-
it "should load the db" do
|
30
|
-
expect(subject.engine).to receive(:loaddb).and_call_original
|
31
|
-
subject.scan(path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "result" do
|
36
|
-
subject { adapter.scan(path) }
|
37
|
-
let(:adapter) { described_class.new }
|
38
|
-
it "should be a ClamavScanResult" do
|
39
|
-
expect(subject).to be_a(ClamavScanResult)
|
40
|
-
end
|
41
|
-
it_should_behave_like "a scan result"
|
42
|
-
context "when a virus is found" do
|
43
|
-
before { allow(adapter.engine).to receive(:scanfile).with(path) { "Bad boy 35" } }
|
44
|
-
it "the raw result should be the virus description" do
|
45
|
-
expect(subject.raw).to eq "Bad boy 35"
|
46
|
-
expect(subject.virus_found).to eq "Bad boy 35"
|
47
|
-
end
|
48
|
-
it_should_behave_like "a virus scan result"
|
49
|
-
end
|
50
|
-
context "when there is an error" do
|
51
|
-
before { allow(adapter.engine).to receive(:scanfile).with(path) { 1 } }
|
52
|
-
it "should not have a virus" do
|
53
|
-
expect(subject).not_to have_virus
|
54
|
-
end
|
55
|
-
it_should_behave_like "an error scan result"
|
56
|
-
end
|
57
|
-
context "success" do
|
58
|
-
before { allow(adapter.engine).to receive(:scanfile).with(path) { 0 } }
|
59
|
-
it_should_behave_like "a successful scan result"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require "shared_examples_for_scan_results"
|
2
|
-
require "ddr/antivirus/adapters/null_scanner_adapter"
|
3
|
-
|
4
|
-
module Ddr
|
5
|
-
module Antivirus
|
6
|
-
module Adapters
|
7
|
-
RSpec.describe NullScannerAdapter do
|
8
|
-
|
9
|
-
let(:path) { File.expand_path(File.join("..", "..", "fixtures", "blue-devil.png"), __FILE__) }
|
10
|
-
|
11
|
-
describe "result" do
|
12
|
-
subject { adapter.scan(path) }
|
13
|
-
let(:adapter) { described_class.new }
|
14
|
-
it "should be a NullScanResult" do
|
15
|
-
expect(subject).to be_a(NullScanResult)
|
16
|
-
end
|
17
|
-
it_should_behave_like "a scan result"
|
18
|
-
it_should_behave_like "a successful scan result"
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'shared_examples_for_scan_results'
|
2
|
-
|
3
|
-
module Ddr
|
4
|
-
module Antivirus
|
5
|
-
module Adapters
|
6
|
-
RSpec.describe ScanResult do
|
7
|
-
subject { described_class.new("Raw result", "/tmp/foo") }
|
8
|
-
|
9
|
-
it_should_behave_like "a scan result"
|
10
|
-
|
11
|
-
describe "success" do
|
12
|
-
it_should_behave_like "a successful scan result"
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "error" do
|
16
|
-
before { allow(subject).to receive(:error?) { true } }
|
17
|
-
it_should_behave_like "an error scan result"
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "virus found" do
|
21
|
-
before { allow(subject).to receive(:virus_found) { "Bad boy 35" } }
|
22
|
-
it_should_behave_like "a virus scan result"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/spec/unit/scanner_spec.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require "ddr/antivirus/adapters/scan_result"
|
2
|
-
|
3
|
-
module Ddr
|
4
|
-
module Antivirus
|
5
|
-
RSpec.describe Scanner do
|
6
|
-
|
7
|
-
shared_examples "a scanner" do
|
8
|
-
let(:path) { "/tmp/foo" }
|
9
|
-
describe "logging" do
|
10
|
-
it "should log the result" do
|
11
|
-
expect(Ddr::Antivirus.logger).to receive(:info)
|
12
|
-
subject.scan(path)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
describe "when a virus is found" do
|
16
|
-
before { allow_any_instance_of(Ddr::Antivirus::Adapters::ScanResult).to receive(:has_virus?) { true } }
|
17
|
-
it "should raise an execption" do
|
18
|
-
expect { subject.scan(path) }.to raise_error
|
19
|
-
end
|
20
|
-
end
|
21
|
-
describe "when a virus is not found" do
|
22
|
-
before { allow_any_instance_of(Ddr::Antivirus::Adapters::ScanResult).to receive(:has_virus?) { false } }
|
23
|
-
it "should return the scan result" do
|
24
|
-
expect(subject.scan(path)).to be_a(Ddr::Antivirus::Adapters::ScanResult)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
describe "when an error occurs in the scanner" do
|
28
|
-
before { allow_any_instance_of(Ddr::Antivirus::Adapters::ScanResult).to receive(:error?) { true } }
|
29
|
-
it "should log an error" do
|
30
|
-
expect(Ddr::Antivirus.logger).to receive(:error)
|
31
|
-
subject.scan(path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
before do
|
37
|
-
@original_adapter = Ddr::Antivirus.scanner_adapter
|
38
|
-
Ddr::Antivirus.scanner_adapter = :null
|
39
|
-
end
|
40
|
-
|
41
|
-
after do
|
42
|
-
Ddr::Antivirus.scanner_adapter = @original_adapter
|
43
|
-
end
|
44
|
-
|
45
|
-
describe ".scan" do
|
46
|
-
subject { described_class }
|
47
|
-
it_behaves_like "a scanner"
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "#scan" do
|
51
|
-
subject { described_class.new }
|
52
|
-
it_behaves_like "a scanner"
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|