~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/controllers/download_ui.py

  • Committer: Matt Nordhoff
  • Date: 2009-05-02 14:01:05 UTC
  • Revision ID: mnordhoff@mattnordhoff.com-20090502140105-m07dxhtzfgsgu2ia
Make sure to close mkstemp's file descriptor (bug #370845)

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import logging
21
21
import mimetypes
22
 
import os
 
22
import time
23
23
import urllib
24
24
 
25
25
from paste import httpexceptions
26
26
from paste.request import path_info_pop
27
27
 
28
28
from loggerhead.controllers import TemplatedBranchView
29
 
from loggerhead.exporter import export_archive
30
29
 
31
30
log = logging.getLogger("loggerhead.controllers")
32
31
 
33
32
 
34
33
class DownloadUI (TemplatedBranchView):
35
34
 
36
 
    def encode_filename(self, filename):
37
 
 
38
 
        return urllib.quote(filename.encode('utf-8'))
39
 
 
40
 
    def get_args(self, environ):
 
35
    def __call__(self, environ, start_response):
 
36
        # /download/<rev_id>/<file_id>/[filename]
 
37
        z = time.time()
 
38
 
 
39
        h = self._history
 
40
 
41
41
        args = []
42
 
        while True:
 
42
        while 1:
43
43
            arg = path_info_pop(environ)
44
44
            if arg is None:
45
45
                break
46
46
            args.append(arg)
47
 
        return args
48
47
 
49
 
    def __call__(self, environ, start_response):
50
 
        # /download/<rev_id>/<file_id>/[filename]
51
 
        h = self._history
52
 
        args = self.get_args(environ)
53
48
        if len(args) < 2:
54
 
            raise httpexceptions.HTTPMovedPermanently(
55
 
                self._branch.absolute_url('/changes'))
 
49
            raise httpexceptions.HTTPMovedPermanently(self._branch.url(
 
50
                      '../changes'))
 
51
 
56
52
        revid = h.fix_revid(args[0])
57
53
        file_id = args[1]
58
54
        path, filename, content = h.get_file(file_id, revid)
59
55
        mime_type, encoding = mimetypes.guess_type(filename)
60
56
        if mime_type is None:
61
57
            mime_type = 'application/octet-stream'
 
58
 
62
59
        self.log.info('/download %s @ %s (%d bytes)',
63
60
                      path,
64
61
                      h.get_revno(revid),
65
62
                      len(content))
66
 
        encoded_filename = self.encode_filename(filename)
 
63
        encoded_filename = urllib.quote(filename.encode('utf-8'))
67
64
        headers = [
68
65
            ('Content-Type', mime_type),
69
 
            ('Content-Length', str(len(content))),
 
66
            ('Content-Length', len(content)),
70
67
            ('Content-Disposition',
71
 
             "attachment; filename*=utf-8''%s" % (encoded_filename,)),
 
68
             'attachment; filename*=utf-8\'\'%s' % encoded_filename),
72
69
            ]
73
70
        start_response('200 OK', headers)
74
71
        return [content]
75
 
 
76
 
 
77
 
class DownloadTarballUI(DownloadUI):
78
 
 
79
 
    def __call__(self, environ, start_response):
80
 
        """Stream a tarball from a bazaar branch."""
81
 
        # Tried to re-use code from downloadui, not very successful
82
 
        if not self._branch.export_tarballs:
83
 
            raise httpexceptions.HTTPForbidden(
84
 
                "Tarball downloads are not allowed")
85
 
        archive_format = "tgz"
86
 
        history = self._history
87
 
        self.args = self.get_args(environ)
88
 
        if len(self.args):
89
 
            revid = history.fix_revid(self.args[0])
90
 
            version_part = '-r' + self.args[0]
91
 
        else:
92
 
            revid = self.get_revid()
93
 
            version_part = ''
94
 
        # XXX: Perhaps some better suggestion based on the URL or path?
95
 
        #
96
 
        # TODO: Perhaps set the tarball suggested mtime to the revision
97
 
        # mtime.
98
 
        root = self._branch.friendly_name or 'branch'
99
 
        encoded_filename = self.encode_filename(
100
 
            root + version_part + '.' + archive_format)
101
 
        headers = [
102
 
            ('Content-Type', 'application/octet-stream'),
103
 
            ('Content-Disposition',
104
 
                "attachment; filename*=utf-8''%s" % (encoded_filename,)),
105
 
            ]
106
 
        start_response('200 OK', headers)
107
 
        return export_archive(history, root, revid, archive_format)