'''
filetype module, version 0.4.0

(c) 2003-2016,2019 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
from avlib import safe

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