# HG changeset patch # User Mikael Berthe # Date 1527533470 -7200 # Node ID 212a0e74e71903d3902e54e223be527e43531e0f # Parent 9aa1cb3e1dee50be04fd02db55c658098f7a4c43 Don't use base64 encoding for header & avatar uploads This should fix https://github.com/McKael/madonctl/issues/14. diff -r 9aa1cb3e1dee -r 212a0e74e719 account.go --- a/account.go Wed Mar 21 22:43:32 2018 +0100 +++ b/account.go Mon May 28 20:51:10 2018 +0200 @@ -8,14 +8,12 @@ import ( "bytes" - "encoding/base64" "encoding/json" "fmt" "mime/multipart" - "net/http" "os" + "path/filepath" "strconv" - "strings" "github.com/pkg/errors" "github.com/sendgrid/rest" @@ -402,14 +400,17 @@ } // UpdateAccount updates the connected user's account data -// The fields avatar & headerImage can contain base64-encoded images; if -// they do not (that is; if they don't contain ";base64,"), they are considered -// as file paths and their content will be encoded. +// +// The fields avatar & headerImage are considered as file paths +// and their content will be uploaded. +// Please note that currently Mastodon leaks the avatar file name: +// https://github.com/tootsuite/mastodon/issues/5776 +// // Setting 'locked' to true means all followers should be approved. // All fields can be nil, in which case they are not updated. // displayName and note can be set to "" to delete previous values; // I'm not sure images can be deleted -- only replaced AFAICS. -func (mc *Client) UpdateAccount(displayName, note, avatar, headerImage *string, locked *bool) (*Account, error) { +func (mc *Client) UpdateAccount(displayName, note, avatarImagePath, headerImagePath *string, locked *bool) (*Account, error) { const endPoint = "accounts/update_credentials" params := make(apiCallParams) @@ -428,11 +429,14 @@ } var err error - avatar, err = fileToBase64(avatar, nil) + var avatar, headerImage []byte + + avatar, err = readFile(avatarImagePath) if err != nil { return nil, err } - headerImage, err = fileToBase64(headerImage, nil) + + headerImage, err = readFile(headerImagePath) if err != nil { return nil, err } @@ -441,10 +445,18 @@ w := multipart.NewWriter(&formBuf) if avatar != nil { - w.WriteField("avatar", *avatar) + formWriter, err := w.CreateFormFile("avatar", filepath.Base(*avatarImagePath)) + if err != nil { + return nil, errors.Wrap(err, "avatar upload") + } + formWriter.Write(avatar) } if headerImage != nil { - w.WriteField("header", *headerImage) + formWriter, err := w.CreateFormFile("header", filepath.Base(*headerImagePath)) + if err != nil { + return nil, errors.Wrap(err, "header upload") + } + formWriter.Write(headerImage) } w.Close() @@ -479,26 +491,13 @@ return &account, nil } -// fileToBase64 is a helper function to convert a file's contents to -// base64-encoded data. Is the data string already contains base64 data, it -// is not modified. -// If contentType is nil, it is detected. -func fileToBase64(data, contentType *string) (*string, error) { - if data == nil { +// readFile is a helper function to read a file's contents. +func readFile(filename *string) ([]byte, error) { + if filename == nil || *filename == "" { return nil, nil } - if *data == "" { - return data, nil - } - - if strings.Contains(*data, ";base64,") { - return data, nil - } - - // We need to convert the file and file name to base64 - - file, err := os.Open(*data) + file, err := os.Open(*filename) if err != nil { return nil, err } @@ -515,13 +514,5 @@ return nil, err } - var cType string - if contentType == nil || *contentType == "" { - cType = http.DetectContentType(buffer[:512]) - } else { - cType = *contentType - } - contentData := base64.StdEncoding.EncodeToString(buffer) - newData := "data:" + cType + ";base64," + contentData - return &newData, nil + return buffer, nil }