Skip to content

Commit 4bc95f6

Browse files
committed
Cutoff dates and basic checkings over the plain file. See ietf-tools#580
- Legacy-Id: 2806
1 parent 8c5ffce commit 4bc95f6

13 files changed

Lines changed: 237 additions & 0 deletions

File tree

ietf/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
'ietf.redirects',
132132
'ietf.idrfc',
133133
'ietf.wginfo',
134+
'ietf.submit',
134135
)
135136

136137
INTERNAL_IPS = (

ietf/submit/error_manager.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from ietf.submit.models import IdSubmissionStatus
2+
3+
class ErrorManager(object):
4+
ERROR_CODES = {
5+
'DEFAULT': 'Unknow error',
6+
'INVALID_FILENAME': 111,
7+
'EXCEEDED_SIZE': 102,
8+
}
9+
10+
def get_error_str(self, key):
11+
error_code = self.ERROR_CODES.get(key, self.ERROR_CODES['DEFAULT'])
12+
if isinstance(error_code, basestring):
13+
return '%s (%s)' % (key, error_code)
14+
try:
15+
return IdSubmissionStatus.objects.get(status_id=error_code).status_value
16+
except IdSubmissionStatus.DoesNotExist:
17+
return '%s (%s)' % (self.ERROR_CODES['DEFAULT'], key)
18+
19+
MainErrorManager=ErrorManager()

ietf/submit/forms.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
ShowAttachmentsWidget, RelatedLiaisonWidget)
1717

1818

19+
from ietf.submit.models import IdSubmitDateConfig
20+
from ietf.submit.parsers.plain_parser import PlainParser
21+
from ietf.submit.parsers.pdf_parser import PDFParser
22+
from ietf.submit.parsers.ps_parser import PSParser
23+
from ietf.submit.parsers.xml_parser import XMLParser
24+
25+
26+
CUTOFF_HOUR = 17
27+
28+
1929
class UploadForm(forms.Form):
2030

2131
txt = forms.FileField(label=u'.txt format', required=True)
@@ -28,6 +38,35 @@ class UploadForm(forms.Form):
2838
class Media:
2939
css = {'all': ("/css/liaisons.css", )}
3040

41+
def __init__(self, *args, **kwargs):
42+
super(UploadForm, self).__init__(*args, **kwargs)
43+
self.in_first_cut_off = False
44+
self.shutdown = False
45+
self.read_dates()
46+
47+
def read_dates(self):
48+
now = datetime.datetime.now()
49+
first_cut_off = IdSubmitDateConfig.get_first_cut_off()
50+
second_cut_off = IdSubmitDateConfig.get_second_cut_off()
51+
ietf_monday = IdSubmitDateConfig.get_ietf_monday()
52+
processed_ids_date = IdSubmitDateConfig.get_processed_ids_date()
53+
monday_after_ietf = IdSubmitDateConfig.get_monday_after_ietf()
54+
list_aproved_date = IdSubmitDateConfig.get_list_aproved_date()
55+
56+
if now.date() >= first_cut_off and now.date() < second_cut_off: # We are in the first_cut_off
57+
if now.date() == first_cut_off and now.hour < CUTOFF_HOUR:
58+
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)
59+
else: # No 00 version allowed
60+
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.<br>You can still submit a version -01 or higher Internet-Draft until 5 PM (PT), %s' % (first_cut_off, ietf_monday, second_cut_off)
61+
self.in_first_cut_off = True
62+
elif now.date() >= second_cut_off and now.date() < ietf_monday:
63+
if now.date() == second_cut_off and now.hour < CUTOFF_HOUR: # We are in the first_cut_off yet
64+
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.<br>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)
65+
self.in_first_cut_off = True
66+
else: # Completely shut down of the tool
67+
self.cutoff_warning = 'The cut off time for the I-D submission was 5 PM (PT), %s.<br>The I-D submission tool will be reopened at midnight, %s' % (second_cut_off, ietf_monday)
68+
self.shutdown = True
69+
3170
def __unicode__(self):
3271
return self.as_div()
3372

@@ -47,3 +86,28 @@ def get_fieldsets(self):
4786
# if there is no fields in this fieldset, we continue to next fieldset
4887
continue
4988
yield fieldset_dict
89+
90+
def clean_txt(self):
91+
parsed_info = PlainParser(self.cleaned_data['txt']).parse_critical()
92+
if parsed_info.errors:
93+
raise forms.ValidationError(parsed_info.errors)
94+
95+
def clean_pdf(self):
96+
parsed_info = PDFParser(self.cleaned_data['pdf']).parse_critical()
97+
if parsed_info.errors:
98+
raise forms.ValidationError(parsed_info.errors)
99+
100+
def clean_ps(self):
101+
parsed_info = PSParser(self.cleaned_data['ps']).parse_critical()
102+
if parsed_info.errors:
103+
raise forms.ValidationError(parsed_info.errors)
104+
105+
def clean_xml(self):
106+
parsed_info = XMLParser(self.cleaned_data['xml']).parse_critical()
107+
if parsed_info.errors:
108+
raise forms.ValidationError(parsed_info.errors)
109+
110+
def clean(self):
111+
if self.shutdown:
112+
raise forms.ValidationError('The tool is shut down')
113+
return super(UploadForm, self).clean()

ietf/submit/models.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from django.db import models
2+
3+
class IdSubmissionStatus(models.Model):
4+
status_id = models.IntegerField(primary_key=True)
5+
status_value = models.CharField(blank=True, max_length=255)
6+
7+
class Meta:
8+
db_table = 'id_submission_status'
9+
10+
11+
class IdSubmitDateConfig(models.Model):
12+
id = models.IntegerField(primary_key=True)
13+
id_date = models.DateField(null=True, blank=True)
14+
date_name = models.CharField(blank=True, max_length=255)
15+
f_name = models.CharField(blank=True, max_length=255)
16+
17+
class Meta:
18+
db_table = 'id_dates'
19+
20+
@classmethod
21+
def get_first_cut_off(cls):
22+
return cls.objects.get(id=1).id_date
23+
24+
@classmethod
25+
def get_second_cut_off(cls):
26+
return cls.objects.get(id=2).id_date
27+
28+
@classmethod
29+
def get_ietf_monday(cls):
30+
return cls.objects.get(id=3).id_date
31+
32+
@classmethod
33+
def get_processed_ids_date(cls):
34+
return cls.objects.get(id=4).id_date
35+
36+
@classmethod
37+
def get_monday_after_ietf(cls):
38+
return cls.objects.get(id=5).id_date
39+
40+
@classmethod
41+
def get_list_aproved_date(cls):
42+
return cls.objects.get(id=6).id_date

ietf/submit/parsers/__init__.py

Whitespace-only changes.

ietf/submit/parsers/base.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import datetime
2+
import re
3+
4+
5+
CUTOFF_HOUR = 17
6+
7+
8+
class ParseInfo(object):
9+
10+
def __init__(self):
11+
self.errors = []
12+
self.warnings = {}
13+
14+
def add_error(self, error_str):
15+
self.errors.append(error_str)
16+
17+
def add_warning(self, warning_type, warning_str):
18+
warn_list = self.warnings.get(warning_type, [])
19+
self.warnings[warning_type] = warn_list + [warning_str]
20+
21+
22+
class FileParser(object):
23+
24+
def __init__(self, fd):
25+
self.fd = fd
26+
self.parsed_info = ParseInfo()
27+
28+
def parse_critical(self):
29+
if not self.fd:
30+
return self.parsed_info
31+
for attr in dir(self):
32+
if attr.startswith('parse_critical_'):
33+
method = getattr(self, attr, None)
34+
if callable(method):
35+
method()
36+
return self.parsed_info
37+
38+
def parse_critical_invalid_chars_in_filename(self):
39+
name = self.fd.name
40+
regexp = re.compile(r'&|\|\/|;|\*|\s|\$')
41+
chars = regexp.findall(name)
42+
if chars:
43+
self.parsed_info.add_error('Invalid characters were found in the name of the file which was just submitted: %s' % ', '.join(set(chars)))

ietf/submit/parsers/pdf_parser.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from ietf.submit.parsers.base import FileParser
2+
3+
class PDFParser(FileParser):
4+
5+
def parse_critical_filename_extension(self):
6+
if not self.fd.name.endswith('.pdf'):
7+
self.parsed_info.add_error('Format of this document must be PDF')
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import re
2+
3+
from ietf.submit.error_manager import MainErrorManager
4+
from ietf.submit.parsers.base import FileParser
5+
6+
MAX_PLAIN_FILE_SIZE = 6000000
7+
8+
class PlainParser(FileParser):
9+
10+
def parse_critical_max_size(self):
11+
if self.fd.size > MAX_PLAIN_FILE_SIZE:
12+
self.parsed_info.add_error(MainErrorManager.get_error_str('EXCEEDED_SIZE'))
13+
14+
def parse_critical_file_charset(self):
15+
import magic
16+
self.fd.file.seek(0)
17+
m = magic.open(magic.MAGIC_MIME)
18+
m.load()
19+
filetype=m.buffer(self.fd.file.read())
20+
if not 'ascii' in filetype:
21+
self.parsed_info.add_error('A plain text document must be submitted.');
22+
23+
def parse_filename(self):
24+
self.fd.file.seek(0)
25+
draftre = re.compile('(draft-\S+)')
26+
limit = 80
27+
while limit:
28+
line = self.fd.readline()
29+
match = draftre.match(line)
30+
if not match:
31+
continue
32+
filename = match.group(0)
33+
filename = re.sub('^[^\w]+', '', filename)
34+
filename = re.sub('[^\w]+$', '', filename)
35+
filename = re.sub('\.txt$', '', filename)
36+
line = re.sub('^[^\w]+', '')

ietf/submit/parsers/ps_parser.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from ietf.submit.parsers.base import FileParser
2+
3+
class PSParser(FileParser):
4+
5+
def parse_critical_filename_extension(self):
6+
if not self.fd.name.endswith('.ps'):
7+
self.parsed_info.add_error('Format of this document must be PS')

ietf/submit/parsers/xml_parser.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from ietf.submit.parsers.base import FileParser
2+
3+
class XMLParser(FileParser):
4+
5+
def parse_critical_filename_extension(self):
6+
if not self.fd.name.endswith('.xml'):
7+
self.parsed_info.add_error('Format of this document must be XML')

0 commit comments

Comments
 (0)