|
| 1 | +import logging |
| 2 | +from typing import Tuple |
1 | 3 | from urllib.parse import parse_qs, urlencode, urlparse |
2 | 4 |
|
3 | 5 | from mfr.extensions import settings |
4 | 6 |
|
| 7 | +logger = logging.getLogger(__name__) |
5 | 8 |
|
6 | | -def munge_url_for_localdev(url): |
7 | | - """ |
8 | | - If MFR is being run in a local development environment (i.e. LOCAL_DEVELOPMENT is True), we |
| 9 | + |
| 10 | +def munge_url_for_localdev(url: str) -> Tuple: |
| 11 | + """If MFR is being run in a local development environment (i.e. LOCAL_DEVELOPMENT is True), we |
9 | 12 | need to replace the internal host (the one the backend services communicate on, default: |
10 | 13 | 192.168.168.167) with the external host (the one the user provides, default: "localhost") |
11 | 14 | e.g. http://192.168.168.167:7777/foo/bar => http://localhost:7777/foo/bar |
12 | 15 | """ |
| 16 | + |
13 | 17 | url_obj = urlparse(url) |
14 | | - if (settings.LOCAL_DEVELOPMENT and url_obj.hostname == settings.DOCKER_LOCAL_HOST): |
15 | | - query_dict = parse_qs(url_obj.query, keep_blank_values=True) |
| 18 | + if settings.LOCAL_DEVELOPMENT and url_obj.hostname == settings.DOCKER_LOCAL_HOST: |
| 19 | + query_dict = parse_qs(url_obj.query, keep_blank_values=True) |
16 | 20 |
|
17 | | - # the 'mode' param will break image downloads from the osf |
18 | | - query_dict.pop('mode', None) |
| 21 | + # the 'mode' param will break image downloads from the osf |
| 22 | + query_dict.pop('mode', None) |
19 | 23 |
|
20 | | - url_obj = url_obj._replace( |
21 | | - query=urlencode(query_dict, doseq=True), |
22 | | - netloc='{}:{}'.format(settings.LOCAL_HOST, url_obj.port) |
23 | | - ) |
| 24 | + url_obj = url_obj._replace( |
| 25 | + query=urlencode(query_dict, doseq=True), |
| 26 | + netloc='{}:{}'.format(settings.LOCAL_HOST, url_obj.port) |
| 27 | + ) |
24 | 28 |
|
25 | 29 | return url_obj |
| 30 | + |
| 31 | + |
| 32 | +def escape_url_for_template(url: str, logs: bool=True) -> str: |
| 33 | + """Escape (URL Encode) single and double quote(s) for the given URL. |
| 34 | +
|
| 35 | + Download and export URLs may end up not properly encoded right before they are about to be sent |
| 36 | + to the mako template due to issues including (but not limited to) (1) ``furl`` dropping encoding |
| 37 | + for single quote (2) URL (provided by users or constructed by scripts) not having the correct |
| 38 | + encoding. This helper method must be called for each render request that sends URL to the mako |
| 39 | + template. |
| 40 | +
|
| 41 | + :param str url: the URL to be sent to the mako template |
| 42 | + :param bool logs: whether to enable warnings, default is `True` and is set to `False` for tests |
| 43 | + :return: the properly encoded URL |
| 44 | + """ |
| 45 | + |
| 46 | + safe_url = url.replace('"', '%22').replace("'", '%27') |
| 47 | + if url != safe_url and logs: |
| 48 | + logger.warning('Unsafe URL containing unescaped single (double) quote(s) has been replaced') |
| 49 | + return safe_url |
0 commit comments