Commit e1254d74 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'fix-exif-on-multipart-uploads' into 'master'

Fix EXIF cleaning for S3 compatible Object Storage

See merge request gitlab-org/gitlab-workhorse!658
parents e6d86a89 18339264
---
title: Fix EXIF cleaning for S3 compatible Object Storage
merge_request:
author:
type: fixed
...@@ -15,19 +15,15 @@ import ( ...@@ -15,19 +15,15 @@ import (
var ErrRemovingExif = errors.New("error while removing EXIF") var ErrRemovingExif = errors.New("error while removing EXIF")
type cleaner struct { type cleaner struct {
ctx context.Context ctx context.Context
cmd *exec.Cmd cmd *exec.Cmd
stdout io.Reader stdout io.Reader
stderr bytes.Buffer stderr bytes.Buffer
waitDone chan struct{} eof bool
waitErr error
} }
func NewCleaner(ctx context.Context, stdin io.Reader) (io.Reader, error) { func NewCleaner(ctx context.Context, stdin io.Reader) (io.ReadCloser, error) {
c := &cleaner{ c := &cleaner{ctx: ctx}
ctx: ctx,
waitDone: make(chan struct{}),
}
if err := c.startProcessing(stdin); err != nil { if err := c.startProcessing(stdin); err != nil {
return nil, err return nil, err
...@@ -36,17 +32,32 @@ func NewCleaner(ctx context.Context, stdin io.Reader) (io.Reader, error) { ...@@ -36,17 +32,32 @@ func NewCleaner(ctx context.Context, stdin io.Reader) (io.Reader, error) {
return c, nil return c, nil
} }
func (c *cleaner) Close() error {
if c.cmd == nil {
return nil
}
return c.cmd.Wait()
}
func (c *cleaner) Read(p []byte) (int, error) { func (c *cleaner) Read(p []byte) (int, error) {
if c.eof {
return 0, io.EOF
}
n, err := c.stdout.Read(p) n, err := c.stdout.Read(p)
if err == io.EOF { if err == io.EOF {
if waitErr := c.wait(); waitErr != nil { if waitErr := c.cmd.Wait(); waitErr != nil {
log.WithContextFields(c.ctx, log.Fields{ log.WithContextFields(c.ctx, log.Fields{
"command": c.cmd.Args, "command": c.cmd.Args,
"stderr": c.stderr.String(), "stderr": c.stderr.String(),
"error": waitErr.Error(), "error": waitErr.Error(),
}).Print("exiftool command failed") }).Print("exiftool command failed")
return n, ErrRemovingExif return n, ErrRemovingExif
} }
c.eof = true
} }
return n, err return n, err
...@@ -85,19 +96,10 @@ func (c *cleaner) startProcessing(stdin io.Reader) error { ...@@ -85,19 +96,10 @@ func (c *cleaner) startProcessing(stdin io.Reader) error {
if err = c.cmd.Start(); err != nil { if err = c.cmd.Start(); err != nil {
return fmt.Errorf("start %v: %v", c.cmd.Args, err) return fmt.Errorf("start %v: %v", c.cmd.Args, err)
} }
go func() {
c.waitErr = c.cmd.Wait()
close(c.waitDone)
}()
return nil return nil
} }
func (c *cleaner) wait() error {
<-c.waitDone
return c.waitErr
}
func IsExifFile(filename string) bool { func IsExifFile(filename string) bool {
filenameMatch := regexp.MustCompile(`(?i)\.(jpg|jpeg|tiff)$`) filenameMatch := regexp.MustCompile(`(?i)\.(jpg|jpeg|tiff)$`)
......
...@@ -75,3 +75,21 @@ func TestNewCleanerWithInvalidFile(t *testing.T) { ...@@ -75,3 +75,21 @@ func TestNewCleanerWithInvalidFile(t *testing.T) {
require.Error(t, err, "Expected error when reading output") require.Error(t, err, "Expected error when reading output")
require.Equal(t, int64(0), size, "Size of invalid image should be 0") require.Equal(t, int64(0), size, "Size of invalid image should be 0")
} }
func TestNewCleanerReadingAfterEOF(t *testing.T) {
input, err := os.Open("testdata/sample_exif.jpg")
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cleaner, err := NewCleaner(ctx, input)
require.NoError(t, err, "Expected no error when creating cleaner command")
_, err = io.Copy(ioutil.Discard, cleaner)
require.NoError(t, err, "Expected no error when reading output")
buf := make([]byte, 1)
size, err := cleaner.Read(buf)
require.Equal(t, 0, size, "The output was already consumed by previous reads")
require.Equal(t, io.EOF, err, "We return EOF")
}
...@@ -174,12 +174,12 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string) (io.Rea ...@@ -174,12 +174,12 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string) (io.Rea
"filename": filename, "filename": filename,
}).Print("running exiftool to remove any metadata") }).Print("running exiftool to remove any metadata")
r, err := exif.NewCleaner(ctx, r) cleaner, err := exif.NewCleaner(ctx, r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return ioutil.NopCloser(r), nil return cleaner, nil
} }
func handleLsifUpload(ctx context.Context, reader io.Reader, tempPath, filename string, preauth *api.Response) (io.ReadCloser, error) { func handleLsifUpload(ctx context.Context, reader io.Reader, tempPath, filename string, preauth *api.Response) (io.ReadCloser, error) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment