1 """Macintosh binhex compression/decompression.
4 binhex(inputfilename, outputfilename)
5 hexbin(inputfilename, outputfilename)
29 __all__ = [
"binhex",
"hexbin",
"Error"]
35 [_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
38 REASONABLY_LARGE=32768
52 except AttributeError:
60 finfo = macfs.FSSpec(name).GetFInfo()
61 dir, file = os.path.split(name)
69 return file, finfo, dlen, rlen
93 data =
open(name).read(256)
95 if not c.isspace()
and (c<
' ' or ord(c) > 0x7f):
102 dir, file = os.path.split(name)
103 file = file.replace(
':',
'-', 1)
104 return file, finfo, dsize, 0
119 class _Hqxcoderengine:
120 """Write data to the coder in 3-byte chunks"""
130 datalen = len(self.
data)
131 todo = (datalen//3)*3
132 data = self.
data[:todo]
139 def _flush(self, force):
143 self.ofp.write(self.
hqxdata[first:last]+
'\n')
148 self.ofp.write(self.
hqxdata +
':\n')
159 """Write data to the RLE-coder in suitably large chunks"""
167 if len(self.
data) < REASONABLY_LARGE:
169 rledata = binascii.rlecode_hqx(self.
data)
170 self.ofp.write(rledata)
175 rledata = binascii.rlecode_hqx(self.
data)
176 self.ofp.write(rledata)
181 def __init__(self, (name, finfo, dlen, rlen), ofp):
182 if type(ofp) == type(
''):
184 ofp =
open(ofname,
'w')
186 fss = macfs.FSSpec(ofname)
187 fss.SetCreatorType(
'BnHq',
'TEXT')
188 ofp.write(
'(This file must be converted with BinHex 4.0)\n\n:')
199 def _writeinfo(self, name, finfo):
203 raise Error,
'Filename too long'
204 d = chr(nl) + name +
'\0'
205 d2 = finfo.Type + finfo.Creator
208 d3 = struct.pack(
'>h', finfo.Flags)
209 d4 = struct.pack(
'>ii', self.
dlen, self.
rlen)
210 info = d + d2 + d3 + d4
214 def _write(self, data):
215 self.
crc = binascii.crc_hqx(data, self.
crc)
221 self.ofp.write(struct.pack(
'>h', self.
crc))
225 if self.
state != _DID_HEADER:
226 raise Error,
'Writing data at the wrong time'
232 raise Error,
'Incorrect data size, diff='+`self.
rlen`
234 self.
state = _DID_DATA
237 if self.
state < _DID_DATA:
239 if self.
state != _DID_DATA:
240 raise Error,
'Writing resource data at the wrong time'
245 if self.
state < _DID_DATA:
247 if self.
state != _DID_DATA:
248 raise Error,
'Close at the wrong time'
251 "Incorrect resource-datasize, diff="+`self.
rlen`
258 """(infilename, outfilename) - Create binhex-encoded copy of a file"""
262 ifp =
open(inp,
'rb')
280 """Read data via the decoder in 4-byte chunks"""
287 """Read at least wtd bytes (or until EOF)"""
294 if self.
eof:
return decdata
296 data = self.ifp.read(wtd)
304 decdatacur, self.
eof = \
305 binascii.a2b_hqx(data)
307 except binascii.Incomplete:
309 newdata = self.ifp.read(1)
312 'Premature EOF on binhex file'
313 data = data + newdata
314 decdata = decdata + decdatacur
315 wtd = totalwtd - len(decdata)
316 if not decdata
and not self.
eof:
317 raise Error,
'Premature EOF on binhex file'
324 """Read data via the RLE-coder"""
339 def _fill(self, wtd):
359 if self.
pre_buffer[-3:] == RUNCHAR +
'\0' + RUNCHAR:
371 binascii.rledecode_hqx(self.
pre_buffer[:mark])
379 if type(ifp) == type(
''):
387 raise Error,
"No binhex data found"
395 dummy = ifp.readline()
402 def _read(self, len):
403 data = self.ifp.read(len)
404 self.
crc = binascii.crc_hqx(data, self.
crc)
408 filecrc = struct.unpack(
'>h', self.ifp.read(2))[0] & 0xffff
411 self.
crc = self.
crc & 0xffff
412 if filecrc != self.
crc:
413 raise Error,
'CRC error, computed %x, read %x' \
417 def _readheader(self):
419 fname = self.
_read(ord(len))
420 rest = self.
_read(1+4+4+2+4+4)
425 flags = struct.unpack(
'>h', rest[9:11])[0]
426 self.
dlen = struct.unpack(
'>l', rest[11:15])[0]
427 self.
rlen = struct.unpack(
'>l', rest[15:19])[0]
431 self.FInfo.Creator = creator
432 self.FInfo.Type = type
433 self.FInfo.Flags = flags
438 if self.
state != _DID_HEADER:
439 raise Error,
'Read data at wrong time'
447 rv = rv + self.
_read(n-len(rv))
452 if self.
state != _DID_HEADER:
453 raise Error,
'close_data at wrong time'
457 self.
state = _DID_DATA
460 if self.
state == _DID_HEADER:
462 if self.
state != _DID_DATA:
463 raise Error,
'Read resource data at wrong time'
476 self.
state = _DID_RSRC
480 """(infilename, outfilename) - Decode binhexed file"""
486 ofss = macfs.FSSpec(out)
487 out = ofss.as_pathname()
489 ofp =
open(out,
'wb')
498 d = ifp.read_rsrc(128000)
503 d = ifp.read_rsrc(128000)
509 nfinfo = ofss.GetFInfo()
510 nfinfo.Creator = finfo.Creator
511 nfinfo.Type = finfo.Type
512 nfinfo.Flags = finfo.Flags
513 ofss.SetFInfo(nfinfo)
519 fss, ok = macfs.PromptGetFile(
'File to convert:')
522 fname = fss.as_pathname()
525 binhex(fname, fname+
'.hqx')
526 hexbin(fname+
'.hqx', fname+
'.viahqx')
530 if __name__ ==
'__main__':