]> git.r.bdr.sh - rbdr/mobius/commitdiff
Misc cleanup
authorJeff Halter <redacted>
Sat, 28 May 2022 18:35:50 +0000 (11:35 -0700)
committerJeff Halter <redacted>
Sat, 28 May 2022 18:35:50 +0000 (11:35 -0700)
* Removed some unnecessary user of pointers
* Removed dead cruft
* Reorganized code

18 files changed:
cmd/mobius-hotline-server/main.go
hotline/access.go
hotline/client.go
hotline/client_conn.go
hotline/client_conn_test.go
hotline/field.go
hotline/file_store.go
hotline/flattened_file_object.go
hotline/handshake.go [new file with mode: 0644]
hotline/news.go
hotline/server.go
hotline/server_blackbox_test.go
hotline/server_test.go
hotline/tracker.go
hotline/transaction_handlers.go
hotline/transaction_handlers_test.go
hotline/ui.go
hotline/user.go

index cf69ea8ae1f5f2e35b431c5c78a745b38cad4e44..aa1f015ee2aefcbcffd86b7f60e459bcf86390e5 100644 (file)
@@ -44,7 +44,7 @@ func main() {
                logger.Fatalw("Configuration directory not found", "path", configDir)
        }
 
-       hotline.FS = hotline.OSFileStore{}
+       hotline.FS = &hotline.OSFileStore{}
 
        srv, err := hotline.NewServer(*configDir, "", *basePort, logger)
        if err != nil {
index 1cdbeed33e9d04bfd104c932a700f58758c1f840..8d6dd63f75f6399f68f2d3932191e68a6aa1020a 100644 (file)
@@ -28,25 +28,25 @@ const (
        accessOpenUser   = 16
        accessModifyUser = 17
        // accessChangeOwnPass    = 18 // Documented but unused?
-       //accessSendPrivMsg      = 19 // This doesn't do what it seems like it should do. TODO: Investigate
+       // accessSendPrivMsg      = 19 // This doesn't do what it seems like it should do. TODO: Investigate
        accessNewsReadArt    = 20
        accessNewsPostArt    = 21
        accessDisconUser     = 22 // Toggles red user name in user list
        accessCannotBeDiscon = 23
        accessGetClientInfo  = 24
-       //accessUploadAnywhere   = 25
-       //accessAnyName          = 26
-       //accessNoAgreement      = 27
-       //accessSetFileComment   = 28
-       //accessSetFolderComment = 29
-       //accessViewDropBoxes    = 30
+       // accessUploadAnywhere   = 25
+       // accessAnyName          = 26
+       // accessNoAgreement      = 27
+       // accessSetFileComment   = 28
+       // accessSetFolderComment = 29
+       // accessViewDropBoxes    = 30
        accessMakeAlias     = 31
        accessBroadcast     = 32
        accessNewsDeleteArt = 33
        accessNewsCreateCat = 34
-       //accessNewsDeleteCat    = 35
+       // accessNewsDeleteCat    = 35
        accessNewsCreateFldr = 36
-       //accessNewsDeleteFldr   = 37
+       // accessNewsDeleteFldr   = 37
 )
 
 type accessBitmap [8]byte
index 33ec511341878cd7d98c97a64567f48c05f40766..4ca42f38669eef3829ddaf8a804917d1cd108220 100644 (file)
@@ -336,8 +336,8 @@ func handleGetMsgs(c *Client, t *Transaction) (res []Transaction, err error) {
        newsTextView.SetBorder(true).SetTitle("News")
 
        c.UI.Pages.AddPage("news", newsTextView, true, true)
-       //c.UI.Pages.SwitchToPage("news")
-       //c.UI.App.SetFocus(newsTextView)
+       // c.UI.Pages.SwitchToPage("news")
+       // c.UI.App.SetFocus(newsTextView)
        c.UI.App.Draw()
 
        return res, err
@@ -605,10 +605,10 @@ var ServerHandshake = []byte{
 }
 
 func (c *Client) Handshake() error {
-       //Protocol ID   4       ‘TRTP’      0x54 52 54 50
-       //Sub-protocol ID       4               User defined
-       //Version       2       1       Currently 1
-       //Sub-version   2               User defined
+       // Protocol ID  4       ‘TRTP’      0x54 52 54 50
+       // Sub-protocol ID      4               User defined
+       // Version      2       1       Currently 1
+       // Sub-version  2               User defined
        if _, err := c.Connection.Write(ClientHandshake); err != nil {
                return fmt.Errorf("handshake write err: %s", err)
        }
@@ -644,7 +644,7 @@ func (c *Client) Send(t Transaction) error {
        requestNum := binary.BigEndian.Uint16(t.Type)
        tID := binary.BigEndian.Uint32(t.ID)
 
-       //handler := TransactionHandlers[requestNum]
+       // handler := TransactionHandlers[requestNum]
 
        // if transaction is NOT reply, add it to the list to transactions we're expecting a response for
        if t.IsReply == 0 {
index b43a6ff65a371dcca85a169404ae98b5346f5b72..ce9d7f1c320b27c5709ecb163c0f599c5337240c 100644 (file)
@@ -1,9 +1,7 @@
 package hotline
 
 import (
-       "bytes"
        "encoding/binary"
-       "errors"
        "golang.org/x/crypto/bcrypt"
        "math/big"
        "net"
@@ -35,7 +33,7 @@ type ClientConn struct {
        Server     *Server
        Version    *[]byte
        Idle       bool
-       AutoReply  *[]byte
+       AutoReply  []byte
        Transfers  map[int][]*FileTransfer
        Agreed     bool
 }
@@ -54,7 +52,7 @@ func (cc *ClientConn) handleTransaction(transaction *Transaction) error {
 
                        // Validate that required field is present
                        if field.ID == nil {
-                               cc.Server.Logger.Infow(
+                               cc.Server.Logger.Errorw(
                                        "Missing required field",
                                        "Account", cc.Account.Login, "UserName", string(cc.UserName), "RequestType", handler.Name, "FieldID", reqField.ID,
                                )
@@ -176,47 +174,6 @@ func (cc ClientConn) NotifyOthers(t Transaction) {
        }
 }
 
-type handshake struct {
-       Protocol    [4]byte // Must be 0x54525450 TRTP
-       SubProtocol [4]byte
-       Version     [2]byte // Always 1
-       SubVersion  [2]byte
-}
-
-// Handshake
-// After establishing TCP connection, both client and server start the handshake process
-// in order to confirm that each of them comply with requirements of the other.
-// The information provided in this initial data exchange identifies protocols,
-// and their versions, used in the communication. In the case where, after inspection,
-// the capabilities of one of the subjects do not comply with the requirements of the other,
-// the connection is dropped.
-//
-// The following information is sent to the server:
-// Description         Size    Data    Note
-// Protocol ID         4               TRTP    0x54525450
-// Sub-protocol ID     4               HOTL    User defined
-// VERSION                     2               1               Currently 1
-// Sub-version         2               2               User defined
-//
-// The server replies with the following:
-// Description         Size    Data    Note
-// Protocol ID         4               TRTP
-//Error code           4                               Error code returned by the server (0 = no error)
-func Handshake(conn net.Conn, buf []byte) error {
-       var h handshake
-       r := bytes.NewReader(buf)
-       if err := binary.Read(r, binary.BigEndian, &h); err != nil {
-               return err
-       }
-
-       if h.Protocol != [4]byte{0x54, 0x52, 0x54, 0x50} {
-               return errors.New("invalid handshake")
-       }
-
-       _, err := conn.Write([]byte{84, 82, 84, 80, 0, 0, 0, 0})
-       return err
-}
-
 // NewReply returns a reply Transaction with fields for the ClientConn
 func (cc *ClientConn) NewReply(t *Transaction, fields ...Field) Transaction {
        reply := Transaction{
index 2176185876a6a4a10f475df754e31a1b27ed6aaa..da0a2cc1187181d49dd5df8c399d02547845817a 100644 (file)
@@ -17,7 +17,7 @@ func TestClientConn_handleTransaction(t *testing.T) {
                Server     *Server
                Version    *[]byte
                Idle       bool
-               AutoReply  *[]byte
+               AutoReply  []byte
        }
        type args struct {
                transaction *Transaction
index 7955fe3ef3d05135bc1767849937c0d5643a32fd..26012afefcb6e61d17064e5d0d5d5a169c79f348 100644 (file)
@@ -16,7 +16,8 @@ const fieldRefNum = 107
 const fieldTransferSize = 108
 const fieldChatOptions = 109
 const fieldUserAccess = 110
-//const fieldUserAlias = 111 TODO: implement
+
+// const fieldUserAlias = 111 TODO: implement
 const fieldUserFlags = 112
 const fieldOptions = 113
 const fieldChatID = 114
index c1c392905c3704791014653d9937f993114af541..f528c3677ee08f65a4c1f8ca52ac3b88dff49b48 100644 (file)
@@ -14,25 +14,25 @@ type FileStore interface {
        Symlink(oldname, newname string) error
 
        // TODO: implement these
-       //Rename(oldpath string, newpath string) error
-       //RemoveAll(path string) error
+       // Rename(oldpath string, newpath string) error
+       // RemoveAll(path string) error
 }
 
 type OSFileStore struct{}
 
-func (fs OSFileStore) Mkdir(name string, perm os.FileMode) error {
+func (fs *OSFileStore) Mkdir(name string, perm os.FileMode) error {
        return os.Mkdir(name, perm)
 }
 
-func (fs OSFileStore) Stat(name string) (os.FileInfo, error) {
+func (fs *OSFileStore) Stat(name string) (os.FileInfo, error) {
        return os.Stat(name)
 }
 
-func (fs OSFileStore) Open(name string) (*os.File, error) {
+func (fs *OSFileStore) Open(name string) (*os.File, error) {
        return os.Open(name)
 }
 
-func (fs OSFileStore) Symlink(oldname, newname string) error {
+func (fs *OSFileStore) Symlink(oldname, newname string) error {
        return os.Symlink(oldname, newname)
 }
 
@@ -40,12 +40,12 @@ type MockFileStore struct {
        mock.Mock
 }
 
-func (mfs MockFileStore) Mkdir(name string, perm os.FileMode) error {
+func (mfs *MockFileStore) Mkdir(name string, perm os.FileMode) error {
        args := mfs.Called(name, perm)
        return args.Error(0)
 }
 
-func (mfs MockFileStore) Stat(name string) (os.FileInfo, error) {
+func (mfs *MockFileStore) Stat(name string) (os.FileInfo, error) {
        args := mfs.Called(name)
        if args.Get(0) == nil {
                return nil, args.Error(1)
@@ -54,12 +54,12 @@ func (mfs MockFileStore) Stat(name string) (os.FileInfo, error) {
        return args.Get(0).(os.FileInfo), args.Error(1)
 }
 
-func (mfs MockFileStore) Open(name string) (*os.File, error) {
+func (mfs *MockFileStore) Open(name string) (*os.File, error) {
        args := mfs.Called(name)
        return args.Get(0).(*os.File), args.Error(1)
 }
 
-func (mfs MockFileStore) Symlink(oldname, newname string) error {
+func (mfs *MockFileStore) Symlink(oldname, newname string) error {
        args := mfs.Called(oldname, newname)
        return args.Error(0)
 }
index 2cafbc91474946983e22073860f163966dd870d0..fae8ab8051f6588288f9b81962d95937cb4dcece 100644 (file)
@@ -77,7 +77,7 @@ func NewFlatFileInformationFork(fileName string, modifyTime []byte) FlatFileInfo
 func (ffif FlatFileInformationFork) DataSize() []byte {
        size := make([]byte, 4)
 
-       //TODO: Can I do math directly on two byte slices?
+       // TODO: Can I do math directly on two byte slices?
        dataSize := len(ffif.Name) + len(ffif.Comment) + 74
 
        binary.BigEndian.PutUint32(size, uint32(dataSize))
@@ -124,8 +124,8 @@ func ReadFlattenedFileObject(bytes []byte) flattenedFileObject {
 
        comment := bytes[commentStartPos:commentEndPos]
 
-       //dataSizeField := bytes[nameEnd+14+commentLen : nameEnd+18+commentLen]
-       //dataSize := binary.BigEndian.Uint32(dataSizeField)
+       // dataSizeField := bytes[nameEnd+14+commentLen : nameEnd+18+commentLen]
+       // dataSize := binary.BigEndian.Uint32(dataSizeField)
 
        ffo := flattenedFileObject{
                FlatFileHeader: NewFlatFileHeader(),
diff --git a/hotline/handshake.go b/hotline/handshake.go
new file mode 100644 (file)
index 0000000..66bf643
--- /dev/null
@@ -0,0 +1,49 @@
+package hotline
+
+import (
+       "bytes"
+       "encoding/binary"
+       "errors"
+       "net"
+)
+
+type handshake struct {
+       Protocol    [4]byte // Must be 0x54525450 TRTP
+       SubProtocol [4]byte
+       Version     [2]byte // Always 1
+       SubVersion  [2]byte
+}
+
+// Handshake
+// After establishing TCP connection, both client and server start the handshake process
+// in order to confirm that each of them comply with requirements of the other.
+// The information provided in this initial data exchange identifies protocols,
+// and their versions, used in the communication. In the case where, after inspection,
+// the capabilities of one of the subjects do not comply with the requirements of the other,
+// the connection is dropped.
+//
+// The following information is sent to the server:
+// Description         Size    Data    Note
+// Protocol ID         4               TRTP    0x54525450
+// Sub-protocol ID     4               HOTL    User defined
+// VERSION                     2               1               Currently 1
+// Sub-version         2               2               User defined
+//
+// The server replies with the following:
+// Description         Size    Data    Note
+// Protocol ID         4               TRTP
+// Error code          4                               Error code returned by the server (0 = no error)
+func Handshake(conn net.Conn, buf []byte) error {
+       var h handshake
+       r := bytes.NewReader(buf)
+       if err := binary.Read(r, binary.BigEndian, &h); err != nil {
+               return err
+       }
+
+       if h.Protocol != [4]byte{0x54, 0x52, 0x54, 0x50} {
+               return errors.New("invalid handshake")
+       }
+
+       _, err := conn.Write([]byte{84, 82, 84, 80, 0, 0, 0, 0})
+       return err
+}
index a6b8372795c7ff1917f0d0bb3a7593076cbe04ad..77c66966f9ddf0dde81e15331b0cec87fdae2bb1 100644 (file)
@@ -12,7 +12,7 @@ type ThreadedNews struct {
 }
 
 type NewsCategoryListData15 struct {
-       Type     []byte `yaml:"Type"` //Size 2 ; Bundle (2) or category (3)
+       Type     []byte `yaml:"Type"` // Size 2 ; Bundle (2) or category (3)
        Count    []byte // Article or SubCategory count Size 2
        NameSize byte
        Name     string                            `yaml:"Name"`     //
@@ -64,11 +64,11 @@ func (newscat *NewsCategoryListData15) GetNewsArtListData() NewsArtListData {
 type NewsArtData struct {
        Title         string `yaml:"Title"`
        Poster        string `yaml:"Poster"`
-       Date          []byte `yaml:"Date"`             //size 8
-       PrevArt       []byte `yaml:"PrevArt"`          //size 4
-       NextArt       []byte `yaml:"NextArt"`          //size 4
-       ParentArt     []byte `yaml:"ParentArt"`        //size 4
-       FirstChildArt []byte `yaml:"FirstChildArtArt"` //size 4
+       Date          []byte `yaml:"Date"`             // size 8
+       PrevArt       []byte `yaml:"PrevArt"`          // size 4
+       NextArt       []byte `yaml:"NextArt"`          // size 4
+       ParentArt     []byte `yaml:"ParentArt"`        // size 4
+       FirstChildArt []byte `yaml:"FirstChildArtArt"` // size 4
        DataFlav      []byte `yaml:"DataFlav"`         // "text/plain"
        Data          string `yaml:"Data"`
 }
@@ -202,27 +202,6 @@ func (newscat *NewsCategoryListData15) nameLen() []byte {
        return []byte{uint8(len(newscat.Name))}
 }
 
-//type NewsPath struct {
-//     Paths []string
-//}
-//
-//func (np *NewsPath) Payload() []byte {
-//     var out []byte
-//
-//     count := make([]byte, 2)
-//     binary.BigEndian.PutUint16(count, uint16(len(np.Paths)))
-//
-//     out = append(out, count...)
-//     for _, p := range np.Paths {
-//             pLen := byte(len(p))
-//             out = append(out, []byte{0, 0}...) // what is this?
-//             out = append(out, pLen)
-//             out = append(out, []byte(p)...)
-//     }
-//
-//     return out
-//}
-
 func ReadNewsPath(newsPath []byte) []string {
        if len(newsPath) == 0 {
                return []string{}
index c5a29ba9ea19173b3499be0ab3e1ade4d7e49f95..1da2859ba479773c65d3176ab3c87f41e34459b3 100644 (file)
@@ -8,7 +8,6 @@ import (
        "go.uber.org/zap"
        "io"
        "io/ioutil"
-       "log"
        "math/big"
        "math/rand"
        "net"
@@ -21,7 +20,6 @@ import (
        "sync"
        "time"
 
-       "golang.org/x/crypto/bcrypt"
        "gopkg.in/yaml.v2"
 )
 
@@ -50,8 +48,8 @@ type Server struct {
        APIListener  net.Listener
        FileListener net.Listener
 
-       newsReader io.Reader
-       newsWriter io.WriteCloser
+       // newsReader io.Reader
+       // newsWriter io.WriteCloser
 
        outbox chan Transaction
 
@@ -327,7 +325,7 @@ func (s *Server) NewClientConn(conn net.Conn) *ClientConn {
                Connection: conn,
                Server:     s,
                Version:    &[]byte{},
-               AutoReply:  &[]byte{},
+               AutoReply:  []byte{},
                Transfers:  make(map[int][]*FileTransfer),
                Agreed:     false,
        }
@@ -376,7 +374,7 @@ func (s *Server) connectedUsers() []Field {
 
        var connectedUsers []Field
        for _, c := range sortedClients(s.Clients) {
-               if c.Agreed == false {
+               if !c.Agreed {
                        continue
                }
                user := User{
@@ -577,21 +575,6 @@ func (s *Server) handleNewConnection(conn net.Conn) error {
        }
 }
 
-func hashAndSalt(pwd []byte) string {
-       // Use GenerateFromPassword to hash & salt pwd.
-       // MinCost is just an integer constant provided by the bcrypt
-       // package along with DefaultCost & MaxCost.
-       // The cost can be any value you want provided it isn't lower
-       // than the MinCost (4)
-       hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
-       if err != nil {
-               log.Println(err)
-       }
-       // GenerateFromPassword returns a byte slice so we need to
-       // convert the bytes to a string and return it
-       return string(hash)
-}
-
 // NewTransactionRef generates a random ID for the file transfer.  The Hotline client includes this ID
 // in the file transfer request payload, and the file transfer server will use it to map the request
 // to a transfer
@@ -796,7 +779,7 @@ func (s *Server) TransferFile(conn net.Conn) error {
                        }
 
                        // Read the client's Next Action request
-                       //TODO: Remove hardcoded behavior and switch behaviors based on the next action send
+                       // TODO: Remove hardcoded behavior and switch behaviors based on the next action send
                        if _, err := conn.Read(readBuffer); err != nil {
                                return err
                        }
@@ -848,7 +831,7 @@ func (s *Server) TransferFile(conn net.Conn) error {
                                bytesRead, err := file.Read(sendBuffer)
                                if err == io.EOF {
                                        // Read the client's Next Action request
-                                       //TODO: Remove hardcoded behavior and switch behaviors based on the next action send
+                                       // TODO: Remove hardcoded behavior and switch behaviors based on the next action send
                                        if _, err := conn.Read(readBuffer); err != nil {
                                                s.Logger.Errorf("error reading next action: %v", err)
                                                return err
index 601d745e40a215a15c8ea99567b07d0ea6f0ddb4..ee5f76b04d68ec43ef08b0c46e6f5dd4444aa992 100644 (file)
@@ -66,7 +66,7 @@ func NewTestLogger() *zap.SugaredLogger {
 func StartTestServer() (*Server, context.Context, context.CancelFunc) {
        ctx, cancelRoot := context.WithCancel(context.Background())
 
-       FS = OSFileStore{}
+       FS = &OSFileStore{}
 
        srv, err := NewServer("test/config/", "localhost", 0, NewTestLogger())
        if err != nil {
@@ -84,7 +84,7 @@ func StartTestServer() (*Server, context.Context, context.CancelFunc) {
 }
 
 func TestHandshake(t *testing.T) {
-       mfs := MockFileStore{}
+       mfs := &MockFileStore{}
        fh, _ := os.Open("./test/config/Agreement.txt")
        mfs.On("Open", "/test/config/Agreement.txt").Return(fh, nil)
        fh, _ = os.Open("./test/config/config.yaml")
@@ -115,7 +115,7 @@ func TestHandshake(t *testing.T) {
 
 }
 
-//func TestLogin(t *testing.T) {
+// func TestLogin(t *testing.T) {
 //
 //     tests := []struct {
 //             name   string
@@ -131,13 +131,13 @@ func TestHandshake(t *testing.T) {
 //
 //             })
 //     }
-//}
+// }
 
 func TestNewUser(t *testing.T) {
        srv, _, _ := StartTestServer()
 
        tests := []testCase{
-               //{
+               // {
                //      name: "a valid new account",
                //      mockHandler: func() mockClientHandler {
                //              mh := mockClientHandler{}
@@ -180,8 +180,8 @@ func TestNewUser(t *testing.T) {
                //      want: &Transaction{
                //              Fields: []Field{},
                //      },
-               //},
-               //{
+               // },
+               // {
                //      name: "a newUser request from a user without the required access",
                //      mockHandler: func() *mockClientHandler {
                //              mh := mockClientHandler{}
@@ -211,8 +211,8 @@ func TestNewUser(t *testing.T) {
                //              NewField(fieldUserPassword, []byte(NegatedUserString([]byte("testPw")))),
                //              NewField(fieldUserAccess, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
                //      ),
-               //},
-               //{
+               // },
+               // {
                //      name: "when user does not have required permission",
                //      mockHandler: func() map[int]*mockClientHandler {
                //              mockHandlers := make(map[int]*mockClientHandler)
@@ -251,9 +251,9 @@ func TestNewUser(t *testing.T) {
                //              NewField(fieldUserPassword, []byte(NegatedUserString([]byte("testPw")))),
                //              NewField(fieldUserAccess, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
                //      ),
-               //},
+               // },
 
-               //{
+               // {
                //      name: "a request to create a user that already exists",
                //      setup: func() {
                //
@@ -279,7 +279,7 @@ func TestNewUser(t *testing.T) {
                //                      NewField(fieldError, []byte("Cannot create account guest because there is already an account with that login.")),
                //              },
                //      },
-               //},
+               // },
        }
 
        for _, test := range tests {
@@ -301,7 +301,7 @@ func TestNewUser(t *testing.T) {
                        // send test case request
                        _ = c.Send(*test.request)
 
-                       //time.Sleep(1 * time.Second)
+                       // time.Sleep(1 * time.Second)
                        // ===
 
                        transactions, _ := readN(c.Connection, 1)
@@ -320,6 +320,7 @@ func TestNewUser(t *testing.T) {
        }
 }
 
+// tranAssertEqual compares equality of transactions slices after stripping out the random ID
 func tranAssertEqual(t *testing.T, tran1, tran2 []Transaction) bool {
        var newT1 []Transaction
        var newT2 []Transaction
index c69177f91d4ef4ceeccdf16c8befa6ddf8652a48..5937adc11666cb3c4947f742a80ca801a7ac4013 100644 (file)
@@ -1,7 +1,7 @@
 package hotline
 
 //
-//import (
+// import (
 //     "bytes"
 //     "fmt"
 //     "github.com/google/go-cmp/cmp"
@@ -11,18 +11,18 @@ package hotline
 //     "strings"
 //     "sync"
 //     "testing"
-//)
+// )
 //
-//type transactionTest struct {
+// type transactionTest struct {
 //     description string      // Human understandable description
 //     account     Account     // Account struct for a user that will test transaction will execute under
 //     request     Transaction // transaction that will be sent by the client to the server
 //     want        Transaction // transaction that the client expects to receive in response
 //     setup       func()      // Optional setup required for the test scenario
 //     teardown    func()      // Optional teardown for test scenario
-//}
+// }
 //
-//func (tt *transactionTest) Setup(srv *Server) error {
+// func (tt *transactionTest) Setup(srv *Server) error {
 //     if err := srv.NewUser(tt.account.Login, tt.account.Name, NegatedUserString([]byte(tt.account.Password)), tt.account.Access); err != nil {
 //             return err
 //     }
@@ -32,9 +32,9 @@ package hotline
 //     }
 //
 //     return nil
-//}
+// }
 //
-//func (tt *transactionTest) Teardown(srv *Server) error {
+// func (tt *transactionTest) Teardown(srv *Server) error {
 //     if err := srv.DeleteUser(tt.account.Login); err != nil {
 //             return err
 //     }
@@ -44,10 +44,10 @@ package hotline
 //     }
 //
 //     return nil
-//}
+// }
 //
-//// StartTestServer
-//func StartTestServer() (srv *Server, lnPort int) {
+// // StartTestServer
+// func StartTestServer() (srv *Server, lnPort int) {
 //     hotlineServer, _ := NewServer("test/config/")
 //     ln, err := net.Listen("tcp", ":0")
 //
@@ -61,9 +61,9 @@ package hotline
 //             }
 //     }()
 //     return hotlineServer, ln.Addr().(*net.TCPAddr).Port
-//}
+// }
 //
-//func StartTestClient(serverPort int, login, passwd string) (*Client, error) {
+// func StartTestClient(serverPort int, login, passwd string) (*Client, error) {
 //     c := NewClient("")
 //
 //     err := c.JoinServer(fmt.Sprintf(":%v", serverPort), login, passwd)
@@ -72,9 +72,9 @@ package hotline
 //     }
 //
 //     return c, nil
-//}
+// }
 //
-//func StartTestServerWithClients(clientCount int) ([]*Client, int) {
+// func StartTestServerWithClients(clientCount int) ([]*Client, int) {
 //     _, serverPort := StartTestServer()
 //
 //     var clients []*Client
@@ -88,48 +88,48 @@ package hotline
 //     clients[0].ReadN(2)
 //
 //     return clients, serverPort
-//}
+// }
 //
 
-////func TestHandleTranAgreed(t *testing.T) {
-////   clients, _ := StartTestServerWithClients(2)
-////
-////   chatMsg := "Test Chat"
-////
-////   // Assert that both clients should receive the user join notification
-////   var wg sync.WaitGroup
-////   for _, client := range clients {
-////           wg.Add(1)
-////           go func(wg *sync.WaitGroup, c *Client) {
-////                   defer wg.Done()
-////
-////                   receivedMsg := c.ReadTransactions()[0].GetField(fieldData).Data
-////
-////                   want := []byte(fmt.Sprintf("test: %s\r", chatMsg))
-////                   if bytes.Compare(receivedMsg, want) != 0 {
-////                           t.Errorf("%q, want %q", receivedMsg, want)
-////                   }
-////           }(&wg, client)
-////   }
-////
-////   trans := clients[1].ReadTransactions()
-////   spew.Dump(trans)
-////
-////   // Send the agreement
-////   clients[1].Connection.Write(
-////           NewTransaction(
-////                   tranAgreed, 0,
-////                   []Field{
-////                           NewField(fieldUserName, []byte("testUser")),
-////                           NewField(fieldUserIconID, []byte{0x00,0x07}),
-////                   },
-////           ).Payload(),
-////   )
-////
-////   wg.Wait()
-////}
-//
-//func TestChatSend(t *testing.T) {
+// //func TestHandleTranAgreed(t *testing.T) {
+// //  clients, _ := StartTestServerWithClients(2)
+// //
+// //  chatMsg := "Test Chat"
+// //
+// //  // Assert that both clients should receive the user join notification
+// //  var wg sync.WaitGroup
+// //  for _, client := range clients {
+// //          wg.Add(1)
+// //          go func(wg *sync.WaitGroup, c *Client) {
+// //                  defer wg.Done()
+// //
+// //                  receivedMsg := c.ReadTransactions()[0].GetField(fieldData).Data
+// //
+// //                  want := []byte(fmt.Sprintf("test: %s\r", chatMsg))
+// //                  if bytes.Compare(receivedMsg, want) != 0 {
+// //                          t.Errorf("%q, want %q", receivedMsg, want)
+// //                  }
+// //          }(&wg, client)
+// //  }
+// //
+// //  trans := clients[1].ReadTransactions()
+// //  spew.Dump(trans)
+// //
+// //  // Send the agreement
+// //  clients[1].Connection.Write(
+// //          NewTransaction(
+// //                  tranAgreed, 0,
+// //                  []Field{
+// //                          NewField(fieldUserName, []byte("testUser")),
+// //                          NewField(fieldUserIconID, []byte{0x00,0x07}),
+// //                  },
+// //          ).Payload(),
+// //  )
+// //
+// //  wg.Wait()
+// //}
+//
+// func TestChatSend(t *testing.T) {
 //     //srvPort := StartTestServer()
 //     //
 //     //senderClient := NewClient("senderClient")
@@ -169,9 +169,9 @@ package hotline
 //     )
 //
 //     wg.Wait()
-//}
+// }
 //
-//func TestSetClientUserInfo(t *testing.T) {
+// func TestSetClientUserInfo(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //
 //     newIcon := []byte{0x00, 0x01}
@@ -208,11 +208,11 @@ package hotline
 //     }
 //
 //     wg.Wait()
-//}
+// }
 //
-//// TestSendInstantMsg tests that client A can send an instant message to client B
-////
-//func TestSendInstantMsg(t *testing.T) {
+// // TestSendInstantMsg tests that client A can send an instant message to client B
+// //
+// func TestSendInstantMsg(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //
 //     instantMsg := "Test IM"
@@ -258,9 +258,9 @@ package hotline
 //     }
 //
 //     wg.Wait()
-//}
+// }
 //
-//func TestOldPostNews(t *testing.T) {
+// func TestOldPostNews(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //
 //     newsPost := "Test News Post"
@@ -287,35 +287,35 @@ package hotline
 //     )
 //
 //     wg.Wait()
-//}
-//
-//// TODO: Fixme
-////func TestGetFileNameList(t *testing.T) {
-////   clients, _ := StartTestServerWithClients(2)
-////
-////   clients[0].Connection.Write(
-////           NewTransaction(
-////                   tranGetFileNameList, 0,
-////                   []Field{},
-////           ).Payload(),
-////   )
-////
-////   ts := clients[0].ReadTransactions()
-////   testfileSit := ReadFileNameWithInfo(ts[0].Fields[1].Data)
-////
-////   want := "testfile.sit"
-////   got := testfileSit.Name
-////   diff := cmp.Diff(want, got)
-////   if diff != "" {
-////           t.Fatalf(diff)
-////   }
-////   if testfileSit.Name != "testfile.sit" {
-////           t.Errorf("news post missing")
-////           t.Errorf("%q, want %q", testfileSit.Name, "testfile.sit")
-////   }
-////}
-//
-//func TestNewsCategoryList(t *testing.T) {
+// }
+//
+// // TODO: Fixme
+// //func TestGetFileNameList(t *testing.T) {
+// //  clients, _ := StartTestServerWithClients(2)
+// //
+// //  clients[0].Connection.Write(
+// //          NewTransaction(
+// //                  tranGetFileNameList, 0,
+// //                  []Field{},
+// //          ).Payload(),
+// //  )
+// //
+// //  ts := clients[0].ReadTransactions()
+// //  testfileSit := ReadFileNameWithInfo(ts[0].Fields[1].Data)
+// //
+// //  want := "testfile.sit"
+// //  got := testfileSit.Name
+// //  diff := cmp.Diff(want, got)
+// //  if diff != "" {
+// //          t.Fatalf(diff)
+// //  }
+// //  if testfileSit.Name != "testfile.sit" {
+// //          t.Errorf("news post missing")
+// //          t.Errorf("%q, want %q", testfileSit.Name, "testfile.sit")
+// //  }
+// //}
+//
+// func TestNewsCategoryList(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //     client := clients[0]
 //
@@ -344,9 +344,9 @@ package hotline
 //     if diff != "" {
 //             t.Fatalf(diff)
 //     }
-//}
+// }
 //
-//func TestNestedNewsCategoryList(t *testing.T) {
+// func TestNestedNewsCategoryList(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //     client := clients[0]
 //     newsPath := NewsPath{
@@ -381,9 +381,9 @@ package hotline
 //     if diff != "" {
 //             t.Fatalf(diff)
 //     }
-//}
+// }
 //
-//func TestFileDownload(t *testing.T) {
+// func TestFileDownload(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //     client := clients[0]
 //
@@ -436,9 +436,9 @@ package hotline
 //                     t.Errorf("TestFileDownload: fieldTransferSize: %s: got %#v, want %#v", test.fileName, got, test.want.transferSize)
 //             }
 //     }
-//}
+// }
 //
-//func TestFileUpload(t *testing.T) {
+// func TestFileUpload(t *testing.T) {
 //     clients, _ := StartTestServerWithClients(2)
 //     client := clients[0]
 //
@@ -479,10 +479,10 @@ package hotline
 //                     }
 //             }
 //     }
-//}
+// }
 //
-//// TODO: Make canonical
-//func TestNewUser(t *testing.T) {
+// // TODO: Make canonical
+// func TestNewUser(t *testing.T) {
 //     srv, port := StartTestServer()
 //
 //     var tests = []struct {
@@ -604,9 +604,9 @@ package hotline
 //                     test.teardown()
 //             }
 //     }
-//}
+// }
 //
-//func TestDeleteUser(t *testing.T) {
+// func TestDeleteUser(t *testing.T) {
 //     srv, port := StartTestServer()
 //
 //     var tests = []transactionTest{
@@ -676,9 +676,9 @@ package hotline
 //
 //             test.Teardown(srv)
 //     }
-//}
+// }
 //
-//func TestDeleteFile(t *testing.T) {
+// func TestDeleteFile(t *testing.T) {
 //     srv, port := StartTestServer()
 //
 //     var tests = []transactionTest{
@@ -769,9 +769,9 @@ package hotline
 //
 //             test.Teardown(srv)
 //     }
-//}
+// }
 //
-//func Test_authorize(t *testing.T) {
+// func Test_authorize(t *testing.T) {
 //     accessBitmap := big.NewInt(int64(0))
 //     accessBitmap.SetBit(accessBitmap, accessCreateFolder, 1)
 //     fmt.Printf("%v %b %x\n", accessBitmap, accessBitmap, accessBitmap)
@@ -802,4 +802,4 @@ package hotline
 //                     }
 //             })
 //     }
-//}
+// }
index 4ee192a4ae398f4b1479cc81f88907bde4f8e48a..0825fc7e7cabfe6e57a19b65474fd18b010bfa2b 100644 (file)
@@ -49,9 +49,6 @@ func register(tracker string, tr TrackerRegistration) error {
        return nil
 }
 
-type ServerListing struct {
-}
-
 const trackerTimeout = 5 * time.Second
 
 // All string values use 8-bit ASCII character set encoding.
@@ -67,10 +64,10 @@ type TrackerHeader struct {
        Version  [2]byte // Old protocol (1) or new (2)
 }
 
-//Message type 2       1       Sending list of servers
-//Message data size    2               Remaining size of this request
-//Number of servers    2               Number of servers in the server list
-//Number of servers    2               Same as previous field
+// Message type        2       1       Sending list of servers
+// Message data size   2               Remaining size of this request
+// Number of servers   2               Number of servers in the server list
+// Number of servers   2               Same as previous field
 type ServerInfoHeader struct {
        MsgType     [2]byte // always has value of 1
        MsgDataSize [2]byte // Remaining size of request
@@ -177,25 +174,6 @@ func (s *ServerRecord) Read(b []byte) (n int, err error) {
        return 12 + nameLen + int(s.DescriptionSize), nil
 }
 
-//
-//func (s *ServerRecord) UnmarshalBinary(b []byte) (err error) {
-//     r := bytes.NewReader(b[:10])
-//     if err := binary.Read(r, binary.BigEndian, s); err != nil {
-//             return err
-//     }
-//
-//     copy(s.IPAddr[:], b[0:4])
-//     s.Port = b[4:6]
-//     s.NumUsers = b[6:8]
-//     s.NameSize = b[10]
-//     nameLen := int(b[10])
-//     s.Name = b[11 : 11+nameLen]
-//     s.DescriptionSize = b[11+nameLen]
-//     s.Description = b[12+nameLen : 12+nameLen+int(s.DescriptionSize)]
-//
-//     return nil
-//}
-
 func (s *ServerRecord) PortInt() int {
        data := binary.BigEndian.Uint16(s.Port[:])
        return int(data)
index ade846e6d3d283a3149cfeb06fe7980263eb1309..91a4c0dbe015e50632e008bd553aa51eba6bf812 100644 (file)
@@ -237,8 +237,8 @@ var TransactionHandlers = map[uint16]TransactionType{
        },
        tranSendInstantMsg: {
                Access: accessAlwaysAllow,
-               //Access: accessSendPrivMsg,
-               //DenyMsg: "You are not allowed to send private messages",
+               // Access: accessSendPrivMsg,
+               // DenyMsg: "You are not allowed to send private messages",
                Name:    "tranSendInstantMsg",
                Handler: HandleSendInstantMsg,
                RequiredFields: []requiredField{
@@ -357,13 +357,13 @@ func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err erro
 //     101     Data    Optional
 //     214     Quoting message Optional
 //
-//Fields used in the reply:
+// Fields used in the reply:
 // None
 func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
        msg := t.GetField(fieldData)
        ID := t.GetField(fieldUserID)
        // TODO: Implement reply quoting
-       //options := transaction.GetField(hotline.fieldOptions)
+       // options := transaction.GetField(hotline.fieldOptions)
 
        res = append(res,
                *NewTransaction(
@@ -377,23 +377,18 @@ func HandleSendInstantMsg(cc *ClientConn, t *Transaction) (res []Transaction, er
        )
        id, _ := byteToInt(ID.Data)
 
-       //keys := make([]uint16, 0, len(cc.Server.Clients))
-       //for k := range cc.Server.Clients {
-       //      keys = append(keys, k)
-       //}
-
        otherClient := cc.Server.Clients[uint16(id)]
        if otherClient == nil {
                return res, errors.New("ohno")
        }
 
        // Respond with auto reply if other client has it enabled
-       if len(*otherClient.AutoReply) > 0 {
+       if len(otherClient.AutoReply) > 0 {
                res = append(res,
                        *NewTransaction(
                                tranServerMsg,
                                cc.ID,
-                               NewField(fieldData, *otherClient.AutoReply),
+                               NewField(fieldData, otherClient.AutoReply),
                                NewField(fieldUserName, otherClient.UserName),
                                NewField(fieldUserID, *otherClient.ID),
                                NewField(fieldOptions, []byte{0, 1}),
@@ -450,7 +445,7 @@ func HandleSetFileInfo(cc *ClientConn, t *Transaction) (res []Transaction, err e
                return nil, err
        }
 
-       //fileComment := t.GetField(fieldFileComment).Data
+       // fileComment := t.GetField(fieldFileComment).Data
        fileNewName := t.GetField(fieldFileNewName).Data
 
        if fileNewName != nil {
@@ -662,8 +657,8 @@ func HandleSetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error
 }
 
 func HandleGetUser(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
-       userLogin := string(t.GetField(fieldUserLogin).Data)
-       account := cc.Server.Accounts[userLogin]
+       // userLogin := string(t.GetField(fieldUserLogin).Data)
+       account := cc.Server.Accounts[string(t.GetField(fieldUserLogin).Data)]
        if account == nil {
                errorT := cc.NewErrReply(t, "Account does not exist.")
                res = append(res, errorT)
@@ -854,9 +849,9 @@ func HandleTranAgreed(cc *ClientConn, t *Transaction) (res []Transaction, err er
 
        // Check auto response
        if optBitmap.Bit(autoResponse) == 1 {
-               *cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
+               cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
        } else {
-               *cc.AutoReply = []byte{}
+               cc.AutoReply = []byte{}
        }
 
        _, _ = cc.notifyNewUserHasJoined()
@@ -1286,6 +1281,9 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
        }
 
        fullFilePath, err := readPath(cc.Server.Config.FileRoot, t.GetField(fieldFilePath).Data, t.GetField(fieldFileName).Data)
+       if err != nil {
+               return res, err
+       }
 
        transferSize, err := CalcTotalSize(fullFilePath)
        if err != nil {
@@ -1385,9 +1383,9 @@ func HandleSetClientUserInfo(cc *ClientConn, t *Transaction) (res []Transaction,
 
                // Check auto response
                if optBitmap.Bit(autoResponse) == 1 {
-                       *cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
+                       cc.AutoReply = t.GetField(fieldAutomaticResponse).Data
                } else {
-                       *cc.AutoReply = []byte{}
+                       cc.AutoReply = []byte{}
                }
        }
 
index a83f4cca48a9c2cdb7d269be699fb3f0e0a141e6..5ffe45c1f37b3c7a52ebc8b835e91a9313777271 100644 (file)
@@ -579,7 +579,7 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
                                mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
                                FS = mfs
@@ -613,7 +613,7 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
                                mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
                                FS = mfs
@@ -650,7 +650,7 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
                                mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
                                FS = mfs
@@ -675,7 +675,7 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
                                mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
                                FS = mfs
@@ -717,7 +717,7 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
                                mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
                                FS = mfs
@@ -851,9 +851,9 @@ func TestHandleUploadFile(t *testing.T) {
                                t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
                                return
                        }
-                       if !tranAssertEqual(t, tt.wantRes, gotRes) {
-                               t.Errorf("HandleUploadFile() gotRes = %v, want %v", gotRes, tt.wantRes)
-                       }
+
+                       tranAssertEqual(t, tt.wantRes, gotRes)
+
                })
        }
 }
@@ -873,7 +873,7 @@ func TestHandleMakeAlias(t *testing.T) {
                {
                        name: "with valid input and required permissions",
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                path, _ := os.Getwd()
                                mfs.On(
                                        "Symlink",
@@ -924,7 +924,7 @@ func TestHandleMakeAlias(t *testing.T) {
                {
                        name: "when symlink returns an error",
                        setup: func() {
-                               mfs := MockFileStore{}
+                               mfs := &MockFileStore{}
                                path, _ := os.Getwd()
                                mfs.On(
                                        "Symlink",
index d0fd6c04a999866fffc0d7743bd4f4967650e099..79cb5e640909e5c67d96f211ced7e06e94c0e7e7 100644 (file)
@@ -231,7 +231,7 @@ func (ui *UI) renderJoinServerForm(name, server, login, password, backPage strin
        joinServerForm.
                //      AddInputField("Name", server, 0, func(textToCheck string, lastChar rune) bool {
                //      return false
-               //}, nil).
+               // }, nil).
                AddInputField("Server", server, 0, nil, nil).
                AddInputField("Login", login, 0, nil, nil).
                AddPasswordField("Password", password, 0, '*', nil).
@@ -370,7 +370,7 @@ func (ui *UI) renderServerUI() *tview.Flex {
 
                        newsPostForm := tview.NewForm().
                                SetButtonsAlign(tview.AlignRight).
-                               //AddButton("Cancel", nil). // TODO: implement cancel button behavior
+                               // AddButton("Cancel", nil). // TODO: implement cancel button behavior
                                AddButton("Send", nil)
                        newsPostForm.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
                                switch event.Key() {
@@ -438,7 +438,7 @@ func (ui *UI) renderServerUI() *tview.Flex {
                                        SetDirection(tview.FlexRow).
                                        AddItem(nil, 0, 1, false).
                                        AddItem(newsFlex, 15, 1, true).
-                                       //AddItem(newsPostForm, 3, 0, false).
+                                       // AddItem(newsPostForm, 3, 0, false).
                                        AddItem(nil, 0, 1, false), 40, 1, false).
                                AddItem(nil, 0, 1, false)
 
index 5d09b2d449e069fc0f9ffaa296e6567ccd510248..00fe98c8d1dc33355d7bb4562eb1053ae1cd5748 100644 (file)
@@ -2,6 +2,8 @@ package hotline
 
 import (
        "encoding/binary"
+       "golang.org/x/crypto/bcrypt"
+       "log"
 )
 
 // User flags are stored as a 2 byte bitmap with the following values:
@@ -68,3 +70,18 @@ func negateString(clearText []byte) []byte {
        }
        return obfuText
 }
+
+func hashAndSalt(pwd []byte) string {
+       // Use GenerateFromPassword to hash & salt pwd.
+       // MinCost is just an integer constant provided by the bcrypt
+       // package along with DefaultCost & MaxCost.
+       // The cost can be any value you want provided it isn't lower
+       // than the MinCost (4)
+       hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
+       if err != nil {
+               log.Println(err)
+       }
+       // GenerateFromPassword returns a byte slice so we need to
+       // convert the bytes to a string and return it
+       return string(hash)
+}