'''
avg module, version 0.6.0

(c) 2003-2016 Jan ONDREJ (SAL) <ondrejj(at)salstar.sk>
                                                                                
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

'''

from avlib import *
import socket, re

__all__ = ['avgd']

class avgd(ascanner):
  '''
  AVG daemon realscanner.
  
  This scanners is a realscanner, which can be used to scan
  for viruses. It uses AVGd (a deamonized linux version of AVG7).

  Usage: avgd(params='', connto=('localhost', 54322), chroot='')

  Where: params is a string which defines command line parameters,
           like -arc, -heur, -rt, ... see man page for avgscan
           This option is not accepted by AVG8+, so it defaults to "".
         connto is a tuple of host,port of avgd,
           by default ('localhost', 54322)
         chroot is an string in which sagator is running, if avgd
           is not running in this chroot. By default chroot='', so your
           avgscand should run inside sagator's chroot.

  To start AVGd in chroot, move all neccessary files into your chroot,
  and change following line in init.d/avgd from:
    daemon $AVG_HOME/avgscan -d
  to:
    daemon chroot /var/spool/vscan $AVG_HOME/avgscan -d
  or similiar.
  '''
  name='avgd()'
  def __init__(self,params="", connto=('localhost', 54322), chroot=''):
      self.params = params
      self.connto = connto
      self.chroot = chroot
  def _send_command(self, s, cmd):
      debug.echo(5, self.name+": AVG command: "+cmd)
      s.sendall(cmd+"\n")
  def scanfile(self,files,dir='',args={}):
      level = 0.0
      detected = b''
      virlist = []
      s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      socket_settimeout(s,120)
      try:
        s.connect(self.connto)
      except socket.error as err:
        (ec,es) = err.args
        debug.echo(2, "ERROR: avgd(): ", es)
        raise
      f = s.makefile('rw', 512)
      while not re.search("^220 ", f.readline()):
        pass
      if self.params:
        self._send_command(s, "PARM "+self.params)
        l = f.readline()
        if not re.search("^200 ",l):
          raise ScannerError('Protocol error: '+l)
      for fn in files:
        self._send_command(s, "SCAN "+self.chroot+fn)
        l=f.readline()
        debug.echo(4,self.name+": ",l)
        if re.search("^200 ",l):
          pass
        elif re.search("^403 ",l):
          virlist.append(fn+': '+l+'\n')
          reg1=re.search("^403 .*?: +(.*?) +([^ ]+) ?\r?\n?\n?$",l)
          level+=1
          if reg1:
            if not detected:
              detected=reg1.group(2).strip()
          else:
            if not detected:
              detected="Unknown_virus"
        else:
          raise ScannerError(l)
      # send QUIT only for AVG7 and lower
      self._send_command(s, "QUIT")
      l=f.readline()
      if not re.search("^221",l):
        debug.echo(1,"avgd(): AVG returned wrong exit code for QUIT: ",l)
      f.close()
      s.shutdown(socket.SHUT_RDWR)
      s.close()
      return level, detected, virlist
