#463 added capability to send/receive empty folders

This commit is contained in:
iulius98 2022-04-09 01:38:22 +03:00
parent 386c99d057
commit 15d0209a29
2 changed files with 80 additions and 28 deletions

View File

@ -267,7 +267,7 @@ func send(c *cli.Context) (err error) {
crocOptions.SharedSecret = utils.GetRandomName()
}
minimalFileInfos, err := croc.GetFilesInfo(fnames)
minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders, err := croc.GetFilesInfo(fnames)
if err != nil {
return
}
@ -280,7 +280,7 @@ func send(c *cli.Context) (err error) {
// save the config
saveConfig(c, crocOptions)
err = cr.Send(minimalFileInfos)
err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders)
return
}

View File

@ -88,12 +88,14 @@ type Client struct {
Step1ChannelSecured bool
Step2FileInfoTransferred bool
Step3RecipientRequestFile bool
Step4FileTransfer bool
Step4FileTransferred bool
Step5CloseChannels bool
SuccessfulTransfer bool
// send / receive information of all files
FilesToTransfer []FileInfo
EmptyFoldersToTransfer []FileInfo
TotalNumberFolders int
FilesToTransferCurrentNum int
FilesHasFinished map[int]struct{}
@ -154,12 +156,14 @@ type RemoteFileRequest struct {
// SenderInfo lists the files to be transferred
type SenderInfo struct {
FilesToTransfer []FileInfo
MachineID string
Ask bool
SendingText bool
NoCompress bool
HashAlgorithm string
FilesToTransfer []FileInfo
EmptyFoldersToTransfer []FileInfo
TotalNumberFolders int
MachineID string
Ask bool
SendingText bool
NoCompress bool
HashAlgorithm string
}
// New establishes a new connection for transferring files between two instances.
@ -228,11 +232,25 @@ type TransferOptions struct {
KeepPathInRemote bool
}
func isEmptyFolder(folderPath string) (bool, error) {
f, err := os.Open(folderPath)
if err != nil {
return false, err
}
defer f.Close()
_, err = f.Readdirnames(1)
if err == io.EOF {
return true, nil
}
return false, nil
}
// This function retrives the important file informations
// for every file that will be transfered
func GetFilesInfo(fnames []string) (filesInfo []FileInfo, err error) {
func GetFilesInfo(fnames []string) (filesInfo []FileInfo, emptyFolders []FileInfo, totalNumberFolders int, err error) {
// fnames: the relativ/absolute paths of files/folders that will be transfered
totalNumberFolders = 0
var paths []string
for _, fname := range fnames {
// Support wildcard
@ -270,10 +288,9 @@ func GetFilesInfo(fnames []string) (filesInfo []FileInfo, err error) {
if err != nil {
return err
}
remoteFolder := strings.TrimPrefix(filepath.Dir(pathName),
filepath.Dir(absPath)+string(os.PathSeparator))
if !info.IsDir() {
remoteFolder := strings.TrimPrefix(filepath.Dir(pathName),
filepath.Dir(absPath)+string(os.PathSeparator))
filesInfo = append(filesInfo, FileInfo{
Name: info.Name(),
FolderRemote: strings.Replace(remoteFolder, string(os.PathSeparator), "/", -1) + "/",
@ -282,6 +299,15 @@ func GetFilesInfo(fnames []string) (filesInfo []FileInfo, err error) {
ModTime: info.ModTime(),
Mode: info.Mode(),
})
} else {
totalNumberFolders++
isEmptyFolder, _ := isEmptyFolder(pathName)
if isEmptyFolder {
emptyFolders = append(emptyFolders, FileInfo{
FolderRemote: strings.Replace(strings.TrimPrefix(pathName,
filepath.Dir(absPath)+string(os.PathSeparator)), string(os.PathSeparator), "/", -1) + "/",
})
}
}
return nil
})
@ -443,8 +469,10 @@ func (c *Client) transferOverLocalRelay(errchan chan<- error) {
}
// Send will send the specified file
func (c *Client) Send(filesInfo []FileInfo) (err error) {
func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, totalNumberFolders int) (err error) {
err = c.sendCollectFiles(filesInfo)
c.EmptyFoldersToTransfer = emptyFoldersToTransfer
c.TotalNumberFolders = totalNumberFolders
if err != nil {
return
}
@ -778,7 +806,7 @@ func (c *Client) Receive() (err error) {
fmt.Fprintf(os.Stderr, "\rsecuring channel...")
err = c.transfer()
if err == nil {
if c.numberOfTransferredFiles == 0 {
if c.numberOfTransferredFiles+len(c.EmptyFoldersToTransfer) == 0 {
fmt.Fprintf(os.Stderr, "\rNo files transferred.")
}
}
@ -870,6 +898,8 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
c.Options.SendingText = senderInfo.SendingText
c.Options.NoCompress = senderInfo.NoCompress
c.Options.HashAlgorithm = senderInfo.HashAlgorithm
c.EmptyFoldersToTransfer = senderInfo.EmptyFoldersToTransfer
c.TotalNumberFolders = senderInfo.TotalNumberFolders
if c.Options.HashAlgorithm == "" {
c.Options.HashAlgorithm = "xxhash"
}
@ -882,6 +912,7 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
}
c.FilesToTransfer = senderInfo.FilesToTransfer
fname := fmt.Sprintf("%d files", len(c.FilesToTransfer))
folderName := fmt.Sprintf("%d folders", c.TotalNumberFolders)
if len(c.FilesToTransfer) == 1 {
fname = fmt.Sprintf("'%s'", c.FilesToTransfer[0].Name)
}
@ -909,7 +940,7 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
machID, _ := machineid.ID()
fmt.Fprintf(os.Stderr, "\rYour machine id is '%s'.\n%s %s (%s) from '%s'? (Y/n) ", machID, action, fname, utils.ByteCountDecimal(totalSize), senderInfo.MachineID)
} else {
fmt.Fprintf(os.Stderr, "\r%s %s (%s)? (Y/n) ", action, fname, utils.ByteCountDecimal(totalSize))
fmt.Fprintf(os.Stderr, "\r%s %s and %s (%s)? (Y/n) ", action, fname, folderName, utils.ByteCountDecimal(totalSize))
}
choice := strings.ToLower(utils.GetInput(""))
if choice != "" && choice != "y" && choice != "yes" {
@ -927,6 +958,25 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
}
fmt.Fprintf(os.Stderr, "\nReceiving (<-%s)\n", c.ExternalIPConnected)
//after user accepted the transfer we can create empty folders
for i := 0; i < len(c.EmptyFoldersToTransfer); i += 1 {
errMkDirAll := os.MkdirAll(c.EmptyFoldersToTransfer[i].FolderRemote, os.ModePerm)
if err != nil {
err = errMkDirAll
return
}
}
if c.FilesToTransfer == nil {
c.SuccessfulTransfer = true
c.Step3RecipientRequestFile = true
c.Step4FileTransferred = true
errStopTransfer := message.Send(c.conn[0], c.Key, message.Message{
Type: message.TypeFinished,
})
if errStopTransfer != nil {
err = errStopTransfer
}
}
log.Debug(c.FilesToTransfer)
c.Step2FileInfoTransferred = true
return
@ -1121,14 +1171,14 @@ func (c *Client) processMessage(payload []byte) (done bool, err error) {
case message.TypeCloseSender:
c.bar.Finish()
log.Debug("close-sender received...")
c.Step4FileTransfer = false
c.Step4FileTransferred = false
c.Step3RecipientRequestFile = false
log.Debug("sending close-recipient")
err = message.Send(c.conn[0], c.Key, message.Message{
Type: message.TypeCloseRecipient,
})
case message.TypeCloseRecipient:
c.Step4FileTransfer = false
c.Step4FileTransferred = false
c.Step3RecipientRequestFile = false
}
if err != nil {
@ -1148,12 +1198,14 @@ func (c *Client) updateIfSenderChannelSecured() (err error) {
var b []byte
machID, _ := machineid.ID()
b, err = json.Marshal(SenderInfo{
FilesToTransfer: c.FilesToTransfer,
MachineID: machID,
Ask: c.Options.Ask,
SendingText: c.Options.SendingText,
NoCompress: c.Options.NoCompress,
HashAlgorithm: c.Options.HashAlgorithm,
FilesToTransfer: c.FilesToTransfer,
EmptyFoldersToTransfer: c.EmptyFoldersToTransfer,
MachineID: machID,
Ask: c.Options.Ask,
TotalNumberFolders: c.TotalNumberFolders,
SendingText: c.Options.SendingText,
NoCompress: c.Options.NoCompress,
HashAlgorithm: c.Options.HashAlgorithm,
})
if err != nil {
log.Error(err)
@ -1402,7 +1454,7 @@ func (c *Client) updateIfRecipientHasFileInfo() (err error) {
break
}
}
err = c.recipientGetFileReady(finished)
c.recipientGetFileReady(finished)
return
}
@ -1426,7 +1478,7 @@ func (c *Client) updateState() (err error) {
return
}
if c.Options.IsSender && c.Step3RecipientRequestFile && !c.Step4FileTransfer {
if c.Options.IsSender && c.Step3RecipientRequestFile && !c.Step4FileTransferred {
log.Debug("start sending data!")
if !c.firstSend {
@ -1457,7 +1509,7 @@ func (c *Client) updateState() (err error) {
}
}
}
c.Step4FileTransfer = true
c.Step4FileTransferred = true
// setup the progressbar
c.setBar()
c.TotalSent = 0