symbian-qemu-0.9.1-12/python-2.6.1/Lib/plat-mac/applesingle.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 r"""Routines to decode AppleSingle files
       
     2 """
       
     3 
       
     4 from warnings import warnpy3k
       
     5 warnpy3k("In 3.x, the applesingle module is removed.", stacklevel=2)
       
     6 
       
     7 import struct
       
     8 import sys
       
     9 try:
       
    10     import MacOS
       
    11     import Carbon.File
       
    12 except:
       
    13     class MacOS:
       
    14         def openrf(path, mode):
       
    15             return open(path + '.rsrc', mode)
       
    16         openrf = classmethod(openrf)
       
    17     class Carbon:
       
    18         class File:
       
    19             class FSSpec:
       
    20                 pass
       
    21             class FSRef:
       
    22                 pass
       
    23             class Alias:
       
    24                 pass
       
    25 
       
    26 # all of the errors in this module are really errors in the input
       
    27 # so I think it should test positive against ValueError.
       
    28 class Error(ValueError):
       
    29     pass
       
    30 
       
    31 # File header format: magic, version, unused, number of entries
       
    32 AS_HEADER_FORMAT=">LL16sh"
       
    33 AS_HEADER_LENGTH=26
       
    34 # The flag words for AppleSingle
       
    35 AS_MAGIC=0x00051600
       
    36 AS_VERSION=0x00020000
       
    37 
       
    38 # Entry header format: id, offset, length
       
    39 AS_ENTRY_FORMAT=">lll"
       
    40 AS_ENTRY_LENGTH=12
       
    41 
       
    42 # The id values
       
    43 AS_DATAFORK=1
       
    44 AS_RESOURCEFORK=2
       
    45 AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)
       
    46 
       
    47 class AppleSingle(object):
       
    48     datafork = None
       
    49     resourcefork = None
       
    50 
       
    51     def __init__(self, fileobj, verbose=False):
       
    52         header = fileobj.read(AS_HEADER_LENGTH)
       
    53         try:
       
    54             magic, version, ig, nentry = struct.unpack(AS_HEADER_FORMAT, header)
       
    55         except ValueError, arg:
       
    56             raise Error, "Unpack header error: %s" % (arg,)
       
    57         if verbose:
       
    58             print 'Magic:   0x%8.8x' % (magic,)
       
    59             print 'Version: 0x%8.8x' % (version,)
       
    60             print 'Entries: %d' % (nentry,)
       
    61         if magic != AS_MAGIC:
       
    62             raise Error, "Unknown AppleSingle magic number 0x%8.8x" % (magic,)
       
    63         if version != AS_VERSION:
       
    64             raise Error, "Unknown AppleSingle version number 0x%8.8x" % (version,)
       
    65         if nentry <= 0:
       
    66             raise Error, "AppleSingle file contains no forks"
       
    67         headers = [fileobj.read(AS_ENTRY_LENGTH) for i in xrange(nentry)]
       
    68         self.forks = []
       
    69         for hdr in headers:
       
    70             try:
       
    71                 restype, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
       
    72             except ValueError, arg:
       
    73                 raise Error, "Unpack entry error: %s" % (arg,)
       
    74             if verbose:
       
    75                 print "Fork %d, offset %d, length %d" % (restype, offset, length)
       
    76             fileobj.seek(offset)
       
    77             data = fileobj.read(length)
       
    78             if len(data) != length:
       
    79                 raise Error, "Short read: expected %d bytes got %d" % (length, len(data))
       
    80             self.forks.append((restype, data))
       
    81             if restype == AS_DATAFORK:
       
    82                 self.datafork = data
       
    83             elif restype == AS_RESOURCEFORK:
       
    84                 self.resourcefork = data
       
    85 
       
    86     def tofile(self, path, resonly=False):
       
    87         outfile = open(path, 'wb')
       
    88         data = False
       
    89         if resonly:
       
    90             if self.resourcefork is None:
       
    91                 raise Error, "No resource fork found"
       
    92             fp = open(path, 'wb')
       
    93             fp.write(self.resourcefork)
       
    94             fp.close()
       
    95         elif (self.resourcefork is None and self.datafork is None):
       
    96             raise Error, "No useful forks found"
       
    97         else:
       
    98             if self.datafork is not None:
       
    99                 fp = open(path, 'wb')
       
   100                 fp.write(self.datafork)
       
   101                 fp.close()
       
   102             if self.resourcefork is not None:
       
   103                 fp = MacOS.openrf(path, '*wb')
       
   104                 fp.write(self.resourcefork)
       
   105                 fp.close()
       
   106 
       
   107 def decode(infile, outpath, resonly=False, verbose=False):
       
   108     """decode(infile, outpath [, resonly=False, verbose=False])
       
   109 
       
   110     Creates a decoded file from an AppleSingle encoded file.
       
   111     If resonly is True, then it will create a regular file at
       
   112     outpath containing only the resource fork from infile.
       
   113     Otherwise it will create an AppleDouble file at outpath
       
   114     with the data and resource forks from infile.  On platforms
       
   115     without the MacOS module, it will create inpath and inpath+'.rsrc'
       
   116     with the data and resource forks respectively.
       
   117 
       
   118     """
       
   119     if not hasattr(infile, 'read'):
       
   120         if isinstance(infile, Carbon.File.Alias):
       
   121             infile = infile.ResolveAlias()[0]
       
   122         if isinstance(infile, (Carbon.File.FSSpec, Carbon.File.FSRef)):
       
   123             infile = infile.as_pathname()
       
   124         infile = open(infile, 'rb')
       
   125 
       
   126     asfile = AppleSingle(infile, verbose=verbose)
       
   127     asfile.tofile(outpath, resonly=resonly)
       
   128 
       
   129 def _test():
       
   130     if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
       
   131         print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
       
   132         sys.exit(1)
       
   133     if sys.argv[1] == '-r':
       
   134         resonly = True
       
   135         del sys.argv[1]
       
   136     else:
       
   137         resonly = False
       
   138     decode(sys.argv[1], sys.argv[2], resonly=resonly)
       
   139 
       
   140 if __name__ == '__main__':
       
   141     _test()