@ -1,8 +1,9 @@
import re
import hashlib
import hashlib
import time
import time
import ssl
import ssl
import traceback
from pathlib import Path
from pathlib import Path
from datetime import datetime
import imaplib
import imaplib
from smtplib import SMTP_SSL
from smtplib import SMTP_SSL
@ -17,9 +18,7 @@ from email.mime.application import MIMEApplication
import pdfkit
import pdfkit
from jinja2 import Environment , FileSystemLoader
from jinja2 import Environment , FileSystemLoader
from . model import db , UploadUnauthenticated
ENABLED_FILETYPES = [ ' txt ' , ' csv ' , ' pdf ' , ' doc ' , ' docx ' , ' xls ' , ' xlsx ' , ' ppt ' , ' pptx ' , ' xml ' , ' mxliff ' , ' tmx ' ]
REGEX_EMAIL = re . compile ( ' ^[a-z0-9]+[ \ ._]?[a-z0-9]+[@] \ w+[.] \ w { 2,3}$ ' )
class ContractCreator :
class ContractCreator :
@ -49,202 +48,161 @@ class ContractCreator:
pdfkit . from_string ( html_str , out_f , options = self . pdfkit_options )
pdfkit . from_string ( html_str , out_f , options = self . pdfkit_options )
contract_creator = ContractCreator ( )
class UploadHandler :
def __init__ ( self , * * kwargs ) :
def get_upload_metadata ( corpus_name , request ) :
self . config = kwargs
upload_metadata = dict ( )
self . contract_creator = ContractCreator ( )
file_hashes = create_file_hashes ( request . files )
file_names = file_hashes . keys ( )
def extract_upload_metadata ( self , corpus_name , request ) :
form_data = request . form . copy ( )
upload_metadata = dict ( )
upload_timestamp = int ( time . time ( ) )
upload_id = create_upload_id ( corpus_name , form_data , upload_timestamp , file_hashes )
file_hashes = self . create_file_hashes ( request . files )
file_names = file_hashes . keys ( )
upload_metadata [ ' corpus_name ' ] = corpus_name
form_data = request . form . copy ( )
upload_metadata [ ' form_data ' ] = form_data
upload_timestamp = int ( time . time ( ) )
upload_metadata [ ' upload_id ' ] = upload_id
upload_id = self . create_upload_id ( corpus_name , form_data , upload_timestamp , file_hashes )
upload_metadata [ ' timestamp ' ] = upload_timestamp
upload_metadata [ ' file_hashes ' ] = file_hashes
upload_metadata [ ' corpus_name ' ] = corpus_name
upload_metadata [ ' file_names ' ] = file_names
upload_metadata [ ' form_data ' ] = form_data
upload_metadata [ ' upload_id ' ] = upload_id
return upload_metadata
upload_metadata [ ' timestamp ' ] = upload_timestamp
upload_metadata [ ' file_hashes_dict ' ] = file_hashes
upload_metadata [ ' file_names ' ] = file_names
def check_suffixes ( files ) :
upload_metadata [ ' contract_file ' ] = upload_id + ' .pdf '
for key , f in files . items ( ) :
if key . startswith ( ' file ' ) :
return upload_metadata
suffix = f . filename . split ( ' . ' ) [ - 1 ]
if suffix not in ENABLED_FILETYPES :
return ' Datoteka " {} " ni pravilnega formata. ' . format ( f . filename )
def get_uploads_subdir ( self , dir_name ) :
return None
subdir = self . config [ ' UPLOADS_DIR ' ] / dir_name
if not subdir . exists ( ) :
subdir . mkdir ( parents = True )
def get_subdir ( uploads_path , dir_name ) :
return subdir
subdir = uploads_path / dir_name
if not subdir . exists ( ) :
subdir . mkdir ( parents = True )
def create_upload_id ( self , corpus_name , form_data , upload_timestamp , file_hashes ) :
return subdir
# Order is important while hashing, hence the sorting.
val_buff = [ str ( upload_timestamp ) ]
for key in sorted ( form_data ) :
def create_upload_id ( corpus_name , form_data , upload_timestamp , file_hashes ) :
val_buff . append ( form_data [ key ] )
ime = form_data . get ( ' ime ' )
podjetje = form_data . get ( ' podjetje ' )
# This hash serves as an unique identifier for the whole upload.
naslov = form_data . get ( ' naslov ' )
metahash = hashlib . md5 ( ( ' ' . join ( val_buff ) ) . encode ( ) )
posta = form_data . get ( ' posta ' )
# Include file hashes to avoid metafile name collisions if they have the same form values,
email = form_data . get ( ' email ' )
# but different data files. Sort hashes first so upload order doesn't matter.
telefon = form_data . get ( ' telefon ' )
sorted_f_hashes = list ( file_hashes . values ( ) )
sorted_f_hashes . sort ( )
# This hash serves as an unique identifier for the whole upload.
metahash . update ( ' ' . join ( sorted_f_hashes ) . encode ( ) )
metahash = hashlib . md5 ( ( corpus_name + ime + podjetje + naslov + posta + email + telefon ) . encode ( ) )
metahash = metahash . hexdigest ( )
# Include file hashes to avoid metafile name collisions if they have the same form values,
# but different data files. Sort hashes first so upload order doesn't matter.
return metahash
sorted_f_hashes = list ( file_hashes . values ( ) )
sorted_f_hashes . sort ( )
def create_file_hashes ( self , files ) :
metahash . update ( ' ' . join ( sorted_f_hashes ) . encode ( ) )
res = dict ( )
metahash = metahash . hexdigest ( )
for key , f in files . items ( ) :
if key . startswith ( ' file ' ) :
return metahash
h = hashlib . md5 ( f . filename . encode ( ) )
h . update ( f . stream . read ( ) )
res [ f . filename ] = h . hexdigest ( )
def check_form ( form ) :
f . seek ( 0 )
ime = form . get ( ' ime ' )
return res
podjetje = form . get ( ' podjetje ' )
naslov = form . get ( ' naslov ' )
def store_metadata_unauthenticated ( self , upload_metadata ) :
posta = form . get ( ' posta ' )
timestamp = datetime . fromtimestamp ( upload_metadata [ ' timestamp ' ] )
email = form . get ( ' email ' )
form_data = upload_metadata [ ' form_data ' ]
telefon = form . get ( ' telefon ' )
file_hashes = upload_metadata [ ' file_hashes_dict ' ]
sorted_f_hashes = list ( file_hashes . values ( ) )
if len ( ime ) > 100 :
sorted_f_hashes . sort ( )
return ' Predolgo ime. '
try :
if len ( podjetje ) > 100 :
upload_unauthenticated = UploadUnauthenticated (
return ' Predolgo ime institucije. '
upload_hash = upload_metadata [ ' upload_id ' ] ,
timestamp = timestamp ,
if len ( email ) > 100 :
form_name = form_data [ ' ime ' ] ,
return ' Predolgi email naslov '
form_org = form_data [ ' podjetje ' ] ,
elif not re . search ( REGEX_EMAIL , email ) :
form_address = form_data [ ' naslov ' ] ,
return ' Email napačnega formata. '
form_zipcode = form_data [ ' posta ' ] ,
form_email = form_data [ ' email ' ] ,
if len ( telefon ) > 100 :
file_contract = upload_metadata [ ' contract_file ' ] ,
return ' Predolga telefonska št. '
upload_file_hashes = sorted_f_hashes
)
if len ( naslov ) > 100 :
return ' Predolg naslov. '
db . session . add ( upload_unauthenticated )
db . session . commit ( )
if len ( posta ) > 100 :
except Exception :
return ' Predolga pošta '
traceback . print_exc ( )
return None
def store_metadata_authenticated ( self , upload_metadata ) :
pass
def create_file_hashes ( files ) :
def store_datafiles ( self , files , upload_metadata ) :
res = dict ( )
base = self . get_uploads_subdir ( ' files ' )
for key , f in files . items ( ) :
file_hashes = upload_metadata [ ' file_hashes_dict ' ]
if key . startswith ( ' file ' ) :
h = hashlib . md5 ( f . filename . encode ( ) )
for key , f in files . items ( ) :
h . update ( f . stream . read ( ) )
if key . startswith ( ' file ' ) :
res [ f . filename ] = h . hexdigest ( )
path = base / file_hashes [ f . filename ]
f . seek ( 0 )
if not path . exists ( ) :
return res
path . mkdir ( )
f . save ( path / f . filename )
def store_metadata ( uploads_path , upload_metadata ) :
def generate_upload_contract_pdf ( self , upload_metadata ) :
base = get_subdir ( uploads_path , ' meta ' )
base = self . get_uploads_subdir ( ' contracts ' )
form_data = upload_metadata [ ' form_data ' ]
timestamp = upload_metadata [ ' timestamp ' ]
upload_id = upload_metadata [ ' upload_id ' ]
files_table_str = [ ]
form_data = upload_metadata [ ' form_data ' ]
for file_name in upload_metadata [ ' file_names ' ] :
email = form_data [ ' email ' ]
files_table_str . append ( ' <tr><td style= " text-align: center; " > ' )
file_hashes = upload_metadata [ ' file_hashes ' ]
files_table_str . append ( file_name )
contract = upload_metadata [ ' contract ' ]
files_table_str . append ( ' </td></tr> ' )
filename = str ( timestamp ) + ' - ' + email + ' - ' + upload_id + ' .meta '
files_table_str = ' ' . join ( files_table_str )
sorted_f_hashes = list ( file_hashes . values ( ) )
data = {
sorted_f_hashes . sort ( )
' ime_priimek ' : form_data [ ' ime ' ] ,
' naslov ' : form_data [ ' naslov ' ] ,
path = base / filename
' posta ' : form_data [ ' posta ' ] ,
with path . open ( ' w ' ) as f :
' kontakt_narocnik ' : self . config [ ' CONTRACT_CLIENT_CONTACT ' ] ,
f . write ( ' korpus= ' + upload_metadata [ ' corpus_name ' ] )
' kontakt_imetnikpravic ' : form_data [ ' ime ' ] ,
f . write ( ' \n ime= ' + form_data [ ' ime ' ] )
' files_table_str ' : files_table_str
f . write ( ' \n podjetje= ' + form_data [ ' podjetje ' ] )
}
f . write ( ' \n naslov= ' + form_data [ ' naslov ' ] )
f . write ( ' \n posta= ' + form_data [ ' posta ' ] )
self . contract_creator . create_pdf ( base / upload_metadata [ ' contract_file ' ] , data )
f . write ( ' \n email= ' + form_data [ ' email ' ] )
f . write ( ' \n datoteke= ' + str ( sorted_f_hashes ) )
def send_confirm_mail ( self , upload_metadata ) :
f . write ( ' \n pogodba= ' + contract )
upload_id = upload_metadata [ ' upload_id ' ]
message = MIMEMultipart ( )
def store_datafiles ( uploads_path , files , upload_metadata ) :
message [ ' From ' ] = self . config [ ' MAIL_LOGIN ' ]
base = get_subdir ( uploads_path , ' files ' )
message [ ' To ' ] = upload_metadata [ ' form_data ' ] [ ' email ' ]
file_hashes = upload_metadata [ ' file_hashes ' ]
message [ ' Subject ' ] = self . config [ ' MAIL_SUBJECT ' ] . format ( upload_id = upload_id )
body = self . config [ ' MAIL_BODY ' ] . format ( upload_id = upload_id )
for key , f in files . items ( ) :
message . attach ( MIMEText ( body , " plain " ) )
if key . startswith ( ' file ' ) :
path = base / file_hashes [ f . filename ]
contracts_dir = self . get_uploads_subdir ( ' contracts ' )
if not path . exists ( ) :
base_name = upload_metadata [ ' contract_file ' ]
path . mkdir ( )
contract_file = contracts_dir / base_name
f . save ( path / f . filename )
with open ( contract_file , " rb " ) as f :
part = MIMEApplication (
f . read ( ) ,
def generate_contract_pdf ( uploads_path , upload_metadata , contract_client_contact ) :
Name = base_name
base = get_subdir ( uploads_path , ' contracts ' )
)
contract_file_name = upload_metadata [ ' upload_id ' ] + ' .pdf '
part [ ' Content-Disposition ' ] = ' attachment; filename= " %s " ' % base_name
form_data = upload_metadata [ ' form_data ' ]
message . attach ( part )
files_table_str = [ ]
text = message . as_string ( )
for file_name in upload_metadata [ ' file_names ' ] :
files_table_str . append ( ' <tr><td style= " text-align: center; " > ' )
# Create a secure SSL context
files_table_str . append ( file_name )
context = ssl . create_default_context ( )
files_table_str . append ( ' </td></tr> ' )
files_table_str = ' ' . join ( files_table_str )
with SMTP_SSL ( self . config [ ' MAIL_HOST ' ] , self . config [ ' SMTP_PORT ' ] , context = context ) as server :
server . login ( self . config [ ' MAIL_LOGIN ' ] , self . config [ ' MAIL_PASS ' ] )
data = {
server . sendmail ( message [ ' From ' ] , message [ ' To ' ] , text )
' ime_priimek ' : form_data [ ' ime ' ] ,
' naslov ' : form_data [ ' naslov ' ] ,
# Save copy of sent mail in Sent mailbox
' posta ' : form_data [ ' posta ' ] ,
imap = imaplib . IMAP4_SSL ( self . config [ ' MAIL_HOST ' ] , self . config [ ' IMAP_PORT ' ] )
' kontakt_narocnik ' : contract_client_contact ,
imap . login ( self . config [ ' MAIL_LOGIN ' ] , self . config [ ' MAIL_PASS ' ] )
' kontakt_imetnikpravic ' : form_data [ ' ime ' ] ,
imap . append ( ' Sent ' , ' \\ Seen ' , imaplib . Time2Internaldate ( time . time ( ) ) , text . encode ( ' utf8 ' ) )
' files_table_str ' : files_table_str
imap . logout ( )
}
contract_creator . create_pdf ( base / contract_file_name , data )
return contract_file_name
def send_confirm_mail ( subject , body , uploads_path , upload_metadata , mail_host , mail_login , mail_pass , imap_port = 993 , smtp_port = 465 ) :
upload_id = upload_metadata [ ' upload_id ' ]
message = MIMEMultipart ( )
message [ ' From ' ] = mail_login
message [ ' To ' ] = upload_metadata [ ' form_data ' ] [ ' email ' ]
message [ ' Subject ' ] = subject . format ( upload_id = upload_id )
body = body . format ( upload_id = upload_id )
message . attach ( MIMEText ( body , " plain " ) )
contracts_dir = get_subdir ( uploads_path , ' contracts ' )
base_name = upload_metadata [ ' contract ' ]
contract_file = contracts_dir / base_name
with open ( contract_file , " rb " ) as f :
part = MIMEApplication (
f . read ( ) ,
Name = base_name
)
part [ ' Content-Disposition ' ] = ' attachment; filename= " %s " ' % base_name
message . attach ( part )
text = message . as_string ( )
# Create a secure SSL context
context = ssl . create_default_context ( )
with SMTP_SSL ( mail_host , smtp_port , context = context ) as server :
server . login ( mail_login , mail_pass )
server . sendmail ( message [ ' From ' ] , message [ ' To ' ] , text )
# Save copy of sent mail in Sent mailbox
imap = imaplib . IMAP4_SSL ( mail_host , imap_port )
imap . login ( mail_login , mail_pass )
imap . append ( ' Sent ' , ' \\ Seen ' , imaplib . Time2Internaldate ( time . time ( ) ) , text . encode ( ' utf8 ' ) )
imap . logout ( )