Skip to content

Commit

Permalink
Fix some special characters may break the file path (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
mstmdev authored Aug 3, 2023
1 parent 0d83e14 commit bb72f21
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 5 deletions.
19 changes: 19 additions & 0 deletions fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,22 @@ func IsSub(parent, child string) (bool, error) {
relPath = filepath.ToSlash(relPath)
return relPath != ".." && !strings.HasPrefix(relPath, "../"), nil
}

// SafePath encode some special characters for the path like "?", "#" etc.
func SafePath(path string) string {
if len(path) == 0 {
return path
}
filterRule := []struct {
old string
new string
}{
{"%", "%25"}, // stay in the first position
{"?", "%3F"},
{"#", "%23"},
}
for _, r := range filterRule {
path = strings.ReplaceAll(path, r.old, r.new)
}
return path
}
29 changes: 29 additions & 0 deletions fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fs
import (
"errors"
"io"
"net/url"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -350,6 +351,34 @@ func TestIsSub_ReturnError_Windows(t *testing.T) {
}
}

func TestSafePath(t *testing.T) {
testCases := []struct {
path string
}{
{""},
{" "},
{"/hello/world"},
{"/1 1"},
{"/#1/#2"},
{"/?1/?2"},
{"/%25/%3F/%23"},
}

for _, tc := range testCases {
t.Run(tc.path, func(t *testing.T) {
safePath := SafePath(tc.path)
u, err := url.Parse(safePath)
if err != nil {
t.Errorf("parse url error: %v path=%s safe path=%s", err, tc.path, safePath)
return
}
if u.Path != tc.path {
t.Errorf("test SafePath error, expect to get %s, but actual get %s", tc.path, u.Path)
}
})
}
}

func isNotExistAlwaysFalseMock(err error) bool {
return false
}
Expand Down
12 changes: 12 additions & 0 deletions integration/testdata/test/test-gofs-remote-disk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ init:
- mkdir:
source: ./rc/dest
actions:
- mkdir:
source: ./rs/source/#1/%25/%3F/%23
- touch:
source: ./rs/source/#1/%25/%3F/%23/#%25.txt
- echo:
source: ./rs/source/#1/%25/%3F/%23/#%25.txt
input: Hello World
no-newline: true
- cp:
source: ./integration_test.go
dest: ./rs/source/integration_test.go.bak1
Expand All @@ -35,6 +43,10 @@ actions:
source: ./rs/source/empty2
no-newline: true
- sleep: 10s
- hash:
algorithm: md5
source: ./rc/dest/#1/%25/%3F/%23/#%25.txt
expect: b10a8db164e0754105b7a99be72e3fe5
- is-equal:
source: ./integration_test.go
dest: ./rc/dest/integration_test.go.bak1
Expand Down
12 changes: 12 additions & 0 deletions integration/testdata/test/test-gofs-remote-push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ init:
- mkdir:
source: ./rc-push/dest
actions:
- mkdir:
source: ./rc-push/source/#1/%25/%3F/%23
- touch:
source: ./rc-push/source/#1/%25/%3F/%23/#%25.txt
- echo:
source: ./rc-push/source/#1/%25/%3F/%23/#%25.txt
input: Hello World
no-newline: true
- cp:
source: ./integration_test.go
dest: ./rc-push/source/integration_test.go.bak1
Expand All @@ -35,6 +43,10 @@ actions:
source: ./rc-push/source/empty2
no-newline: true
- sleep: 10s
- hash:
algorithm: md5
source: ./rs-push/source/#1/%25/%3F/%23/#%25.txt
expect: b10a8db164e0754105b7a99be72e3fe5
- is-equal:
source: ./rc-push/source/integration_test.go.bak1
dest: ./rs-push/source/integration_test.go.bak1
Expand Down
6 changes: 2 additions & 4 deletions monitor/remote_client_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"net/url"
"os"
"strings"
"time"

"github.com/no-src/gofs/action"
Expand All @@ -14,6 +13,7 @@ import (
"github.com/no-src/gofs/auth"
"github.com/no-src/gofs/contract"
"github.com/no-src/gofs/eventlog"
"github.com/no-src/gofs/fs"
"github.com/no-src/gofs/ignore"
"github.com/no-src/gofs/internal/cbool"
"github.com/no-src/gofs/internal/clist"
Expand Down Expand Up @@ -204,9 +204,7 @@ func (m *remoteClientMonitor) execSync(msg *monitor.MonitorMessage) (err error)
if len(fi.HashValues) > 0 {
values.Add(contract.FsHashValues, stringutil.String(fi.HashValues))
}

// replace question marks with "%3F" to avoid parse the path is breaking when it contains some question marks
path := msg.BaseUrl + strings.ReplaceAll(fi.Path, "?", "%3F") + fmt.Sprintf("?%s", values.Encode())
path := msg.BaseUrl + fs.SafePath(fi.Path) + fmt.Sprintf("?%s", values.Encode())

switch action.Action(msg.Action) {
case action.CreateAction:
Expand Down
2 changes: 2 additions & 0 deletions server/handler/file_api_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ func (h *fileApiHandler) Handle(c *gin.Context) {
}
return
}
defer f.Close()

stat, err := f.Stat()
if err != nil {
h.logger.Error(err, "file server get file stat error")
Expand Down
2 changes: 1 addition & 1 deletion sync/remote_client_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ func (rs *remoteClientSync) syncFiles(files []contract.FileInfo, serverAddr, pat
values.Add(contract.FsCtime, stringutil.String(file.CTime))
values.Add(contract.FsAtime, stringutil.String(file.ATime))
values.Add(contract.FsMtime, stringutil.String(file.MTime))
syncPath := fmt.Sprintf("%s/%s?%s", serverAddr, currentPath, values.Encode())
syncPath := fmt.Sprintf("%s/%s?%s", serverAddr, fs.SafePath(currentPath), values.Encode())

// create directory or file
log.ErrorIf(rs.Create(syncPath), "sync create directory or file error => [syncPath=%s]", syncPath)
Expand Down

0 comments on commit bb72f21

Please sign in to comment.