]> git.r.bdr.sh - rbdr/mobius/blob - hotline/file_path.go
Handle zero length comment and file paths for Nostalgia compatibility
[rbdr/mobius] / hotline / file_path.go
1 package hotline
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "errors"
7 "io"
8 "path"
9 "strings"
10 )
11
12 const pathSeparator = "/" // File path separator TODO: make configurable to support Windows
13
14 // FilePathItem represents the file or directory portion of a delimited file path (e.g. foo and bar in "/foo/bar")
15 // 00 00
16 // 09
17 // 73 75 62 66 6f 6c 64 65 72 // "subfolder"
18 type FilePathItem struct {
19 Len byte
20 Name []byte
21 }
22
23 type FilePath struct {
24 ItemCount [2]byte
25 Items []FilePathItem
26 }
27
28 func (fp *FilePath) UnmarshalBinary(b []byte) error {
29 reader := bytes.NewReader(b)
30 err := binary.Read(reader, binary.BigEndian, &fp.ItemCount)
31 if err != nil && !errors.Is(err, io.EOF) {
32 return err
33 }
34 if errors.Is(err, io.EOF) {
35 return nil
36 }
37
38 for i := uint16(0); i < fp.Len(); i++ {
39 // skip two bytes for the file path delimiter
40 _, _ = reader.Seek(2, io.SeekCurrent)
41
42 // read the length of the next pathItem
43 segLen, err := reader.ReadByte()
44 if err != nil {
45 return err
46 }
47
48 pBytes := make([]byte, segLen)
49
50 _, err = reader.Read(pBytes)
51 if err != nil && !errors.Is(err, io.EOF) {
52 return err
53 }
54
55 fp.Items = append(fp.Items, FilePathItem{Len: segLen, Name: pBytes})
56 }
57
58 return nil
59 }
60
61 func (fp *FilePath) IsDropbox() bool {
62 if fp.Len() == 0 {
63 return false
64 }
65
66 return strings.Contains(strings.ToLower(string(fp.Items[fp.Len()-1].Name)), "drop box")
67 }
68
69 func (fp *FilePath) IsUploadDir() bool {
70 if fp.Len() == 0 {
71 return false
72 }
73
74 return strings.Contains(strings.ToLower(string(fp.Items[fp.Len()-1].Name)), "upload")
75 }
76
77 func (fp *FilePath) Len() uint16 {
78 return binary.BigEndian.Uint16(fp.ItemCount[:])
79 }
80
81 func (fp *FilePath) String() string {
82 out := []string{"/"}
83 for _, i := range fp.Items {
84 out = append(out, string(i.Name))
85 }
86
87 return path.Join(out...)
88 }
89
90 func ReadFilePath(filePathFieldData []byte) string {
91 var fp FilePath
92 err := fp.UnmarshalBinary(filePathFieldData)
93 if err != nil {
94 // TODO
95 }
96 return fp.String()
97 }
98
99 func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error) {
100 var fp FilePath
101 if filePath != nil {
102 if err = fp.UnmarshalBinary(filePath); err != nil {
103 return "", err
104 }
105 }
106
107 fullPath = path.Join(
108 "/",
109 fileRoot,
110 fp.String(),
111 path.Join("/", string(fileName)),
112 )
113
114 return fullPath, nil
115 }