blob: 9e20d871d3b27463a7e134dc6c99de1c36c970f6 [file] [log] [blame]
Jack Jansenfcdffea1995-08-07 14:36:51 +00001"""binhex - Macintosh binhex compression/decompression
2easy interface:
3binhex(inputfilename, outputfilename)
4hexbin(inputfilename, outputfilename)
5"""
6
7#
8# Jack Jansen, CWI, August 1995.
9#
10# The module is supposed to be as compatible as possible. Especially the
11# easy interface should work "as expected" on any platform.
12# XXXX Note: currently, textfiles appear in mac-form on all platforms.
13# We seem to lack a simple character-translate in python.
14# (we should probably use ISO-Latin-1 on all but the mac platform).
15# XXXX The simeple routines are too simple: they expect to hold the complete
16# files in-core. Should be fixed.
17# XXXX It would be nice to handle AppleDouble format on unix (for servers serving
18# macs).
19# XXXX I don't understand what happens when you get 0x90 times the same byte on
20# input. The resulting code (xx 90 90) would appear to be interpreted as an
21# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety...
22#
23import sys
24import os
25import struct
26import string
27import binascii
Jack Jansen479c1b31995-08-14 12:41:20 +000028
Jack Jansenfcdffea1995-08-07 14:36:51 +000029Error = 'binhex.Error'
30
31# States (what have we written)
32[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
33
34# Various constants
35REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder
Guido van Rossuma220e671996-03-23 19:19:04 +000036LINELEN=64
Jack Jansenfcdffea1995-08-07 14:36:51 +000037RUNCHAR=chr(0x90) # run-length introducer
38
39#
40# The code is currently byte-order dependent
41if struct.pack('i', 0177) != '\0\0\0\177':
Guido van Rossuma220e671996-03-23 19:19:04 +000042 raise ImportError, 'Module binhex is big-endian only'
Jack Jansenfcdffea1995-08-07 14:36:51 +000043
44#
45# Workarounds for non-mac machines.
46if os.name == 'mac':
Guido van Rossuma220e671996-03-23 19:19:04 +000047 import macfs
48 import MacOS
49 try:
50 openrf = MacOS.openrf
51 except AttributeError:
52 # Backward compatability
53 openrf = open
54
55 def FInfo():
Jack Jansenfcdffea1995-08-07 14:36:51 +000056 return macfs.FInfo()
Guido van Rossuma220e671996-03-23 19:19:04 +000057
58 def getfileinfo(name):
Jack Jansenfcdffea1995-08-07 14:36:51 +000059 finfo = macfs.FSSpec(name).GetFInfo()
60 dir, file = os.path.split(name)
61 # XXXX Get resource/data sizes
62 fp = open(name, 'rb')
63 fp.seek(0, 2)
64 dlen = fp.tell()
Guido van Rossuma220e671996-03-23 19:19:04 +000065 fp = openrf(name, '*rb')
Jack Jansenfcdffea1995-08-07 14:36:51 +000066 fp.seek(0, 2)
67 rlen = fp.tell()
68 return file, finfo, dlen, rlen
Guido van Rossuma220e671996-03-23 19:19:04 +000069
70 def openrsrc(name, *mode):
71 if not mode:
72 mode = '*rb'
Jack Jansenfcdffea1995-08-07 14:36:51 +000073 else:
Guido van Rossuma220e671996-03-23 19:19:04 +000074 mode = '*' + mode[0]
75 return openrf(name, mode)
Jack Jansenfcdffea1995-08-07 14:36:51 +000076
77else:
Guido van Rossuma220e671996-03-23 19:19:04 +000078 #
79 # Glue code for non-macintosh useage
80 #
81 import regsub
82
83 class FInfo:
Jack Jansenfcdffea1995-08-07 14:36:51 +000084 def __init__(self):
Guido van Rossuma220e671996-03-23 19:19:04 +000085 self.Type = '????'
86 self.Creator = '????'
87 self.Flags = 0
Jack Jansenfcdffea1995-08-07 14:36:51 +000088
Guido van Rossuma220e671996-03-23 19:19:04 +000089 def getfileinfo(name):
Jack Jansenfcdffea1995-08-07 14:36:51 +000090 finfo = FInfo()
91 # Quick check for textfile
92 fp = open(name)
93 data = open(name).read(256)
94 for c in data:
Guido van Rossuma220e671996-03-23 19:19:04 +000095 if not c in string.whitespace and (c<' ' or ord(c) > 0177):
96 break
Jack Jansenfcdffea1995-08-07 14:36:51 +000097 else:
Guido van Rossuma220e671996-03-23 19:19:04 +000098 finfo.Type = 'TEXT'
Jack Jansenfcdffea1995-08-07 14:36:51 +000099 fp.seek(0, 2)
100 dsize = fp.tell()
101 fp.close()
102 dir, file = os.path.split(name)
103 file = regsub.sub(':', '-', file)
104 return file, finfo, dsize, 0
105
Guido van Rossuma220e671996-03-23 19:19:04 +0000106 class openrsrc:
Jack Jansenfcdffea1995-08-07 14:36:51 +0000107 def __init__(self, *args):
Guido van Rossuma220e671996-03-23 19:19:04 +0000108 pass
Jack Jansenfcdffea1995-08-07 14:36:51 +0000109
110 def read(self, *args):
Guido van Rossuma220e671996-03-23 19:19:04 +0000111 return ''
Jack Jansenfcdffea1995-08-07 14:36:51 +0000112
113 def write(self, *args):
114 pass
115
116 def close(self):
Guido van Rossuma220e671996-03-23 19:19:04 +0000117 pass
Jack Jansenfcdffea1995-08-07 14:36:51 +0000118
119class _Hqxcoderengine:
Guido van Rossuma220e671996-03-23 19:19:04 +0000120 """Write data to the coder in 3-byte chunks"""
121
122 def __init__(self, ofp):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000123 self.ofp = ofp
124 self.data = ''
Guido van Rossuma220e671996-03-23 19:19:04 +0000125 self.hqxdata = ''
126 self.linelen = LINELEN-1
Jack Jansenfcdffea1995-08-07 14:36:51 +0000127
Guido van Rossuma220e671996-03-23 19:19:04 +0000128 def write(self, data):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000129 self.data = self.data + data
Guido van Rossuma220e671996-03-23 19:19:04 +0000130 datalen = len(self.data)
131 todo = (datalen/3)*3
132 data = self.data[:todo]
133 self.data = self.data[todo:]
134 self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
135 while len(self.hqxdata) > self.linelen:
136 self.ofp.write(self.hqxdata[:self.linelen]+'\n')
137 self.hqxdata = self.hqxdata[self.linelen:]
138 self.linelen = LINELEN
Jack Jansenfcdffea1995-08-07 14:36:51 +0000139
Guido van Rossuma220e671996-03-23 19:19:04 +0000140 def close(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000141 if self.data:
Guido van Rossuma220e671996-03-23 19:19:04 +0000142 self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data)
143 while self.hqxdata:
144 self.ofp.write(self.hqxdata[:self.linelen])
145 self.hqxdata = self.hqxdata[self.linelen:]
146 self.linelen = LINELEN
Jack Jansenfcdffea1995-08-07 14:36:51 +0000147 self.ofp.write(':\n')
148 self.ofp.close()
Guido van Rossuma220e671996-03-23 19:19:04 +0000149 del self.ofp
Jack Jansenfcdffea1995-08-07 14:36:51 +0000150
151class _Rlecoderengine:
Guido van Rossuma220e671996-03-23 19:19:04 +0000152 """Write data to the RLE-coder in suitably large chunks"""
Jack Jansenfcdffea1995-08-07 14:36:51 +0000153
Guido van Rossuma220e671996-03-23 19:19:04 +0000154 def __init__(self, ofp):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000155 self.ofp = ofp
156 self.data = ''
157
Guido van Rossuma220e671996-03-23 19:19:04 +0000158 def write(self, data):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000159 self.data = self.data + data
160 if len(self.data) < REASONABLY_LARGE:
Guido van Rossuma220e671996-03-23 19:19:04 +0000161 return
Jack Jansenfcdffea1995-08-07 14:36:51 +0000162 rledata = binascii.rlecode_hqx(self.data)
163 self.ofp.write(rledata)
164 self.data = ''
165
Guido van Rossuma220e671996-03-23 19:19:04 +0000166 def close(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000167 if self.data:
Guido van Rossuma220e671996-03-23 19:19:04 +0000168 rledata = binascii.rlecode_hqx(self.data)
169 self.ofp.write(rledata)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000170 self.ofp.close()
Guido van Rossuma220e671996-03-23 19:19:04 +0000171 del self.ofp
Jack Jansenfcdffea1995-08-07 14:36:51 +0000172
173class BinHex:
Guido van Rossuma220e671996-03-23 19:19:04 +0000174 def __init__(self, (name, finfo, dlen, rlen), ofp):
175 if type(ofp) == type(''):
176 ofname = ofp
177 ofp = open(ofname, 'w')
178 if os.name == 'mac':
179 fss = macfs.FSSpec(ofname)
180 fss.SetCreatorType('BnHq', 'TEXT')
181 ofp.write('(This file must be converted with BinHex 4.0)\n\n:')
Jack Jansenfcdffea1995-08-07 14:36:51 +0000182 hqxer = _Hqxcoderengine(ofp)
183 self.ofp = _Rlecoderengine(hqxer)
184 self.crc = 0
185 if finfo == None:
Guido van Rossuma220e671996-03-23 19:19:04 +0000186 finfo = FInfo()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000187 self.dlen = dlen
188 self.rlen = rlen
189 self._writeinfo(name, finfo)
190 self.state = _DID_HEADER
191
Guido van Rossuma220e671996-03-23 19:19:04 +0000192 def _writeinfo(self, name, finfo):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000193 name = name
194 nl = len(name)
195 if nl > 63:
Guido van Rossuma220e671996-03-23 19:19:04 +0000196 raise Error, 'Filename too long'
Jack Jansenfcdffea1995-08-07 14:36:51 +0000197 d = chr(nl) + name + '\0'
198 d2 = finfo.Type + finfo.Creator
199 d3 = struct.pack('h', finfo.Flags)
200 d4 = struct.pack('ii', self.dlen, self.rlen)
201 info = d + d2 + d3 + d4
202 self._write(info)
203 self._writecrc()
204
Guido van Rossuma220e671996-03-23 19:19:04 +0000205 def _write(self, data):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000206 self.crc = binascii.crc_hqx(data, self.crc)
207 self.ofp.write(data)
208
Guido van Rossuma220e671996-03-23 19:19:04 +0000209 def _writecrc(self):
210## self.crc = binascii.crc_hqx('\0\0', self.crc) # XXXX Should this be here??
Jack Jansenfcdffea1995-08-07 14:36:51 +0000211 self.ofp.write(struct.pack('h', self.crc))
212 self.crc = 0
213
Guido van Rossuma220e671996-03-23 19:19:04 +0000214 def write(self, data):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000215 if self.state != _DID_HEADER:
Guido van Rossuma220e671996-03-23 19:19:04 +0000216 raise Error, 'Writing data at the wrong time'
Jack Jansenfcdffea1995-08-07 14:36:51 +0000217 self.dlen = self.dlen - len(data)
218 self._write(data)
219
Guido van Rossuma220e671996-03-23 19:19:04 +0000220 def close_data(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000221 if self.dlen <> 0:
Guido van Rossuma220e671996-03-23 19:19:04 +0000222 raise Error, 'Incorrect data size, diff='+`self.rlen`
Jack Jansenfcdffea1995-08-07 14:36:51 +0000223 self._writecrc()
224 self.state = _DID_DATA
225
Guido van Rossuma220e671996-03-23 19:19:04 +0000226 def write_rsrc(self, data):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000227 if self.state < _DID_DATA:
Guido van Rossuma220e671996-03-23 19:19:04 +0000228 self.close_data()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000229 if self.state != _DID_DATA:
Guido van Rossuma220e671996-03-23 19:19:04 +0000230 raise Error, 'Writing resource data at the wrong time'
Jack Jansenfcdffea1995-08-07 14:36:51 +0000231 self.rlen = self.rlen - len(data)
232 self._write(data)
233
Guido van Rossuma220e671996-03-23 19:19:04 +0000234 def close(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000235 if self.state < _DID_DATA:
Guido van Rossuma220e671996-03-23 19:19:04 +0000236 self.close_data()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000237 if self.state != _DID_DATA:
Guido van Rossuma220e671996-03-23 19:19:04 +0000238 raise Error, 'Close at the wrong time'
Jack Jansenfcdffea1995-08-07 14:36:51 +0000239 if self.rlen <> 0:
Guido van Rossuma220e671996-03-23 19:19:04 +0000240 raise Error, "Incorrect resource-datasize, diff="+`self.rlen`
Jack Jansenfcdffea1995-08-07 14:36:51 +0000241 self._writecrc()
242 self.ofp.close()
243 self.state = None
Guido van Rossuma220e671996-03-23 19:19:04 +0000244 del self.ofp
Jack Jansenfcdffea1995-08-07 14:36:51 +0000245
246def binhex(inp, out):
247 """(infilename, outfilename) - Create binhex-encoded copy of a file"""
248 finfo = getfileinfo(inp)
249 ofp = BinHex(finfo, out)
250
251 ifp = open(inp, 'rb')
252 # XXXX Do textfile translation on non-mac systems
Guido van Rossuma220e671996-03-23 19:19:04 +0000253 while 1:
254 d = ifp.read(128000)
255 if not d: break
256 ofp.write(d)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000257 ofp.close_data()
258 ifp.close()
259
260 ifp = openrsrc(inp, 'rb')
Guido van Rossuma220e671996-03-23 19:19:04 +0000261 while 1:
262 d = ifp.read(128000)
263 if not d: break
264 ofp.write_rsrc(d)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000265 ofp.close()
Guido van Rossuma220e671996-03-23 19:19:04 +0000266 ifp.close()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000267
268class _Hqxdecoderengine:
Guido van Rossuma220e671996-03-23 19:19:04 +0000269 """Read data via the decoder in 4-byte chunks"""
270
271 def __init__(self, ifp):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000272 self.ifp = ifp
273 self.eof = 0
274
Guido van Rossuma220e671996-03-23 19:19:04 +0000275 def read(self, totalwtd):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000276 """Read at least wtd bytes (or until EOF)"""
277 decdata = ''
Jack Jansen685e16d1995-10-03 14:41:15 +0000278 wtd = totalwtd
Jack Jansenfcdffea1995-08-07 14:36:51 +0000279 #
280 # The loop here is convoluted, since we don't really now how much
281 # to decode: there may be newlines in the incoming data.
282 while wtd > 0:
283 if self.eof: return decdata
284 wtd = ((wtd+2)/3)*4
285 data = self.ifp.read(wtd)
286 #
287 # Next problem: there may not be a complete number of bytes in what we
288 # pass to a2b. Solve by yet another loop.
289 #
290 while 1:
291 try:
292 decdatacur, self.eof = binascii.a2b_hqx(data)
293 if self.eof: print 'EOF'
294 break
295 except binascii.Incomplete:
296 pass
297 newdata = self.ifp.read(1)
298 if not newdata:
299 raise Error, 'Premature EOF on binhex file'
300 data = data + newdata
301 decdata = decdata + decdatacur
Jack Jansen685e16d1995-10-03 14:41:15 +0000302 wtd = totalwtd - len(decdata)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000303 if not decdata and not self.eof:
304 raise Error, 'Premature EOF on binhex file'
305 return decdata
306
Guido van Rossuma220e671996-03-23 19:19:04 +0000307 def close(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000308 self.ifp.close()
309
310class _Rledecoderengine:
Guido van Rossuma220e671996-03-23 19:19:04 +0000311 """Read data via the RLE-coder"""
Jack Jansenfcdffea1995-08-07 14:36:51 +0000312
Guido van Rossuma220e671996-03-23 19:19:04 +0000313 def __init__(self, ifp):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000314 self.ifp = ifp
315 self.pre_buffer = ''
316 self.post_buffer = ''
317 self.eof = 0
318
Guido van Rossuma220e671996-03-23 19:19:04 +0000319 def read(self, wtd):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000320 if wtd > len(self.post_buffer):
Guido van Rossuma220e671996-03-23 19:19:04 +0000321 self._fill(wtd-len(self.post_buffer))
Jack Jansenfcdffea1995-08-07 14:36:51 +0000322 rv = self.post_buffer[:wtd]
323 self.post_buffer = self.post_buffer[wtd:]
Jack Jansenfcdffea1995-08-07 14:36:51 +0000324 return rv
325
Guido van Rossuma220e671996-03-23 19:19:04 +0000326 def _fill(self, wtd):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000327 #
328 # Obfuscated code ahead. We keep at least one byte in the pre_buffer,
329 # so we don't stumble over an orphaned RUNCHAR later on. If the
330 # last or second-last char is a RUNCHAR we keep more bytes.
331 #
332 self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+2)
333 if self.ifp.eof:
334 self.post_buffer = self.post_buffer + \
335 binascii.rledecode_hqx(self.pre_buffer)
336 self.pre_buffer = ''
337 return
338
339 lastrle = string.rfind(self.pre_buffer, RUNCHAR)
340 if lastrle > 0 and lastrle == len(self.pre_buffer)-1:
341 # Last byte is an RLE, keep two bytes
342 mark = len(self.pre_buffer)-2
343 elif lastrle > 0 and lastrle == len(self.pre_buffer)-2:
344 # second-last byte is an RLE. Decode all.
345 mark = len(self.pre_buffer)
346 else:
347 mark = len(self.pre_buffer)-1
348 self.post_buffer = self.post_buffer + \
349 binascii.rledecode_hqx(self.pre_buffer[:mark])
350 self.pre_buffer = self.pre_buffer[mark:]
351
Guido van Rossuma220e671996-03-23 19:19:04 +0000352 def close(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000353 self.ifp.close()
354
355class HexBin:
Guido van Rossuma220e671996-03-23 19:19:04 +0000356 def __init__(self, ifp):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000357 if type(ifp) == type(''):
Guido van Rossuma220e671996-03-23 19:19:04 +0000358 ifp = open(ifp)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000359 #
360 # Find initial colon.
361 #
362 while 1:
363 ch = ifp.read(1)
364 if not ch:
365 raise Error, "No binhex data found"
366 if ch == ':':
367 break
368 if ch != '\n':
369 dummy = ifp.readline()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000370
371 hqxifp = _Hqxdecoderengine(ifp)
372 self.ifp = _Rledecoderengine(hqxifp)
373 self.crc = 0
374 self._readheader()
375
Guido van Rossuma220e671996-03-23 19:19:04 +0000376 def _read(self, len):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000377 data = self.ifp.read(len)
378 self.crc = binascii.crc_hqx(data, self.crc)
379 return data
380
Guido van Rossuma220e671996-03-23 19:19:04 +0000381 def _checkcrc(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000382 filecrc = struct.unpack('h', self.ifp.read(2))[0] & 0xffff
Jack Jansen685e16d1995-10-03 14:41:15 +0000383## self.crc = binascii.crc_hqx('\0\0', self.crc) # XXXX Is this needed??
Jack Jansenfcdffea1995-08-07 14:36:51 +0000384 self.crc = self.crc & 0xffff
Jack Jansen685e16d1995-10-03 14:41:15 +0000385 if filecrc != self.crc:
386 raise Error, 'CRC error, computed %x, read %x'%(self.crc, filecrc)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000387 self.crc = 0
388
Guido van Rossuma220e671996-03-23 19:19:04 +0000389 def _readheader(self):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000390 len = self._read(1)
391 fname = self._read(ord(len))
392 rest = self._read(1+4+4+2+4+4)
393 self._checkcrc()
394
395 type = rest[1:5]
396 creator = rest[5:9]
397 flags = struct.unpack('h', rest[9:11])[0]
398 self.dlen = struct.unpack('l', rest[11:15])[0]
399 self.rlen = struct.unpack('l', rest[15:19])[0]
400
Jack Jansenfcdffea1995-08-07 14:36:51 +0000401 self.FName = fname
402 self.FInfo = FInfo()
403 self.FInfo.Creator = creator
404 self.FInfo.Type = type
405 self.FInfo.Flags = flags
406
407 self.state = _DID_HEADER
408
Guido van Rossuma220e671996-03-23 19:19:04 +0000409 def read(self, *n):
Jack Jansenfcdffea1995-08-07 14:36:51 +0000410 if self.state != _DID_HEADER:
411 raise Error, 'Read data at wrong time'
412 if n:
413 n = n[0]
414 n = min(n, self.dlen)
415 else:
416 n = self.dlen
417 self.dlen = self.dlen - n
418 return self._read(n)
419
Guido van Rossuma220e671996-03-23 19:19:04 +0000420 def close_data(self):
421 if self.state != _DID_HEADER:
422 raise Error, 'close_data at wrong time'
423 if self.dlen:
Jack Jansenfcdffea1995-08-07 14:36:51 +0000424 dummy = self._read(self.dlen)
Guido van Rossuma220e671996-03-23 19:19:04 +0000425 self._checkcrc()
426 self.state = _DID_DATA
Jack Jansenfcdffea1995-08-07 14:36:51 +0000427
Guido van Rossuma220e671996-03-23 19:19:04 +0000428 def read_rsrc(self, *n):
429 if self.state == _DID_HEADER:
430 self.close_data()
431 if self.state != _DID_DATA:
432 raise Error, 'Read resource data at wrong time'
433 if n:
434 n = n[0]
435 n = min(n, self.rlen)
436 else:
437 n = self.rlen
438 self.rlen = self.rlen - n
439 return self._read(n)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000440
Guido van Rossuma220e671996-03-23 19:19:04 +0000441 def close(self):
442 if self.rlen:
443 dummy = self.read_rsrc(self.rlen)
444 self._checkcrc()
445 self.state = _DID_RSRC
446 self.ifp.close()
Jack Jansenfcdffea1995-08-07 14:36:51 +0000447
448def hexbin(inp, out):
449 """(infilename, outfilename) - Decode binhexed file"""
450 ifp = HexBin(inp)
451 finfo = ifp.FInfo
452 if not out:
453 out = ifp.FName
454 if os.name == 'mac':
455 ofss = macfs.FSSpec(out)
456 out = ofss.as_pathname()
457
458 ofp = open(out, 'wb')
459 # XXXX Do translation on non-mac systems
Guido van Rossuma220e671996-03-23 19:19:04 +0000460 while 1:
461 d = ifp.read(128000)
462 if not d: break
463 ofp.write(d)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000464 ofp.close()
465 ifp.close_data()
466
Guido van Rossuma220e671996-03-23 19:19:04 +0000467 d = ifp.read_rsrc(128000)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000468 if d:
469 ofp = openrsrc(out, 'wb')
470 ofp.write(d)
Guido van Rossuma220e671996-03-23 19:19:04 +0000471 while 1:
472 d = ifp.read_rsrc(128000)
473 if not d: break
474 ofp.write(d)
Jack Jansenfcdffea1995-08-07 14:36:51 +0000475 ofp.close()
476
477 if os.name == 'mac':
478 nfinfo = ofss.GetFInfo()
479 nfinfo.Creator = finfo.Creator
480 nfinfo.Type = finfo.Type
481 nfinfo.Flags = finfo.Flags
482 ofss.SetFInfo(nfinfo)
483
484 ifp.close()
485
486def _test():
487 if os.name == 'mac':
Jack Jansen479c1b31995-08-14 12:41:20 +0000488 fss, ok = macfs.PromptGetFile('File to convert:')
Jack Jansenfcdffea1995-08-07 14:36:51 +0000489 if not ok:
490 sys.exit(0)
491 fname = fss.as_pathname()
492 else:
493 fname = sys.argv[1]
494 #binhex(fname, fname+'.hqx')
495 #hexbin(fname+'.hqx', fname+'.viahqx')
496 hexbin(fname, fname+'.unpacked')
497 sys.exit(1)
498
499if __name__ == '__main__':
500 _test()