Commit 6f033ba4 by Luciano Barletta

First commit

0 parents
#-*- coding: utf-8 -*-
from flask import Flask, render_template, json, request, url_for
from werkzeug.datastructures import FileStorage
import os
import ipdb
from process_message import Process
import time, threading
from python_arptable import get_arp_table
app = Flask(__name__)
retry_timer = 10
@app.route('/')
def main():
return render_template('index.html')
@app.route('/init', methods = ['GET', 'POST'])
def init():
mac = mac_from_ip(request.remote_addr)
if mac == None:
return "Error de inicializacion, no se pudo conseguir la MAC"
if not os.path.exists(mac):
os.mkdir(mac)
return key(mac)
def key(dir):
os.system("openssl genrsa -out ./" + dir + "/rsa_key.pri 2048") # private key
os.system("openssl rsa -in ./" + dir + "/rsa_key.pri -out ./" + dir + "/rsa_key.pub -outform PEM -pubout") # public key
f = open("./" + dir + "/rsa_key.pub", "r")
key = f.read()
f.close()
return key
def mac_from_ip(ip):
os.system("ping " + ip + " c1")
for i in get_arp_table():
if i['IP address'] == ip:
return i['HW address']
return None
@app.route('/data', methods = ['POST'])
def data():
dir = mac_from_ip(request.remote_addr)
if not os.path.exists(dir):
return "Debe llamar a /init primero"
key = request.files.get('key')
if key != None:
key.save("./" + dir + "/key")
request.files['data'].save("./" + dir + "/data")
return ""
@app.route('/msg', methods = ['POST'])
def msg():
process = Process('messages.db')
dir = mac_from_ip(request.remote_addr)
if not os.path.exists(dir):
return "Debe llamar a /init primero"
# symetric key was sent, decrypt data
if os.path.exists("./" + dir + "/key"):
# decrypt random key with stored private key and store in host folder
os.system("openssl rsautl -decrypt -inkey ./" + dir + "/rsa_key.pri -in ./" + dir + "/key -out ./" + dir + "/key")
# decrypt JSON with decrypted random key and store in dir folder
os.system("openssl enc -d -aes-256-cbc -in ./" + dir + "/data -out ./" + dir + "/data -pass file:./" + dir + "/key")
# delete key
os.system("rm ./" + dir + "/key")
query = {
'dir' : dir,
'serv' : request.values['serv'],
'dest' : request.values['dest'],
'type' : request.values['type']
}
id = process.store(query)
os.system("mv ./data ./" + id)
@app.route('/cons', methods = ['POST'])
def cons():
process = Process('messages.db')
id_query = request.form['id']
query_state = process.lookup(id_query)
return query_state
def attempt():
process = Process('messages.db')
process.send()
threading.Timer(retry_timer, attempt).start()
if __name__ == "__main__":
# starts attempt daemon
attempt()
app.run("0.0.0.0")
\ No newline at end of file
import sqlite3
from sqlite3 import Error
import ipdb
import os
from services import serviceFactory, Datatypes, Services
class DBconnection:
def __init__(self,db):
# main table
self.db = db
self.query("CREATE TABLE IF NOT EXISTS msg(\
id integer PRIMARY KEY,\
dir text,\
serv text CHECK( serv IN ('wpp1', 'wwp2', 'telegram', 'sms') ),\
dest text CHECK( LENGTH(dest) <= 13 ),\
type text CHECK( type IN ('text', 'file', 'multimedia') ),\
state text CHECK( state IN ('delivered', 'queued') ) )")
# delivered messages that were informed
self.query("CREATE TABLE IF NOT EXISTS history(\
id integer PRIMARY KEY,\
dir text,\
serv text CHECK( serv IN ('wpp1', 'wwp2', 'telegram', 'sms') ),\
dest text CHECK( LENGTH(dest) <= 13 ),\
type text CHECK( type IN ('text', 'file', 'multimedia') ),\
state text CHECK( state IN ('delivered', 'queued') ) )")
def query(self,query,*args):
con = sqlite3.connect(self.db)
cursor = con.cursor()
entities = None
for ar in args:
entities = ar
if entities:
cursor.execute(query,entities)
else:
cursor.execute(query)
if query.find("INSERT") == 0:
cursor.execute("SELECT last_insert_rowid()")
rows = cursor.fetchall()
con.commit()
con.close()
return rows
@staticmethod
def parseToTable(rows):
dictarray = []
for row in rows:
dictarray.append(
{
'id' : row[0],
'dir' : row[1],
'serv' : row[2],
'dest' : row[3],
'type' : row[4],
'state' : row[5]
}
)
return dictarray
class Process:
def __init__(self,db):
self.db = db
self.conn = DBconnection(db)
# stores the message and returns its id
def store(self,query):
# service is wrong
if not Services.validate(query['serv']):
return "No existe el servicio '" + query['serv'] + "'"
# message can't be sent by this service
if not serviceFactory(query['serv']).validate(query['type']):
return "El servicio '" + query['serv'] + "' no puede enviar el tipo '" + query['type'] + "'"
entities = (query['dir'],query['serv'],query['dest'],query['type'],'queued')
rows = self.conn.query("INSERT INTO msg(dir,serv,dest,type,state) VALUES(?,?,?,?,?)", entities)
return str(rows[0][0])
# tries to send all messages available
def send(self):
rows = self.conn.query("SELECT * FROM msg WHERE state = 'queued'")
for query in DBconnection.parseToTable(rows):
# if folder doesn't exists, erase the message request, it can't be read anyway
if not os.path.exists(query['dir']):
self.conn.query("DELETE FROM msg WHERE id = ?",(query['id'],))
serv = serviceFactory(query['serv'])
success = serv.send(query)
if success:
# save as delivered
self.conn.query("UPDATE msg SET state = 'delivered' WHERE id = ?",(query['id'],))
# returns the state of a message given its id
# stores the message to history if delivered
def lookup(self,id):
rows = self.conn.query("SELECT * FROM msg WHERE id = ?",(id,))
if rows == []:
return "El id " + str(id) + " no existe"
rows = DBconnection.parseToTable(rows)
row = rows[0]
if row['state'] == "delivered":
self.conn.query("DELETE FROM msg WHERE id = ?",(id,))
self.conn.query("INSERT INTO history(dir,serv,dest,type,state) VALUES(?,?,?,?,?)", (row['dir'],row['serv'],row['dest'],row['type'],row['state']))
return row['state']
\ No newline at end of file
import requests
import json
from abc import ABC, abstractmethod
class Services:
wpp1 = "wpp1"
@staticmethod
def validate(serv):
if serv == Services.wpp1:
return True
return False
# move this to be more accessible, everything needs to use it...
# or perhaps I can work around it
class Datatypes:
text = "text"
@staticmethod
def validate(datatype):
if datatype == Datatypes.text:
return True
return False
class ServiceBase(ABC):
@abstractmethod
def send(self,data):
pass
@abstractmethod
def validate(self,serv):
pass
class Wpp1(ServiceBase):
URL = "https://www.waboxapp.com/api/send/chat"
token = "fd378337aebead91c2eb25209aa51a7d5ce9754ea1718"
uid = "5493413674832"
def send(self,data):
if data['type'] == Datatypes.text:
f = open("./" + data['dir'] + "/data")
text = f.read()
f.close()
result = requests.get(url = Wpp1.URL,params = {
'token':Wpp1.token,
'uid':Wpp1.uid,
'to':data['dest'],
'text':text
})
return result.json()['success']
return False
def validate(self,serv):
return Datatypes.validate(serv)
def serviceFactory(serv):
if serv == Services.wpp1:
return Wpp1()
return None
Nothing to see here...
\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!