Skip to content

Commit

Permalink
Add option for account-specific file root
Browse files Browse the repository at this point in the history
  • Loading branch information
jhalter committed Jul 20, 2024
1 parent 9f89cd9 commit dcd23d5
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 43 deletions.
1 change: 1 addition & 0 deletions hotline/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
7 changes: 7 additions & 0 deletions hotline/client_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion hotline/file_transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func (ftm *MemFileTransferMgr) Delete(id FileTransferID) {
}

type FileTransfer struct {
FileRoot string
FileName []byte
FilePath []byte
RefNum [4]byte
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions hotline/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,15 +526,15 @@ 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
}

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)
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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
Expand Down
11 changes: 5 additions & 6 deletions hotline/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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",
Expand Down
52 changes: 29 additions & 23 deletions internal/mobius/transaction_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Expand All @@ -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[:]))

Expand Down Expand Up @@ -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,
)
Expand Down Expand Up @@ -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
}
Expand All @@ -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,
Expand Down
16 changes: 8 additions & 8 deletions internal/mobius/transaction_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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},
Expand Down

0 comments on commit dcd23d5

Please sign in to comment.