class Ratonvirus::Scanner::Base

Attributes

config[R]

:errors - Only available after `virus?` has been called.

errors[R]

:errors - Only available after `virus?` has been called.

Public Class Methods

executable?() click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 9
def executable?
  false
end
new(configuration = {}) click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 17
def initialize(configuration = {})
  @config = default_config.merge!(configuration)

  # Make the following callbacks available:
  # - before_process_scan
  # - before_scan
  # - after_scan
  # - after_process_scan
  #
  # Usage:
  #   module CustomAddon
  #     def self.extended(validator)
  #       validator.before_process_scan :around_scan
  #       validator.before_scan :do_something
  #       validator.after_scan :do_something
  #       validator.before_process_scan :around_scan
  #     end
  #
  #     private
  #       def around_scan(resource)
  #         puts resource.inspect
  #         # Depends on the provided resource, e.g.
  #         # => #<ActiveStorage::Attached::One: ...>
  #         # => #<ActiveStorage::Attached::Many: ...>
  #         # => #<CarrierWave::Uploader::Base: ...>
  #         # => #<File: ...>
  #         # => #<String: ...>
  #       end
  #
  #       def do_something(processable)
  #         puts processable.inspect
  #         # => #<Ratonvirus::Processable: ...>
  #       end
  #   end
  define_callbacks :process_scan # Around the scan for the whole resource
  define_callbacks :scan # The actual scan for individual assets

  setup
end

Public Instance Methods

available?() click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 67
def available?
  return @available unless @available.nil?

  @available = self.class.executable?
end
setup() click to toggle source

This method can be overridden in the scanner implementations in case the setup needs to be customized.

# File lib/ratonvirus/scanner/base.rb, line 59
def setup
  if config[:force_availability]
    @available = true
  else
    available?
  end
end
virus?(resource) click to toggle source

The virus? method runs the scan and returns a boolean indicating whether the scanner rejected the given resource or detected a virus. Scanning is mainly used to detect viruses but the scanner can reject the resource also because of other reasons than it detecting a virus.

All these cases, however, should be interpreted as the resource containing a virus because in case there is e.g. a client error, we cannot be sure whether the file contains a virus and therefore it's safer to assume the worst.

Possible errors are:

  • :antivirus_virus_detected - A virus was detected.

  • :antivirus_file_not_found - The scanner did not find the file for the given resource.

  • :antivirus_client_error - There was a client error at the scanner, e.g. it is temporarily unavailable.

# File lib/ratonvirus/scanner/base.rb, line 89
def virus?(resource)
  prepare

  @errors = []

  run_callbacks :process_scan, resource do
    storage.process(resource) do |processable|
      # In case multiple processables are processed, make sure that the
      # local errors for each scan refer only to that scan.
      errors_before = @errors
      @errors = []

      begin
        scan(processable)
      ensure
        # Make sure that after the scan, the errors are reverted back to
        # all errors.
        @errors = errors_before + @errors
      end
    end
  end

  # Only show unique errors
  errors.uniq!

  errors.any?
end

Protected Instance Methods

default_config() click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 119
def default_config
  { force_availability: false }
end
run_scan(_path) click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 135
def run_scan(_path)
  raise NotImplementedError, "Implement run_scan on #{self.class.name}"
end
scan(processable) click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 127
def scan(processable)
  processable.path do |path|
    run_callbacks :scan, processable do
      run_scan(path)
    end
  end
end
storage() click to toggle source
# File lib/ratonvirus/scanner/base.rb, line 123
def storage
  Ratonvirus.storage
end

Private Instance Methods

prepare() click to toggle source

Prepare is called each time before scanning is run. During the first call to this method, the addons are applied to the scanner instance.

# File lib/ratonvirus/scanner/base.rb, line 143
def prepare
  return if @ready

  Ratonvirus.addons.each do |addon_cls|
    extend addon_cls
  end

  @ready = true
end