diff --git a/ui/medashare/metadata/crw.py b/ui/medashare/metadata/crw.py index 9e34161..e696998 100644 --- a/ui/medashare/metadata/crw.py +++ b/ui/medashare/metadata/crw.py @@ -619,6 +619,7 @@ class IFD(object): if tag is None: nextptr.append(res) break + tag = self.getEnum(tag) if tag in taghandlers: res = taghandlers[tag](fh, endian, res, off) @@ -639,7 +640,7 @@ class IFD(object): def getEnum(self, key): try: return self.__enum(key) - except KeyError: + except ValueError: return key def __repr__(self): @@ -919,6 +920,7 @@ def tiff_srational(endian, data): return rational_dcomp(tiff_slong(endian, data)) tifftypes = { + # function to decode, length of an element 1: (tiff_bytes, 1), 2: (tiff_ascii, 1), 3: (tiff_short, 2), @@ -1083,7 +1085,7 @@ def idcrw(fh): if hlen == 0x2a: #TIFF/CR2 - hoff, idstr, ver, hlen = readstruct(fh, endian + "I2sHI") + hoff, idstr, ver, rawifdoff = readstruct(fh, endian + "I2sHI") if not isjpeg and (hoff != 0x10 or idstr != b'CR' or ver != 2): raise ValueError('normal TIFF, not a CR2') nextoff = [ hoff ] @@ -1180,6 +1182,64 @@ class _TestCRW(unittest.TestCase): l.sort() set(l) + @staticmethod + def ifd_builder(endian, off, entries): + '''Build an IFD. It is assumed to be rooted at off, but + will be returned as a bare string. To locate it properly, + something like: + file = b'\x00' * off + ifd_builder('<', off) + + needs to be used. Obviously the prefix above is wrong and will + need to be a proper TIFF header and/or other IFDs. + + The data will be added at the end. + + entires is a list of tuples: + (tag, type, count, value) + + Return value is a tuple of bytes, and offset of nextifd. + ''' + + entries = list(entries) + cnt = len(entries) + + r = [] + + r.append(struct.pack(endian + 'H', cnt)) + + # offset + count + ifd entries + nextifd + extra = off + 2 + cnt * 12 + 4 + sextra = extra + e = [] # extra values + + for tag, _type, count, value in entries: + if len(value) <= 4: + r.append(struct.pack(endian + 'HHI', tag, _type, count) + value + b'\x00' * (4 - len(value))) + else: + r.append(struct.pack(endian + 'HHII', tag, _type, count, extra)) + e.append(value) + extra += len(value) + + r = b''.join(r) + + nextoff = len(r) + off + + assert len(r) + 4 == sextra - off + + return r + b'\x00' * 4 + b''.join(e), len(r) + + def test_unknown(self): + endian = '<' + off = 10 + + ifd, nextoff = self.ifd_builder(endian, off, [ + (65000, 1, 4, b'\x10' * 4), + (65001, 1, 10, b'\x20' * 10) + ]) + fh = BytesIO(b'\x00' * 10 + ifd) + + r = IFD(ExifTag, {}, fh, endian, off) + def test_bogus(self): # make sure various bogus "files" raise an error