#
# getides.py
#
# Bob Stammers <saphena@compuserve.com>, January 2002
#
# Use this as you please.  It comes, however, with no warranties at all!

import sys,os,zipfile,re
from shutil import copy

debug = 0

# Release history
#
# 1.0  08JAN02 Initial release to Parnassus
# 1.1  10JAN02 Include Version/debug + improved error trapping

version = '1.1'

class idehandler:
  """        i d e h a n d l e r
  
  This class handles automatic downloading of IDEs from SOPHOS.
  
  It's designed for upating clients across LANs so has separate methods for
  fetching and distributing the IDEs.
  
  SGET.EXE must be in the current folder
  
  """
  def __init__(self,
    			download='.',    # folderpath to hold downloads
    			verbose=0,     
    			host="http://www.sophos.com/downloads/ide/",
    			idepat=".*\.ide",    # re to match IDE files
    			modID="GetIDEs",    # prefix shown in print messages
    			retries=1    # number of retries of SGET on failure
    ):
    self.download = download
    self.verbose = verbose or debug
    self.host = host
    self.pat = re.compile(idepat,re.I)   # Note the case-insensitive flag
    self.modID = modID + ':'
    self.SGET_retries = retries
    

  def fetchupdates(self,zipid='ides.zip'):
    """       f e t c h u p d a t e s
    
    This does the work of fetching the latest set of virus identities
    from the SOPHOS website into the local download directory.
    """
    
    # Clear existing .zip & .ide from download folder
    
    if self.verbose: print self.modID,"Clearing download files"
    
    if os.path.exists(os.path.join(self.download,zipid)):
     try:
      os.remove(os.path.join(self.download,zipid))
     except:
      if self.verbose: print self.modID,"Couldn't remove existing",zipid
   
    for n in os.listdir(self.download):
      if self.pat.match(n):
        try:
         os.remove(os.path.join(self.download,n))
        except:
         if self.verbose: print self.modID,"Couldn't remove existing",n
   
    sget_run_not_ok = 1
    args = ["sget"]
    if not self.verbose: args.append("-q") # make SGET run silently
    args.extend(["-l=" + self.download,self.host + zipid])
    while sget_run_not_ok:
     try:
      sget_run_not_ok = os.spawnv(os.P_WAIT,"SGET.EXE",args)
      
      # This may fail first time through if no existing internet connect
      # available on proxy'ed network
      
      if sget_run_not_ok:
       if self.verbose: print self.modID,"SGET returned",sget_run_not_ok
       if self.SGET_retries > 0:
        self.SGET_retries -= 1
       else:
        break
     except:
      if debug: raise
      break

    if sget_run_not_ok:
     if self.verbose: print self.modID,"SGET failed, aborting"
     return 0
     
    try:
      if self.verbose: print self.modID,"Unzipping IDEs"
      
      z = zipfile.ZipFile(os.path.join(self.download,zipid),"r")
      for n in z.namelist():
       f = open(os.path.join(self.download,n),'w')
       f.write(z.read(n))
       f.close()
 
      if self.verbose: print self.modID,len(z.namelist()),"IDEs downloaded"
      return 1
    except:
      if debug: raise
      if self.verbose: print self.modID,"Unzip failed, aborting"
      return 0
 
  def updatetarget(self,
                     target,		# folder to be updated
                     issetup=0	# is this a standalone SWEEP or a network setup?
                   ):
    """       u p d a t e t a r g e t
    
    This updates the target folder with the IDEs recently downloaded
    from the SOPHOS website
    """
    if issetup:
     targettype = 'SETUP'
    else:
     targettype = 'SWEEP'
    try:
      if self.verbose: print self.modID,"Updating %s folder %s" % (targettype,target)
      for n in os.listdir(target): # kill any existing IDEs
       if self.pat.match(n):
        os.remove(os.path.join(target,n))
      for n in os.listdir(self.download): # copy over the new ones
       if self.pat.match(n):
         copy(os.path.join(self.download,n),os.path.join(target,n))
      if issetup:
        args = ["setup"]
        if self.verbose:
         args.append("-ni") # not interactive
        else:
         args.append("-in") # invisible
        args.append("/UPDATE")
        os.spawnv(os.P_WAIT,os.path.join(target,"SETUP.EXE"),args)
      if self.verbose: print self.modID,target,"updated"
      return 1
    except:
      if debug: raise
      if self.verbose: print self.modID,"UPDATE FAILED"
      return 0
      

if __name__ == '__main__':
 ge = idehandler()
 ge.fetchupdates()
 ge.updatetarget('C:\\Program Files\\Sophos SWEEP')
 