lib/ddr/antivirus/adapters/clamd_scanner_adapter.rb in ddr-antivirus-2.0.0 vs lib/ddr/antivirus/adapters/clamd_scanner_adapter.rb in ddr-antivirus-2.1.1

- old
+ new

@@ -1,84 +1,76 @@ -require "open3" require "fileutils" require "shellwords" module Ddr::Antivirus # # Adapter for clamd client (clamdscan) # class ClamdScannerAdapter < ScannerAdapter SCANNER = "clamdscan".freeze + CONFIG = "clamconf".freeze + MAX_FILE_SIZE_RE = Regexp.new('^MaxFileSize = "(\d+)"') + def scan(path) - output, status = clamdscan(path) + output, exitcode = clamdscan(path) result = ScanResult.new(path, output, version: version, scanned_at: Time.now.utc) - case status.exitstatus + case exitcode when 0 result when 1 raise VirusFoundError.new(result) when 2 raise ScannerError.new(result) end end def clamdscan(path) - make_readable(path) do - command(path) + output = make_readable(path) do + command "--fdpass", safe_path(path) end + [ output, $?.exitstatus ] end def version - out, err, status = Open3.capture3(SCANNER, "-V") - out.strip + @version ||= command("-V").strip end + def config + @config ||= `#{CONFIG}` + end + + def max_file_size + if m = MAX_FILE_SIZE_RE.match(config) + m[1] + end + end + private - def command(path) - safe_path = Shellwords.shellescape(path) - Open3.capture2e(SCANNER, safe_path) + def command(*args) + cmd = args.dup.unshift(SCANNER).join(" ") + `#{cmd}` end def make_readable(path) changed = false original = File.stat(path).mode # raises Errno::ENOENT if !File.world_readable?(path) changed = FileUtils.chmod("a+r", path) - logger.info "File #{path} made world-readable for virus scanning." + logger.debug "#{self.class} - File \"#{path}\" made world-readable." end result = yield if changed FileUtils.chmod(original, path) - logger.info "Mode reset to original #{original} on file #{path}." + logger.debug "#{self.class} - Mode on file \"#{path}\" reset to original: #{original}." end result end - end - - # Result of a scan with the ClamdScannerAdapter - # @api private - class ClamdScanResult < ScanResult - - def virus_found - if m = /: ([^\s]+) FOUND$/.match(output) - m[1] - end - end - - def ok? - status.exitstatus == 0 - end - - def has_virus? - status.exitstatus == 1 - end - - def error? - status.exitstatus == 2 + def safe_path(path) + Shellwords.shellescape(path) end end end