]>
Commit | Line | Data |
---|---|---|
6988a057 JH |
1 | package hotline |
2 | ||
3 | import ( | |
8fc43f8e | 4 | "bufio" |
00d1ef67 | 5 | "bytes" |
6988a057 | 6 | "encoding/binary" |
00d1ef67 | 7 | "errors" |
050407a3 | 8 | "io" |
f22acf38 | 9 | "path/filepath" |
7e2e07da | 10 | "strings" |
6988a057 JH |
11 | ) |
12 | ||
6988a057 | 13 | // FilePathItem represents the file or directory portion of a delimited file path (e.g. foo and bar in "/foo/bar") |
8fc43f8e | 14 | // Example bytes: |
6988a057 JH |
15 | // 00 00 |
16 | // 09 | |
8fc43f8e | 17 | // 73 75 62 66 6f 6c 64 65 72 "subfolder" |
6988a057 JH |
18 | type FilePathItem struct { |
19 | Len byte | |
20 | Name []byte | |
21 | } | |
22 | ||
8fc43f8e JH |
23 | const fileItemMinLen = 3 |
24 | ||
25 | // fileItemScanner implements bufio.SplitFunc for parsing incoming byte slices into complete tokens | |
26 | func fileItemScanner(data []byte, _ bool) (advance int, token []byte, err error) { | |
27 | if len(data) < fileItemMinLen { | |
28 | return 0, nil, nil | |
29 | } | |
30 | ||
31 | advance = fileItemMinLen + int(data[2]) | |
32 | return advance, data[0:advance], nil | |
33 | } | |
34 | ||
35 | // Write implements the io.Writer interface for FilePathItem | |
36 | func (fpi *FilePathItem) Write(b []byte) (n int, err error) { | |
37 | fpi.Len = b[2] | |
38 | fpi.Name = b[fileItemMinLen : fpi.Len+fileItemMinLen] | |
39 | ||
40 | return int(fpi.Len) + fileItemMinLen, nil | |
41 | } | |
42 | ||
6988a057 | 43 | type FilePath struct { |
00d1ef67 | 44 | ItemCount [2]byte |
72dd37f1 | 45 | Items []FilePathItem |
6988a057 JH |
46 | } |
47 | ||
8fc43f8e | 48 | func (fp *FilePath) Write(b []byte) (n int, err error) { |
050407a3 | 49 | reader := bytes.NewReader(b) |
8fc43f8e | 50 | err = binary.Read(reader, binary.BigEndian, &fp.ItemCount) |
050407a3 | 51 | if err != nil && !errors.Is(err, io.EOF) { |
8fc43f8e | 52 | return n, err |
00d1ef67 | 53 | } |
050407a3 | 54 | if errors.Is(err, io.EOF) { |
8fc43f8e | 55 | return n, nil |
050407a3 | 56 | } |
6988a057 | 57 | |
8fc43f8e JH |
58 | scanner := bufio.NewScanner(reader) |
59 | scanner.Split(fileItemScanner) | |
050407a3 | 60 | |
8fc43f8e JH |
61 | for i := 0; i < int(binary.BigEndian.Uint16(fp.ItemCount[:])); i++ { |
62 | var fpi FilePathItem | |
63 | scanner.Scan() | |
64 | if _, err := fpi.Write(scanner.Bytes()); err != nil { | |
65 | return n, err | |
050407a3 | 66 | } |
8fc43f8e | 67 | fp.Items = append(fp.Items, fpi) |
6988a057 JH |
68 | } |
69 | ||
8fc43f8e | 70 | return n, nil |
72dd37f1 JH |
71 | } |
72 | ||
8fc43f8e | 73 | // IsDropbox checks if a FilePath matches the special drop box folder type |
7e2e07da JH |
74 | func (fp *FilePath) IsDropbox() bool { |
75 | if fp.Len() == 0 { | |
76 | return false | |
77 | } | |
78 | ||
79 | return strings.Contains(strings.ToLower(string(fp.Items[fp.Len()-1].Name)), "drop box") | |
80 | } | |
81 | ||
82 | func (fp *FilePath) IsUploadDir() bool { | |
83 | if fp.Len() == 0 { | |
84 | return false | |
85 | } | |
86 | ||
25f0d77d | 87 | return strings.Contains(strings.ToLower(string(fp.Items[fp.Len()-1].Name)), "upload") |
7e2e07da JH |
88 | } |
89 | ||
72dd37f1 | 90 | func (fp *FilePath) Len() uint16 { |
00d1ef67 | 91 | return binary.BigEndian.Uint16(fp.ItemCount[:]) |
6988a057 JH |
92 | } |
93 | ||
92a7e455 JH |
94 | func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error) { |
95 | var fp FilePath | |
96 | if filePath != nil { | |
8fc43f8e | 97 | if _, err = fp.Write(filePath); err != nil { |
92a7e455 JH |
98 | return "", err |
99 | } | |
100 | } | |
101 | ||
2e08be58 JH |
102 | var subPath string |
103 | for _, pathItem := range fp.Items { | |
104 | subPath = filepath.Join("/", subPath, string(pathItem.Name)) | |
105 | } | |
106 | ||
f22acf38 | 107 | fullPath = filepath.Join( |
92a7e455 | 108 | fileRoot, |
2e08be58 | 109 | subPath, |
f22acf38 | 110 | filepath.Join("/", string(fileName)), |
92a7e455 JH |
111 | ) |
112 | ||
113 | return fullPath, nil | |
114 | } |