]>
Commit | Line | Data |
---|---|---|
6988a057 JH |
1 | package hotline |
2 | ||
3 | import ( | |
00d1ef67 | 4 | "bytes" |
6988a057 | 5 | "encoding/binary" |
00d1ef67 | 6 | "errors" |
050407a3 | 7 | "io" |
00d1ef67 | 8 | "path" |
7e2e07da | 9 | "strings" |
6988a057 JH |
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 | ||
6988a057 | 23 | type FilePath struct { |
00d1ef67 | 24 | ItemCount [2]byte |
72dd37f1 | 25 | Items []FilePathItem |
6988a057 JH |
26 | } |
27 | ||
72dd37f1 | 28 | func (fp *FilePath) UnmarshalBinary(b []byte) error { |
050407a3 JH |
29 | reader := bytes.NewReader(b) |
30 | err := binary.Read(reader, binary.BigEndian, &fp.ItemCount) | |
31 | if err != nil && !errors.Is(err, io.EOF) { | |
00d1ef67 JH |
32 | return err |
33 | } | |
050407a3 JH |
34 | if errors.Is(err, io.EOF) { |
35 | return nil | |
36 | } | |
6988a057 | 37 | |
72dd37f1 | 38 | for i := uint16(0); i < fp.Len(); i++ { |
050407a3 JH |
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}) | |
6988a057 JH |
56 | } |
57 | ||
72dd37f1 JH |
58 | return nil |
59 | } | |
60 | ||
7e2e07da JH |
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 | ||
25f0d77d | 74 | return strings.Contains(strings.ToLower(string(fp.Items[fp.Len()-1].Name)), "upload") |
7e2e07da JH |
75 | } |
76 | ||
72dd37f1 | 77 | func (fp *FilePath) Len() uint16 { |
00d1ef67 | 78 | return binary.BigEndian.Uint16(fp.ItemCount[:]) |
6988a057 JH |
79 | } |
80 | ||
81 | func (fp *FilePath) String() string { | |
00d1ef67 | 82 | out := []string{"/"} |
72dd37f1 | 83 | for _, i := range fp.Items { |
6988a057 JH |
84 | out = append(out, string(i.Name)) |
85 | } | |
00d1ef67 JH |
86 | |
87 | return path.Join(out...) | |
6988a057 | 88 | } |
c5d9af5a | 89 | |
92a7e455 JH |
90 | func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err error) { |
91 | var fp FilePath | |
92 | if filePath != nil { | |
93 | if err = fp.UnmarshalBinary(filePath); err != nil { | |
94 | return "", err | |
95 | } | |
96 | } | |
97 | ||
98 | fullPath = path.Join( | |
99 | "/", | |
100 | fileRoot, | |
101 | fp.String(), | |
102 | path.Join("/", string(fileName)), | |
103 | ) | |
104 | ||
105 | return fullPath, nil | |
106 | } |