aboutsummaryrefslogtreecommitdiff
path: root/Command/TransferInfo.hs
blob: 3f352a82ebd9fac09298039728e10b456789a93f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{- git-annex command
 -
 - Copyright 2012 Joey Hess <id@joeyh.name>
 -
 - Licensed under the GNU GPL version 3 or higher.
 -}

module Command.TransferInfo where

import Command
import Annex.Content
import Types.Transfer
import Logs.Transfer
import qualified CmdLine.GitAnnexShell.Fields as Fields
import Utility.Metered
import Utility.SimpleProtocol

cmd :: Command
cmd = noCommit $ 
	command "transferinfo" SectionPlumbing
		"updates sender on number of bytes of content received"
		paramKey (withParams seek)

seek :: CmdParams -> CommandSeek
seek = withWords start

{- Security:
 - 
 - The transfer info file contains the user-supplied key, but
 - the built-in guards prevent slashes in it from showing up in the filename.
 - It also contains the UUID of the remote. But slashes are also filtered
 - out of that when generating the filename.
 - 
 - Checks that the key being transferred is inAnnex, to prevent
 - malicious spamming of bogus keys. Does not check that a transfer
 - of the key is actually in progress, because this could be started
 - concurrently with sendkey, and win the race.
 -}
start :: [String] -> CommandStart
start (k:[]) = do
	case file2key k of
		Nothing -> error "bad key"
		(Just key) -> whenM (inAnnex key) $ do
			afile <- AssociatedFile <$> Fields.getField Fields.associatedFile
			u <- maybe (error "missing remoteuuid") toUUID
				<$> Fields.getField Fields.remoteUUID
			let t = Transfer
				{ transferDirection = Upload
				, transferUUID = u
				, transferKey = key
				}
			tinfo <- liftIO $ startTransferInfo afile
			(update, tfile, _) <- mkProgressUpdater t tinfo
			liftIO $ mapM_ void
				[ tryIO $ forever $ do
					bytes <- readUpdate
					maybe (error "transferinfo protocol error")
						(update . toBytesProcessed) bytes
				, tryIO $ removeFile tfile
				, exitSuccess
				]
	stop
start _ = giveup "wrong number of parameters"

readUpdate :: IO (Maybe Integer)
readUpdate = maybe Nothing readish <$> getProtocolLine stdin