From 4bc95f643628d783c730f719727164986d76d2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20A=2E=20S=C3=A1nchez=20L=C3=B3pez?= Date: Thu, 3 Feb 2011 11:46:04 +0000 Subject: [PATCH] Cutoff dates and basic checkings over the plain file. See #580 - Legacy-Id: 2806 --- ietf/settings.py | 1 + ietf/submit/error_manager.py | 19 ++++++++ ietf/submit/forms.py | 64 ++++++++++++++++++++++++++ ietf/submit/models.py | 42 +++++++++++++++++ ietf/submit/parsers/__init__.py | 0 ietf/submit/parsers/base.py | 43 +++++++++++++++++ ietf/submit/parsers/pdf_parser.py | 7 +++ ietf/submit/parsers/plain_parser.py | 36 +++++++++++++++ ietf/submit/parsers/ps_parser.py | 7 +++ ietf/submit/parsers/xml_parser.py | 7 +++ ietf/submit/views.py | 2 + ietf/templates/submit/submit_base.html | 7 +++ ietf/templates/submit/submitform.html | 2 + 13 files changed, 237 insertions(+) create mode 100644 ietf/submit/error_manager.py create mode 100644 ietf/submit/models.py create mode 100644 ietf/submit/parsers/__init__.py create mode 100644 ietf/submit/parsers/base.py create mode 100644 ietf/submit/parsers/pdf_parser.py create mode 100644 ietf/submit/parsers/plain_parser.py create mode 100644 ietf/submit/parsers/ps_parser.py create mode 100644 ietf/submit/parsers/xml_parser.py diff --git a/ietf/settings.py b/ietf/settings.py index aecc2fb73..be418e92d 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -131,6 +131,7 @@ INSTALLED_APPS = ( 'ietf.redirects', 'ietf.idrfc', 'ietf.wginfo', + 'ietf.submit', ) INTERNAL_IPS = ( diff --git a/ietf/submit/error_manager.py b/ietf/submit/error_manager.py new file mode 100644 index 000000000..b4dcefd8f --- /dev/null +++ b/ietf/submit/error_manager.py @@ -0,0 +1,19 @@ +from ietf.submit.models import IdSubmissionStatus + +class ErrorManager(object): + ERROR_CODES = { + 'DEFAULT': 'Unknow error', + 'INVALID_FILENAME': 111, + 'EXCEEDED_SIZE': 102, + } + + def get_error_str(self, key): + error_code = self.ERROR_CODES.get(key, self.ERROR_CODES['DEFAULT']) + if isinstance(error_code, basestring): + return '%s (%s)' % (key, error_code) + try: + return IdSubmissionStatus.objects.get(status_id=error_code).status_value + except IdSubmissionStatus.DoesNotExist: + return '%s (%s)' % (self.ERROR_CODES['DEFAULT'], key) + +MainErrorManager=ErrorManager() diff --git a/ietf/submit/forms.py b/ietf/submit/forms.py index cee907c41..69acd0573 100644 --- a/ietf/submit/forms.py +++ b/ietf/submit/forms.py @@ -16,6 +16,16 @@ from ietf.liaisons.widgets import (FromWidget, ReadOnlyWidget, ButtonWidget, ShowAttachmentsWidget, RelatedLiaisonWidget) +from ietf.submit.models import IdSubmitDateConfig +from ietf.submit.parsers.plain_parser import PlainParser +from ietf.submit.parsers.pdf_parser import PDFParser +from ietf.submit.parsers.ps_parser import PSParser +from ietf.submit.parsers.xml_parser import XMLParser + + +CUTOFF_HOUR = 17 + + class UploadForm(forms.Form): txt = forms.FileField(label=u'.txt format', required=True) @@ -28,6 +38,35 @@ class UploadForm(forms.Form): class Media: css = {'all': ("/css/liaisons.css", )} + def __init__(self, *args, **kwargs): + super(UploadForm, self).__init__(*args, **kwargs) + self.in_first_cut_off = False + self.shutdown = False + self.read_dates() + + def read_dates(self): + now = datetime.datetime.now() + first_cut_off = IdSubmitDateConfig.get_first_cut_off() + second_cut_off = IdSubmitDateConfig.get_second_cut_off() + ietf_monday = IdSubmitDateConfig.get_ietf_monday() + processed_ids_date = IdSubmitDateConfig.get_processed_ids_date() + monday_after_ietf = IdSubmitDateConfig.get_monday_after_ietf() + list_aproved_date = IdSubmitDateConfig.get_list_aproved_date() + + if now.date() >= first_cut_off and now.date() < second_cut_off: # We are in the first_cut_off + if now.date() == first_cut_off and now.hour < CUTOFF_HOUR: + self.cutoff_warning = 'The pre-meeting cutoff date for new documents (i.e., version -00 Internet-Drafts) is %s at 5 PM (PT). You will not be able to submit a new document after this time until %s, at midnight' % (first_cut_off, ietf_monday) + else: # No 00 version allowed + self.cutoff_warning = 'The pre-meeting cutoff date for new documents (i.e., version -00 Internet-Drafts) was %s at 5 PM (PT). You will not be able to submit a new document until %s, at midnight.
You can still submit a version -01 or higher Internet-Draft until 5 PM (PT), %s' % (first_cut_off, ietf_monday, second_cut_off) + self.in_first_cut_off = True + elif now.date() >= second_cut_off and now.date() < ietf_monday: + if now.date() == second_cut_off and now.hour < CUTOFF_HOUR: # We are in the first_cut_off yet + self.cutoff_warning = 'The pre-meeting cutoff date for new documents (i.e., version -00 Internet-Drafts) was %s at 5 PM (PT). You will not be able to submit a new document until %s, at midnight.
The I-D submission tool will be shut down at 5 PM (PT) today, and reopened at midnight (PT), %s' % (first_cut_off, ietf_monday, ietf_monday) + self.in_first_cut_off = True + else: # Completely shut down of the tool + self.cutoff_warning = 'The cut off time for the I-D submission was 5 PM (PT), %s.
The I-D submission tool will be reopened at midnight, %s' % (second_cut_off, ietf_monday) + self.shutdown = True + def __unicode__(self): return self.as_div() @@ -47,3 +86,28 @@ class UploadForm(forms.Form): # if there is no fields in this fieldset, we continue to next fieldset continue yield fieldset_dict + + def clean_txt(self): + parsed_info = PlainParser(self.cleaned_data['txt']).parse_critical() + if parsed_info.errors: + raise forms.ValidationError(parsed_info.errors) + + def clean_pdf(self): + parsed_info = PDFParser(self.cleaned_data['pdf']).parse_critical() + if parsed_info.errors: + raise forms.ValidationError(parsed_info.errors) + + def clean_ps(self): + parsed_info = PSParser(self.cleaned_data['ps']).parse_critical() + if parsed_info.errors: + raise forms.ValidationError(parsed_info.errors) + + def clean_xml(self): + parsed_info = XMLParser(self.cleaned_data['xml']).parse_critical() + if parsed_info.errors: + raise forms.ValidationError(parsed_info.errors) + + def clean(self): + if self.shutdown: + raise forms.ValidationError('The tool is shut down') + return super(UploadForm, self).clean() diff --git a/ietf/submit/models.py b/ietf/submit/models.py new file mode 100644 index 000000000..22be5e1f7 --- /dev/null +++ b/ietf/submit/models.py @@ -0,0 +1,42 @@ +from django.db import models + +class IdSubmissionStatus(models.Model): + status_id = models.IntegerField(primary_key=True) + status_value = models.CharField(blank=True, max_length=255) + + class Meta: + db_table = 'id_submission_status' + + +class IdSubmitDateConfig(models.Model): + id = models.IntegerField(primary_key=True) + id_date = models.DateField(null=True, blank=True) + date_name = models.CharField(blank=True, max_length=255) + f_name = models.CharField(blank=True, max_length=255) + + class Meta: + db_table = 'id_dates' + + @classmethod + def get_first_cut_off(cls): + return cls.objects.get(id=1).id_date + + @classmethod + def get_second_cut_off(cls): + return cls.objects.get(id=2).id_date + + @classmethod + def get_ietf_monday(cls): + return cls.objects.get(id=3).id_date + + @classmethod + def get_processed_ids_date(cls): + return cls.objects.get(id=4).id_date + + @classmethod + def get_monday_after_ietf(cls): + return cls.objects.get(id=5).id_date + + @classmethod + def get_list_aproved_date(cls): + return cls.objects.get(id=6).id_date diff --git a/ietf/submit/parsers/__init__.py b/ietf/submit/parsers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ietf/submit/parsers/base.py b/ietf/submit/parsers/base.py new file mode 100644 index 000000000..92578ded2 --- /dev/null +++ b/ietf/submit/parsers/base.py @@ -0,0 +1,43 @@ +import datetime +import re + + +CUTOFF_HOUR = 17 + + +class ParseInfo(object): + + def __init__(self): + self.errors = [] + self.warnings = {} + + def add_error(self, error_str): + self.errors.append(error_str) + + def add_warning(self, warning_type, warning_str): + warn_list = self.warnings.get(warning_type, []) + self.warnings[warning_type] = warn_list + [warning_str] + + +class FileParser(object): + + def __init__(self, fd): + self.fd = fd + self.parsed_info = ParseInfo() + + def parse_critical(self): + if not self.fd: + return self.parsed_info + for attr in dir(self): + if attr.startswith('parse_critical_'): + method = getattr(self, attr, None) + if callable(method): + method() + return self.parsed_info + + def parse_critical_invalid_chars_in_filename(self): + name = self.fd.name + regexp = re.compile(r'&|\|\/|;|\*|\s|\$') + chars = regexp.findall(name) + if chars: + self.parsed_info.add_error('Invalid characters were found in the name of the file which was just submitted: %s' % ', '.join(set(chars))) diff --git a/ietf/submit/parsers/pdf_parser.py b/ietf/submit/parsers/pdf_parser.py new file mode 100644 index 000000000..b7b7659ca --- /dev/null +++ b/ietf/submit/parsers/pdf_parser.py @@ -0,0 +1,7 @@ +from ietf.submit.parsers.base import FileParser + +class PDFParser(FileParser): + + def parse_critical_filename_extension(self): + if not self.fd.name.endswith('.pdf'): + self.parsed_info.add_error('Format of this document must be PDF') diff --git a/ietf/submit/parsers/plain_parser.py b/ietf/submit/parsers/plain_parser.py new file mode 100644 index 000000000..3979f9ed4 --- /dev/null +++ b/ietf/submit/parsers/plain_parser.py @@ -0,0 +1,36 @@ +import re + +from ietf.submit.error_manager import MainErrorManager +from ietf.submit.parsers.base import FileParser + +MAX_PLAIN_FILE_SIZE = 6000000 + +class PlainParser(FileParser): + + def parse_critical_max_size(self): + if self.fd.size > MAX_PLAIN_FILE_SIZE: + self.parsed_info.add_error(MainErrorManager.get_error_str('EXCEEDED_SIZE')) + + def parse_critical_file_charset(self): + import magic + self.fd.file.seek(0) + m = magic.open(magic.MAGIC_MIME) + m.load() + filetype=m.buffer(self.fd.file.read()) + if not 'ascii' in filetype: + self.parsed_info.add_error('A plain text document must be submitted.'); + + def parse_filename(self): + self.fd.file.seek(0) + draftre = re.compile('(draft-\S+)') + limit = 80 + while limit: + line = self.fd.readline() + match = draftre.match(line) + if not match: + continue + filename = match.group(0) + filename = re.sub('^[^\w]+', '', filename) + filename = re.sub('[^\w]+$', '', filename) + filename = re.sub('\.txt$', '', filename) + line = re.sub('^[^\w]+', '') diff --git a/ietf/submit/parsers/ps_parser.py b/ietf/submit/parsers/ps_parser.py new file mode 100644 index 000000000..e3d0cea74 --- /dev/null +++ b/ietf/submit/parsers/ps_parser.py @@ -0,0 +1,7 @@ +from ietf.submit.parsers.base import FileParser + +class PSParser(FileParser): + + def parse_critical_filename_extension(self): + if not self.fd.name.endswith('.ps'): + self.parsed_info.add_error('Format of this document must be PS') diff --git a/ietf/submit/parsers/xml_parser.py b/ietf/submit/parsers/xml_parser.py new file mode 100644 index 000000000..2edd9e08c --- /dev/null +++ b/ietf/submit/parsers/xml_parser.py @@ -0,0 +1,7 @@ +from ietf.submit.parsers.base import FileParser + +class XMLParser(FileParser): + + def parse_critical_filename_extension(self): + if not self.fd.name.endswith('.xml'): + self.parsed_info.add_error('Format of this document must be XML') diff --git a/ietf/submit/views.py b/ietf/submit/views.py index 458b73835..40a5b4c8b 100644 --- a/ietf/submit/views.py +++ b/ietf/submit/views.py @@ -18,6 +18,8 @@ from ietf.submit.forms import UploadForm def submit_index(request): if request.method == 'POST': form = UploadForm(data=request.POST, files=request.FILES) + if form.is_valid(): + pass else: form = UploadForm() return render_to_response('submit/submit_index.html', diff --git a/ietf/templates/submit/submit_base.html b/ietf/templates/submit/submit_base.html index 4ffc1561e..e89d599a2 100644 --- a/ietf/templates/submit/submit_base.html +++ b/ietf/templates/submit/submit_base.html @@ -9,6 +9,7 @@ } .ietf-navset .selected { font-weight:bold; padding: 0 3px; } .ietf-navset a, .ietf-navset a:visited { color: white; padding:0 3px; } +.cutoff-warning { border: 1px dashed red; background-color: #ffeeaa; padding: 1em 2em; margin: 1em 0px; } {% endblock %} {% block content %} @@ -21,6 +22,12 @@ {% ifequal selected "notewell" %}NOTE WELL{% else %}NOTE WELL{% endifequal %} +{% if form.cutoff_warning %} +
+{{ form.cutoff_warning|safe }} +
+{% endif %} + {% block submit_content %} {% endblock %} {% endblock %} diff --git a/ietf/templates/submit/submitform.html b/ietf/templates/submit/submitform.html index 9c43ab0a9..5e889674b 100644 --- a/ietf/templates/submit/submitform.html +++ b/ietf/templates/submit/submitform.html @@ -42,9 +42,11 @@ {% endif %} {% endfor %} +{% if not form.shutdown %}
+{% endif %}