def delete_screenshot(self, screenshot):
        this_screenshot = model.Screenshot.q().get(screenshot)
        if not this_screenshot:
            abort(404)

        package = this_screenshot.package

        # Make sure the user is allowed to delete the screenshot!
        if not my.authorized_for_screenshot(this_screenshot):
            abort(403, "I'm afraid I can't do that, Dave.")

        # Admins or the one who uploaded the screenshot is allowed to delete
        elif ('username' in session) or (my.client_cookie_hash() is not None and my.client_cookie_hash() == this_screenshot.uploaderhash):
            db.delete(this_screenshot)
            for image_path in this_screenshot.image_paths:
                if os.path.isfile(image_path):
                    os.unlink(image_path)
            my.message('Screenshot for package <em>%s</em> deleted.' % package.name)
        # If the screenshot is 'approved' and the current user is not an admin
        # then it's only possible to mark the screenshot for deletion by an admin.
        else:
            this_screenshot.markedfordelete=True
            this_screenshot.delete_reason=request.params.get('reason','?')[:100]
            my.message('Admins will be asked to delete this screenshot.')

        db.commit()

        # TODO: The approved screenshots have changes. Remove the cached start page.

        # Try to redirect to the backlink (if provided)
        my.redirect_back()

        # Otherwise redirect to the package overview
        redirect(url('package', package=package.name))
    def approve_screenshot(self, screenshot):
        """Approve a screenshot. Sets it to status 'approved'."""
        this_screenshot = model.Screenshot.q().get(screenshot)
        if not this_screenshot:
            abort(404)

        if this_screenshot.approved:
            my.message("Screenshot for package <em>%s</em> already approved." % this_screenshot.package.name)
            my.redirect_back()
            redirect(url('package', package=package.name))

        package = this_screenshot.package

        # Make sure the user is allowed to delete the screenshot!
        # Has this screenshot been uploaded by the current user?
        if not my.authorized_for_screenshot(this_screenshot):
            abort(403, "I'm afraid I can't do that, Dave.")

        old_image_paths = this_screenshot.image_paths
        this_screenshot.approved = True
        new_image_paths = this_screenshot.image_paths

        # sanity check
        assert(len(old_image_paths) == len(new_image_paths))

        try:
            for old_path, new_path in zip(old_image_paths, new_image_paths):
                if not os.path.isdir(this_screenshot.directory):
                    log.debug("Creating new directory %s", this_screenshot.directory)
                    os.makedirs(this_screenshot.directory)
                log.debug("Renaming %s to %s", old_path, new_path)
                os.rename(old_path, new_path)
            db.commit()
        except IOError:
            raise

        my.message("Screenshot for package <em>%s</em> approved." % package.name)

        # The approved screenshots have changes. Remove the cached start page.
        # TODO: cache.remove_value()...
        # (http://wiki.pylonshq.com/display/pylonsdocs/Caching+in+Templates+and+Controllers)
        # (-> Other Cache Options)

        my.redirect_back()
        redirect(url('package', package=package.name))
    def image_by_id(self, id, size):
        """Return an image or None if there is no such image."""
        screenshot = model.Screenshot.q().get(id)

        # Make sure the screenshot database row is available
        if not screenshot:
            log.warn("Requested screenshot #%s which was not found in the database", id)
            return self._image404(size)

        # only show images that are approved (or for admins or owners)
        if not my.authorized_for_screenshot(screenshot):
            log.warn("User is not authorized to access screenshot #%s", id)
            return self._image404(size)

        file_path = screenshot.image_path(size)

        # Make sure the file on disk exists
        if not os.path.isfile(file_path):
            # The file is in the database but not on disk? Remove it from the database then.
            log.error("Screenshot #%s exists in database but is missing on disk at '%s'." % \
                      (screenshot.id, file_path))
            return self._image404(size)

        return self._image_by_path(file_path)