diff --git a/exercise/views.py b/exercise/views.py index 8da11f39e..d64396ef0 100644 --- a/exercise/views.py +++ b/exercise/views.py @@ -20,7 +20,7 @@ from course.models import CourseModule, StudentModuleGoal, SubmissionTag from course.viewbase import CourseInstanceBaseView, CourseModuleBaseView, EnrollableViewMixin from exercise.forms import StudentModuleGoalForm -from lib.helpers import query_dict_to_list_of_tuples, safe_file_name, is_ajax +from lib.helpers import get_redirect_url_from_referer, query_dict_to_list_of_tuples, safe_file_name, is_ajax from lib.remote_page import RemotePageNotFound, request_for_response from lib.viewbase import BaseFormView, BaseRedirectMixin, BaseView from userprofile.models import UserProfile @@ -62,7 +62,7 @@ def post(self, request, *args, **kwargs): SubmissionTagging.objects.create(submission=submission, tag=subtag) # Redirect back to the previous page - return redirect(request.headers.get('referer', '/')) + return redirect(get_redirect_url_from_referer(request)) class SubmissionTaggingRemoveView(CourseInstanceBaseView): @@ -80,7 +80,7 @@ def post(self, request, *args, **kwargs): SubmissionTagging.objects.filter(submission=submission, tag=subtag).delete() # Redirect back to the previous page - return redirect(request.headers.get('referer', '/')) + return redirect(get_redirect_url_from_referer(request)) class ExerciseInfoView(ExerciseBaseView): diff --git a/lib/helpers.py b/lib/helpers.py index b46869a71..abbd80130 100644 --- a/lib/helpers.py +++ b/lib/helpers.py @@ -11,6 +11,7 @@ from django.conf import settings from django.utils.crypto import get_random_string as django_get_random_string from django.utils.deprecation import RemovedInNextVersionWarning +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.translation import get_language @@ -146,6 +147,25 @@ def build_aplus_url(url: str, user_url: bool = False) -> str: return urlunparse(parsed) +def get_redirect_url_from_referer(request): + referer = request.headers.get('referer', '/') + if url_has_allowed_host_and_scheme(url=referer, allowed_hosts={request.get_host()}): + parsed = urlparse(referer) + path = parsed.path + if parsed.query: + path += '?' + parsed.query + if parsed.fragment: + path += '#' + parsed.fragment + + if path.startswith('//'): + referer = '/' + else: + referer = path + else: + referer = '/' + return referer + + FILENAME_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-0123456789" def safe_file_name(name): diff --git a/userprofile/views.py b/userprofile/views.py index 60f4dbdac..125100f3e 100644 --- a/userprofile/views.py +++ b/userprofile/views.py @@ -24,7 +24,7 @@ from authorization.permissions import ACCESS from course.models import CourseInstance -from lib.helpers import settings_text, remove_query_param_from_url, is_ajax +from lib.helpers import get_redirect_url_from_referer, settings_text, remove_query_param_from_url, is_ajax from lib.viewbase import BaseView from userprofile.models import UserProfile from .viewbase import UserProfileView @@ -368,4 +368,4 @@ class PseudonymizeView(BaseView): def get(self, request: HttpRequest) -> HttpResponse: pseudonymize = request.session.get("pseudonymize", False) request.session["pseudonymize"] = not pseudonymize - return HttpResponseRedirect(request.headers.get("referer", "/")) + return HttpResponseRedirect(get_redirect_url_from_referer(request))