Cutoff dates and basic checkings over the plain file. See #580

- Legacy-Id: 2806
This commit is contained in:
Emilio A. Sánchez López 2011-02-03 11:46:04 +00:00
parent 8c5ffce3eb
commit 4bc95f6436
13 changed files with 237 additions and 0 deletions

View file

@ -131,6 +131,7 @@ INSTALLED_APPS = (
'ietf.redirects',
'ietf.idrfc',
'ietf.wginfo',
'ietf.submit',
)
INTERNAL_IPS = (

View file

@ -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()

View file

@ -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.<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)
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.<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)
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.<br>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()

42
ietf/submit/models.py Normal file
View file

@ -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

View file

View file

@ -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)))

View file

@ -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')

View file

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

View file

@ -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')

View file

@ -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')

View file

@ -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',

View file

@ -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" %}<span class="selected">NOTE WELL</span>{% else %}<a href="{% url submit_note_well %}">NOTE WELL</a>{% endifequal %}
</div>
{% if form.cutoff_warning %}
<div class="cutoff-warning">
{{ form.cutoff_warning|safe }}
</div>
{% endif %}
{% block submit_content %}
{% endblock %}
{% endblock %}

View file

@ -42,9 +42,11 @@
{% endif %}
{% endfor %}
{% if not form.shutdown %}
<div class="submitrow">
<input type="submit" value="Upload" name="upload" />
</div>
{% endif %}
</div>
</form>