aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJeff Halter <868228+jhalter@users.noreply.github.com>2026-03-15 14:54:44 -0700
committerJeff Halter <868228+jhalter@users.noreply.github.com>2026-03-15 14:54:44 -0700
commitf78ab940a8c09702be3e0ba310ac56e02fa76701 (patch)
tree4b128f55860d1ce7ef9c87861179d97f5732b476 /internal
parent72c6ddc104c349a4798fddeaa8f77dbe139fe104 (diff)
Add configurable text encoding for file and folder names
Replace hardcoded Mac Roman encoding globals with a configurable Encoding field in config.yaml. Servers that exclusively serve modern UTF-8 clients can now set Encoding: utf8 to disable Mac Roman conversion. The default remains "macintosh" for backward compatibility. - Add Encoding field to Config struct (macintosh|utf8) - Store TextDecoder/TextEncoder on Server, initialized from config - Add TextDecoder()/TextEncoder() accessors on ClientConn - Pass decoder/encoder explicitly to ReadPath and GetFileNameList - Remove package-level txtEncoder/txtDecoder globals - Add warning log when files are skipped due to encoding errors - Log and return error replies in HandleGetFileNameList on failure - Document the new config option in docs/text-encoding.md
Diffstat (limited to 'internal')
-rw-r--r--internal/mobius/transaction_handlers.go51
-rw-r--r--internal/mobius/transaction_handlers_test.go165
2 files changed, 184 insertions, 32 deletions
diff --git a/internal/mobius/transaction_handlers.go b/internal/mobius/transaction_handlers.go
index 33af941..ce31abd 100644
--- a/internal/mobius/transaction_handlers.go
+++ b/internal/mobius/transaction_handlers.go
@@ -14,7 +14,6 @@ import (
"time"
"github.com/jhalter/mobius/hotline"
- "golang.org/x/text/encoding/charmap"
)
// Public error message constants for reuse by other packages
@@ -96,12 +95,6 @@ const (
ErrMsgReadMessageBoard = "Error reading message board."
)
-// Converts bytes from Mac Roman encoding to UTF-8
-var txtDecoder = charmap.Macintosh.NewDecoder()
-
-// Converts bytes from UTF-8 to Mac Roman encoding
-var txtEncoder = charmap.Macintosh.NewEncoder()
-
// Assign functions to handle specific Hotline transaction types
func RegisterHandlers(srv *hotline.Server) {
srv.HandleFunc(hotline.TranAgreed, HandleTranAgreed)
@@ -303,7 +296,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.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
@@ -313,7 +306,7 @@ func HandleGetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
return res
}
- encodedName, err := txtEncoder.String(fw.Name)
+ encodedName, err := cc.TextEncoder().String(fw.Name)
if err != nil {
return res
}
@@ -355,7 +348,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.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
@@ -394,7 +387,7 @@ func HandleSetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
}
}
- fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, t.GetField(hotline.FieldFileNewName).Data)
+ fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, t.GetField(hotline.FieldFileNewName).Data, cc.TextDecoder())
if err != nil {
return nil
}
@@ -416,11 +409,11 @@ func HandleSetFileInfo(cc *hotline.ClientConn, t *hotline.Transaction) (res []ho
if !cc.Authorize(hotline.AccessRenameFile) {
return cc.NewErrReply(t, ErrMsgNotAllowedRenameFiles)
}
- fileDir, err := hotline.ReadPath(cc.FileRoot(), filePath, []byte{})
+ fileDir, err := hotline.ReadPath(cc.FileRoot(), filePath, []byte{}, cc.TextDecoder())
if err != nil {
return nil
}
- hlFile.Name, err = txtDecoder.String(string(fileNewName))
+ hlFile.Name, err = cc.TextDecoder().String(string(fileNewName))
if err != nil {
return res
}
@@ -452,7 +445,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.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
@@ -497,12 +490,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.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, cc.TextDecoder())
if err != nil {
return res
}
- fileNewPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFileNewPath).Data, nil)
+ fileNewPath, err := hotline.ReadPath(cc.FileRoot(), t.GetField(hotline.FieldFileNewPath).Data, nil, cc.TextDecoder())
if err != nil {
return res
}
@@ -571,11 +564,11 @@ func HandleNewFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res []hotl
// 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)
+ subPath, err := cc.TextDecoder().String(subPath)
if err != nil {
return res
}
- folderName, err = txtDecoder.String(folderName)
+ folderName, err = cc.TextDecoder().String(folderName)
if err != nil {
return res
}
@@ -1594,7 +1587,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.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
@@ -1658,7 +1651,7 @@ func HandleDownloadFolder(cc *hotline.ClientConn, t *hotline.Transaction) (res [
return cc.NewErrReply(t, ErrMsgNotAllowedDownloadFolders)
}
- fullFilePath, err := hotline.ReadPath(cc.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, cc.TextDecoder())
if err != nil {
return nil
}
@@ -1769,7 +1762,7 @@ func HandleUploadFile(cc *hotline.ClientConn, t *hotline.Transaction) (res []hot
return cc.NewErrReply(t, fmt.Sprintf(ErrMsgUploadRestrictedTemplate, "file", string(fileName)))
}
}
- fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
@@ -1911,15 +1904,18 @@ func HandleGetFileNameList(cc *hotline.ClientConn, t *hotline.Transaction) (res
cc.FileRoot(),
t.GetField(hotline.FieldFilePath).Data,
nil,
+ cc.TextDecoder(),
)
if err != nil {
- return res
+ cc.Logger.Error("error reading file path", "err", err)
+ return cc.NewErrReply(t, "Cannot get file list.")
}
var fp hotline.FilePath
if t.GetField(hotline.FieldFilePath).Data != nil {
if _, err = fp.Write(t.GetField(hotline.FieldFilePath).Data); err != nil {
- return res
+ cc.Logger.Error("error parsing file path", "err", err)
+ return cc.NewErrReply(t, "Cannot get file list.")
}
}
@@ -1928,9 +1924,10 @@ func HandleGetFileNameList(cc *hotline.ClientConn, t *hotline.Transaction) (res
return cc.NewErrReply(t, ErrMsgNotAllowedViewDropBoxes)
}
- fileNames, err := hotline.GetFileNameList(fullPath, cc.Server.Config.IgnoreFiles)
+ fileNames, err := hotline.GetFileNameList(fullPath, cc.Server.Config.IgnoreFiles, cc.TextEncoder(), cc.Logger)
if err != nil {
- return res
+ cc.Logger.Error("error getting file name list", "err", err)
+ return cc.NewErrReply(t, "Cannot get file list.")
}
res = append(res, cc.NewReply(t, fileNames...))
@@ -2186,12 +2183,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.FileRoot(), filePath, fileName)
+ fullFilePath, err := hotline.ReadPath(cc.FileRoot(), filePath, fileName, cc.TextDecoder())
if err != nil {
return res
}
- fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), fileNewPath, fileName)
+ fullNewFilePath, err := hotline.ReadPath(cc.FileRoot(), fileNewPath, fileName, cc.TextDecoder())
if err != nil {
return res
}
diff --git a/internal/mobius/transaction_handlers_test.go b/internal/mobius/transaction_handlers_test.go
index 9e995b5..e9dfdfc 100644
--- a/internal/mobius/transaction_handlers_test.go
+++ b/internal/mobius/transaction_handlers_test.go
@@ -17,6 +17,7 @@ import (
"github.com/jhalter/mobius/hotline"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ "golang.org/x/text/encoding/charmap"
)
type mockReadWriteSeeker struct {
@@ -113,6 +114,8 @@ func TestHandleSetChatSubject(t *testing.T) {
cc: &hotline.ClientConn{
UserName: []byte{0x00, 0x01},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
m.On("Members", hotline.ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*hotline.ClientConn{
@@ -227,6 +230,8 @@ func TestHandleLeaveChat(t *testing.T) {
cc: &hotline.ClientConn{
ID: [2]byte{0, 2},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
m.On("Members", hotline.ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*hotline.ClientConn{
@@ -302,6 +307,8 @@ func TestHandleGetUserNameList(t *testing.T) {
cc: &hotline.ClientConn{
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -374,6 +381,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte{0x00, 0x01},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -435,6 +444,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte{0x00, 0x01},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -491,6 +502,8 @@ func TestHandleChatSend(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -522,6 +535,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte("Testy McTest"),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -584,6 +599,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte("Testy McTest"),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -642,6 +659,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte{0x00, 0x01},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -694,6 +713,8 @@ func TestHandleChatSend(t *testing.T) {
},
UserName: []byte{0x00, 0x01},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
m.On("Members", hotline.ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*hotline.ClientConn{
@@ -786,6 +807,8 @@ func TestHandleGetFileInfo(t *testing.T) {
ID: [2]byte{0, 1},
Account: &hotline.Account{},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
FS: &hotline.OSFileStore{},
Config: hotline.Config{
FileRoot: func() string {
@@ -884,6 +907,8 @@ func TestHandleNewFolder(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: "/Files/",
},
@@ -926,6 +951,8 @@ func TestHandleNewFolder(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: "/Files",
},
@@ -962,6 +989,8 @@ func TestHandleNewFolder(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: "/Files/",
},
@@ -996,6 +1025,8 @@ func TestHandleNewFolder(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: "/Files/",
},
@@ -1032,6 +1063,8 @@ func TestHandleNewFolder(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: "/Files/",
},
@@ -1091,6 +1124,8 @@ func TestHandleUploadFile(t *testing.T) {
args: args{
cc: &hotline.ClientConn{
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
FS: &hotline.OSFileStore{},
FileTransferMgr: hotline.NewMemFileTransferMgr(),
Config: hotline.Config{
@@ -1190,6 +1225,8 @@ func TestHandleMakeAlias(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
path, _ := os.Getwd()
@@ -1236,6 +1273,8 @@ func TestHandleMakeAlias(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
path, _ := os.Getwd()
@@ -1281,6 +1320,8 @@ func TestHandleMakeAlias(t *testing.T) {
Access: hotline.AccessBitmap{},
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
path, _ := os.Getwd()
@@ -1347,6 +1388,8 @@ func TestHandleGetUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "guest").Return(&hotline.Account{
@@ -1387,6 +1430,8 @@ func TestHandleGetUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -1417,6 +1462,8 @@ func TestHandleGetUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "nonExistentUser").Return((*hotline.Account)(nil))
@@ -1472,6 +1519,8 @@ func TestHandleDeleteUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Delete", "testuser").Return(nil)
@@ -1506,6 +1555,8 @@ func TestHandleDeleteUser(t *testing.T) {
Access: hotline.AccessBitmap{},
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -1555,6 +1606,8 @@ func TestHandleGetMsgs(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
MessageBoard: func() *mockReadWriteSeeker {
m := mockReadWriteSeeker{}
m.On("Seek", int64(0), 0).Return(int64(0), nil)
@@ -1592,6 +1645,8 @@ func TestHandleGetMsgs(t *testing.T) {
},
Logger: NewTestLogger(),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
MessageBoard: func() *mockReadWriteSeeker {
m := mockReadWriteSeeker{}
m.On("Seek", int64(0), 0).Return(int64(0), nil)
@@ -1622,6 +1677,8 @@ func TestHandleGetMsgs(t *testing.T) {
Access: hotline.AccessBitmap{},
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -1669,6 +1726,8 @@ func TestHandleNewUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -1698,6 +1757,8 @@ func TestHandleNewUser(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "userB").Return((*hotline.Account)(nil))
@@ -1758,6 +1819,8 @@ func TestHandleListUsers(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -1787,6 +1850,8 @@ func TestHandleListUsers(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("List").Return([]hotline.Account{
@@ -1849,7 +1914,7 @@ func TestHandleDownloadFile(t *testing.T) {
return bits
}(),
},
- Server: &hotline.Server{},
+ Server: &hotline.Server{TextDecoder: charmap.Macintosh.NewDecoder(), TextEncoder: charmap.Macintosh.NewEncoder()},
},
t: hotline.NewTransaction(hotline.TranDownloadFile, [2]byte{0, 1}),
},
@@ -1876,6 +1941,8 @@ func TestHandleDownloadFile(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
FS: &hotline.OSFileStore{},
FileTransferMgr: hotline.NewMemFileTransferMgr(),
Config: hotline.Config{
@@ -1915,6 +1982,8 @@ func TestHandleDownloadFile(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
FS: &hotline.OSFileStore{},
// FS: func() *hotline.MockFileStore {
@@ -2005,6 +2074,8 @@ func TestHandleUpdateUser(t *testing.T) {
cc: &hotline.ClientConn{
Logger: NewTestLogger(),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "bbb").Return((*hotline.Account)(nil))
@@ -2056,6 +2127,8 @@ func TestHandleUpdateUser(t *testing.T) {
cc: &hotline.ClientConn{
Logger: NewTestLogger(),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Logger: NewTestLogger(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
@@ -2109,7 +2182,7 @@ func TestHandleUpdateUser(t *testing.T) {
args: args{
cc: &hotline.ClientConn{
Logger: NewTestLogger(),
- Server: &hotline.Server{},
+ Server: &hotline.Server{TextDecoder: charmap.Macintosh.NewDecoder(), TextEncoder: charmap.Macintosh.NewEncoder()},
Account: &hotline.Account{
Access: hotline.AccessBitmap{},
},
@@ -2194,6 +2267,8 @@ func TestHandleDelNewsArt(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("DeleteArticle", []string{"test"}, uint32(1), false).Return(errors.New("write error"))
@@ -2275,6 +2350,8 @@ func TestHandleDisconnectUser(t *testing.T) {
args: args{
cc: &hotline.ClientConn{
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x1}).Return(&hotline.ClientConn{
@@ -2374,6 +2451,8 @@ func TestHandleSendInstantMsg(t *testing.T) {
ID: [2]byte{0, 1},
UserName: []byte("User1"),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x2}).Return(&hotline.ClientConn{
@@ -2422,6 +2501,8 @@ func TestHandleSendInstantMsg(t *testing.T) {
ID: [2]byte{0, 1},
UserName: []byte("User1"),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x2}).Return(&hotline.ClientConn{
@@ -2479,6 +2560,8 @@ func TestHandleSendInstantMsg(t *testing.T) {
ID: [2]byte{0, 1},
UserName: []byte("User1"),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x2}).Return(&hotline.ClientConn{
@@ -2544,6 +2627,8 @@ func TestHandleDeleteFile(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
return "/fakeRoot/Files"
@@ -2600,6 +2685,8 @@ func TestHandleDeleteFile(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
return "/fakeRoot/Files"
@@ -2678,6 +2765,8 @@ func TestHandleGetFileNameList(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
FileRoot: func() string {
@@ -2717,7 +2806,7 @@ func TestHandleGetFileNameList(t *testing.T) {
return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
}(),
},
- Server: &hotline.Server{},
+ Server: &hotline.Server{TextDecoder: charmap.Macintosh.NewDecoder(), TextEncoder: charmap.Macintosh.NewEncoder()},
},
t: hotline.NewTransaction(
hotline.TranGetFileNameList, [2]byte{0, 1},
@@ -2783,6 +2872,8 @@ func TestHandleGetClientInfoText(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -2817,6 +2908,8 @@ func TestHandleGetClientInfoText(t *testing.T) {
Login: "test",
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x1}).Return(&hotline.ClientConn{
@@ -2916,6 +3009,8 @@ func TestHandleTranAgreed(t *testing.T) {
ID: [2]byte{0, 1},
Logger: NewTestLogger(),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
BannerFile: "Banner.jpg",
},
@@ -2971,6 +3066,8 @@ func TestHandleTranAgreed(t *testing.T) {
ID: [2]byte{0, 1},
Logger: NewTestLogger(),
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
BannerFile: "Banner.gif",
},
@@ -3036,6 +3133,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
UserName: []byte("Guest"),
Flags: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3080,6 +3179,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
UserName: []byte("Guest"),
Flags: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3122,6 +3223,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
UserName: []byte("Guest"),
Flags: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3164,6 +3267,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
UserName: []byte("Guest"),
Flags: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3207,6 +3312,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
Flags: [2]byte{0, 1},
Version: []byte{0x01, 0x03},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3251,6 +3358,8 @@ func TestHandleSetClientUserInfo(t *testing.T) {
Flags: [2]byte{0, 1},
Version: []byte{0x01, 0x03},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("List").Return([]*hotline.ClientConn{
@@ -3307,6 +3416,8 @@ func TestHandleDelNewsItem(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("NewsItem", []string{"test"}).Return(hotline.NewsCategoryListData15{
@@ -3348,6 +3459,8 @@ func TestHandleDelNewsItem(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("NewsItem", []string{"test"}).Return(hotline.NewsCategoryListData15{
@@ -3393,6 +3506,8 @@ func TestHandleDelNewsItem(t *testing.T) {
},
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("NewsItem", []string{"test"}).Return(hotline.NewsCategoryListData15{Type: hotline.NewsBundle})
@@ -3476,6 +3591,8 @@ func TestHandleTranOldPostNews(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
Config: hotline.Config{
NewsDateFormat: "",
},
@@ -3566,6 +3683,8 @@ func TestHandleInviteNewChat(t *testing.T) {
Icon: []byte{0, 1},
Flags: [2]byte{0, 0},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0x0, 0x2}).Return(&hotline.ClientConn{
@@ -3625,6 +3744,8 @@ func TestHandleInviteNewChat(t *testing.T) {
Icon: []byte{0, 1},
Flags: [2]byte{0, 0},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ClientMgr: func() *hotline.MockClientMgr {
m := hotline.MockClientMgr{}
m.On("Get", hotline.ClientID{0, 2}).Return(&hotline.ClientConn{
@@ -3722,6 +3843,8 @@ func TestHandleGetNewsArtData(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("GetArticle", []string{"Example Category"}, uint32(1)).Return(&hotline.NewsArtData{
@@ -3795,6 +3918,8 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -3826,6 +3951,8 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
// }(),
// },
// Server: &hotline.Server{
+ // TextDecoder: charmap.Macintosh.NewDecoder(),
+ // TextEncoder: charmap.Macintosh.NewEncoder(),
// ThreadedNewsMgr: func() *mockThreadNewsMgr {
// m := mockThreadNewsMgr{}
// m.On("ListArticles", []string{"Example Category"}).Return(NewsArtListData{
@@ -3893,6 +4020,8 @@ func TestHandleNewNewsFldr(t *testing.T) {
}(),
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
//Accounts: map[string]*Account{},
},
},
@@ -3926,6 +4055,8 @@ func TestHandleNewNewsFldr(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("CreateGrouping", []string{"test"}, "testFolder", hotline.NewsBundle).Return(nil)
@@ -3968,6 +4099,8 @@ func TestHandleNewNewsFldr(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("CreateGrouping", []string{"test"}, "testFolder", hotline.NewsBundle).Return(errors.New("write error"))
@@ -4071,6 +4204,8 @@ func TestHandlePostNewsArt(t *testing.T) {
args: args{
cc: &hotline.ClientConn{
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("PostArticle", []string{"www"}, uint32(0), mock.AnythingOfType("hotline.NewsArtData")).Return(nil)
@@ -4105,6 +4240,8 @@ func TestHandlePostNewsArt(t *testing.T) {
args: args{
cc: &hotline.ClientConn{
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("PostArticle", []string{"www"}, uint32(0), mock.AnythingOfType("hotline.NewsArtData")).Return(errors.New("write error"))
@@ -4261,6 +4398,8 @@ func TestHandleJoinChat(t *testing.T) {
Access: hotline.AccessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
// Mock existing members before join
@@ -4377,6 +4516,8 @@ func TestHandleJoinChat(t *testing.T) {
Access: hotline.AccessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
// Mock empty chat before join
@@ -4446,6 +4587,8 @@ func TestHandleRejectChatInvite(t *testing.T) {
UserName: []byte("RejectUser"),
ID: [2]byte{0, 3},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
// Mock current members of the chat
@@ -4497,6 +4640,8 @@ func TestHandleRejectChatInvite(t *testing.T) {
UserName: []byte("LoneRejecter"),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
// Mock empty chat (no members)
@@ -4524,6 +4669,8 @@ func TestHandleRejectChatInvite(t *testing.T) {
UserName: []byte("Shy"),
ID: [2]byte{0, 2},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ChatMgr: func() *hotline.MockChatManager {
m := hotline.MockChatManager{}
// Mock chat with single member
@@ -4738,7 +4885,7 @@ func TestHandleSetUser(t *testing.T) {
return bits
}(),
},
- Server: &hotline.Server{},
+ Server: &hotline.Server{TextDecoder: charmap.Macintosh.NewDecoder(), TextEncoder: charmap.Macintosh.NewEncoder()},
},
t: hotline.NewTransaction(
hotline.TranSetUser, [2]byte{0, 1},
@@ -4770,6 +4917,8 @@ func TestHandleSetUser(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "testuser").Return((*hotline.Account)(nil))
@@ -4809,6 +4958,8 @@ func TestHandleSetUser(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
AccountManager: func() *MockAccountManager {
m := MockAccountManager{}
m.On("Get", "testuser").Return(&hotline.Account{
@@ -4868,7 +5019,7 @@ func TestHandleNewNewsCat(t *testing.T) {
return bits
}(),
},
- Server: &hotline.Server{},
+ Server: &hotline.Server{TextDecoder: charmap.Macintosh.NewDecoder(), TextEncoder: charmap.Macintosh.NewEncoder()},
},
t: hotline.NewTransaction(
hotline.TranNewNewsCat, [2]byte{0, 1},
@@ -4900,6 +5051,8 @@ func TestHandleNewNewsCat(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("CreateGrouping", []string{"test"}, "TestCat", hotline.NewsCategory).Return(errors.New("write error"))
@@ -4945,6 +5098,8 @@ func TestHandleNewNewsCat(t *testing.T) {
Logger: NewTestLogger(),
ID: [2]byte{0, 1},
Server: &hotline.Server{
+ TextDecoder: charmap.Macintosh.NewDecoder(),
+ TextEncoder: charmap.Macintosh.NewEncoder(),
ThreadedNewsMgr: func() *hotline.MockThreadNewsMgr {
m := hotline.MockThreadNewsMgr{}
m.On("CreateGrouping", []string{"test"}, "TestCat", hotline.NewsCategory).Return(nil)