From 74820cc3de944ffb9b128c301fbc3e2fb45fb8b8 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 11 Dec 2007 18:04:44 -0700
Subject: [PATCH] webish: append save=true to a GET URL to save-to-disk. Closes
 #222.

---
 src/allmydata/test/test_web.py |  7 +++++++
 src/allmydata/webish.py        | 16 +++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index c3188b48..5299209c 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -344,6 +344,13 @@ class Web(WebMixin, unittest.TestCase):
         d.addCallback(self.failUnlessIsBarDotTxt)
         return d
 
+    def test_GET_FILEURL_save(self):
+        d = self.GET(self.public_url + "/foo/bar.txt?save=bar.txt")
+        # TODO: look at the headers, expect a Content-Disposition: attachment
+        # header.
+        d.addCallback(self.failUnlessIsBarDotTxt)
+        return d
+
     def test_GET_FILEURL_download(self):
         d = self.GET(self.public_url + "/foo/bar.txt?t=download")
         d.addCallback(self.failUnlessIsBarDotTxt)
diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py
index 84aa6ba4..2db720d8 100644
--- a/src/allmydata/webish.py
+++ b/src/allmydata/webish.py
@@ -360,12 +360,13 @@ class Directory(rend.Page):
 
 class WebDownloadTarget:
     implements(IDownloadTarget, IConsumer)
-    def __init__(self, req, content_type, content_encoding):
+    def __init__(self, req, content_type, content_encoding, save_to_file):
         self._req = req
         self._content_type = content_type
         self._content_encoding = content_encoding
         self._opened = False
         self._producer = None
+        self._save_to_file = save_to_file
 
     def registerProducer(self, producer, streaming):
         self._req.registerProducer(producer, streaming)
@@ -378,6 +379,12 @@ class WebDownloadTarget:
         if self._content_encoding:
             self._req.setHeader("content-encoding", self._content_encoding)
         self._req.setHeader("content-length", str(size))
+        if self._save_to_file is not None:
+            # tell the browser to save the file rather display it
+            # TODO: quote save_to_file properly
+            self._req.setHeader("content-disposition",
+                                'attachment; filename="%s"'
+                                % self._save_to_file)
 
     def write(self, data):
         self._req.write(data)
@@ -425,8 +432,11 @@ class FileDownloader(resource.Resource):
                              static.File.contentTypes,
                              static.File.contentEncodings,
                              defaultType="text/plain")
-
-        d = self._filenode.download(WebDownloadTarget(req, type, encoding))
+        save_to_file = None
+        if "save" in req.args:
+            save_to_file = self._name
+        wdt = WebDownloadTarget(req, type, encoding, save_to_file)
+        d = self._filenode.download(wdt)
         # exceptions during download are handled by the WebDownloadTarget
         d.addErrback(lambda why: None)
         return server.NOT_DONE_YET
-- 
2.45.2