From e6f340d2454abbcf212918661ee0e644a944ad66 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 27 Feb 2016 18:55:21 +0000 Subject: [PATCH] swift: Fix uploading of chunked files with non ascii characters - fixes #350 --- swift/swift.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/swift/swift.go b/swift/swift.go index ab317b852..17ea0359a 100644 --- a/swift/swift.go +++ b/swift/swift.go @@ -618,6 +618,23 @@ func (o *Object) removeSegments(except string) error { return nil } +// urlEncode encodes a string so that it is a valid URL +// +// We don't use any of Go's standard methods as we need `/` not +// encoded but we need '&' encoded. +func urlEncode(str string) string { + var buf bytes.Buffer + for i := 0; i < len(str); i++ { + c := str[i] + if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '/' || c == '.' { + _ = buf.WriteByte(c) + } else { + _, _ = buf.WriteString(fmt.Sprintf("%%%02X", c)) + } + } + return buf.String() +} + // updateChunks updates the existing object using chunks to a separate // container. It returns a string which prefixes current segments. func (o *Object) updateChunks(in io.Reader, headers swift.Headers, size int64) (string, error) { @@ -645,7 +662,7 @@ func (o *Object) updateChunks(in io.Reader, headers swift.Headers, size int64) ( i++ } // Upload the manifest - headers["X-Object-Manifest"] = fmt.Sprintf("%s/%s", o.fs.segmentsContainer, segmentsPath) + headers["X-Object-Manifest"] = urlEncode(fmt.Sprintf("%s/%s", o.fs.segmentsContainer, segmentsPath)) headers["Content-Length"] = "0" // set Content-Length as we know it emptyReader := bytes.NewReader(nil) manifestName := o.fs.root + o.remote