Welcome to mirror list, hosted at ThFree Co, Russian Federation.

exif.go « upload « internal « workhorse - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e77afb24502e19664e4ff759ca32ee834bbd8867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package upload

import (
	"context"
	"io"
	"net/http"
	"os"

	"gitlab.com/gitlab-org/labkit/log"
	"golang.org/x/image/tiff"

	"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/exif"
)

func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageType exif.FileType) (io.ReadCloser, error) {
	tmpfile, err := os.CreateTemp("", "exifremove")
	if err != nil {
		return nil, err
	}
	go func() {
		<-ctx.Done()
		tmpfile.Close()
	}()
	if err := os.Remove(tmpfile.Name()); err != nil {
		return nil, err
	}

	_, err = io.Copy(tmpfile, r)
	if err != nil {
		return nil, err
	}

	if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
		return nil, err
	}

	isValidType := false
	switch imageType {
	case exif.TypeJPEG:
		isValidType = isJPEG(tmpfile)
	case exif.TypeTIFF:
		isValidType = isTIFF(tmpfile)
	}

	if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
		return nil, err
	}

	if !isValidType {
		log.WithContextFields(ctx, log.Fields{
			"filename":  filename,
			"imageType": imageType,
		}).Info("invalid content type, not running exiftool")

		return tmpfile, nil
	}

	log.WithContextFields(ctx, log.Fields{
		"filename": filename,
	}).Info("running exiftool to remove any metadata")

	cleaner, err := exif.NewCleaner(ctx, tmpfile)
	if err != nil {
		return nil, err
	}

	return cleaner, nil
}

func isTIFF(r io.Reader) bool {
	_, err := tiff.DecodeConfig(r)
	if err == nil {
		return true
	}

	if _, unsupported := err.(tiff.UnsupportedError); unsupported {
		return true
	}

	return false
}

func isJPEG(r io.Reader) bool {
	// Only the first 512 bytes are used to sniff the content type.
	buf, err := io.ReadAll(io.LimitReader(r, 512))
	if err != nil {
		return false
	}

	return http.DetectContentType(buf) == "image/jpeg"
}