Skip to content

Commit 948c42a

Browse files
committed
Fix URL redirection from remote source
Fixes #1518
1 parent 849a1b9 commit 948c42a

3 files changed

Lines changed: 25 additions & 5 deletions

File tree

exercise/views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from course.models import CourseModule, StudentModuleGoal, SubmissionTag
2121
from course.viewbase import CourseInstanceBaseView, CourseModuleBaseView, EnrollableViewMixin
2222
from exercise.forms import StudentModuleGoalForm
23-
from lib.helpers import query_dict_to_list_of_tuples, safe_file_name, is_ajax
23+
from lib.helpers import get_redirect_url_from_referer, query_dict_to_list_of_tuples, safe_file_name, is_ajax
2424
from lib.remote_page import RemotePageNotFound, request_for_response
2525
from lib.viewbase import BaseFormView, BaseRedirectMixin, BaseView
2626
from userprofile.models import UserProfile
@@ -62,7 +62,7 @@ def post(self, request, *args, **kwargs):
6262
SubmissionTagging.objects.create(submission=submission, tag=subtag)
6363

6464
# Redirect back to the previous page
65-
return redirect(request.headers.get('referer', '/'))
65+
return redirect(get_redirect_url_from_referer(request))
6666

6767

6868
class SubmissionTaggingRemoveView(CourseInstanceBaseView):
@@ -80,7 +80,7 @@ def post(self, request, *args, **kwargs):
8080
SubmissionTagging.objects.filter(submission=submission, tag=subtag).delete()
8181

8282
# Redirect back to the previous page
83-
return redirect(request.headers.get('referer', '/'))
83+
return redirect(get_redirect_url_from_referer(request))
8484

8585

8686
class ExerciseInfoView(ExerciseBaseView):

lib/helpers.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from django.conf import settings
1212
from django.utils.crypto import get_random_string as django_get_random_string
1313
from django.utils.deprecation import RemovedInNextVersionWarning
14+
from django.utils.http import url_has_allowed_host_and_scheme
1415
from django.utils.translation import get_language
1516

1617

@@ -146,6 +147,25 @@ def build_aplus_url(url: str, user_url: bool = False) -> str:
146147
return urlunparse(parsed)
147148

148149

150+
def get_redirect_url_from_referer(request):
151+
referer = request.headers.get('referer', '/')
152+
if url_has_allowed_host_and_scheme(url=referer, allowed_hosts={request.get_host()}):
153+
parsed = urlparse(referer)
154+
path = parsed.path
155+
if parsed.query:
156+
path += '?' + parsed.query
157+
if parsed.fragment:
158+
path += '#' + parsed.fragment
159+
160+
if path.startswith('//'):
161+
referer = '/'
162+
else:
163+
referer = path
164+
else:
165+
referer = '/'
166+
return referer
167+
168+
149169
FILENAME_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-0123456789"
150170

151171
def safe_file_name(name):

userprofile/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
from authorization.permissions import ACCESS
2626
from course.models import CourseInstance
27-
from lib.helpers import settings_text, remove_query_param_from_url, is_ajax
27+
from lib.helpers import get_redirect_url_from_referer, settings_text, remove_query_param_from_url, is_ajax
2828
from lib.viewbase import BaseView
2929
from userprofile.models import UserProfile
3030
from .viewbase import UserProfileView
@@ -368,4 +368,4 @@ class PseudonymizeView(BaseView):
368368
def get(self, request: HttpRequest) -> HttpResponse:
369369
pseudonymize = request.session.get("pseudonymize", False)
370370
request.session["pseudonymize"] = not pseudonymize
371-
return HttpResponseRedirect(request.headers.get("referer", "/"))
371+
return HttpResponseRedirect(get_redirect_url_from_referer(request))

0 commit comments

Comments
 (0)