ifd_enumerate: Can now elect to not resolve tag value.

- To support testing.
pull/3/head
Dustin Oprea 2018-06-08 00:41:28 -04:00
parent 4c3a9d79f1
commit 1ce5b771db
4 changed files with 34 additions and 24 deletions

View File

@ -179,7 +179,7 @@ func Visit(exifData []byte, visitor TagVisitor) (eh ExifHeader, err error) {
ie := NewIfdEnumerate(exifData, eh.ByteOrder)
err = ie.Scan(eh.FirstIfdOffset, visitor)
err = ie.Scan(eh.FirstIfdOffset, visitor, true)
log.PanicIf(err)
return eh, nil
@ -198,7 +198,7 @@ func Collect(exifData []byte) (eh ExifHeader, index IfdIndex, err error) {
ie := NewIfdEnumerate(exifData, eh.ByteOrder)
index, err = ie.Collect(eh.FirstIfdOffset)
index, err = ie.Collect(eh.FirstIfdOffset, true)
log.PanicIf(err)
return eh, index, nil

View File

@ -375,7 +375,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
t.Fatalf("Child IFD is not the right size: (%d)", len(childIfdBlock))
}
iteV, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes)
iteV, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes, false)
log.PanicIf(err)
if iteV.TagId != IfdExifId {
@ -398,7 +398,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
// Validate the child's raw IFD bytes.
childNextIfdOffset, childEntries, err := ParseOneIfd(ExifIi, TestDefaultByteOrder, childIfdBlock, nil)
childNextIfdOffset, childEntries, err := ParseOneIfd(ExifIi, TestDefaultByteOrder, childIfdBlock, nil, false)
log.PanicIf(err)
if childNextIfdOffset != uint32(0) {
@ -429,6 +429,13 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
}
func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.PrintErrorf(err, "Test failure.")
}
}()
// Encode the tag. Since we've actually provided an offset at which we can
// allocate data, the child-IFD will automatically be encoded, allocated,
// and installed into the allocated-data block (which will follow the IFD
@ -467,7 +474,8 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
t.Fatalf("Child IFD not have been allocated.")
}
ite, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes)
ite, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes, false)
log.PanicIf(err)
if ite.TagId != 0x000b {

View File

@ -125,7 +125,7 @@ func (ie *IfdEnumerate) getTagEnumerator(ifdOffset uint32) (ite *IfdTagEnumerato
return ite
}
func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagIndex int, ite *IfdTagEnumerator) (tag *IfdTagEntry, err error) {
func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagIndex int, ite *IfdTagEnumerator, resolveValue bool) (tag *IfdTagEntry, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -154,11 +154,13 @@ func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagIndex int, ite *IfdTagEnumer
RawValueOffset: rawValueOffset,
}
value, isUnhandledUnknown, err := ie.resolveTagValue(tag)
log.PanicIf(err)
if resolveValue == true {
value, isUnhandledUnknown, err := ie.resolveTagValue(tag)
log.PanicIf(err)
tag.value = value
tag.isUnhandledUnknown = isUnhandledUnknown
tag.value = value
tag.isUnhandledUnknown = isUnhandledUnknown
}
// If it's an IFD but not a standard one, it'll just be seen as a LONG
// (the standard IFD tag type), later, unless we skip it because it's
@ -248,7 +250,7 @@ type TagVisitor func(ii IfdIdentity, ifdIndex int, tagId uint16, tagType TagType
// ParseIfd decodes the IFD block that we're currently sitting on the first
// byte of.
func (ie *IfdEnumerate) ParseIfd(ii IfdIdentity, ifdIndex int, ite *IfdTagEnumerator, visitor TagVisitor, doDescend bool) (nextIfdOffset uint32, entries []*IfdTagEntry, thumbnailData []byte, err error) {
func (ie *IfdEnumerate) ParseIfd(ii IfdIdentity, ifdIndex int, ite *IfdTagEnumerator, visitor TagVisitor, doDescend bool, resolveValues bool) (nextIfdOffset uint32, entries []*IfdTagEntry, thumbnailData []byte, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -266,7 +268,7 @@ func (ie *IfdEnumerate) ParseIfd(ii IfdIdentity, ifdIndex int, ite *IfdTagEnumer
var iteThumbnailSize *IfdTagEntry
for i := 0; i < int(tagCount); i++ {
tag, err := ie.parseTag(ii, i, ite)
tag, err := ie.parseTag(ii, i, ite, resolveValues)
log.PanicIf(err)
if tag.TagId == ThumbnailOffsetTagId {
@ -300,7 +302,7 @@ func (ie *IfdEnumerate) ParseIfd(ii IfdIdentity, ifdIndex int, ite *IfdTagEnumer
childIi, _ := IfdIdOrFail(ii.IfdName, tag.ChildIfdName)
err := ie.scan(childIi, tag.ValueOffset, visitor)
err := ie.scan(childIi, tag.ValueOffset, visitor, resolveValues)
log.PanicIf(err)
}
@ -351,7 +353,7 @@ func (ie *IfdEnumerate) parseThumbnail(offsetIte, lengthIte *IfdTagEntry) (thumb
}
// Scan enumerates the different EXIF's IFD blocks.
func (ie *IfdEnumerate) scan(ii IfdIdentity, ifdOffset uint32, visitor TagVisitor) (err error) {
func (ie *IfdEnumerate) scan(ii IfdIdentity, ifdOffset uint32, visitor TagVisitor, resolveValues bool) (err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -362,7 +364,7 @@ func (ie *IfdEnumerate) scan(ii IfdIdentity, ifdOffset uint32, visitor TagVisito
ifdEnumerateLogger.Debugf(nil, "Parsing IFD [%s] (%d) at offset (%04x).", ii.IfdName, ifdIndex, ifdOffset)
ite := ie.getTagEnumerator(ifdOffset)
nextIfdOffset, _, _, err := ie.ParseIfd(ii, ifdIndex, ite, visitor, true)
nextIfdOffset, _, _, err := ie.ParseIfd(ii, ifdIndex, ite, visitor, true, resolveValues)
log.PanicIf(err)
if nextIfdOffset == 0 {
@ -376,7 +378,7 @@ func (ie *IfdEnumerate) scan(ii IfdIdentity, ifdOffset uint32, visitor TagVisito
}
// Scan enumerates the different EXIF blocks (called IFDs).
func (ie *IfdEnumerate) Scan(ifdOffset uint32, visitor TagVisitor) (err error) {
func (ie *IfdEnumerate) Scan(ifdOffset uint32, visitor TagVisitor, resolveValue bool) (err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -385,7 +387,7 @@ func (ie *IfdEnumerate) Scan(ifdOffset uint32, visitor TagVisitor) (err error) {
ii, _ := IfdIdOrFail("", IfdStandard)
err = ie.scan(ii, ifdOffset, visitor)
err = ie.scan(ii, ifdOffset, visitor, resolveValue)
log.PanicIf(err)
return nil
@ -818,7 +820,7 @@ type IfdIndex struct {
// Scan enumerates the different EXIF blocks (called IFDs).
func (ie *IfdEnumerate) Collect(rootIfdOffset uint32) (index IfdIndex, err error) {
func (ie *IfdEnumerate) Collect(rootIfdOffset uint32, resolveValues bool) (index IfdIndex, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -860,7 +862,7 @@ func (ie *IfdEnumerate) Collect(rootIfdOffset uint32) (index IfdIndex, err error
ifdEnumerateLogger.Debugf(nil, "Parsing IFD [%s] (%d) at offset (%04x).", ii.IfdName, index, offset)
ite := ie.getTagEnumerator(offset)
nextIfdOffset, entries, thumbnailData, err := ie.ParseIfd(ii, index, ite, nil, false)
nextIfdOffset, entries, thumbnailData, err := ie.ParseIfd(ii, index, ite, nil, false, resolveValues)
log.PanicIf(err)
id := len(ifds)
@ -979,7 +981,7 @@ func (ie *IfdEnumerate) Collect(rootIfdOffset uint32) (index IfdIndex, err error
// ParseOneIfd is a hack to use an IE to parse a raw IFD block. Can be used for
// testing.
func ParseOneIfd(ii IfdIdentity, byteOrder binary.ByteOrder, ifdBlock []byte, visitor TagVisitor) (nextIfdOffset uint32, entries []*IfdTagEntry, err error) {
func ParseOneIfd(ii IfdIdentity, byteOrder binary.ByteOrder, ifdBlock []byte, visitor TagVisitor, resolveValues bool) (nextIfdOffset uint32, entries []*IfdTagEntry, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -992,14 +994,14 @@ func ParseOneIfd(ii IfdIdentity, byteOrder binary.ByteOrder, ifdBlock []byte, vi
ite := NewIfdTagEnumerator(ifdBlock, byteOrder, 0)
nextIfdOffset, entries, _, err = ie.ParseIfd(ii, 0, ite, visitor, true)
nextIfdOffset, entries, _, err = ie.ParseIfd(ii, 0, ite, visitor, true, resolveValues)
log.PanicIf(err)
return nextIfdOffset, entries, nil
}
// ParseOneTag is a hack to use an IE to parse a raw tag block.
func ParseOneTag(ii IfdIdentity, byteOrder binary.ByteOrder, tagBlock []byte) (tag *IfdTagEntry, err error) {
func ParseOneTag(ii IfdIdentity, byteOrder binary.ByteOrder, tagBlock []byte, resolveValue bool) (tag *IfdTagEntry, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
@ -1012,7 +1014,7 @@ func ParseOneTag(ii IfdIdentity, byteOrder binary.ByteOrder, tagBlock []byte) (t
ite := NewIfdTagEnumerator(tagBlock, byteOrder, 0)
tag, err = ie.parseTag(ii, 0, ite)
tag, err = ie.parseTag(ii, 0, ite, resolveValue)
log.PanicIf(err)
return tag, nil

View File

@ -60,7 +60,7 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
t.Fatalf("Tag not encoded to the right number of bytes: (%d)", len(tagBytes))
}
ite, err := ParseOneTag(ii, byteOrder, tagBytes)
ite, err := ParseOneTag(ii, byteOrder, tagBytes, false)
log.PanicIf(err)
if ite.TagId != 0x9000 {