]> git.r.bdr.sh - rbdr/mobius/commitdiff
Add option for account-specific file root
authorJeff Halter <redacted>
Sat, 20 Jul 2024 04:31:42 +0000 (21:31 -0700)
committerJeff Halter <redacted>
Sat, 20 Jul 2024 04:40:38 +0000 (21:40 -0700)
hotline/account.go
hotline/client_conn.go
hotline/file_transfer.go
hotline/server.go
hotline/server_test.go
internal/mobius/transaction_handlers.go
internal/mobius/transaction_handlers_test.go

index 7f770b197db7013d48b0e69dee7e308a1ebbe455..526eb053b176a84b54d9d84b56ade12ac9e0a89f 100644 (file)
@@ -15,6 +15,7 @@ type Account struct {
        Name     string       `yaml:"Name"`
        Password string       `yaml:"Password"`
        Access   AccessBitmap `yaml:"Access,flow"`
+       FileRoot string       `yaml:"FileRoot"`
 
        readOffset int // Internal offset to track read progress
 }
index 060a2b9e1a133b67f0e61dcd9fc8f590cb70cc58..d32459116074aeff5213ff35601a0e15a17283f6 100644 (file)
@@ -42,6 +42,13 @@ type ClientConn struct {
        mu sync.RWMutex
 }
 
+func (cc *ClientConn) FileRoot() string {
+       if cc.Account.FileRoot != "" {
+               return cc.Account.FileRoot
+       }
+       return cc.Server.Config.FileRoot
+}
+
 type ClientFileTransferMgr struct {
        transfers map[FileTransferType]map[FileTransferID]*FileTransfer
 
index 806466b927a189c0e811c82ed706b4427d6c6e7a..12725db620779d7ba4e1f197ba2683c960986dc7 100644 (file)
@@ -87,6 +87,7 @@ func (ftm *MemFileTransferMgr) Delete(id FileTransferID) {
 }
 
 type FileTransfer struct {
+       FileRoot         string
        FileName         []byte
        FilePath         []byte
        RefNum           [4]byte
@@ -116,9 +117,10 @@ func (wc *WriteCounter) Write(p []byte) (int, error) {
        return n, nil
 }
 
-func (cc *ClientConn) NewFileTransfer(transferType FileTransferType, fileName, filePath, size []byte) *FileTransfer {
+func (cc *ClientConn) NewFileTransfer(transferType FileTransferType, fileroot string, fileName, filePath, size []byte) *FileTransfer {
        ft := &FileTransfer{
                FileName:         fileName,
+               FileRoot:         fileroot,
                FilePath:         filePath,
                Type:             transferType,
                TransferSize:     size,
index 04ac8c7119c4d0dafbece1047026b78d5e805297..c4d8f7f429d22bf27bbd4cca397a56d9b712ce9c 100644 (file)
@@ -526,7 +526,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro
                "Name", string(fileTransfer.ClientConn.UserName),
        )
 
-       fullPath, err := ReadPath(s.Config.FileRoot, fileTransfer.FilePath, fileTransfer.FileName)
+       fullPath, err := ReadPath(fileTransfer.FileRoot, fileTransfer.FilePath, fileTransfer.FileName)
        if err != nil {
                return err
        }
@@ -534,7 +534,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro
        switch fileTransfer.Type {
        case BannerDownload:
                if _, err := io.Copy(rwc, bytes.NewBuffer(s.Banner)); err != nil {
-                       return fmt.Errorf("error sending Banner: %w", err)
+                       return fmt.Errorf("banner download: %w", err)
                }
        case FileDownload:
                s.Stats.Increment(StatDownloadCounter, StatDownloadsInProgress)
@@ -555,7 +555,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro
 
                err = UploadHandler(rwc, fullPath, fileTransfer, s.FS, rLogger, s.Config.PreserveResourceForks)
                if err != nil {
-                       return fmt.Errorf("file upload error: %w", err)
+                       return fmt.Errorf("file upload: %w", err)
                }
 
        case FolderDownload:
@@ -566,7 +566,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro
 
                err = DownloadFolderHandler(rwc, fullPath, fileTransfer, s.FS, rLogger, s.Config.PreserveResourceForks)
                if err != nil {
-                       return fmt.Errorf("file upload error: %w", err)
+                       return fmt.Errorf("folder download: %w", err)
                }
 
        case FolderUpload:
@@ -584,7 +584,7 @@ func (s *Server) handleFileTransfer(ctx context.Context, rwc io.ReadWriter) erro
 
                err = UploadFolderHandler(rwc, fullPath, fileTransfer, s.FS, rLogger, s.Config.PreserveResourceForks)
                if err != nil {
-                       return fmt.Errorf("file upload error: %w", err)
+                       return fmt.Errorf("folder upload: %w", err)
                }
        }
        return nil
index c3d38da57db7a6b35bda33b4308ffc0a88902740..d0e2372a9d4d8e9cd83afbfc1acf9995a4ea4268 100644 (file)
@@ -99,12 +99,7 @@ func TestServer_handleFileTransfer(t *testing.T) {
                {
                        name: "file download",
                        fields: fields{
-                               FS: &OSFileStore{},
-                               Config: Config{
-                                       FileRoot: func() string {
-                                               path, _ := os.Getwd()
-                                               return path + "/test/config/Files"
-                                       }()},
+                               FS:     &OSFileStore{},
                                Logger: NewTestLogger(),
                                Stats:  NewStats(),
                                FileTransferMgr: &MemFileTransferMgr{
@@ -114,6 +109,10 @@ func TestServer_handleFileTransfer(t *testing.T) {
                                                        Type:     FileDownload,
                                                        FileName: []byte("testfile-8b"),
                                                        FilePath: []byte{},
+                                                       FileRoot: func() string {
+                                                               path, _ := os.Getwd()
+                                                               return path + "/test/config/Files"
+                                                       }(),
                                                        ClientConn: &ClientConn{
                                                                Account: &Account{
                                                                        Login: "foo",
index 399a8c038ea4e9ccee9916407f0ba7548cf765a5..759ee66ed20db7a72f0c94f62ec84c348e52018c 100644 (file)
@@ -204,7 +204,7 @@ func HandleGetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
        fileName := t.GetField(hotline.FieldFileName).Data
        filePath := t.GetField(hotline.FieldFilePath).Data
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
@@ -253,7 +253,7 @@ func HandleSetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
        fileName := t.GetField(hotline.FieldFileName).Data
        filePath := t.GetField(hotline.FieldFilePath).Data
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
@@ -292,7 +292,7 @@ func HandleSetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
                }
        }
 
-       fullNewFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, t.GetField(hotline.FieldFileNewName).Data)
+       fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, t.GetField(hotline.FieldFileNewName).Data)
        if err != nil {
                return nil
        }
@@ -314,7 +314,7 @@ func HandleSetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
                        if !cc.Authorize(hotline.AccessRenameFile) {
                                return cc.NewErrReply(t, "You are not allowed to rename files.")
                        }
-                       fileDir, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, []byte{})
+                       fileDir, err := hotline.ReadPath(cc.FileRoot(), filePath, []byte{})
                        if err != nil {
                                return nil
                        }
@@ -346,7 +346,7 @@ func HandleDeleteFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot
        fileName := t.GetField(hotline.FieldFileName).Data
        filePath := t.GetField(hotline.FieldFilePath).Data
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
@@ -384,12 +384,12 @@ func HandleDeleteFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot
 func HandleMoveFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) {
        fileName := string(t.GetField(hotline.FieldFileName).Data)
 
-       filePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, t.GetField(hotline.FieldFilePath).Data, t.GetField(hotline.FieldFileName).Data)
+       filePath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, t.GetField(hotline.FieldFileName).Data)
        if err != nil {
                return res
        }
 
-       fileNewPath, err := hotline.ReadPath(cc.Server.Config.FileRoot, t.GetField(hotline.FieldFileNewPath).Data, nil)
+       fileNewPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFileNewPath).Data, nil)
        if err != nil {
                return res
        }
@@ -446,7 +446,7 @@ func HandleNewFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
                        subPath = filepath.Join("/", subPath, string(pathItem.Name))
                }
        }
-       newFolderPath := path.Join(cc.Server.Config.FileRoot, subPath, folderName)
+       newFolderPath := path.Join(cc.FileRoot(), subPath, folderName)
        newFolderPath, err := txtDecoder.String(newFolderPath)
        if err != nil {
                return res
@@ -1279,7 +1279,7 @@ func HandleDownloadFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []h
                dataOffset = int64(binary.BigEndian.Uint32(frd.ForkInfoList[0].DataSize[:]))
        }
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
@@ -1291,9 +1291,14 @@ func HandleDownloadFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []h
 
        xferSize := hlFile.Ffo.TransferSize(0)
 
-       ft := cc.NewFileTransfer(hotline.FileDownload, fileName, filePath, xferSize)
+       ft := cc.NewFileTransfer(
+               hotline.FileDownload,
+               cc.FileRoot(),
+               fileName,
+               filePath,
+               xferSize,
+       )
 
-       // TODO: refactor to remove this
        if resumeData != nil {
                var frd hotline.FileResumeData
                if err := frd.UnmarshalBinary(t.GetField(hotline.FieldFileResumeData).Data); err != nil {
@@ -1326,26 +1331,26 @@ func HandleDownloadFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res [
                return cc.NewErrReply(t, "You are not allowed to download folders.")
        }
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, t.GetField(hotline.FieldFilePath).Data, t.GetField(hotline.FieldFileName).Data)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFilePath).Data, t.GetField(hotline.FieldFileName).Data)
        if err != nil {
-               return res
+               return nil
        }
 
        transferSize, err := hotline.CalcTotalSize(fullFilePath)
        if err != nil {
-               return res
+               return nil
        }
        itemCount, err := hotline.CalcItemCount(fullFilePath)
        if err != nil {
-               return res
+               return nil
        }
 
-       fileTransfer := cc.NewFileTransfer(hotline.FolderDownload, t.GetField(hotline.FieldFileName).Data, t.GetField(hotline.FieldFilePath).Data, transferSize)
+       fileTransfer := cc.NewFileTransfer(hotline.FolderDownload, cc.FileRoot(), t.GetField(hotline.FieldFileName).Data, t.GetField(hotline.FieldFilePath).Data, transferSize)
 
        var fp hotline.FilePath
        _, err = fp.Write(t.GetField(hotline.FieldFilePath).Data)
        if err != nil {
-               return res
+               return nil
        }
 
        res = append(res, cc.NewReply(t,
@@ -1380,6 +1385,7 @@ func HandleUploadFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res []h
        }
 
        fileTransfer := cc.NewFileTransfer(hotline.FolderUpload,
+               cc.FileRoot(),
                t.GetField(hotline.FieldFileName).Data,
                t.GetField(hotline.FieldFilePath).Data,
                t.GetField(hotline.FieldTransferSize).Data,
@@ -1420,7 +1426,7 @@ func HandleUploadFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot
                        return cc.NewErrReply(t, fmt.Sprintf("Cannot accept upload of the file \"%v\" because you are only allowed to upload to the \"Uploads\" folder.", string(fileName)))
                }
        }
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
@@ -1429,7 +1435,7 @@ func HandleUploadFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot
                return cc.NewErrReply(t, fmt.Sprintf("Cannot accept upload because there is already a file named \"%v\".  Try choosing a different Name.", string(fileName)))
        }
 
-       ft := cc.NewFileTransfer(hotline.FileUpload, fileName, filePath, transferSize)
+       ft := cc.NewFileTransfer(hotline.FileUpload, cc.FileRoot(), fileName, filePath, transferSize)
 
        replyT := cc.NewReply(t, hotline.NewField(hotline.FieldRefNum, ft.RefNum[:]))
 
@@ -1509,7 +1515,7 @@ func HandleKeepAlive(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
 
 func HandleGetFileNameList(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) {
        fullPath, err := hotline.ReadPath(
-               cc.Server.Config.FileRoot,
+               cc.FileRoot(),
                t.GetField(hotline.FieldFilePath).Data,
                nil,
        )
@@ -1756,12 +1762,12 @@ func HandleMakeAlias(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
        filePath := t.GetField(hotline.FieldFilePath).Data
        fileNewPath := t.GetField(hotline.FieldFileNewPath).Data
 
-       fullFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, filePath, fileName)
+       fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
        if err != nil {
                return res
        }
 
-       fullNewFilePath, err := hotline.ReadPath(cc.Server.Config.FileRoot, fileNewPath, fileName)
+       fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), fileNewPath, fileName)
        if err != nil {
                return res
        }
@@ -1783,7 +1789,7 @@ func HandleMakeAlias(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
 // 107 FieldRefNum                     Used later for transfer
 // 108 FieldTransferSize       Size of data to be downloaded
 func HandleDownloadBanner(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotline.Transaction) {
-       ft := cc.NewFileTransfer(hotline.BannerDownload, []byte{}, []byte{}, make([]byte, 4))
+       ft := cc.NewFileTransfer(hotline.BannerDownload, "", []byte{}, []byte{}, make([]byte, 4))
        binary.BigEndian.PutUint32(ft.TransferSize, uint32(len(cc.Server.Banner)))
 
        return append(res, cc.NewReply(t,
index 63d294662a5edbb4fc0e5d8891378c4592e9e24a..26ea9504fac1b4121d98f138315e5e0185f17afd 100644 (file)
@@ -782,7 +782,8 @@ func TestHandleGetFileInfo(t *testing.T) {
                        name: "returns expected fields when a valid file is requested",
                        args: args{
                                cc: &hotline.ClientConn{
-                                       ID: [2]byte{0x00, 0x01},
+                                       ID:      [2]byte{0, 1},
+                                       Account: &hotline.Account{},
                                        Server: &hotline.Server{
                                                FS: &hotline.OSFileStore{},
                                                Config: hotline.Config{
@@ -2629,14 +2630,13 @@ func TestHandleGetFileNameList(t *testing.T) {
                        name: "with file root",
                        args: args{
                                cc: &hotline.ClientConn{
-                                       Server: &hotline.Server{
-                                               Config: hotline.Config{
-                                                       FileRoot: func() string {
-                                                               path, _ := os.Getwd()
-                                                               return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
-                                                       }(),
-                                               },
+                                       Account: &hotline.Account{
+                                               FileRoot: func() string {
+                                                       path, _ := os.Getwd()
+                                                       return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
+                                               }(),
                                        },
+                                       Server: &hotline.Server{},
                                },
                                t: hotline.NewTransaction(
                                        hotline.TranGetFileNameList, [2]byte{0, 1},