serve/http: fix serving files with : in - fixes #1939
This commit is contained in:
parent
be4ed14525
commit
65618afd8c
2 changed files with 51 additions and 8 deletions
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/ncw/rclone/cmd"
|
"github.com/ncw/rclone/cmd"
|
||||||
"github.com/ncw/rclone/fs"
|
"github.com/ncw/rclone/fs"
|
||||||
|
"github.com/ncw/rclone/rest"
|
||||||
"github.com/ncw/rclone/vfs"
|
"github.com/ncw/rclone/vfs"
|
||||||
"github.com/ncw/rclone/vfs/vfsflags"
|
"github.com/ncw/rclone/vfs/vfsflags"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -117,6 +118,22 @@ type entry struct {
|
||||||
// entries represents a directory
|
// entries represents a directory
|
||||||
type entries []entry
|
type entries []entry
|
||||||
|
|
||||||
|
// addEntry adds an entry to that directory
|
||||||
|
func (es *entries) addEntry(node interface {
|
||||||
|
Path() string
|
||||||
|
Name() string
|
||||||
|
IsDir() bool
|
||||||
|
}) {
|
||||||
|
remote := node.Path()
|
||||||
|
leaf := node.Name()
|
||||||
|
urlRemote := leaf
|
||||||
|
if node.IsDir() {
|
||||||
|
leaf += "/"
|
||||||
|
urlRemote += "/"
|
||||||
|
}
|
||||||
|
*es = append(*es, entry{remote: remote, URL: rest.URLPathEscape(urlRemote), Leaf: leaf})
|
||||||
|
}
|
||||||
|
|
||||||
// indexPage is a directory listing template
|
// indexPage is a directory listing template
|
||||||
var indexPage = `<!DOCTYPE html>
|
var indexPage = `<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
@ -171,14 +188,7 @@ func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri
|
||||||
|
|
||||||
var out entries
|
var out entries
|
||||||
for _, node := range dirEntries {
|
for _, node := range dirEntries {
|
||||||
remote := node.Path()
|
out.addEntry(node)
|
||||||
leaf := node.Name()
|
|
||||||
urlRemote := leaf
|
|
||||||
if node.IsDir() {
|
|
||||||
leaf += "/"
|
|
||||||
urlRemote += "/"
|
|
||||||
}
|
|
||||||
out = append(out, entry{remote: remote, URL: urlRemote, Leaf: leaf})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account the transfer
|
// Account the transfer
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build go1.8
|
||||||
|
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -5,6 +7,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -190,3 +193,33 @@ func TestGET(t *testing.T) {
|
||||||
checkGolden(t, test.Golden, body)
|
checkGolden(t, test.Golden, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mockNode struct {
|
||||||
|
path string
|
||||||
|
isdir bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n mockNode) Path() string { return n.path }
|
||||||
|
func (n mockNode) Name() string {
|
||||||
|
if n.path == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return path.Base(n.path)
|
||||||
|
}
|
||||||
|
func (n mockNode) IsDir() bool { return n.isdir }
|
||||||
|
|
||||||
|
func TestAddEntry(t *testing.T) {
|
||||||
|
var es entries
|
||||||
|
es.addEntry(mockNode{path: "", isdir: true})
|
||||||
|
es.addEntry(mockNode{path: "dir", isdir: true})
|
||||||
|
es.addEntry(mockNode{path: "a/b/c/d.txt", isdir: false})
|
||||||
|
es.addEntry(mockNode{path: "a/b/c/colon:colon.txt", isdir: false})
|
||||||
|
es.addEntry(mockNode{path: "\"quotes\".txt", isdir: false})
|
||||||
|
assert.Equal(t, entries{
|
||||||
|
{remote: "", URL: "/", Leaf: "/"},
|
||||||
|
{remote: "dir", URL: "dir/", Leaf: "dir/"},
|
||||||
|
{remote: "a/b/c/d.txt", URL: "d.txt", Leaf: "d.txt"},
|
||||||
|
{remote: "a/b/c/colon:colon.txt", URL: "./colon:colon.txt", Leaf: "colon:colon.txt"},
|
||||||
|
{remote: "\"quotes\".txt", URL: "%22quotes%22.txt", Leaf: "\"quotes\".txt"},
|
||||||
|
}, es)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue