magic-wormhole/bin/receive_file.py

74 lines
2.5 KiB
Python
Raw Normal View History

2015-02-11 09:18:31 +00:00
from __future__ import print_function
import sys, os, json
2015-02-11 00:50:32 +00:00
from nacl.secret import SecretBox
2015-02-20 08:32:48 +00:00
from wormhole.blocking.transcribe import Receiver, WrongPasswordError
2015-02-15 17:53:59 +00:00
from wormhole.blocking.transit import TransitReceiver
2015-02-11 00:50:32 +00:00
APPID = "lothar.com/wormhole/file-xfer"
# we're receiving
2015-02-15 17:53:59 +00:00
transit_receiver = TransitReceiver()
2015-02-15 22:42:59 +00:00
mydata = json.dumps({
"transit": {
2015-02-20 03:09:08 +00:00
"direct_connection_hints": transit_receiver.get_direct_hints(),
"relay_connection_hints": transit_receiver.get_relay_hints(),
2015-02-15 22:42:59 +00:00
},
}).encode("utf-8")
r = Receiver(APPID, mydata)
r.set_code(r.input_code("Enter receive-file wormhole code: "))
2015-02-15 17:53:59 +00:00
2015-02-20 08:32:48 +00:00
try:
data = json.loads(r.get_data().decode("utf-8"))
except WrongPasswordError as e:
print("ERROR: " + e.explain(), file=sys.stderr)
sys.exit(1)
#print("their data: %r" % (data,))
2015-02-15 17:53:59 +00:00
2015-02-15 22:42:59 +00:00
file_data = data["file"]
xfer_key = r.derive_key(APPID+"/xfer-key", SecretBox.KEY_SIZE)
2015-02-15 22:42:59 +00:00
filename = os.path.basename(file_data["filename"]) # unicode
filesize = file_data["filesize"]
encrypted_filesize = filesize + SecretBox.NONCE_SIZE+16
2015-02-11 00:50:32 +00:00
# now receive the rest of the owl
2015-02-15 22:42:59 +00:00
tdata = data["transit"]
transit_key = r.derive_key(APPID+"/transit-key")
transit_receiver.set_transit_key(transit_key)
2015-02-20 03:09:08 +00:00
transit_receiver.add_their_direct_hints(tdata["direct_connection_hints"])
transit_receiver.add_their_relay_hints(tdata["relay_connection_hints"])
skt = transit_receiver.establish_connection()
print("Receiving %d bytes.." % filesize)
encrypted = b""
while len(encrypted) < encrypted_filesize:
more = skt.recv(encrypted_filesize - len(encrypted))
if not more:
print("Connection dropped before full file received")
print("got %d bytes, wanted %d" % (len(encrypted), encrypted_filesize))
sys.exit(1)
encrypted += more
assert len(encrypted) == encrypted_filesize
2015-02-11 01:04:28 +00:00
decrypted = SecretBox(xfer_key).decrypt(encrypted)
# only write to the current directory, and never overwrite anything
here = os.path.abspath(os.getcwd())
target = os.path.abspath(os.path.join(here, filename))
if os.path.dirname(target) != here:
print("Error: suggested filename (%s) would be outside current directory"
% (filename,))
skt.send("bad filename\n")
skt.close()
sys.exit(1)
if os.path.exists(target):
print("Error: refusing to overwrite existing file %s" % (filename,))
skt.send("file already exists\n")
skt.close()
sys.exit(1)
2015-02-11 01:04:28 +00:00
with open(target, "wb") as f:
f.write(decrypted)
print("Received file written to %s" % filename)
skt.send("ok\n")
skt.close()
sys.exit(0)