clambytoo 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 522d95e9b100b7fa407904af1d747054b3977f8eab68193a207fc3f0196fa663
4
+ data.tar.gz: b5b98d1e4342a98632afeae44beb5f0499a999e8b1ac430ec621ad43034b96a1
5
+ SHA512:
6
+ metadata.gz: 304daa2134c849ec2ee89aa4b0e0d9905d43d0ec877577d9e42f358c7c5690fef482dd66b1a5cdaf68d4a5d915bd656b3e10bdc60b74fc47c7d0ebb762cb6fb0
7
+ data.tar.gz: ebe2655c8dbd1e96d3d7d8374dfdf298bfdd43aae81e89ebffb6e63ffccf10adffd37c2b08764d0f83c6ae487e1a63068297669c3115cd5e9818f1d9457dde9d
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in clamby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 kobaltz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
data/clambytoo.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'clambytoo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "clambytoo"
8
+ spec.version = Clambytoo::VERSION
9
+ spec.authors = ["kobaltz"]
10
+ spec.email = ["dave@k-innovations.net"]
11
+ spec.summary = "Scan file uploads with ClamAV"
12
+ spec.description = "This is a temp fork for testing purposes only. Clamby allows users to scan files uploaded with Paperclip or Carrierwave. If a file has a virus, then you can delete this file and discard it without causing harm to other users."
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,121 @@
1
+ module Clambytoo
2
+ # Interface with the system. Builds and runs the command.
3
+ class Command
4
+ EXECUTABLES = %w(clamscan clamdscan freshclam)
5
+
6
+ # Array containing the complete command line.
7
+ attr_accessor :command
8
+
9
+ # Returns the appropriate scan executable, based on clamd being used.
10
+ def self.scan_executable
11
+ return 'clamdscan' if Clambytoo.config[:daemonize]
12
+ return 'clamscan'
13
+ end
14
+
15
+ # Perform a ClamAV scan on the given path.
16
+ def self.scan(path)
17
+ return nil unless file_exists?(path)
18
+
19
+ args = [Shellwords.escape(path), '--no-summary']
20
+
21
+ if Clambytoo.config[:daemonize]
22
+ args << '--fdpass' if Clambytoo.config[:fdpass]
23
+ args << '--stream' if Clambytoo.config[:stream]
24
+ end
25
+
26
+ args << "-d #{Clambytoo.config[:datadir]}" if Clambytoo.config[:datadir]
27
+
28
+ new.run scan_executable, *args
29
+
30
+
31
+ # $CHILD_STATUS maybe nil if the execution itself (not the client process)
32
+ # fails
33
+ case $CHILD_STATUS && $CHILD_STATUS.exitstatus
34
+ when 0
35
+ return false
36
+ when nil, 2
37
+ # clamdscan returns 2 whenever error other than a detection happens
38
+ if Clambytoo.config[:error_clamscan_client_error] && Clambytoo.config[:daemonize]
39
+ raise Clambytoo::ClamscanClientError.new("Clamscan client error")
40
+ end
41
+
42
+ # returns true to maintain legacy behavior
43
+ return true
44
+ else
45
+ return true unless Clambytoo.config[:error_file_virus]
46
+
47
+ raise Clambytoo::VirusDetected.new("VIRUS DETECTED on #{Time.now}: #{path}")
48
+ end
49
+ end
50
+
51
+ # Update the virus definitions.
52
+ def self.freshclam
53
+ args = []
54
+ args << "--datadir=#{Clambytoo.config[:datadir]}" if Clambytoo.config[:datadir]
55
+ new.run 'freshclam', *args
56
+ end
57
+
58
+ # Show the ClamAV version. Also acts as a quick check if ClamAV functions.
59
+ def self.clamscan_version
60
+ new.run scan_executable, '--version'
61
+ end
62
+
63
+ # Run the given commands via a system call.
64
+ # The executable must be one of the permitted ClamAV executables.
65
+ # The arguments will be combined with default arguments if needed.
66
+ # The arguments are sorted alphabetically before being passed to the system.
67
+ #
68
+ # Examples:
69
+ # run('clamscan', file, '--verbose')
70
+ # run('clamscan', '-V')
71
+ def run(executable, *args)
72
+ executable_full = executable_path(executable)
73
+ self.command = args | default_args
74
+ self.command = command.sort.unshift(executable_full)
75
+ if caller_locations(1,1)[0].label == "clamscan_version"
76
+ Open3.popen3(self.command.join(' ')) do |stdin, stdout, stderr, wait_thr|
77
+ exit_status = wait_thr.value
78
+ return true if exit_status.success? && stderr.gets.nil?
79
+ return nil unless stderr.gets.nil? #if we have any kind of error executing a command we should return nil
80
+ end
81
+ else
82
+ system(self.command.join(' '), system_options)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def default_args
89
+ args = []
90
+ args << "--config-file=#{Clambytoo.config[:config_file]}" if Clambytoo.config[:daemonize] && Clambytoo.config[:config_file]
91
+ args << '--quiet' if Clambytoo.config[:output_level] == 'low'
92
+ args << '--verbose' if Clambytoo.config[:output_level] == 'high'
93
+ args
94
+ end
95
+
96
+ # This applies to the `system` call itself; does not end up in the command.
97
+ def system_options
98
+ if Clambytoo.config[:output_level] == 'off'
99
+ { out: File::NULL }
100
+ else
101
+ {}
102
+ end
103
+ end
104
+
105
+ def executable_path(executable)
106
+ raise "`#{executable}` is not permitted" unless EXECUTABLES.include?(executable)
107
+ Clambytoo.config[:"executable_path_#{executable}"]
108
+ end
109
+
110
+ def self.file_exists?(path)
111
+ return true if File.file?(path)
112
+
113
+ if Clambytoo.config[:error_file_missing]
114
+ raise Clambytoo::FileNotFound.new("File not found: #{path}")
115
+ else
116
+ puts "FILE NOT FOUND on #{Time.now}: #{path}"
117
+ return false
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,8 @@
1
+ module Clambytoo
2
+ class Error < StandardError; end
3
+
4
+ class VirusDetected < Error; end
5
+ class ClamscanMissing < Error; end
6
+ class ClamscanClientError < Error; end
7
+ class FileNotFound < Error; end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Clambytoo
2
+ VERSION = "1.0.0"
3
+ end
data/lib/clambytoo.rb ADDED
@@ -0,0 +1,67 @@
1
+ require "English"
2
+ require 'open3'
3
+ require "clambytoo/command"
4
+ require "clambytoo/error"
5
+ require "clambytoo/version"
6
+
7
+ module Clambytoo
8
+ DEFAULT_CONFIG = {
9
+ :check => true,
10
+ :daemonize => false,
11
+ :config_file => nil,
12
+ :error_clamscan_client_error => false,
13
+ :error_file_missing => true,
14
+ :error_file_virus => false,
15
+ :fdpass => false,
16
+ :stream => false,
17
+ :output_level => 'medium',
18
+ :datadir => nil,
19
+ :executable_path_clamscan => 'clamscan',
20
+ :executable_path_clamdscan => 'clamdscan',
21
+ :executable_path_freshclam => 'freshclam',
22
+ }.freeze
23
+
24
+ @config = DEFAULT_CONFIG.dup
25
+
26
+ @valid_config_keys = @config.keys
27
+
28
+ class << self
29
+ attr_reader :config
30
+ attr_reader :valid_config_keys
31
+ end
32
+
33
+ def self.configure(opts = {})
34
+ if opts.delete(:silence_output)
35
+ warn ':silence_output config is deprecated. Use :output_level => "off" instead.'
36
+ opts[:output_level] = 'off'
37
+ end
38
+
39
+ opts.each {|k,v| config[k.to_sym] = v if valid_config_keys.include? k.to_sym}
40
+ end
41
+
42
+ def self.safe?(path)
43
+ value = virus?(path)
44
+ return nil if value.nil?
45
+ ! value
46
+ end
47
+
48
+ def self.virus?(path)
49
+ return nil unless scanner_exists?
50
+ Command.scan path
51
+ end
52
+
53
+ def self.scanner_exists?
54
+ return true unless config[:check]
55
+ scanner = Command.clamscan_version
56
+
57
+ return scanner ? true : false
58
+ end
59
+
60
+ def self.update
61
+ Command.freshclam
62
+ end
63
+
64
+ def self.daemonize?
65
+ !! config[:daemonize]
66
+ end
67
+ end
data/spec/.DS_Store ADDED
Binary file
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+ require 'support/shared_context'
3
+
4
+ describe Clambytoo::Command do
5
+ before { Clambytoo.configure(Clambytoo::DEFAULT_CONFIG.dup) }
6
+
7
+ describe 'ClamAV version' do
8
+ it 'returns true' do
9
+ command = described_class.clamscan_version
10
+ expect(command).to be true
11
+ end
12
+ end
13
+
14
+ describe 'scan' do
15
+ include_context 'paths'
16
+
17
+ let(:runner){ instance_double(described_class) }
18
+
19
+ describe 'exceptions' do
20
+ it "can be configured to raise exception when file is missing" do
21
+ Clambytoo.configure({:error_file_missing => true})
22
+
23
+ expect do
24
+ described_class.scan(bad_path)
25
+ end.to raise_exception(Clambytoo::FileNotFound)
26
+ end
27
+ it 'can be configured to return nil when file is missing' do
28
+ Clambytoo.configure({:error_file_missing => false})
29
+ command = described_class.scan(bad_path)
30
+
31
+ expect(command).to be(nil)
32
+ end
33
+ end
34
+
35
+ describe 'passing file descriptor' do
36
+ it 'does not include fdpass in the command by default' do
37
+ Clambytoo.configure
38
+ expect(runner).to receive(:run).with('clamscan', good_path, '--no-summary')
39
+ allow(described_class).to receive(:new).and_return(runner)
40
+
41
+ described_class.scan(good_path)
42
+ end
43
+
44
+ it 'omits the fdpass option when invoking clamscan if it is set, but daemonize isn\'t' do
45
+ Clambytoo.configure(fdpass: true)
46
+ expect(runner).to receive(:run).with('clamscan', good_path, '--no-summary')
47
+ allow(described_class).to receive(:new).and_return(runner)
48
+
49
+ described_class.scan(good_path)
50
+ end
51
+
52
+ it 'passes the fdpass option when invoking clamscan if it is set with daemonize' do
53
+ Clambytoo.configure(fdpass: true, daemonize: true)
54
+ expect(runner).to receive(:run).with('clamdscan', good_path, '--no-summary', '--fdpass')
55
+ allow(described_class).to receive(:new).and_return(runner)
56
+
57
+ described_class.scan(good_path)
58
+ end
59
+ end
60
+
61
+ describe 'streaming files to clamd' do
62
+ it 'does not include stream in the command by default' do
63
+ Clambytoo.configure
64
+ expect(runner).to receive(:run).with('clamscan', good_path, '--no-summary')
65
+ allow(described_class).to receive(:new).and_return(runner)
66
+
67
+ described_class.scan(good_path)
68
+ end
69
+
70
+ it 'omits the stream option when invoking clamscan if it is set, but daemonize isn\'t' do
71
+ Clambytoo.configure(stream: true)
72
+ expect(runner).to receive(:run).with('clamscan', good_path, '--no-summary')
73
+ allow(described_class).to receive(:new).and_return(runner)
74
+
75
+ described_class.scan(good_path)
76
+ end
77
+
78
+ it 'passes the stream option when invoking clamscan if it is set with daemonize' do
79
+ Clambytoo.configure(stream: true, daemonize: true)
80
+ expect(runner).to receive(:run).with('clamdscan', good_path, '--no-summary', '--stream')
81
+ allow(described_class).to receive(:new).and_return(runner)
82
+
83
+ described_class.scan(good_path)
84
+ end
85
+ end
86
+
87
+ describe 'specifying config-file' do
88
+ it 'does not include the parameter in the clamscan command by default' do
89
+ Clambytoo.configure
90
+
91
+ expect(described_class.new.send(:default_args)).not_to include(a_string_matching(/--config-file/))
92
+ end
93
+ it 'does not include the parameter in the clamdscan command by default' do
94
+ Clambytoo.configure(daemonize: true)
95
+
96
+ expect(described_class.new.send(:default_args)).not_to include(a_string_matching(/--config-file/))
97
+ end
98
+ it 'omits the parameter when invoking clamscan if it is set' do
99
+ Clambytoo.configure(daemonize: false, config_file: 'clamd.conf')
100
+
101
+ expect(described_class.new.send(:default_args)).not_to include('--config-file=clamd.conf')
102
+ end
103
+ it 'passes the parameter when invoking clamdscan if it is set' do
104
+ Clambytoo.configure(daemonize: true, config_file: 'clamd.conf')
105
+
106
+ expect(described_class.new.send(:default_args)).to include('--config-file=clamd.conf')
107
+ end
108
+ end
109
+
110
+ describe 'specifying custom executable paths' do
111
+ let(:runner) { described_class.new }
112
+ let(:custom_path) { '/custom/path' }
113
+
114
+ before do
115
+ Clambytoo.configure(
116
+ executable_path_clamscan: "#{custom_path}/clamscan",
117
+ executable_path_clamdscan: "#{custom_path}/clamdscan",
118
+ executable_path_freshclam: "#{custom_path}/freshclam",
119
+ )
120
+ allow(described_class).to receive(:new).and_return(runner)
121
+ end
122
+
123
+ it 'executes the freshclam executable from the custom path' do
124
+ expect(runner).to receive(:system).with(
125
+ "#{custom_path}/freshclam",
126
+ {}
127
+ ) { system("exit 0", out: File::NULL) }
128
+
129
+ described_class.freshclam
130
+ end
131
+
132
+ context 'when not set with daemonize' do
133
+ before { Clambytoo.configure(daemonize: false) }
134
+
135
+ it 'executes the clamscan executable from the custom path' do
136
+ expect(runner).to receive(:system).with(
137
+ "#{custom_path}/clamscan --no-summary #{good_path}",
138
+ {}
139
+ ) { system("exit 0", out: File::NULL) }
140
+
141
+ described_class.scan(good_path)
142
+ end
143
+ end
144
+
145
+ context 'when set with daemonize' do
146
+ before { Clambytoo.configure(daemonize: true) }
147
+
148
+ it 'executes the clamdscan executable from the custom path' do
149
+ expect(runner).to receive(:system).with(
150
+ "#{custom_path}/clamdscan --no-summary #{good_path}",
151
+ {}
152
+ ) { system("exit 0", out: File::NULL) }
153
+
154
+ described_class.scan(good_path)
155
+ end
156
+ end
157
+ end
158
+
159
+ describe 'special filenames' do
160
+ it 'does not fail' do
161
+ expect(described_class.scan(special_path)).to be(false)
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+ require 'support/shared_context'
3
+
4
+ describe Clambytoo do
5
+ include_context 'paths'
6
+
7
+ before { Clambytoo.configure(Clambytoo::DEFAULT_CONFIG.dup) }
8
+
9
+ it "should find clamscan" do
10
+ expect(Clambytoo.scanner_exists?).to be true
11
+ end
12
+
13
+ it "should scan file as safe" do
14
+ expect(Clambytoo.safe?(good_path)).to be true
15
+ expect(Clambytoo.virus?(good_path)).to be false
16
+ end
17
+
18
+ it "should scan file and return nil" do
19
+ Clambytoo.configure({:error_file_missing => false})
20
+ expect(Clambytoo.safe?(bad_path)).to be nil
21
+ expect(Clambytoo.virus?(bad_path)).to be nil
22
+ end
23
+
24
+ it "should scan file as dangerous" do
25
+ begin
26
+ file = download('https://secure.eicar.org/eicar.com')
27
+ rescue SocketError => error
28
+ pending("Skipped because reasons: #{error}")
29
+ end
30
+
31
+ dangerous = file.path
32
+ Clambytoo.configure({:error_file_virus => true})
33
+ expect{Clambytoo.safe?(dangerous)}.to raise_exception(Clambytoo::VirusDetected)
34
+ expect{Clambytoo.virus?(dangerous)}.to raise_exception(Clambytoo::VirusDetected)
35
+ Clambytoo.configure({:error_file_virus => false})
36
+ expect(Clambytoo.safe?(dangerous)).to be false
37
+ expect(Clambytoo.virus?(dangerous)).to be true
38
+ File.delete(dangerous)
39
+ end
40
+
41
+ # From the clamscan man page:
42
+ # Pass the file descriptor permissions to clamd. This is useful if clamd is
43
+ # running as a different user as it is faster than streaming the file to
44
+ # clamd. Only available if connected to clamd via local(unix) socket.
45
+ context 'fdpass option' do
46
+ it 'is false by default' do
47
+ expect(Clambytoo.config[:fdpass]).to eq false
48
+ end
49
+ it 'accepts an fdpass option in the config' do
50
+ Clambytoo.configure(fdpass: true)
51
+ expect(Clambytoo.config[:fdpass]).to eq true
52
+ end
53
+ end
54
+
55
+ # From the clamscan man page:
56
+ # Forces file streaming to clamd. This is generally not needed as clamdscan
57
+ # detects automatically if streaming is required. This option only exists for
58
+ # debugging and testing purposes, in all other cases --fdpass is preferred.
59
+ context 'stream option' do
60
+ it 'is false by default' do
61
+ expect(Clambytoo.config[:stream]).to eq false
62
+ end
63
+ it 'accepts an stream option in the config' do
64
+ Clambytoo.configure(stream: true)
65
+ expect(Clambytoo.config[:stream]).to eq true
66
+ end
67
+ end
68
+
69
+ context 'error_clamscan_client_error option' do
70
+ it 'is false by default' do
71
+ expect(Clambytoo.config[:error_clamscan_client_error]).to eq false
72
+ end
73
+ it 'accepts an error_clamscan_client_error option in the config' do
74
+ Clambytoo.configure(error_clamscan_client_error: true)
75
+ expect(Clambytoo.config[:error_clamscan_client_error]).to eq true
76
+ end
77
+
78
+ before {
79
+ Clambytoo.configure(check: false)
80
+ allow_any_instance_of(Process::Status).to receive(:exitstatus).and_return(2)
81
+ allow(Clambytoo).to receive(:system)
82
+ }
83
+
84
+ context 'when false' do
85
+ before { Clambytoo.configure(error_clamscan_client_error: false) }
86
+
87
+ it 'virus? returns true when the daemonized client exits with status 2' do
88
+ Clambytoo.configure(daemonize: true)
89
+ expect(Clambytoo.virus?(good_path)).to eq true
90
+ end
91
+ it 'returns true when the client exits with status 2' do
92
+ Clambytoo.configure(daemonize: false)
93
+ expect(Clambytoo.virus?(good_path)).to eq true
94
+ end
95
+ end
96
+
97
+ context 'when true' do
98
+ before { Clambytoo.configure(error_clamscan_client_error: true) }
99
+
100
+ it 'virus? raises when the daemonized client exits with status 2' do
101
+ Clambytoo.configure(daemonize: true)
102
+ expect { Clambytoo.virus?(good_path) }.to raise_error(Clambytoo::ClamscanClientError)
103
+ end
104
+ it 'returns true when the client exits with status 2' do
105
+ Clambytoo.configure(daemonize: false)
106
+ expect(Clambytoo.virus?(good_path)).to eq true
107
+ end
108
+ end
109
+ end
110
+
111
+ context 'executable paths' do
112
+ context 'executable_path_clamscan option' do
113
+ it 'is clamscan by default' do
114
+ expect(Clambytoo.config[:executable_path_clamscan]).to eq 'clamscan'
115
+ end
116
+ it 'accepts an executable_path_clamscan option in the config' do
117
+ path = '/custom/path/clamscan'
118
+ Clambytoo.configure(executable_path_clamscan: path)
119
+ expect(Clambytoo.config[:executable_path_clamscan]).to eq path
120
+ end
121
+ end
122
+
123
+ context 'executable_path_clamdscan option' do
124
+ it 'is clamdscan by default' do
125
+ expect(Clambytoo.config[:executable_path_clamdscan]).to eq 'clamdscan'
126
+ end
127
+ it 'accepts an executable_path_clamdscan option in the config' do
128
+ path = '/custom/path/clamdscan'
129
+ Clambytoo.configure(executable_path_clamdscan: path)
130
+ expect(Clambytoo.config[:executable_path_clamdscan]).to eq path
131
+ end
132
+ end
133
+
134
+ context 'executable_path_freshclam option' do
135
+ it 'is freshclam by default' do
136
+ expect(Clambytoo.config[:executable_path_freshclam]).to eq 'freshclam'
137
+ end
138
+ it 'accepts an executable_path_freshclam option in the config' do
139
+ path = '/custom/path/freshclam'
140
+ Clambytoo.configure(executable_path_freshclam: path)
141
+ expect(Clambytoo.config[:executable_path_freshclam]).to eq path
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,2 @@
1
+ This is a virus-free file.
2
+ It is used by automated tests.
@@ -0,0 +1,2 @@
1
+ This is a virus-free file.
2
+ It is used by automated tests.
@@ -0,0 +1,30 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'open-uri'
5
+ require 'tempfile'
6
+
7
+ require 'clamby' # and any other gems you need
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec do |mocks|
11
+ # so that Command can keep doing what it always does.
12
+ mocks.verify_partial_doubles = true
13
+ end
14
+
15
+ def download(url)
16
+ file = open(url)
17
+ file.is_a?(StringIO) ? to_tempfile(file) : file
18
+ end
19
+
20
+ # OpenURI returns either Tempfile or StringIO depending of the size of
21
+ # the response. We want to unify this and always return Tempfile.
22
+ def to_tempfile(io)
23
+ tempfile = Tempfile.new('tmp')
24
+ tempfile.binmode
25
+ ::OpenURI::Meta.init(tempfile, io)
26
+ tempfile << io.string
27
+ tempfile.rewind
28
+ tempfile
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ RSpec.shared_context 'paths' do
2
+ let(:special_path) { File.expand_path('../../fixtures/safe (special).txt', __FILE__) }
3
+ let(:good_path) { File.expand_path('../../fixtures/safe.txt', __FILE__) }
4
+ let(:bad_path) { File.expand_path("not-here/#{rand 10e6}.txt", __FILE__) }
5
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clambytoo
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - kobaltz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: This is a temp fork for testing purposes only. Clamby allows users to
56
+ scan files uploaded with Paperclip or Carrierwave. If a file has a virus, then you
57
+ can delete this file and discard it without causing harm to other users.
58
+ email:
59
+ - dave@k-innovations.net
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - Rakefile
67
+ - clambytoo.gemspec
68
+ - lib/clambytoo.rb
69
+ - lib/clambytoo/command.rb
70
+ - lib/clambytoo/error.rb
71
+ - lib/clambytoo/version.rb
72
+ - spec/.DS_Store
73
+ - spec/clamby/command_spec.rb
74
+ - spec/clamby_spec.rb
75
+ - spec/fixtures/safe (special).txt
76
+ - spec/fixtures/safe.txt
77
+ - spec/spec_helper.rb
78
+ - spec/support/shared_context.rb
79
+ homepage: ''
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.0.9
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Scan file uploads with ClamAV
102
+ test_files:
103
+ - spec/.DS_Store
104
+ - spec/clamby/command_spec.rb
105
+ - spec/clamby_spec.rb
106
+ - spec/fixtures/safe (special).txt
107
+ - spec/fixtures/safe.txt
108
+ - spec/spec_helper.rb
109
+ - spec/support/shared_context.rb