aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hotline/file_path.go18
-rw-r--r--hotline/file_path_test.go23
-rw-r--r--internal/mobius/transaction_handlers.go12
3 files changed, 46 insertions, 7 deletions
diff --git a/hotline/file_path.go b/hotline/file_path.go
index a3a13f1..c97faea 100644
--- a/hotline/file_path.go
+++ b/hotline/file_path.go
@@ -115,14 +115,22 @@ func ReadPath(fileRoot string, filePath, fileName []byte) (fullPath string, err
subPath = path.Join("/", subPath, string(pathItem.Name))
}
+ // Decode only client-provided path components from Mac Roman to UTF-8.
+ // The fileRoot is already a UTF-8 filesystem path and must not be decoded.
+ subPath, err = txtDecoder.String(subPath)
+ if err != nil {
+ return "", fmt.Errorf("invalid filepath encoding: %w", err)
+ }
+
+ decodedFileName, err := txtDecoder.String(string(fileName))
+ if err != nil {
+ return "", fmt.Errorf("invalid filename encoding: %w", err)
+ }
+
fullPath = path.Join(
fileRoot,
subPath,
- path.Join("/", string(fileName)),
+ path.Join("/", decodedFileName),
)
- fullPath, err = txtDecoder.String(fullPath)
- if err != nil {
- return "", fmt.Errorf("invalid filepath encoding: %w", err)
- }
return fullPath, nil
}
diff --git a/hotline/file_path_test.go b/hotline/file_path_test.go
index ee0cbac..c86a8d9 100644
--- a/hotline/file_path_test.go
+++ b/hotline/file_path_test.go
@@ -152,6 +152,29 @@ func Test_readPath(t *testing.T) {
},
want: "/usr/local/var/mobius/Files",
},
+ {
+ name: "when fileRoot contains non-ASCII UTF-8 characters",
+ args: args{
+ fileRoot: "/files/español",
+ filePath: nil,
+ fileName: []byte("foo"),
+ },
+ want: "/files/español/foo",
+ },
+ {
+ name: "when fileRoot contains non-ASCII and filePath has Mac Roman bytes",
+ args: args{
+ fileRoot: "/files/español",
+ filePath: []byte{
+ 0x00, 0x01,
+ 0x00, 0x00,
+ 0x06,
+ 0x63, 0x61, 0x66, 0x8e, 0x73, 0x21, // "caf\x8es!" where 0x8e is Mac Roman é
+ },
+ fileName: []byte("foo"),
+ },
+ want: "/files/español/cafés!/foo",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/internal/mobius/transaction_handlers.go b/internal/mobius/transaction_handlers.go
index 259ac02..33af941 100644
--- a/internal/mobius/transaction_handlers.go
+++ b/internal/mobius/transaction_handlers.go
@@ -568,11 +568,19 @@ func HandleNewFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
subPath = path.Join("/", subPath, string(pathItem.Name))
}
}
- newFolderPath := path.Join(cc.FileRoot(), subPath, folderName)
- newFolderPath, err := txtDecoder.String(newFolderPath)
+
+ // Decode only client-provided path components from Mac Roman to UTF-8.
+ // The FileRoot is already a UTF-8 filesystem path and must not be decoded.
+ subPath, err := txtDecoder.String(subPath)
if err != nil {
return res
}
+ folderName, err = txtDecoder.String(folderName)
+ if err != nil {
+ return res
+ }
+
+ newFolderPath := path.Join(cc.FileRoot(), subPath, folderName)
// TODO: check path and folder Name lengths