From 63f3079c0a788e057963278036a1caa5d642e0cc Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 12 Apr 2019 19:07:26 +0200 Subject: [PATCH 1/3] utils: add a same_origin(url1, url2) helper (#32239) --- combo/utils/urls.py | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/combo/utils/urls.py b/combo/utils/urls.py index 57e67be..7d0c439 100644 --- a/combo/utils/urls.py +++ b/combo/utils/urls.py @@ -20,6 +20,7 @@ from django.conf import settings from django.utils.encoding import force_text from django.template import Context, Template, TemplateSyntaxError, VariableDoesNotExist from django.utils.http import quote +from django.utils.six.moves.urllib import parse as urlparse class TemplateError(Exception): @@ -62,3 +63,49 @@ def get_templated_url(url, context=None): raise TemplateError('unknown variable %s', varname) return force_text(template_vars[varname]) return re.sub(r'(\[.+?\])', repl, url) + +PROTOCOLS_TO_PORT = { + 'http': '80', + 'https': '443', +} + + +def same_domain(domain1, domain2): + if domain1 == domain2: + return True + + if not domain1 or not domain2: + return False + + if domain2.startswith('.'): + # p1 is a sub-domain or the base domain + if domain1.endswith(domain2) or domain1 == domain2[1:]: + return True + return False + + +def same_origin(url1, url2): + '''Checks if both URL use the same domain. It understands domain patterns on url2, i.e. .example.com + matches www.example.com. + + If not scheme is given in url2, scheme compare is skipped. + If not scheme and not port are given, port compare is skipped. + The last two rules allow authorizing complete domains easily. + ''' + p1, p2 = urlparse.urlparse(url1), urlparse.urlparse(url2) + + if p2.scheme and p1.scheme != p2.scheme: + return False + + if not same_domain(p1.hostname, p2.hostname): + return False + + try: + if (p2.port or (p1.port and p2.scheme)) and ( + (p1.port or PROTOCOLS_TO_PORT[p1.scheme]) + != (p2.port or PROTOCOLS_TO_PORT[p2.scheme])): + return False + except (ValueError, KeyError): + return False + + return True -- 2.20.1