Skip to content

Commit

Permalink
Fix profile image webp issue (#551)
Browse files Browse the repository at this point in the history
  • Loading branch information
lazynina authored Mar 12, 2024
1 parent 1642c89 commit f4d1970
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 17 deletions.
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ require (
github.com/stretchr/testify v1.8.0
github.com/tyler-smith/go-bip39 v1.1.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/image v0.15.0
golang.org/x/sync v0.1.0
google.golang.org/api v0.46.0
gopkg.in/DataDog/dd-trace-go.v1 v1.29.0
)
Expand Down Expand Up @@ -108,13 +109,13 @@ require (
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c // indirect
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
golang.org/x/tools v0.1.5 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab // indirect
Expand Down
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,10 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand All @@ -655,6 +658,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -703,6 +707,8 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -729,6 +735,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -792,6 +800,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -802,6 +812,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -862,6 +874,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
5 changes: 4 additions & 1 deletion routes/global_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,10 @@ func (gs *GlobalState) Get(key []byte) (value []byte, _err error) {
err := gs.GlobalStateDB.View(func(txn *badger.Txn) error {
item, err := txn.Get(key)
if err != nil {
return nil
if errors.Is(err, badger.ErrKeyNotFound) {
return nil
}
return err
}
retValue, err = item.ValueCopy(nil)
if err != nil {
Expand Down
30 changes: 21 additions & 9 deletions routes/media.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"golang.org/x/image/webp"
"image"
"io"
"net/http"
Expand Down Expand Up @@ -51,7 +53,7 @@ func (fes *APIServer) uploadSingleImage(image string, extension string) (_imageU

if extension != ".gif" {
var imageBytes []byte
imageBytes, err = resizeAndConvertFromEncodedImageContent(image, 1000)
imageBytes, err = resizeAndConvertFromEncodedImageContent(image, 1000, extension)
if err != nil {
return "", err
}
Expand All @@ -78,36 +80,46 @@ func getEncodedImageContent(encodedImageString string) string {
return encodedImageString[strings.Index(encodedImageString, ",")+1:]
}

func resizeAndConvertToWebp(encodedImageString string, maxDim uint) (_image []byte, _err error) {
func resizeAndConvertToWebp(encodedImageString string, maxDim uint, extension string) (_image []byte, _err error) {
// Extract the relevant portion of the base64 encoded string and process the image.
encodedImageContent := getEncodedImageContent(encodedImageString)
return resizeAndConvertFromEncodedImageContent(encodedImageContent, maxDim)
return resizeAndConvertFromEncodedImageContent(encodedImageContent, maxDim, extension)

}

// Prevent pixel flood attack. This function checks the image size before processing it.
// Reference: https://github.com/h2non/bimg/issues/394#issuecomment-1015932411
func validateImageSize(encodedImageContentBytes []byte) error {
func validateImageSize(encodedImageContentBytes []byte, extension string) error {
byteReader := bytes.NewReader(encodedImageContentBytes)
imageConfig, _, err := image.DecodeConfig(byteReader)
var imageConfig image.Config
var err error
if extension == ".webp" {
imageConfig, err = webp.DecodeConfig(byteReader)
} else {
imageConfig, _, err = image.DecodeConfig(byteReader)
}
if err != nil {
return err
return errors.Wrap(err, "validateImageSize: Problem decoding image config")
}
if imageConfig.Width > bimg.MaxSize || imageConfig.Height > bimg.MaxSize {
return fmt.Errorf("image too large. Max dimensions are %v x %v. ImageConfig dimensions are %v x %v",
return fmt.Errorf("validateImageSize: image too large. Max dimensions are %v x %v. ImageConfig dimensions are %v x %v",
bimg.MaxSize, bimg.MaxSize, imageConfig.Width, imageConfig.Height)
}
return nil
}

func resizeAndConvertFromEncodedImageContent(encodedImageContent string, maxDim uint) (_image []byte, _err error) {
func resizeAndConvertFromEncodedImageContent(
encodedImageContent string,
maxDim uint,
extension string,
) (_image []byte, _err error) {
// always strip metadata
processOptions := bimg.Options{StripMetadata: true}
decodedBytes, err := base64.StdEncoding.DecodeString(encodedImageContent)
if err != nil {
return nil, err
}
if err = validateImageSize(decodedBytes); err != nil {
if err = validateImageSize(decodedBytes, extension); err != nil {
return nil, err
}
imgBytes, err := bimg.NewImage(decodedBytes).Process(processOptions)
Expand Down
23 changes: 22 additions & 1 deletion routes/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,29 @@ func (fes *APIServer) UpdateProfile(ww http.ResponseWriter, req *http.Request) {
// If an image is set on the request then resize it.
// Convert image to base64 by stripping the data: prefix.
if requestData.NewProfilePic != "" {
// split on base64 to get the extension
extensionSplit := strings.Split(requestData.NewProfilePic, ";base64")
if len(extensionSplit) != 2 {
_AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Problem parsing profile pic extension: %v", err))
return
}
extension := extensionSplit[0]
switch {
case strings.Contains(extension, "image/png"):
extension = ".png"
case strings.Contains(extension, "image/jpeg"):
extension = ".jpeg"
case strings.Contains(extension, "image/webp"):
extension = ".webp"
case strings.Contains(extension, "image/gif"):
extension = ".gif"
default:
_AddBadRequestError(ww, fmt.Sprintf("UpdateProfile: Unsupported image type: %v", extension))
return
}
var resizedImageBytes []byte
resizedImageBytes, err = resizeAndConvertToWebp(requestData.NewProfilePic, uint(fes.Params.MaxProfilePicDimensions))
resizedImageBytes, err = resizeAndConvertToWebp(
requestData.NewProfilePic, uint(fes.Params.MaxProfilePicDimensions), extension)
if err != nil {
_AddBadRequestError(ww, fmt.Sprintf("Problem resizing profile picture: %v", err))
return
Expand Down

0 comments on commit f4d1970

Please sign in to comment.