Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a48d4ea

Browse files
committed
Minimal module to decode AppleSingle files (the way resource files are
stored in the CVS repository). It can either decode resource/data forks in the standard Mac way or decode only the resource fork but store the result in the data fork (the MacOSX preferred way). Finder info and all other stuff is ignored.
1 parent f7adf2f commit a48d4ea

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

Mac/Lib/applesingle.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# applesingle - a module to decode AppleSingle files
2+
import struct
3+
import MacOS
4+
import sys
5+
6+
Error="applesingle.Error"
7+
8+
verbose=0
9+
10+
# File header format: magic, version, unused, number of entries
11+
AS_HEADER_FORMAT="ll16sh"
12+
AS_HEADER_LENGTH=26
13+
# The flag words for AppleSingle
14+
AS_MAGIC=0x00051600
15+
AS_VERSION=0x00020000
16+
17+
# Entry header format: id, offset, length
18+
AS_ENTRY_FORMAT="lll"
19+
AS_ENTRY_LENGTH=12
20+
21+
# The id values
22+
AS_DATAFORK=1
23+
AS_RESOURCEFORK=2
24+
AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)
25+
26+
def decode(input, output, resonly=0):
27+
if type(input) == type(''):
28+
input = open(input, 'rb')
29+
# Should we also test for FSSpecs or FSRefs?
30+
header = input.read(AS_HEADER_LENGTH)
31+
print `header`
32+
try:
33+
magic, version, dummy, nentry = struct.unpack(AS_HEADER_FORMAT, header)
34+
except ValueError, arg:
35+
raise Error, "Unpack header error: %s"%arg
36+
if verbose:
37+
print 'Magic: 0x%8.8x'%magic
38+
print 'Version: 0x%8.8x'%version
39+
print 'Entries: %d'%nentry
40+
if magic != AS_MAGIC:
41+
raise Error, 'Unknown AppleSingle magic number 0x%8.8x'%magic
42+
if version != AS_VERSION:
43+
raise Error, 'Unknown AppleSingle version number 0x%8.8x'%version
44+
if nentry <= 0:
45+
raise Error, "AppleSingle file contains no forks"
46+
headers = [input.read(AS_ENTRY_LENGTH) for i in range(nentry)]
47+
didwork = 0
48+
for hdr in headers:
49+
try:
50+
id, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
51+
except ValueError, arg:
52+
raise Error, "Unpack entry error: %s"%arg
53+
if verbose:
54+
print 'Fork %d, offset %d, length %d'%(id, offset, length)
55+
input.seek(offset)
56+
if length == 0:
57+
data = ''
58+
else:
59+
data = input.read(length)
60+
if len(data) != length:
61+
raise Error, 'Short read: expected %d bytes got %d'%(length, len(data))
62+
if id == AS_DATAFORK:
63+
if verbose:
64+
print ' (data fork)'
65+
if not resonly:
66+
didwork = 1
67+
fp = open(output, 'wb')
68+
fp.write(data)
69+
fp.close()
70+
elif id == AS_RESOURCEFORK:
71+
didwork = 1
72+
if verbose:
73+
print ' (resource fork)'
74+
if resonly:
75+
fp = open(output, 'wb')
76+
else:
77+
fp = MacOS.openrf(output, 'wb')
78+
fp.write(data)
79+
fp.close()
80+
elif id in AS_IGNORE:
81+
if verbose:
82+
print ' (ignored)'
83+
else:
84+
raise Error, 'Unknown fork type %d'%id
85+
if not didwork:
86+
raise Error, 'No useful forks found'
87+
88+
def _test():
89+
if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
90+
print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
91+
sys.exit(1)
92+
if sys.argv[1] == '-r':
93+
resonly = 1
94+
del sys.argv[1]
95+
else:
96+
resonly = 0
97+
decode(sys.argv[1], sys.argv[2], resonly=resonly)
98+
99+
if __name__ == '__main__':
100+
_test()
101+

0 commit comments

Comments
 (0)