]>
Commit | Line | Data |
---|---|---|
1 | package hotline | |
2 | ||
3 | import ( | |
4 | "bufio" | |
5 | "bytes" | |
6 | "encoding/binary" | |
7 | "errors" | |
8 | "io" | |
9 | "os" | |
10 | "path/filepath" | |
11 | ) | |
12 | ||
13 | type transfer struct { | |
14 | Protocol [4]byte // "HTXF" 0x48545846 | |
15 | ReferenceNumber [4]byte // Unique ID generated for the transfer | |
16 | DataSize [4]byte // File size | |
17 | RSVD [4]byte // Not implemented in Hotline Protocol | |
18 | } | |
19 | ||
20 | var HTXF = [4]byte{0x48, 0x54, 0x58, 0x46} // (HTXF) is the only supported transfer protocol | |
21 | ||
22 | func (tf *transfer) Write(b []byte) (int, error) { | |
23 | if err := binary.Read(bytes.NewReader(b), binary.BigEndian, tf); err != nil { | |
24 | return 0, err | |
25 | } | |
26 | ||
27 | if tf.Protocol != HTXF { | |
28 | return 0, errors.New("invalid protocol") | |
29 | } | |
30 | ||
31 | return len(b), nil | |
32 | } | |
33 | ||
34 | const fileCopyBufSize = 4096 | |
35 | ||
36 | func receiveFile(r io.Reader, targetFile, resForkFile, infoFork io.Writer) error { | |
37 | var ffo flattenedFileObject | |
38 | if _, err := ffo.ReadFrom(r); err != nil { | |
39 | return err | |
40 | } | |
41 | ||
42 | // Write the information fork | |
43 | _, err := infoFork.Write(ffo.FlatFileInformationFork.MarshalBinary()) | |
44 | if err != nil { | |
45 | return err | |
46 | } | |
47 | ||
48 | // read and write the data fork | |
49 | bw := bufio.NewWriterSize(targetFile, fileCopyBufSize) | |
50 | if _, err = io.CopyN(bw, r, ffo.dataSize()); err != nil { | |
51 | return err | |
52 | } | |
53 | if err := bw.Flush(); err != nil { | |
54 | return err | |
55 | } | |
56 | ||
57 | if ffo.FlatFileHeader.ForkCount == [2]byte{0, 3} { | |
58 | if err := binary.Read(r, binary.BigEndian, &ffo.FlatFileResForkHeader); err != nil { | |
59 | return err | |
60 | } | |
61 | ||
62 | bw = bufio.NewWriterSize(resForkFile, fileCopyBufSize) | |
63 | _, err = io.CopyN(resForkFile, r, ffo.rsrcSize()) | |
64 | if err != nil { | |
65 | return err | |
66 | } | |
67 | if err := bw.Flush(); err != nil { | |
68 | return err | |
69 | } | |
70 | } | |
71 | return nil | |
72 | } | |
73 | ||
74 | func sendFile(w io.Writer, r io.Reader, offset int) (err error) { | |
75 | br := bufio.NewReader(r) | |
76 | if _, err := br.Discard(offset); err != nil { | |
77 | return err | |
78 | } | |
79 | ||
80 | rSendBuffer := make([]byte, 1024) | |
81 | for { | |
82 | var bytesRead int | |
83 | ||
84 | if bytesRead, err = br.Read(rSendBuffer); err == io.EOF { | |
85 | if _, err := w.Write(rSendBuffer[:bytesRead]); err != nil { | |
86 | return err | |
87 | } | |
88 | return nil | |
89 | } | |
90 | if err != nil { | |
91 | return err | |
92 | } | |
93 | // totalSent += int64(bytesRead) | |
94 | ||
95 | // fileTransfer.BytesSent += bytesRead | |
96 | ||
97 | if _, err := w.Write(rSendBuffer[:bytesRead]); err != nil { | |
98 | return err | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | func (s *Server) bannerDownload(w io.Writer) error { | |
104 | bannerBytes, err := os.ReadFile(filepath.Join(s.ConfigDir, s.Config.BannerFile)) | |
105 | if err != nil { | |
106 | return err | |
107 | } | |
108 | _, err = w.Write(bannerBytes) | |
109 | ||
110 | return err | |
111 | } |