def send_file(name,
              path_or_fd,
              mimetype,
              last_modified=None,
              no_cache=True,
              inline=None,
              conditional=False,
              safe=True):
    """Sends a file to the user.

    `name` is required and should be the filename visible to the user.
    `path_or_fd` is either the physical path to the file or a file-like object (e.g. a StringIO).
    `mimetype` SHOULD be a proper MIME type such as image/png. It may also be an snms-style file type such as JPG.
    `last_modified` may contain a unix timestamp or datetime object indicating the last modification of the file.
    `no_cache` can be set to False to disable no-cache headers.
    `inline` defaults to true except for certain filetypes like XML and CSV. It SHOULD be set to false only when you
    want to force the user's browser to download the file. Usually it is much nicer if e.g. a PDF file can be displayed
    inline so don't disable it unless really necessary.
    `conditional` is very useful when sending static files such as CSS/JS/images. It will allow the browser to retrieve
    the file only if it has been modified (based on mtime and size).
    `safe` adds some basic security features such a adding a content-security-policy and forcing inline=False for
    text/html mimetypes
    """

    name = secure_filename(name)
    assert '/' in mimetype
    if inline is None:
        inline = mimetype not in ('text/csv', 'text/xml', 'application/xml')
    if request.user_agent.platform == 'android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if safe and mimetype in ('text/html', 'image/svg+xml'):
        inline = False
    try:
        rv = _send_file(path_or_fd,
                        mimetype=mimetype,
                        as_attachment=not inline,
                        attachment_filename=name,
                        conditional=conditional)
    except IOError:
        if not current_app.debug:
            raise
        raise NotFound('File not found: %s' % path_or_fd)
    if safe:
        rv.headers.add('Content-Security-Policy',
                       "script-src 'self'; object-src 'self'")
    if inline:
        # send_file does not add this header if as_attachment is False
        rv.headers.add('Content-Disposition', 'inline', filename=name)
    if last_modified:
        if not isinstance(last_modified, int):
            last_modified = int(time.mktime(last_modified.timetuple()))
        rv.last_modified = last_modified
    if no_cache:
        del rv.expires
        del rv.cache_control.max_age
        rv.cache_control.public = False
        rv.cache_control.private = True
        rv.cache_control.no_cache = True
    return rv
예제 #2
0
파일: util.py 프로젝트: javfg/indico
def send_file(name,
              path_or_fd,
              mimetype,
              last_modified=None,
              no_cache=True,
              inline=None,
              conditional=False,
              safe=True,
              **kwargs):
    """Send a file to the user.

    `name` is required and should be the filename visible to the user.
    `path_or_fd` is either the physical path to the file or a file-like object (e.g. a StringIO).
    `mimetype` SHOULD be a proper MIME type such as image/png. It may also be an indico-style file type such as JPG.
    `last_modified` may contain a unix timestamp or datetime object indicating the last modification of the file.
    `no_cache` can be set to False to disable no-cache headers. Setting `conditional` to `True` overrides it (`False`).
    `inline` defaults to true except for certain filetypes like XML and CSV. It SHOULD be set to false only when you
    want to force the user's browser to download the file. Usually it is much nicer if e.g. a PDF file can be displayed
    inline so don't disable it unless really necessary.
    `conditional` is very useful when sending static files such as CSS/JS/images. It will allow the browser to retrieve
    the file only if it has been modified (based on mtime and size). Setting it will override `no_cache`.
    `safe` adds some basic security features such a adding a content-security-policy and forcing inline=False for
    text/html mimetypes
    """

    name = re.sub(r'\s+', ' ', name).strip()  # get rid of crap like linebreaks
    assert '/' in mimetype
    if inline is None:
        inline = mimetype not in ('text/csv', 'text/xml', 'application/xml')
    if request.user_agent.platform == 'Android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if _is_office_mimetype(mimetype):
        inline = False
    if safe and mimetype in ('text/html', 'image/svg+xml'):
        inline = False
    try:
        rv = _send_file(path_or_fd,
                        mimetype=mimetype,
                        as_attachment=(not inline),
                        download_name=name,
                        conditional=conditional,
                        last_modified=last_modified,
                        **kwargs)
    except OSError:
        if not current_app.debug:
            raise
        raise NotFound('File not found: %s' % path_or_fd)
    if safe:
        rv.headers.add('Content-Security-Policy',
                       "script-src 'self'; object-src 'self'")
    # if the request is conditional, then caching shouldn't be disabled
    if not conditional and no_cache:
        del rv.expires
        del rv.cache_control.max_age
        rv.cache_control.public = False
        rv.cache_control.private = True
        rv.cache_control.no_cache = True
    return rv
예제 #3
0
def send_file(name,
              path_or_fd,
              mimetype,
              last_modified=None,
              no_cache=True,
              inline=True,
              conditional=False):
    """Sends a file to the user.

    `name` is required and should be the filename visible to the user.
    `path_or_fd` is either the physical path to the file or a file-like object (e.g. a StringIO).
    `mimetype` SHOULD be a proper MIME type such as image/png. It may also be an indico-style file type such as JPG.
    `last_modified` may contain a unix timestamp or datetime object indicating the last modification of the file.
    `no_cache` can be set to False to disable no-cache headers.
    `inline` SHOULD be set to false only when you want to force the user's browser to download the file. Usually it is
    much nicer if e.g. a PDF file can be displayed inline so don't disable it unless really necessary.
    `conditional` is very useful when sending static files such as CSS/JS/images. It will allow the browser to retrieve
    the file only if it has been modified (based on mtime and size).
    """

    name = secure_filename(name)
    if request.user_agent.platform == 'android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if mimetype.isupper() and '/' not in mimetype:
        # Indico file type such as "JPG" or "CSV"
        from indico.core.config import Config
        mimetype = Config.getInstance().getFileTypeMimeType(mimetype)
    if _is_office_mimetype(mimetype):
        inline = False
    try:
        rv = _send_file(path_or_fd,
                        mimetype=mimetype,
                        as_attachment=not inline,
                        attachment_filename=name,
                        conditional=conditional)
    except IOError:
        from MaKaC.common.info import HelperMaKaCInfo
        if not app.debug:
            raise
        raise NotFound('File not found: %s' % path_or_fd)
    if inline:
        # send_file does not add this header if as_attachment is False
        rv.headers.add('Content-Disposition', 'inline', filename=name)
    if last_modified:
        if not isinstance(last_modified, int):
            last_modified = int(time.mktime(last_modified.timetuple()))
        rv.last_modified = last_modified
    if no_cache:
        del rv.expires
        del rv.cache_control.max_age
        rv.cache_control.public = False
        rv.cache_control.private = True
        rv.cache_control.no_cache = True
    return rv
예제 #4
0
def send_file(name, path_or_fd, mimetype, last_modified=None, no_cache=True, inline=None, conditional=False, safe=True):
    """Sends a file to the user.

    `name` is required and should be the filename visible to the user.
    `path_or_fd` is either the physical path to the file or a file-like object (e.g. a StringIO).
    `mimetype` SHOULD be a proper MIME type such as image/png. It may also be an indico-style file type such as JPG.
    `last_modified` may contain a unix timestamp or datetime object indicating the last modification of the file.
    `no_cache` can be set to False to disable no-cache headers.
    `inline` defaults to true except for certain filetypes like XML and CSV. It SHOULD be set to false only when you
    want to force the user's browser to download the file. Usually it is much nicer if e.g. a PDF file can be displayed
    inline so don't disable it unless really necessary.
    `conditional` is very useful when sending static files such as CSS/JS/images. It will allow the browser to retrieve
    the file only if it has been modified (based on mtime and size).
    `safe` adds some basic security features such a adding a content-security-policy and forcing inline=False for
    text/html mimetypes
    """

    name = secure_filename(name, 'file')
    if inline is None:
        inline = mimetype not in ('XML', 'CSV')
    if request.user_agent.platform == 'android':
        # Android is just full of fail when it comes to inline content-disposition...
        inline = False
    if mimetype.isupper() and '/' not in mimetype:
        # Indico file type such as "JPG" or "CSV"
        from indico.core.config import Config
        mimetype = Config.getInstance().getFileTypeMimeType(mimetype)
    if _is_office_mimetype(mimetype):
        inline = False
    if safe and mimetype in ('text/html', 'image/svg+xml'):
        inline = False
    try:
        rv = _send_file(path_or_fd, mimetype=mimetype, as_attachment=not inline, attachment_filename=name,
                        conditional=conditional)
    except IOError:
        from MaKaC.common.info import HelperMaKaCInfo
        if not app.debug:
            raise
        raise NotFound('File not found: %s' % path_or_fd)
    if safe:
        rv.headers.add('Content-Security-Policy', "script-src 'self'; object-src 'self'")
    if inline:
        # send_file does not add this header if as_attachment is False
        rv.headers.add('Content-Disposition', 'inline', filename=name)
    if last_modified:
        if not isinstance(last_modified, int):
            last_modified = int(time.mktime(last_modified.timetuple()))
        rv.last_modified = last_modified
    if no_cache:
        del rv.expires
        del rv.cache_control.max_age
        rv.cache_control.public = False
        rv.cache_control.private = True
        rv.cache_control.no_cache = True
    return rv
예제 #5
0
 def wrapper(filepath, plugin=None):
     path = obj.calculatePath(filepath, plugin=plugin)
     if not os.path.isfile(path):
         raise NotFound
     return _send_file(path)
예제 #6
0
def send_file(filename):
    return _send_file(os.path.join('webroot', filename))
예제 #7
0
def send_file(file, *args, **kwargs):
    kwargs.setdefault('mimetype', mimetypes.guess_type(file.name)[0])

    return _send_file(BytesIO(base64.b64decode(file.properties['data'])), *args, **kwargs)
예제 #8
0
 def wrapper(filepath, plugin=None):
     path = obj.calculatePath(filepath, plugin=plugin)
     if not os.path.isfile(path):
         raise NotFound
     return _send_file(path)