'''
ICAP module, version 0.2
 
(c) 2003-2018 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__ = ['savse']

class icap:
  def __init__(self, host, port, path='AVSCAN?action=SCAN'):
      self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      socket_settimeout(self.s, 120)
      self.s.connect((host, port))
      self.f = self.s.makefile('rw',0)
      self.server = host+":"+str(port)
      self.path = path
  def check(self, buffer, filename):
      level, virname, response = 0.0, b'', []
      # send ICAP request
      self.s.sendall("RESPMOD icap://"+self.server+"/"+self.path+" ICAP/1.0\r\n")
      self.s.sendall("Host: "+self.server+"\r\n")
      self.s.sendall("Allow: 204\r\n")
      req = "GET http://sagator.salstar.sk/"+filename+" HTTP/1.1\r\n\r\n"
      hdr = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
      self.s.sendall("Encapsulated: req-hdr=0, res-hdr=%d, res-body=%d\r\n\r\n"
        % (len(req),len(req+hdr)))
      debug.echo(7, 'icap(): ', req, hdr)
      self.s.sendall(req)
      self.s.sendall(hdr)
      # send data buffer
      #i,l,s=0,len(buffer),0xFF
      #while True:
      #  if (i+s)>=l:
      #    self.s.sendall("%X\r\n" % (len(buffer[i:])))
      #    self.s.sendall(buffer[i:])
      #    self.s.sendall("\r\n\r\n0\r\n\r\n")
      #    break
      #  else:
      #    self.s.sendall("%X\r\n" % s)
      #    self.s.sendall(buffer[i:i+s])
      #    self.s.sendall("\r\n\r\n")
      #  i+=s
      self.s.sendall("%X\r\n" % (len(buffer)))
      self.s.sendall(buffer)
      self.s.sendall("\r\n\r\n0\r\n\r\n")
      # read protocol status
      ics = self.f.readline()
      debug.echo(7, "savse():", ics)
      try:
        icc = re.search("^ICAP/[0-9.]* ([0-9]{3}) ", ics).group(1)
      except:
        icc = '000'
      if icc=='204':
        pass # it's clean
      elif (icc[:2]=='20'):
        # returned OK
        while 1:
          line=self.f.readline()
          if not line:
            break
          debug.echo(7, "savse():", line)
          reg = re.search("^X-Infection-Found: Type=([0-9]*); Resolution=([0-9]*); Threat=([^;]*);",line)
          if reg:
            if (reg.group(1)=='0'):
              virname += reg.group(3)
              level += 1.0
              debug.echo(5, "savse(): found:", virname)
          else:
            reg1 = re.search("^X-Violations-Found:", line)
            if reg1:
              while 1:
                line=self.f.readline()
                if not line:
                  break
                if (line[0]==' ') or (line[0]=='\t'):
                  response.append(line)
                else:
                  break
      else:
        raise Exception(ics)
      return level, virname, response
  def close(self):
      self.s.shutdown(socket.SHUT_RDWR)

class savse(ascanner):
  '''
  Symantec antivirus scan engine scanner.
  
  Usage: savse('host',port)
  
  Example: parsemail(savse('localhost',1344))
  
  Comments:
    You need to configure ICAP protocol on port 1344 (or another)
    to use this scanner properly.
    These options are suggested in symcscan.cfg:
      BindAddress=127.0.0.1
      Port=1344
      Protocol=ICAP
      ExtensionPolicy=0
      ICAPActionPolicy=SCAN
      ICAPResponse=1
  '''
  name='savse()'
  def __init__(self, host, port=1344):
      self.host = host
      self.port = port
  def scanbuffer(self, buffer, args={}):
      c=icap(self.host,self.port)
      level, r, response = c.check(buffer,self.filename)
      c.close()
      return level, r, response
