]> git.ipfire.org Git - people/jschlag/pbs.git/commitdiff
Make it possible to download files from the packages.
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 3 Dec 2012 21:45:28 +0000 (22:45 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 3 Dec 2012 21:45:28 +0000 (22:45 +0100)
backend/constants.py
backend/packages.py
data/templates/modules/packages-files-table.html
web/__init__.py
web/handlers_packages.py

index 54b549ab2ff51e058c3c2eee3bac8a1305988190..88ff0bd6457bf31d3881ce0bfabc3ec0188a2854 100644 (file)
@@ -19,6 +19,25 @@ BUFFER_SIZE = 1024 * 100 # 100kb
 BUGZILLA_PATTERN = r"(bug\s?|#)(\d+)"
 CVE_PATTERN = r"(CVE)(\s|\-)(\d{4}\-\d{4})"
 
+FILE_EXTENSIONS_VIEWABLE = (
+       ".c",
+       ".cfg",
+       ".conf",
+       ".config",
+       ".h",
+       ".nm",
+       ".patch",
+       ".pl",
+       ".pm",
+       ".py",
+       ".S",
+       ".s",
+       ".sh",
+       ".txt",
+       "Kconfig",
+       "Makefile",
+)
+
 N_ = lambda x: x
 
 MSG_BUILD_FAILED_SUBJECT = N_("[%(build_name)s] Build job failed.")
index 68058ebb7df103460d6d5353c819703b783bcd30..d2f9ca19cba0374c56146d01a0cf506375bbacb5 100644 (file)
@@ -477,15 +477,19 @@ class Package(base.Object):
        @property
        def filelist(self):
                if self._filelist is None:
-                       self._filelist = \
-                               self.db.query("SELECT * FROM filelists WHERE pkg_id = %s ORDER BY name",
-                                       self.id)
+                       self._filelist = []
+
+                       for f in self.db.query("SELECT * FROM filelists WHERE pkg_id = %s ORDER BY name", self.id):
+                               f = File(self.pakfire, f)
+                               self._filelist.append(f)
 
                return self._filelist
 
        def get_file(self):
-               if os.path.exists(self.path):
-                       return pakfire.packages.open(self.path)
+               path = os.path.join(PACKAGES_DIR, self.path)
+
+               if os.path.exists(path):
+                       return pakfire.packages.open(None, None, path)
 
        ## properties
 
@@ -515,9 +519,35 @@ class Package(base.Object):
                return self.properties.get("critical_path", "N") == "Y"
 
 
+class File(base.Object):
+       def __init__(self, pakfire, data):
+               base.Object.__init__(self, pakfire)
+
+               self.data = data
+
+       def __getattr__(self, attr):
+               try:
+                       return self.data[attr]
+               except KeyError:
+                       raise AttributeError, attr
+
+       @property
+       def downloadable(self):
+               # All regular files are downloadable.
+               return self.type == 0
+
+       @property
+       def viewable(self):
+               for ext in FILE_EXTENSIONS_VIEWABLE:
+                       if self.name.endswith(ext):
+                               return True
+
+               return False
+
+
 # XXX DEAD CODE
 
-class File(base.Object):
+class __File(base.Object):
        def __init__(self, pakfire, path):
                base.Object.__init__(self, pakfire)
 
index 3b9cfb0e98c40ee3b7fa30dc80828b08d1d5ed62..58de689d423a639a6ca897a0a7f021cce765f2a6 100644 (file)
                                        {{ file.name }}
                                </td>
                                <td>
-                                       <div class="btn-toolbar">
-                                               <div class="btn-group">
-                                                       <a class="btn btn-mini" href="#">V</a>
-                                                       <a class="btn btn-mini" href="#">D</a>
-                                               </div>
+                                       <div class="btn-group">
+                                               {% if file.viewable %}
+                                                       <a class="btn btn-mini" href="#">
+                                                               <i class="icon-file"></i>
+                                                       </a>
+                                               {% end %}
+                                               {% if file.downloadable %}
+                                                       <a class="btn btn-mini" href="/package/{{ pkg.uuid }}/download{{ file.name }}">
+                                                               <i class="icon-download"></i>
+                                                       </a>
+                                               {% end %}
                                        </div>
                                </td>
                        </tr>
index 71a687539b2864ff62e540e9a212871e21263aac..83f4e3c5bd95587cbb2320df686aa8b770c70663 100644 (file)
@@ -121,6 +121,7 @@ class Application(tornado.web.Application):
                        (r"/package/([\w\-\+]+)/properties", PackagePropertiesHandler),
                        (r"/package/([\w\-\+]+)", PackageNameHandler),
                        (r"/package/([\w\-\+]+)/changelog", PackageChangelogHandler),
+                       (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/download(.*)", PackageFileDownloadHandler),
 
                        # Files
                        (r"/file/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", FileDetailHandler),
index a9321b0c36b8653dc241bda487d2af90197faaca..9883088dacdac23c96035a9b166ae99240921413 100644 (file)
@@ -1,9 +1,13 @@
 #!/usr/bin/python
 
+import mimetypes
+import os.path
 import tornado.web
 
 from handlers_base import BaseHandler
 
+from backend.constants import BUFFER_SIZE
+
 class PackageIDDetailHandler(BaseHandler):
        def get(self, id):
                package = self.packages.get_by_id(id)
@@ -162,3 +166,47 @@ class PackagePropertiesHandler(BaseHandler):
                else:
                        critical_path = False
                build.pkg.update_property("critical_path", critical_path)
+
+
+class PackageFileDownloadHandler(BaseHandler):
+       def get(self, pkg_uuid, filename):
+               # Fetch package.
+               pkg = self.pakfire.packages.get_by_uuid(pkg_uuid)
+               if not pkg:
+                       raise tornado.web.HTTPError(404, "Package not found: %s" % pkg_uuid)
+
+               # Check if the package has got a file with the given name.
+               if not filename in [f.name for f in pkg.filelist]:
+                       raise tornado.web.HTTPError(404, "Package %s does not contain file %s" % (pkg, filename))
+
+               # Open the package in the filesystem.
+               pkg_file = pkg.get_file()
+               if not pkg_file:
+                       raise torando.web.HTTPError(404, "Could not open package %s" % pkg.path)
+
+               # Open the file to transfer it to the client.
+               f = pkg_file.open_file(filename)
+               if not f:
+                       raise tornado.web.HTTPError(404, "Package %s does not contain file %s" % (pkg_file, filename))
+
+               # Send the filename in header.
+               self.set_header("Content-Disposition", "attachment; filename=%s" % os.path.basename(filename))
+
+               # Guess the MIME type of the file.
+               (type, encoding) = mimetypes.guess_type(filename)
+               if not type:
+                       type = "text/plain"
+               self.set_header("Content-Type", type)
+
+               # Transfer the content chunk by chunk.
+               while True:
+                       buf = f.read(BUFFER_SIZE)
+                       if not buf:
+                               break
+
+                       self.write(buf)
+
+               f.close()
+
+               # Done.
+               self.finish()