#!/usr/bin/env python """This program is a client that sends files to xfer-server.py. You give it the server's FURL, and it can put files into the server's targetdir (and nowhere else). When you want an unattended process on one machine to be able to place files in a remote directory, you could give its parent process an ssh account on the target, with an empty passphrase, but that provides too much power. This program is a least-privilege replacement for the ssh/scp approach. Give the client a FURL, or a file where the FURL is stored. You also give it the name of the local file to be transferred. The last component of the local pathname will be used as the remote filename. """ import os.path from twisted.internet import reactor from foolscap import UnauthenticatedTub from twisted.python import usage class Options(usage.Options): synopsis = "xfer-client.py (--furl FURL | --furlfile furlfile) LOCALFILE" optParameters = [ ["furl", "f", None, "The server FURL. You must either provide --furl or --furlfile."], ["furlfile", "l", None, "A file containing the server FURL."], ] optFlags = [ ["quiet", "q", "Do not announce success."], ] def parseArgs(self, localfile): self['localfile'] = localfile def postOptions(self): if not self["furl"] and not self["furlfile"]: raise usage.UsageError("you must either provide --furl or --furlfile") if not os.path.exists(self["localfile"]): raise usage.UsageError("local file '%s' doesn't exist" % self["localfile"]) opts = Options() opts.parseOptions() tub = UnauthenticatedTub() tub.startService() if opts["furl"]: furl = opts["furl"] else: furl = open(os.path.expanduser(opts["furlfile"]), "r").read().strip() remotename = os.path.basename(opts["localfile"]) d = tub.getReference(furl) def _push(rref): data = open(os.path.expanduser(opts["localfile"]), "r").read() return rref.callRemote("putfile", remotename, data) d.addCallback(_push) def _success(res): reactor.stop() if not opts["quiet"]: print "file transferred to %s" % remotename def _failure(f): reactor.stop() print "error while transferring file:" print f d.addCallbacks(_success, _failure) reactor.run()