1+ import sha
2+ import random
13import os
24import subprocess
35import datetime
46
57from django import forms
8+ from django .forms .fields import email_re
69from django .conf import settings
710from django .template .loader import render_to_string
811from django .utils .html import mark_safe
912
1013from ietf .idtracker .models import InternetDraft , IETFWG
1114from ietf .proceedings .models import Meeting
1215from ietf .submit .models import IdSubmissionDetail , TempIdAuthors
16+ from ietf .submit .utils import MANUAL_POST_REQUESTED , NONE_WG , UPLOADED , WAITING_AUTHENTICATION
1317from ietf .submit .parsers .pdf_parser import PDFParser
1418from ietf .submit .parsers .plain_parser import PlainParser
1519from ietf .submit .parsers .ps_parser import PSParser
1620from ietf .submit .parsers .xml_parser import XMLParser
21+ from ietf .utils .mail import send_mail
1722from ietf .utils .draft import Draft
1823
1924
@@ -42,6 +47,7 @@ def __init__(self, *args, **kwargs):
4247 self .draft = None
4348 self .filesize = None
4449 self .group = None
50+ self .file_type = []
4551 self .read_dates ()
4652
4753 def read_dates (self ):
@@ -200,15 +206,16 @@ def get_draft(self):
200206 return self .draft
201207
202208 def save (self ):
203- for fd in [self . cleaned_data [ 'txt' ], self . cleaned_data [ 'pdf' ],
204- self .cleaned_data ['xml' ], self . cleaned_data [ 'ps' ]]:
209+ for ext in ['txt' , 'pdf' , 'xml' , 'ps' ]:
210+ fd = self .cleaned_data [ext ]
205211 if not fd :
206212 continue
207- filename = os .path .join (self .staging_path , fd .name )
213+ self .file_type .append ('.%s' % ext )
214+ filename = os .path .join (self .staging_path , '%s-%s.%s' % (self .draft .filename , self .draft .revision , ext ))
208215 destination = open (filename , 'wb+' )
209216 for chunk in fd .chunks ():
210217 destination .write (chunk )
211- destination .close ()
218+ destination .close ()
212219 self .check_idnits ()
213220 return self .save_draft_info (self .draft )
214221
@@ -222,7 +229,7 @@ def get_working_group(self):
222229 existing_draft = InternetDraft .objects .filter (filename = filename )
223230 if existing_draft :
224231 group = existing_draft [0 ].group and existing_draft [0 ].group .ietfwg or None
225- if group and group .pk != 1027 :
232+ if group and group .pk != NONE_WG :
226233 return group
227234 else :
228235 return None
@@ -258,7 +265,9 @@ def save_draft_info(self, draft):
258265 group_acronym = self .group ,
259266 remote_ip = self .remote_ip ,
260267 first_two_pages = '' .join (draft .pages [:2 ]),
261- status_id = 1 , # Status 1 - upload
268+ status_id = UPLOADED ,
269+ abstract = draft .get_abstract (),
270+ file_type = ',' .join (self .file_type ),
262271 )
263272 order = 0
264273 for author in draft .get_authors ():
@@ -297,3 +306,163 @@ def get_author_buttons(self):
297306 'email' : i .email ()[1 ],
298307 'full_name' : full_name })
299308 return '' .join (buttons )
309+
310+ def save (self , request ):
311+ self .save_submitter_info ()
312+ self .save_new_draft_info ()
313+ self .send_confirmation_mail (request )
314+
315+ def send_confirmation_mail (self , request ):
316+ subject = 'Confirmation for Auto-Post of I-D %s' % self .draft .filename
317+ from_email = settings .IDST_FROM_EMAIL
318+ to_email = self .cleaned_data ['email' ]
319+ send_mail (request , from_email , to_email , subject , 'submit/confirm_autopost.txt' ,
320+ {'draft' : self .draft })
321+
322+ def save_submitter_info (self ):
323+ TempIdAuthors .objects .create (
324+ id_document_tag = self .draft .temp_id_document_tag ,
325+ first_name = self .cleaned_data ['first_name' ],
326+ last_name = self .cleaned_data ['last_name' ],
327+ email_address = self .cleaned_data ['email' ],
328+ author_order = 0 ,
329+ submission = self .draft )
330+
331+ def save_new_draft_info (self ):
332+ salt = sha .new (str (random .random ())).hexdigest ()[:5 ]
333+ self .draft .auth_key = sha .new (salt + self .cleaned_data ['email' ]).hexdigest ()
334+ self .draft .status_id = WAITING_AUTHENTICATION
335+ self .draft .save ()
336+
337+
338+ class MetaDataForm (AutoPostForm ):
339+
340+ title = forms .CharField (label = u'Title' , required = True )
341+ version = forms .CharField (label = u'Version' , required = True )
342+ creation_date = forms .DateField (label = u'Creation date' , required = True )
343+ pages = forms .IntegerField (label = u'Pages' , required = True )
344+ abstract = forms .CharField (label = u'Abstract' , widget = forms .Textarea , required = True )
345+ first_name = forms .CharField (label = u'Given name' , required = True )
346+ last_name = forms .CharField (label = u'Last name' , required = True )
347+ email = forms .EmailField (label = u'Email address' , required = True )
348+ comments = forms .CharField (label = u'Comments to the secretariat' , widget = forms .Textarea , required = False )
349+ fields = ['title' , 'version' , 'creation_date' , 'pages' , 'abstract' , 'first_name' , 'last_name' , 'email' , 'comments' ]
350+
351+ def __init__ (self , * args , ** kwargs ):
352+ super (MetaDataForm , self ).__init__ (* args , ** kwargs )
353+ self .set_initials ()
354+ self .authors = self .get_initial_authors ()
355+
356+ def get_initial_authors (self ):
357+ authors = []
358+ if self .is_bound :
359+ for key , value in self .data .items ():
360+ if key .startswith ('first_name_' ):
361+ author = {'errors' : {}}
362+ index = key .replace ('first_name_' , '' )
363+ first_name = value .strip ()
364+ if not first_name :
365+ author ['errors' ]['first_name' ] = 'This field is required'
366+ last_name = self .data .get ('last_name_%s' % index , '' ).strip ()
367+ if not last_name :
368+ author ['errors' ]['last_name' ] = 'This field is required'
369+ email = self .data .get ('email_%s' % index , '' ).strip ()
370+ if not email :
371+ author ['errors' ]['email' ] = 'This field is required'
372+ elif not email_re .search (email ):
373+ author ['errors' ]['email' ] = 'Enter a valid e-mail address'
374+ if first_name or last_name or email :
375+ author .update ({'first_name' : first_name ,
376+ 'last_name' : last_name ,
377+ 'email' : ('%s %s' % (first_name , last_name ), email ),
378+ 'index' : index ,
379+ })
380+ authors .append (author )
381+ authors .sort (lambda x ,y : cmp (int (x ['index' ]), int (y ['index' ])))
382+ return authors
383+
384+ def set_initials (self ):
385+ self .fields ['pages' ].initial = self .draft .txt_page_count
386+ self .fields ['creation_date' ].initial = self .draft .creation_date
387+ self .fields ['version' ].initial = self .draft .revision
388+ self .fields ['abstract' ].initial = self .draft .abstract
389+ self .fields ['title' ].initial = self .draft .id_document_name
390+
391+ def clean_creation_date (self ):
392+ creation_date = self .cleaned_data .get ('creation_date' , None )
393+ if not creation_date :
394+ return None
395+ submit_date = self .draft .submission_date
396+ if creation_date > submit_date :
397+ raise forms .ValidationError ('Creation Date must not be set after submission date' )
398+ if creation_date + datetime .timedelta (days = 3 ) < submit_date :
399+ raise forms .ValidationError ('Creation Date must be within 3 days of submission date' )
400+ return creation_date
401+
402+ def clean_version (self ):
403+ version = self .cleaned_data .get ('version' , None )
404+ if not version :
405+ return None
406+ if len (version ) > 2 :
407+ raise forms .ValidationError ('Version field is not in NN format' )
408+ try :
409+ version_int = int (version )
410+ except ValueError :
411+ raise forms .ValidationError ('Version field is not in NN format' )
412+ if version_int > 99 or version_int < 0 :
413+ raise forms .ValidationError ('Version must be set between 00 and 99' )
414+ existing_revisions = [int (i .revision ) for i in InternetDraft .objects .filter (filename = self .draft .filename )]
415+ expected = 0
416+ if existing_revisions :
417+ expected = max (existing_revisions ) + 1
418+ if version_int != expected :
419+ raise forms .ValidationError ('Invalid Version Number (Version %00d is expected)' % expected )
420+ return version
421+
422+ def clean (self ):
423+ if bool ([i for i in self .authors if i ['errors' ]]):
424+ raise forms .ValidationError ('Please fix errors in author list' )
425+ return super (MetaDataForm , self ).clean ()
426+
427+ def get_authors (self ):
428+ if not self .is_bound :
429+ return self .validation .get_authors ()
430+ else :
431+ return self .authors
432+
433+ def move_docs (self , draft , revision ):
434+ old_revision = draft .revision
435+ for ext in draft .file_type .split (',' ):
436+ source = os .path .join (settings .STAGING_PATH , '%s-%s%s' % (draft .filename , old_revision , ext ))
437+ dest = os .path .join (settings .STAGING_PATH , '%s-%s%s' % (draft .filename , revision , ext ))
438+ os .rename (source , dest )
439+
440+ def save_new_draft_info (self ):
441+ draft = self .draft
442+ draft .id_documen_name = self .cleaned_data ['title' ]
443+ if draft .revision != self .cleaned_data ['version' ]:
444+ self .move_docs (draft , self .cleaned_data ['version' ])
445+ draft .revision = self .cleaned_data ['version' ]
446+ draft .creation_date = self .cleaned_data ['creation_date' ]
447+ draft .txt_page_count = self .cleaned_data ['pages' ]
448+ draft .abstract = self .cleaned_data ['abstract' ]
449+ draft .comment_to_sec = self .cleaned_data ['comments' ]
450+ draft .status_id = MANUAL_POST_REQUESTED
451+ draft .save ()
452+ self .save_submitter_info ()
453+
454+ def save (self , request ):
455+ self .save_new_draft_info ()
456+ self .send_mail_to_secretariat (request )
457+
458+ def send_mail_to_secretariat (self , request ):
459+ subject = 'Manual Post Requested for %s' % self .draft .filename
460+ from_email = settings .IDST_FROM_EMAIL
461+ to_email = settings .IDST_TO_EMAIL
462+ cc = [self .cleaned_data ['email' ]]
463+ cc += [i ['email' ][1 ] for i in self .authors ]
464+ if self .draft .group_acronym :
465+ cc += [i .person .email ()[1 ] for i in self .draft .group_acronym .wgchair_set .all ()]
466+ cc = list (set (cc ))
467+ send_mail (request , from_email , to_email , subject , 'submit/manual_post_mail.txt' ,
468+ {'form' : self , 'draft' : self .draft }, cc = cc )
0 commit comments