'''
NOD module, version 0.6.1

(c) 2003-2004 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 os,socket,re,string
from dazuko import dazuko

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

class nod2(ascanner):
  '''
  NOD2 scanner. Works with nod32lfs.
  
  Usage: nod2(['command','params...'])

  Where: in [] are command line parameters for nod32

  This scanners is a realscanner, which can be used to scan
  for viruses. You can use nod32 from nod32lfs package.
  '''
  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']):
      self.arg=arg
  def scanfile(self,files,dirname=''):
      level,detected,virlist=0.0,'',[]
      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
      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 nodold(ascanner):
  '''
  NOD32d scanner. This works only with nod32d from ESET.
  
  Usage: nodoldd(['host',port],params)
  
  Where: 'host' is a string, which defines a host of nod32d
            (by default 'localhost')
         port is a number, which defines a port of nod32d
            (by default 8448)
         params is a string to define scanner parameters.
            It's defaults to "@patt:1@heur:2@clean:0".
            There is no format description.
  
  This scanner mat be used to scan for viruses by ESET's NOD32.
  Only old version (buyed directly from ESET) may be used.
  
  WARNING! NOD32 can't scan direct mboxes and archives.
  You need parsemail() module to parse mailboxes. For exmple:
    mimeparse(stream2file(nodoldd(['localhost',8448])))
  If you need also unpacker support, add decompress interscanner:
    mimeparse(stream2file(decompress(nodoldd(['localhost',8448]))))
  
  If you want start nod32d in chroot, use for example:
    exec chroot /var/spool/vscan /opt/nod32/nod32d
  from any script.
  '''
  name='NodOldD()'
  def __init__(self,arg,params="@patt:1@heur:2@clean:0"):
      self.arg=arg
      self.params=params
  def scanfile(self,filenames,dirname=''):
      level=0.0
      debug.echo(7,"nodold(): ",[filenames],dirname)
      if type(self.arg)==type('string'): # local socket
        s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
        socket_settimeout(s,120)
        s.connect(self.arg)
      else:
        s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        socket_settimeout(s,120)
        s.connect((self.arg[0],self.arg[1]))
      f=s.makefile('rw',BUFSIZE)
      r=f.readline() # 200 NOD32SS 1.386 (20030326)
      s.sendall("PARM "+self.params+"\n")
      r=f.readline() # 200 OK (patt: 1, heur: 2, clean: 0)
      ret=[]
      for fname in filenames:
        s.sendall("SCAN "+os.path.join(dirname,fname)+"\n")
        line=f.readline()
        if not re.search("^200",line):
          ret.append(line[4:])
          level+=1.0
        if re.search("^5",line): # error opening file?
          raise ScannerError,'nodold: '+line
      s.sendall("QUIT\n")
      r=f.readline()
      f.close()
      s.shutdown(2)
      s.close()
      if ret==[]:
        detected=''
      else:
        detected=string.rstrip(ret[0])
      if is_infected(level,detected):
        mail.addheader('X-Sagator-NodOld',detected)
      return level,detected,ret
