]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Change default webseed path escaping to work for all S3-compatible providers
authorMatt Joiner <anacrolix@gmail.com>
Fri, 23 Dec 2022 00:18:36 +0000 (11:18 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Fri, 23 Dec 2022 00:18:36 +0000 (11:18 +1100)
webseed/request.go
webseed/request_test.go

index a38e6372952357a7a8ea9d723bcafa84086bb887..e7c28155fbdc8eb76f9c930b0977eb049cdeb96f 100644 (file)
@@ -24,7 +24,12 @@ func EscapePath(pathComps []string) string {
 func defaultPathEscaper(pathComps []string) string {
        var ret []string
        for _, comp := range pathComps {
-               ret = append(ret, url.QueryEscape(comp))
+               esc := url.PathEscape(comp)
+               // S3 incorrectly escapes + in paths to spaces, so we add an extra encoding for that. This
+               // seems to be handled correctly regardless of whether an endpoint uses query or path
+               // escaping.
+               esc = strings.ReplaceAll(esc, "+", "%2B")
+               ret = append(ret, esc)
        }
        return path.Join(ret...)
 }
index 7f691e0a04523b16f0e3bc11d9afa32b1ab2b45b..6fd033bb4642e219c8935349ebe223dff233b36a 100644 (file)
@@ -2,71 +2,29 @@ package webseed
 
 import (
        "net/url"
-       "path"
        "testing"
 
        qt "github.com/frankban/quicktest"
 )
 
-func TestEscapePath(t *testing.T) {
+func TestDefaultPathEscaper(t *testing.T) {
        c := qt.New(t)
-       test := func(
-               parts []string, result string,
-               escaper PathEscaper,
-               unescaper func(string) (string, error),
-       ) {
-               unescaped, err := unescaper(escaper(parts))
-               if !c.Check(err, qt.IsNil) {
-                       return
-               }
-               c.Check(unescaped, qt.Equals, result)
+       test := func(unescaped string, parts ...string) {
+               escaped := defaultPathEscaper(parts)
+               pathUnescaped, err := url.PathUnescape(escaped)
+               c.Assert(err, qt.IsNil)
+               c.Assert(pathUnescaped, qt.Equals, unescaped)
+               queryUnescaped, err := url.QueryUnescape(escaped)
+               c.Assert(err, qt.IsNil)
+               c.Assert(queryUnescaped, qt.Equals, unescaped)
        }
-
-       // Test with nil escapers (always uses url.QueryEscape)
-       // ------
-       test(
-               []string{"a_b-c", "d + e.f"},
-               "a_b-c/d + e.f",
-               defaultPathEscaper,
-               url.QueryUnescape,
-       )
-       test(
-               []string{"a_1-b_c2", "d 3. (e, f).g"},
-               "a_1-b_c2/d 3. (e, f).g",
-               defaultPathEscaper,
-               url.QueryUnescape,
-       )
-
-       // Test with custom escapers
-       // ------
-       test(
-               []string{"a_b-c", "d + e.f"},
-               "a_b-c/d + e.f",
-               func(s []string) string {
-                       var ret []string
-                       for _, comp := range s {
-                               ret = append(ret, url.PathEscape(comp))
-                       }
-                       return path.Join(ret...)
-               },
-               url.PathUnescape,
-       )
-       test(
-               []string{"a_1-b_c2", "d 3. (e, f).g"},
-               "a_1-b_c2/d 3. (e, f).g",
-               func(s []string) string {
-                       var ret []string
-                       for _, comp := range s {
-                               ret = append(ret, url.PathEscape(comp))
-                       }
-                       return path.Join(ret...)
-               },
-               url.PathUnescape,
-       )
-}
-
-func TestEscapePathForEmptyInfoName(t *testing.T) {
-       qt.Check(t, defaultPathEscaper([]string{`ノ┬─┬ノ ︵ ( \o°o)\`}), qt.Equals, "%E3%83%8E%E2%94%AC%E2%94%80%E2%94%AC%E3%83%8E+%EF%B8%B5+%28+%5Co%C2%B0o%29%5C")
-       qt.Check(t, defaultPathEscaper([]string{"hello", "world"}), qt.Equals, "hello/world")
-       qt.Check(t, defaultPathEscaper([]string{"war", "and", "peace"}), qt.Equals, "war/and/peace")
+       test("a_b-c/d + e.f", "a_b-c", "d + e.f")
+       test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
+       test("a_b-c/d + e.f", "a_b-c", "d + e.f")
+       test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
+       test("war/and/peace", "war", "and", "peace")
+       test("hello/world", "hello", "world")
+       test(`ノ┬─┬ノ ︵ ( \o°o)\`, `ノ┬─┬ノ ︵ ( \o°o)\`)
+       test(`%aa + %bb/Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`,
+               `%aa + %bb`, `Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`)
 }