]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/transfer.go
Fix and refactor file transfers to handle resource forks
[rbdr/mobius] / hotline / transfer.go
index fa431cee176de216af5582336c5d3e6f0ecea198..703dae0582b02c9457fa0ef35c802dd53cf77b58 100644 (file)
@@ -4,6 +4,7 @@ import (
        "bytes"
        "encoding/binary"
        "errors"
+       "io"
 )
 
 type transfer struct {
@@ -26,3 +27,78 @@ func (tf *transfer) Write(b []byte) (int, error) {
 
        return len(b), nil
 }
+
+func receiveFile(conn io.Reader, targetFile io.Writer, resForkFile io.Writer) error {
+       ffhBuf := make([]byte, 24)
+       if _, err := conn.Read(ffhBuf); err != nil {
+               return err
+       }
+
+       var ffh FlatFileHeader
+       err := binary.Read(bytes.NewReader(ffhBuf), binary.BigEndian, &ffh)
+       if err != nil {
+               return err
+       }
+
+       ffifhBuf := make([]byte, 16)
+       if _, err := conn.Read(ffifhBuf); err != nil {
+               return err
+       }
+
+       var ffifh FlatFileInformationForkHeader
+       err = binary.Read(bytes.NewReader(ffifhBuf), binary.BigEndian, &ffifh)
+       if err != nil {
+               return err
+       }
+
+       var ffif FlatFileInformationFork
+
+       dataLen := binary.BigEndian.Uint32(ffifh.DataSize[:])
+       ffifBuf := make([]byte, dataLen)
+       if _, err := conn.Read(ffifBuf); err != nil {
+               return err
+       }
+       if err := ffif.UnmarshalBinary(ffifBuf); err != nil {
+               return err
+       }
+
+       var ffdfh FlatFileDataForkHeader
+       ffdfhBuf := make([]byte, 16)
+       if _, err := conn.Read(ffdfhBuf); err != nil {
+               return err
+       }
+       err = binary.Read(bytes.NewReader(ffdfhBuf), binary.BigEndian, &ffdfh)
+       if err != nil {
+               return err
+       }
+
+       // this will be zero if the file only has a resource fork
+       fileSize := int(binary.BigEndian.Uint32(ffdfh.DataSize[:]))
+
+       // Copy N bytes from conn to upload file
+       _, err = io.CopyN(targetFile, conn, int64(fileSize))
+       if err != nil {
+               return err
+       }
+
+       if ffh.ForkCount == [2]byte{0, 3} {
+               var resForkHeader FlatFileDataForkHeader
+               resForkBuf := make([]byte, 16)
+
+               if _, err := conn.Read(resForkBuf); err != nil {
+                       return err
+               }
+               err = binary.Read(bytes.NewReader(resForkBuf), binary.BigEndian, &resForkHeader)
+               if err != nil {
+                       return err
+               }
+
+               fileSize = int(binary.BigEndian.Uint32(resForkHeader.DataSize[:]))
+
+               _, err = io.CopyN(resForkFile, conn, int64(fileSize))
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}