diff --git a/go.mod b/go.mod index 4010adfe01c..e5d8a088283 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect github.com/prometheus/procfs v0.0.0-20190322151404-55ae3d9d5573 // indirect github.com/rs/cors v1.6.0 - github.com/rwcarlsen/goexif v0.0.0-20190318171057-76e3344f7516 + github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd github.com/segmentio/analytics-go v2.0.1-0.20160426181448-2d840d861c32+incompatible github.com/segmentio/backo-go v0.0.0-20160424052352-204274ad699c // indirect github.com/sirupsen/logrus v1.4.0 diff --git a/go.sum b/go.sum index 1504b97b8b3..60b3325276a 100644 --- a/go.sum +++ b/go.sum @@ -298,6 +298,8 @@ github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rwcarlsen/goexif v0.0.0-20190318171057-76e3344f7516 h1:unvLzUrgn54Nhn5yJB8qUBr/a7wiZHQaJ/8Y4yTGAjE= github.com/rwcarlsen/goexif v0.0.0-20190318171057-76e3344f7516/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc= +github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= diff --git a/vendor/github.com/rwcarlsen/goexif/exif/exif.go b/vendor/github.com/rwcarlsen/goexif/exif/exif.go index 4232fb937a4..03afe6507a6 100644 --- a/vendor/github.com/rwcarlsen/goexif/exif/exif.go +++ b/vendor/github.com/rwcarlsen/goexif/exif/exif.go @@ -3,12 +3,14 @@ package exif import ( + "bufio" "bytes" "encoding/binary" "encoding/json" "errors" "fmt" "io" + "io/ioutil" "math" "strconv" "strings" @@ -138,15 +140,6 @@ var stagePrefix = map[tiffError]string{ loadInteroperability: "loading Interoperability sub-IFD", } -type offsetReaderAt struct { - offset int64 - r io.ReaderAt -} - -func (r *offsetReaderAt) ReadAt(p []byte, off int64) (int, error) { - return r.r.ReadAt(p, off+r.offset) -} - // Parse reads data from the tiff data in x and populates the tags // in x. If parsing a sub-IFD fails, the error is recorded and // parsing continues with the remaining sub-IFDs. @@ -181,6 +174,7 @@ func (p *parser) Parse(x *Exif) error { } func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error { + r := bytes.NewReader(x.Raw) tag, err := x.Get(ptr) if err != nil { @@ -191,7 +185,11 @@ func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error { return nil } - subDir, _, err := tiff.DecodeDir(x.ReaderAt, x.Tiff.Order, uint32(offset)) + _, err = r.Seek(offset, 0) + if err != nil { + return fmt.Errorf("exif: seek to sub-IFD %s failed: %v", ptr, err) + } + subDir, _, err := tiff.DecodeDir(r, x.Tiff.Order) if err != nil { return fmt.Errorf("exif: sub-IFD %s decode failed: %v", ptr, err) } @@ -201,12 +199,9 @@ func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error { // Exif provides access to decoded EXIF metadata fields and values. type Exif struct { - Tiff *tiff.Tiff - main map[FieldName]*tiff.Tag - Raw []byte - ReaderAt io.ReaderAt - exifLength uint16 - exifStart uint32 + Tiff *tiff.Tiff + main map[FieldName]*tiff.Tag + Raw []byte } // Decode parses EXIF data from r (a TIFF, JPEG, or raw EXIF block) @@ -218,39 +213,6 @@ type Exif struct { // The error can be inspected with functions such as IsCriticalError // to determine whether the returned object might still be usable. func Decode(r io.Reader) (*Exif, error) { - reader := &readerToReaderAt{reader: r} - exif, err := LazyDecode(reader) - if err != nil { - return nil, err - } - _, err = exif.Tiff.LoadAllVals() - if err != nil { - return nil, err - } - if exif.exifLength > 0 { - exif.Raw = make([]byte, exif.exifLength) - _, err := exif.ReaderAt.ReadAt(exif.Raw, 0) - if err != nil { - return nil, decodeError{cause: err} - } - } else { - exif.Raw = reader.buffer[exif.exifStart:] - } - return exif, nil -} - -// LazyDecode parses EXIF data from r (a TIFF, JPEG, or raw EXIF block) -// and returns a queryable Exif object. After the EXIF data section is -// called and the TIFF structure is decoded, each registered parser is -// called (in order of registration). If one parser returns an error, -// decoding terminates and the remaining parsers are not called. -// -// The error can be inspected with functions such as IsCriticalError -// to determine whether the returned object might still be usable. -// -// It differs from Decode as it only reads known exif fields and does not attempt to read the -// entire contents of the exif tiff subdirectory; the Exif.Raw field will be nil. -func LazyDecode(r io.ReaderAt) (*Exif, error) { // EXIF data in JPEG is stored in the APP1 marker. EXIF data uses the TIFF // format to store data. @@ -258,41 +220,86 @@ func LazyDecode(r io.ReaderAt) (*Exif, error) { // If we're parsing a JPEG image, we need to strip away the JPEG APP1 // marker and also the EXIF header. - // build an exif structure from the tiff - x := &Exif{ - main: map[FieldName]*tiff.Tag{}, - exifStart: 0, - exifLength: 0, - ReaderAt: r, + header := make([]byte, 4) + n, err := io.ReadFull(r, header) + if err != nil { + return nil, fmt.Errorf("exif: error reading 4 byte header, got %d, %v", n, err) } - b := make([]byte, 6) - _, err := r.ReadAt(b, 0) - if bytes.Compare(b, []byte("Exif\x00\x00")) == 0 { - x.exifStart = 6 - x.ReaderAt = &offsetReaderAt{ - offset: 6, - r: x.ReaderAt, + var isTiff bool + var isRawExif bool + var assumeJPEG bool + switch string(header) { + case "II*\x00": + // TIFF - Little endian (Intel) + isTiff = true + case "MM\x00*": + // TIFF - Big endian (Motorola) + isTiff = true + case "Exif": + isRawExif = true + default: + // Not TIFF, assume JPEG + assumeJPEG = true + } + + // Put the header bytes back into the reader. + r = io.MultiReader(bytes.NewReader(header), r) + var ( + er *bytes.Reader + tif *tiff.Tiff + sec *appSec + ) + + switch { + case isRawExif: + var header [6]byte + if _, err := io.ReadFull(r, header[:]); err != nil { + return nil, fmt.Errorf("exif: unexpected raw exif header read error") } - } - - x.Tiff, err = tiff.LazyDecode(x.ReaderAt) - if tiff.IsInvalidTiff(err) { - x.exifStart, x.exifLength, err = findJPEGExifOffset(jpeg_APP1, r) + if got, want := string(header[:]), "Exif\x00\x00"; got != want { + return nil, fmt.Errorf("exif: unexpected raw exif header; got %q, want %q", got, want) + } + fallthrough + case isTiff: + // Functions below need the IFDs from the TIFF data to be stored in a + // *bytes.Reader. We use TeeReader to get a copy of the bytes as a + // side-effect of tiff.Decode() doing its work. + b := &bytes.Buffer{} + tr := io.TeeReader(r, b) + tif, err = tiff.Decode(tr) + er = bytes.NewReader(b.Bytes()) + case assumeJPEG: + // Locate the JPEG APP1 header. + sec, err = newAppSec(jpeg_APP1, r) if err != nil { - return nil, decodeError{cause: err} + return nil, err } - x.ReaderAt = &offsetReaderAt{ - offset: int64(x.exifStart), - r: x.ReaderAt, + // Strip away EXIF header. + er, err = sec.exifReader() + if err != nil { + return nil, err } - x.Tiff, err = tiff.LazyDecode(x.ReaderAt) + tif, err = tiff.Decode(er) } if err != nil { return nil, decodeError{cause: err} } + er.Seek(0, 0) + raw, err := ioutil.ReadAll(er) + if err != nil { + return nil, decodeError{cause: err} + } + + // build an exif structure from the tiff + x := &Exif{ + main: map[FieldName]*tiff.Tag{}, + Tiff: tif, + Raw: raw, + } + for i, p := range parsers { if err := p.Parse(x); err != nil { if _, ok := err.(tiffErrors); ok { @@ -347,10 +354,6 @@ type Walker interface { // EXIF field. If w aborts the walk with an error, that error is returned. func (x *Exif) Walk(w Walker) error { for name, tag := range x.main { - err := tag.LoadVal() - if err != nil { - return err - } if err := w.Walk(name, tag); err != nil { return err } @@ -572,13 +575,8 @@ func (x *Exif) JpegThumbnail() ([]byte, error) { if err != nil { return nil, err } - tiff := make([]byte, l) - _, err = x.ReaderAt.ReadAt(tiff, int64(start)) - if err != nil { - return nil, err - } - return tiff, nil + return x.Raw[start : start+l], nil } // MarshalJson implements the encoding/json.Marshaler interface providing output of @@ -587,45 +585,71 @@ func (x Exif) MarshalJSON() ([]byte, error) { return json.Marshal(x.main) } -// findJPEGExifOffset finds marker in r and returns the offset of the Exif data -func findJPEGExifOffset(marker byte, r io.ReaderAt) (uint32, uint16, error) { - // read the file 1MB per 1MB to locate the marker - bufferLength := 4096 - // Ensure there is a small overlap between buffers to handle the case - // where the marker is located exactly in-between 2 reads - seeker := make([]byte, bufferLength+2) - appHeader := []byte{0xFF, marker} +type appSec struct { + marker byte + data []byte +} + +// newAppSec finds marker in r and returns the corresponding application data +// section. +func newAppSec(marker byte, r io.Reader) (*appSec, error) { + br := bufio.NewReader(r) + app := &appSec{marker: marker} + var dataLen int // seek to marker - var markerIndex int - i := 0 - for { - count, err := r.ReadAt(seeker, int64(i*bufferLength)) - if err != nil && err != io.EOF { - return 0, 0, err + for dataLen == 0 { + if _, err := br.ReadBytes(0xFF); err != nil { + return nil, err + } + c, err := br.ReadByte() + if err != nil { + return nil, err + } else if c != marker { + continue } - markerIndex = bytes.Index(seeker, appHeader) - // stop at the end of the file or when the marker is found - if markerIndex >= 0 || count < bufferLength { - break + dataLenBytes := make([]byte, 2) + for k, _ := range dataLenBytes { + c, err := br.ReadByte() + if err != nil { + return nil, err + } + dataLenBytes[k] = c } - i++ + dataLen = int(binary.BigEndian.Uint16(dataLenBytes)) - 2 } - if markerIndex < 0 { - return 0, 0, fmt.Errorf("Unable to find the JPEG Exif marker") + + // read section data + nread := 0 + for nread < dataLen { + s := make([]byte, dataLen-nread) + n, err := br.Read(s) + nread += n + if err != nil && nread < dataLen { + return nil, err + } + app.data = append(app.data, s[:n]...) } - // Skip the application header - markerIndex += i*bufferLength + 2 - // Read content length and check that it actually contains an exif - header := make([]byte, 8) - _, err := r.ReadAt(header, int64(markerIndex)) - if err != nil { - return 0, 0, err - } - if !bytes.Equal(header[2:], []byte("Exif\000\000")) { - return 0, 0, fmt.Errorf("Unable to find the JPEG Exif marker") - } - dataLen := binary.BigEndian.Uint16(header[:2]) - 2 - return uint32(markerIndex + len(header)), dataLen, nil + return app, nil +} + +// reader returns a reader on this appSec. +func (app *appSec) reader() *bytes.Reader { + return bytes.NewReader(app.data) +} + +// exifReader returns a reader on this appSec with the read cursor advanced to +// the start of the exif's tiff encoded portion. +func (app *appSec) exifReader() (*bytes.Reader, error) { + if len(app.data) < 6 { + return nil, errors.New("exif: failed to find exif intro marker") + } + + // read/check for exif special mark + exif := app.data[:6] + if !bytes.Equal(exif, append([]byte("Exif"), 0x00, 0x00)) { + return nil, errors.New("exif: failed to find exif intro marker") + } + return bytes.NewReader(app.data[6:]), nil } diff --git a/vendor/github.com/rwcarlsen/goexif/exif/readerAt.go b/vendor/github.com/rwcarlsen/goexif/exif/readerAt.go deleted file mode 100644 index b9a170dcd9e..00000000000 --- a/vendor/github.com/rwcarlsen/goexif/exif/readerAt.go +++ /dev/null @@ -1,29 +0,0 @@ -package exif - -import ( - "io" -) - -type readerToReaderAt struct { - reader io.Reader - buffer []byte -} - -func (r *readerToReaderAt) ReadAt(p []byte, start int64) (n int, err error) { - end := start + int64(len(p)) - n = 0 - l := len(r.buffer) - if end > int64(l) { - new := make([]byte, end-int64(l)) - n, err = r.reader.Read(new) - if err == io.EOF { - err = nil - } - r.buffer = append(r.buffer, new[:n]...) - } - if end > int64(len(r.buffer)) { - end = int64(len(r.buffer)) - } - n = copy(p[:], r.buffer[start:end]) - return -} diff --git a/vendor/github.com/rwcarlsen/goexif/tiff/tag.go b/vendor/github.com/rwcarlsen/goexif/tiff/tag.go index 090e822c557..b9ce791f54b 100644 --- a/vendor/github.com/rwcarlsen/goexif/tiff/tag.go +++ b/vendor/github.com/rwcarlsen/goexif/tiff/tag.go @@ -107,59 +107,71 @@ type Tag struct { ratVals [][]int64 strVal string format Format - // raw contains the raw content of the value - // either the value if it fits in 4 bytes or a pointer to it if bigger - r io.ReaderAt - raw []byte - valLen uint32 } // DecodeTag parses a tiff-encoded IFD tag from r and returns a Tag object. The // first read from r should be the first byte of the tag. ReadAt offsets should // generally be relative to the beginning of the tiff structure (not relative // to the beginning of the tag). -func DecodeTag(r io.ReaderAt, rawData []byte, order binary.ByteOrder) (*Tag, error) { +func DecodeTag(r ReadAtReader, order binary.ByteOrder) (*Tag, error) { t := new(Tag) t.order = order - t.r = r - t.Id = order.Uint16(rawData[0:2]) - t.Type = DataType(order.Uint16(rawData[2:4])) - t.Count = order.Uint32(rawData[4:8]) + err := binary.Read(r, order, &t.Id) + if err != nil { + return nil, errors.New("tiff: tag id read failed: " + err.Error()) + } + + err = binary.Read(r, order, &t.Type) + if err != nil { + return nil, errors.New("tiff: tag type read failed: " + err.Error()) + } + + err = binary.Read(r, order, &t.Count) + if err != nil { + return nil, errors.New("tiff: tag component count read failed: " + err.Error()) + } // There seems to be a relatively common corrupt tag which has a Count of // MaxUint32. This is probably not a valid value, so return early. - if t.Count >= 1<<32-1 { + if t.Count == 1<<32-1 { return t, errors.New("invalid Count offset in tag") } - t.valLen = typeSize[t.Type] * t.Count - if t.valLen == 0 { + valLen := typeSize[t.Type] * t.Count + if valLen == 0 { return t, errors.New("zero length tag value") } - t.raw = rawData[8:12] + if valLen > 4 { + binary.Read(r, order, &t.ValOffset) - return t, nil -} - -func (t *Tag) LoadVal() error { - if t.Val != nil { - return nil - } - if t.valLen > 4 { - offset := t.order.Uint32(t.raw) - val := make([]byte, t.valLen) - _, err := t.r.ReadAt(val, int64(offset)) + // Use a bytes.Buffer so we don't allocate a huge slice if the tag + // is corrupt. + var buff bytes.Buffer + sr := io.NewSectionReader(r, int64(t.ValOffset), int64(valLen)) + n, err := io.Copy(&buff, sr) if err != nil { - return errors.New("tiff: tag value read failed: " + err.Error()) + return t, errors.New("tiff: tag value read failed: " + err.Error()) + } else if n != int64(valLen) { + return t, ErrShortReadTagValue } - t.Val = val + t.Val = buff.Bytes() } else { - t.Val = t.raw[0:t.valLen] + val := make([]byte, valLen) + if _, err = io.ReadFull(r, val); err != nil { + return t, errors.New("tiff: tag offset read failed: " + err.Error()) + } + // ignore padding. + if _, err = io.ReadFull(r, make([]byte, 4-valLen)); err != nil { + return t, errors.New("tiff: tag offset read failed: " + err.Error()) + } + + t.Val = val } - return t.convertVals() + + return t, t.convertVals() } func (t *Tag) convertVals() error { @@ -328,12 +340,6 @@ func (t *Tag) Rat(i int) (*big.Rat, error) { // numerator-denominator pair. It returns an error if the tag's Format is not // RatVal. It panics if i is out of range. func (t *Tag) Rat2(i int) (num, den int64, err error) { - if t.ratVals == nil { - err := t.LoadVal() - if err != nil { - return 0, 0, err - } - } if t.format != RatVal { return 0, 0, t.typeErr(RatVal) } @@ -343,12 +349,6 @@ func (t *Tag) Rat2(i int) (num, den int64, err error) { // Int64 returns the tag's i'th value as an integer. It returns an error if the // tag's Format is not IntVal. It panics if i is out of range. func (t *Tag) Int64(i int) (int64, error) { - if t.intVals == nil { - err := t.LoadVal() - if err != nil { - return 0, err - } - } if t.format != IntVal { return 0, t.typeErr(IntVal) } @@ -358,12 +358,6 @@ func (t *Tag) Int64(i int) (int64, error) { // Int returns the tag's i'th value as an integer. It returns an error if the // tag's Format is not IntVal. It panics if i is out of range. func (t *Tag) Int(i int) (int, error) { - if t.intVals == nil { - err := t.LoadVal() - if err != nil { - return 0, err - } - } if t.format != IntVal { return 0, t.typeErr(IntVal) } @@ -373,12 +367,6 @@ func (t *Tag) Int(i int) (int, error) { // Float returns the tag's i'th value as a float. It returns an error if the // tag's Format is not IntVal. It panics if i is out of range. func (t *Tag) Float(i int) (float64, error) { - if t.floatVals == nil { - err := t.LoadVal() - if err != nil { - return 0, err - } - } if t.format != FloatVal { return 0, t.typeErr(FloatVal) } @@ -388,12 +376,6 @@ func (t *Tag) Float(i int) (float64, error) { // StringVal returns the tag's value as a string. It returns an error if the // tag's Format is not StringVal. It panics if i is out of range. func (t *Tag) StringVal() (string, error) { - if t.strVal == "" { - err := t.LoadVal() - if err != nil { - return "", err - } - } if t.format != StringVal { return "", t.typeErr(StringVal) } @@ -414,10 +396,6 @@ func (t *Tag) String() string { } func (t *Tag) MarshalJSON() ([]byte, error) { - err := t.LoadVal() - if err != nil { - return nil, err - } switch t.format { case StringVal, UndefVal: return nullString(t.Val), nil diff --git a/vendor/github.com/rwcarlsen/goexif/tiff/tiff.go b/vendor/github.com/rwcarlsen/goexif/tiff/tiff.go index 63bbf70e4d0..771e9187860 100644 --- a/vendor/github.com/rwcarlsen/goexif/tiff/tiff.go +++ b/vendor/github.com/rwcarlsen/goexif/tiff/tiff.go @@ -11,8 +11,6 @@ import ( "io/ioutil" ) -const notValidTIFF = "tiff: invalid TIFF header" - // ReadAtReader is used when decoding Tiff tags and directories type ReadAtReader interface { io.Reader @@ -28,10 +26,6 @@ type Tiff struct { Order binary.ByteOrder } -func IsInvalidTiff(err error) bool { - return err != nil && err.Error() == notValidTIFF -} - // Decode parses tiff-encoded data from r and returns a Tiff struct that // reflects the structure and content of the tiff data. The first read from r // should be the first byte of the tiff-encoded data and not necessarily the @@ -42,27 +36,12 @@ func Decode(r io.Reader) (*Tiff, error) { return nil, errors.New("tiff: could not read data") } buf := bytes.NewReader(data) - t, err := LazyDecode(buf) - if err != nil { - return nil, err - } - return t.LoadAllVals() -} - -// LazyDecode parses tiff-encoded data from r and returns a Tiff struct that -// reflects the structure and content of the tiff data. The first read from r -// should be the first byte of the tiff-encoded data and not necessarily the -// first byte of an os.File object. -// -// It differs from Decode as it is restricted to parsing the tiff structure -// and only decodes the values on demand. -func LazyDecode(r io.ReaderAt) (*Tiff, error) { t := new(Tiff) // read byte order bo := make([]byte, 2) - if _, err := r.ReadAt(bo, 0); err != nil { + if _, err = io.ReadFull(buf, bo); err != nil { return nil, errors.New("tiff: could not read tiff byte order") } if string(bo) == "II" { @@ -70,31 +49,39 @@ func LazyDecode(r io.ReaderAt) (*Tiff, error) { } else if string(bo) == "MM" { t.Order = binary.BigEndian } else { - return nil, errors.New(notValidTIFF) + return nil, errors.New("tiff: could not read tiff byte order") } // check for special tiff marker - sp := make([]byte, 2) - _, err := r.ReadAt(sp, 2) - if err != nil || 42 != t.Order.Uint16(sp) { + var sp int16 + err = binary.Read(buf, t.Order, &sp) + if err != nil || 42 != sp { return nil, errors.New("tiff: could not find special tiff marker") } // load offset to first IFD - binaryOffset := make([]byte, 4) - _, err = r.ReadAt(binaryOffset, 4) + var offset int32 + err = binary.Read(buf, t.Order, &offset) if err != nil { return nil, errors.New("tiff: could not read offset to first IFD") } - offset := t.Order.Uint32(binaryOffset) // load IFD's var d *Dir prev := offset for offset != 0 { + // seek to offset + _, err := buf.Seek(int64(offset), 0) + if err != nil { + return nil, errors.New("tiff: seek to IFD failed") + } + + if buf.Len() == 0 { + return nil, errors.New("tiff: seek offset after EOF") + } // load the dir - d, offset, err = DecodeDir(r, t.Order, offset) + d, offset, err = DecodeDir(buf, t.Order) if err != nil { return nil, err } @@ -110,19 +97,6 @@ func LazyDecode(r io.ReaderAt) (*Tiff, error) { return t, nil } -// LoadAllVals loads and parses all tiff directory values in memory -func (t *Tiff) LoadAllVals() (*Tiff, error) { - for _, d := range t.Dirs { - for _, tag := range d.Tags { - err := tag.LoadVal() - if err != nil { - return nil, err - } - } - } - return t, nil -} - func (tf *Tiff) String() string { var buf bytes.Buffer fmt.Fprint(&buf, "Tiff{") @@ -142,41 +116,32 @@ type Dir struct { // is the offset to the next IFD. The first read from r should be at the first // byte of the IFD. ReadAt offsets should generally be relative to the // beginning of the tiff structure (not relative to the beginning of the IFD). -func DecodeDir(r io.ReaderAt, order binary.ByteOrder, offset uint32) (*Dir, uint32, error) { - d := new(Dir) +func DecodeDir(r ReadAtReader, order binary.ByteOrder) (d *Dir, offset int32, err error) { + d = new(Dir) // get num of tags in ifd - b := make([]byte, 4) - _, err := r.ReadAt(b[0:2], int64(offset)) + var nTags int16 + err = binary.Read(r, order, &nTags) if err != nil { return nil, 0, errors.New("tiff: failed to read IFD tag count: " + err.Error()) } - nTags := order.Uint16(b[0:2]) - tags := make([]byte, 12*nTags) - offset += 2 - _, err = r.ReadAt(tags, int64(offset)) - if err != nil { - return nil, 0, errors.New("tiff: falied to read offset to next IFD: " + err.Error()) - } // load tags for n := 0; n < int(nTags); n++ { - t, err := DecodeTag(r, tags[n*12:(n+1)*12], order) + t, err := DecodeTag(r, order) if err != nil { return nil, 0, err } d.Tags = append(d.Tags, t) - offset += 12 } // get offset to next ifd - - _, err = r.ReadAt(b, int64(offset)) + err = binary.Read(r, order, &offset) if err != nil { return nil, 0, errors.New("tiff: falied to read offset to next IFD: " + err.Error()) } - return d, order.Uint32(b), nil + return d, offset, nil } func (d *Dir) String() string { diff --git a/vendor/modules.txt b/vendor/modules.txt index 36bac6bd36b..b68e5345f2f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -190,7 +190,7 @@ github.com/prometheus/procfs/xfs github.com/prometheus/procfs/internal/util # github.com/rs/cors v1.6.0 github.com/rs/cors -# github.com/rwcarlsen/goexif v0.0.0-20190318171057-76e3344f7516 +# github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd github.com/rwcarlsen/goexif/exif github.com/rwcarlsen/goexif/tiff # github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529