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
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
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 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', ])
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']])
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', ])
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")), ]