Example #1
0
    def check_blacklist(self, path):
        """
        Check the given path to make sure it isn't blacklisted. If it is
        blacklisted, then raise an :class:`~pants.contrib.web.HTTPException`
        via :func:`~pants.contrib.web.abort`.

        =========  ============
        Argument   Description
        =========  ============
        path       The path to check against the blacklist.
        =========  ============
        """
        for bl in self.blacklist:
            if isinstance(bl, unicode):
                if bl in path:
                    abort(403)
            elif bl.match(path):
                abort(403)
Example #2
0
    def check_blacklist(self, path):
        """
        Check the given path to make sure it isn't blacklisted. If it is
        blacklisted, then raise an :class:`~pants.contrib.web.HTTPException`
        via :func:`~pants.contrib.web.abort`.

        =========  ============
        Argument   Description
        =========  ============
        path       The path to check against the blacklist.
        =========  ============
        """
        for bl in self.blacklist:
            if isinstance(bl, unicode):
                if bl in path:
                    abort(403)
            elif bl.match(path):
                abort(403)
Example #3
0
    def list_directory(self, request, path):
        """
        Generate a directory listing and return it.
        """

        # Normalize the path.
        full_path = os.path.normpath(os.path.join(self.path, path))

        # Get the URL, which is just request.path decoded.
        url = decode(urllib.unquote(request.path))
        if not url.startswith(u'/'):
            url = u'/%s' % url
        if not url.endswith(u'/'):
            return redirect(u'%s/' % url)

        go_up = u''
        if url.strip(u'/'):
            go_up = u'<p><a href="..">Up to Higher Directory</a></p>'

        files = []
        dirs = []

        try:
            contents = os.listdir(full_path)
        except OSError:
            abort(403)

        for p in sorted(contents, key=unicode.lower):
            if _is_hidden(p, full_path):
                continue

            full = os.path.join(full_path, p)
            try:
                fp = full
                if os.path.isdir(full):
                    fp += '/'
                self.check_blacklist(fp)
            except HTTPException:
                continue

            stat = os.stat(full)
            mtime = datetime.fromtimestamp(stat.st_mtime).strftime(
                u'%Y-%m-%d %I:%M:%S %p'
                )

            if os.path.isdir(full):
                cls = u'folder'
                link = u'%s/' % p
                size = u'<span class="faint">Directory</span>'
                obj = dirs

            elif os.path.isfile(full):
                cls = 'document'
                ext = p[p.rfind('.')+1:]
                if ext in ('jpg','jpeg','png','gif','bmp'):
                    cls = 'image'
                elif ext in ('zip','gz','tar','7z','tgz'):
                    cls = 'zip'
                elif ext in ('mp3','mpa','wma','wav','flac','mid','midi','raw',
                        'mod','xm','aac','m4a','ogg','aiff','au','voc','m3u',
                        'pls','asx'):
                    cls = 'audio'
                elif ext in ('mpg','mpeg','mkv','mp4','wmv','avi','mov'):
                    cls = 'video'
                link = p
                size = _human_readable_size(stat.st_size)
                obj = files

            else:
                continue

            obj.append(DIRECTORY_ENTRY.safe_substitute(
                        cls=cls,
                        url=url + link,
                        name=p,
                        size=size,
                        modified=mtime
                        ))

        if files or dirs:
            files = u''.join(dirs) + u''.join(files)
        else:
            files = (u'<tr><td colspan="3" class="noborder">'
                     u'<div class="footer center">'
                     u'This directory is empty.</div></td></tr>')

        if Application.current_app and Application.current_app.debug:
            rtime = u'%0.3f ms' % (1000 * request.time)
        else:
            rtime = u''

        output = DIRECTORY_PAGE.safe_substitute(
                    path=url,
                    go_up=go_up,
                    host=request.host,
                    scheme=request.scheme,
                    content=''.join(files),
                    debug=rtime
                    )

        return output, 200, {'Content-Type': 'text/html; charset=UTF-8'}
Example #4
0
    def __call__(self, request):
        """
        Serve a request.
        """

        try:
            path = request.match.groups()[-1]
            if path is None:
                path = urllib.unquote_plus(request.path)
        except (AttributeError, IndexError):
            path = urllib.unquote_plus(request.path)

        # Convert the path to unicode.
        path = decode(path)

        # Strip off a starting quote.
        if path.startswith('/') or path.startswith('\\'):
            path = path[1:]

        # Normalize the path.
        full_path = os.path.normpath(os.path.join(self.path, path))

        # Validate the request.
        if not full_path.startswith(self.path):
            abort(403)
        elif not os.path.exists(full_path):
            abort()
        elif not os.access(full_path, os.R_OK):
            abort(403)

        # Is this a directory?
        if os.path.isdir(full_path):
            # Check defaults.
            for f in self.defaults:
                full = os.path.join(full_path, f)
                if os.path.exists(full):
                    request.path = urllib.quote(full.encode('utf8'))
                    if hasattr(request, 'match'):
                        del request.match
                    return self.__call__(request)

            # Guess not. List it.
            if hasattr(request, 'match'):
                return self.list_directory(request, path)
            else:
                body, status, headers = self.list_directory(request, path)
                if isinstance(body, unicode):
                    body = body.encode('utf-8')
                headers['Content-Length'] = len(body)
                request.send_status(status)
                request.send_headers(headers)
                request.send(body)
                request.finish()
                return

        # Blacklist Checking.
        self.check_blacklist(full_path)

        # Let's send the file.
        request.auto_finish = False
        request.send_file(full_path)
Example #5
0
    def __call__(self, request):
        """
        Serve a request.
        """

        try:
            path = request.match.group(1)
            if path is None:
                path = urllib.unquote_plus(request.path)
        except (AttributeError, IndexError):
            path = urllib.unquote_plus(request.path)

        # Convert the path to unicode.
        path = decode(path)

        # Strip off a starting quote.
        if path.startswith('/') or path.startswith('\\'):
            path = path[1:]

        # Normalize the path.
        full_path = os.path.normpath(os.path.join(self.path, path))

        # Validate the request.
        if not full_path.startswith(self.path):
            abort(403)
        elif not os.path.exists(full_path):
            abort()
        elif not os.access(full_path, os.R_OK):
            abort(403)

        # Is this a directory?
        if os.path.isdir(full_path):
            # Check defaults.
            for f in self.defaults:
                full = os.path.join(full_path, f)
                if os.path.exists(full):
                    request.path = urllib.quote(full.encode('utf8'))
                    if hasattr(request, 'match'):
                        del request.match
                    return self.__call__(request)

            # Guess not. List it.
            if hasattr(request, 'match'):
                return self.list_directory(request, path)
            else:
                body, status, headers = self.list_directory(request, path)
                if isinstance(body, unicode):
                    body = body.encode('utf-8')
                headers['Content-Length'] = len(body)
                request.send_status(status)
                request.send_headers(headers)
                request.send(body)
                request.finish()
                return

        # Blacklist Checking.
        self.check_blacklist(full_path)

        # Try rendering the content.
        ext = os.path.basename(full_path).rpartition('.')[-1]
        if ext in self.renderers:
            f, mtime, size, type = self.renderers[ext](request, full_path)
        else:
            # Get the information for the actual file.
            f = None
            stat = os.stat(full_path)
            mtime = stat.st_mtime
            size = stat.st_size
            type = mimetypes.guess_type(full_path)[0]

        # If we don't have a type, text/plain it.
        if type is None:
            type = 'text/plain'

        # Generate a bunch of data for headers.
        modified = datetime.fromtimestamp(mtime)
        expires = datetime.utcnow() + timedelta(days=7)

        etag = '"%x-%x"' % (size, int(mtime))

        headers = {
            'Last-Modified' : date(modified),
            'Expires'       : date(expires),
            'Cache-Control' : 'max-age=604800',
            'Content-Type'  : type,
            'Date'          : date(datetime.utcnow()),
            'Server'        : SERVER,
            'Accept-Ranges' : 'bytes',
            'ETag'          : etag
        }

        do304 = False

        if 'If-Modified-Since' in request.headers:
            try:
                since = _parse_date(request.headers['If-Modified-Since'])
            except ValueError:
                since = None
            if since and since >= modified:
                do304 = True

        if 'If-None-Match' in request.headers:
            if etag == request.headers['If-None-Match']:
                do304 = True

        if do304:
            if f:
                f.close()
            request.auto_finish = False
            request.send_status(304)
            request.send_headers(headers)
            request.finish()
            return

        if 'If-Range' in request.headers:
            if etag != request.headers['If-Range'] and \
                    'Range' in request.headers:
                del request.headers['Range']

        last = size - 1
        range = 0, last
        status = 200

        if 'Range' in request.headers:
            if request.headers['Range'].startswith('bytes='):
                try:
                    val = request.headers['Range'][6:].split(',')[0]
                    start, end = val.split('-')
                except ValueError:
                    if f:
                        f.close()
                    abort(416)

                try:
                    if end and not start:
                        end = last
                        start = last - int(end)
                    else:
                        start = int(start or 0)
                        end = int(end or last)

                    if start < 0 or start > end or end > last:
                        if f:
                            f.close()
                        abort(416)
                    range = start, end
                except ValueError:
                    pass
                if range[0] != 0 or range[1] != last:
                    status = 206
                    headers['Content-Range'] = 'bytes %d-%d/%d' % (
                        range[0], range[1], size)

        # Set the content length header.
        if range[0] == range[1]:
            headers['Content-Length'] = 0
        else:
            headers['Content-Length'] = 1 + (range[1] - range[0])

        # Send the headers and status line.
        request.auto_finish = False
        request.send_status(status)
        request.send_headers(headers)

        # Don't send the body if this is head.
        if request.method == 'HEAD':
            if f:
                f.close()
            request.finish()
            return

        # Open the file and send it.
        if range[0] == range[1]:
            if f:
                f.close()
            request.finish()
            return

        if f is None:
            f = open(full_path, 'rb')

        if range[1] != last:
            length = 1 + (range[1] - range[0])
        else:
            length = 0

        request.connection.write_file(f, nbytes=length, offset=range[0])
        request.connection._finished = True
Example #6
0
    def list_directory(self, request, path):
        """
        Generate a directory listing and return it.
        """

        # Normalize the path.
        full_path = os.path.normpath(os.path.join(self.path, path))

        # Get the URL, which is just request.path decoded.
        url = decode(urllib.unquote(request.path))
        if not url.startswith(u'/'):
            url = u'/%s' % url
        if not url.endswith(u'/'):
            return redirect(u'%s/' % url)

        go_up = u''
        if url.strip(u'/'):
            go_up = u'<p><a href="..">Up to Higher Directory</a></p>'

        files = []
        dirs = []

        try:
            contents = os.listdir(full_path)
        except OSError:
            abort(403)

        for p in sorted(contents, key=unicode.lower):
            if _is_hidden(p, full_path):
                continue

            full = os.path.join(full_path, p)
            try:
                fp = full
                if os.path.isdir(full):
                    fp += '/'
                self.check_blacklist(fp)
            except HTTPException:
                continue

            stat = os.stat(full)
            mtime = datetime.fromtimestamp(
                stat.st_mtime).strftime(u'%Y-%m-%d %I:%M:%S %p')

            if os.path.isdir(full):
                cls = u'folder'
                link = u'%s/' % p
                size = u'<span class="faint">Directory</span>'
                obj = dirs

            elif os.path.isfile(full):
                cls = 'document'
                ext = p[p.rfind('.') + 1:]
                if ext in ('jpg', 'jpeg', 'png', 'gif', 'bmp'):
                    cls = 'image'
                elif ext in ('zip', 'gz', 'tar', '7z', 'tgz'):
                    cls = 'zip'
                elif ext in ('mp3', 'mpa', 'wma', 'wav', 'flac', 'mid', 'midi',
                             'raw', 'mod', 'xm', 'aac', 'm4a', 'ogg', 'aiff',
                             'au', 'voc', 'm3u', 'pls', 'asx'):
                    cls = 'audio'
                elif ext in ('mpg', 'mpeg', 'mkv', 'mp4', 'wmv', 'avi', 'mov'):
                    cls = 'video'
                link = p
                size = _human_readable_size(stat.st_size)
                obj = files

            else:
                continue

            obj.append(
                DIRECTORY_ENTRY.safe_substitute(cls=cls,
                                                url=url + link,
                                                name=p,
                                                size=size,
                                                modified=mtime))

        if files or dirs:
            files = u''.join(dirs) + u''.join(files)
        else:
            files = (u'<tr><td colspan="3" class="noborder">'
                     u'<div class="footer center">'
                     u'This directory is empty.</div></td></tr>')

        if Application.current_app and Application.current_app.debug:
            rtime = u'%0.3f ms' % (1000 * request.time)
        else:
            rtime = u''

        output = DIRECTORY_PAGE.safe_substitute(path=url,
                                                go_up=go_up,
                                                host=request.host,
                                                scheme=request.scheme,
                                                content=''.join(files),
                                                debug=rtime)

        return output, 200, {'Content-Type': 'text/html; charset=UTF-8'}
Example #7
0
    def __call__(self, request):
        """
        Serve a request.
        """

        try:
            path = request.match.groups()[-1]
            if path is None:
                path = urllib.unquote_plus(request.path)
        except (AttributeError, IndexError):
            path = urllib.unquote_plus(request.path)

        # Convert the path to unicode.
        path = decode(path)

        # Strip off a starting quote.
        if path.startswith('/') or path.startswith('\\'):
            path = path[1:]

        # Normalize the path.
        full_path = os.path.normpath(os.path.join(self.path, path))

        # Validate the request.
        if not full_path.startswith(self.path):
            abort(403)
        elif not os.path.exists(full_path):
            abort()
        elif not os.access(full_path, os.R_OK):
            abort(403)

        # Is this a directory?
        if os.path.isdir(full_path):
            # Check defaults.
            for f in self.defaults:
                full = os.path.join(full_path, f)
                if os.path.exists(full):
                    request.path = urllib.quote(full.encode('utf8'))
                    if hasattr(request, 'match'):
                        del request.match
                    return self.__call__(request)

            # Guess not. List it.
            if hasattr(request, 'match'):
                return self.list_directory(request, path)
            else:
                body, status, headers = self.list_directory(request, path)
                if isinstance(body, unicode):
                    body = body.encode('utf-8')
                headers['Content-Length'] = len(body)
                request.send_status(status)
                request.send_headers(headers)
                request.send(body)
                request.finish()
                return

        # Blacklist Checking.
        self.check_blacklist(full_path)

        # Let's send the file.
        request.auto_finish = False
        request.send_file(full_path)