As per GvR recomendations, remove the restriction that binhex only run on

big-endian machines.  This is done by directing the struct module's pack
and unpack methods to treat the data always in bin endian format.
This has been tested on irix (big endian) and solaris x86 (little endian)
but not yet on the mac.
This commit is contained in:
Roger E. Masse 1997-01-16 16:51:57 +00:00
parent 47d3500787
commit 469848a1ea
1 changed files with 43 additions and 33 deletions

View File

@ -14,8 +14,8 @@ hexbin(inputfilename, outputfilename)
# (we should probably use ISO-Latin-1 on all but the mac platform). # (we should probably use ISO-Latin-1 on all but the mac platform).
# XXXX The simeple routines are too simple: they expect to hold the complete # XXXX The simeple routines are too simple: they expect to hold the complete
# files in-core. Should be fixed. # files in-core. Should be fixed.
# XXXX It would be nice to handle AppleDouble format on unix (for servers serving # XXXX It would be nice to handle AppleDouble format on unix
# macs). # (for servers serving macs).
# XXXX I don't understand what happens when you get 0x90 times the same byte on # XXXX I don't understand what happens when you get 0x90 times the same byte on
# input. The resulting code (xx 90 90) would appear to be interpreted as an # input. The resulting code (xx 90 90) would appear to be interpreted as an
# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety... # escaped *value* of 0x90. All coders I've seen appear to ignore this nicety...
@ -37,9 +37,7 @@ LINELEN=64
RUNCHAR=chr(0x90) # run-length introducer RUNCHAR=chr(0x90) # run-length introducer
# #
# The code is currently byte-order dependent # This code is no longer byte-order dependent
if struct.pack('i', 0177) != '\0\0\0\177':
raise ImportError, 'Module binhex is big-endian only'
# #
# Workarounds for non-mac machines. # Workarounds for non-mac machines.
@ -92,9 +90,10 @@ else:
fp = open(name) fp = open(name)
data = open(name).read(256) data = open(name).read(256)
for c in data: for c in data:
if not c in string.whitespace and (c<' ' or ord(c) > 0177): if not c in string.whitespace \
break and (c<' ' or ord(c) > 0177):
else: break
else:
finfo.Type = 'TEXT' finfo.Type = 'TEXT'
fp.seek(0, 2) fp.seek(0, 2)
dsize = fp.tell() dsize = fp.tell()
@ -149,7 +148,8 @@ class _Hqxcoderengine:
def close(self): def close(self):
if self.data: if self.data:
self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data) self.hqxdata = \
self.hqxdata + binascii.b2a_hqx(self.data)
self._flush(1) self._flush(1)
self.ofp.close() self.ofp.close()
del self.ofp del self.ofp
@ -202,8 +202,10 @@ class BinHex:
raise Error, 'Filename too long' raise Error, 'Filename too long'
d = chr(nl) + name + '\0' d = chr(nl) + name + '\0'
d2 = finfo.Type + finfo.Creator d2 = finfo.Type + finfo.Creator
d3 = struct.pack('h', finfo.Flags)
d4 = struct.pack('ii', self.dlen, self.rlen) # Force all structs to be packed with big-endian
d3 = struct.pack('>h', finfo.Flags)
d4 = struct.pack('>ii', self.dlen, self.rlen)
info = d + d2 + d3 + d4 info = d + d2 + d3 + d4
self._write(info) self._write(info)
self._writecrc() self._writecrc()
@ -213,9 +215,10 @@ class BinHex:
self.ofp.write(data) self.ofp.write(data)
def _writecrc(self): def _writecrc(self):
## self.crc = binascii.crc_hqx('\0\0', self.crc) # XXXX Should this be here?? # XXXX Should this be here??
self.ofp.write(struct.pack('h', self.crc)) # self.crc = binascii.crc_hqx('\0\0', self.crc)
self.crc = 0 self.ofp.write(struct.pack('>h', self.crc))
self.crc = 0
def write(self, data): def write(self, data):
if self.state != _DID_HEADER: if self.state != _DID_HEADER:
@ -243,7 +246,8 @@ class BinHex:
if self.state != _DID_DATA: if self.state != _DID_DATA:
raise Error, 'Close at the wrong time' raise Error, 'Close at the wrong time'
if self.rlen <> 0: if self.rlen <> 0:
raise Error, "Incorrect resource-datasize, diff="+`self.rlen` raise Error, \
"Incorrect resource-datasize, diff="+`self.rlen`
self._writecrc() self._writecrc()
self.ofp.close() self.ofp.close()
self.state = None self.state = None
@ -283,25 +287,28 @@ class _Hqxdecoderengine:
decdata = '' decdata = ''
wtd = totalwtd wtd = totalwtd
# #
# The loop here is convoluted, since we don't really now how much # The loop here is convoluted, since we don't really now how
# to decode: there may be newlines in the incoming data. # much to decode: there may be newlines in the incoming data.
while wtd > 0: while wtd > 0:
if self.eof: return decdata if self.eof: return decdata
wtd = ((wtd+2)/3)*4 wtd = ((wtd+2)/3)*4
data = self.ifp.read(wtd) data = self.ifp.read(wtd)
# #
# Next problem: there may not be a complete number of bytes in what we # Next problem: there may not be a complete number of
# pass to a2b. Solve by yet another loop. # bytes in what we pass to a2b. Solve by yet another
# loop.
# #
while 1: while 1:
try: try:
decdatacur, self.eof = binascii.a2b_hqx(data) decdatacur, self.eof = \
binascii.a2b_hqx(data)
break break
except binascii.Incomplete: except binascii.Incomplete:
pass pass
newdata = self.ifp.read(1) newdata = self.ifp.read(1)
if not newdata: if not newdata:
raise Error, 'Premature EOF on binhex file' raise Error, \
'Premature EOF on binhex file'
data = data + newdata data = data + newdata
decdata = decdata + decdatacur decdata = decdata + decdatacur
wtd = totalwtd - len(decdata) wtd = totalwtd - len(decdata)
@ -330,9 +337,10 @@ class _Rledecoderengine:
def _fill(self, wtd): def _fill(self, wtd):
# #
# Obfuscated code ahead. We keep at least one byte in the pre_buffer, # Obfuscated code ahead. We keep at least one byte in the
# so we don't stumble over an orphaned RUNCHAR later on. If the # pre_buffer, so we don't stumble over an orphaned RUNCHAR
# last or second-last char is a RUNCHAR we keep more bytes. # later on. If the last or second-last char is a RUNCHAR
# we keep more bytes.
# #
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+2) self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+2)
if self.ifp.eof: if self.ifp.eof:
@ -384,11 +392,13 @@ class HexBin:
return data return data
def _checkcrc(self): def _checkcrc(self):
filecrc = struct.unpack('h', self.ifp.read(2))[0] & 0xffff filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff
## self.crc = binascii.crc_hqx('\0\0', self.crc) # XXXX Is this needed?? #self.crc = binascii.crc_hqx('\0\0', self.crc)
# XXXX Is this needed??
self.crc = self.crc & 0xffff self.crc = self.crc & 0xffff
if filecrc != self.crc: if filecrc != self.crc:
raise Error, 'CRC error, computed %x, read %x'%(self.crc, filecrc) raise Error, 'CRC error, computed %x, read %x' \
%(self.crc, filecrc)
self.crc = 0 self.crc = 0
def _readheader(self): def _readheader(self):
@ -399,9 +409,9 @@ class HexBin:
type = rest[1:5] type = rest[1:5]
creator = rest[5:9] creator = rest[5:9]
flags = struct.unpack('h', rest[9:11])[0] flags = struct.unpack('>h', rest[9:11])[0]
self.dlen = struct.unpack('l', rest[11:15])[0] self.dlen = struct.unpack('>l', rest[11:15])[0]
self.rlen = struct.unpack('l', rest[15:19])[0] self.rlen = struct.unpack('>l', rest[15:19])[0]
self.FName = fname self.FName = fname
self.FInfo = FInfo() self.FInfo = FInfo()
@ -496,9 +506,9 @@ def _test():
fname = fss.as_pathname() fname = fss.as_pathname()
else: else:
fname = sys.argv[1] fname = sys.argv[1]
#binhex(fname, fname+'.hqx') binhex(fname, fname+'.hqx')
#hexbin(fname+'.hqx', fname+'.viahqx') hexbin(fname+'.hqx', fname+'.viahqx')
hexbin(fname, fname+'.unpacked') #hexbin(fname, fname+'.unpacked')
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':