Class: ClamAV::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/clamav/client.rb

Defined Under Namespace

Classes: ConnectTimeoutError, ConnectionError, Error, ReadTimeoutError, WriteTimeoutError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Client

Returns a new instance of Client.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/clamav/client.rb', line 30

def initialize(*args)
  @options = env_options

  args.each do |arg|
    case arg
    when Connection
      @connection = arg
    when Hash
      @options = env_options.inject({}) do |acc, (option, default)|
        acc[option] = arg[option] || default
        acc
      end
    end
  end
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



28
29
30
# File 'lib/clamav/client.rb', line 28

def options
  @options
end

Instance Method Details

#build_socketObject



134
135
136
137
138
139
140
141
142
# File 'lib/clamav/client.rb', line 134

def build_socket
  return Socket.tcp(tcp_host, tcp_port, connect_timeout: connect_timeout) if tcp?

  ::UNIXSocket.new(unix_socket)
rescue Errno::ETIMEDOUT => e
  raise ConnectTimeoutError.new(e.to_s)
rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => e
  raise ConnectionError.new(e.to_s)
end

#connect!(conn = nil) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/clamav/client.rb', line 106

def connect!(conn=nil)
  (conn || @connection).establish_connection
rescue Errno::ETIMEDOUT => e
  @connection = nil

  raise ConnectTimeoutError.new(e.to_s)
rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => e
  @connection = nil

  raise ConnectionError.new(e.to_s)
end

#connectionObject



92
93
94
95
96
# File 'lib/clamav/client.rb', line 92

def connection
  @connection ||= default_connection.tap do |conn|
    connect!(conn)
  end
end

#default_connectionObject



98
99
100
101
102
103
104
# File 'lib/clamav/client.rb', line 98

def default_connection
  ClamAV::Connection.new(
    client: self,
    socket: build_socket,
    wrapper: ::ClamAV::Wrappers::NewLineWrapper.new
  )
end

#disconnect!Object



118
119
120
121
122
123
124
# File 'lib/clamav/client.rb', line 118

def disconnect!
  return true if @connection.nil?

  @connection.disconnect!.tap do
    @connection = nil
  end
end

#env_optionsObject



63
64
65
66
67
68
69
70
71
72
# File 'lib/clamav/client.rb', line 63

def env_options
  @env_options ||= {
    unix_socket: ENV.fetch('CLAMD_UNIX_SOCKET', '/var/run/clamav/clamd.ctl'),
    tcp_host: ENV.fetch('CLAMD_TCP_HOST', nil),
    tcp_port: ENV.fetch('CLAMD_TCP_PORT', nil),
    connect_timeout: ENV.fetch("CLAMD_TCP_CONNECT_TIMEOUT", nil),
    write_timeout: ENV.fetch("CLAMD_TCP_WRITE_TIMEOUT", nil),
    read_timeout: ENV.fetch("CLAMD_TCP_READ_TIMEOUT", nil),
  }
end

#execute(command) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/clamav/client.rb', line 74

def execute(command)
  begin
    command.call(connection)
  rescue Errno::ETIMEDOUT => e
    disconnect!

    raise ConnectTimeoutError.new(e.to_s)
  rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETDOWN  => e
    disconnect!

    raise ConnectionError.new(e.to_s)
  rescue => e
    disconnect!

    raise e
  end
end

#file?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/clamav/client.rb', line 130

def file?
  !tcp
end

#pingObject



144
145
146
# File 'lib/clamav/client.rb', line 144

def ping
  execute Commands::PingCommand.new
end

#safe?(target) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
151
# File 'lib/clamav/client.rb', line 148

def safe?(target)
  return instream(target).virus_name.nil? if target.is_a?(StringIO)
  scan(target).all? { |file| file.virus_name.nil? }
end

#tcp?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/clamav/client.rb', line 126

def tcp?
  !!tcp_host && !!tcp_port
end