deploy.py 3.97 KB
#-*- coding: utf-8 -*-
from flask import Flask, render_template, json, request, url_for
from werkzeug.datastructures import FileStorage
from process import Process
from python_arptable import get_arp_table
from enums import States, Table
import os, ipdb, time, threading, random, datetime

app = Flask(__name__)

# carpeta de los mensajes
msgfolder = "msg/"
# tiempo para reintentar mensajhes
retry_timer = 10
# tiempo para limpieza
clean_timer = 20
# largo de los nombres de las carpetas bajo msg/
prefix_lenght = 16
# tiempo límite que debe pasar para eliminar cosas
operation_timer = 86400
# conección a base de datos
process = Process("messages.db")

@app.route('/')
def main():
  return render_template('index.html')

# Devuelve la llave pública del server
@app.route('/key', methods = ['GET', 'POST'])
def key():
  f = open("rsa_key.pub", "r")
  key = f.read()
  f.close()
  return key

# Guarda archivos del emisor en una nueva carpeta (desencriptados)
# Pide guardar en base de datos una preinstancia del mensaje
@app.route('/data', methods = ['POST'])
def data():
  prefix = newprefix()
  path = msgfolder + prefix + "/"
  os.mkdir(path)

  key = request.files.get('key')
  if key:
    request.files[file].save(path + "rand.key.enc")
    # denecripto llave simétrica con mi llave privada y la guardo en la carpeta del emisor
    os.system("openssl rsautl -decrypt -inkey rsa_key.pri -in " + path + "rand.key.enc -out " + path + "rand.key")
    os.remove(path + "rand.key.enc")

  for file in request.files:
    # si hay llave y no es esta
    if key and file != "key":
      request.files[file].save(filepath + ".enc")
      # desencripto archivo con la llave simétrica y lo guardo en la carpeta del emisor 
      os.system("openssl enc -d -aes-256-cbc -in " + filepath + ".enc -out " + filepath + " -pass file:" + path + "rand.key")
      os.remove(filepath + ".enc")
    else:
      request.files[file].save(path + request.files[file].filename)

  if key:
    os.remove(path + "rand.key")
  
  return str(process.datastore(path))

# Devuelve un string al azar entre [0-9,a-z,A-Z]
def newprefix():
  prefix = ""
  i = 0
  while i < prefix_lenght:
    range = random.randrange(3)
    if range == 0:
      prefix += chr(random.randrange(48,58))
    if range == 1:
      prefix += chr(random.randrange(65,91))
    if range == 2:
      prefix += chr(random.randrange(97,123))
    i += 1
  return prefix

# Guarda los parámetros de los archivos enviados en /data
@app.route('/msg', methods = ['POST'])
def msg():
  id = request.values['id']
  query = {
    Table.id : id,
    Table.serv : request.values['serv'],
    Table.dest : request.values['dest'],
    Table.type : request.values['type']
  }
  state = process.paramstore(query)
  return state

# Consulta el estado de un mensaje dado su id
@app.route('/cons', methods = ['POST'])
def cons():
  id_query = request.values['id']
  row = process.lookup(id_query)
  if type(row) == str:  # error
    return row 
  if row[Table.state] == States.delivered:
    os.system("rm -r " + row[Table.path])
  return str(row[Table.state])

# Intenta enviar mensajes
def attempt():
  p = Process('messages.db')
  p.send()
  threading.Timer(retry_timer, attempt).start()

# Limpia basura
def clean():
  p = Process('messages.db')
  paths = p.paths()
  now = datetime.datetime.now()

  for folder in paths:
    mtime = os.path.getmtime(folder)
    # Si la carpeta existe por más de X segundos, borrala
    if int(now.strftime("%Y%m%d%H%M%S")) - int(time.strftime("%Y%m%d%H%M%S")) > operation_timer:
      os.system("rm -r " + folder)

  threading.Timer(clean_timer, clean).start()

# Inicio del servicio
if __name__ == "__main__":
  # Genero llaves
  os.system("openssl genrsa -out rsa_key.pri 4096") # private key
  os.system("openssl rsa -in rsa_key.pri -out rsa_key.pub -outform PEM -pubout") # public key
  # Demonio attempt
  attempt()
  # Demonio clean
  clean()
  # Borro y creo msg/ por limpieza
  if os.path.exists(msgfolder):
    os.system("rm -r " + msgfolder)
  os.mkdir(msgfolder)
  app.run("0.0.0.0")