diff --git a/judge/bridge/judge_handler.py b/judge/bridge/judge_handler.py index ed05e8752..cca7b5373 100644 --- a/judge/bridge/judge_handler.py +++ b/judge/bridge/judge_handler.py @@ -3,14 +3,11 @@ import logging import threading import time -import urllib.parse from collections import deque, namedtuple from operator import itemgetter from django import db from django.conf import settings -from django.core.exceptions import ValidationError -from django.core.validators import URLValidator from django.utils import timezone from judge import event_poster as event @@ -18,11 +15,11 @@ from judge.caching import finished_submission from judge.models import Judge, Language, LanguageLimit, Problem, Profile, \ RuntimeVersion, Submission, SubmissionTestCase +from judge.utils.url import get_absolute_submission_file_url logger = logging.getLogger('judge.bridge') json_log = logging.getLogger('judge.json.bridge') -URL_VALIDATOR = URLValidator() UPDATE_RATE_LIMIT = 5 UPDATE_RATE_TIME = 0.5 SubmissionData = namedtuple( @@ -35,20 +32,6 @@ def _ensure_connection(): db.connection.close_if_unusable_or_obsolete() -def get_submission_file_url(source): - """ Get absolute URL to submission file - We cannot simply return domain + source, because - in the future, we might want to serve this by MEDIA_URL - """ - try: - # If source is a valid url, - # it might be serve by a MEDIA_URL - URL_VALIDATOR(source) - return source - except ValidationError: - return urllib.parse.urljoin(settings.SITE_FULL_URL, source) - - class JudgeHandler(ZlibPacketHandler): proxies = proxy_list(settings.BRIDGED_JUDGE_PROXIES or []) @@ -257,7 +240,7 @@ def submit(self, id, problem, language, source): 'submission-id': id, 'problem-id': problem, 'language': language, - 'source': source if not data.file_only else get_submission_file_url(source), + 'source': source if not data.file_only else get_absolute_submission_file_url(source), 'time-limit': data.time, 'memory-limit': data.memory, 'short-circuit': data.short_circuit, diff --git a/judge/models/problem.py b/judge/models/problem.py index 7f8b3a210..51d1b8e2d 100644 --- a/judge/models/problem.py +++ b/judge/models/problem.py @@ -20,6 +20,7 @@ from judge.models.profile import Organization, Profile from judge.models.runtime import Language from judge.user_translations import gettext as user_gettext +from judge.utils.url import get_absolute_pdf_url __all__ = ['ProblemGroup', 'ProblemType', 'Problem', 'ProblemTranslation', 'ProblemClarification', 'License', 'Solution', 'SubmissionSourceAccess', 'TranslatedProblemQuerySet'] @@ -236,6 +237,10 @@ def __init__(self, *args, **kwargs): if 'points' in self.__dict__: self.__original_points = self.points + @property + def absolute_pdf_url(self): + return get_absolute_pdf_url(self.pdf_url) if self.pdf_url else None + @cached_property def types_list(self): return list(map(user_gettext, map(attrgetter('full_name'), self.types.all()))) diff --git a/judge/utils/url.py b/judge/utils/url.py new file mode 100644 index 000000000..934a81cb5 --- /dev/null +++ b/judge/utils/url.py @@ -0,0 +1,23 @@ +import urllib.parse + +from django.conf import settings +from django.core.exceptions import ValidationError +from django.core.validators import URLValidator + +URL_VALIDATOR = URLValidator(schemes=['http', 'https']) + + +def get_absolute_url(url, host): + try: + URL_VALIDATOR(url) + return url + except ValidationError: + return urllib.parse.urljoin(host, url) + + +def get_absolute_submission_file_url(source): + return get_absolute_url(source, settings.SITE_FULL_URL) + + +def get_absolute_pdf_url(pdf_url): + return get_absolute_url(pdf_url, settings.SITE_FULL_URL) diff --git a/templates/problem/problem-detail.html b/templates/problem/problem-detail.html index 5553adafd..9f6ca15b8 100644 --- a/templates/problem/problem-detail.html +++ b/templates/problem/problem-detail.html @@ -1,4 +1,4 @@ -{% with pdf_url=problem.pdf_url %} +{% with pdf_url=problem.absolute_pdf_url %} {% if pdf_url %}

{{ _("In case the statement didn't load correctly, you can download the statement here: ") }}{{ _("Statement") }}