'''
filetype module, version 0.3.2

(c) 2003 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.

String constants are based on Magdir/* from file package.
Extended to better support sfx archives.
 
Function returns an array of filetypes. For example for zip/sfx is returned:
  ['zip','exe'] in this order.
'''

import re,avlib

class rsc:
      def __init__(self,ext,*res):
          self.ext=ext
          self.fx=[]
          for r in res:
            self.fx.append(re.compile(r,re.DOTALL))
      def check(self,s):
          for i in self.fx:
            if i.search(s):
              return 1
          return 0

class rsc_multipos(rsc):
      def __init__(self, ext, res, *pos):
          self.ext = ext
          a = len(res.strip('^.'))
          self.pos = list([x+a for x in pos])
          self.pre, self.post = res.split('{}', 1)
          self.pre = re.compile(self.pre, re.DOTALL)
          self.post = re.compile('^'+self.post, re.DOTALL)
      def check(self,s):
          for i in self.pos:
            if self.pre.search(s) and self.post.search(s[i:]):
              return 1
          return 0

type_table = [
  rsc('Z', '^\037\235'),
  rsc('gz', '^\037\213'),
  rsc('bz2', '^BZh'),
  rsc('bz', '^BZ'),
  rsc('lzop', '^\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a'),
  rsc('tar', '^.{257}ustar(\0|\040\040\0)'),
  rsc('zip', '^PK\003\004'),
  rsc('zoo', '^.{20}\xdc\xa7\xc4\xfd'),
  rsc('rar', '^Rar!'),
  rsc('arj', '^\x60\xea'),
  rsc('lha', '^..-l[hz].-'),
  rsc('uc2', '^UC2\x1a'),
  rsc('cab', '^MSCF\0\0\0\0'),
  rsc('deb', '^!<arch>\ndebian'),
  rsc('cpio', '^(07070[712]|\xc7\x71|\x71\xc7)'),
  rsc('arc', '^\x1a[\x01\x02\x03\x04\x05\x06\x07\x08\x09]'),
  rsc('rpm', '^\xab\xed\xdb\xee'),
  rsc('uu', '^begin\040'),
  # Executables
  rsc_multipos('zip','^MZ.{}PK\003\004',
               11694,13297,15588,15770,28374,25115,26331,47031,49845,69120),
  rsc_multipos('rar','^MZ.{}Rar!',7193,38910,51710,95110),
  rsc('arj', '^MZ.{28}RJSX\xff\xff'),
  rsc('lha', '^MZ.{34}LHa\'s SFX','^MZ.{1636}-lh5-'),
  rsc('winpe', '^.{128}PE\0\0'),
  rsc('exe', '^[LM]Z'),
  rsc('elf', '^\177ELF')
]

def what(buffer):
    r=[]
    for f in type_table:
      if f.check(buffer):
        r.append(f.ext)
    return r

def file(filename):
    return what(avlib.safe.open(filename,'rb').read(99999))
