from twisted.application import service, strports
-from twisted.web import static, resource, server
+from twisted.web import static, resource, server, html
from twisted.python import util, log
from nevow import inevow, rend, loaders, appserver, url, tags as T
from allmydata.util import idlib
class IClient(Interface):
pass
-class WebishServer(service.MultiService):
- name = "webish"
-
- def __init__(self, webport):
- service.MultiService.__init__(self)
- self.root = root = static.Data("root", "text/plain")
- w = Welcome()
- root.putChild("", w)
- root.putChild("vdrive",
- static.Data("sorry, still initializing", "text/plain"))
- self.site = site = appserver.NevowSite(root)
- s = strports.service(webport, site)
- s.setServiceParent(self)
- self.listener = s # stash it so the tests can query for the portnum
-
- def startService(self):
- service.MultiService.startService(self)
- # to make various services available to render_* methods, we stash a
- # reference to the client on the NevowSite. This will be available by
- # adapting the 'context' argument to a special marker interface named
- # IClient.
- self.site.remember(self.parent, IClient)
- # I thought you could do the same with an existing interface, but
- # apparently 'ISite' does not exist
- #self.site._client = self.parent
-
- def set_root_dirnode(self, dirnode):
- self.root.putChild("vdrive", Directory(dirnode, "/"))
- # I tried doing it this way and for some reason it didn't seem to work
- #print "REMEMBERING", self.site, dl, IDownloader
- #self.site.remember(dl, IDownloader)
-
+def get_downloader_service(ctx):
+ return IClient(ctx).getServiceNamed("downloader")
+def get_uploader_service(ctx):
+ return IClient(ctx).getServiceNamed("uploader")
+def get_vdrive_service(ctx):
+ return IClient(ctx).getServiceNamed("vdrive")
class Welcome(rend.Page):
addSlash = True
ctx.fillSlots("connected", connected)
return ctx.tag
+ # this is a form where users can download files by URI
+
+ def bind_download(self, ctx):
+ uriarg = annotate.Argument("uri",
+ annotate.String("URI of file to download: "))
+ namearg = annotate.Argument("filename",
+ annotate.String("Filename to download as: "))
+ ctxarg = annotate.Argument("ctx", annotate.Context())
+ meth = annotate.Method(arguments=[uriarg, namearg, ctxarg],
+ label="Download File by URI")
+ # buttons always use value=data.label
+ # MethodBindingRenderer uses value=(data.action or data.label)
+ return annotate.MethodBinding("download", meth, action="Download")
+
+ def download(self, uri, filename, ctx):
+ log.msg("webish downloading URI")
+ target = url.here.sibling("download_uri").add("uri", uri)
+ if filename:
+ target = target.add("filename", filename)
+ return target
+
+ def render_forms(self, ctx, data):
+ return webform.renderForms()
+
+
class Directory(rend.Page):
addSlash = True
docFactory = getxmlfile("directory.xhtml")
self._dirnode = dirnode
self._dirname = dirname
- def get_service(self, ctx, name):
- return IClient(ctx).getServiceNamed(name)
-
def childFactory(self, ctx, name):
if name.startswith("freeform"): # ick
return None
- if name == "_download":
- args = inevow.IRequest(ctx).args
- filename = args["filename"][0]
- verifierid = args["verifierid"][0]
- return Downloader(self.get_service(ctx, "downloader"),
- self._dirname, filename, idlib.a2b(verifierid))
if self._dirname == "/":
dirname = "/" + name
else:
dirname = self._dirname + "/" + name
d = self._dirnode.callRemote("get", name)
- d.addCallback(lambda newnode: Directory(newnode, dirname))
+ def _got_child(res):
+ if isinstance(res, str):
+ dl = get_downloader_service(ctx)
+ return Downloader(dl, name, res)
+ return Directory(res, dirname)
+ d.addCallback(_got_child)
return d
def render_title(self, ctx, data):
name, target = data
if isinstance(target, str):
# file
- args = {'verifierid': idlib.b2a(target),
- 'filename': name,
- }
- dlurl = "_download?%s" % urllib.urlencode(args)
- ctx.fillSlots("filename", T.a(href=dlurl)[name])
+ dlurl = urllib.quote(name)
+ ctx.fillSlots("filename",
+ T.a(href=dlurl)[html.escape(name)])
ctx.fillSlots("type", "FILE")
- ctx.fillSlots("fileid", idlib.b2a(target))
+ uri = idlib.b2a(target)
+ dl_uri_url = url.root.child("download_uri").child(uri)
+ # add a filename= query argument to give it a Content-Type
+ dl_uri_url = dl_uri_url.add("filename", name)
+ ctx.fillSlots("fileid", T.a(href=dl_uri_url)[html.escape(uri)])
# this creates a button which will cause our child__delete method
# to be invoked, which deletes the file and then redirects the
ctx.fillSlots("delete", delete)
else:
# directory
- ctx.fillSlots("filename", T.a(href=name)[name])
+ subdir_url = urllib.quote(name)
+ ctx.fillSlots("filename",
+ T.a(href=subdir_url)[html.escape(name)])
ctx.fillSlots("type", "DIR")
ctx.fillSlots("fileid", "-")
ctx.fillSlots("delete", "-")
return ctx.tag
- child_webform_css = webform.defaultCSS
def render_forms(self, ctx, data):
return webform.renderForms()
contentsarg = annotate.Argument("contents", up)
ctxarg = annotate.Argument("ctx", annotate.Context())
- meth = annotate.Method(arguments=[contentsarg, ctxarg])
- return annotate.MethodBinding("upload", meth, action="Upload File")
+ meth = annotate.Method(arguments=[contentsarg, ctxarg],
+ label="Upload File to this directory")
+ return annotate.MethodBinding("upload", meth, action="Upload")
def upload(self, contents, ctx):
# contents is a cgi.FieldStorage instance
log.msg("starting webish upload")
- uploader = self.get_service(ctx, "uploader")
+ uploader = get_uploader_service(ctx)
d = uploader.upload(upload.Data(contents.value))
name = contents.filename
d.addCallback(lambda vid:
"""Make new directory 1"""
namearg = annotate.Argument("name",
annotate.String("New directory name: "))
- meth = annotate.Method(arguments=[namearg])
- return annotate.MethodBinding("mkdir", meth, action="Make Directory")
+ meth = annotate.Method(arguments=[namearg], label="Make New Subdirectory")
+ return annotate.MethodBinding("mkdir", meth, action="Create Directory")
def mkdir(self, name):
"""mkdir2"""
def child__delete(self, ctx):
# perform the delete, then redirect back to the directory page
args = inevow.IRequest(ctx).args
- vdrive = self.get_service(ctx, "vdrive")
+ vdrive = get_vdrive_service(ctx)
d = vdrive.remove(self._dirnode, args["name"][0])
def _deleted(res):
return url.here.up()
self.defaultType)
class Downloader(resource.Resource):
- def __init__(self, downloader, dirname, name, verifierid):
+ def __init__(self, downloader, name, verifierid):
self._downloader = downloader
- self._dirname = dirname
self._name = name
self._verifierid = verifierid
return server.NOT_DONE_YET
+
+class Root(rend.Page):
+ def locateChild(self, ctx, segments):
+ if segments[0] == "download_uri":
+ req = inevow.IRequest(ctx)
+ dl = get_downloader_service(ctx)
+ filename = "unknown_filename"
+ if "filename" in req.args:
+ filename = req.args["filename"][0]
+ if len(segments) > 1:
+ # http://host/download_uri/URIGOESHERE
+ uri_a = segments[1]
+ elif "uri" in req.args:
+ # http://host/download_uri?uri=URIGOESHERE
+ uri_a = req.args["uri"][0]
+ else:
+ return rend.NotFound
+ child = Downloader(dl, filename, idlib.a2b(uri_a))
+ return child, ()
+ return rend.Page.locateChild(self, ctx, segments)
+
+ child_webform_css = webform.defaultCSS
+
+ child_welcome = Welcome()
+
+
+class WebishServer(service.MultiService):
+ name = "webish"
+
+ def __init__(self, webport):
+ service.MultiService.__init__(self)
+ self.root = Root()
+ placeholder = static.Data("sorry, still initializing", "text/plain")
+ self.root.putChild("vdrive", placeholder)
+ self.root.putChild("", url.here.child("welcome"))#Welcome())
+
+ self.site = site = appserver.NevowSite(self.root)
+ s = strports.service(webport, site)
+ s.setServiceParent(self)
+ self.listener = s # stash it so the tests can query for the portnum
+
+ def startService(self):
+ service.MultiService.startService(self)
+ # to make various services available to render_* methods, we stash a
+ # reference to the client on the NevowSite. This will be available by
+ # adapting the 'context' argument to a special marker interface named
+ # IClient.
+ self.site.remember(self.parent, IClient)
+ # I thought you could do the same with an existing interface, but
+ # apparently 'ISite' does not exist
+ #self.site._client = self.parent
+
+ def set_root_dirnode(self, dirnode):
+ self.root.putChild("vdrive", Directory(dirnode, "/"))
+ # I tried doing it this way and for some reason it didn't seem to work
+ #print "REMEMBERING", self.site, dl, IDownloader
+ #self.site.remember(dl, IDownloader)