Working auth and photo json endpoint
Signed-off-by: Kris Nóva <kris@nivenly.com>
This commit is contained in:
parent
ef275f97f4
commit
e4323b6047
2032 changed files with 821464 additions and 52 deletions
395
vendor/github.com/dsoprea/go-jpeg-image-structure/segment_list.go
generated
vendored
Normal file
395
vendor/github.com/dsoprea/go-jpeg-image-structure/segment_list.go
generated
vendored
Normal file
|
@ -0,0 +1,395 @@
|
|||
package jpegstructure
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/dsoprea/go-exif/v2"
|
||||
"github.com/dsoprea/go-iptc"
|
||||
log "github.com/dsoprea/go-logging"
|
||||
)
|
||||
|
||||
// SegmentList contains a slice of segments.
|
||||
type SegmentList struct {
|
||||
segments []*Segment
|
||||
}
|
||||
|
||||
// NewSegmentList returns a new SegmentList struct.
|
||||
func NewSegmentList(segments []*Segment) (sl *SegmentList) {
|
||||
if segments == nil {
|
||||
segments = make([]*Segment, 0)
|
||||
}
|
||||
|
||||
return &SegmentList{
|
||||
segments: segments,
|
||||
}
|
||||
}
|
||||
|
||||
// OffsetsEqual returns true is all segments have the same marker-IDs and were
|
||||
// found at the same offsets.
|
||||
func (sl *SegmentList) OffsetsEqual(o *SegmentList) bool {
|
||||
if len(o.segments) != len(sl.segments) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, s := range o.segments {
|
||||
if s.MarkerId != sl.segments[i].MarkerId || s.Offset != sl.segments[i].Offset {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Segments returns the underlying slice of segments.
|
||||
func (sl *SegmentList) Segments() []*Segment {
|
||||
return sl.segments
|
||||
}
|
||||
|
||||
// Add adds another segment.
|
||||
func (sl *SegmentList) Add(s *Segment) {
|
||||
sl.segments = append(sl.segments, s)
|
||||
}
|
||||
|
||||
// Print prints segment info.
|
||||
func (sl *SegmentList) Print() {
|
||||
if len(sl.segments) == 0 {
|
||||
fmt.Printf("No segments.\n")
|
||||
} else {
|
||||
exifIndex, _, err := sl.FindExif()
|
||||
if err != nil {
|
||||
if err == exif.ErrNoExif {
|
||||
exifIndex = -1
|
||||
} else {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
xmpIndex, _, err := sl.FindXmp()
|
||||
if err != nil {
|
||||
if err == ErrNoXmp {
|
||||
xmpIndex = -1
|
||||
} else {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
iptcIndex, _, err := sl.FindIptc()
|
||||
if err != nil {
|
||||
if err == ErrNoIptc {
|
||||
iptcIndex = -1
|
||||
} else {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for i, s := range sl.segments {
|
||||
fmt.Printf("%2d: %s", i, s.EmbeddedString())
|
||||
|
||||
if i == exifIndex {
|
||||
fmt.Printf(" [EXIF]")
|
||||
} else if i == xmpIndex {
|
||||
fmt.Printf(" [XMP]")
|
||||
} else if i == iptcIndex {
|
||||
fmt.Printf(" [IPTC]")
|
||||
}
|
||||
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate checks that all of the markers are actually located at all of the
|
||||
// recorded offsets.
|
||||
func (sl *SegmentList) Validate(data []byte) (err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
if len(sl.segments) < 2 {
|
||||
log.Panicf("minimum segments not found")
|
||||
}
|
||||
|
||||
if sl.segments[0].MarkerId != MARKER_SOI {
|
||||
log.Panicf("first segment not SOI")
|
||||
} else if sl.segments[len(sl.segments)-1].MarkerId != MARKER_EOI {
|
||||
log.Panicf("last segment not EOI")
|
||||
}
|
||||
|
||||
lastOffset := 0
|
||||
for i, s := range sl.segments {
|
||||
if lastOffset != 0 && s.Offset <= lastOffset {
|
||||
log.Panicf("segment offset not greater than the last: SEGMENT=(%d) (0x%08x) <= (0x%08x)", i, s.Offset, lastOffset)
|
||||
}
|
||||
|
||||
// The scan-data doesn't start with a marker.
|
||||
if s.MarkerId == 0x0 {
|
||||
continue
|
||||
}
|
||||
|
||||
o := s.Offset
|
||||
if bytes.Compare(data[o:o+2], []byte{0xff, s.MarkerId}) != 0 {
|
||||
log.Panicf("segment offset does not point to the start of a segment: SEGMENT=(%d) (0x%08x)", i, s.Offset)
|
||||
}
|
||||
|
||||
lastOffset = o
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindExif returns the the segment that hosts the EXIF data (if present).
|
||||
func (sl *SegmentList) FindExif() (index int, segment *Segment, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
for i, s := range sl.segments {
|
||||
if s.IsExif() == true {
|
||||
return i, s, nil
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil, exif.ErrNoExif
|
||||
}
|
||||
|
||||
// FindXmp returns the the segment that hosts the XMP data (if present).
|
||||
func (sl *SegmentList) FindXmp() (index int, segment *Segment, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
for i, s := range sl.segments {
|
||||
if s.IsXmp() == true {
|
||||
return i, s, nil
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil, ErrNoXmp
|
||||
}
|
||||
|
||||
// FindIptc returns the the segment that hosts the IPTC data (if present).
|
||||
func (sl *SegmentList) FindIptc() (index int, segment *Segment, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
for i, s := range sl.segments {
|
||||
if s.IsIptc() == true {
|
||||
return i, s, nil
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil, ErrNoIptc
|
||||
}
|
||||
|
||||
// Exif returns an `exif.Ifd` instance for the EXIF data we currently have.
|
||||
func (sl *SegmentList) Exif() (rootIfd *exif.Ifd, rawExif []byte, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
_, s, err := sl.FindExif()
|
||||
log.PanicIf(err)
|
||||
|
||||
rootIfd, rawExif, err = s.Exif()
|
||||
log.PanicIf(err)
|
||||
|
||||
return rootIfd, rawExif, nil
|
||||
}
|
||||
|
||||
// Iptc returns embedded IPTC data if present.
|
||||
func (sl *SegmentList) Iptc() (tags map[iptc.StreamTagKey][]iptc.TagData, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
// TODO(dustin): Add comment and return data.
|
||||
|
||||
_, s, err := sl.FindIptc()
|
||||
log.PanicIf(err)
|
||||
|
||||
tags, err = s.Iptc()
|
||||
log.PanicIf(err)
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
// ConstructExifBuilder returns an `exif.IfdBuilder` instance (needed for
|
||||
// modifying) preloaded with all existing tags.
|
||||
func (sl *SegmentList) ConstructExifBuilder() (rootIb *exif.IfdBuilder, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
rootIfd, _, err := sl.Exif()
|
||||
log.PanicIf(err)
|
||||
|
||||
ib := exif.NewIfdBuilderFromExistingChain(rootIfd)
|
||||
|
||||
return ib, nil
|
||||
}
|
||||
|
||||
// DumpExif returns an unstructured list of tags (useful when just reviewing).
|
||||
func (sl *SegmentList) DumpExif() (segmentIndex int, segment *Segment, exifTags []exif.ExifTag, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
segmentIndex, s, err := sl.FindExif()
|
||||
if err != nil {
|
||||
if err == exif.ErrNoExif {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
exifTags, err = s.FlatExif()
|
||||
log.PanicIf(err)
|
||||
|
||||
return segmentIndex, s, exifTags, nil
|
||||
}
|
||||
|
||||
func makeEmptyExifSegment() (s *Segment) {
|
||||
|
||||
// TODO(dustin): Add test
|
||||
|
||||
return &Segment{
|
||||
MarkerId: MARKER_APP1,
|
||||
}
|
||||
}
|
||||
|
||||
// SetExif encodes and sets EXIF data into the given segment. If `index` is -1,
|
||||
// append a new segment.
|
||||
func (sl *SegmentList) SetExif(ib *exif.IfdBuilder) (err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
_, s, err := sl.FindExif()
|
||||
if err != nil {
|
||||
if log.Is(err, exif.ErrNoExif) == false {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
s = makeEmptyExifSegment()
|
||||
|
||||
prefix := sl.segments[:1]
|
||||
|
||||
// Install it near the beginning where we know it's safe. We can't
|
||||
// insert it after the EOI segment, and there might be more than one
|
||||
// depending on implementation and/or lax adherence to the standard.
|
||||
tail := append([]*Segment{s}, sl.segments[1:]...)
|
||||
|
||||
sl.segments = append(prefix, tail...)
|
||||
}
|
||||
|
||||
err = s.SetExif(ib)
|
||||
log.PanicIf(err)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DropExif will drop the EXIF data if present.
|
||||
func (sl *SegmentList) DropExif() (wasDropped bool, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
// TODO(dustin): Add test
|
||||
|
||||
i, _, err := sl.FindExif()
|
||||
if err == nil {
|
||||
// Found.
|
||||
sl.segments = append(sl.segments[:i], sl.segments[i+1:]...)
|
||||
|
||||
return true, nil
|
||||
} else if log.Is(err, exif.ErrNoExif) == false {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
// Not found.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Write writes the segment data to the given `io.Writer`.
|
||||
func (sl *SegmentList) Write(w io.Writer) (err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
offset := 0
|
||||
|
||||
for i, s := range sl.segments {
|
||||
h := sha1.New()
|
||||
h.Write(s.Data)
|
||||
|
||||
// The scan-data will have a marker-ID of (0) because it doesn't have a
|
||||
// marker-ID or length.
|
||||
if s.MarkerId != 0 {
|
||||
_, err := w.Write([]byte{0xff})
|
||||
log.PanicIf(err)
|
||||
|
||||
offset++
|
||||
|
||||
_, err = w.Write([]byte{s.MarkerId})
|
||||
log.PanicIf(err)
|
||||
|
||||
offset++
|
||||
|
||||
sizeLen, found := markerLen[s.MarkerId]
|
||||
if found == false || sizeLen == 2 {
|
||||
sizeLen = 2
|
||||
l := uint16(len(s.Data) + sizeLen)
|
||||
|
||||
err = binary.Write(w, binary.BigEndian, &l)
|
||||
log.PanicIf(err)
|
||||
|
||||
offset += 2
|
||||
} else if sizeLen == 4 {
|
||||
l := uint32(len(s.Data) + sizeLen)
|
||||
|
||||
err = binary.Write(w, binary.BigEndian, &l)
|
||||
log.PanicIf(err)
|
||||
|
||||
offset += 4
|
||||
} else if sizeLen != 0 {
|
||||
log.Panicf("not a supported marker-size: SEGMENT-INDEX=(%d) MARKER-ID=(0x%02x) MARKER-SIZE-LEN=(%d)", i, s.MarkerId, sizeLen)
|
||||
}
|
||||
}
|
||||
|
||||
_, err := w.Write(s.Data)
|
||||
log.PanicIf(err)
|
||||
|
||||
offset += len(s.Data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue