serve/http: fix serving files with : in - fixes #1939

This commit is contained in:
Nick Craig-Wood 2018-01-05 16:47:00 +00:00
parent be4ed14525
commit 65618afd8c
2 changed files with 51 additions and 8 deletions

View file

@ -11,6 +11,7 @@ import (
"github.com/ncw/rclone/cmd"
"github.com/ncw/rclone/fs"
"github.com/ncw/rclone/rest"
"github.com/ncw/rclone/vfs"
"github.com/ncw/rclone/vfs/vfsflags"
"github.com/spf13/cobra"
@ -117,6 +118,22 @@ type entry struct {
// entries represents a directory
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
var indexPage = `<!DOCTYPE html>
<html lang="en">
@ -171,14 +188,7 @@ func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri
var out entries
for _, node := range dirEntries {
remote := node.Path()
leaf := node.Name()
urlRemote := leaf
if node.IsDir() {
leaf += "/"
urlRemote += "/"
}
out = append(out, entry{remote: remote, URL: urlRemote, Leaf: leaf})
out.addEntry(node)
}
// Account the transfer

View file

@ -1,3 +1,5 @@
// +build go1.8
package http
import (
@ -5,6 +7,7 @@ import (
"io/ioutil"
"net"
"net/http"
"path"
"strings"
"testing"
"time"
@ -190,3 +193,33 @@ func TestGET(t *testing.T) {
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)
}