home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pypil112.zip / PIL-1.1.2.zip / Lib / site-packages / PIL / OleFileIO.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2001-12-25  |  16KB  |  407 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.2)
  3.  
  4. import string
  5. import StringIO
  6.  
  7. def i16(c, o = 0):
  8.     return ord(c[o]) + (ord(c[o + 1]) << 8)
  9.  
  10.  
  11. def i32(c, o = 0):
  12.     return ord(c[o]) + (ord(c[o + 1]) << 8) + (ord(c[o + 2]) << 16) + (ord(c[o + 3]) << 24)
  13.  
  14. MAGIC = '\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1'
  15. VT_EMPTY = 0
  16. VT_NULL = 1
  17. VT_I2 = 2
  18. VT_I4 = 3
  19. VT_R4 = 4
  20. VT_R8 = 5
  21. VT_CY = 6
  22. VT_DATE = 7
  23. VT_BSTR = 8
  24. VT_DISPATCH = 9
  25. VT_ERROR = 10
  26. VT_BOOL = 11
  27. VT_VARIANT = 12
  28. VT_UNKNOWN = 13
  29. VT_DECIMAL = 14
  30. VT_I1 = 16
  31. VT_UI1 = 17
  32. VT_UI2 = 18
  33. VT_UI4 = 19
  34. VT_I8 = 20
  35. VT_UI8 = 21
  36. VT_INT = 22
  37. VT_UINT = 23
  38. VT_VOID = 24
  39. VT_HRESULT = 25
  40. VT_PTR = 26
  41. VT_SAFEARRAY = 27
  42. VT_CARRAY = 28
  43. VT_USERDEFINED = 29
  44. VT_LPSTR = 30
  45. VT_LPWSTR = 31
  46. VT_FILETIME = 64
  47. VT_BLOB = 65
  48. VT_STREAM = 66
  49. VT_STORAGE = 67
  50. VT_STREAMED_OBJECT = 68
  51. VT_STORED_OBJECT = 69
  52. VT_BLOB_OBJECT = 70
  53. VT_CF = 71
  54. VT_CLSID = 72
  55. VT_VECTOR = 4096
  56. VT = { }
  57. for k, v in vars().items():
  58.     if k[:3] == 'VT_':
  59.         VT[v] = k
  60.     
  61.  
  62. WORD_CLSID = '00020900-0000-0000-C000-000000000046'
  63.  
  64. class _OleStream(StringIO.StringIO):
  65.     '''OLE2 Stream
  66.  
  67.     Returns a read-only file object which can be used to read
  68.     the contents of a OLE stream.  To open a stream, use the
  69.     openstream method in the OleFile class.
  70.  
  71.     This function can be used with either ordinary streams,
  72.     or ministreams, depending on the offset, sectorsize, and
  73.     fat table arguments.
  74.     '''
  75.     
  76.     def __init__(self, fp, sect, size, offset, sectorsize, fat):
  77.         data = []
  78.         while sect != -2:
  79.             fp.seek(offset + sectorsize * sect)
  80.             data.append(fp.read(sectorsize))
  81.             sect = fat[sect]
  82.         data = string.join(data, '')
  83.         StringIO.StringIO.__init__(self, data[:size])
  84.  
  85.  
  86.  
  87. class _OleDirectoryEntry:
  88.     '''OLE2 Directory Entry
  89.  
  90.     Encapsulates a stream directory entry.  Note that the
  91.     constructor builds a tree of all subentries, so we only
  92.     have to call it with the root object.
  93.     '''
  94.     
  95.     def __init__(self, sidlist, sid):
  96.         (name, type, sect, size, sids, clsid) = sidlist[sid]
  97.         self.sid = sid
  98.         self.name = name
  99.         self.type = type
  100.         self.sect = sect
  101.         self.size = size
  102.         self.clsid = clsid
  103.         self.kids = []
  104.         sid = sidlist[sid][4][2]
  105.         if sid != -1:
  106.             stack = [
  107.                 self.sid]
  108.             (left, right, child) = sidlist[sid][4]
  109.             while left != -1:
  110.                 stack.append(sid)
  111.                 sid = left
  112.                 (left, right, child) = sidlist[sid][4]
  113.             while sid != self.sid:
  114.                 self.kids.append(_OleDirectoryEntry(sidlist, sid))
  115.                 (left, right, child) = sidlist[sid][4]
  116.                 if right != -1:
  117.                     sid = right
  118.                     while 1:
  119.                         (left, right, child) = sidlist[sid][4]
  120.                         if left == -1:
  121.                             break
  122.                         
  123.                         stack.append(sid)
  124.                         sid = left
  125.                 else:
  126.                     while 1:
  127.                         ptr = stack[-1]
  128.                         del stack[-1]
  129.                         (left, right, child) = sidlist[ptr][4]
  130.                         if right != sid:
  131.                             break
  132.                         
  133.                         sid = right
  134.                     (left, right, child) = sidlist[sid][4]
  135.                     if right != ptr:
  136.                         sid = ptr
  137.                     
  138.             self.kids.sort()
  139.         
  140.  
  141.     
  142.     def __cmp__(self, other):
  143.         '''Compare entries by name'''
  144.         return cmp(self.name, other.name)
  145.  
  146.     
  147.     def dump(self, tab = 0):
  148.         '''Dump this entry, and all its subentries (for debug purposes only)'''
  149.         TYPES = [
  150.             '(invalid)',
  151.             '(storage)',
  152.             '(stream)',
  153.             '(lockbytes)',
  154.             '(property)',
  155.             '(root)']
  156.         print ' ' * tab + repr(self.name), TYPES[self.type],
  157.         if self.type in (2, 5):
  158.             print self.size, 'bytes',
  159.         
  160.         print 
  161.         if self.type in (1, 5) and self.clsid:
  162.             print ' ' * tab + '{%s}' % self.clsid
  163.         
  164.         for kid in self.kids:
  165.             kid.dump(tab + 2)
  166.         
  167.  
  168.  
  169.  
  170. class OleFileIO:
  171.     '''OLE container object
  172.  
  173.     This class encapsulates the interface to an OLE 2 structured
  174.     storage file.  Use the listdir and openstream methods to access
  175.     the contents of this file.
  176.  
  177.     Object names are given as a list of strings, one for each subentry
  178.     level.  The root entry should be omitted.  For example, the following
  179.     code extracts all image streams from a Microsoft Image Composer file:
  180.  
  181.         ole = OleFileIO("fan.mic")
  182.  
  183.         for entry in ole.listdir():
  184.             if entry[1:2] == "Image":
  185.                 fin = ole.openstream(entry)
  186.                 fout = open(entry[0:1], "wb")
  187.                 while 1:
  188.                     s = fin.read(8192)
  189.                     if not s:
  190.                         break
  191.                     fout.write(s)
  192.  
  193.     You can use the viewer application provided with the Python Imaging
  194.     Library to view the resulting files (which happens to be standard
  195.     TIFF files).
  196.     '''
  197.     
  198.     def __init__(self, filename = None):
  199.         if filename:
  200.             self.open(filename)
  201.         
  202.  
  203.     
  204.     def open(self, filename):
  205.         '''Connect to a OLE2 file'''
  206.         if type(filename) == type(''):
  207.             self.fp = open(filename, 'rb')
  208.         else:
  209.             self.fp = filename
  210.         header = self.fp.read(512)
  211.         if len(header) != 512 or header[:8] != MAGIC:
  212.             raise IOError, 'not an OLE2 structured storage file'
  213.         
  214.         clsid = self._clsid(header[8:24])
  215.         self.sectorsize = 1 << i16(header, 30)
  216.         self.minisectorsize = 1 << i16(header, 32)
  217.         self.minisectorcutoff = i32(header, 56)
  218.         self.loadfat(header)
  219.         self.loaddirectory(i32(header, 48))
  220.         self.ministream = None
  221.         self.minifatsect = i32(header, 60)
  222.  
  223.     
  224.     def loadfat(self, header):
  225.         sect = header[76:512]
  226.         fat = []
  227.         for i in range(0, len(sect), 4):
  228.             ix = i32(sect, i)
  229.             if ix in [
  230.                 -2,
  231.                 -1]:
  232.                 break
  233.             
  234.             s = self.getsect(ix)
  235.             fat = fat + map((lambda i, s = s: i32(s, i)), range(0, len(s), 4))
  236.         
  237.         self.fat = fat
  238.  
  239.     
  240.     def loadminifat(self):
  241.         s = self._open(self.minifatsect).read()
  242.         self.minifat = map((lambda i, s = s: i32(s, i)), range(0, len(s), 4))
  243.  
  244.     
  245.     def getsect(self, sect):
  246.         self.fp.seek(512 + self.sectorsize * sect)
  247.         return self.fp.read(self.sectorsize)
  248.  
  249.     
  250.     def _unicode(self, s):
  251.         return filter(ord, s)
  252.  
  253.     
  254.     def loaddirectory(self, sect):
  255.         fp = self._open(sect)
  256.         self.sidlist = []
  257.         while 1:
  258.             entry = fp.read(128)
  259.             if not entry:
  260.                 break
  261.             
  262.             type = ord(entry[66])
  263.             name = self._unicode(entry[0:0 + i16(entry, 64)])
  264.             ptrs = (i32(entry, 68), i32(entry, 72), i32(entry, 76))
  265.             (sect, size) = (i32(entry, 116), i32(entry, 120))
  266.             clsid = self._clsid(entry[80:96])
  267.             self.sidlist.append((name, type, sect, size, ptrs, clsid))
  268.         self.root = _OleDirectoryEntry(self.sidlist, 0)
  269.  
  270.     
  271.     def dumpdirectory(self):
  272.         self.root.dump()
  273.  
  274.     
  275.     def _clsid(self, clsid):
  276.         if clsid == '\x00' * len(clsid):
  277.             return ''
  278.         
  279.         return ('%08X-%04X-%04X-%02X%02X-' + '%02X' * 6) % ((i32(clsid, 0), i16(clsid, 4), i16(clsid, 6)) + tuple(map(ord, clsid[8:16])))
  280.  
  281.     
  282.     def _list(self, files, prefix, node):
  283.         prefix = prefix + [
  284.             node.name]
  285.         for entry in node.kids:
  286.             if entry.kids:
  287.                 self._list(files, prefix, entry)
  288.             else:
  289.                 files.append(prefix[1:] + [
  290.                     entry.name])
  291.         
  292.  
  293.     
  294.     def _find(self, filename):
  295.         node = self.root
  296.         for name in filename:
  297.             for kid in node.kids:
  298.                 if kid.name == name:
  299.                     break
  300.                 
  301.             else:
  302.                 raise IOError, 'file not found'
  303.             node = kid
  304.         
  305.         return node.sid
  306.  
  307.     
  308.     def _open(self, start, size = 2147483647):
  309.         if size < self.minisectorcutoff:
  310.             if not (self.ministream):
  311.                 self.loadminifat()
  312.                 self.ministream = self._open(self.sidlist[0][2])
  313.             
  314.             return _OleStream(self.ministream, start, size, 0, self.minisectorsize, self.minifat)
  315.         
  316.         return _OleStream(self.fp, start, size, 512, self.sectorsize, self.fat)
  317.  
  318.     
  319.     def listdir(self):
  320.         '''Return a list of streams stored in this file'''
  321.         files = []
  322.         self._list(files, [], self.root)
  323.         return files
  324.  
  325.     
  326.     def openstream(self, filename):
  327.         '''Open a stream as a read-only file object'''
  328.         slot = self._find(filename)
  329.         (name, type, sect, size, sids, clsid) = self.sidlist[slot]
  330.         if type != 2:
  331.             raise IOError, 'this file is not a stream'
  332.         
  333.         return self._open(sect, size)
  334.  
  335.     
  336.     def getproperties(self, filename):
  337.         '''Return properties described in substream'''
  338.         fp = self.openstream(filename)
  339.         data = { }
  340.         s = fp.read(28)
  341.         clsid = self._clsid(s[8:24])
  342.         s = fp.read(20)
  343.         fmtid = self._clsid(s[:16])
  344.         fp.seek(i32(s, 16))
  345.         s = '****' + fp.read(i32(fp.read(4)) - 4)
  346.         for i in range(i32(s, 4)):
  347.             id = i32(s, 8 + i * 8)
  348.             offset = i32(s, 12 + i * 8)
  349.             type = i32(s, offset)
  350.             if type == VT_I2:
  351.                 value = i16(s, offset + 4)
  352.                 if value >= 32768:
  353.                     value = value - 65536
  354.                 
  355.             elif type == VT_UI2:
  356.                 value = i16(s, offset + 4)
  357.             elif type in (VT_I4, VT_ERROR):
  358.                 value = i32(s, offset + 4)
  359.             elif type == VT_UI4:
  360.                 value = i32(s, offset + 4)
  361.             elif type in (VT_BSTR, VT_LPSTR):
  362.                 count = i32(s, offset + 4)
  363.                 value = s[offset + 8:offset + 8 + count - 1]
  364.             elif type == VT_BLOB:
  365.                 count = i32(s, offset + 4)
  366.                 value = s[offset + 8:offset + 8 + count]
  367.             elif type == VT_LPWSTR:
  368.                 count = i32(s, offset + 4)
  369.                 value = self._unicode(s[offset + 8:offset + 8 + count * 2])
  370.             elif type == VT_FILETIME:
  371.                 value = long(i32(s, offset + 4)) + (long(i32(s, offset + 8)) << 32)
  372.                 value = value / 0x989680L
  373.             elif type == VT_UI1:
  374.                 value = ord(s[offset + 4])
  375.             elif type == VT_CLSID:
  376.                 value = self._clsid(s[offset + 4:offset + 20])
  377.             elif type == VT_CF:
  378.                 count = i32(s, offset + 4)
  379.                 value = s[offset + 8:offset + 8 + count]
  380.             else:
  381.                 value = None
  382.             data[id] = value
  383.         
  384.         return data
  385.  
  386.  
  387. if __name__ == '__main__':
  388.     import sys
  389.     for file in sys.argv[1:]:
  390.         
  391.         try:
  392.             ole = OleFileIO(file)
  393.             print '-' * 68
  394.             print file
  395.             print '-' * 68
  396.             ole.dumpdirectory()
  397.             for file in ole.listdir():
  398.                 if file[-1][0] == '\x05':
  399.                     print file
  400.                     ole.getproperties(file)
  401.                 
  402.         except IOError:
  403.             pass
  404.  
  405.     
  406.  
  407.