From 12b4a2638518bebc6edeaebcfa8a5c669645cd58 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Thu, 29 Apr 2021 11:58:50 +0200 Subject: [PATCH] implement thumbnail support for txt files --- changelog/unreleased/thumbnails-for-txt.md | 5 + ocis/go.sum | 1 + ocs/go.mod | 4 +- .../expected-failures-API-on-OCIS-storage.md | 6 +- ...pected-failures-API-on-OWNCLOUD-storage.md | 6 +- .../apiWebdavPreviews-previews.feature | 13 +-- thumbnails/go.mod | 2 + thumbnails/go.sum | 1 + thumbnails/pkg/preprocessor/preprocessor.go | 106 ++++++++++++++++++ thumbnails/pkg/service/v0/service.go | 22 ++-- thumbnails/pkg/thumbnail/imgsource/cs3.go | 15 +-- .../pkg/thumbnail/imgsource/filesystem.go | 11 +- .../pkg/thumbnail/imgsource/imgsource.go | 4 +- thumbnails/pkg/thumbnail/imgsource/webdav.go | 14 +-- thumbnails/pkg/thumbnail/thumbnail.go | 8 +- webdav/go.sum | 1 + 16 files changed, 160 insertions(+), 59 deletions(-) create mode 100644 changelog/unreleased/thumbnails-for-txt.md create mode 100644 thumbnails/pkg/preprocessor/preprocessor.go diff --git a/changelog/unreleased/thumbnails-for-txt.md b/changelog/unreleased/thumbnails-for-txt.md new file mode 100644 index 00000000000..5e1ac643777 --- /dev/null +++ b/changelog/unreleased/thumbnails-for-txt.md @@ -0,0 +1,5 @@ +Enhancement: Support thumbnails for txt files + +Implemented support for thumbnails for txt files in the thumbnails service. + +https://github.com/owncloud/ocis/pull/1988 diff --git a/ocis/go.sum b/ocis/go.sum index c7d221e2025..86f7a7b292b 100644 --- a/ocis/go.sum +++ b/ocis/go.sum @@ -669,6 +669,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/gddo v0.0.0-20180828051604-96d2a289f41e/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= diff --git a/ocs/go.mod b/ocs/go.mod index c573fbdb87d..0ea61bfe009 100644 --- a/ocs/go.mod +++ b/ocs/go.mod @@ -22,14 +22,14 @@ require ( github.com/owncloud/ocis/proxy v0.0.0-20210412105747-9b95e9b1191b github.com/owncloud/ocis/settings v0.0.0-20210413063522-955bd60edf33 github.com/owncloud/ocis/store v0.0.0-20210413063522-955bd60edf33 - github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.10.0 github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/thejerf/suture/v4 v4.0.0 go.opencensus.io v0.23.0 google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea - google.golang.org/grpc v1.37.0 // indirect + google.golang.org/grpc v1.37.0 google.golang.org/protobuf v1.26.0 ) diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index 8420b39e0ac..5a3cb63c762 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -801,16 +801,14 @@ cannot share a folder with create permission #### [Previews via webDAV API tests fail on OCIS](https://github.com/owncloud/ocis/issues/187) - [apiWebdavPreviews/previews.feature:15](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L15) -- [apiWebdavPreviews/previews.feature:16](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L16) - [apiWebdavPreviews/previews.feature:17](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L17) - [apiWebdavPreviews/previews.feature:18](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L18) - [apiWebdavPreviews/previews.feature:19](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L19) -- [apiWebdavPreviews/previews.feature:56](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L56) -- [apiWebdavPreviews/previews.feature:87](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L87) - [apiWebdavPreviews/previews.feature:95](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L95) - [apiWebdavPreviews/previews.feature:104](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L104) - [apiWebdavPreviews/previews.feature:113](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L113) -- [apiWebdavPreviews/previews.feature:163](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L163) +- [apiWebdavPreviews/previews.feature:127](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L127) +- [apiWebdavPreviews/previews.feature:135](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L135) - [apiWebdavPreviews/previews.feature:164](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L164) - [apiWebdavPreviews/previews.feature:165](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L165) - [apiWebdavPreviews/previews.feature:166](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L166) diff --git a/tests/acceptance/expected-failures-API-on-OWNCLOUD-storage.md b/tests/acceptance/expected-failures-API-on-OWNCLOUD-storage.md index a9e2ebeec0c..9a2f79853fe 100644 --- a/tests/acceptance/expected-failures-API-on-OWNCLOUD-storage.md +++ b/tests/acceptance/expected-failures-API-on-OWNCLOUD-storage.md @@ -825,16 +825,14 @@ cannot share a folder with create permission #### [Previews via webDAV API tests fail on OCIS](https://github.com/owncloud/ocis/issues/187) - [apiWebdavPreviews/previews.feature:15](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L15) -- [apiWebdavPreviews/previews.feature:16](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L16) - [apiWebdavPreviews/previews.feature:17](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L17) - [apiWebdavPreviews/previews.feature:18](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L18) - [apiWebdavPreviews/previews.feature:19](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L19) -- [apiWebdavPreviews/previews.feature:56](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L56) -- [apiWebdavPreviews/previews.feature:87](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L87) - [apiWebdavPreviews/previews.feature:95](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L95) - [apiWebdavPreviews/previews.feature:104](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L104) - [apiWebdavPreviews/previews.feature:113](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L113) -- [apiWebdavPreviews/previews.feature:163](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L163) +- [apiWebdavPreviews/previews.feature:127](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L127) +- [apiWebdavPreviews/previews.feature:135](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L135) - [apiWebdavPreviews/previews.feature:164](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L164) - [apiWebdavPreviews/previews.feature:165](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L165) - [apiWebdavPreviews/previews.feature:166](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L166) diff --git a/tests/acceptance/features/apiBugDemonstration/apiWebdavPreviews-previews.feature b/tests/acceptance/features/apiBugDemonstration/apiWebdavPreviews-previews.feature index 1740e5395a5..564b9641539 100644 --- a/tests/acceptance/features/apiBugDemonstration/apiWebdavPreviews-previews.feature +++ b/tests/acceptance/features/apiBugDemonstration/apiWebdavPreviews-previews.feature @@ -36,15 +36,6 @@ Feature: previews of files downloaded through the webdav API | A | | %2F | - @issue-ocis-187 - # after fixing all issues delete this Scenario and use the one from oC10 core - Scenario: download previews of image after renaming it - Given user "Alice" has uploaded file "filesForUpload/testavatar.jpg" to "/testimage.jpg" - When user "Alice" moves file "/testimage.jpg" to "/testimage.txt" using the WebDAV API - And user "Alice" downloads the preview of "/testimage.txt" with width "32" and height "32" using the WebDAV API - Then the HTTP status code should be "404" - # And the downloaded image should be "1240" pixels wide and "648" pixels high - @issue-ocis-thumbnails-191 @skipOnOcis-EOS-Storage @issue-ocis-reva-308 # after fixing all issues delete this Scenario and use the one from oC10 core Scenario: download previews of other users files @@ -66,7 +57,7 @@ Feature: previews of files downloaded through the webdav API Given the administrator has updated system config key "enable_previews" with value "false" and type "boolean" And user "Alice" has uploaded file "filesForUpload/lorem.txt" to "/parent.txt" When user "Alice" downloads the preview of "/parent.txt" with width "32" and height "32" using the WebDAV API - Then the HTTP status code should be "404" + Then the HTTP status code should be "200" @issue-ocis-193 # after fixing all issues delete this Scenario and use the one from oC10 core @@ -75,7 +66,7 @@ Feature: previews of files downloaded through the webdav API And the administrator has updated system config key "preview_max_x" with value "null" And the administrator has updated system config key "preview_max_y" with value "null" When user "Alice" downloads the preview of "/parent.txt" with width "32" and height "32" using the WebDAV API - Then the HTTP status code should be "404" + Then the HTTP status code should be "200" @issue-ocis-193 # after fixing all issues delete this Scenario and use the one from oC10 core diff --git a/thumbnails/go.mod b/thumbnails/go.mod index b31acf173f7..ad23ecd1f07 100644 --- a/thumbnails/go.mod +++ b/thumbnails/go.mod @@ -10,6 +10,7 @@ require ( github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535 github.com/cs3org/reva v1.6.1-0.20210414111318-a4b5148cbfb2 github.com/disintegration/imaging v1.6.2 + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/golang/protobuf v1.5.2 github.com/grpc-ecosystem/grpc-gateway/v2 v2.2.0 github.com/micro/cli/v2 v2.1.2 @@ -23,6 +24,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/thejerf/suture/v4 v4.0.0 go.opencensus.io v0.23.0 + golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 google.golang.org/grpc v1.37.0 google.golang.org/protobuf v1.26.0 ) diff --git a/thumbnails/go.sum b/thumbnails/go.sum index f0bb6b76f3e..d4b4520c7fd 100644 --- a/thumbnails/go.sum +++ b/thumbnails/go.sum @@ -665,6 +665,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/gddo v0.0.0-20180828051604-96d2a289f41e/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= diff --git a/thumbnails/pkg/preprocessor/preprocessor.go b/thumbnails/pkg/preprocessor/preprocessor.go new file mode 100644 index 00000000000..b0d22d8e3ec --- /dev/null +++ b/thumbnails/pkg/preprocessor/preprocessor.go @@ -0,0 +1,106 @@ +package preprocessor + +import ( + "bufio" + "github.com/golang/freetype" + "github.com/golang/freetype/truetype" + "github.com/pkg/errors" + "golang.org/x/image/font" + "golang.org/x/image/font/gofont/goregular" + "image" + "image/draw" + "io" + "mime" + "strings" +) + +const ( + fontSize = 12 + spacing float64 = 1.5 +) + +type FileConverter interface { + Convert(r io.Reader) (image.Image, error) +} + +type ImageDecoder struct{} + +func (i ImageDecoder) Convert(r io.Reader) (image.Image, error) { + img, _, err := image.Decode(r) + if err != nil { + return nil, errors.Wrap(err, `could not decode the image`) + } + return img, nil +} + +type TxtToImageConverter struct{} + +func (t TxtToImageConverter) Convert(r io.Reader) (image.Image, error) { + img := image.NewRGBA(image.Rect(0, 0, 640, 480)) + draw.Draw(img, img.Bounds(), image.White, image.Point{}, draw.Src) + + c := freetype.NewContext() + // Ignoring the error since we are using the embedded Golang font. + // This shouldn't return an error. + f, _ := truetype.Parse(goregular.TTF) + c.SetFont(f) + c.SetFontSize(fontSize) + c.SetClip(img.Bounds()) + c.SetDst(img) + c.SetSrc(image.Black) + c.SetHinting(font.HintingFull) + pt := freetype.Pt(10, 10+int(c.PointToFixed(fontSize)>>6)) + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + txt := scanner.Text() + cs := chunks(txt, 80) + for _, s := range cs { + _, err := c.DrawString(strings.TrimSpace(s), pt) + if err != nil { + return nil, err + } + pt.Y += c.PointToFixed(fontSize * spacing) + if pt.Y.Round() >= img.Bounds().Dy() { + return img, scanner.Err() + } + } + + } + return img, scanner.Err() +} + +// Code from https://stackoverflow.com/a/61469854 +// Written By Igor Mikushkin +func chunks(s string, chunkSize int) []string { + if chunkSize >= len(s) { + return []string{s} + } + var chunks []string + chunk := make([]rune, chunkSize) + length := 0 + for _, r := range s { + chunk[length] = r + length++ + if length == chunkSize { + chunks = append(chunks, string(chunk)) + length = 0 + } + } + if length > 0 { + chunks = append(chunks, string(chunk[:length])) + } + return chunks +} + +func ForType(mimeType string) FileConverter { + // We can ignore the error here because we parse it in IsMimeTypeSupported before and if it fails + // return the service call. So we should only get here when the mimeType parses fine. + mimeType, _, _ = mime.ParseMediaType(mimeType) + switch mimeType { + case "text/plain": + return TxtToImageConverter{} + default: + return ImageDecoder{} + } +} diff --git a/thumbnails/pkg/service/v0/service.go b/thumbnails/pkg/service/v0/service.go index 45adfa92314..227196cd9b0 100644 --- a/thumbnails/pkg/service/v0/service.go +++ b/thumbnails/pkg/service/v0/service.go @@ -8,6 +8,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/token" "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/owncloud/ocis/thumbnails/pkg/preprocessor" v0proto "github.com/owncloud/ocis/thumbnails/pkg/proto/v0" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail/imgsource" @@ -105,12 +106,15 @@ func (g Thumbnail) handleCS3Source(ctx context.Context, req *v0proto.GetThumbnai } ctx = imgsource.ContextSetAuthorization(ctx, src.Authorization) - img, err := g.cs3Source.Get(ctx, src.Path) + r, err := g.cs3Source.Get(ctx, src.Path) if err != nil { return nil, merrors.InternalServerError(g.serviceID, "could not get image from source: %s", err.Error()) } - if img == nil { - return nil, merrors.InternalServerError(g.serviceID, "could not get image from source") + defer r.Close() // nolint:errcheck + pp := preprocessor.ForType(sRes.GetInfo().GetMimeType()) + img, err := pp.Convert(r) + if img == nil || err != nil { + return nil, merrors.InternalServerError(g.serviceID, "could not get image") } if thumb, err = g.manager.Generate(tr, img); err != nil { return nil, err @@ -176,12 +180,15 @@ func (g Thumbnail) handleWebdavSource(ctx context.Context, req *v0proto.GetThumb ctx = imgsource.ContextSetAuthorization(ctx, src.WebdavAuthorization) } imgURL.RawQuery = "" - img, err := g.webdavSource.Get(ctx, imgURL.String()) + r, err := g.webdavSource.Get(ctx, imgURL.String()) if err != nil { return nil, merrors.InternalServerError(g.serviceID, "could not get image from source: %s", err.Error()) } - if img == nil { - return nil, merrors.InternalServerError(g.serviceID, "could not get image from source") + defer r.Close() // nolint:errcheck + pp := preprocessor.ForType(sRes.GetInfo().GetMimeType()) + img, err := pp.Convert(r) + if img == nil || err != nil { + return nil, merrors.InternalServerError(g.serviceID, "could not get image") } if thumb, err = g.manager.Generate(tr, img); err != nil { return nil, err @@ -223,8 +230,5 @@ func (g Thumbnail) stat(path, auth string) (*provider.StatResponse, error) { if !thumbnail.IsMimeTypeSupported(rsp.Info.MimeType) { return nil, merrors.NotFound(g.serviceID, "Unsupported file type") } - - - return rsp, nil } diff --git a/thumbnails/pkg/thumbnail/imgsource/cs3.go b/thumbnails/pkg/thumbnail/imgsource/cs3.go index 11689952f76..68de7cdf6fd 100644 --- a/thumbnails/pkg/thumbnail/imgsource/cs3.go +++ b/thumbnails/pkg/thumbnail/imgsource/cs3.go @@ -11,7 +11,7 @@ import ( "github.com/cs3org/reva/pkg/token" "github.com/pkg/errors" "google.golang.org/grpc/metadata" - "image" + "io" "net/http" ) @@ -25,7 +25,9 @@ func NewCS3Source(c gateway.GatewayAPIClient) CS3 { } } -func (s CS3) Get(ctx context.Context, path string) (image.Image, error) { +// Get downloads the file from a cs3 service +// The caller MUST make sure to close the returned ReadCloser +func (s CS3) Get(ctx context.Context, path string) (io.ReadCloser, error) { auth, ok := ContextGetAuthorization(ctx) if !ok { return nil, errors.New("cs3source: authorization missing") @@ -63,19 +65,14 @@ func (s CS3) Get(ctx context.Context, path string) (image.Image, error) { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec client := &http.Client{} - resp, err := client.Do(httpReq) + resp, err := client.Do(httpReq) // nolint:bodyclose if err != nil { return nil, err } - defer resp.Body.Close() //nolint:errcheck if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("could not get the image \"%s\". Request returned with statuscode %d ", path, resp.StatusCode) } - img, _, err := image.Decode(resp.Body) - if err != nil { - return nil, errors.Wrapf(err, `could not decode the image "%s"`, path) - } - return img, nil + return resp.Body, nil } diff --git a/thumbnails/pkg/thumbnail/imgsource/filesystem.go b/thumbnails/pkg/thumbnail/imgsource/filesystem.go index f809ba30b92..68f0ce35b25 100644 --- a/thumbnails/pkg/thumbnail/imgsource/filesystem.go +++ b/thumbnails/pkg/thumbnail/imgsource/filesystem.go @@ -2,7 +2,7 @@ package imgsource import ( "context" - "image" + "io" "os" "path/filepath" @@ -23,17 +23,12 @@ type FileSystem struct { } // Get retrieves an image from the filesystem. -func (s FileSystem) Get(ctx context.Context, file string) (image.Image, error) { +func (s FileSystem) Get(ctx context.Context, file string) (io.ReadCloser, error) { imgPath := filepath.Join(s.basePath, file) f, err := os.Open(filepath.Clean(imgPath)) if err != nil { return nil, errors.Wrapf(err, "failed to load the file %s from %s", file, imgPath) } - img, _, err := image.Decode(f) - if err != nil { - return nil, errors.Wrap(err, "Get: Decode:") - } - - return img, nil + return f, nil } diff --git a/thumbnails/pkg/thumbnail/imgsource/imgsource.go b/thumbnails/pkg/thumbnail/imgsource/imgsource.go index 394836a8002..77c274bf2d7 100644 --- a/thumbnails/pkg/thumbnail/imgsource/imgsource.go +++ b/thumbnails/pkg/thumbnail/imgsource/imgsource.go @@ -2,7 +2,7 @@ package imgsource import ( "context" - "image" + "io" ) type key int @@ -13,7 +13,7 @@ const ( // Source defines the interface for image sources type Source interface { - Get(ctx context.Context, path string) (image.Image, error) + Get(ctx context.Context, path string) (io.ReadCloser, error) } // ContextSetAuthorization puts the authorization in the context. diff --git a/thumbnails/pkg/thumbnail/imgsource/webdav.go b/thumbnails/pkg/thumbnail/imgsource/webdav.go index 7c340a35685..ea95ea32aea 100644 --- a/thumbnails/pkg/thumbnail/imgsource/webdav.go +++ b/thumbnails/pkg/thumbnail/imgsource/webdav.go @@ -6,10 +6,10 @@ import ( "fmt" "github.com/owncloud/ocis/thumbnails/pkg/config" "github.com/pkg/errors" - "image" _ "image/gif" // Import the gif package so that image.Decode can understand gifs _ "image/jpeg" // Import the jpeg package so that image.Decode can understand jpegs _ "image/png" // Import the png package so that image.Decode can understand pngs + "io" "net/http" ) @@ -26,7 +26,8 @@ type WebDav struct { } // Get downloads the file from a webdav service -func (s WebDav) Get(ctx context.Context, url string) (image.Image, error) { +// The caller MUST make sure to close the returned ReadCloser +func (s WebDav) Get(ctx context.Context, url string) (io.ReadCloser, error) { req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, errors.Wrapf(err, `could not get the image "%s"`, url) @@ -39,19 +40,14 @@ func (s WebDav) Get(ctx context.Context, url string) (image.Image, error) { } client := &http.Client{} - resp, err := client.Do(req) + resp, err := client.Do(req) // nolint:bodyclose if err != nil { return nil, errors.Wrapf(err, `could not get the image "%s"`, url) } - defer resp.Body.Close() //nolint:errcheck if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("could not get the image \"%s\". Request returned with statuscode %d ", url, resp.StatusCode) } - img, _, err := image.Decode(resp.Body) - if err != nil { - return nil, errors.Wrapf(err, `could not decode the image "%s"`, url) - } - return img, nil + return resp.Body, nil } diff --git a/thumbnails/pkg/thumbnail/thumbnail.go b/thumbnails/pkg/thumbnail/thumbnail.go index e976c62a44c..815c8928a33 100644 --- a/thumbnails/pkg/thumbnail/thumbnail.go +++ b/thumbnails/pkg/thumbnail/thumbnail.go @@ -6,6 +6,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail/storage" "image" + "mime" "strings" ) @@ -15,6 +16,7 @@ var ( "image/jpg", "image/jpeg", "image/gif", + "text/plain", } ) @@ -90,8 +92,12 @@ func mapToStorageRequest(r Request) storage.Request { } func IsMimeTypeSupported(m string) bool { + mimeType, _, err := mime.ParseMediaType(m) + if err != nil { + return false + } for _, mt := range SupportedMimeTypes { - if strings.EqualFold(mt, m) { + if strings.EqualFold(mt, mimeType) { return true } } diff --git a/webdav/go.sum b/webdav/go.sum index 20a82edbb20..7b1c8b99cf7 100644 --- a/webdav/go.sum +++ b/webdav/go.sum @@ -665,6 +665,7 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/gddo v0.0.0-20180828051604-96d2a289f41e/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=