'''
NOD module, version 0.7.0

(c) 2003-2006 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 *
from filesys import *

__all__=['nod2','nod2pac','nod2dazuko']

class nod2(ascanner):
  '''
  NOD2 scanner. Works with nod32lfs.

  This scanners is a realscanner, which can be used to scan
  for viruses. You can use nod32 from nod32lfs package.
  
  Usage: nod2(['command','params...'])

  Where: in [] are command line parameters for nod32
  '''
  name='nod2()'
  reg_nod2_02=re.compile('^object="[^"]*", name="([^"]*)", virus="([^"]*)", ',
        re.IGNORECASE)
  reg_nod2_01=re.compile(" - (([^ ][^-][^ ]|[a-z/-])*)$",re.IGNORECASE)
  def __init__(self,arg=['/usr/sbin/nod32','--log-brief','--all','--mail','--arch','--adv-heur','--adware','--unsafe']):
      self.arg=arg
  def scanfile(self,files,dirname='',args={}):
      level=0.0
      detected=''
      virlist=[]
      if dirname:
        pf=popen(self.arg+[safe.fn(dirname)])
        pf.tocmd.close()
        for line in pf.readlines():
          virlist.append(line)
        rc=pf.wait()
        pf.fromcmd.close()
        debug.echo(4,"NOD2: ",rc,virlist)
        if rc in [1,10]:
          reg1=self.reg_nod2_02.search(virlist[0])
          if reg1:
            detected=reg1.group(2)
            level+=1.0
          else:
            reg1=self.reg_nod2_01.search(virlist[0])
            level+=1.0
            if reg1:
              detected=reg1.group(1)
              level+=1.0
            else:
              debug.echo(1,"NOD2: Can't decode reply! ",virlist)
              detected="CANT_DECOCE_VIRNAME"
              level+=1.0
        elif rc==101: # Error occurred during archives unpacking
          return 0.5,'ArchiveUnpackingError',virlist
        elif rc>100:
          debug.echo(1,"ERROR: NOD2: ",rc,virlist)
          raise ScannerError,'Error running NOD32: [%d] %s' % (rc,virlist[0])
      if is_infected(level,detected):
        mail.addheader('X-Sagator-NOD2',detected)
      return level,detected,virlist

class nod2dazuko(dazuko):
  '''
  NOD32lfs scanner over dazuko module.
  
  Usage: nod2dazuko('/dazuko_prefix','logfile')
  
  Where: '/dazuko_prefix' is a string, which defines directory
            and a part of filename to store scanned files,
            by default '/tmp/dazuko'
         'logfile' is a string, which defines full path and filename
            of logfile, by default not logfile used
  '''
  name='nod2dazuko()'
  def __init__(self,dazuko_prefix,logfile=''):
      self.prefix=dazuko_prefix
      self.logfile=logfile
      self.reg=re.compile(
        '^[0-9: -]*: event=[a-z]*, uid=[0-9]*, access=0, object="[^"]*", name="([^"]*)", virus="([^"]*)", ',
        re.IGNORECASE)

class nod2pac(filesys):
  '''
  NOD32lfs scanner over it's preload library module.

  You need to set LD_PRELOAD to NOD32's preload library (libnod32pac.so).
  You can do this by adding this line into /etc/sysconfig/sagator:
    LD_PRELOAD=/usr/lib/libnod32pac.so
  
  Usage: nod2pac(logfile='/var/log/nod32d.log',prefix='/tmp/scand')
  
  Where: logfile is a string, which defines path to logfile. This parameter
           is used only when called from scanner daemon.
         prefix is a string, which defines directory and a part of filename
           to store scanned files, by default '/tmp/scand'.

  Recommended settings for NOD32LFS:
    /etc/nod32/nod32.cfg:
      [global]
      log_enabled = yes
      [pac]
      ctl_incl = "/var/spool/vscan/tmp/scand"
  
  New in version 0.8.0.
  '''
  name='nod2pac()'
  def __init__(self,prefix='/tmp/scand',logfile='/var/log/nod32d.log'):
      self.prefix=prefix
      self.logfile=logfile
      self.reg=re.compile(
        '^[0-9: +-]*: vdb=(?P<vdb>[0-9]+), agent=pac, msgid=none, object="(?P<object>[^"]*)", name="(?P<filename>[^"]*)", virus="(?P<virus>[^"]*)", action="[^"]*", info="(?P<info>[^"]*)"(?:, lines=(?P<lines>[0-9]+))?',
        re.IGNORECASE)
      self.virname_to_return_value={
        'is OK': (0.5,'ProcessingError')
      }
      self.hdr='' #fromhdr()
  def shortname(self,filename):
      return filename.split(' -> ')[0]
  def scanfile(self,files,dirname='',args={}):
      return filesys.scanfile(self,files,dirname,args)
