web_tools.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import re,cherrypy,lmdb,threading
  2. import smtplib,ssl,string,random
  3. from os import path
  4. from config import *
  5. from mailconfig import *
  6. from email.mime.multipart import MIMEMultipart
  7. from email.mime.text import MIMEText
  8. def ConvertTemplateCode(TemplateName:str,VarsDictionary={},LoopSource=None):
  9. template_file_path = path.join(TEMPLATES_DIR,TEMPLATES_DICTIONARY[TemplateName])
  10. VarsDictionary+=TEMPLATE_VALUES_DICTIONARY
  11. with open(template_file_path) as template_file:
  12. result=template_file.read()
  13. searchPattern=re.compile(r'(\[::([^\]]*)])') #searching for template code variables
  14. for oldString,variableName in searchPattern.findall(result):
  15. if variableName in VarsDictionary:
  16. result=result.replace(oldString,VarsDictionary[variableName])
  17. if LoopSource!=None:
  18. for regGroups in re.findall(r'(\[::foreach (\w*)](\n(\s*((?!\[::end\]).)*\n?)*)\[::end])',result):
  19. #searching for template code foreach
  20. #foreach regex groups:
  21. # 0: old full string for replacing
  22. # 1: foreach source
  23. # 2: repeatable template
  24. # 3: the last content line.(no needed, just needed for regex algurithm)
  25. newHtml=''
  26. for localVarsDict in LoopSource[regGroups[1]]:
  27. sec=ConvertTemplateCode(regGroups[2])
  28. sec=ConvertTemplateCode(sec,localVarsDict)
  29. newHtml+=sec
  30. result=result.replace(regGroups[0],newHtml)
  31. return result
  32. class mail_sender:
  33. def __init__(self):
  34. self.context = ssl.create_default_context()
  35. self.server=None
  36. def connect(self):
  37. self.server = smtplib.SMTP(SMTP_SERVER,SMTP_PORT_SSL)
  38. self.server.ehlo() # Can be omitted
  39. self.server.starttls(context=self.context) # Secure the connection
  40. self.server.ehlo() # Can be omitted
  41. self.server.login(SENDER_EMAIL, PASSWORD)
  42. def send(self,to,msg:MIMEMultipart):
  43. msg['To'] = to
  44. self.server.sendmail(SENDER_EMAIL, to, msg.as_string())
  45. def close(self):
  46. self.server.quit()
  47. class root:
  48. def __init__(self,env,db):
  49. self.env=env
  50. self.db=env.open_db(db)
  51. self.keys=[]
  52. self.mail_keys={}
  53. def get_random_string(self,length):
  54. letters = string.ascii_lowercase+string.digits+string.ascii_uppercase
  55. return random.choices(letters, k=length)
  56. def expire_key(self,enum,index):
  57. del enum[index]
  58. @cherrypy.expose
  59. def index(self):
  60. # generate a temporary key to verify registeration
  61. key=''
  62. while key not in self.keys:
  63. key=self.get_random_string(16)
  64. self.keys.append(key)
  65. # expire key after 15 minutes
  66. threading.Timer(15*60*60,self.expire_key,(self.keys,self.keys.index(key))).start()
  67. return ConvertTemplateCode('HOME_PAGE',{'key':key})
  68. @cherrypy.expose
  69. def register(self,key=None,uni_code=None,email=None,**args):
  70. if key in self.keys:
  71. # register
  72. with self.env.begin(self.db) as txn:
  73. if txn.get(uni_code) == None:
  74. # new user. prepairing for registration
  75. ms=mail_sender()
  76. ms.connect()
  77. msg = MIMEMultipart('alternative')
  78. msg['From'] = EMAIL_SENDER_NAME
  79. msg['Subject'] = REGISTRATION_MAIL_SUBJECT
  80. key=''
  81. while key not in self.mail_keys:
  82. key=self.get_random_string(36)
  83. self.mail_keys[key]=email
  84. # expire key after 30 minutes
  85. threading.Timer(30*60*60,self.expire_key,(self.mail_keys,key)).start()
  86. news_html=ConvertTemplateCode('REGISTRATION_MAIL_BODY',args+{'link':WEB_SERV_ROOT+'verify?q='+key})
  87. msg.attach(MIMEText(news_html,'html'))
  88. ms.send(email,msg)
  89. return ConvertTemplateCode('VARIFY_MAIL_SENT',args)
  90. raise cherrypy.HTTPError(404)
  91. def run_web_serv(env,db):
  92. conf = {"global":
  93. {
  94. "server.socket_host": WEB_SERV_BIND_TO,
  95. "server.socket_port": WEB_SERV_PORT,
  96. "log.screen": WEB_SERV_LOG,
  97. "log.access_file": WEB_SERV_ACCESS_FILE,
  98. "log.error_file": WEB_SERV_ERROR_FILE,
  99. "tools.staticdir.root": WEB_SERV_STATIC_ROOT,
  100. "tools.staticdir.on": WEB_SERV_STATIC_ON,
  101. "tools.staticdir.dir": WEB_SERV_STATIC_DIR
  102. }
  103. }
  104. cherrypy.tree.mount(root(env,db),'/',conf)
  105. cherrypy.engine.start()
  106. def stopWebServ():
  107. cherrypy.server.bus.exit()
  108. cherrypy.engine.block()