From b18595ae07473937de6c2dd8de90dd81376c47a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20B=C3=BCnger?= <buengese@gmail.com>
Date: Sun, 16 Sep 2018 22:30:20 +0200
Subject: [PATCH] jottacloud: Fix handling of reserved characters. fixes #2531

---
 backend/jottacloud/jottacloud.go   | 11 ++++++++---
 backend/jottacloud/replace.go      |  7 -------
 backend/jottacloud/replace_test.go |  4 ++--
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/backend/jottacloud/jottacloud.go b/backend/jottacloud/jottacloud.go
index aa433d2fa..1a478cbe5 100644
--- a/backend/jottacloud/jottacloud.go
+++ b/backend/jottacloud/jottacloud.go
@@ -199,7 +199,7 @@ func (f *Fs) readMetaDataForPath(path string) (info *api.JottaFile, err error) {
 func (f *Fs) getAccountInfo() (info *api.AccountInfo, err error) {
 	opts := rest.Opts{
 		Method: "GET",
-		Path:   rest.URLPathEscape(f.user),
+		Path:   urlPathEscape(f.user),
 	}
 
 	var resp *http.Response
@@ -220,7 +220,7 @@ func (f *Fs) setEndpointURL(mountpoint string) (err error) {
 	if err != nil {
 		return errors.Wrap(err, "failed to get endpoint url")
 	}
-	f.endpointURL = rest.URLPathEscape(path.Join(info.Username, defaultDevice, mountpoint))
+	f.endpointURL = urlPathEscape(path.Join(info.Username, defaultDevice, mountpoint))
 	return nil
 }
 
@@ -241,6 +241,11 @@ func errorHandler(resp *http.Response) error {
 	return errResponse
 }
 
+// Jottacloud want's '+' to be URL encoded even though the RFC states it's not reserved
+func urlPathEscape(in string) string {
+	return strings.Replace(rest.URLPathEscape(in), "+", "%2B", -1)
+}
+
 // filePathRaw returns an unescaped file path (f.root, file)
 func (f *Fs) filePathRaw(file string) string {
 	return path.Join(f.endpointURL, replaceReservedChars(path.Join(f.root, file)))
@@ -248,7 +253,7 @@ func (f *Fs) filePathRaw(file string) string {
 
 // filePath returns a escaped file path (f.root, file)
 func (f *Fs) filePath(file string) string {
-	return rest.URLPathEscape(f.filePathRaw(file))
+	return urlPathEscape(f.filePathRaw(file))
 }
 
 // filePath returns a escaped file path (f.root, remote)
diff --git a/backend/jottacloud/replace.go b/backend/jottacloud/replace.go
index c6622b33b..92f0ce051 100644
--- a/backend/jottacloud/replace.go
+++ b/backend/jottacloud/replace.go
@@ -27,21 +27,14 @@ import (
 var (
 	charMap = map[rune]rune{
 		'\\': '\', // FULLWIDTH REVERSE SOLIDUS
-		'+':  '+', // FULLWIDTH PLUS SIGN
 		'*':  '*', // FULLWIDTH ASTERISK
 		'<':  '<', // FULLWIDTH LESS-THAN SIGN
 		'>':  '>', // FULLWIDTH GREATER-THAN SIGN
 		'?':  '?', // FULLWIDTH QUESTION MARK
-		'!':  '!', // FULLWIDTH EXCLAMATION MARK
-		'&':  '&', // FULLWIDTH AMPERSAND
 		':':  ':', // FULLWIDTH COLON
 		';':  ';', // FULLWIDTH SEMICOLON
 		'|':  '|', // FULLWIDTH VERTICAL LINE
-		'#':  '#', // FULLWIDTH NUMBER SIGN
-		'%':  '%', // FULLWIDTH PERCENT SIGN
 		'"':  '"', // FULLWIDTH QUOTATION MARK - not on the list but seems to be reserved
-		'\'': ''', // FULLWIDTH APOSTROPHE
-		'~':  '~', // FULLWIDTH TILDE
 		' ':  '␠', // SYMBOL FOR SPACE
 	}
 	invCharMap           map[rune]rune
diff --git a/backend/jottacloud/replace_test.go b/backend/jottacloud/replace_test.go
index 38d1308e2..b1f2979b8 100644
--- a/backend/jottacloud/replace_test.go
+++ b/backend/jottacloud/replace_test.go
@@ -9,8 +9,8 @@ func TestReplace(t *testing.T) {
 	}{
 		{"", ""},
 		{"abc 123", "abc 123"},
-		{`\+*<>?!&:;|#%"'~`, `\+*<>?!&:;|#%"'~`},
-		{`\+*<>?!&:;|#%"'~\+*<>?!&:;|#%"'~`, `\+*<>?!&:;|#%"'~\+*<>?!&:;|#%"'~`},
+		{`\*<>?:;|"`, `\*<>?:;|"`},
+		{`\*<>?:;|"\*<>?:;|"`, `\*<>?:;|"\*<>?:;|"`},
 		{" leading space", "␠leading space"},
 		{"trailing space ", "trailing space␠"},
 		{" leading space/ leading space/ leading space", "␠leading space/␠leading space/␠leading space"},