class VirusScanService::KasperskyRunner

Constants

AntivirusExecNotSet
RequestNotSuccessful
ScanLogParseError
ScanLogPathNotSet

Attributes

antivirus_exec[RW]
archive_folder[W]
result[R]
scan_folder[W]
scan_log_path[RW]
timestamp_builder[RW]
url[R]

Public Class Methods

new(url) click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 18
def initialize(url)
  @url = url
  @timestamp_builder = ->{ Time.now.to_i.to_s }
end

Public Instance Methods

archive_folder() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 53
def archive_folder
  @archive_folder ||= Pathname
    .new('/tmp')
    .join('scans')
    .tap do |path|
      ::FileUtils.mkdir_p(path)
    end
end
call() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 23
def call
  begin
    pull_file
    begin
      empty_scan_log
      scan_file
      set_result
    ensure
      remove_file
      archive_scan_log if File.size?(scan_log_path) # Exists & non-empty
    end
  rescue URI::InvalidURIError, RequestNotSuccessful
    set_result_download_error
  end
  return nil
end
scan_file_path() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 40
def scan_file_path
  scan_folder.join(filename)
end
scan_folder() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 44
def scan_folder
  @scan_folder ||= Pathname
    .new('/tmp')
    .join('scans')
    .tap do |path|
      ::FileUtils.mkdir_p(path)
    end
end

Private Instance Methods

archive_scan_log() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 63
def archive_scan_log
  archive_name = "#{File.basename(scan_log_path.to_s, '.*')}_#{timestamp_builder.call}.log"
  ::FileUtils.mv(scan_log_path, archive_folder.join(archive_name))
end
empty_scan_log() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 87
def empty_scan_log
  File.open(scan_log_path, 'w') {}
end
filename() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 133
def filename
  File.basename(uri.path)
end
pull_file() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 115
def pull_file
  http = build_http

  request = Net::HTTP::Get.new(uri.to_s)
  response = http.request(request)

  raise(RequestNotSuccessful) unless response.class == Net::HTTPOK

  open(scan_file_path, 'wb') do |file|
    file.write(response.body)
    file.close
  end
end
remove_file() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 68
def remove_file
  begin
    FileUtils.rm_r(scan_folder.join(filename))
  rescue => e
    # kaspersky is automatically removing suspicious files
    # this is rescue ensures that after kasperky removes that file
    # script wont blow up
    #
    # For whatever reason under Windows using
    #
    #   if File.exist?(scan_folder.join(filename))
    #
    # won't help to determine if file was removed by kaspersky
    #
    # That's why this captures if exception matches Permission deny @ unlink_internal
    raise e unless e.to_s.match('unlink_internal')
  end
end
scan_file() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 110
def scan_file
  (antivirus_exec || raise(AntivirusExecNotSet))
    .scan(scan_file_path, scan_log_path)
end
set_result() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 91
def set_result
  result = File.read(scan_log_path || raise(ScanLogPathNotSet))
  result.scan(/(?:Total detected|Threats found):\s*(\d+)/) do |threat_count, *other|
    if threat_count == ''
      raise ScanLogParseError
    elsif threat_count == '0'
      @result = 'Clean'
    else
      @result = 'VirusInfected'
    end
  end

  raise ScanLogParseError if @result.nil?
end
set_result_download_error() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 106
def set_result_download_error
  @result = 'FileDownloadError'
end
uri() click to toggle source
# File lib/virus_scan_service/kaspersky_runner.rb, line 129
def uri
  @uri ||= URI.parse(url)
end