예제 #1
0
def submit_view(request):
    try:
        token = request.POST['token']
        current_token = SubmitServiceToken.objects.filter(token=token)
        if not current_token.exists():
            raise PermissionDenied('AUTHORIZATION_FAILED')
        request.user = current_token[0].user
        if not can_enter_contest(request):
            raise PermissionDenied('AUTHORIZATION_FAILED')
        task_name = request.POST['task']
        file_name, file_extension = os.path.splitext(
            request.FILES['file'].name)
        if task_name:
            file_name = task_name
        pi = match_problem(visible_problem_instances(request), file_name)
        if not pi:
            raise SubmitServiceException(
                'NO_SUCH_PROBLEM',
                ', '.join([
                    x.short_name for x in visible_problem_instances(request)
                ]),
            )

        lang_exts = get_allowed_languages_extensions(pi)
        if file_extension[1:] not in lang_exts:
            raise ValueError('UNSUPPORTED_EXTENSION')

        form = SubmissionForm(
            request,
            {
                'problem_instance_id': pi.id,
                'user': request.user,
                'kind': 'NORMAL'
            },
            request.FILES,
        )
        if not form.is_valid():
            raise SubmitServiceException('INVALID_SUBMISSION', form.errors)
        submission = request.contest.controller.create_submission(
            request, pi, form.cleaned_data)
        result_url = reverse(
            'submission',
            kwargs={
                'contest_id': request.contest.id,
                'submission_id': submission.id
            },
        )
        result = {'result_url': result_url, 'submission_id': submission.id}
    except SubmitServiceException as exception_info:
        result = {
            'error_code':
            exception_info.args[0],
            'error_data':
            exception_info.args[1] if len(exception_info.args) == 2 else '',
        }
    except Exception as e:
        result = {'error_code': 'UNKNOWN_ERROR', 'error_data': str(e)}
    return result
예제 #2
0
파일: views.py 프로젝트: sio2project/oioioi
def submit_view(request):
    try:
        token = request.POST['token']
        current_token = SubmitServiceToken.objects.filter(token=token)
        if not current_token.exists():
            raise PermissionDenied('AUTHORIZATION_FAILED')
        request.user = current_token[0].user
        if not can_enter_contest(request):
            raise PermissionDenied('AUTHORIZATION_FAILED')
        task_name = request.POST['task']
        file_name, file_extension = \
            os.path.splitext(request.FILES['file'].name)
        if task_name:
            file_name = task_name
        pi = match_problem(visible_problem_instances(request), file_name)
        if not pi:
            raise SubmitServiceException('NO_SUCH_PROBLEM', ', '.join([
                    x.short_name for x in visible_problem_instances(request)]))

        lang_exts = get_allowed_languages_extensions(pi)
        if file_extension[1:] not in lang_exts:
            raise ValueError('UNSUPPORTED_EXTENSION')

        form = SubmissionForm(request, {
            'problem_instance_id': pi.id,
            'user': request.user,
            'kind': 'NORMAL'
        }, request.FILES)
        if not form.is_valid():
            raise SubmitServiceException('INVALID_SUBMISSION', form.errors)
        submission = request.contest.controller \
            .create_submission(request, pi, form.cleaned_data)
        result_url = reverse('submission',
                             kwargs={'contest_id': request.contest.id,
                                     'submission_id': submission.id})
        result = {'result_url': result_url, 'submission_id': submission.id}
    except SubmitServiceException as exception_info:
        result = {'error_code': exception_info.args[0],
                  'error_data': exception_info.args[1]
                  if len(exception_info.args) == 2 else ''}
    except Exception as e:
        result = {'error_code': 'UNKNOWN_ERROR',
                  'error_data': str(e)}
    return result
예제 #3
0
 def validate_language(file):
     ext = controller.get_extension(file, problem_instance)
     if ext not in get_allowed_languages_extensions(problem_instance):
         raise ValidationError(
             _("Unknown or not supported file extension."))
예제 #4
0
    def adjust_submission_form(self, request, form, problem_instance):
        controller = problem_instance.controller
        size_limit = controller.get_submission_size_limit(problem_instance)

        def validate_file_size(file):
            if file.size > size_limit:
                raise ValidationError(_("File size limit exceeded."))

        def validate_code_length(code):
            if len(code) > size_limit:
                raise ValidationError(_("Code length limit exceeded."))

        def validate_language(file):
            ext = controller.get_extension(file, problem_instance)
            if ext not in get_allowed_languages_extensions(problem_instance):
                raise ValidationError(
                    _("Unknown or not supported file extension."))

        def parse_problem(problem):
            available_problems = form.fields['problem_instance_id'].choices
            problem_id = None
            for (id, name) in available_problems:
                if name.find(problem) != -1:
                    if problem_id is None:
                        problem_id = id
                    else:
                        # matched more than one available problem
                        return None
            return problem_id

        form.fields['file'] = forms.FileField(
            required=False,
            allow_empty_file=False,
            validators=[validate_file_size, validate_language],
            label=_("File"),
            help_text=mark_safe(
                _("Language is determined by the file extension."
                  " It has to be one of: %s."
                  " You can paste the code below instead of"
                  " choosing file."
                  " <strong>Try drag-and-drop too!</strong>") % (', '.join(
                      get_allowed_languages_extensions(problem_instance)))))
        form.fields['code'] = forms.CharField(
            required=False,
            label=_("Code"),
            validators=[validate_code_length],
            widget=forms.widgets.Textarea(attrs={
                'rows': 10,
                'class': 'monospace'
            }))

        self._add_langs_to_form(request, form, problem_instance)

        if 'dropped_solution' in request.POST:
            form.fields['code'].initial = request.POST['dropped_solution']

        # guessing problem name and extension when file dragged and dropped
        if 'dropped_solution_name' in request.POST:
            # do not validate blank fields this time
            form.is_bound = False

            langs_field_name = form_field_id_for_langs(problem_instance)
            fname = request.POST['dropped_solution_name']
            if fname.count('.') == 1:
                [problem, ext] = fname.split('.', 1)
                if 'problem_instance_id' not in request.POST:
                    form.fields['problem_instance_id'].initial = \
                            parse_problem(problem)
                if langs_field_name not in request.POST:
                    form.fields[langs_field_name].initial = \
                            get_language_by_extension(problem_instance, ext)

        form.media.add_js([
            'common/submit_view.js',
        ])
예제 #5
0
    def adjust_submission_form(self, request, form, problem_instance):
        controller = problem_instance.controller
        size_limit = controller.get_submission_size_limit(problem_instance)

        def validate_file_size(file):
            if file.size > size_limit:
                raise ValidationError(_("File size limit exceeded."))

        def validate_code_length(code):
            if len(code) > size_limit:
                raise ValidationError(_("Code length limit exceeded."))

        def validate_language(file):
            ext = controller._get_language(file, problem_instance)
            if ext not in get_allowed_languages_extensions(problem_instance):
                raise ValidationError(_(
                    "Unknown or not supported file extension."))

        def parse_problem(problem):
            available_problems = form.fields['problem_instance_id'].choices
            problem_id = None
            for (id, name) in available_problems:
                if name.find(problem) != -1:
                    if problem_id is None:
                        problem_id = id
                    else:
                        # matched more than one available problem
                        return None
            return problem_id

        form.fields['file'] = forms.FileField(required=False,
                allow_empty_file=False,
                validators=[validate_file_size, validate_language],
                label=_("File"),
                help_text=mark_safe(_(
                    "Language is determined by the file extension."
                    " It has to be one of: %s."
                    " You can paste the code below instead of"
                    " choosing file."
                    " <strong>Try drag-and-drop too!</strong>"
                ) % (', '.join(get_allowed_languages_extensions(
                        problem_instance))))
        )
        form.fields['code'] = forms.CharField(required=False,
                label=_("Code"),
                validators=[validate_code_length],
                widget=forms.widgets.Textarea(attrs={'rows': 10,
                    'class': 'monospace input-xxxlarge'})
        )

        choices = [('', '')]
        choices += [(lang, lang) for lang
                    in problem_instance.controller.get_allowed_languages()]
        form.fields['prog_lang'] = forms.ChoiceField(required=False,
                label=_("Programming language"),
                choices=choices,
                widget=forms.Select(attrs={'disabled': 'disabled'})
        )
        narrow_input_field(form.fields['prog_lang'])

        if 'dropped_solution' in request.POST:
            form.fields['code'].initial = request.POST['dropped_solution']

        # guessing problem name and extension when file dragged and dropped
        if 'dropped_solution_name' in request.POST:
            # do not validate blank fields this time
            form.is_bound = False

            fname = request.POST['dropped_solution_name']
            if fname.count('.') == 1:
                [problem, ext] = fname.split('.', 1)
                if 'problem_instance_id' not in request.POST:
                    form.fields['problem_instance_id'].initial = \
                            parse_problem(problem)
                if 'prog_lang' not in request.POST:
                    form.fields['prog_lang'].initial = \
                            get_language_by_extension(problem_instance, ext)

        if request.contest and is_contest_admin(request):
            form.fields['user'] = UserSelectionField(
                    label=_("User"),
                    hints_url=reverse('contest_user_hints',
                            kwargs={'contest_id': request.contest.id}),
                    initial=request.user)


            def clean_user():
                try:
                    user = form.cleaned_data['user']
                    if user == request.user:
                        return user
                    if not request.user.is_superuser:
                        controller.registration_controller() \
                            .filter_participants(
                                User.objects.filter(pk=user.pk)).get()
                    return user
                except User.DoesNotExist:
                    raise forms.ValidationError(_(
                            "User does not exist or "
                            "you do not have enough privileges"))
            form.clean_user = clean_user
            form.fields['kind'] = forms.ChoiceField(choices=[
                ('NORMAL', _("Normal")), ('IGNORED', _("Ignored"))],
                initial=form.kind, label=_("Kind"))
            narrow_input_fields([form.fields['kind'], form.fields['user']])
예제 #6
0
    def adjust_submission_form(self, request, form, problem_instance):
        controller = problem_instance.controller
        size_limit = controller.get_submission_size_limit(problem_instance)

        def validate_file_size(file):
            if file.size > size_limit:
                raise ValidationError(_("File size limit exceeded."))

        def validate_code_length(code):
            if len(code) > size_limit:
                raise ValidationError(_("Code length limit exceeded."))

        def validate_language(file):
            ext = controller.get_extension(file, problem_instance)
            if ext not in get_allowed_languages_extensions(problem_instance):
                raise ValidationError(
                    _("Unknown or not supported file extension."))

        def parse_problem(problem):
            available_problems = form.fields['problem_instance_id'].choices
            problem_id = None
            for (id, name) in available_problems:
                if name.find(problem) != -1:
                    if problem_id is None:
                        problem_id = id
                    else:
                        # matched more than one available problem
                        return None
            return problem_id

        form.fields['file'] = forms.FileField(
            required=False,
            allow_empty_file=False,
            validators=[validate_file_size, validate_language],
            label=_("File"),
            help_text=mark_safe(
                _("Language is determined by the file extension."
                  " It has to be one of: %s."
                  " You can paste the code below instead of"
                  " choosing file."
                  " <strong>Try drag-and-drop too!</strong>") % (', '.join(
                      get_allowed_languages_extensions(problem_instance)))))
        form.fields['code'] = forms.CharField(
            required=False,
            label=_("Code"),
            validators=[validate_code_length],
            widget=forms.widgets.Textarea(attrs={
                'rows': 10,
                'class': 'monospace input-xxxlarge'
            }))

        choices = [('', '')]
        for lang in controller.get_allowed_languages():
            compiler_name = None
            compiler = controller.get_compiler_for_language(
                problem_instance, lang)
            if compiler is not None:
                available_compilers = getattr(settings, 'AVAILABLE_COMPILERS',
                                              {})
                compilers_for_language = available_compilers.get(lang)
                if compilers_for_language is not None:
                    compiler_info = compilers_for_language.get(compiler)
                    if compiler_info is not None:
                        compiler_name = compiler_info.get('display_name')
            langs = getattr(settings, 'SUBMITTABLE_LANGUAGES', {})
            lang_display = langs[lang]['display_name']
            if compiler_name is not None:
                choices.append(
                    (lang, "%s (%s)" % (lang_display, compiler_name)))
            else:
                choices.append((lang, lang_display))

        form.fields['prog_lang'] = forms.ChoiceField(
            required=False,
            label=_("Programming language"),
            choices=choices,
            widget=forms.Select(attrs={'disabled': 'disabled'}))
        narrow_input_field(form.fields['prog_lang'])

        if 'dropped_solution' in request.POST:
            form.fields['code'].initial = request.POST['dropped_solution']

        # guessing problem name and extension when file dragged and dropped
        if 'dropped_solution_name' in request.POST:
            # do not validate blank fields this time
            form.is_bound = False

            fname = request.POST['dropped_solution_name']
            if fname.count('.') == 1:
                [problem, ext] = fname.split('.', 1)
                if 'problem_instance_id' not in request.POST:
                    form.fields['problem_instance_id'].initial = \
                            parse_problem(problem)
                if 'prog_lang' not in request.POST:
                    form.fields['prog_lang'].initial = \
                            get_language_by_extension(problem_instance, ext)

        form.media.add_js([
            'common/submit_view.js',
        ])
예제 #7
0
    def adjust_submission_form(self, request, form, problem_instance):
        super(TestRunContestControllerMixin, self) \
            .adjust_submission_form(request, form, problem_instance)

        if form.kind != 'TESTRUN':
            return

        def validate_file_size(file):
            if (file.name.upper().endswith(".ZIP") and
                    file.size > self.get_testrun_zipped_input_limit()):
                raise ValidationError(
                    _("Zipped input file size limit exceeded."))
            elif file.size > self.get_testrun_input_limit():
                raise ValidationError(_("Input file size limit exceeded."))

        def validate_zip(file):
            if file.name.upper().endswith(".ZIP"):
                archive = Archive(file, '.zip')
                if len(archive.filenames()) != 1:
                    raise ValidationError(
                        _("Archive should have only 1 file inside.")
                    )
                if (archive.extracted_size()
                        > self.get_testrun_unzipped_input_limit()):
                    raise ValidationError(
                        _("Uncompressed archive is too big to be"
                          " considered safe.")
                    )
                # Extraction is safe, see:
                # https://docs.python.org/2/library/zipfile.html#zipfile.ZipFile.extract
                tmpdir = tempfile.mkdtemp()
                try:
                    # The simplest way to check validity
                    # All other are kinda lazy and don't check everything
                    archive.extract(tmpdir)
                # Zipfile has some undocumented exception types, we shouldn't
                # rely on those, thus we better catch all
                except Exception:
                    raise ValidationError(_("Archive seems to be corrupted."))
                finally:
                    shutil.rmtree(tmpdir)

        form.fields['input'] = forms.FileField(
            allow_empty_file=True,
            validators=[validate_file_size, validate_zip],
            label=_("Input"),
            help_text=mark_safe(
                _(
                    "Maximum input size is"
                    " <strong>%(input_size)d KiB</strong> or"
                    " <strong>%(zipped_size)d KiB</strong> zipped."
                    " Keep in mind that this feature does not provide"
                    " any validation of your input or output."
                ) % {
                    "input_size": self.get_testrun_input_limit() / 1024,
                    "zipped_size": self.get_testrun_zipped_input_limit() / 1024
                }
            )
        )

        form.fields['file'].help_text = _("Language is determined by the file"
                " extension. The following are recognized: %s, but allowed"
                " languages may vary. You can paste the code below instead of"
                " choosing file.") % (', '.join(
                    get_allowed_languages_extensions(problem_instance)))

        if 'kind' in form.fields:
            form.fields['kind'].choices = [('TESTRUN', _("Test run")), ]