X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/aebc4d3647b9823ae8cbb57b21b1af83bfd011fb..7778a321b14898bc8dabe4bb19c8ce5cb0100654:/hotline/transaction_handlers.go diff --git a/hotline/transaction_handlers.go b/hotline/transaction_handlers.go index 91a4c0d..ba2512e 100644 --- a/hotline/transaction_handlers.go +++ b/hotline/transaction_handlers.go @@ -272,7 +272,7 @@ var TransactionHandlers = map[uint16]TransactionType{ Handler: HandleSetClientUserInfo, }, tranSetFileInfo: { - Access: accessAlwaysAllow, // granular access is in the handler + Access: accessAlwaysAllow, Name: "tranSetFileInfo", Handler: HandleSetFileInfo, }, @@ -284,12 +284,11 @@ var TransactionHandlers = map[uint16]TransactionType{ }, tranUploadFile: { Access: accessAlwaysAllow, - DenyMsg: "You are not allowed to upload files.", Name: "tranUploadFile", Handler: HandleUploadFile, }, tranUploadFldr: { - Access: accessAlwaysAllow, // TODO: what should this be? + Access: accessAlwaysAllow, Name: "tranUploadFldr", Handler: HandleUploadFolder, }, @@ -302,6 +301,11 @@ var TransactionHandlers = map[uint16]TransactionType{ } func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err error) { + if !authorize(cc.Account.Access, accessSendChat) { + res = append(res, cc.NewErrReply(t, "You are not allowed to participate in chat.")) + return res, err + } + // Truncate long usernames trunc := fmt.Sprintf("%13s", cc.UserName) formattedMsg := fmt.Sprintf("\r%.14s: %s", trunc, t.GetField(fieldData).Data) @@ -418,7 +422,7 @@ func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e NewField(fieldFileType, ffo.FlatFileInformationFork.TypeSignature), NewField(fieldFileCreateDate, ffo.FlatFileInformationFork.CreateDate), NewField(fieldFileModifyDate, ffo.FlatFileInformationFork.ModifyDate), - NewField(fieldFileSize, ffo.FlatFileDataForkHeader.DataSize), + NewField(fieldFileSize, ffo.FlatFileDataForkHeader.DataSize[:]), )) return res, err } @@ -527,8 +531,8 @@ func HandleMoveFile(cc *ClientConn, t *Transaction) (res []Transaction, err erro cc.Server.Logger.Debugw("Move file", "src", filePath+"/"+fileName, "dst", fileNewPath+"/"+fileName) - path := filePath + "/" + fileName - fi, err := os.Stat(path) + fp := filePath + "/" + fileName + fi, err := os.Stat(fp) if err != nil { return res, err } @@ -649,15 +653,16 @@ func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error } } - // TODO: If we have just promoted a connected user to admin, notify - // connected clients to turn the user red - res = append(res, cc.NewReply(t)) return res, err } func HandleGetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error) { - // userLogin := string(t.GetField(fieldUserLogin).Data) + if !authorize(cc.Account.Access, accessOpenUser) { + res = append(res, cc.NewErrReply(t, "You are not allowed to view accounts.")) + return res, err + } + account := cc.Server.Accounts[string(t.GetField(fieldUserLogin).Data)] if account == nil { errorT := cc.NewErrReply(t, "Account does not exist.") @@ -711,6 +716,11 @@ func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error } func HandleDeleteUser(cc *ClientConn, t *Transaction) (res []Transaction, err error) { + if !authorize(cc.Account.Access, accessDeleteUser) { + res = append(res, cc.NewErrReply(t, "You are not allowed to delete accounts.")) + return res, err + } + // TODO: Handle case where account doesn't exist; e.g. delete race condition login := DecodeUserString(t.GetField(fieldUserLogin).Data) @@ -810,21 +820,6 @@ func HandleGetUserNameList(cc *ClientConn, t *Transaction) (res []Transaction, e return res, err } -func (cc *ClientConn) notifyNewUserHasJoined() (res []Transaction, err error) { - // Notify other ccs that a new user has connected - cc.NotifyOthers( - *NewTransaction( - tranNotifyChangeUser, nil, - NewField(fieldUserName, cc.UserName), - NewField(fieldUserID, *cc.ID), - NewField(fieldUserIconID, *cc.Icon), - NewField(fieldUserFlags, *cc.Flags), - ), - ) - - return res, nil -} - func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err error) { cc.Agreed = true cc.UserName = t.GetField(fieldUserName).Data @@ -854,7 +849,15 @@ func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err er cc.AutoReply = []byte{} } - _, _ = cc.notifyNewUserHasJoined() + cc.notifyOthers( + *NewTransaction( + tranNotifyChangeUser, nil, + NewField(fieldUserName, cc.UserName), + NewField(fieldUserID, *cc.ID), + NewField(fieldUserIconID, *cc.Icon), + NewField(fieldUserFlags, *cc.Flags), + ), + ) res = append(res, cc.NewReply(t)) @@ -1010,9 +1013,9 @@ func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction var cat NewsCategoryListData15 cats := cc.Server.ThreadedNews.Categories - for _, path := range pathStrs { - cat = cats[path] - cats = cats[path].SubCats + for _, fp := range pathStrs { + cat = cats[fp] + cats = cats[fp].SubCats } nald := cat.GetNewsArtListData() @@ -1023,7 +1026,7 @@ func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, err error) { // Request fields - // 325 News path + // 325 News fp // 326 News article ID // 327 News article data flavor @@ -1032,9 +1035,9 @@ func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, er var cat NewsCategoryListData15 cats := cc.Server.ThreadedNews.Categories - for _, path := range pathStrs { - cat = cats[path] - cats = cats[path].SubCats + for _, fp := range pathStrs { + cat = cats[fp] + cats = cats[fp].SubCats } newsArtID := t.GetField(fieldNewsArtID).Data @@ -1084,8 +1087,8 @@ func HandleDelNewsItem(cc *ClientConn, t *Transaction) (res []Transaction, err e delName := pathStrs[len(pathStrs)-1] if len(pathStrs) > 1 { - for _, path := range pathStrs[0 : len(pathStrs)-1] { - cats = cats[path].SubCats + for _, fp := range pathStrs[0 : len(pathStrs)-1] { + cats = cats[fp].SubCats } } @@ -1231,7 +1234,7 @@ func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err NewField(fieldRefNum, transactionRef), NewField(fieldWaitingCount, []byte{0x00, 0x00}), // TODO: Implement waiting count NewField(fieldTransferSize, ffo.TransferSize()), - NewField(fieldFileSize, ffo.FlatFileDataForkHeader.DataSize), + NewField(fieldFileSize, ffo.FlatFileDataForkHeader.DataSize[:]), )) return res, err @@ -1313,6 +1316,21 @@ func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err transactionRef := cc.Server.NewTransactionRef() data := binary.BigEndian.Uint32(transactionRef) + var fp FilePath + if t.GetField(fieldFilePath).Data != nil { + if err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data); err != nil { + return res, err + } + } + + // Handle special cases for Upload and Drop Box folders + if !authorize(cc.Account.Access, accessUploadAnywhere) { + if !fp.IsUploadDir() && !fp.IsDropbox() { + res = append(res, cc.NewErrReply(t, fmt.Sprintf("Cannot accept upload of the folder \"%v\" because you are only allowed to upload to the \"Uploads\" folder.", string(t.GetField(fieldFileName).Data)))) + return res, err + } + } + fileTransfer := &FileTransfer{ FileName: t.GetField(fieldFileName).Data, FilePath: t.GetField(fieldFilePath).Data, @@ -1327,8 +1345,10 @@ func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err return res, err } +// HandleUploadFile +// Special cases: +// * If the target directory contains "uploads" (case insensitive) func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err error) { - // TODO: add permission handing for upload folders and drop boxes if !authorize(cc.Account.Access, accessUploadFile) { res = append(res, cc.NewErrReply(t, "You are not allowed to upload files.")) return res, err @@ -1337,6 +1357,21 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er fileName := t.GetField(fieldFileName).Data filePath := t.GetField(fieldFilePath).Data + var fp FilePath + if filePath != nil { + if err = fp.UnmarshalBinary(filePath); err != nil { + return res, err + } + } + + // Handle special cases for Upload and Drop Box folders + if !authorize(cc.Account.Access, accessUploadAnywhere) { + if !fp.IsUploadDir() && !fp.IsDropbox() { + res = append(res, 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)))) + return res, err + } + } + transactionRef := cc.Server.NewTransactionRef() data := binary.BigEndian.Uint32(transactionRef) @@ -1351,13 +1386,6 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er return res, err } -// User options -const ( - refusePM = 0 - refuseChat = 1 - autoResponse = 2 -) - func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) { var icon []byte if len(t.GetField(fieldUserIconID).Data) == 4 { @@ -1420,6 +1448,19 @@ func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, e return res, err } + var fp FilePath + if t.GetField(fieldFilePath).Data != nil { + if err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data); err != nil { + return res, err + } + } + + // Handle special case for drop box folders + if fp.IsDropbox() && !authorize(cc.Account.Access, accessViewDropBoxes) { + res = append(res, cc.NewReply(t)) + return res, err + } + fileNames, err := getFileNameList(fullPath) if err != nil { return res, err