Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 1e07de2009c1b4cf9b7971c91f42461d > files > 193

python-foolscap-0.4.2-1mdv2010.0.noarch.rpm

#! /usr/bin/python

"""This program is a server that receives file-upload requests from
xfer-client.py. Anyone who knows the server's FURL will be able to put files
in the 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 server a --basedir where it can store persistent private data, so it
can use the same FURL from one run to the next. The server's FURL will be
stored in 'server.furl' in that directory, and will also be printed to stdout
(unless you pass --quiet).

This server should be placed into the background, like this:

 xfer-server.py --quiet --basedir ~/private 12345 ~/targetdir &

It may be convenient to launch this from a cron @reboot job, so that it is
always available.
"""

from os import chmod
import os.path
from twisted.internet import reactor
from foolscap.api import Tub, Referenceable
from twisted.python import usage

class Options(usage.Options):
    synopsis = "xfer-server.py PORTNUM TARGETDIR"
    optParameters = [
        ["basedir", "b", "~/.foolscap-xfer-server",
         "Directory to store my private certificate and FURL file."],
        ["mode", "m", "0644",
         "(octal) mode to set uploaded files to, use 0644 for world-readable"],
        ]
    optFlags = [
        ["quiet", "q", "Do not print the server FURL at startup."],
        ]

    def parseArgs(self, port, targetdir):
        self['port'] = port
        self['targetdir'] = os.path.abspath(targetdir)

class BadFilenameError(Exception):
    pass

class FileReceiver(Referenceable):
    def __init__(self, targetdir, mode):
        self.targetdir = targetdir
        self.mode = mode

    def remote_putfile(self, name, data):
        if "/" in name or name == "..":
            raise BadFilenameError()
        targetfile = os.path.join(self.targetdir, name)
        f = open(targetfile, "w")
        f.write(data)
        f.close()
        chmod(targetfile, self.mode)

opts = Options()
opts.parseOptions()
mode = opts["mode"]
if mode.startswith("0"):
    mode = int(mode, 8)
else:
    mode = int(mode)
gr = FileReceiver(opts["targetdir"], mode)

tub = Tub(certFile=os.path.join(opts["basedir"], "tub.pem"))
l = tub.listenOn(opts["port"])
tub.startService()
furlfile = os.path.join(opts["basedir"], "receiver.furl")
d = tub.setLocationAutomatically()
d.addCallback(lambda res: tub.registerReference(gr, furlFile=furlfile))
def _print_furl(furl):
    if not opts["quiet"]:
        print "Server is listening on:"
        print " " + furl
d.addCallback(_print_furl)

reactor.run()