aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hotline/file_name_with_info_test.go6
-rw-r--r--hotline/file_path.go61
-rw-r--r--hotline/file_path_test.go6
-rw-r--r--hotline/flattened_file_object_test.go2
-rw-r--r--hotline/transaction_handlers.go10
-rw-r--r--hotline/transaction_handlers_test.go2
6 files changed, 51 insertions, 36 deletions
diff --git a/hotline/file_name_with_info_test.go b/hotline/file_name_with_info_test.go
index 3ca2c30..1637a64 100644
--- a/hotline/file_name_with_info_test.go
+++ b/hotline/file_name_with_info_test.go
@@ -72,7 +72,7 @@ func TestFileNameWithInfo_UnmarshalBinary(t *testing.T) {
name string
fields fields
args args
- want *FileNameWithInfo
+ want *FileNameWithInfo
wantErr bool
}{
{
@@ -109,11 +109,11 @@ func TestFileNameWithInfo_UnmarshalBinary(t *testing.T) {
name: tt.fields.name,
}
if err := f.UnmarshalBinary(tt.args.data); (err != nil) != tt.wantErr {
- t.Errorf("UnmarshalBinary() error = %v, wantErr %v", err, tt.wantErr)
+ t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr)
}
if !assert.Equal(t, tt.want, f) {
t.Errorf("Read() got = %v, want %v", f, tt.want)
}
})
}
-} \ No newline at end of file
+}
diff --git a/hotline/file_path.go b/hotline/file_path.go
index 460af03..46ef97c 100644
--- a/hotline/file_path.go
+++ b/hotline/file_path.go
@@ -1,6 +1,7 @@
package hotline
import (
+ "bufio"
"bytes"
"encoding/binary"
"errors"
@@ -10,52 +11,66 @@ import (
)
// FilePathItem represents the file or directory portion of a delimited file path (e.g. foo and bar in "/foo/bar")
+// Example bytes:
// 00 00
// 09
-// 73 75 62 66 6f 6c 64 65 72 // "subfolder"
+// 73 75 62 66 6f 6c 64 65 72 "subfolder"
type FilePathItem struct {
Len byte
Name []byte
}
+const fileItemMinLen = 3
+
+// fileItemScanner implements bufio.SplitFunc for parsing incoming byte slices into complete tokens
+func fileItemScanner(data []byte, _ bool) (advance int, token []byte, err error) {
+ if len(data) < fileItemMinLen {
+ return 0, nil, nil
+ }
+
+ advance = fileItemMinLen + int(data[2])
+ return advance, data[0:advance], nil
+}
+
+// Write implements the io.Writer interface for FilePathItem
+func (fpi *FilePathItem) Write(b []byte) (n int, err error) {
+ fpi.Len = b[2]
+ fpi.Name = b[fileItemMinLen : fpi.Len+fileItemMinLen]
+
+ return int(fpi.Len) + fileItemMinLen, nil
+}
+
type FilePath struct {
ItemCount [2]byte
Items []FilePathItem
}
-func (fp *FilePath) UnmarshalBinary(b []byte) error {
+func (fp *FilePath) Write(b []byte) (n int, err error) {
reader := bytes.NewReader(b)
- err := binary.Read(reader, binary.BigEndian, &fp.ItemCount)
+ err = binary.Read(reader, binary.BigEndian, &fp.ItemCount)
if err != nil && !errors.Is(err, io.EOF) {
- return err
+ return n, err
}
if errors.Is(err, io.EOF) {
- return nil
+ return n, nil
}
- for i := uint16(0); i < fp.Len(); i++ {
- // skip two bytes for the file path delimiter
- _, _ = reader.Seek(2, io.SeekCurrent)
-
- // read the length of the next pathItem
- segLen, err := reader.ReadByte()
- if err != nil {
- return err
- }
-
- pBytes := make([]byte, segLen)
+ scanner := bufio.NewScanner(reader)
+ scanner.Split(fileItemScanner)
- _, err = reader.Read(pBytes)
- if err != nil && !errors.Is(err, io.EOF) {
- return err
+ for i := 0; i < int(binary.BigEndian.Uint16(fp.ItemCount[:])); i++ {
+ var fpi FilePathItem
+ scanner.Scan()
+ if _, err := fpi.Write(scanner.Bytes()); err != nil {
+ return n, err
}
-
- fp.Items = append(fp.Items, FilePathItem{Len: segLen, Name: pBytes})
+ fp.Items = append(fp.Items, fpi)
}
- return nil
+ return n, nil
}
+// IsDropbox checks if a FilePath matches the special drop box folder type
func (fp *FilePath) IsDropbox() bool {
if fp.Len() == 0 {
return false
@@ -79,7 +94,7 @@ func (fp *FilePath) Len() uint16 {
func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error) {
var fp FilePath
if filePath != nil {
- if err = fp.UnmarshalBinary(filePath); err != nil {
+ if _, err = fp.Write(filePath); err != nil {
return "", err
}
}
diff --git a/hotline/file_path_test.go b/hotline/file_path_test.go
index f25941e..c2fa666 100644
--- a/hotline/file_path_test.go
+++ b/hotline/file_path_test.go
@@ -5,7 +5,7 @@ import (
"testing"
)
-func TestFilePath_UnmarshalBinary(t *testing.T) {
+func TestFilePath_Write(t *testing.T) {
type args struct {
b []byte
}
@@ -56,8 +56,8 @@ func TestFilePath_UnmarshalBinary(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var fp FilePath
- if err := fp.UnmarshalBinary(tt.args.b); (err != nil) != tt.wantErr {
- t.Errorf("UnmarshalBinary() error = %v, wantErr %v", err, tt.wantErr)
+ if _, err := fp.Write(tt.args.b); (err != nil) != tt.wantErr {
+ t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr)
}
if !assert.Equal(t, tt.want, fp) {
t.Errorf("Read() got = %v, want %v", fp, tt.want)
diff --git a/hotline/flattened_file_object_test.go b/hotline/flattened_file_object_test.go
index 596ca2c..274ca2b 100644
--- a/hotline/flattened_file_object_test.go
+++ b/hotline/flattened_file_object_test.go
@@ -37,7 +37,7 @@ func TestFlatFileInformationFork_UnmarshalBinary(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ffif := &FlatFileInformationFork{}
- tt.wantErr(t, ffif.UnmarshalBinary(tt.args.b), fmt.Sprintf("UnmarshalBinary(%v)", tt.args.b))
+ tt.wantErr(t, ffif.UnmarshalBinary(tt.args.b), fmt.Sprintf("Write(%v)", tt.args.b))
})
}
}
diff --git a/hotline/transaction_handlers.go b/hotline/transaction_handlers.go
index 23ee0e6..8ba3632 100644
--- a/hotline/transaction_handlers.go
+++ b/hotline/transaction_handlers.go
@@ -582,7 +582,7 @@ func HandleNewFolder(cc *ClientConn, t *Transaction) (res []Transaction, err err
// fieldFilePath is only present for nested paths
if t.GetField(fieldFilePath).Data != nil {
var newFp FilePath
- err := newFp.UnmarshalBinary(t.GetField(fieldFilePath).Data)
+ _, err := newFp.Write(t.GetField(fieldFilePath).Data)
if err != nil {
return nil, err
}
@@ -1472,7 +1472,7 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
fileTransfer := cc.newFileTransfer(FolderDownload, t.GetField(fieldFileName).Data, t.GetField(fieldFilePath).Data, transferSize)
var fp FilePath
- err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data)
+ _, err = fp.Write(t.GetField(fieldFilePath).Data)
if err != nil {
return res, err
}
@@ -1496,7 +1496,7 @@ func HandleDownloadFolder(cc *ClientConn, t *Transaction) (res []Transaction, er
func HandleUploadFolder(cc *ClientConn, t *Transaction) (res []Transaction, err error) {
var fp FilePath
if t.GetField(fieldFilePath).Data != nil {
- if err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data); err != nil {
+ if _, err = fp.Write(t.GetField(fieldFilePath).Data); err != nil {
return res, err
}
}
@@ -1541,7 +1541,7 @@ func HandleUploadFile(cc *ClientConn, t *Transaction) (res []Transaction, err er
var fp FilePath
if filePath != nil {
- if err = fp.UnmarshalBinary(filePath); err != nil {
+ if _, err = fp.Write(filePath); err != nil {
return res, err
}
}
@@ -1658,7 +1658,7 @@ func HandleGetFileNameList(cc *ClientConn, t *Transaction) (res []Transaction, e
var fp FilePath
if t.GetField(fieldFilePath).Data != nil {
- if err = fp.UnmarshalBinary(t.GetField(fieldFilePath).Data); err != nil {
+ if _, err = fp.Write(t.GetField(fieldFilePath).Data); err != nil {
return res, err
}
}
diff --git a/hotline/transaction_handlers_test.go b/hotline/transaction_handlers_test.go
index 0d6b1dc..b5e0bac 100644
--- a/hotline/transaction_handlers_test.go
+++ b/hotline/transaction_handlers_test.go
@@ -814,7 +814,7 @@ func TestHandleNewFolder(t *testing.T) {
wantErr: false,
},
{
- name: "when UnmarshalBinary returns an err",
+ name: "when Write returns an err",
args: args{
cc: &ClientConn{
Account: &Account{