]> git.r.bdr.sh - rbdr/mobius/commitdiff
Initial refactor to split client from protocol package
authorJeff Halter <redacted>
Mon, 27 Mar 2023 04:10:03 +0000 (21:10 -0700)
committerJeff Halter <redacted>
Mon, 27 Mar 2023 04:10:03 +0000 (21:10 -0700)
13 files changed:
cmd/mobius-hotline-client/main.go
hotline/account.go
hotline/client.go
hotline/client_conn.go
hotline/field.go
hotline/files.go
hotline/server.go
hotline/transaction.go
hotline/transaction_handlers.go
hotline/transaction_handlers_test.go
hotline/transaction_test.go
hotline/ui.go
hotline/user.go

index 4bd40c9b124ff7fd49888dae8f5a01584f044608..33100bf02457e75e7d7b6948800734cb916ecca5 100644 (file)
@@ -71,7 +71,7 @@ func main() {
                cancelRoot()
        }()
 
                cancelRoot()
        }()
 
-       client := hotline.NewClient(*configDir, logger)
+       client := hotline.NewUIClient(*configDir, logger)
        client.DebugBuf = db
        client.UI.Start()
 
        client.DebugBuf = db
        client.UI.Start()
 
index 9a0fb7dea55f56dcf0aace97223e0e32fac69650..c51162d3c8b70c0388367db9ddbdc4c42c49ce43 100644 (file)
@@ -18,13 +18,13 @@ type Account struct {
 // Read implements io.Reader interface for Account
 func (a *Account) Read(p []byte) (n int, err error) {
        fields := []Field{
 // Read implements io.Reader interface for Account
 func (a *Account) Read(p []byte) (n int, err error) {
        fields := []Field{
-               NewField(fieldUserName, []byte(a.Name)),
-               NewField(fieldUserLogin, negateString([]byte(a.Login))),
-               NewField(fieldUserAccess, a.Access[:]),
+               NewField(FieldUserName, []byte(a.Name)),
+               NewField(FieldUserLogin, negateString([]byte(a.Login))),
+               NewField(FieldUserAccess, a.Access[:]),
        }
 
        if bcrypt.CompareHashAndPassword([]byte(a.Password), []byte("")) != nil {
        }
 
        if bcrypt.CompareHashAndPassword([]byte(a.Password), []byte("")) != nil {
-               fields = append(fields, NewField(fieldUserPassword, []byte("x")))
+               fields = append(fields, NewField(FieldUserPassword, []byte("x")))
        }
 
        fieldCount := make([]byte, 2)
        }
 
        fieldCount := make([]byte, 2)
index c7c1463b118e4d5aa2a68fcb6cd8b456e137833e..6abe62322bfd3c95d6fc99f0b5137190a682edb5 100644 (file)
@@ -1,6 +1,7 @@
 package hotline
 
 import (
 package hotline
 
 import (
+       "bufio"
        "bytes"
        "embed"
        "encoding/binary"
        "bytes"
        "embed"
        "encoding/binary"
@@ -72,11 +73,6 @@ type Client struct {
        cfgPath     string
        DebugBuf    *DebugBuffer
        Connection  net.Conn
        cfgPath     string
        DebugBuf    *DebugBuffer
        Connection  net.Conn
-       Login       *[]byte
-       Password    *[]byte
-       Flags       *[]byte
-       ID          *[]byte
-       Version     []byte
        UserAccess  []byte
        filePath    []string
        UserList    []User
        UserAccess  []byte
        filePath    []string
        UserList    []User
@@ -84,16 +80,27 @@ type Client struct {
        activeTasks map[uint32]*Transaction
        serverName  string
 
        activeTasks map[uint32]*Transaction
        serverName  string
 
-       pref *ClientPrefs
+       Pref *ClientPrefs
 
 
-       Handlers map[uint16]clientTHandler
+       Handlers map[uint16]ClientTHandler
 
        UI *UI
 
        Inbox chan *Transaction
 }
 
 
        UI *UI
 
        Inbox chan *Transaction
 }
 
-func NewClient(cfgPath string, logger *zap.SugaredLogger) *Client {
+func NewClient(username string, logger *zap.SugaredLogger) *Client {
+       c := &Client{
+               Logger:      logger,
+               activeTasks: make(map[uint32]*Transaction),
+               Handlers:    make(map[uint16]ClientTHandler),
+       }
+       c.Pref = &ClientPrefs{Username: username}
+
+       return c
+}
+
+func NewUIClient(cfgPath string, logger *zap.SugaredLogger) *Client {
        c := &Client{
                cfgPath:     cfgPath,
                Logger:      logger,
        c := &Client{
                cfgPath:     cfgPath,
                Logger:      logger,
@@ -106,7 +113,7 @@ func NewClient(cfgPath string, logger *zap.SugaredLogger) *Client {
        if err != nil {
                logger.Fatal(fmt.Sprintf("unable to read config file %s\n", cfgPath))
        }
        if err != nil {
                logger.Fatal(fmt.Sprintf("unable to read config file %s\n", cfgPath))
        }
-       c.pref = prefs
+       c.Pref = prefs
 
        return c
 }
 
        return c
 }
@@ -134,16 +141,16 @@ func randomBanner() string {
        return fmt.Sprintf("\n\n\nWelcome to...\n\n[red::b]%s[-:-:-]\n\n", file)
 }
 
        return fmt.Sprintf("\n\n\nWelcome to...\n\n[red::b]%s[-:-:-]\n\n", file)
 }
 
-type clientTransaction struct {
+type ClientTransaction struct {
        Name    string
        Handler func(*Client, *Transaction) ([]Transaction, error)
 }
 
        Name    string
        Handler func(*Client, *Transaction) ([]Transaction, error)
 }
 
-func (ch clientTransaction) Handle(cc *Client, t *Transaction) ([]Transaction, error) {
+func (ch ClientTransaction) Handle(cc *Client, t *Transaction) ([]Transaction, error) {
        return ch.Handler(cc, t)
 }
 
        return ch.Handler(cc, t)
 }
 
-type clientTHandler interface {
+type ClientTHandler interface {
        Handle(*Client, *Transaction) ([]Transaction, error)
 }
 
        Handle(*Client, *Transaction) ([]Transaction, error)
 }
 
@@ -156,50 +163,50 @@ func (mh *mockClientHandler) Handle(cc *Client, t *Transaction) ([]Transaction,
        return args.Get(0).([]Transaction), args.Error(1)
 }
 
        return args.Get(0).([]Transaction), args.Error(1)
 }
 
-var clientHandlers = map[uint16]clientTHandler{
+var clientHandlers = map[uint16]ClientTHandler{
        // Server initiated
        // Server initiated
-       tranChatMsg: clientTransaction{
-               Name:    "tranChatMsg",
+       TranChatMsg: ClientTransaction{
+               Name:    "TranChatMsg",
                Handler: handleClientChatMsg,
        },
                Handler: handleClientChatMsg,
        },
-       tranLogin: clientTransaction{
-               Name:    "tranLogin",
+       TranLogin: ClientTransaction{
+               Name:    "TranLogin",
                Handler: handleClientTranLogin,
        },
                Handler: handleClientTranLogin,
        },
-       tranShowAgreement: clientTransaction{
-               Name:    "tranShowAgreement",
+       TranShowAgreement: ClientTransaction{
+               Name:    "TranShowAgreement",
                Handler: handleClientTranShowAgreement,
        },
                Handler: handleClientTranShowAgreement,
        },
-       tranUserAccess: clientTransaction{
-               Name:    "tranUserAccess",
+       TranUserAccess: ClientTransaction{
+               Name:    "TranUserAccess",
                Handler: handleClientTranUserAccess,
        },
                Handler: handleClientTranUserAccess,
        },
-       tranGetUserNameList: clientTransaction{
-               Name:    "tranGetUserNameList",
+       TranGetUserNameList: ClientTransaction{
+               Name:    "TranGetUserNameList",
                Handler: handleClientGetUserNameList,
        },
                Handler: handleClientGetUserNameList,
        },
-       tranNotifyChangeUser: clientTransaction{
-               Name:    "tranNotifyChangeUser",
+       TranNotifyChangeUser: ClientTransaction{
+               Name:    "TranNotifyChangeUser",
                Handler: handleNotifyChangeUser,
        },
                Handler: handleNotifyChangeUser,
        },
-       tranNotifyDeleteUser: clientTransaction{
-               Name:    "tranNotifyDeleteUser",
+       TranNotifyDeleteUser: ClientTransaction{
+               Name:    "TranNotifyDeleteUser",
                Handler: handleNotifyDeleteUser,
        },
                Handler: handleNotifyDeleteUser,
        },
-       tranGetMsgs: clientTransaction{
-               Name:    "tranNotifyDeleteUser",
+       TranGetMsgs: ClientTransaction{
+               Name:    "TranNotifyDeleteUser",
                Handler: handleGetMsgs,
        },
                Handler: handleGetMsgs,
        },
-       tranGetFileNameList: clientTransaction{
-               Name:    "tranGetFileNameList",
+       TranGetFileNameList: ClientTransaction{
+               Name:    "TranGetFileNameList",
                Handler: handleGetFileNameList,
        },
                Handler: handleGetFileNameList,
        },
-       tranServerMsg: clientTransaction{
-               Name:    "tranServerMsg",
+       TranServerMsg: ClientTransaction{
+               Name:    "TranServerMsg",
                Handler: handleTranServerMsg,
        },
                Handler: handleTranServerMsg,
        },
-       tranKeepAlive: clientTransaction{
-               Name: "tranKeepAlive",
+       TranKeepAlive: ClientTransaction{
+               Name: "TranKeepAlive",
                Handler: func(client *Client, transaction *Transaction) (t []Transaction, err error) {
                        return t, err
                },
                Handler: func(client *Client, transaction *Transaction) (t []Transaction, err error) {
                        return t, err
                },
@@ -209,9 +216,9 @@ var clientHandlers = map[uint16]clientTHandler{
 func handleTranServerMsg(c *Client, t *Transaction) (res []Transaction, err error) {
        time := time.Now().Format(time.RFC850)
 
 func handleTranServerMsg(c *Client, t *Transaction) (res []Transaction, err error) {
        time := time.Now().Format(time.RFC850)
 
-       msg := strings.ReplaceAll(string(t.GetField(fieldData).Data), "\r", "\n")
+       msg := strings.ReplaceAll(string(t.GetField(FieldData).Data), "\r", "\n")
        msg += "\n\nAt " + time
        msg += "\n\nAt " + time
-       title := fmt.Sprintf("| Private Message From:   %s |", t.GetField(fieldUserName).Data)
+       title := fmt.Sprintf("| Private Message From:   %s |", t.GetField(FieldUserName).Data)
 
        msgBox := tview.NewTextView().SetScrollable(true)
        msgBox.SetText(msg).SetBackgroundColor(tcell.ColorDarkSlateBlue)
 
        msgBox := tview.NewTextView().SetScrollable(true)
        msgBox.SetText(msg).SetBackgroundColor(tcell.ColorDarkSlateBlue)
@@ -268,8 +275,8 @@ func (c *Client) showErrMsg(msg string) {
 
 func handleGetFileNameList(c *Client, t *Transaction) (res []Transaction, err error) {
        if t.IsError() {
 
 func handleGetFileNameList(c *Client, t *Transaction) (res []Transaction, err error) {
        if t.IsError() {
-               c.showErrMsg(string(t.GetField(fieldError).Data))
-               c.Logger.Infof("Error: %s", t.GetField(fieldError).Data)
+               c.showErrMsg(string(t.GetField(FieldError).Data))
+               c.Logger.Infof("Error: %s", t.GetField(FieldError).Data)
                return res, err
        }
 
                return res, err
        }
 
@@ -287,9 +294,9 @@ func handleGetFileNameList(c *Client, t *Transaction) (res []Transaction, err er
 
                        if selectedNode.GetText() == "<- Back" {
                                c.filePath = c.filePath[:len(c.filePath)-1]
 
                        if selectedNode.GetText() == "<- Back" {
                                c.filePath = c.filePath[:len(c.filePath)-1]
-                               f := NewField(fieldFilePath, EncodeFilePath(strings.Join(c.filePath, "/")))
+                               f := NewField(FieldFilePath, EncodeFilePath(strings.Join(c.filePath, "/")))
 
 
-                               if err := c.UI.HLClient.Send(*NewTransaction(tranGetFileNameList, nil, f)); err != nil {
+                               if err := c.UI.HLClient.Send(*NewTransaction(TranGetFileNameList, nil, f)); err != nil {
                                        c.UI.HLClient.Logger.Errorw("err", "err", err)
                                }
                                return event
                                        c.UI.HLClient.Logger.Errorw("err", "err", err)
                                }
                                return event
@@ -301,9 +308,9 @@ func handleGetFileNameList(c *Client, t *Transaction) (res []Transaction, err er
                                c.Logger.Infow("get new directory listing", "name", string(entry.name))
 
                                c.filePath = append(c.filePath, string(entry.name))
                                c.Logger.Infow("get new directory listing", "name", string(entry.name))
 
                                c.filePath = append(c.filePath, string(entry.name))
-                               f := NewField(fieldFilePath, EncodeFilePath(strings.Join(c.filePath, "/")))
+                               f := NewField(FieldFilePath, EncodeFilePath(strings.Join(c.filePath, "/")))
 
 
-                               if err := c.UI.HLClient.Send(*NewTransaction(tranGetFileNameList, nil, f)); err != nil {
+                               if err := c.UI.HLClient.Send(*NewTransaction(TranGetFileNameList, nil, f)); err != nil {
                                        c.UI.HLClient.Logger.Errorw("err", "err", err)
                                }
                        } else {
                                        c.UI.HLClient.Logger.Errorw("err", "err", err)
                                }
                        } else {
@@ -357,7 +364,7 @@ func handleGetFileNameList(c *Client, t *Transaction) (res []Transaction, err er
 }
 
 func handleGetMsgs(c *Client, t *Transaction) (res []Transaction, err error) {
 }
 
 func handleGetMsgs(c *Client, t *Transaction) (res []Transaction, err error) {
-       newsText := string(t.GetField(fieldData).Data)
+       newsText := string(t.GetField(FieldData).Data)
        newsText = strings.ReplaceAll(newsText, "\r", "\n")
 
        newsTextView := tview.NewTextView().
        newsText = strings.ReplaceAll(newsText, "\r", "\n")
 
        newsTextView := tview.NewTextView().
@@ -378,10 +385,10 @@ func handleGetMsgs(c *Client, t *Transaction) (res []Transaction, err error) {
 
 func handleNotifyChangeUser(c *Client, t *Transaction) (res []Transaction, err error) {
        newUser := User{
 
 func handleNotifyChangeUser(c *Client, t *Transaction) (res []Transaction, err error) {
        newUser := User{
-               ID:    t.GetField(fieldUserID).Data,
-               Name:  string(t.GetField(fieldUserName).Data),
-               Icon:  t.GetField(fieldUserIconID).Data,
-               Flags: t.GetField(fieldUserFlags).Data,
+               ID:    t.GetField(FieldUserID).Data,
+               Name:  string(t.GetField(FieldUserName).Data),
+               Icon:  t.GetField(FieldUserIconID).Data,
+               Flags: t.GetField(FieldUserFlags).Data,
        }
 
        // Possible cases:
        }
 
        // Possible cases:
@@ -416,7 +423,7 @@ func handleNotifyChangeUser(c *Client, t *Transaction) (res []Transaction, err e
 }
 
 func handleNotifyDeleteUser(c *Client, t *Transaction) (res []Transaction, err error) {
 }
 
 func handleNotifyDeleteUser(c *Client, t *Transaction) (res []Transaction, err error) {
-       exitUser := t.GetField(fieldUserID).Data
+       exitUser := t.GetField(FieldUserID).Data
 
        var newUserList []User
        for _, u := range c.UserList {
 
        var newUserList []User
        for _, u := range c.UserList {
@@ -435,8 +442,8 @@ func handleNotifyDeleteUser(c *Client, t *Transaction) (res []Transaction, err e
 func handleClientGetUserNameList(c *Client, t *Transaction) (res []Transaction, err error) {
        var users []User
        for _, field := range t.Fields {
 func handleClientGetUserNameList(c *Client, t *Transaction) (res []Transaction, err error) {
        var users []User
        for _, field := range t.Fields {
-               // The Hotline protocol docs say that ClientGetUserNameList should only return fieldUsernameWithInfo (300)
-               // fields, but shxd sneaks in fieldChatSubject (115) so it's important to filter explicitly for the expected
+               // The Hotline protocol docs say that ClientGetUserNameList should only return FieldUsernameWithInfo (300)
+               // fields, but shxd sneaks in FieldChatSubject (115) so it's important to filter explicitly for the expected
                // field type.  Probably a good idea to do everywhere.
                if bytes.Equal(field.ID, []byte{0x01, 0x2c}) {
                        u, err := ReadUser(field.Data)
                // field type.  Probably a good idea to do everywhere.
                if bytes.Equal(field.ID, []byte{0x01, 0x2c}) {
                        u, err := ReadUser(field.Data)
@@ -467,23 +474,23 @@ func (c *Client) renderUserList() {
 }
 
 func handleClientChatMsg(c *Client, t *Transaction) (res []Transaction, err error) {
 }
 
 func handleClientChatMsg(c *Client, t *Transaction) (res []Transaction, err error) {
-       if c.pref.EnableBell {
+       if c.Pref.EnableBell {
                fmt.Println("\a")
        }
 
                fmt.Println("\a")
        }
 
-       _, _ = fmt.Fprintf(c.UI.chatBox, "%s \n", t.GetField(fieldData).Data)
+       _, _ = fmt.Fprintf(c.UI.chatBox, "%s \n", t.GetField(FieldData).Data)
 
        return res, err
 }
 
 func handleClientTranUserAccess(c *Client, t *Transaction) (res []Transaction, err error) {
 
        return res, err
 }
 
 func handleClientTranUserAccess(c *Client, t *Transaction) (res []Transaction, err error) {
-       c.UserAccess = t.GetField(fieldUserAccess).Data
+       c.UserAccess = t.GetField(FieldUserAccess).Data
 
        return res, err
 }
 
 func handleClientTranShowAgreement(c *Client, t *Transaction) (res []Transaction, err error) {
 
        return res, err
 }
 
 func handleClientTranShowAgreement(c *Client, t *Transaction) (res []Transaction, err error) {
-       agreement := string(t.GetField(fieldData).Data)
+       agreement := string(t.GetField(FieldData).Data)
        agreement = strings.ReplaceAll(agreement, "\r", "\n")
 
        agreeModal := tview.NewModal().
        agreement = strings.ReplaceAll(agreement, "\r", "\n")
 
        agreeModal := tview.NewModal().
@@ -493,11 +500,11 @@ func handleClientTranShowAgreement(c *Client, t *Transaction) (res []Transaction
                        if buttonIndex == 0 {
                                res = append(res,
                                        *NewTransaction(
                        if buttonIndex == 0 {
                                res = append(res,
                                        *NewTransaction(
-                                               tranAgreed, nil,
-                                               NewField(fieldUserName, []byte(c.pref.Username)),
-                                               NewField(fieldUserIconID, c.pref.IconBytes()),
-                                               NewField(fieldUserFlags, []byte{0x00, 0x00}),
-                                               NewField(fieldOptions, []byte{0x00, 0x00}),
+                                               TranAgreed, nil,
+                                               NewField(FieldUserName, []byte(c.Pref.Username)),
+                                               NewField(FieldUserIconID, c.Pref.IconBytes()),
+                                               NewField(FieldUserFlags, []byte{0x00, 0x00}),
+                                               NewField(FieldOptions, []byte{0x00, 0x00}),
                                        ),
                                )
                                c.UI.Pages.HidePage("agreement")
                                        ),
                                )
                                c.UI.Pages.HidePage("agreement")
@@ -516,7 +523,7 @@ func handleClientTranShowAgreement(c *Client, t *Transaction) (res []Transaction
 
 func handleClientTranLogin(c *Client, t *Transaction) (res []Transaction, err error) {
        if !bytes.Equal(t.ErrorCode, []byte{0, 0, 0, 0}) {
 
 func handleClientTranLogin(c *Client, t *Transaction) (res []Transaction, err error) {
        if !bytes.Equal(t.ErrorCode, []byte{0, 0, 0, 0}) {
-               errMsg := string(t.GetField(fieldError).Data)
+               errMsg := string(t.GetField(FieldError).Data)
                errModal := tview.NewModal()
                errModal.SetText(errMsg)
                errModal.AddButtons([]string{"Oh no"})
                errModal := tview.NewModal()
                errModal.SetText(errMsg)
                errModal.AddButtons([]string{"Oh no"})
@@ -528,22 +535,23 @@ func handleClientTranLogin(c *Client, t *Transaction) (res []Transaction, err er
 
                c.UI.App.Draw() // TODO: errModal doesn't render without this.  wtf?
 
 
                c.UI.App.Draw() // TODO: errModal doesn't render without this.  wtf?
 
-               c.Logger.Error(string(t.GetField(fieldError).Data))
-               return nil, errors.New("login error: " + string(t.GetField(fieldError).Data))
+               c.Logger.Error(string(t.GetField(FieldError).Data))
+               return nil, errors.New("login error: " + string(t.GetField(FieldError).Data))
        }
        c.UI.Pages.AddAndSwitchToPage(serverUIPage, c.UI.renderServerUI(), true)
        c.UI.App.SetFocus(c.UI.chatInput)
 
        }
        c.UI.Pages.AddAndSwitchToPage(serverUIPage, c.UI.renderServerUI(), true)
        c.UI.App.SetFocus(c.UI.chatInput)
 
-       if err := c.Send(*NewTransaction(tranGetUserNameList, nil)); err != nil {
+       if err := c.Send(*NewTransaction(TranGetUserNameList, nil)); err != nil {
                c.Logger.Errorw("err", "err", err)
        }
        return res, err
 }
 
 // JoinServer connects to a Hotline server and completes the login flow
                c.Logger.Errorw("err", "err", err)
        }
        return res, err
 }
 
 // JoinServer connects to a Hotline server and completes the login flow
-func (c *Client) JoinServer(address, login, passwd string) error {
+func (c *Client) Connect(address, login, passwd string) (err error) {
        // Establish TCP connection to server
        // Establish TCP connection to server
-       if err := c.connect(address); err != nil {
+       c.Connection, err = net.DialTimeout("tcp", address, 5*time.Second)
+       if err != nil {
                return err
        }
 
                return err
        }
 
@@ -552,7 +560,7 @@ func (c *Client) JoinServer(address, login, passwd string) error {
                return err
        }
 
                return err
        }
 
-       // Authenticate (send tranLogin 107)
+       // Authenticate (send TranLogin 107)
        if err := c.LogIn(login, passwd); err != nil {
                return err
        }
        if err := c.LogIn(login, passwd); err != nil {
                return err
        }
@@ -566,21 +574,11 @@ func (c *Client) JoinServer(address, login, passwd string) error {
 func (c *Client) keepalive() error {
        for {
                time.Sleep(300 * time.Second)
 func (c *Client) keepalive() error {
        for {
                time.Sleep(300 * time.Second)
-               _ = c.Send(*NewTransaction(tranKeepAlive, nil))
+               _ = c.Send(*NewTransaction(TranKeepAlive, nil))
                c.Logger.Infow("Sent keepalive ping")
        }
 }
 
                c.Logger.Infow("Sent keepalive ping")
        }
 }
 
-// connect establishes a connection with a Server by sending handshake sequence
-func (c *Client) connect(address string) error {
-       var err error
-       c.Connection, err = net.DialTimeout("tcp", address, 5*time.Second)
-       if err != nil {
-               return err
-       }
-       return nil
-}
-
 var ClientHandshake = []byte{
        0x54, 0x52, 0x54, 0x50, // TRTP
        0x48, 0x4f, 0x54, 0x4c, // HOTL
 var ClientHandshake = []byte{
        0x54, 0x52, 0x54, 0x50, // TRTP
        0x48, 0x4f, 0x54, 0x4c, // HOTL
@@ -619,11 +617,11 @@ func (c *Client) Handshake() error {
 func (c *Client) LogIn(login string, password string) error {
        return c.Send(
                *NewTransaction(
 func (c *Client) LogIn(login string, password string) error {
        return c.Send(
                *NewTransaction(
-                       tranLogin, nil,
-                       NewField(fieldUserName, []byte(c.pref.Username)),
-                       NewField(fieldUserIconID, c.pref.IconBytes()),
-                       NewField(fieldUserLogin, negateString([]byte(login))),
-                       NewField(fieldUserPassword, negateString([]byte(password))),
+                       TranLogin, nil,
+                       NewField(FieldUserName, []byte(c.Pref.Username)),
+                       NewField(FieldUserIconID, c.Pref.IconBytes()),
+                       NewField(FieldUserLogin, negateString([]byte(login))),
+                       NewField(FieldUserPassword, negateString([]byte(password))),
                ),
        )
 }
                ),
        )
 }
@@ -673,7 +671,7 @@ func (c *Client) HandleTransaction(t *Transaction) error {
                        c.Send(t)
                }
        } else {
                        c.Send(t)
                }
        } else {
-               c.Logger.Errorw(
+               c.Logger.Debugw(
                        "Unimplemented transaction type received",
                        "RequestID", requestNum,
                        "TransactionID", t.ID,
                        "Unimplemented transaction type received",
                        "RequestID", requestNum,
                        "TransactionID", t.ID,
@@ -686,3 +684,31 @@ func (c *Client) HandleTransaction(t *Transaction) error {
 func (c *Client) Disconnect() error {
        return c.Connection.Close()
 }
 func (c *Client) Disconnect() error {
        return c.Connection.Close()
 }
+
+func (c *Client) HandleTransactions() error {
+       // Create a new scanner for parsing incoming bytes into transaction tokens
+       scanner := bufio.NewScanner(c.Connection)
+       scanner.Split(transactionScanner)
+
+       // Scan for new transactions and handle them as they come in.
+       for scanner.Scan() {
+               // Make a new []byte slice and copy the scanner bytes to it.  This is critical to avoid a data race as the
+               // scanner re-uses the buffer for subsequent scans.
+               buf := make([]byte, len(scanner.Bytes()))
+               copy(buf, scanner.Bytes())
+
+               var t Transaction
+               _, err := t.Write(buf)
+               if err != nil {
+                       break
+               }
+               if err := c.HandleTransaction(&t); err != nil {
+                       c.Logger.Errorw("Error handling transaction", "err", err)
+               }
+       }
+
+       if scanner.Err() == nil {
+               return scanner.Err()
+       }
+       return nil
+}
index 14aef9e835ebc7ae5f79a0d826f55930db0046af..f92c1cdb5999d37e598ae7708b3882ff5fdb4bf3 100644 (file)
@@ -94,7 +94,7 @@ func (cc *ClientConn) handleTransaction(transaction Transaction) error {
        cc.Server.mux.Lock()
        defer cc.Server.mux.Unlock()
 
        cc.Server.mux.Lock()
        defer cc.Server.mux.Unlock()
 
-       if requestNum != tranKeepAlive {
+       if requestNum != TranKeepAlive {
                // reset the user idle timer
                cc.IdleTime = 0
 
                // reset the user idle timer
                cc.IdleTime = 0
 
@@ -107,11 +107,11 @@ func (cc *ClientConn) handleTransaction(transaction Transaction) error {
                        cc.Idle = false
 
                        cc.sendAll(
                        cc.Idle = false
 
                        cc.sendAll(
-                               tranNotifyChangeUser,
-                               NewField(fieldUserID, *cc.ID),
-                               NewField(fieldUserFlags, cc.Flags),
-                               NewField(fieldUserName, cc.UserName),
-                               NewField(fieldUserIconID, cc.Icon),
+                               TranNotifyChangeUser,
+                               NewField(FieldUserID, *cc.ID),
+                               NewField(FieldUserFlags, cc.Flags),
+                               NewField(FieldUserName, cc.UserName),
+                               NewField(FieldUserIconID, cc.Icon),
                        )
                }
        }
                        )
                }
        }
@@ -144,7 +144,7 @@ func (cc *ClientConn) Disconnect() {
 
        delete(cc.Server.Clients, binary.BigEndian.Uint16(*cc.ID))
 
 
        delete(cc.Server.Clients, binary.BigEndian.Uint16(*cc.ID))
 
-       for _, t := range cc.notifyOthers(*NewTransaction(tranNotifyDeleteUser, nil, NewField(fieldUserID, *cc.ID))) {
+       for _, t := range cc.notifyOthers(*NewTransaction(TranNotifyDeleteUser, nil, NewField(FieldUserID, *cc.ID))) {
                cc.Server.outbox <- t
        }
 
                cc.Server.outbox <- t
        }
 
@@ -189,7 +189,7 @@ func (cc *ClientConn) NewErrReply(t *Transaction, errMsg string) Transaction {
                ID:        t.ID,
                ErrorCode: []byte{0, 0, 0, 1},
                Fields: []Field{
                ID:        t.ID,
                ErrorCode: []byte{0, 0, 0, 1},
                Fields: []Field{
-                       NewField(fieldError, []byte(errMsg)),
+                       NewField(FieldError, []byte(errMsg)),
                },
        }
 }
                },
        }
 }
index 3378552a8f0da2408691919cc16d53e85d61a9f2..c5ae55bfb3ba82a6e68acfec61fd34cd98e02b45 100644 (file)
@@ -5,65 +5,65 @@ import (
        "github.com/jhalter/mobius/concat"
 )
 
        "github.com/jhalter/mobius/concat"
 )
 
-const fieldError = 100
-const fieldData = 101
-const fieldUserName = 102
-const fieldUserID = 103
-const fieldUserIconID = 104
-const fieldUserLogin = 105
-const fieldUserPassword = 106
-const fieldRefNum = 107
-const fieldTransferSize = 108
-const fieldChatOptions = 109
-const fieldUserAccess = 110
-
-// const fieldUserAlias = 111 TODO: implement
-const fieldUserFlags = 112
-const fieldOptions = 113
-const fieldChatID = 114
-const fieldChatSubject = 115
-const fieldWaitingCount = 116
-const fieldBannerType = 152
-const fieldNoServerAgreement = 152
-const fieldVersion = 160
-const fieldCommunityBannerID = 161
-const fieldServerName = 162
-const fieldFileNameWithInfo = 200
-const fieldFileName = 201
-const fieldFilePath = 202
-const fieldFileResumeData = 203
-const fieldFileTransferOptions = 204
-const fieldFileTypeString = 205
-const fieldFileCreatorString = 206
-const fieldFileSize = 207
-const fieldFileCreateDate = 208
-const fieldFileModifyDate = 209
-const fieldFileComment = 210
-const fieldFileNewName = 211
-const fieldFileNewPath = 212
-const fieldFileType = 213
-const fieldQuotingMsg = 214
-const fieldAutomaticResponse = 215
-const fieldFolderItemCount = 220
-const fieldUsernameWithInfo = 300
-const fieldNewsArtListData = 321
-const fieldNewsCatName = 322
-const fieldNewsCatListData15 = 323
-const fieldNewsPath = 325
-const fieldNewsArtID = 326
-const fieldNewsArtDataFlav = 327
-const fieldNewsArtTitle = 328
-const fieldNewsArtPoster = 329
-const fieldNewsArtDate = 330
-const fieldNewsArtPrevArt = 331
-const fieldNewsArtNextArt = 332
-const fieldNewsArtData = 333
-
-// const fieldNewsArtFlags = 334
-const fieldNewsArtParentArt = 335
-const fieldNewsArt1stChildArt = 336
-
-// const fieldNewsArtRecurseDel = 337
+// List of Hotline protocol field types taken from the official 1.9 protocol document
+const (
+       FieldError               = 100
+       FieldData                = 101
+       FieldUserName            = 102
+       FieldUserID              = 103
+       FieldUserIconID          = 104
+       FieldUserLogin           = 105
+       FieldUserPassword        = 106
+       FieldRefNum              = 107
+       FieldTransferSize        = 108
+       FieldChatOptions         = 109
+       FieldUserAccess          = 110
+       FieldUserAlias           = 111 // TODO: implement
+       FieldUserFlags           = 112
+       FieldOptions             = 113
+       FieldChatID              = 114
+       FieldChatSubject         = 115
+       FieldWaitingCount        = 116
+       FieldBannerType          = 152
+       FieldNoServerAgreement   = 152
+       FieldVersion             = 160
+       FieldCommunityBannerID   = 161
+       FieldServerName          = 162
+       FieldFileNameWithInfo    = 200
+       FieldFileName            = 201
+       FieldFilePath            = 202
+       FieldFileResumeData      = 203
+       FieldFileTransferOptions = 204
+       FieldFileTypeString      = 205
+       FieldFileCreatorString   = 206
+       FieldFileSize            = 207
+       FieldFileCreateDate      = 208
+       FieldFileModifyDate      = 209
+       FieldFileComment         = 210
+       FieldFileNewName         = 211
+       FieldFileNewPath         = 212
+       FieldFileType            = 213
+       FieldQuotingMsg          = 214
+       FieldAutomaticResponse   = 215
+       FieldFolderItemCount     = 220
+       FieldUsernameWithInfo    = 300
+       FieldNewsArtListData     = 321
+       FieldNewsCatName         = 322
+       FieldNewsCatListData15   = 323
+       FieldNewsPath            = 325
+       FieldNewsArtID           = 326
+       FieldNewsArtDataFlav     = 327
+       FieldNewsArtTitle        = 328
+       FieldNewsArtPoster       = 329
+       FieldNewsArtDate         = 330
+       FieldNewsArtPrevArt      = 331
+       FieldNewsArtNextArt      = 332
+       FieldNewsArtData         = 333
+       FieldNewsArtFlags        = 334 // TODO: what is this used for?
+       FieldNewsArtParentArt    = 335
+       FieldNewsArt1stChildArt  = 336
+       FieldNewsArtRecurseDel   = 337 // TODO: implement news article recusive deletion
+)
 
 type Field struct {
        ID        []byte // Type of field
 
 type Field struct {
        ID        []byte // Type of field
index aa248f81893f06ca0d61e2b27e0f106a9b707c10..c4ba718b8fd23cf1319c39f6833fd71887646878 100644 (file)
@@ -131,7 +131,7 @@ func getFileNameList(path string, ignoreList []string) (fields []Field, err erro
                if err != nil {
                        return nil, err
                }
                if err != nil {
                        return nil, err
                }
-               fields = append(fields, NewField(fieldFileNameWithInfo, b))
+               fields = append(fields, NewField(FieldFileNameWithInfo, b))
        }
 
        return fields, nil
        }
 
        return fields, nil
index 9e5f498332f46151c1ed367bb3311df15a828989..f4a2ad4acca78cee7b7317aea7737cba3b4c1528 100644 (file)
@@ -319,11 +319,11 @@ func (s *Server) keepaliveHandler() {
                                binary.BigEndian.PutUint16(c.Flags, uint16(flagBitmap.Int64()))
 
                                c.sendAll(
                                binary.BigEndian.PutUint16(c.Flags, uint16(flagBitmap.Int64()))
 
                                c.sendAll(
-                                       tranNotifyChangeUser,
-                                       NewField(fieldUserID, *c.ID),
-                                       NewField(fieldUserFlags, c.Flags),
-                                       NewField(fieldUserName, c.UserName),
-                                       NewField(fieldUserIconID, c.Icon),
+                                       TranNotifyChangeUser,
+                                       NewField(FieldUserID, *c.ID),
+                                       NewField(FieldUserFlags, c.Flags),
+                                       NewField(FieldUserName, c.UserName),
+                                       NewField(FieldUserIconID, c.Icon),
                                )
                        }
                }
                                )
                        }
                }
@@ -469,7 +469,7 @@ func (s *Server) connectedUsers() []Field {
                        Flags: c.Flags,
                        Name:  string(c.UserName),
                }
                        Flags: c.Flags,
                        Name:  string(c.UserName),
                }
-               connectedUsers = append(connectedUsers, NewField(fieldUsernameWithInfo, user.Payload()))
+               connectedUsers = append(connectedUsers, NewField(FieldUsernameWithInfo, user.Payload()))
        }
        return connectedUsers
 }
        }
        return connectedUsers
 }
@@ -572,10 +572,10 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
                // permaban
                if banUntil == nil {
                        t := NewTransaction(
                // permaban
                if banUntil == nil {
                        t := NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                &[]byte{0, 0},
                                &[]byte{0, 0},
-                               NewField(fieldData, []byte("You are permanently banned on this server")),
-                               NewField(fieldChatOptions, []byte{0, 0}),
+                               NewField(FieldData, []byte("You are permanently banned on this server")),
+                               NewField(FieldChatOptions, []byte{0, 0}),
                        )
 
                        b, err := t.MarshalBinary()
                        )
 
                        b, err := t.MarshalBinary()
@@ -595,10 +595,10 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
                // temporary ban
                if time.Now().Before(*banUntil) {
                        t := NewTransaction(
                // temporary ban
                if time.Now().Before(*banUntil) {
                        t := NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                &[]byte{0, 0},
                                &[]byte{0, 0},
-                               NewField(fieldData, []byte("You are temporarily banned on this server")),
-                               NewField(fieldChatOptions, []byte{0, 0}),
+                               NewField(FieldData, []byte("You are temporarily banned on this server")),
+                               NewField(FieldChatOptions, []byte{0, 0}),
                        )
                        b, err := t.MarshalBinary()
                        if err != nil {
                        )
                        b, err := t.MarshalBinary()
                        if err != nil {
@@ -618,9 +618,9 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
        c := s.NewClientConn(rwc, remoteAddr)
        defer c.Disconnect()
 
        c := s.NewClientConn(rwc, remoteAddr)
        defer c.Disconnect()
 
-       encodedLogin := clientLogin.GetField(fieldUserLogin).Data
-       encodedPassword := clientLogin.GetField(fieldUserPassword).Data
-       c.Version = clientLogin.GetField(fieldVersion).Data
+       encodedLogin := clientLogin.GetField(FieldUserLogin).Data
+       encodedPassword := clientLogin.GetField(FieldUserPassword).Data
+       c.Version = clientLogin.GetField(FieldVersion).Data
 
        var login string
        for _, char := range encodedLogin {
 
        var login string
        for _, char := range encodedLogin {
@@ -648,15 +648,15 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
                return nil
        }
 
                return nil
        }
 
-       if clientLogin.GetField(fieldUserIconID).Data != nil {
-               c.Icon = clientLogin.GetField(fieldUserIconID).Data
+       if clientLogin.GetField(FieldUserIconID).Data != nil {
+               c.Icon = clientLogin.GetField(FieldUserIconID).Data
        }
 
        c.Account = c.Server.Accounts[login]
 
        }
 
        c.Account = c.Server.Accounts[login]
 
-       if clientLogin.GetField(fieldUserName).Data != nil {
+       if clientLogin.GetField(FieldUserName).Data != nil {
                if c.Authorize(accessAnyName) {
                if c.Authorize(accessAnyName) {
-                       c.UserName = clientLogin.GetField(fieldUserName).Data
+                       c.UserName = clientLogin.GetField(FieldUserName).Data
                } else {
                        c.UserName = []byte(c.Account.Name)
                }
                } else {
                        c.UserName = []byte(c.Account.Name)
                }
@@ -667,44 +667,44 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
        }
 
        s.outbox <- c.NewReply(&clientLogin,
        }
 
        s.outbox <- c.NewReply(&clientLogin,
-               NewField(fieldVersion, []byte{0x00, 0xbe}),
-               NewField(fieldCommunityBannerID, []byte{0, 0}),
-               NewField(fieldServerName, []byte(s.Config.Name)),
+               NewField(FieldVersion, []byte{0x00, 0xbe}),
+               NewField(FieldCommunityBannerID, []byte{0, 0}),
+               NewField(FieldServerName, []byte(s.Config.Name)),
        )
 
        // Send user access privs so client UI knows how to behave
        )
 
        // Send user access privs so client UI knows how to behave
-       c.Server.outbox <- *NewTransaction(tranUserAccess, c.ID, NewField(fieldUserAccess, c.Account.Access[:]))
+       c.Server.outbox <- *NewTransaction(TranUserAccess, c.ID, NewField(FieldUserAccess, c.Account.Access[:]))
 
        // Accounts with accessNoAgreement do not receive the server agreement on login.  The behavior is different between
 
        // Accounts with accessNoAgreement do not receive the server agreement on login.  The behavior is different between
-       // client versions.  For 1.2.3 client, we do not send tranShowAgreement.  For other client versions, we send
-       // tranShowAgreement but with the NoServerAgreement field set to 1.
+       // client versions.  For 1.2.3 client, we do not send TranShowAgreement.  For other client versions, we send
+       // TranShowAgreement but with the NoServerAgreement field set to 1.
        if c.Authorize(accessNoAgreement) {
                // If client version is nil, then the client uses the 1.2.3 login behavior
                if c.Version != nil {
        if c.Authorize(accessNoAgreement) {
                // If client version is nil, then the client uses the 1.2.3 login behavior
                if c.Version != nil {
-                       c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldNoServerAgreement, []byte{1}))
+                       c.Server.outbox <- *NewTransaction(TranShowAgreement, c.ID, NewField(FieldNoServerAgreement, []byte{1}))
                }
        } else {
                }
        } else {
-               c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldData, s.Agreement))
+               c.Server.outbox <- *NewTransaction(TranShowAgreement, c.ID, NewField(FieldData, s.Agreement))
        }
 
        // If the client has provided a username as part of the login, we can infer that it is using the 1.2.3 login
        // flow and not the 1.5+ flow.
        if len(c.UserName) != 0 {
                // Add the client username to the logger.  For 1.5+ clients, we don't have this information yet as it comes as
        }
 
        // If the client has provided a username as part of the login, we can infer that it is using the 1.2.3 login
        // flow and not the 1.5+ flow.
        if len(c.UserName) != 0 {
                // Add the client username to the logger.  For 1.5+ clients, we don't have this information yet as it comes as
-               // part of tranAgreed
+               // part of TranAgreed
                c.logger = c.logger.With("name", string(c.UserName))
 
                c.logger.Infow("Login successful", "clientVersion", "Not sent (probably 1.2.3)")
 
                // Notify other clients on the server that the new user has logged in.  For 1.5+ clients we don't have this
                c.logger = c.logger.With("name", string(c.UserName))
 
                c.logger.Infow("Login successful", "clientVersion", "Not sent (probably 1.2.3)")
 
                // Notify other clients on the server that the new user has logged in.  For 1.5+ clients we don't have this
-               // information yet, so we do it in tranAgreed instead
+               // information yet, so we do it in TranAgreed instead
                for _, t := range c.notifyOthers(
                        *NewTransaction(
                for _, t := range c.notifyOthers(
                        *NewTransaction(
-                               tranNotifyChangeUser, nil,
-                               NewField(fieldUserName, c.UserName),
-                               NewField(fieldUserID, *c.ID),
-                               NewField(fieldUserIconID, c.Icon),
-                               NewField(fieldUserFlags, c.Flags),
+                               TranNotifyChangeUser, nil,
+                               NewField(FieldUserName, c.UserName),
+                               NewField(FieldUserID, *c.ID),
+                               NewField(FieldUserIconID, c.Icon),
+                               NewField(FieldUserFlags, c.Flags),
                        ),
                ) {
                        c.Server.outbox <- t
                        ),
                ) {
                        c.Server.outbox <- t
index 8d7d9ed43b60ac41a296bca25c9224ad1172c763..b01fdfb112e8c6bb61922728cd0d879dabfb00e9 100644 (file)
@@ -10,64 +10,64 @@ import (
 )
 
 const (
 )
 
 const (
-       tranError          = 0
-       tranGetMsgs        = 101
-       tranNewMsg         = 102
-       tranOldPostNews    = 103
-       tranServerMsg      = 104
-       tranChatSend       = 105
-       tranChatMsg        = 106
-       tranLogin          = 107
-       tranSendInstantMsg = 108
-       tranShowAgreement  = 109
-       tranDisconnectUser = 110
-       // tranDisconnectMsg        = 111 TODO: implement friendly disconnect
-       tranInviteNewChat        = 112
-       tranInviteToChat         = 113
-       tranRejectChatInvite     = 114
-       tranJoinChat             = 115
-       tranLeaveChat            = 116
-       tranNotifyChatChangeUser = 117
-       tranNotifyChatDeleteUser = 118
-       tranNotifyChatSubject    = 119
-       tranSetChatSubject       = 120
-       tranAgreed               = 121
-       tranServerBanner         = 122
-       tranGetFileNameList      = 200
-       tranDownloadFile         = 202
-       tranUploadFile           = 203
-       tranNewFolder            = 205
-       tranDeleteFile           = 204
-       tranGetFileInfo          = 206
-       tranSetFileInfo          = 207
-       tranMoveFile             = 208
-       tranMakeFileAlias        = 209
-       tranDownloadFldr         = 210
-       // tranDownloadInfo         = 211 TODO: implement file transfer queue
-       tranDownloadBanner     = 212
-       tranUploadFldr         = 213
-       tranGetUserNameList    = 300
-       tranNotifyChangeUser   = 301
-       tranNotifyDeleteUser   = 302
-       tranGetClientInfoText  = 303
-       tranSetClientUserInfo  = 304
-       tranListUsers          = 348
-       tranUpdateUser         = 349
-       tranNewUser            = 350
-       tranDeleteUser         = 351
-       tranGetUser            = 352
-       tranSetUser            = 353
-       tranUserAccess         = 354
-       tranUserBroadcast      = 355
-       tranGetNewsCatNameList = 370
-       tranGetNewsArtNameList = 371
-       tranDelNewsItem        = 380
-       tranNewNewsFldr        = 381
-       tranNewNewsCat         = 382
-       tranGetNewsArtData     = 400
-       tranPostNewsArt        = 410
-       tranDelNewsArt         = 411
-       tranKeepAlive          = 500
+       TranError                = 0
+       TranGetMsgs              = 101
+       TranNewMsg               = 102
+       TranOldPostNews          = 103
+       TranServerMsg            = 104
+       TranChatSend             = 105
+       TranChatMsg              = 106
+       TranLogin                = 107
+       TranSendInstantMsg       = 108
+       TranShowAgreement        = 109
+       TranDisconnectUser       = 110
+       TranDisconnectMsg        = 111 // TODO: implement server initiated friendly disconnect
+       TranInviteNewChat        = 112
+       TranInviteToChat         = 113
+       TranRejectChatInvite     = 114
+       TranJoinChat             = 115
+       TranLeaveChat            = 116
+       TranNotifyChatChangeUser = 117
+       TranNotifyChatDeleteUser = 118
+       TranNotifyChatSubject    = 119
+       TranSetChatSubject       = 120
+       TranAgreed               = 121
+       TranServerBanner         = 122
+       TranGetFileNameList      = 200
+       TranDownloadFile         = 202
+       TranUploadFile           = 203
+       TranNewFolder            = 205
+       TranDeleteFile           = 204
+       TranGetFileInfo          = 206
+       TranSetFileInfo          = 207
+       TranMoveFile             = 208
+       TranMakeFileAlias        = 209
+       TranDownloadFldr         = 210
+       TranDownloadInfo         = 211 // TODO: implement file transfer queue
+       TranDownloadBanner       = 212
+       TranUploadFldr           = 213
+       TranGetUserNameList      = 300
+       TranNotifyChangeUser     = 301
+       TranNotifyDeleteUser     = 302
+       TranGetClientInfoText    = 303
+       TranSetClientUserInfo    = 304
+       TranListUsers            = 348
+       TranUpdateUser           = 349
+       TranNewUser              = 350
+       TranDeleteUser           = 351
+       TranGetUser              = 352
+       TranSetUser              = 353
+       TranUserAccess           = 354
+       TranUserBroadcast        = 355
+       TranGetNewsCatNameList   = 370
+       TranGetNewsArtNameList   = 371
+       TranDelNewsItem          = 380
+       TranNewNewsFldr          = 381
+       TranNewNewsCat           = 382
+       TranGetNewsArtData       = 400
+       TranPostNewsArt          = 410
+       TranDelNewsArt           = 411
+       TranKeepAlive            = 500
 )
 
 type Transaction struct {
 )
 
 type Transaction struct {
index d99da53519a393c559fd6ce005157f7f34e0f8db..813d25c072185ab9f80f32915a702d28a7777da5 100644 (file)
@@ -15,223 +15,225 @@ import (
        "time"
 )
 
        "time"
 )
 
+type HandlerFunc func(*ClientConn, *Transaction) ([]Transaction, error)
+
 type TransactionType struct {
 type TransactionType struct {
-       Handler        func(*ClientConn, *Transaction) ([]Transaction, error) // function for handling the transaction type
-       Name           string                                                 // Name of transaction as it will appear in logging
+       Handler        HandlerFunc // function for handling the transaction type
+       Name           string      // Name of transaction as it will appear in logging
        RequiredFields []requiredField
 }
 
 var TransactionHandlers = map[uint16]TransactionType{
        // Server initiated
        RequiredFields []requiredField
 }
 
 var TransactionHandlers = map[uint16]TransactionType{
        // Server initiated
-       tranChatMsg: {
-               Name: "tranChatMsg",
+       TranChatMsg: {
+               Name: "TranChatMsg",
        },
        // Server initiated
        },
        // Server initiated
-       tranNotifyChangeUser: {
-               Name: "tranNotifyChangeUser",
+       TranNotifyChangeUser: {
+               Name: "TranNotifyChangeUser",
        },
        },
-       tranError: {
-               Name: "tranError",
+       TranError: {
+               Name: "TranError",
        },
        },
-       tranShowAgreement: {
-               Name: "tranShowAgreement",
+       TranShowAgreement: {
+               Name: "TranShowAgreement",
        },
        },
-       tranUserAccess: {
-               Name: "tranUserAccess",
+       TranUserAccess: {
+               Name: "TranUserAccess",
        },
        },
-       tranNotifyDeleteUser: {
-               Name: "tranNotifyDeleteUser",
+       TranNotifyDeleteUser: {
+               Name: "TranNotifyDeleteUser",
        },
        },
-       tranAgreed: {
-               Name:    "tranAgreed",
+       TranAgreed: {
+               Name:    "TranAgreed",
                Handler: HandleTranAgreed,
        },
                Handler: HandleTranAgreed,
        },
-       tranChatSend: {
-               Name:    "tranChatSend",
+       TranChatSend: {
+               Name:    "TranChatSend",
                Handler: HandleChatSend,
                RequiredFields: []requiredField{
                        {
                Handler: HandleChatSend,
                RequiredFields: []requiredField{
                        {
-                               ID:     fieldData,
+                               ID:     FieldData,
                                minLen: 0,
                        },
                },
        },
                                minLen: 0,
                        },
                },
        },
-       tranDelNewsArt: {
-               Name:    "tranDelNewsArt",
+       TranDelNewsArt: {
+               Name:    "TranDelNewsArt",
                Handler: HandleDelNewsArt,
        },
                Handler: HandleDelNewsArt,
        },
-       tranDelNewsItem: {
-               Name:    "tranDelNewsItem",
+       TranDelNewsItem: {
+               Name:    "TranDelNewsItem",
                Handler: HandleDelNewsItem,
        },
                Handler: HandleDelNewsItem,
        },
-       tranDeleteFile: {
-               Name:    "tranDeleteFile",
+       TranDeleteFile: {
+               Name:    "TranDeleteFile",
                Handler: HandleDeleteFile,
        },
                Handler: HandleDeleteFile,
        },
-       tranDeleteUser: {
-               Name:    "tranDeleteUser",
+       TranDeleteUser: {
+               Name:    "TranDeleteUser",
                Handler: HandleDeleteUser,
        },
                Handler: HandleDeleteUser,
        },
-       tranDisconnectUser: {
-               Name:    "tranDisconnectUser",
+       TranDisconnectUser: {
+               Name:    "TranDisconnectUser",
                Handler: HandleDisconnectUser,
        },
                Handler: HandleDisconnectUser,
        },
-       tranDownloadFile: {
-               Name:    "tranDownloadFile",
+       TranDownloadFile: {
+               Name:    "TranDownloadFile",
                Handler: HandleDownloadFile,
        },
                Handler: HandleDownloadFile,
        },
-       tranDownloadFldr: {
-               Name:    "tranDownloadFldr",
+       TranDownloadFldr: {
+               Name:    "TranDownloadFldr",
                Handler: HandleDownloadFolder,
        },
                Handler: HandleDownloadFolder,
        },
-       tranGetClientInfoText: {
-               Name:    "tranGetClientInfoText",
+       TranGetClientInfoText: {
+               Name:    "TranGetClientInfoText",
                Handler: HandleGetClientInfoText,
        },
                Handler: HandleGetClientInfoText,
        },
-       tranGetFileInfo: {
-               Name:    "tranGetFileInfo",
+       TranGetFileInfo: {
+               Name:    "TranGetFileInfo",
                Handler: HandleGetFileInfo,
        },
                Handler: HandleGetFileInfo,
        },
-       tranGetFileNameList: {
-               Name:    "tranGetFileNameList",
+       TranGetFileNameList: {
+               Name:    "TranGetFileNameList",
                Handler: HandleGetFileNameList,
        },
                Handler: HandleGetFileNameList,
        },
-       tranGetMsgs: {
-               Name:    "tranGetMsgs",
+       TranGetMsgs: {
+               Name:    "TranGetMsgs",
                Handler: HandleGetMsgs,
        },
                Handler: HandleGetMsgs,
        },
-       tranGetNewsArtData: {
-               Name:    "tranGetNewsArtData",
+       TranGetNewsArtData: {
+               Name:    "TranGetNewsArtData",
                Handler: HandleGetNewsArtData,
        },
                Handler: HandleGetNewsArtData,
        },
-       tranGetNewsArtNameList: {
-               Name:    "tranGetNewsArtNameList",
+       TranGetNewsArtNameList: {
+               Name:    "TranGetNewsArtNameList",
                Handler: HandleGetNewsArtNameList,
        },
                Handler: HandleGetNewsArtNameList,
        },
-       tranGetNewsCatNameList: {
-               Name:    "tranGetNewsCatNameList",
+       TranGetNewsCatNameList: {
+               Name:    "TranGetNewsCatNameList",
                Handler: HandleGetNewsCatNameList,
        },
                Handler: HandleGetNewsCatNameList,
        },
-       tranGetUser: {
-               Name:    "tranGetUser",
+       TranGetUser: {
+               Name:    "TranGetUser",
                Handler: HandleGetUser,
        },
                Handler: HandleGetUser,
        },
-       tranGetUserNameList: {
+       TranGetUserNameList: {
                Name:    "tranHandleGetUserNameList",
                Handler: HandleGetUserNameList,
        },
                Name:    "tranHandleGetUserNameList",
                Handler: HandleGetUserNameList,
        },
-       tranInviteNewChat: {
-               Name:    "tranInviteNewChat",
+       TranInviteNewChat: {
+               Name:    "TranInviteNewChat",
                Handler: HandleInviteNewChat,
        },
                Handler: HandleInviteNewChat,
        },
-       tranInviteToChat: {
-               Name:    "tranInviteToChat",
+       TranInviteToChat: {
+               Name:    "TranInviteToChat",
                Handler: HandleInviteToChat,
        },
                Handler: HandleInviteToChat,
        },
-       tranJoinChat: {
-               Name:    "tranJoinChat",
+       TranJoinChat: {
+               Name:    "TranJoinChat",
                Handler: HandleJoinChat,
        },
                Handler: HandleJoinChat,
        },
-       tranKeepAlive: {
-               Name:    "tranKeepAlive",
+       TranKeepAlive: {
+               Name:    "TranKeepAlive",
                Handler: HandleKeepAlive,
        },
                Handler: HandleKeepAlive,
        },
-       tranLeaveChat: {
-               Name:    "tranJoinChat",
+       TranLeaveChat: {
+               Name:    "TranJoinChat",
                Handler: HandleLeaveChat,
        },
                Handler: HandleLeaveChat,
        },
-       tranListUsers: {
-               Name:    "tranListUsers",
+       TranListUsers: {
+               Name:    "TranListUsers",
                Handler: HandleListUsers,
        },
                Handler: HandleListUsers,
        },
-       tranMoveFile: {
-               Name:    "tranMoveFile",
+       TranMoveFile: {
+               Name:    "TranMoveFile",
                Handler: HandleMoveFile,
        },
                Handler: HandleMoveFile,
        },
-       tranNewFolder: {
-               Name:    "tranNewFolder",
+       TranNewFolder: {
+               Name:    "TranNewFolder",
                Handler: HandleNewFolder,
        },
                Handler: HandleNewFolder,
        },
-       tranNewNewsCat: {
-               Name:    "tranNewNewsCat",
+       TranNewNewsCat: {
+               Name:    "TranNewNewsCat",
                Handler: HandleNewNewsCat,
        },
                Handler: HandleNewNewsCat,
        },
-       tranNewNewsFldr: {
-               Name:    "tranNewNewsFldr",
+       TranNewNewsFldr: {
+               Name:    "TranNewNewsFldr",
                Handler: HandleNewNewsFldr,
        },
                Handler: HandleNewNewsFldr,
        },
-       tranNewUser: {
-               Name:    "tranNewUser",
+       TranNewUser: {
+               Name:    "TranNewUser",
                Handler: HandleNewUser,
        },
                Handler: HandleNewUser,
        },
-       tranUpdateUser: {
-               Name:    "tranUpdateUser",
+       TranUpdateUser: {
+               Name:    "TranUpdateUser",
                Handler: HandleUpdateUser,
        },
                Handler: HandleUpdateUser,
        },
-       tranOldPostNews: {
-               Name:    "tranOldPostNews",
+       TranOldPostNews: {
+               Name:    "TranOldPostNews",
                Handler: HandleTranOldPostNews,
        },
                Handler: HandleTranOldPostNews,
        },
-       tranPostNewsArt: {
-               Name:    "tranPostNewsArt",
+       TranPostNewsArt: {
+               Name:    "TranPostNewsArt",
                Handler: HandlePostNewsArt,
        },
                Handler: HandlePostNewsArt,
        },
-       tranRejectChatInvite: {
-               Name:    "tranRejectChatInvite",
+       TranRejectChatInvite: {
+               Name:    "TranRejectChatInvite",
                Handler: HandleRejectChatInvite,
        },
                Handler: HandleRejectChatInvite,
        },
-       tranSendInstantMsg: {
-               Name:    "tranSendInstantMsg",
+       TranSendInstantMsg: {
+               Name:    "TranSendInstantMsg",
                Handler: HandleSendInstantMsg,
                RequiredFields: []requiredField{
                        {
                Handler: HandleSendInstantMsg,
                RequiredFields: []requiredField{
                        {
-                               ID:     fieldData,
+                               ID:     FieldData,
                                minLen: 0,
                        },
                        {
                                minLen: 0,
                        },
                        {
-                               ID: fieldUserID,
+                               ID: FieldUserID,
                        },
                },
        },
                        },
                },
        },
-       tranSetChatSubject: {
-               Name:    "tranSetChatSubject",
+       TranSetChatSubject: {
+               Name:    "TranSetChatSubject",
                Handler: HandleSetChatSubject,
        },
                Handler: HandleSetChatSubject,
        },
-       tranMakeFileAlias: {
-               Name:    "tranMakeFileAlias",
+       TranMakeFileAlias: {
+               Name:    "TranMakeFileAlias",
                Handler: HandleMakeAlias,
                RequiredFields: []requiredField{
                Handler: HandleMakeAlias,
                RequiredFields: []requiredField{
-                       {ID: fieldFileName, minLen: 1},
-                       {ID: fieldFilePath, minLen: 1},
-                       {ID: fieldFileNewPath, minLen: 1},
+                       {ID: FieldFileName, minLen: 1},
+                       {ID: FieldFilePath, minLen: 1},
+                       {ID: FieldFileNewPath, minLen: 1},
                },
        },
                },
        },
-       tranSetClientUserInfo: {
-               Name:    "tranSetClientUserInfo",
+       TranSetClientUserInfo: {
+               Name:    "TranSetClientUserInfo",
                Handler: HandleSetClientUserInfo,
        },
                Handler: HandleSetClientUserInfo,
        },
-       tranSetFileInfo: {
-               Name:    "tranSetFileInfo",
+       TranSetFileInfo: {
+               Name:    "TranSetFileInfo",
                Handler: HandleSetFileInfo,
        },
                Handler: HandleSetFileInfo,
        },
-       tranSetUser: {
-               Name:    "tranSetUser",
+       TranSetUser: {
+               Name:    "TranSetUser",
                Handler: HandleSetUser,
        },
                Handler: HandleSetUser,
        },
-       tranUploadFile: {
-               Name:    "tranUploadFile",
+       TranUploadFile: {
+               Name:    "TranUploadFile",
                Handler: HandleUploadFile,
        },
                Handler: HandleUploadFile,
        },
-       tranUploadFldr: {
-               Name:    "tranUploadFldr",
+       TranUploadFldr: {
+               Name:    "TranUploadFldr",
                Handler: HandleUploadFolder,
        },
                Handler: HandleUploadFolder,
        },
-       tranUserBroadcast: {
-               Name:    "tranUserBroadcast",
+       TranUserBroadcast: {
+               Name:    "TranUserBroadcast",
                Handler: HandleUserBroadcast,
        },
                Handler: HandleUserBroadcast,
        },
-       tranDownloadBanner: {
-               Name:    "tranDownloadBanner",
+       TranDownloadBanner: {
+               Name:    "TranDownloadBanner",
                Handler: HandleDownloadBanner,
        },
 }
                Handler: HandleDownloadBanner,
        },
 }
@@ -244,19 +246,19 @@ func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err erro
 
        // Truncate long usernames
        trunc := fmt.Sprintf("%13s", cc.UserName)
 
        // Truncate long usernames
        trunc := fmt.Sprintf("%13s", cc.UserName)
-       formattedMsg := fmt.Sprintf("\r%.14s:  %s", trunc, t.GetField(fieldData).Data)
+       formattedMsg := fmt.Sprintf("\r%.14s:  %s", trunc, t.GetField(FieldData).Data)
 
        // By holding the option key, Hotline chat allows users to send /me formatted messages like:
        // *** Halcyon does stuff
 
        // By holding the option key, Hotline chat allows users to send /me formatted messages like:
        // *** Halcyon does stuff
-       // This is indicated by the presence of the optional field fieldChatOptions set to a value of 1.
+       // This is indicated by the presence of the optional field FieldChatOptions set to a value of 1.
        // Most clients do not send this option for normal chat messages.
        // Most clients do not send this option for normal chat messages.
-       if t.GetField(fieldChatOptions).Data != nil && bytes.Equal(t.GetField(fieldChatOptions).Data, []byte{0, 1}) {
-               formattedMsg = fmt.Sprintf("\r*** %s %s", cc.UserName, t.GetField(fieldData).Data)
+       if t.GetField(FieldChatOptions).Data != nil && bytes.Equal(t.GetField(FieldChatOptions).Data, []byte{0, 1}) {
+               formattedMsg = fmt.Sprintf("\r*** %s %s", cc.UserName, t.GetField(FieldData).Data)
        }
 
        // The ChatID field is used to identify messages as belonging to a private chat.
        // All clients *except* Frogblast omit this field for public chat, but Frogblast sends a value of 00 00 00 00.
        }
 
        // The ChatID field is used to identify messages as belonging to a private chat.
        // All clients *except* Frogblast omit this field for public chat, but Frogblast sends a value of 00 00 00 00.
-       chatID := t.GetField(fieldChatID).Data
+       chatID := t.GetField(FieldChatID).Data
        if chatID != nil && !bytes.Equal([]byte{0, 0, 0, 0}, chatID) {
                chatInt := binary.BigEndian.Uint32(chatID)
                privChat := cc.Server.PrivateChats[chatInt]
        if chatID != nil && !bytes.Equal([]byte{0, 0, 0, 0}, chatID) {
                chatInt := binary.BigEndian.Uint32(chatID)
                privChat := cc.Server.PrivateChats[chatInt]
@@ -266,10 +268,10 @@ func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err erro
                // send the message to all connected clients of the private chat
                for _, c := range clients {
                        res = append(res, *NewTransaction(
                // send the message to all connected clients of the private chat
                for _, c := range clients {
                        res = append(res, *NewTransaction(
-                               tranChatMsg,
+                               TranChatMsg,
                                c.ID,
                                c.ID,
-                               NewField(fieldChatID, chatID),
-                               NewField(fieldData, []byte(formattedMsg)),
+                               NewField(FieldChatID, chatID),
+                               NewField(FieldData, []byte(formattedMsg)),
                        ))
                }
                return res, err
                        ))
                }
                return res, err
@@ -278,7 +280,7 @@ func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err erro
        for _, c := range sortedClients(cc.Server.Clients) {
                // Filter out clients that do not have the read chat permission
                if c.Authorize(accessReadChat) {
        for _, c := range sortedClients(cc.Server.Clients) {
                // Filter out clients that do not have the read chat permission
                if c.Authorize(accessReadChat) {
-                       res = append(res, *NewTransaction(tranChatMsg, c.ID, NewField(fieldData, []byte(formattedMsg))))
+                       res = append(res, *NewTransaction(TranChatMsg, c.ID, NewField(FieldData, []byte(formattedMsg))))
                }
        }
 
                }
        }
 
@@ -306,22 +308,22 @@ func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, er
                return res, err
        }
 
                return res, err
        }
 
-       msg := t.GetField(fieldData)
-       ID := t.GetField(fieldUserID)
+       msg := t.GetField(FieldData)
+       ID := t.GetField(FieldUserID)
 
        reply := NewTransaction(
 
        reply := NewTransaction(
-               tranServerMsg,
+               TranServerMsg,
                &ID.Data,
                &ID.Data,
-               NewField(fieldData, msg.Data),
-               NewField(fieldUserName, cc.UserName),
-               NewField(fieldUserID, *cc.ID),
-               NewField(fieldOptions, []byte{0, 1}),
+               NewField(FieldData, msg.Data),
+               NewField(FieldUserName, cc.UserName),
+               NewField(FieldUserID, *cc.ID),
+               NewField(FieldOptions, []byte{0, 1}),
        )
 
        )
 
-       // Later versions of Hotline include the original message in the fieldQuotingMsg field so
+       // Later versions of Hotline include the original message in the FieldQuotingMsg field so
        //  the receiving client can display both the received message and what it is in reply to
        //  the receiving client can display both the received message and what it is in reply to
-       if t.GetField(fieldQuotingMsg).Data != nil {
-               reply.Fields = append(reply.Fields, NewField(fieldQuotingMsg, t.GetField(fieldQuotingMsg).Data))
+       if t.GetField(FieldQuotingMsg).Data != nil {
+               reply.Fields = append(reply.Fields, NewField(FieldQuotingMsg, t.GetField(FieldQuotingMsg).Data))
        }
 
        id, _ := byteToInt(ID.Data)
        }
 
        id, _ := byteToInt(ID.Data)
@@ -335,12 +337,12 @@ func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, er
        if flagBitmap.Bit(userFLagRefusePChat) == 1 {
                res = append(res,
                        *NewTransaction(
        if flagBitmap.Bit(userFLagRefusePChat) == 1 {
                res = append(res,
                        *NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                cc.ID,
                                cc.ID,
-                               NewField(fieldData, []byte(string(otherClient.UserName)+" does not accept private messages.")),
-                               NewField(fieldUserName, otherClient.UserName),
-                               NewField(fieldUserID, *otherClient.ID),
-                               NewField(fieldOptions, []byte{0, 2}),
+                               NewField(FieldData, []byte(string(otherClient.UserName)+" does not accept private messages.")),
+                               NewField(FieldUserName, otherClient.UserName),
+                               NewField(FieldUserID, *otherClient.ID),
+                               NewField(FieldOptions, []byte{0, 2}),
                        ),
                )
        } else {
                        ),
                )
        } else {
@@ -351,12 +353,12 @@ func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, er
        if len(otherClient.AutoReply) > 0 {
                res = append(res,
                        *NewTransaction(
        if len(otherClient.AutoReply) > 0 {
                res = append(res,
                        *NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                cc.ID,
                                cc.ID,
-                               NewField(fieldData, otherClient.AutoReply),
-                               NewField(fieldUserName, otherClient.UserName),
-                               NewField(fieldUserID, *otherClient.ID),
-                               NewField(fieldOptions, []byte{0, 1}),
+                               NewField(FieldData, otherClient.AutoReply),
+                               NewField(FieldUserName, otherClient.UserName),
+                               NewField(FieldUserID, *otherClient.ID),
+                               NewField(FieldOptions, []byte{0, 1}),
                        ),
                )
        }
                        ),
                )
        }
@@ -367,8 +369,8 @@ func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, er
 }
 
 func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 }
 
 func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
@@ -381,14 +383,14 @@ func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
        }
 
        res = append(res, cc.NewReply(t,
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldFileName, []byte(fw.name)),
-               NewField(fieldFileTypeString, fw.ffo.FlatFileInformationFork.friendlyType()),
-               NewField(fieldFileCreatorString, fw.ffo.FlatFileInformationFork.friendlyCreator()),
-               NewField(fieldFileComment, fw.ffo.FlatFileInformationFork.Comment),
-               NewField(fieldFileType, fw.ffo.FlatFileInformationFork.TypeSignature),
-               NewField(fieldFileCreateDate, fw.ffo.FlatFileInformationFork.CreateDate),
-               NewField(fieldFileModifyDate, fw.ffo.FlatFileInformationFork.ModifyDate),
-               NewField(fieldFileSize, fw.totalSize()),
+               NewField(FieldFileName, []byte(fw.name)),
+               NewField(FieldFileTypeString, fw.ffo.FlatFileInformationFork.friendlyType()),
+               NewField(FieldFileCreatorString, fw.ffo.FlatFileInformationFork.friendlyCreator()),
+               NewField(FieldFileComment, fw.ffo.FlatFileInformationFork.Comment),
+               NewField(FieldFileType, fw.ffo.FlatFileInformationFork.TypeSignature),
+               NewField(FieldFileCreateDate, fw.ffo.FlatFileInformationFork.CreateDate),
+               NewField(FieldFileModifyDate, fw.ffo.FlatFileInformationFork.ModifyDate),
+               NewField(FieldFileSize, fw.totalSize()),
        ))
        return res, err
 }
        ))
        return res, err
 }
@@ -401,8 +403,8 @@ func HandleGetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
 // * 210       File comment    Optional
 // Fields used in the reply:   None
 func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 // * 210       File comment    Optional
 // Fields used in the reply:   None
 func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
@@ -418,7 +420,7 @@ func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
-       if t.GetField(fieldFileComment).Data != nil {
+       if t.GetField(FieldFileComment).Data != nil {
                switch mode := fi.Mode(); {
                case mode.IsDir():
                        if !cc.Authorize(accessSetFolderComment) {
                switch mode := fi.Mode(); {
                case mode.IsDir():
                        if !cc.Authorize(accessSetFolderComment) {
@@ -432,7 +434,7 @@ func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
                        }
                }
 
                        }
                }
 
-               if err := hlFile.ffo.FlatFileInformationFork.setComment(t.GetField(fieldFileComment).Data); err != nil {
+               if err := hlFile.ffo.FlatFileInformationFork.setComment(t.GetField(FieldFileComment).Data); err != nil {
                        return res, err
                }
                w, err := hlFile.infoForkWriter()
                        return res, err
                }
                w, err := hlFile.infoForkWriter()
@@ -445,12 +447,12 @@ func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
                }
        }
 
                }
        }
 
-       fullNewFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, t.GetField(fieldFileNewName).Data)
+       fullNewFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, t.GetField(FieldFileNewName).Data)
        if err != nil {
                return nil, err
        }
 
        if err != nil {
                return nil, err
        }
 
-       fileNewName := t.GetField(fieldFileNewName).Data
+       fileNewName := t.GetField(FieldFileNewName).Data
 
        if fileNewName != nil {
                switch mode := fi.Mode(); {
 
        if fileNewName != nil {
                switch mode := fi.Mode(); {
@@ -495,8 +497,8 @@ func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
 // * 202       File path
 // Fields used in the reply: none
 func HandleDeleteFile(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 // * 202       File path
 // Fields used in the reply: none
 func HandleDeleteFile(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
@@ -537,14 +539,14 @@ func HandleDeleteFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
 
 // HandleMoveFile moves files or folders. Note: seemingly not documented
 func HandleMoveFile(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 
 // HandleMoveFile moves files or folders. Note: seemingly not documented
 func HandleMoveFile(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       fileName := string(t.GetField(fieldFileName).Data)
+       fileName := string(t.GetField(FieldFileName).Data)
 
 
-       filePath, err := readPath(cc.Server.Config.FileRoot, t.GetField(fieldFilePath).Data, t.GetField(fieldFileName).Data)
+       filePath, err := readPath(cc.Server.Config.FileRoot, t.GetField(FieldFilePath).Data, t.GetField(FieldFileName).Data)
        if err != nil {
                return res, err
        }
 
        if err != nil {
                return res, err
        }
 
-       fileNewPath, err := readPath(cc.Server.Config.FileRoot, t.GetField(fieldFileNewPath).Data, nil)
+       fileNewPath, err := readPath(cc.Server.Config.FileRoot, t.GetField(FieldFileNewPath).Data, nil)
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
@@ -590,16 +592,16 @@ func HandleNewFolder(cc *ClientConn, t *Transaction) (res []Transaction, err err
                res = append(res, cc.NewErrReply(t, "You are not allowed to create folders."))
                return res, err
        }
                res = append(res, cc.NewErrReply(t, "You are not allowed to create folders."))
                return res, err
        }
-       folderName := string(t.GetField(fieldFileName).Data)
+       folderName := string(t.GetField(FieldFileName).Data)
 
        folderName = path.Join("/", folderName)
 
        var subPath string
 
 
        folderName = path.Join("/", folderName)
 
        var subPath string
 
-       // fieldFilePath is only present for nested paths
-       if t.GetField(fieldFilePath).Data != nil {
+       // FieldFilePath is only present for nested paths
+       if t.GetField(FieldFilePath).Data != nil {
                var newFp FilePath
                var newFp FilePath
-               _, err := newFp.Write(t.GetField(fieldFilePath).Data)
+               _, err := newFp.Write(t.GetField(FieldFilePath).Data)
                if err != nil {
                        return nil, err
                }
                if err != nil {
                        return nil, err
                }
@@ -634,22 +636,22 @@ func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
                return res, err
        }
 
                return res, err
        }
 
-       login := DecodeUserString(t.GetField(fieldUserLogin).Data)
-       userName := string(t.GetField(fieldUserName).Data)
+       login := DecodeUserString(t.GetField(FieldUserLogin).Data)
+       userName := string(t.GetField(FieldUserName).Data)
 
 
-       newAccessLvl := t.GetField(fieldUserAccess).Data
+       newAccessLvl := t.GetField(FieldUserAccess).Data
 
        account := cc.Server.Accounts[login]
        account.Name = userName
        copy(account.Access[:], newAccessLvl)
 
        // If the password field is cleared in the Hotline edit user UI, the SetUser transaction does
 
        account := cc.Server.Accounts[login]
        account.Name = userName
        copy(account.Access[:], newAccessLvl)
 
        // If the password field is cleared in the Hotline edit user UI, the SetUser transaction does
-       // not include fieldUserPassword
-       if t.GetField(fieldUserPassword).Data == nil {
+       // not include FieldUserPassword
+       if t.GetField(FieldUserPassword).Data == nil {
                account.Password = hashAndSalt([]byte(""))
        }
                account.Password = hashAndSalt([]byte(""))
        }
-       if len(t.GetField(fieldUserPassword).Data) > 1 {
-               account.Password = hashAndSalt(t.GetField(fieldUserPassword).Data)
+       if len(t.GetField(FieldUserPassword).Data) > 1 {
+               account.Password = hashAndSalt(t.GetField(FieldUserPassword).Data)
        }
 
        out, err := yaml.Marshal(&account)
        }
 
        out, err := yaml.Marshal(&account)
@@ -664,7 +666,7 @@ func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
        for _, c := range cc.Server.Clients {
                if c.Account.Login == login {
                        // Note: comment out these two lines to test server-side deny messages
        for _, c := range cc.Server.Clients {
                if c.Account.Login == login {
                        // Note: comment out these two lines to test server-side deny messages
-                       newT := NewTransaction(tranUserAccess, c.ID, NewField(fieldUserAccess, newAccessLvl))
+                       newT := NewTransaction(TranUserAccess, c.ID, NewField(FieldUserAccess, newAccessLvl))
                        res = append(res, *newT)
 
                        flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(c.Flags)))
                        res = append(res, *newT)
 
                        flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(c.Flags)))
@@ -678,11 +680,11 @@ func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
                        c.Account.Access = account.Access
 
                        cc.sendAll(
                        c.Account.Access = account.Access
 
                        cc.sendAll(
-                               tranNotifyChangeUser,
-                               NewField(fieldUserID, *c.ID),
-                               NewField(fieldUserFlags, c.Flags),
-                               NewField(fieldUserName, c.UserName),
-                               NewField(fieldUserIconID, c.Icon),
+                               TranNotifyChangeUser,
+                               NewField(FieldUserID, *c.ID),
+                               NewField(FieldUserFlags, c.Flags),
+                               NewField(FieldUserName, c.UserName),
+                               NewField(FieldUserIconID, c.Icon),
                        )
                }
        }
                        )
                }
        }
@@ -697,17 +699,17 @@ func HandleGetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
                return res, err
        }
 
                return res, err
        }
 
-       account := cc.Server.Accounts[string(t.GetField(fieldUserLogin).Data)]
+       account := cc.Server.Accounts[string(t.GetField(FieldUserLogin).Data)]
        if account == nil {
                res = append(res, cc.NewErrReply(t, "Account does not exist."))
                return res, err
        }
 
        res = append(res, cc.NewReply(t,
        if account == nil {
                res = append(res, cc.NewErrReply(t, "Account does not exist."))
                return res, err
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldUserName, []byte(account.Name)),
-               NewField(fieldUserLogin, negateString(t.GetField(fieldUserLogin).Data)),
-               NewField(fieldUserPassword, []byte(account.Password)),
-               NewField(fieldUserAccess, account.Access[:]),
+               NewField(FieldUserName, []byte(account.Name)),
+               NewField(FieldUserLogin, negateString(t.GetField(FieldUserLogin).Data)),
+               NewField(FieldUserPassword, []byte(account.Password)),
+               NewField(FieldUserAccess, account.Access[:]),
        ))
        return res, err
 }
        ))
        return res, err
 }
@@ -726,7 +728,7 @@ func HandleListUsers(cc *ClientConn, t *Transaction) (res []Transaction, err err
                        return res, err
                }
 
                        return res, err
                }
 
-               userFields = append(userFields, NewField(fieldData, b[:n]))
+               userFields = append(userFields, NewField(FieldData, b[:n]))
        }
 
        res = append(res, cc.NewReply(t, userFields...))
        }
 
        res = append(res, cc.NewReply(t, userFields...))
@@ -750,7 +752,7 @@ func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
                }
 
                if len(subFields) == 1 {
                }
 
                if len(subFields) == 1 {
-                       login := DecodeUserString(getField(fieldData, &subFields).Data)
+                       login := DecodeUserString(getField(FieldData, &subFields).Data)
                        cc.logger.Infow("DeleteUser", "login", login)
 
                        if !cc.Authorize(accessDeleteUser) {
                        cc.logger.Infow("DeleteUser", "login", login)
 
                        if !cc.Authorize(accessDeleteUser) {
@@ -764,7 +766,7 @@ func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
                        continue
                }
 
                        continue
                }
 
-               login := DecodeUserString(getField(fieldUserLogin, &subFields).Data)
+               login := DecodeUserString(getField(FieldUserLogin, &subFields).Data)
 
                // check if the login dataFile; if so, we know we are updating an existing user
                if acc, ok := cc.Server.Accounts[login]; ok {
 
                // check if the login dataFile; if so, we know we are updating an existing user
                if acc, ok := cc.Server.Accounts[login]; ok {
@@ -776,21 +778,21 @@ func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
                                return res, err
                        }
 
                                return res, err
                        }
 
-                       if getField(fieldUserPassword, &subFields) != nil {
-                               newPass := getField(fieldUserPassword, &subFields).Data
+                       if getField(FieldUserPassword, &subFields) != nil {
+                               newPass := getField(FieldUserPassword, &subFields).Data
                                acc.Password = hashAndSalt(newPass)
                        } else {
                                acc.Password = hashAndSalt([]byte(""))
                        }
 
                                acc.Password = hashAndSalt(newPass)
                        } else {
                                acc.Password = hashAndSalt([]byte(""))
                        }
 
-                       if getField(fieldUserAccess, &subFields) != nil {
-                               copy(acc.Access[:], getField(fieldUserAccess, &subFields).Data)
+                       if getField(FieldUserAccess, &subFields) != nil {
+                               copy(acc.Access[:], getField(FieldUserAccess, &subFields).Data)
                        }
 
                        err = cc.Server.UpdateUser(
                        }
 
                        err = cc.Server.UpdateUser(
-                               DecodeUserString(getField(fieldData, &subFields).Data),
-                               DecodeUserString(getField(fieldUserLogin, &subFields).Data),
-                               string(getField(fieldUserName, &subFields).Data),
+                               DecodeUserString(getField(FieldData, &subFields).Data),
+                               DecodeUserString(getField(FieldUserLogin, &subFields).Data),
+                               string(getField(FieldUserName, &subFields).Data),
                                acc.Password,
                                acc.Access,
                        )
                                acc.Password,
                                acc.Access,
                        )
@@ -806,7 +808,7 @@ func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
                        }
 
                        newAccess := accessBitmap{}
                        }
 
                        newAccess := accessBitmap{}
-                       copy(newAccess[:], getField(fieldUserAccess, &subFields).Data[:])
+                       copy(newAccess[:], getField(FieldUserAccess, &subFields).Data[:])
 
                        // Prevent account from creating new account with greater permission
                        for i := 0; i < 64; i++ {
 
                        // Prevent account from creating new account with greater permission
                        for i := 0; i < 64; i++ {
@@ -817,7 +819,7 @@ func HandleUpdateUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
                                }
                        }
 
                                }
                        }
 
-                       err := cc.Server.NewUser(login, string(getField(fieldUserName, &subFields).Data), string(getField(fieldUserPassword, &subFields).Data), newAccess)
+                       err := cc.Server.NewUser(login, string(getField(FieldUserName, &subFields).Data), string(getField(FieldUserPassword, &subFields).Data), newAccess)
                        if err != nil {
                                return []Transaction{}, err
                        }
                        if err != nil {
                                return []Transaction{}, err
                        }
@@ -835,7 +837,7 @@ func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
                return res, err
        }
 
                return res, err
        }
 
-       login := DecodeUserString(t.GetField(fieldUserLogin).Data)
+       login := DecodeUserString(t.GetField(FieldUserLogin).Data)
 
        // If the account already dataFile, reply with an error
        if _, ok := cc.Server.Accounts[login]; ok {
 
        // If the account already dataFile, reply with an error
        if _, ok := cc.Server.Accounts[login]; ok {
@@ -844,7 +846,7 @@ func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
        }
 
        newAccess := accessBitmap{}
        }
 
        newAccess := accessBitmap{}
-       copy(newAccess[:], t.GetField(fieldUserAccess).Data[:])
+       copy(newAccess[:], t.GetField(FieldUserAccess).Data[:])
 
        // Prevent account from creating new account with greater permission
        for i := 0; i < 64; i++ {
 
        // Prevent account from creating new account with greater permission
        for i := 0; i < 64; i++ {
@@ -856,7 +858,7 @@ func HandleNewUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
                }
        }
 
                }
        }
 
-       if err := cc.Server.NewUser(login, string(t.GetField(fieldUserName).Data), string(t.GetField(fieldUserPassword).Data), newAccess); err != nil {
+       if err := cc.Server.NewUser(login, string(t.GetField(FieldUserName).Data), string(t.GetField(FieldUserPassword).Data), newAccess); err != nil {
                return []Transaction{}, err
        }
 
                return []Transaction{}, err
        }
 
@@ -871,7 +873,7 @@ func HandleDeleteUser(cc *ClientConn, t *Transaction) (res []Transaction, err er
        }
 
        // TODO: Handle case where account doesn't exist; e.g. delete race condition
        }
 
        // TODO: Handle case where account doesn't exist; e.g. delete race condition
-       login := DecodeUserString(t.GetField(fieldUserLogin).Data)
+       login := DecodeUserString(t.GetField(FieldUserLogin).Data)
 
        if err := cc.Server.DeleteUser(login); err != nil {
                return res, err
 
        if err := cc.Server.DeleteUser(login); err != nil {
                return res, err
@@ -889,9 +891,9 @@ func HandleUserBroadcast(cc *ClientConn, t *Transaction) (res []Transaction, err
        }
 
        cc.sendAll(
        }
 
        cc.sendAll(
-               tranServerMsg,
-               NewField(fieldData, t.GetField(tranGetMsgs).Data),
-               NewField(fieldChatOptions, []byte{0}),
+               TranServerMsg,
+               NewField(FieldData, t.GetField(TranGetMsgs).Data),
+               NewField(FieldChatOptions, []byte{0}),
        )
 
        res = append(res, cc.NewReply(t))
        )
 
        res = append(res, cc.NewReply(t))
@@ -912,7 +914,7 @@ func HandleGetClientInfoText(cc *ClientConn, t *Transaction) (res []Transaction,
                return res, err
        }
 
                return res, err
        }
 
-       clientID, _ := byteToInt(t.GetField(fieldUserID).Data)
+       clientID, _ := byteToInt(t.GetField(FieldUserID).Data)
 
        clientConn := cc.Server.Clients[uint16(clientID)]
        if clientConn == nil {
 
        clientConn := cc.Server.Clients[uint16(clientID)]
        if clientConn == nil {
@@ -920,8 +922,8 @@ func HandleGetClientInfoText(cc *ClientConn, t *Transaction) (res []Transaction,
        }
 
        res = append(res, cc.NewReply(t,
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldData, []byte(clientConn.String())),
-               NewField(fieldUserName, clientConn.UserName),
+               NewField(FieldData, []byte(clientConn.String())),
+               NewField(FieldUserName, clientConn.UserName),
        ))
        return res, err
 }
        ))
        return res, err
 }
@@ -933,20 +935,20 @@ func HandleGetUserNameList(cc *ClientConn, t *Transaction) (res []Transaction, e
 }
 
 func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 }
 
 func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       if t.GetField(fieldUserName).Data != nil {
+       if t.GetField(FieldUserName).Data != nil {
                if cc.Authorize(accessAnyName) {
                if cc.Authorize(accessAnyName) {
-                       cc.UserName = t.GetField(fieldUserName).Data
+                       cc.UserName = t.GetField(FieldUserName).Data
                } else {
                        cc.UserName = []byte(cc.Account.Name)
                }
        }
 
                } else {
                        cc.UserName = []byte(cc.Account.Name)
                }
        }
 
-       cc.Icon = t.GetField(fieldUserIconID).Data
+       cc.Icon = t.GetField(FieldUserIconID).Data
 
        cc.logger = cc.logger.With("name", string(cc.UserName))
        cc.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%v", func() int { i, _ := byteToInt(cc.Version); return i }()))
 
 
        cc.logger = cc.logger.With("name", string(cc.UserName))
        cc.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%v", func() int { i, _ := byteToInt(cc.Version); return i }()))
 
-       options := t.GetField(fieldOptions).Data
+       options := t.GetField(FieldOptions).Data
        optBitmap := big.NewInt(int64(binary.BigEndian.Uint16(options)))
 
        flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(cc.Flags)))
        optBitmap := big.NewInt(int64(binary.BigEndian.Uint16(options)))
 
        flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(cc.Flags)))
@@ -965,24 +967,24 @@ func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err er
 
        // Check auto response
        if optBitmap.Bit(autoResponse) == 1 {
 
        // Check auto response
        if optBitmap.Bit(autoResponse) == 1 {
-               cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
+               cc.AutoReply = t.GetField(FieldAutomaticResponse).Data
        } else {
                cc.AutoReply = []byte{}
        }
 
        trans := cc.notifyOthers(
                *NewTransaction(
        } else {
                cc.AutoReply = []byte{}
        }
 
        trans := cc.notifyOthers(
                *NewTransaction(
-                       tranNotifyChangeUser, nil,
-                       NewField(fieldUserName, cc.UserName),
-                       NewField(fieldUserID, *cc.ID),
-                       NewField(fieldUserIconID, cc.Icon),
-                       NewField(fieldUserFlags, cc.Flags),
+                       TranNotifyChangeUser, nil,
+                       NewField(FieldUserName, cc.UserName),
+                       NewField(FieldUserID, *cc.ID),
+                       NewField(FieldUserIconID, cc.Icon),
+                       NewField(FieldUserFlags, cc.Flags),
                ),
        )
        res = append(res, trans...)
 
        if cc.Server.Config.BannerFile != "" {
                ),
        )
        res = append(res, trans...)
 
        if cc.Server.Config.BannerFile != "" {
-               res = append(res, *NewTransaction(tranServerBanner, cc.ID, NewField(fieldBannerType, []byte("JPEG"))))
+               res = append(res, *NewTransaction(TranServerBanner, cc.ID, NewField(FieldBannerType, []byte("JPEG"))))
        }
 
        res = append(res, cc.NewReply(t))
        }
 
        res = append(res, cc.NewReply(t))
@@ -1012,7 +1014,7 @@ func HandleTranOldPostNews(cc *ClientConn, t *Transaction) (res []Transaction, e
                newsTemplate = cc.Server.Config.NewsDelimiter
        }
 
                newsTemplate = cc.Server.Config.NewsDelimiter
        }
 
-       newsPost := fmt.Sprintf(newsTemplate+"\r", cc.UserName, time.Now().Format(newsDateTemplate), t.GetField(fieldData).Data)
+       newsPost := fmt.Sprintf(newsTemplate+"\r", cc.UserName, time.Now().Format(newsDateTemplate), t.GetField(FieldData).Data)
        newsPost = strings.Replace(newsPost, "\n", "\r", -1)
 
        // update news in memory
        newsPost = strings.Replace(newsPost, "\n", "\r", -1)
 
        // update news in memory
@@ -1025,8 +1027,8 @@ func HandleTranOldPostNews(cc *ClientConn, t *Transaction) (res []Transaction, e
 
        // Notify all clients of updated news
        cc.sendAll(
 
        // Notify all clients of updated news
        cc.sendAll(
-               tranNewMsg,
-               NewField(fieldData, []byte(newsPost)),
+               TranNewMsg,
+               NewField(FieldData, []byte(newsPost)),
        )
 
        res = append(res, cc.NewReply(t))
        )
 
        res = append(res, cc.NewReply(t))
@@ -1039,27 +1041,27 @@ func HandleDisconnectUser(cc *ClientConn, t *Transaction) (res []Transaction, er
                return res, err
        }
 
                return res, err
        }
 
-       clientConn := cc.Server.Clients[binary.BigEndian.Uint16(t.GetField(fieldUserID).Data)]
+       clientConn := cc.Server.Clients[binary.BigEndian.Uint16(t.GetField(FieldUserID).Data)]
 
        if clientConn.Authorize(accessCannotBeDiscon) {
                res = append(res, cc.NewErrReply(t, clientConn.Account.Login+" is not allowed to be disconnected."))
                return res, err
        }
 
 
        if clientConn.Authorize(accessCannotBeDiscon) {
                res = append(res, cc.NewErrReply(t, clientConn.Account.Login+" is not allowed to be disconnected."))
                return res, err
        }
 
-       // If fieldOptions is set, then the client IP is banned in addition to disconnected.
+       // If FieldOptions is set, then the client IP is banned in addition to disconnected.
        // 00 01 = temporary ban
        // 00 02 = permanent ban
        // 00 01 = temporary ban
        // 00 02 = permanent ban
-       if t.GetField(fieldOptions).Data != nil {
-               switch t.GetField(fieldOptions).Data[1] {
+       if t.GetField(FieldOptions).Data != nil {
+               switch t.GetField(FieldOptions).Data[1] {
                case 1:
                        // send message: "You are temporarily banned on this server"
                        cc.logger.Infow("Disconnect & temporarily ban " + string(clientConn.UserName))
 
                        res = append(res, *NewTransaction(
                case 1:
                        // send message: "You are temporarily banned on this server"
                        cc.logger.Infow("Disconnect & temporarily ban " + string(clientConn.UserName))
 
                        res = append(res, *NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                clientConn.ID,
                                clientConn.ID,
-                               NewField(fieldData, []byte("You are temporarily banned on this server")),
-                               NewField(fieldChatOptions, []byte{0, 0}),
+                               NewField(FieldData, []byte("You are temporarily banned on this server")),
+                               NewField(FieldChatOptions, []byte{0, 0}),
                        ))
 
                        banUntil := time.Now().Add(tempBanDuration)
                        ))
 
                        banUntil := time.Now().Add(tempBanDuration)
@@ -1070,10 +1072,10 @@ func HandleDisconnectUser(cc *ClientConn, t *Transaction) (res []Transaction, er
                        cc.logger.Infow("Disconnect & ban " + string(clientConn.UserName))
 
                        res = append(res, *NewTransaction(
                        cc.logger.Infow("Disconnect & ban " + string(clientConn.UserName))
 
                        res = append(res, *NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                clientConn.ID,
                                clientConn.ID,
-                               NewField(fieldData, []byte("You are permanently banned on this server")),
-                               NewField(fieldChatOptions, []byte{0, 0}),
+                               NewField(FieldData, []byte("You are permanently banned on this server")),
+                               NewField(FieldChatOptions, []byte{0, 0}),
                        ))
 
                        cc.Server.banList[strings.Split(clientConn.RemoteAddr, ":")[0]] = nil
                        ))
 
                        cc.Server.banList[strings.Split(clientConn.RemoteAddr, ":")[0]] = nil
@@ -1099,7 +1101,7 @@ func HandleGetNewsCatNameList(cc *ClientConn, t *Transaction) (res []Transaction
                return res, err
        }
 
                return res, err
        }
 
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
        cats := cc.Server.GetNewsCatByPath(pathStrs)
 
        // To store the keys in slice in sorted order
        cats := cc.Server.GetNewsCatByPath(pathStrs)
 
        // To store the keys in slice in sorted order
@@ -1116,7 +1118,7 @@ func HandleGetNewsCatNameList(cc *ClientConn, t *Transaction) (res []Transaction
                cat := cats[k]
                b, _ := cat.MarshalBinary()
                fieldData = append(fieldData, NewField(
                cat := cats[k]
                b, _ := cat.MarshalBinary()
                fieldData = append(fieldData, NewField(
-                       fieldNewsCatListData15,
+                       FieldNewsCatListData15,
                        b,
                ))
        }
                        b,
                ))
        }
@@ -1131,8 +1133,8 @@ func HandleNewNewsCat(cc *ClientConn, t *Transaction) (res []Transaction, err er
                return res, err
        }
 
                return res, err
        }
 
-       name := string(t.GetField(fieldNewsCatName).Data)
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       name := string(t.GetField(FieldNewsCatName).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
 
        cats := cc.Server.GetNewsCatByPath(pathStrs)
        cats[name] = NewsCategoryListData15{
 
        cats := cc.Server.GetNewsCatByPath(pathStrs)
        cats[name] = NewsCategoryListData15{
@@ -1158,8 +1160,8 @@ func HandleNewNewsFldr(cc *ClientConn, t *Transaction) (res []Transaction, err e
                return res, err
        }
 
                return res, err
        }
 
-       name := string(t.GetField(fieldFileName).Data)
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       name := string(t.GetField(FieldFileName).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
 
        cc.logger.Infof("Creating new news folder %s", name)
 
 
        cc.logger.Infof("Creating new news folder %s", name)
 
@@ -1189,7 +1191,7 @@ func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction
                res = append(res, cc.NewErrReply(t, "You are not allowed to read news."))
                return res, err
        }
                res = append(res, cc.NewErrReply(t, "You are not allowed to read news."))
                return res, err
        }
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
 
        var cat NewsCategoryListData15
        cats := cc.Server.ThreadedNews.Categories
 
        var cat NewsCategoryListData15
        cats := cc.Server.ThreadedNews.Categories
@@ -1201,7 +1203,7 @@ func HandleGetNewsArtNameList(cc *ClientConn, t *Transaction) (res []Transaction
 
        nald := cat.GetNewsArtListData()
 
 
        nald := cat.GetNewsArtListData()
 
-       res = append(res, cc.NewReply(t, NewField(fieldNewsArtListData, nald.Payload())))
+       res = append(res, cc.NewReply(t, NewField(FieldNewsArtListData, nald.Payload())))
        return res, err
 }
 
        return res, err
 }
 
@@ -1232,14 +1234,14 @@ func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, er
        var cat NewsCategoryListData15
        cats := cc.Server.ThreadedNews.Categories
 
        var cat NewsCategoryListData15
        cats := cc.Server.ThreadedNews.Categories
 
-       for _, fp := range ReadNewsPath(t.GetField(fieldNewsPath).Data) {
+       for _, fp := range ReadNewsPath(t.GetField(FieldNewsPath).Data) {
                cat = cats[fp]
                cats = cats[fp].SubCats
        }
 
        // The official Hotline clients will send the article ID as 2 bytes if possible, but
        // some third party clients such as Frogblast and Heildrun will always send 4 bytes
                cat = cats[fp]
                cats = cats[fp].SubCats
        }
 
        // The official Hotline clients will send the article ID as 2 bytes if possible, but
        // some third party clients such as Frogblast and Heildrun will always send 4 bytes
-       convertedID, err := byteToInt(t.GetField(fieldNewsArtID).Data)
+       convertedID, err := byteToInt(t.GetField(FieldNewsArtID).Data)
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
@@ -1251,15 +1253,15 @@ func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, er
        }
 
        res = append(res, cc.NewReply(t,
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldNewsArtTitle, []byte(art.Title)),
-               NewField(fieldNewsArtPoster, []byte(art.Poster)),
-               NewField(fieldNewsArtDate, art.Date),
-               NewField(fieldNewsArtPrevArt, art.PrevArt),
-               NewField(fieldNewsArtNextArt, art.NextArt),
-               NewField(fieldNewsArtParentArt, art.ParentArt),
-               NewField(fieldNewsArt1stChildArt, art.FirstChildArt),
-               NewField(fieldNewsArtDataFlav, []byte("text/plain")),
-               NewField(fieldNewsArtData, []byte(art.Data)),
+               NewField(FieldNewsArtTitle, []byte(art.Title)),
+               NewField(FieldNewsArtPoster, []byte(art.Poster)),
+               NewField(FieldNewsArtDate, art.Date),
+               NewField(FieldNewsArtPrevArt, art.PrevArt),
+               NewField(FieldNewsArtNextArt, art.NextArt),
+               NewField(FieldNewsArtParentArt, art.ParentArt),
+               NewField(FieldNewsArt1stChildArt, art.FirstChildArt),
+               NewField(FieldNewsArtDataFlav, []byte("text/plain")),
+               NewField(FieldNewsArtData, []byte(art.Data)),
        ))
        return res, err
 }
        ))
        return res, err
 }
@@ -1270,7 +1272,7 @@ func HandleGetNewsArtData(cc *ClientConn, t *Transaction) (res []Transaction, er
 // Fields used in the reply:
 // None
 func HandleDelNewsItem(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 // Fields used in the reply:
 // None
 func HandleDelNewsItem(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
 
        cats := cc.Server.ThreadedNews.Categories
        delName := pathStrs[len(pathStrs)-1]
 
        cats := cc.Server.ThreadedNews.Categories
        delName := pathStrs[len(pathStrs)-1]
@@ -1309,8 +1311,8 @@ func HandleDelNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err er
        // 325  News path
        // 326  News article ID
        // 337  News article â€“ recursive delete       Delete child articles (1) or not (0)
        // 325  News path
        // 326  News article ID
        // 337  News article â€“ recursive delete       Delete child articles (1) or not (0)
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
-       ID, err := byteToInt(t.GetField(fieldNewsArtID).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
+       ID, err := byteToInt(t.GetField(FieldNewsArtID).Data)
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
@@ -1345,13 +1347,13 @@ func HandlePostNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err e
                return res, err
        }
 
                return res, err
        }
 
-       pathStrs := ReadNewsPath(t.GetField(fieldNewsPath).Data)
+       pathStrs := ReadNewsPath(t.GetField(FieldNewsPath).Data)
        cats := cc.Server.GetNewsCatByPath(pathStrs[:len(pathStrs)-1])
 
        catName := pathStrs[len(pathStrs)-1]
        cat := cats[catName]
 
        cats := cc.Server.GetNewsCatByPath(pathStrs[:len(pathStrs)-1])
 
        catName := pathStrs[len(pathStrs)-1]
        cat := cats[catName]
 
-       artID, err := byteToInt(t.GetField(fieldNewsArtID).Data)
+       artID, err := byteToInt(t.GetField(FieldNewsArtID).Data)
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
@@ -1360,7 +1362,7 @@ func HandlePostNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err e
        binary.BigEndian.PutUint32(bs, convertedArtID)
 
        newArt := NewsArtData{
        binary.BigEndian.PutUint32(bs, convertedArtID)
 
        newArt := NewsArtData{
-               Title:         string(t.GetField(fieldNewsArtTitle).Data),
+               Title:         string(t.GetField(FieldNewsArtTitle).Data),
                Poster:        string(cc.UserName),
                Date:          toHotlineTime(time.Now()),
                PrevArt:       []byte{0, 0, 0, 0},
                Poster:        string(cc.UserName),
                Date:          toHotlineTime(time.Now()),
                PrevArt:       []byte{0, 0, 0, 0},
@@ -1368,7 +1370,7 @@ func HandlePostNewsArt(cc *ClientConn, t *Transaction) (res []Transaction, err e
                ParentArt:     bs,
                FirstChildArt: []byte{0, 0, 0, 0},
                DataFlav:      []byte("text/plain"),
                ParentArt:     bs,
                FirstChildArt: []byte{0, 0, 0, 0},
                DataFlav:      []byte("text/plain"),
-               Data:          string(t.GetField(fieldNewsArtData).Data),
+               Data:          string(t.GetField(FieldNewsArtData).Data),
        }
 
        var keys []int
        }
 
        var keys []int
@@ -1416,7 +1418,7 @@ func HandleGetMsgs(cc *ClientConn, t *Transaction) (res []Transaction, err error
                return res, err
        }
 
                return res, err
        }
 
-       res = append(res, cc.NewReply(t, NewField(fieldData, cc.Server.FlatNews)))
+       res = append(res, cc.NewReply(t, NewField(FieldData, cc.Server.FlatNews)))
 
        return res, err
 }
 
        return res, err
 }
@@ -1427,14 +1429,14 @@ func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err
                return res, err
        }
 
                return res, err
        }
 
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
-       resumeData := t.GetField(fieldFileResumeData).Data
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
+       resumeData := t.GetField(FieldFileResumeData).Data
 
        var dataOffset int64
        var frd FileResumeData
        if resumeData != nil {
 
        var dataOffset int64
        var frd FileResumeData
        if resumeData != nil {
-               if err := frd.UnmarshalBinary(t.GetField(fieldFileResumeData).Data); err != nil {
+               if err := frd.UnmarshalBinary(t.GetField(FieldFileResumeData).Data); err != nil {
                        return res, err
                }
                // TODO: handle rsrc fork offset
                        return res, err
                }
                // TODO: handle rsrc fork offset
@@ -1458,7 +1460,7 @@ func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err
        // TODO: refactor to remove this
        if resumeData != nil {
                var frd FileResumeData
        // TODO: refactor to remove this
        if resumeData != nil {
                var frd FileResumeData
-               if err := frd.UnmarshalBinary(t.GetField(fieldFileResumeData).Data); err != nil {
+               if err := frd.UnmarshalBinary(t.GetField(FieldFileResumeData).Data); err != nil {
                        return res, err
                }
                ft.fileResumeData = &frd
                        return res, err
                }
                ft.fileResumeData = &frd
@@ -1467,16 +1469,16 @@ func HandleDownloadFile(cc *ClientConn, t *Transaction) (res []Transaction, err
        // Optional field for when a HL v1.5+ client requests file preview
        // Used only for TEXT, JPEG, GIFF, BMP or PICT files
        // The value will always be 2
        // Optional field for when a HL v1.5+ client requests file preview
        // Used only for TEXT, JPEG, GIFF, BMP or PICT files
        // The value will always be 2
-       if t.GetField(fieldFileTransferOptions).Data != nil {
-               ft.options = t.GetField(fieldFileTransferOptions).Data
+       if t.GetField(FieldFileTransferOptions).Data != nil {
+               ft.options = t.GetField(FieldFileTransferOptions).Data
                xferSize = hlFile.ffo.FlatFileDataForkHeader.DataSize[:]
        }
 
        res = append(res, cc.NewReply(t,
                xferSize = hlFile.ffo.FlatFileDataForkHeader.DataSize[:]
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldRefNum, ft.refNum[:]),
-               NewField(fieldWaitingCount, []byte{0x00, 0x00}), // TODO: Implement waiting count
-               NewField(fieldTransferSize, xferSize),
-               NewField(fieldFileSize, hlFile.ffo.FlatFileDataForkHeader.DataSize[:]),
+               NewField(FieldRefNum, ft.refNum[:]),
+               NewField(FieldWaitingCount, []byte{0x00, 0x00}), // TODO: Implement waiting count
+               NewField(FieldTransferSize, xferSize),
+               NewField(FieldFileSize, hlFile.ffo.FlatFileDataForkHeader.DataSize[:]),
        ))
 
        return res, err
        ))
 
        return res, err
@@ -1489,7 +1491,7 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
                return res, err
        }
 
                return res, err
        }
 
-       fullFilePath, err := readPath(cc.Server.Config.FileRoot, t.GetField(fieldFilePath).Data, t.GetField(fieldFileName).Data)
+       fullFilePath, err := readPath(cc.Server.Config.FileRoot, t.GetField(FieldFilePath).Data, t.GetField(FieldFileName).Data)
        if err != nil {
                return res, err
        }
        if err != nil {
                return res, err
        }
@@ -1503,19 +1505,19 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
                return res, err
        }
 
                return res, err
        }
 
-       fileTransfer := cc.newFileTransfer(FolderDownload, t.GetField(fieldFileName).Data, t.GetField(fieldFilePath).Data, transferSize)
+       fileTransfer := cc.newFileTransfer(FolderDownload, t.GetField(FieldFileName).Data, t.GetField(FieldFilePath).Data, transferSize)
 
        var fp FilePath
 
        var fp FilePath
-       _, err = fp.Write(t.GetField(fieldFilePath).Data)
+       _, err = fp.Write(t.GetField(FieldFilePath).Data)
        if err != nil {
                return res, err
        }
 
        res = append(res, cc.NewReply(t,
        if err != nil {
                return res, err
        }
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldRefNum, fileTransfer.ReferenceNumber),
-               NewField(fieldTransferSize, transferSize),
-               NewField(fieldFolderItemCount, itemCount),
-               NewField(fieldWaitingCount, []byte{0x00, 0x00}), // TODO: Implement waiting count
+               NewField(FieldRefNum, fileTransfer.ReferenceNumber),
+               NewField(FieldTransferSize, transferSize),
+               NewField(FieldFolderItemCount, itemCount),
+               NewField(FieldWaitingCount, []byte{0x00, 0x00}), // TODO: Implement waiting count
        ))
        return res, err
 }
        ))
        return res, err
 }
@@ -1529,8 +1531,8 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
 // 204 File transfer options   "Optional Currently set to 1" (TODO: ??)
 func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        var fp FilePath
 // 204 File transfer options   "Optional Currently set to 1" (TODO: ??)
 func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        var fp FilePath
-       if t.GetField(fieldFilePath).Data != nil {
-               if _, err = fp.Write(t.GetField(fieldFilePath).Data); err != nil {
+       if t.GetField(FieldFilePath).Data != nil {
+               if _, err = fp.Write(t.GetField(FieldFilePath).Data); err != nil {
                        return res, err
                }
        }
                        return res, err
                }
        }
@@ -1538,20 +1540,20 @@ func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err
        // Handle special cases for Upload and Drop Box folders
        if !cc.Authorize(accessUploadAnywhere) {
                if !fp.IsUploadDir() && !fp.IsDropbox() {
        // Handle special cases for Upload and Drop Box folders
        if !cc.Authorize(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))))
+                       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 := cc.newFileTransfer(FolderUpload,
                        return res, err
                }
        }
 
        fileTransfer := cc.newFileTransfer(FolderUpload,
-               t.GetField(fieldFileName).Data,
-               t.GetField(fieldFilePath).Data,
-               t.GetField(fieldTransferSize).Data,
+               t.GetField(FieldFileName).Data,
+               t.GetField(FieldFilePath).Data,
+               t.GetField(FieldTransferSize).Data,
        )
 
        )
 
-       fileTransfer.FolderItemCount = t.GetField(fieldFolderItemCount).Data
+       fileTransfer.FolderItemCount = t.GetField(FieldFolderItemCount).Data
 
 
-       res = append(res, cc.NewReply(t, NewField(fieldRefNum, fileTransfer.ReferenceNumber)))
+       res = append(res, cc.NewReply(t, NewField(FieldRefNum, fileTransfer.ReferenceNumber)))
        return res, err
 }
 
        return res, err
 }
 
@@ -1568,10 +1570,10 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
                return res, err
        }
 
                return res, err
        }
 
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
-       transferOptions := t.GetField(fieldFileTransferOptions).Data
-       transferSize := t.GetField(fieldTransferSize).Data // not sent for resume
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
+       transferOptions := t.GetField(FieldFileTransferOptions).Data
+       transferSize := t.GetField(FieldTransferSize).Data // not sent for resume
 
        var fp FilePath
        if filePath != nil {
 
        var fp FilePath
        if filePath != nil {
@@ -1599,7 +1601,7 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
 
        ft := cc.newFileTransfer(FileUpload, fileName, filePath, transferSize)
 
 
        ft := cc.newFileTransfer(FileUpload, fileName, filePath, transferSize)
 
-       replyT := cc.NewReply(t, NewField(fieldRefNum, ft.ReferenceNumber))
+       replyT := cc.NewReply(t, NewField(FieldRefNum, ft.ReferenceNumber))
 
        // client has requested to resume a partially transferred file
        if transferOptions != nil {
 
        // client has requested to resume a partially transferred file
        if transferOptions != nil {
@@ -1620,7 +1622,7 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
 
                ft.TransferSize = offset
 
 
                ft.TransferSize = offset
 
-               replyT.Fields = append(replyT.Fields, NewField(fieldFileResumeData, b))
+               replyT.Fields = append(replyT.Fields, NewField(FieldFileResumeData, b))
        }
 
        res = append(res, replyT)
        }
 
        res = append(res, replyT)
@@ -1628,17 +1630,17 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
 }
 
 func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 }
 
 func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       if len(t.GetField(fieldUserIconID).Data) == 4 {
-               cc.Icon = t.GetField(fieldUserIconID).Data[2:]
+       if len(t.GetField(FieldUserIconID).Data) == 4 {
+               cc.Icon = t.GetField(FieldUserIconID).Data[2:]
        } else {
        } else {
-               cc.Icon = t.GetField(fieldUserIconID).Data
+               cc.Icon = t.GetField(FieldUserIconID).Data
        }
        if cc.Authorize(accessAnyName) {
        }
        if cc.Authorize(accessAnyName) {
-               cc.UserName = t.GetField(fieldUserName).Data
+               cc.UserName = t.GetField(FieldUserName).Data
        }
 
        // the options field is only passed by the client versions > 1.2.3.
        }
 
        // the options field is only passed by the client versions > 1.2.3.
-       options := t.GetField(fieldOptions).Data
+       options := t.GetField(FieldOptions).Data
        if options != nil {
                optBitmap := big.NewInt(int64(binary.BigEndian.Uint16(options)))
                flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(cc.Flags)))
        if options != nil {
                optBitmap := big.NewInt(int64(binary.BigEndian.Uint16(options)))
                flagBitmap := big.NewInt(int64(binary.BigEndian.Uint16(cc.Flags)))
@@ -1651,7 +1653,7 @@ func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction,
 
                // Check auto response
                if optBitmap.Bit(autoResponse) == 1 {
 
                // Check auto response
                if optBitmap.Bit(autoResponse) == 1 {
-                       cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
+                       cc.AutoReply = t.GetField(FieldAutomaticResponse).Data
                } else {
                        cc.AutoReply = []byte{}
                }
                } else {
                        cc.AutoReply = []byte{}
                }
@@ -1659,12 +1661,12 @@ func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction,
 
        for _, c := range sortedClients(cc.Server.Clients) {
                res = append(res, *NewTransaction(
 
        for _, c := range sortedClients(cc.Server.Clients) {
                res = append(res, *NewTransaction(
-                       tranNotifyChangeUser,
+                       TranNotifyChangeUser,
                        c.ID,
                        c.ID,
-                       NewField(fieldUserID, *cc.ID),
-                       NewField(fieldUserIconID, cc.Icon),
-                       NewField(fieldUserFlags, cc.Flags),
-                       NewField(fieldUserName, cc.UserName),
+                       NewField(FieldUserID, *cc.ID),
+                       NewField(FieldUserIconID, cc.Icon),
+                       NewField(FieldUserFlags, cc.Flags),
+                       NewField(FieldUserName, cc.UserName),
                ))
        }
 
                ))
        }
 
@@ -1683,7 +1685,7 @@ func HandleKeepAlive(cc *ClientConn, t *Transaction) (res []Transaction, err err
 func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        fullPath, err := readPath(
                cc.Server.Config.FileRoot,
 func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        fullPath, err := readPath(
                cc.Server.Config.FileRoot,
-               t.GetField(fieldFilePath).Data,
+               t.GetField(FieldFilePath).Data,
                nil,
        )
        if err != nil {
                nil,
        )
        if err != nil {
@@ -1691,8 +1693,8 @@ func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, e
        }
 
        var fp FilePath
        }
 
        var fp FilePath
-       if t.GetField(fieldFilePath).Data != nil {
-               if _, err = fp.Write(t.GetField(fieldFilePath).Data); err != nil {
+       if t.GetField(FieldFilePath).Data != nil {
+               if _, err = fp.Write(t.GetField(FieldFilePath).Data); err != nil {
                        return res, err
                }
        }
                        return res, err
                }
        }
@@ -1716,14 +1718,14 @@ func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, e
 // =================================
 //     Hotline private chat flow
 // =================================
 // =================================
 //     Hotline private chat flow
 // =================================
-// 1. ClientA sends tranInviteNewChat to server with user ID to invite
+// 1. ClientA sends TranInviteNewChat to server with user ID to invite
 // 2. Server creates new ChatID
 // 2. Server creates new ChatID
-// 3. Server sends tranInviteToChat to invitee
+// 3. Server sends TranInviteToChat to invitee
 // 4. Server replies to ClientA with new Chat ID
 //
 // A dialog box pops up in the invitee client with options to accept or decline the invitation.
 // If Accepted is clicked:
 // 4. Server replies to ClientA with new Chat ID
 //
 // A dialog box pops up in the invitee client with options to accept or decline the invitation.
 // If Accepted is clicked:
-// 1. ClientB sends tranJoinChat with fieldChatID
+// 1. ClientB sends TranJoinChat with FieldChatID
 
 // HandleInviteNewChat invites users to new private chat
 func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 
 // HandleInviteNewChat invites users to new private chat
 func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
@@ -1733,7 +1735,7 @@ func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err
        }
 
        // Client to Invite
        }
 
        // Client to Invite
-       targetID := t.GetField(fieldUserID).Data
+       targetID := t.GetField(FieldUserID).Data
        newChatID := cc.Server.NewPrivateChat(cc)
 
        // Check if target user has "Refuse private chat" flag
        newChatID := cc.Server.NewPrivateChat(cc)
 
        // Check if target user has "Refuse private chat" flag
@@ -1744,33 +1746,33 @@ func HandleInviteNewChat(cc *ClientConn, t *Transaction) (res []Transaction, err
        if flagBitmap.Bit(userFLagRefusePChat) == 1 {
                res = append(res,
                        *NewTransaction(
        if flagBitmap.Bit(userFLagRefusePChat) == 1 {
                res = append(res,
                        *NewTransaction(
-                               tranServerMsg,
+                               TranServerMsg,
                                cc.ID,
                                cc.ID,
-                               NewField(fieldData, []byte(string(targetClient.UserName)+" does not accept private chats.")),
-                               NewField(fieldUserName, targetClient.UserName),
-                               NewField(fieldUserID, *targetClient.ID),
-                               NewField(fieldOptions, []byte{0, 2}),
+                               NewField(FieldData, []byte(string(targetClient.UserName)+" does not accept private chats.")),
+                               NewField(FieldUserName, targetClient.UserName),
+                               NewField(FieldUserID, *targetClient.ID),
+                               NewField(FieldOptions, []byte{0, 2}),
                        ),
                )
        } else {
                res = append(res,
                        *NewTransaction(
                        ),
                )
        } else {
                res = append(res,
                        *NewTransaction(
-                               tranInviteToChat,
+                               TranInviteToChat,
                                &targetID,
                                &targetID,
-                               NewField(fieldChatID, newChatID),
-                               NewField(fieldUserName, cc.UserName),
-                               NewField(fieldUserID, *cc.ID),
+                               NewField(FieldChatID, newChatID),
+                               NewField(FieldUserName, cc.UserName),
+                               NewField(FieldUserID, *cc.ID),
                        ),
                )
        }
 
        res = append(res,
                cc.NewReply(t,
                        ),
                )
        }
 
        res = append(res,
                cc.NewReply(t,
-                       NewField(fieldChatID, newChatID),
-                       NewField(fieldUserName, cc.UserName),
-                       NewField(fieldUserID, *cc.ID),
-                       NewField(fieldUserIconID, cc.Icon),
-                       NewField(fieldUserFlags, cc.Flags),
+                       NewField(FieldChatID, newChatID),
+                       NewField(FieldUserName, cc.UserName),
+                       NewField(FieldUserID, *cc.ID),
+                       NewField(FieldUserIconID, cc.Icon),
+                       NewField(FieldUserFlags, cc.Flags),
                ),
        )
 
                ),
        )
 
@@ -1784,26 +1786,26 @@ func HandleInviteToChat(cc *ClientConn, t *Transaction) (res []Transaction, err
        }
 
        // Client to Invite
        }
 
        // Client to Invite
-       targetID := t.GetField(fieldUserID).Data
-       chatID := t.GetField(fieldChatID).Data
+       targetID := t.GetField(FieldUserID).Data
+       chatID := t.GetField(FieldChatID).Data
 
        res = append(res,
                *NewTransaction(
 
        res = append(res,
                *NewTransaction(
-                       tranInviteToChat,
+                       TranInviteToChat,
                        &targetID,
                        &targetID,
-                       NewField(fieldChatID, chatID),
-                       NewField(fieldUserName, cc.UserName),
-                       NewField(fieldUserID, *cc.ID),
+                       NewField(FieldChatID, chatID),
+                       NewField(FieldUserName, cc.UserName),
+                       NewField(FieldUserID, *cc.ID),
                ),
        )
        res = append(res,
                cc.NewReply(
                        t,
                ),
        )
        res = append(res,
                cc.NewReply(
                        t,
-                       NewField(fieldChatID, chatID),
-                       NewField(fieldUserName, cc.UserName),
-                       NewField(fieldUserID, *cc.ID),
-                       NewField(fieldUserIconID, cc.Icon),
-                       NewField(fieldUserFlags, cc.Flags),
+                       NewField(FieldChatID, chatID),
+                       NewField(FieldUserName, cc.UserName),
+                       NewField(FieldUserID, *cc.ID),
+                       NewField(FieldUserIconID, cc.Icon),
+                       NewField(FieldUserFlags, cc.Flags),
                ),
        )
 
                ),
        )
 
@@ -1811,7 +1813,7 @@ func HandleInviteToChat(cc *ClientConn, t *Transaction) (res []Transaction, err
 }
 
 func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 }
 
 func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       chatID := t.GetField(fieldChatID).Data
+       chatID := t.GetField(FieldChatID).Data
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
@@ -1821,10 +1823,10 @@ func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction,
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
-                               tranChatMsg,
+                               TranChatMsg,
                                c.ID,
                                c.ID,
-                               NewField(fieldChatID, chatID),
-                               NewField(fieldData, resMsg),
+                               NewField(FieldChatID, chatID),
+                               NewField(FieldData, resMsg),
                        ),
                )
        }
                        ),
                )
        }
@@ -1838,29 +1840,29 @@ func HandleRejectChatInvite(cc *ClientConn, t *Transaction) (res []Transaction,
 // * 300       User name with info (Optional)
 // * 300       (more user names with info)
 func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 // * 300       User name with info (Optional)
 // * 300       (more user names with info)
 func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       chatID := t.GetField(fieldChatID).Data
+       chatID := t.GetField(FieldChatID).Data
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
 
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
 
-       // Send tranNotifyChatChangeUser to current members of the chat to inform of new user
+       // Send TranNotifyChatChangeUser to current members of the chat to inform of new user
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
-                               tranNotifyChatChangeUser,
+                               TranNotifyChatChangeUser,
                                c.ID,
                                c.ID,
-                               NewField(fieldChatID, chatID),
-                               NewField(fieldUserName, cc.UserName),
-                               NewField(fieldUserID, *cc.ID),
-                               NewField(fieldUserIconID, cc.Icon),
-                               NewField(fieldUserFlags, cc.Flags),
+                               NewField(FieldChatID, chatID),
+                               NewField(FieldUserName, cc.UserName),
+                               NewField(FieldUserID, *cc.ID),
+                               NewField(FieldUserIconID, cc.Icon),
+                               NewField(FieldUserFlags, cc.Flags),
                        ),
                )
        }
 
        privChat.ClientConn[cc.uint16ID()] = cc
 
                        ),
                )
        }
 
        privChat.ClientConn[cc.uint16ID()] = cc
 
-       replyFields := []Field{NewField(fieldChatSubject, []byte(privChat.Subject))}
+       replyFields := []Field{NewField(FieldChatSubject, []byte(privChat.Subject))}
        for _, c := range sortedClients(privChat.ClientConn) {
                user := User{
                        ID:    *c.ID,
        for _, c := range sortedClients(privChat.ClientConn) {
                user := User{
                        ID:    *c.ID,
@@ -1869,7 +1871,7 @@ func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err erro
                        Name:  string(c.UserName),
                }
 
                        Name:  string(c.UserName),
                }
 
-               replyFields = append(replyFields, NewField(fieldUsernameWithInfo, user.Payload()))
+               replyFields = append(replyFields, NewField(FieldUsernameWithInfo, user.Payload()))
        }
 
        res = append(res, cc.NewReply(t, replyFields...))
        }
 
        res = append(res, cc.NewReply(t, replyFields...))
@@ -1878,11 +1880,11 @@ func HandleJoinChat(cc *ClientConn, t *Transaction) (res []Transaction, err erro
 
 // HandleLeaveChat is sent from a v1.8+ Hotline client when the user exits a private chat
 // Fields used in the request:
 
 // HandleLeaveChat is sent from a v1.8+ Hotline client when the user exits a private chat
 // Fields used in the request:
-//   - 114     fieldChatID
+//   - 114     FieldChatID
 //
 // Reply is not expected.
 func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 //
 // Reply is not expected.
 func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       chatID := t.GetField(fieldChatID).Data
+       chatID := t.GetField(FieldChatID).Data
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat, ok := cc.Server.PrivateChats[chatInt]
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat, ok := cc.Server.PrivateChats[chatInt]
@@ -1896,10 +1898,10 @@ func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err err
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
-                               tranNotifyChatDeleteUser,
+                               TranNotifyChatDeleteUser,
                                c.ID,
                                c.ID,
-                               NewField(fieldChatID, chatID),
-                               NewField(fieldUserID, *cc.ID),
+                               NewField(FieldChatID, chatID),
+                               NewField(FieldUserID, *cc.ID),
                        ),
                )
        }
                        ),
                )
        }
@@ -1913,19 +1915,19 @@ func HandleLeaveChat(cc *ClientConn, t *Transaction) (res []Transaction, err err
 // * 115       Chat subject
 // Reply is not expected.
 func HandleSetChatSubject(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
 // * 115       Chat subject
 // Reply is not expected.
 func HandleSetChatSubject(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       chatID := t.GetField(fieldChatID).Data
+       chatID := t.GetField(FieldChatID).Data
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
        chatInt := binary.BigEndian.Uint32(chatID)
 
        privChat := cc.Server.PrivateChats[chatInt]
-       privChat.Subject = string(t.GetField(fieldChatSubject).Data)
+       privChat.Subject = string(t.GetField(FieldChatSubject).Data)
 
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
 
        for _, c := range sortedClients(privChat.ClientConn) {
                res = append(res,
                        *NewTransaction(
-                               tranNotifyChatSubject,
+                               TranNotifyChatSubject,
                                c.ID,
                                c.ID,
-                               NewField(fieldChatID, chatID),
-                               NewField(fieldChatSubject, t.GetField(fieldChatSubject).Data),
+                               NewField(FieldChatID, chatID),
+                               NewField(FieldChatSubject, t.GetField(FieldChatSubject).Data),
                        ),
                )
        }
                        ),
                )
        }
@@ -1946,9 +1948,9 @@ func HandleMakeAlias(cc *ClientConn, t *Transaction) (res []Transaction, err err
                res = append(res, cc.NewErrReply(t, "You are not allowed to make aliases."))
                return res, err
        }
                res = append(res, cc.NewErrReply(t, "You are not allowed to make aliases."))
                return res, err
        }
-       fileName := t.GetField(fieldFileName).Data
-       filePath := t.GetField(fieldFilePath).Data
-       fileNewPath := t.GetField(fieldFileNewPath).Data
+       fileName := t.GetField(FieldFileName).Data
+       filePath := t.GetField(FieldFilePath).Data
+       fileNewPath := t.GetField(FieldFileNewPath).Data
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, filePath, fileName)
        if err != nil {
@@ -1975,8 +1977,8 @@ func HandleMakeAlias(cc *ClientConn, t *Transaction) (res []Transaction, err err
 // Fields used in the request:
 // None
 // Fields used in the reply:
 // Fields used in the request:
 // None
 // Fields used in the reply:
-// 107 fieldRefNum                     Used later for transfer
-// 108 fieldTransferSize       Size of data to be downloaded
+// 107 FieldRefNum                     Used later for transfer
+// 108 FieldTransferSize       Size of data to be downloaded
 func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        fi, err := cc.Server.FS.Stat(filepath.Join(cc.Server.ConfigDir, cc.Server.Config.BannerFile))
        if err != nil {
 func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        fi, err := cc.Server.FS.Stat(filepath.Join(cc.Server.ConfigDir, cc.Server.Config.BannerFile))
        if err != nil {
@@ -1988,8 +1990,8 @@ func HandleDownloadBanner(cc *ClientConn, t *Transaction) (res []Transaction, er
        binary.BigEndian.PutUint32(ft.TransferSize, uint32(fi.Size()))
 
        res = append(res, cc.NewReply(t,
        binary.BigEndian.PutUint32(ft.TransferSize, uint32(fi.Size()))
 
        res = append(res, cc.NewReply(t,
-               NewField(fieldRefNum, ft.refNum[:]),
-               NewField(fieldTransferSize, ft.TransferSize),
+               NewField(FieldRefNum, ft.refNum[:]),
+               NewField(FieldTransferSize, ft.TransferSize),
        ))
 
        return res, err
        ))
 
        return res, err
index 3f46f645cf5ed134b61f1db43d7cc5388592403e..751590e7aff710809a7996d80f5b0ffec592c337 100644 (file)
@@ -73,8 +73,8 @@ func TestHandleSetChatSubject(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 1},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 1},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldChatSubject, []byte("Test Subject")),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldChatSubject, []byte("Test Subject")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -87,8 +87,8 @@ func TestHandleSetChatSubject(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldChatSubject, []byte("Test Subject")),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldChatSubject, []byte("Test Subject")),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -99,8 +99,8 @@ func TestHandleSetChatSubject(t *testing.T) {
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldChatSubject, []byte("Test Subject")),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldChatSubject, []byte("Test Subject")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -174,7 +174,7 @@ func TestHandleLeaveChat(t *testing.T) {
                                                },
                                        },
                                },
                                                },
                                        },
                                },
-                               t: NewTransaction(tranDeleteUser, nil, NewField(fieldChatID, []byte{0, 0, 0, 1})),
+                               t: NewTransaction(TranDeleteUser, nil, NewField(FieldChatID, []byte{0, 0, 0, 1})),
                        },
                        want: []Transaction{
                                {
                        },
                        want: []Transaction{
                                {
@@ -185,8 +185,8 @@ func TestHandleLeaveChat(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldUserID, []byte{0, 2}),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldUserID, []byte{0, 2}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -257,11 +257,11 @@ func TestHandleGetUserNameList(t *testing.T) {
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                                NewField(
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                                NewField(
-                                                       fieldUsernameWithInfo,
+                                                       FieldUsernameWithInfo,
                                                        []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
                                                ),
                                                NewField(
                                                        []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
                                                ),
                                                NewField(
-                                                       fieldUsernameWithInfo,
+                                                       FieldUsernameWithInfo,
                                                        []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
                                                ),
                                        },
                                                        []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
                                                ),
                                        },
@@ -324,7 +324,7 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("hai")),
+                                               NewField(FieldData, []byte("hai")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -337,7 +337,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -348,7 +348,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -385,8 +385,8 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("hai")),
-                                               NewField(fieldChatID, []byte{0, 0, 0, 0}),
+                                               NewField(FieldData, []byte("hai")),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 0}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -399,7 +399,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -410,7 +410,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -431,8 +431,8 @@ func TestHandleChatSend(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranChatSend, &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
+                                       TranChatSend, &[]byte{0, 1},
+                                       NewField(FieldData, []byte("hai")),
                                ),
                        },
                        want: []Transaction{
                                ),
                        },
                        want: []Transaction{
@@ -443,14 +443,14 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to participate in chat.")),
+                                               NewField(FieldError, []byte("You are not allowed to participate in chat.")),
                                        },
                                },
                        },
                        wantErr: false,
                },
                {
                                        },
                                },
                        },
                        wantErr: false,
                },
                {
-                       name: "sends chat msg as emote if fieldChatOptions is set to 1",
+                       name: "sends chat msg as emote if FieldChatOptions is set to 1",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -480,8 +480,8 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("performed action")),
-                                               NewField(fieldChatOptions, []byte{0x00, 0x01}),
+                                               NewField(FieldData, []byte("performed action")),
+                                               NewField(FieldChatOptions, []byte{0x00, 0x01}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -494,7 +494,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("\r*** Testy McTest performed action")),
+                                               NewField(FieldData, []byte("\r*** Testy McTest performed action")),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -505,14 +505,14 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("\r*** Testy McTest performed action")),
+                                               NewField(FieldData, []byte("\r*** Testy McTest performed action")),
                                        },
                                },
                        },
                        wantErr: false,
                },
                {
                                        },
                                },
                        },
                        wantErr: false,
                },
                {
-                       name: "does not send chat msg as emote if fieldChatOptions is set to 0",
+                       name: "does not send chat msg as emote if FieldChatOptions is set to 0",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -542,8 +542,8 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("hello")),
-                                               NewField(fieldChatOptions, []byte{0x00, 0x00}),
+                                               NewField(FieldData, []byte("hello")),
+                                               NewField(FieldChatOptions, []byte{0x00, 0x00}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -556,7 +556,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("\r Testy McTest:  hello")),
+                                               NewField(FieldData, []byte("\r Testy McTest:  hello")),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -567,7 +567,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("\r Testy McTest:  hello")),
+                                               NewField(FieldData, []byte("\r Testy McTest:  hello")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -607,7 +607,7 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("hai")),
+                                               NewField(FieldData, []byte("hai")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -620,7 +620,7 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -675,8 +675,8 @@ func TestHandleChatSend(t *testing.T) {
                                },
                                t: &Transaction{
                                        Fields: []Field{
                                },
                                t: &Transaction{
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("hai")),
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldData, []byte("hai")),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -689,8 +689,8 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -701,8 +701,8 @@ func TestHandleChatSend(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0, 0, 0, 1}),
-                                               NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+                                               NewField(FieldChatID, []byte{0, 0, 0, 1}),
+                                               NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -751,9 +751,9 @@ func TestHandleGetFileInfo(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetFileInfo, nil,
-                                       NewField(fieldFileName, []byte("testfile.txt")),
-                                       NewField(fieldFilePath, []byte{0x00, 0x00}),
+                                       TranGetFileInfo, nil,
+                                       NewField(FieldFileName, []byte("testfile.txt")),
+                                       NewField(FieldFilePath, []byte{0x00, 0x00}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -765,14 +765,14 @@ func TestHandleGetFileInfo(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldFileName, []byte("testfile.txt")),
-                                               NewField(fieldFileTypeString, []byte("Text File")),
-                                               NewField(fieldFileCreatorString, []byte("ttxt")),
-                                               NewField(fieldFileComment, []byte{}),
-                                               NewField(fieldFileType, []byte("TEXT")),
-                                               NewField(fieldFileCreateDate, make([]byte, 8)),
-                                               NewField(fieldFileModifyDate, make([]byte, 8)),
-                                               NewField(fieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
+                                               NewField(FieldFileName, []byte("testfile.txt")),
+                                               NewField(FieldFileTypeString, []byte("Text File")),
+                                               NewField(FieldFileCreatorString, []byte("ttxt")),
+                                               NewField(FieldFileComment, []byte{}),
+                                               NewField(FieldFileType, []byte("TEXT")),
+                                               NewField(FieldFileCreateDate, make([]byte, 8)),
+                                               NewField(FieldFileModifyDate, make([]byte, 8)),
+                                               NewField(FieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -835,7 +835,7 @@ func TestHandleNewFolder(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to create folders.")),
+                                               NewField(FieldError, []byte("You are not allowed to create folders.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -866,9 +866,9 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewFolder, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFolder")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranNewFolder, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFolder")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -913,8 +913,8 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewFolder, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFolder")),
+                                       TranNewFolder, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFolder")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -954,9 +954,9 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewFolder, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFolder")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranNewFolder, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFolder")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00,
                                        }),
                                ),
                                                0x00,
                                        }),
                                ),
@@ -965,7 +965,7 @@ func TestHandleNewFolder(t *testing.T) {
                        wantErr: true,
                },
                {
                        wantErr: true,
                },
                {
-                       name: "fieldFileName does not allow directory traversal",
+                       name: "FieldFileName does not allow directory traversal",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -989,8 +989,8 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewFolder, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("../../testFolder")),
+                                       TranNewFolder, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("../../testFolder")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1005,7 +1005,7 @@ func TestHandleNewFolder(t *testing.T) {
                        }, wantErr: false,
                },
                {
                        }, wantErr: false,
                },
                {
-                       name: "fieldFilePath does not allow directory traversal",
+                       name: "FieldFilePath does not allow directory traversal",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -1029,9 +1029,9 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewFolder, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFolder")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranNewFolder, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFolder")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x02,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x02,
                                                0x00, 0x00,
                                                0x03,
@@ -1104,9 +1104,9 @@ func TestHandleUploadFile(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranUploadFile, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFile")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranUploadFile, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFile")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -1122,7 +1122,7 @@ func TestHandleUploadFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
+                                               NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1140,9 +1140,9 @@ func TestHandleUploadFile(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranUploadFile, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFile")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranUploadFile, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFile")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -1158,7 +1158,7 @@ func TestHandleUploadFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
+                                               NewField(FieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1224,10 +1224,10 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranMakeFileAlias, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFile")),
-                                       NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
-                                       NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
+                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFile")),
+                                       NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
+                                       NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1275,10 +1275,10 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranMakeFileAlias, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFile")),
-                                       NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
-                                       NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
+                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFile")),
+                                       NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
+                                       NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1289,7 +1289,7 @@ func TestHandleMakeAlias(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("Error creating alias")),
+                                               NewField(FieldError, []byte("Error creating alias")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1316,15 +1316,15 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranMakeFileAlias, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFile")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFile")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x2e, 0x2e, 0x2e,
                                        }),
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x2e, 0x2e, 0x2e,
                                        }),
-                                       NewField(fieldFileNewPath, []byte{
+                                       NewField(FieldFileNewPath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -1340,7 +1340,7 @@ func TestHandleMakeAlias(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to make aliases.")),
+                                               NewField(FieldError, []byte("You are not allowed to make aliases.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1394,8 +1394,8 @@ func TestHandleGetUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, []byte("guest")),
+                                       TranGetUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, []byte("guest")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1406,10 +1406,10 @@ func TestHandleGetUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldUserName, []byte("Guest")),
-                                               NewField(fieldUserLogin, negateString([]byte("guest"))),
-                                               NewField(fieldUserPassword, []byte("password")),
-                                               NewField(fieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
+                                               NewField(FieldUserName, []byte("Guest")),
+                                               NewField(FieldUserLogin, negateString([]byte("guest"))),
+                                               NewField(FieldUserPassword, []byte("password")),
+                                               NewField(FieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1430,8 +1430,8 @@ func TestHandleGetUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, []byte("nonExistentUser")),
+                                       TranGetUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, []byte("nonExistentUser")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1442,7 +1442,7 @@ func TestHandleGetUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to view accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to view accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1464,8 +1464,8 @@ func TestHandleGetUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, []byte("nonExistentUser")),
+                                       TranGetUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, []byte("nonExistentUser")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1476,7 +1476,7 @@ func TestHandleGetUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("Account does not exist.")),
+                                               NewField(FieldError, []byte("Account does not exist.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1534,8 +1534,8 @@ func TestHandleDeleteUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDeleteUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, negateString([]byte("testuser"))),
+                                       TranDeleteUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, negateString([]byte("testuser"))),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1565,8 +1565,8 @@ func TestHandleDeleteUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDeleteUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, negateString([]byte("testuser"))),
+                                       TranDeleteUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, negateString([]byte("testuser"))),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1577,7 +1577,7 @@ func TestHandleDeleteUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1623,7 +1623,7 @@ func TestHandleGetMsgs(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetMsgs, &[]byte{0, 1},
+                                       TranGetMsgs, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1634,7 +1634,7 @@ func TestHandleGetMsgs(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("TEST")),
+                                               NewField(FieldData, []byte("TEST")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1655,7 +1655,7 @@ func TestHandleGetMsgs(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetMsgs, &[]byte{0, 1},
+                                       TranGetMsgs, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1666,7 +1666,7 @@ func TestHandleGetMsgs(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to read news.")),
+                                               NewField(FieldError, []byte("You are not allowed to read news.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1711,7 +1711,7 @@ func TestHandleNewUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewUser, &[]byte{0, 1},
+                                       TranNewUser, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1722,7 +1722,7 @@ func TestHandleNewUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to create new accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to create new accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1744,10 +1744,10 @@ func TestHandleNewUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewUser, &[]byte{0, 1},
-                                       NewField(fieldUserLogin, []byte("userB")),
+                                       TranNewUser, &[]byte{0, 1},
+                                       NewField(FieldUserLogin, []byte("userB")),
                                        NewField(
                                        NewField(
-                                               fieldUserAccess,
+                                               FieldUserAccess,
                                                func() []byte {
                                                        var bits accessBitmap
                                                        bits.Set(accessDisconUser)
                                                func() []byte {
                                                        var bits accessBitmap
                                                        bits.Set(accessDisconUser)
@@ -1764,7 +1764,7 @@ func TestHandleNewUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("Cannot create account with more access than yourself.")),
+                                               NewField(FieldError, []byte("Cannot create account with more access than yourself.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1809,7 +1809,7 @@ func TestHandleListUsers(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranNewUser, &[]byte{0, 1},
+                                       TranNewUser, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1820,7 +1820,7 @@ func TestHandleListUsers(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to view accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to view accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1849,8 +1849,8 @@ func TestHandleListUsers(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetClientInfoText, &[]byte{0, 1},
-                                       NewField(fieldUserID, []byte{0, 1}),
+                                       TranGetClientInfoText, &[]byte{0, 1},
+                                       NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1861,7 +1861,7 @@ func TestHandleListUsers(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte{
+                                               NewField(FieldData, []byte{
                                                        0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
                                                        0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                                        0x00, 0x6a, 0x00, 0x01, 0x78,
                                                        0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
                                                        0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                                        0x00, 0x6a, 0x00, 0x01, 0x78,
@@ -1907,7 +1907,7 @@ func TestHandleDownloadFile(t *testing.T) {
                                        },
                                        Server: &Server{},
                                },
                                        },
                                        Server: &Server{},
                                },
-                               t: NewTransaction(tranDownloadFile, &[]byte{0, 1}),
+                               t: NewTransaction(TranDownloadFile, &[]byte{0, 1}),
                        },
                        wantRes: []Transaction{
                                {
                        },
                        wantRes: []Transaction{
                                {
@@ -1917,7 +1917,7 @@ func TestHandleDownloadFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to download files.")),
+                                               NewField(FieldError, []byte("You are not allowed to download files.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -1949,8 +1949,8 @@ func TestHandleDownloadFile(t *testing.T) {
                                t: NewTransaction(
                                        accessDownloadFile,
                                        &[]byte{0, 1},
                                t: NewTransaction(
                                        accessDownloadFile,
                                        &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testfile.txt")),
-                                       NewField(fieldFilePath, []byte{0x0, 0x00}),
+                                       NewField(FieldFileName, []byte("testfile.txt")),
+                                       NewField(FieldFilePath, []byte{0x0, 0x00}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -1961,10 +1961,10 @@ func TestHandleDownloadFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
-                                               NewField(fieldWaitingCount, []byte{0x00, 0x00}),
-                                               NewField(fieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
-                                               NewField(fieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
+                                               NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
+                                               NewField(FieldWaitingCount, []byte{0x00, 0x00}),
+                                               NewField(FieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
+                                               NewField(FieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2013,10 +2013,10 @@ func TestHandleDownloadFile(t *testing.T) {
                                t: NewTransaction(
                                        accessDownloadFile,
                                        &[]byte{0, 1},
                                t: NewTransaction(
                                        accessDownloadFile,
                                        &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testfile-1k")),
-                                       NewField(fieldFilePath, []byte{0x00, 0x00}),
+                                       NewField(FieldFileName, []byte("testfile-1k")),
+                                       NewField(FieldFilePath, []byte{0x00, 0x00}),
                                        NewField(
                                        NewField(
-                                               fieldFileResumeData,
+                                               FieldFileResumeData,
                                                func() []byte {
                                                        frd := FileResumeData{
                                                                Format:    [4]byte{},
                                                func() []byte {
                                                        frd := FileResumeData{
                                                                Format:    [4]byte{},
@@ -2052,10 +2052,10 @@ func TestHandleDownloadFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
-                                               NewField(fieldWaitingCount, []byte{0x00, 0x00}),
-                                               NewField(fieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
-                                               NewField(fieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
+                                               NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
+                                               NewField(FieldWaitingCount, []byte{0x00, 0x00}),
+                                               NewField(FieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
+                                               NewField(FieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2101,24 +2101,24 @@ func TestHandleUpdateUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranUpdateUser,
+                                       TranUpdateUser,
                                        &[]byte{0, 0},
                                        &[]byte{0, 0},
-                                       NewField(fieldData, []byte{
+                                       NewField(FieldData, []byte{
                                                0x00, 0x04, // field count
 
                                                0x00, 0x04, // field count
 
-                                               0x00, 0x69, // fieldUserLogin = 105
+                                               0x00, 0x69, // FieldUserLogin = 105
                                                0x00, 0x03,
                                                0x9d, 0x9d, 0x9d,
 
                                                0x00, 0x03,
                                                0x9d, 0x9d, 0x9d,
 
-                                               0x00, 0x6a, // fieldUserPassword = 106
+                                               0x00, 0x6a, // FieldUserPassword = 106
                                                0x00, 0x03,
                                                0x9c, 0x9c, 0x9c,
 
                                                0x00, 0x03,
                                                0x9c, 0x9c, 0x9c,
 
-                                               0x00, 0x66, // fieldUserName = 102
+                                               0x00, 0x66, // FieldUserName = 102
                                                0x00, 0x03,
                                                0x61, 0x61, 0x61,
 
                                                0x00, 0x03,
                                                0x61, 0x61, 0x61,
 
-                                               0x00, 0x6e, // fieldUserAccess = 110
+                                               0x00, 0x6e, // FieldUserAccess = 110
                                                0x00, 0x08,
                                                0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
                                        }),
                                                0x00, 0x08,
                                                0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
                                        }),
@@ -2132,7 +2132,7 @@ func TestHandleUpdateUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to create new accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to create new accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2157,24 +2157,24 @@ func TestHandleUpdateUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranUpdateUser,
+                                       TranUpdateUser,
                                        &[]byte{0, 0},
                                        &[]byte{0, 0},
-                                       NewField(fieldData, []byte{
+                                       NewField(FieldData, []byte{
                                                0x00, 0x04, // field count
 
                                                0x00, 0x04, // field count
 
-                                               0x00, 0x69, // fieldUserLogin = 105
+                                               0x00, 0x69, // FieldUserLogin = 105
                                                0x00, 0x03,
                                                0x9d, 0x9d, 0x9d,
 
                                                0x00, 0x03,
                                                0x9d, 0x9d, 0x9d,
 
-                                               0x00, 0x6a, // fieldUserPassword = 106
+                                               0x00, 0x6a, // FieldUserPassword = 106
                                                0x00, 0x03,
                                                0x9c, 0x9c, 0x9c,
 
                                                0x00, 0x03,
                                                0x9c, 0x9c, 0x9c,
 
-                                               0x00, 0x66, // fieldUserName = 102
+                                               0x00, 0x66, // FieldUserName = 102
                                                0x00, 0x03,
                                                0x61, 0x61, 0x61,
 
                                                0x00, 0x03,
                                                0x61, 0x61, 0x61,
 
-                                               0x00, 0x6e, // fieldUserAccess = 110
+                                               0x00, 0x6e, // FieldUserAccess = 110
                                                0x00, 0x08,
                                                0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
                                        }),
                                                0x00, 0x08,
                                                0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
                                        }),
@@ -2188,7 +2188,7 @@ func TestHandleUpdateUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to modify accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to modify accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2212,9 +2212,9 @@ func TestHandleUpdateUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranUpdateUser,
+                                       TranUpdateUser,
                                        &[]byte{0, 0},
                                        &[]byte{0, 0},
-                                       NewField(fieldData, []byte{
+                                       NewField(FieldData, []byte{
                                                0x00, 0x01,
                                                0x00, 0x65,
                                                0x00, 0x03,
                                                0x00, 0x01,
                                                0x00, 0x65,
                                                0x00, 0x03,
@@ -2230,7 +2230,7 @@ func TestHandleUpdateUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete accounts.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete accounts.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2272,7 +2272,7 @@ func TestHandleDelNewsArt(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsArt,
+                                       TranDelNewsArt,
                                        &[]byte{0, 0},
                                ),
                        },
                                        &[]byte{0, 0},
                                ),
                        },
@@ -2284,7 +2284,7 @@ func TestHandleDelNewsArt(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete news articles.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete news articles.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2325,7 +2325,7 @@ func TestHandleDisconnectUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsArt,
+                                       TranDelNewsArt,
                                        &[]byte{0, 0},
                                ),
                        },
                                        &[]byte{0, 0},
                                ),
                        },
@@ -2337,7 +2337,7 @@ func TestHandleDisconnectUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to disconnect users.")),
+                                               NewField(FieldError, []byte("You are not allowed to disconnect users.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2370,9 +2370,9 @@ func TestHandleDisconnectUser(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsArt,
+                                       TranDelNewsArt,
                                        &[]byte{0, 0},
                                        &[]byte{0, 0},
-                                       NewField(fieldUserID, []byte{0, 1}),
+                                       NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -2383,7 +2383,7 @@ func TestHandleDisconnectUser(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("unnamed is not allowed to be disconnected.")),
+                                               NewField(FieldError, []byte("unnamed is not allowed to be disconnected.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2424,7 +2424,7 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsArt,
+                                       TranDelNewsArt,
                                        &[]byte{0, 0},
                                ),
                        },
                                        &[]byte{0, 0},
                                ),
                        },
@@ -2436,7 +2436,7 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to send private messages.")),
+                                               NewField(FieldError, []byte("You are not allowed to send private messages.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2465,20 +2465,20 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranSendInstantMsg,
+                                       TranSendInstantMsg,
                                        &[]byte{0, 1},
                                        &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
-                                       NewField(fieldUserID, []byte{0, 2}),
+                                       NewField(FieldData, []byte("hai")),
+                                       NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
-                                       tranServerMsg,
+                                       TranServerMsg,
                                        &[]byte{0, 2},
                                        &[]byte{0, 2},
-                                       NewField(fieldData, []byte("hai")),
-                                       NewField(fieldUserName, []byte("User1")),
-                                       NewField(fieldUserID, []byte{0, 1}),
-                                       NewField(fieldOptions, []byte{0, 1}),
+                                       NewField(FieldData, []byte("hai")),
+                                       NewField(FieldUserName, []byte("User1")),
+                                       NewField(FieldUserID, []byte{0, 1}),
+                                       NewField(FieldOptions, []byte{0, 1}),
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
@@ -2517,28 +2517,28 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranSendInstantMsg,
+                                       TranSendInstantMsg,
                                        &[]byte{0, 1},
                                        &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
-                                       NewField(fieldUserID, []byte{0, 2}),
+                                       NewField(FieldData, []byte("hai")),
+                                       NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
-                                       tranServerMsg,
+                                       TranServerMsg,
                                        &[]byte{0, 2},
                                        &[]byte{0, 2},
-                                       NewField(fieldData, []byte("hai")),
-                                       NewField(fieldUserName, []byte("User1")),
-                                       NewField(fieldUserID, []byte{0, 1}),
-                                       NewField(fieldOptions, []byte{0, 1}),
+                                       NewField(FieldData, []byte("hai")),
+                                       NewField(FieldUserName, []byte("User1")),
+                                       NewField(FieldUserID, []byte{0, 1}),
+                                       NewField(FieldOptions, []byte{0, 1}),
                                ),
                                *NewTransaction(
                                ),
                                *NewTransaction(
-                                       tranServerMsg,
+                                       TranServerMsg,
                                        &[]byte{0, 1},
                                        &[]byte{0, 1},
-                                       NewField(fieldData, []byte("autohai")),
-                                       NewField(fieldUserName, []byte("User2")),
-                                       NewField(fieldUserID, []byte{0, 2}),
-                                       NewField(fieldOptions, []byte{0, 1}),
+                                       NewField(FieldData, []byte("autohai")),
+                                       NewField(FieldUserName, []byte("User2")),
+                                       NewField(FieldUserID, []byte{0, 2}),
+                                       NewField(FieldOptions, []byte{0, 1}),
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
@@ -2576,20 +2576,20 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranSendInstantMsg,
+                                       TranSendInstantMsg,
                                        &[]byte{0, 1},
                                        &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
-                                       NewField(fieldUserID, []byte{0, 2}),
+                                       NewField(FieldData, []byte("hai")),
+                                       NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
                                ),
                        },
                        wantRes: []Transaction{
                                *NewTransaction(
-                                       tranServerMsg,
+                                       TranServerMsg,
                                        &[]byte{0, 1},
                                        &[]byte{0, 1},
-                                       NewField(fieldData, []byte("User2 does not accept private messages.")),
-                                       NewField(fieldUserName, []byte("User2")),
-                                       NewField(fieldUserID, []byte{0, 2}),
-                                       NewField(fieldOptions, []byte{0, 2}),
+                                       NewField(FieldData, []byte("User2 does not accept private messages.")),
+                                       NewField(FieldUserName, []byte("User2")),
+                                       NewField(FieldUserID, []byte{0, 2}),
+                                       NewField(FieldOptions, []byte{0, 2}),
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
                                ),
                                {
                                        clientID:  &[]byte{0, 1},
@@ -2662,9 +2662,9 @@ func TestHandleDeleteFile(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDeleteFile, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testfile")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranDeleteFile, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testfile")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -2680,7 +2680,7 @@ func TestHandleDeleteFile(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete files.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete files.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2727,9 +2727,9 @@ func TestHandleDeleteFile(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDeleteFile, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testfile")),
-                                       NewField(fieldFilePath, []byte{
+                                       TranDeleteFile, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testfile")),
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x03,
@@ -2776,7 +2776,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                wantErr assert.ErrorAssertionFunc
        }{
                {
                wantErr assert.ErrorAssertionFunc
        }{
                {
-                       name: "when fieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
+                       name: "when FieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -2796,8 +2796,8 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetFileNameList, &[]byte{0, 1},
-                                       NewField(fieldFilePath, []byte{
+                                       TranGetFileNameList, &[]byte{0, 1},
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x08,
                                                0x00, 0x01,
                                                0x00, 0x00,
                                                0x08,
@@ -2813,7 +2813,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to view drop boxes.")),
+                                               NewField(FieldError, []byte("You are not allowed to view drop boxes.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2833,8 +2833,8 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetFileNameList, &[]byte{0, 1},
-                                       NewField(fieldFilePath, []byte{
+                                       TranGetFileNameList, &[]byte{0, 1},
+                                       NewField(FieldFilePath, []byte{
                                                0x00, 0x00,
                                                0x00, 0x00,
                                        }),
                                                0x00, 0x00,
                                                0x00, 0x00,
                                        }),
@@ -2849,7 +2849,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                                NewField(
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                                NewField(
-                                                       fieldFileNameWithInfo,
+                                                       FieldFileNameWithInfo,
                                                        func() []byte {
                                                                fnwi := FileNameWithInfo{
                                                                        fileNameWithInfoHeader: fileNameWithInfoHeader{
                                                        func() []byte {
                                                                fnwi := FileNameWithInfo{
                                                                        fileNameWithInfoHeader: fileNameWithInfoHeader{
@@ -2910,8 +2910,8 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetClientInfoText, &[]byte{0, 1},
-                                       NewField(fieldUserID, []byte{0, 1}),
+                                       TranGetClientInfoText, &[]byte{0, 1},
+                                       NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -2922,7 +2922,7 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to get client info.")),
+                                               NewField(FieldError, []byte("You are not allowed to get client info.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -2969,8 +2969,8 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetClientInfoText, &[]byte{0, 1},
-                                       NewField(fieldUserID, []byte{0, 1}),
+                                       TranGetClientInfoText, &[]byte{0, 1},
+                                       NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -2981,7 +2981,7 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte(
+                                               NewField(FieldData, []byte(
                                                        strings.Replace(`Nickname:   Testy McTest
 Name:       test
 Account:    test
                                                        strings.Replace(`Nickname:   Testy McTest
 Name:       test
 Account:    test
@@ -3009,7 +3009,7 @@ None.
 
 `, "\n", "\r", -1)),
                                                ),
 
 `, "\n", "\r", -1)),
                                                ),
-                                               NewField(fieldUserName, []byte("Testy McTest")),
+                                               NewField(FieldUserName, []byte("Testy McTest")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3061,10 +3061,10 @@ func TestHandleTranAgreed(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranAgreed, nil,
-                                       NewField(fieldUserName, []byte("username")),
-                                       NewField(fieldUserIconID, []byte{0, 1}),
-                                       NewField(fieldOptions, []byte{0, 0}),
+                                       TranAgreed, nil,
+                                       NewField(FieldUserName, []byte("username")),
+                                       NewField(FieldUserIconID, []byte{0, 1}),
+                                       NewField(FieldOptions, []byte{0, 0}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3076,7 +3076,7 @@ func TestHandleTranAgreed(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldBannerType, []byte("JPEG")),
+                                               NewField(FieldBannerType, []byte("JPEG")),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -3136,9 +3136,9 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranSetClientUserInfo, nil,
-                                       NewField(fieldUserIconID, []byte{0, 1}),
-                                       NewField(fieldUserName, []byte("NOPE")),
+                                       TranSetClientUserInfo, nil,
+                                       NewField(FieldUserIconID, []byte{0, 1}),
+                                       NewField(FieldUserName, []byte("NOPE")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3150,10 +3150,10 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldUserID, []byte{0, 1}),
-                                               NewField(fieldUserIconID, []byte{0, 1}),
-                                               NewField(fieldUserFlags, []byte{0, 1}),
-                                               NewField(fieldUserName, []byte("Guest"))},
+                                               NewField(FieldUserID, []byte{0, 1}),
+                                               NewField(FieldUserIconID, []byte{0, 1}),
+                                               NewField(FieldUserFlags, []byte{0, 1}),
+                                               NewField(FieldUserName, []byte("Guest"))},
                                },
                        },
                        wantErr: assert.NoError,
                                },
                        },
                        wantErr: assert.NoError,
@@ -3202,8 +3202,8 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsItem, nil,
-                                       NewField(fieldNewsPath,
+                                       TranDelNewsItem, nil,
+                                       NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
@@ -3222,7 +3222,7 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete news categories.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete news categories.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3248,8 +3248,8 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsItem, nil,
-                                       NewField(fieldNewsPath,
+                                       TranDelNewsItem, nil,
+                                       NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
@@ -3268,7 +3268,7 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to delete news folders.")),
+                                               NewField(FieldError, []byte("You are not allowed to delete news folders.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3304,8 +3304,8 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranDelNewsItem, nil,
-                                       NewField(fieldNewsPath,
+                                       TranDelNewsItem, nil,
+                                       NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
@@ -3375,7 +3375,7 @@ func TestHandleDownloadBanner(t *testing.T) {
                                                }(),
                                        },
                                },
                                                }(),
                                        },
                                },
-                               t: NewTransaction(tranDownloadBanner, nil),
+                               t: NewTransaction(TranDownloadBanner, nil),
                        },
                        wantRes: []Transaction{
                                {
                        },
                        wantRes: []Transaction{
                                {
@@ -3386,8 +3386,8 @@ func TestHandleDownloadBanner(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldRefNum, []byte{1, 2, 3, 4}),
-                                               NewField(fieldTransferSize, []byte{0, 0, 0, 0x64}),
+                                               NewField(FieldRefNum, []byte{1, 2, 3, 4}),
+                                               NewField(FieldTransferSize, []byte{0, 0, 0, 0x64}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3429,8 +3429,8 @@ func TestHandleTranOldPostNews(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranOldPostNews, &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
+                                       TranOldPostNews, &[]byte{0, 1},
+                                       NewField(FieldData, []byte("hai")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3441,7 +3441,7 @@ func TestHandleTranOldPostNews(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to post news.")),
+                                               NewField(FieldError, []byte("You are not allowed to post news.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3469,8 +3469,8 @@ func TestHandleTranOldPostNews(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranOldPostNews, &[]byte{0, 1},
-                                       NewField(fieldData, []byte("hai")),
+                                       TranOldPostNews, &[]byte{0, 1},
+                                       NewField(FieldData, []byte("hai")),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3519,7 +3519,7 @@ func TestHandleInviteNewChat(t *testing.T) {
                                                }(),
                                        },
                                },
                                                }(),
                                        },
                                },
-                               t: NewTransaction(tranInviteNewChat, &[]byte{0, 1}),
+                               t: NewTransaction(TranInviteNewChat, &[]byte{0, 1}),
                        },
                        wantRes: []Transaction{
                                {
                        },
                        wantRes: []Transaction{
                                {
@@ -3529,7 +3529,7 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to request private chat.")),
+                                               NewField(FieldError, []byte("You are not allowed to request private chat.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3562,8 +3562,8 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranInviteNewChat, &[]byte{0, 1},
-                                       NewField(fieldUserID, []byte{0, 2}),
+                                       TranInviteNewChat, &[]byte{0, 1},
+                                       NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3575,9 +3575,9 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
-                                               NewField(fieldUserName, []byte("UserA")),
-                                               NewField(fieldUserID, []byte{0, 1}),
+                                               NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
+                                               NewField(FieldUserName, []byte("UserA")),
+                                               NewField(FieldUserID, []byte{0, 1}),
                                        },
                                },
 
                                        },
                                },
 
@@ -3589,11 +3589,11 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
-                                               NewField(fieldUserName, []byte("UserA")),
-                                               NewField(fieldUserID, []byte{0, 1}),
-                                               NewField(fieldUserIconID, []byte{0, 1}),
-                                               NewField(fieldUserFlags, []byte{0, 0}),
+                                               NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
+                                               NewField(FieldUserName, []byte("UserA")),
+                                               NewField(FieldUserID, []byte{0, 1}),
+                                               NewField(FieldUserIconID, []byte{0, 1}),
+                                               NewField(FieldUserFlags, []byte{0, 0}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3626,8 +3626,8 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranInviteNewChat, &[]byte{0, 1},
-                                       NewField(fieldUserID, []byte{0, 2}),
+                                       TranInviteNewChat, &[]byte{0, 1},
+                                       NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3639,10 +3639,10 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldData, []byte("UserB does not accept private chats.")),
-                                               NewField(fieldUserName, []byte("UserB")),
-                                               NewField(fieldUserID, []byte{0, 2}),
-                                               NewField(fieldOptions, []byte{0, 2}),
+                                               NewField(FieldData, []byte("UserB does not accept private chats.")),
+                                               NewField(FieldUserName, []byte("UserB")),
+                                               NewField(FieldUserID, []byte{0, 2}),
+                                               NewField(FieldOptions, []byte{0, 2}),
                                        },
                                },
                                {
                                        },
                                },
                                {
@@ -3653,11 +3653,11 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
                                        ID:        []byte{0, 0, 0, 0},
                                        ErrorCode: []byte{0, 0, 0, 0},
                                        Fields: []Field{
-                                               NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
-                                               NewField(fieldUserName, []byte("UserA")),
-                                               NewField(fieldUserID, []byte{0, 1}),
-                                               NewField(fieldUserIconID, []byte{0, 1}),
-                                               NewField(fieldUserFlags, []byte{0, 0}),
+                                               NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
+                                               NewField(FieldUserName, []byte("UserA")),
+                                               NewField(FieldUserID, []byte{0, 1}),
+                                               NewField(FieldUserIconID, []byte{0, 1}),
+                                               NewField(FieldUserFlags, []byte{0, 0}),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3702,7 +3702,7 @@ func TestHandleGetNewsArtData(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetNewsArtData, &[]byte{0, 1},
+                                       TranGetNewsArtData, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3713,7 +3713,7 @@ func TestHandleGetNewsArtData(t *testing.T) {
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to read news.")),
+                                               NewField(FieldError, []byte("You are not allowed to read news.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3757,7 +3757,7 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetNewsArtNameList, &[]byte{0, 1},
+                                       TranGetNewsArtNameList, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3767,7 +3767,7 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
                                        Type:      []byte{0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        Type:      []byte{0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to read news.")),
+                                               NewField(FieldError, []byte("You are not allowed to read news.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3812,7 +3812,7 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetNewsArtNameList, &[]byte{0, 1},
+                                       TranGetNewsArtNameList, &[]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                ),
                        },
                        wantRes: []Transaction{
@@ -3822,7 +3822,7 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                        Type:      []byte{0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
                                        Type:      []byte{0, 0},
                                        ErrorCode: []byte{0, 0, 0, 1},
                                        Fields: []Field{
-                                               NewField(fieldError, []byte("You are not allowed to create news folders.")),
+                                               NewField(FieldError, []byte("You are not allowed to create news folders.")),
                                        },
                                },
                        },
                                        },
                                },
                        },
@@ -3860,9 +3860,9 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
                                        },
                                },
                                t: NewTransaction(
-                                       tranGetNewsArtNameList, &[]byte{0, 1},
-                                       NewField(fieldFileName, []byte("testFolder")),
-                                       NewField(fieldNewsPath,
+                                       TranGetNewsArtNameList, &[]byte{0, 1},
+                                       NewField(FieldFileName, []byte("testFolder")),
+                                       NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
                                                []byte{
                                                        0, 1,
                                                        0, 0,
@@ -3917,9 +3917,9 @@ func TestHandleNewNewsFldr(t *testing.T) {
                //                      },
                //              },
                //              t: NewTransaction(
                //                      },
                //              },
                //              t: NewTransaction(
-               //                      tranGetNewsArtNameList, &[]byte{0, 1},
-               //                      NewField(fieldFileName, []byte("testFolder")),
-               //                      NewField(fieldNewsPath,
+               //                      TranGetNewsArtNameList, &[]byte{0, 1},
+               //                      NewField(FieldFileName, []byte("testFolder")),
+               //                      NewField(FieldNewsPath,
                //                              []byte{
                //                                      0, 1,
                //                                      0, 0,
                //                              []byte{
                //                                      0, 1,
                //                                      0, 0,
@@ -3937,7 +3937,7 @@ func TestHandleNewNewsFldr(t *testing.T) {
                //                      Type:      []byte{0, 0},
                //                      ErrorCode: []byte{0, 0, 0, 1},
                //                      Fields: []Field{
                //                      Type:      []byte{0, 0},
                //                      ErrorCode: []byte{0, 0, 0, 1},
                //                      Fields: []Field{
-               //                              NewField(fieldError, []byte("Error creating news folder.")),
+               //                              NewField(FieldError, []byte("Error creating news folder.")),
                //                      },
                //              },
                //      },
                //                      },
                //              },
                //      },
index 4b4f183a52b02b2939811d28d2a85ac7fce9a5b2..65f428a7c0f187bd4f01c02c425a5818fd59ceff 100644 (file)
@@ -22,10 +22,10 @@ func TestReadFields(t *testing.T) {
                        args: args{
                                paramCount: []byte{0x00, 0x02},
                                buf: []byte{
                        args: args{
                                paramCount: []byte{0x00, 0x02},
                                buf: []byte{
-                                       0x00, 0x65, // ID: fieldData
+                                       0x00, 0x65, // ID: FieldData
                                        0x00, 0x04, // Size: 2 bytes
                                        0x01, 0x02, 0x03, 0x04, // Data
                                        0x00, 0x04, // Size: 2 bytes
                                        0x01, 0x02, 0x03, 0x04, // Data
-                                       0x00, 0x66, // ID: fieldUserName
+                                       0x00, 0x66, // ID: FieldUserName
                                        0x00, 0x02, // Size: 2 bytes
                                        0x00, 0x01, // Data
                                },
                                        0x00, 0x02, // Size: 2 bytes
                                        0x00, 0x01, // Data
                                },
@@ -58,7 +58,7 @@ func TestReadFields(t *testing.T) {
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
-                                       0x00, 0x65, // ID: fieldData
+                                       0x00, 0x65, // ID: FieldData
                                        0x00, 0x04, // Size: 4 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
                                        0x00, 0x04, // Size: 4 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
@@ -71,10 +71,10 @@ func TestReadFields(t *testing.T) {
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
-                                       0x00, 0x65, // ID: fieldData
+                                       0x00, 0x65, // ID: FieldData
                                        0x00, 0x02, // Size: 2 bytes
                                        0x01, 0x02, // Data
                                        0x00, 0x02, // Size: 2 bytes
                                        0x01, 0x02, // Data
-                                       0x00, 0x65, // ID: fieldData
+                                       0x00, 0x65, // ID: FieldData
                                        0x00, 0x04, // Size: 4 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
                                        0x00, 0x04, // Size: 4 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
@@ -87,7 +87,7 @@ func TestReadFields(t *testing.T) {
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
                        args: args{
                                paramCount: []byte{0x00, 0x01},
                                buf: []byte{
-                                       0x00, 0x65, // ID: fieldData
+                                       0x00, 0x65, // ID: FieldData
                                        0x00, 0x02, // Size: 2 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
                                        0x00, 0x02, // Size: 2 bytes
                                        0x01, 0x02, 0x03, // Data
                                },
@@ -163,10 +163,10 @@ func Test_transactionScanner(t *testing.T) {
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
-                                       00, 0x6c, // 108 - fieldTransferSize
+                                       00, 0x6c, // 108 - FieldTransferSize
                                        00, 02,
                                        0x63, 0x3b,
                                        00, 02,
                                        0x63, 0x3b,
-                                       00, 0x6b, // 107 = fieldRefNum
+                                       00, 0x6b, // 107 = FieldRefNum
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                },
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                },
@@ -182,10 +182,10 @@ func Test_transactionScanner(t *testing.T) {
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
-                               00, 0x6c, // 108 - fieldTransferSize
+                               00, 0x6c, // 108 - FieldTransferSize
                                00, 02,
                                0x63, 0x3b,
                                00, 02,
                                0x63, 0x3b,
-                               00, 0x6b, // 107 = fieldRefNum
+                               00, 0x6b, // 107 = FieldRefNum
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
@@ -203,10 +203,10 @@ func Test_transactionScanner(t *testing.T) {
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
-                                       00, 0x6c, // 108 - fieldTransferSize
+                                       00, 0x6c, // 108 - FieldTransferSize
                                        00, 02,
                                        0x63, 0x3b,
                                        00, 02,
                                        0x63, 0x3b,
-                                       00, 0x6b, // 107 = fieldRefNum
+                                       00, 0x6b, // 107 = FieldRefNum
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -223,10 +223,10 @@ func Test_transactionScanner(t *testing.T) {
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
-                               00, 0x6c, // 108 - fieldTransferSize
+                               00, 0x6c, // 108 - FieldTransferSize
                                00, 02,
                                0x63, 0x3b,
                                00, 02,
                                0x63, 0x3b,
-                               00, 0x6b, // 107 = fieldRefNum
+                               00, 0x6b, // 107 = FieldRefNum
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
@@ -244,10 +244,10 @@ func Test_transactionScanner(t *testing.T) {
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
-                                       00, 0x6c, // 108 - fieldTransferSize
+                                       00, 0x6c, // 108 - FieldTransferSize
                                        00, 02,
                                        0x63, 0x3b,
                                        00, 02,
                                        0x63, 0x3b,
-                                       00, 0x6b, // 107 = fieldRefNum
+                                       00, 0x6b, // 107 = FieldRefNum
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                        0,
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                        0,
@@ -258,10 +258,10 @@ func Test_transactionScanner(t *testing.T) {
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
                                        00, 00, 00, 0x10,
                                        00, 00, 00, 0x10,
                                        00, 02,
-                                       00, 0x6c, // 108 - fieldTransferSize
+                                       00, 0x6c, // 108 - FieldTransferSize
                                        00, 02,
                                        0x63, 0x3b,
                                        00, 02,
                                        0x63, 0x3b,
-                                       00, 0x6b, // 107 = fieldRefNum
+                                       00, 0x6b, // 107 = FieldRefNum
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                },
                                        00, 0x04,
                                        00, 0x02, 0x93, 0x47,
                                },
@@ -277,10 +277,10 @@ func Test_transactionScanner(t *testing.T) {
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
                                00, 00, 00, 0x10,
                                00, 00, 00, 0x10,
                                00, 02,
-                               00, 0x6c, // 108 - fieldTransferSize
+                               00, 0x6c, // 108 - FieldTransferSize
                                00, 02,
                                0x63, 0x3b,
                                00, 02,
                                0x63, 0x3b,
-                               00, 0x6b, // 107 = fieldRefNum
+                               00, 0x6b, // 107 = FieldRefNum
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
                                00, 0x04,
                                00, 0x02, 0x93, 0x47,
                        },
index 8b0a8c5607759b198d7e94549b43eddf3ee9a0aa..c005fb438001969d03e3fdbc7c629daa07152ec5 100644 (file)
@@ -1,7 +1,6 @@
 package hotline
 
 import (
 package hotline
 
 import (
-       "bufio"
        "fmt"
        "github.com/gdamore/tcell/v2"
        "github.com/rivo/tview"
        "fmt"
        "github.com/gdamore/tcell/v2"
        "github.com/rivo/tview"
@@ -49,8 +48,8 @@ func NewUI(c *Client) *UI {
                        }
 
                        _ = c.Send(
                        }
 
                        _ = c.Send(
-                               *NewTransaction(tranChatSend, nil,
-                                       NewField(fieldData, []byte(chatInput.GetText())),
+                               *NewTransaction(TranChatSend, nil,
+                                       NewField(FieldData, []byte(chatInput.GetText())),
                                ),
                        )
                        chatInput.SetText("") // clear the input field after chat send
                                ),
                        )
                        chatInput.SetText("") // clear the input field after chat send
@@ -88,7 +87,7 @@ func (ui *UI) showBookmarks() *tview.List {
        list.Box.SetBorder(true).SetTitle("| Bookmarks |")
 
        shortcut := 97 // rune for "a"
        list.Box.SetBorder(true).SetTitle("| Bookmarks |")
 
        shortcut := 97 // rune for "a"
-       for i, srv := range ui.HLClient.pref.Bookmarks {
+       for i, srv := range ui.HLClient.Pref.Bookmarks {
                addr := srv.Addr
                login := srv.Login
                pass := srv.Password
                addr := srv.Addr
                login := srv.Login
                pass := srv.Password
@@ -105,7 +104,7 @@ func (ui *UI) showBookmarks() *tview.List {
 }
 
 func (ui *UI) getTrackerList() *tview.List {
 }
 
 func (ui *UI) getTrackerList() *tview.List {
-       listing, err := GetListing(ui.HLClient.pref.Tracker)
+       listing, err := GetListing(ui.HLClient.Pref.Tracker)
        if err != nil {
                // TODO
        }
        if err != nil {
                // TODO
        }
@@ -137,27 +136,27 @@ func (ui *UI) getTrackerList() *tview.List {
 }
 
 func (ui *UI) renderSettingsForm() *tview.Flex {
 }
 
 func (ui *UI) renderSettingsForm() *tview.Flex {
-       iconStr := strconv.Itoa(ui.HLClient.pref.IconID)
+       iconStr := strconv.Itoa(ui.HLClient.Pref.IconID)
        settingsForm := tview.NewForm()
        settingsForm := tview.NewForm()
-       settingsForm.AddInputField("Your Name", ui.HLClient.pref.Username, 0, nil, nil)
+       settingsForm.AddInputField("Your Name", ui.HLClient.Pref.Username, 0, nil, nil)
        settingsForm.AddInputField("IconID", iconStr, 0, func(idStr string, _ rune) bool {
                _, err := strconv.Atoi(idStr)
                return err == nil
        }, nil)
        settingsForm.AddInputField("IconID", iconStr, 0, func(idStr string, _ rune) bool {
                _, err := strconv.Atoi(idStr)
                return err == nil
        }, nil)
-       settingsForm.AddInputField("Tracker", ui.HLClient.pref.Tracker, 0, nil, nil)
-       settingsForm.AddCheckbox("Enable Terminal Bell", ui.HLClient.pref.EnableBell, nil)
+       settingsForm.AddInputField("Tracker", ui.HLClient.Pref.Tracker, 0, nil, nil)
+       settingsForm.AddCheckbox("Enable Terminal Bell", ui.HLClient.Pref.EnableBell, nil)
        settingsForm.AddButton("Save", func() {
                usernameInput := settingsForm.GetFormItem(0).(*tview.InputField).GetText()
                if len(usernameInput) == 0 {
                        usernameInput = "unnamed"
                }
        settingsForm.AddButton("Save", func() {
                usernameInput := settingsForm.GetFormItem(0).(*tview.InputField).GetText()
                if len(usernameInput) == 0 {
                        usernameInput = "unnamed"
                }
-               ui.HLClient.pref.Username = usernameInput
+               ui.HLClient.Pref.Username = usernameInput
                iconStr = settingsForm.GetFormItem(1).(*tview.InputField).GetText()
                iconStr = settingsForm.GetFormItem(1).(*tview.InputField).GetText()
-               ui.HLClient.pref.IconID, _ = strconv.Atoi(iconStr)
-               ui.HLClient.pref.Tracker = settingsForm.GetFormItem(2).(*tview.InputField).GetText()
-               ui.HLClient.pref.EnableBell = settingsForm.GetFormItem(3).(*tview.Checkbox).IsChecked()
+               ui.HLClient.Pref.IconID, _ = strconv.Atoi(iconStr)
+               ui.HLClient.Pref.Tracker = settingsForm.GetFormItem(2).(*tview.InputField).GetText()
+               ui.HLClient.Pref.EnableBell = settingsForm.GetFormItem(3).(*tview.Checkbox).IsChecked()
 
 
-               out, err := yaml.Marshal(&ui.HLClient.pref)
+               out, err := yaml.Marshal(&ui.HLClient.Pref)
                if err != nil {
                        // TODO: handle err
                }
                if err != nil {
                        // TODO: handle err
                }
@@ -194,47 +193,25 @@ func (ui *UI) joinServer(addr, login, password string) error {
        if len(strings.Split(addr, ":")) == 1 {
                addr += ":5500"
        }
        if len(strings.Split(addr, ":")) == 1 {
                addr += ":5500"
        }
-       if err := ui.HLClient.JoinServer(addr, login, password); err != nil {
+       if err := ui.HLClient.Connect(addr, login, password); err != nil {
                return fmt.Errorf("Error joining server: %v\n", err)
        }
 
        go func() {
                return fmt.Errorf("Error joining server: %v\n", err)
        }
 
        go func() {
-               // Create a new scanner for parsing incoming bytes into transaction tokens
-               scanner := bufio.NewScanner(ui.HLClient.Connection)
-               scanner.Split(transactionScanner)
-
-               // Scan for new transactions and handle them as they come in.
-               for scanner.Scan() {
-                       // Make a new []byte slice and copy the scanner bytes to it.  This is critical to avoid a data race as the
-                       // scanner re-uses the buffer for subsequent scans.
-                       buf := make([]byte, len(scanner.Bytes()))
-                       copy(buf, scanner.Bytes())
-
-                       var t Transaction
-                       _, err := t.Write(buf)
-                       if err != nil {
-                               break
-                       }
-                       if err := ui.HLClient.HandleTransaction(&t); err != nil {
-                               ui.HLClient.Logger.Errorw("Error handling transaction", "err", err)
-                       }
+               if err := ui.HLClient.HandleTransactions(); err != nil {
+                       ui.Pages.SwitchToPage("home")
                }
 
                }
 
-               if scanner.Err() == nil {
-                       loginErrModal := tview.NewModal().
-                               AddButtons([]string{"Ok"}).
-                               SetText("The server connection has closed.").
-                               SetDoneFunc(func(buttonIndex int, buttonLabel string) {
-                                       ui.Pages.SwitchToPage("home")
-                               })
-                       loginErrModal.Box.SetTitle("Server Connection Error")
-
-                       ui.Pages.AddPage("loginErr", loginErrModal, false, true)
-                       ui.App.Draw()
-                       return
-               }
-               ui.Pages.SwitchToPage("home")
+               loginErrModal := tview.NewModal().
+                       AddButtons([]string{"Ok"}).
+                       SetText("The server connection has closed.").
+                       SetDoneFunc(func(buttonIndex int, buttonLabel string) {
+                               ui.Pages.SwitchToPage("home")
+                       })
+               loginErrModal.Box.SetTitle("Server Connection Error")
 
 
+               ui.Pages.AddPage("loginErr", loginErrModal, false, true)
+               ui.App.Draw()
        }()
 
        return nil
        }()
 
        return nil
@@ -253,8 +230,8 @@ func (ui *UI) renderJoinServerForm(name, server, login, password, backPage strin
                        ui.HLClient.Logger.Infow("saving bookmark")
                        // TODO: Implement bookmark saving
 
                        ui.HLClient.Logger.Infow("saving bookmark")
                        // TODO: Implement bookmark saving
 
-                       ui.HLClient.pref.AddBookmark(joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(1).(*tview.InputField).GetText(), joinServerForm.GetFormItem(2).(*tview.InputField).GetText())
-                       out, err := yaml.Marshal(ui.HLClient.pref)
+                       ui.HLClient.Pref.AddBookmark(joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(0).(*tview.InputField).GetText(), joinServerForm.GetFormItem(1).(*tview.InputField).GetText(), joinServerForm.GetFormItem(2).(*tview.InputField).GetText())
+                       out, err := yaml.Marshal(ui.HLClient.Pref)
                        if err != nil {
                                panic(err)
                        }
                        if err != nil {
                                panic(err)
                        }
@@ -263,7 +240,7 @@ func (ui *UI) renderJoinServerForm(name, server, login, password, backPage strin
                        if err != nil {
                                panic(err)
                        }
                        if err != nil {
                                panic(err)
                        }
-                       //              pref := ui.HLClient.pref
+                       //              Pref := ui.HLClient.Pref
                }).
                AddButton("Cancel", func() {
                        ui.Pages.SwitchToPage(backPage)
                }).
                AddButton("Cancel", func() {
                        ui.Pages.SwitchToPage(backPage)
@@ -360,14 +337,14 @@ func (ui *UI) renderServerUI() *tview.Flex {
 
                // List files
                if event.Key() == tcell.KeyCtrlF {
 
                // List files
                if event.Key() == tcell.KeyCtrlF {
-                       if err := ui.HLClient.Send(*NewTransaction(tranGetFileNameList, nil)); err != nil {
+                       if err := ui.HLClient.Send(*NewTransaction(TranGetFileNameList, nil)); err != nil {
                                ui.HLClient.Logger.Errorw("err", "err", err)
                        }
                }
 
                // Show News
                if event.Key() == tcell.KeyCtrlN {
                                ui.HLClient.Logger.Errorw("err", "err", err)
                        }
                }
 
                // Show News
                if event.Key() == tcell.KeyCtrlN {
-                       if err := ui.HLClient.Send(*NewTransaction(tranGetMsgs, nil)); err != nil {
+                       if err := ui.HLClient.Send(*NewTransaction(TranGetMsgs, nil)); err != nil {
                                ui.HLClient.Logger.Errorw("err", "err", err)
                        }
                }
                                ui.HLClient.Logger.Errorw("err", "err", err)
                        }
                }
@@ -399,8 +376,8 @@ func (ui *UI) renderServerUI() *tview.Flex {
                                                return event
                                        }
                                        err := ui.HLClient.Send(
                                                return event
                                        }
                                        err := ui.HLClient.Send(
-                                               *NewTransaction(tranOldPostNews, nil,
-                                                       NewField(fieldData, []byte(newsText)),
+                                               *NewTransaction(TranOldPostNews, nil,
+                                                       NewField(FieldData, []byte(newsText)),
                                                ),
                                        )
                                        if err != nil {
                                                ),
                                        )
                                        if err != nil {
index f6e4592ba9068a7e2b124e3943680681736d5b34..a86aebab66219b7e0acb66611b42cce63efb7dd5 100644 (file)
@@ -12,7 +12,7 @@ const (
        userFLagRefusePChat = 3 // User refuses private chat
 )
 
        userFLagRefusePChat = 3 // User refuses private chat
 )
 
-// fieldOptions flags are sent from v1.5+ clients as part of tranAgreed
+// FieldOptions flags are sent from v1.5+ clients as part of TranAgreed
 const (
        refusePM     = 0 // User has "Refuse private messages" pref set
        refuseChat   = 1 // User has "Refuse private chat" pref set
 const (
        refusePM     = 0 // User has "Refuse private messages" pref set
        refuseChat   = 1 // User has "Refuse private chat" pref set