forked from orbit-oss/flask
Add safe_join: returns the filename used by send_from_directory.
Signed-off-by: Armin Ronacher <armin.ronacher@active-4.com>
This commit is contained in:
parent
0e4cd2e651
commit
7ed3196e8d
3 changed files with 30 additions and 8 deletions
|
|
@ -244,6 +244,8 @@ Useful Functions and Classes
|
||||||
|
|
||||||
.. autofunction:: send_from_directory
|
.. autofunction:: send_from_directory
|
||||||
|
|
||||||
|
.. autofunction:: safe_join
|
||||||
|
|
||||||
.. autofunction:: escape
|
.. autofunction:: escape
|
||||||
|
|
||||||
.. autoclass:: Markup
|
.. autoclass:: Markup
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ from .app import Flask, Request, Response
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .helpers import url_for, jsonify, json_available, flash, \
|
from .helpers import url_for, jsonify, json_available, flash, \
|
||||||
send_file, send_from_directory, get_flashed_messages, \
|
send_file, send_from_directory, get_flashed_messages, \
|
||||||
get_template_attribute, make_response
|
get_template_attribute, make_response, safe_join
|
||||||
from .globals import current_app, g, request, session, _request_ctx_stack
|
from .globals import current_app, g, request, session, _request_ctx_stack
|
||||||
from .ctx import has_request_context
|
from .ctx import has_request_context
|
||||||
from .module import Module
|
from .module import Module
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,32 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
def safe_join(directory, filename):
|
||||||
|
"""Safely join `directory` and `filename`.
|
||||||
|
|
||||||
|
:param directory: the base directory.
|
||||||
|
:param filename: the untrusted filename relative to that directory.
|
||||||
|
:raises: :class:`~werkzeug.exceptions.NotFound` if the retsulting path
|
||||||
|
would fall out of `directory`.
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
@app.route('/wiki/<path:filename>')
|
||||||
|
def wiki_page(filename):
|
||||||
|
filename = safe_join(app.config['WIKI_FOLDER'], filename)
|
||||||
|
with open(filename, 'rb') as fd:
|
||||||
|
content = fd.read() # Read and process the file content...
|
||||||
|
|
||||||
|
"""
|
||||||
|
filename = posixpath.normpath(filename)
|
||||||
|
for sep in _os_alt_seps:
|
||||||
|
if sep in filename:
|
||||||
|
raise NotFound()
|
||||||
|
if os.path.isabs(filename) or filename.startswith('../'):
|
||||||
|
raise NotFound()
|
||||||
|
return os.path.join(directory, filename)
|
||||||
|
|
||||||
|
|
||||||
def send_from_directory(directory, filename, **options):
|
def send_from_directory(directory, filename, **options):
|
||||||
"""Send a file from a given directory with :func:`send_file`. This
|
"""Send a file from a given directory with :func:`send_file`. This
|
||||||
is a secure way to quickly expose static files from an upload folder
|
is a secure way to quickly expose static files from an upload folder
|
||||||
|
|
@ -415,13 +441,7 @@ def send_from_directory(directory, filename, **options):
|
||||||
:param options: optional keyword arguments that are directly
|
:param options: optional keyword arguments that are directly
|
||||||
forwarded to :func:`send_file`.
|
forwarded to :func:`send_file`.
|
||||||
"""
|
"""
|
||||||
filename = posixpath.normpath(filename)
|
filename = safe_join(directory, filename)
|
||||||
for sep in _os_alt_seps:
|
|
||||||
if sep in filename:
|
|
||||||
raise NotFound()
|
|
||||||
if os.path.isabs(filename) or filename.startswith('../'):
|
|
||||||
raise NotFound()
|
|
||||||
filename = os.path.join(directory, filename)
|
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
raise NotFound()
|
raise NotFound()
|
||||||
return send_file(filename, conditional=True, **options)
|
return send_file(filename, conditional=True, **options)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue