· 6 years ago · Jul 05, 2019, 01:06 PM
1"""
2Document Validator
3
4This code allows you to upload documents and later check whether they have been modified.
5
6This tool accepts .txt files.-
7
8Technologies used are flask, flask_mail, sha256, IPFS and sqlite
9"""
10
11from flask import Flask, render_template, request, send_file
12from flask_mail import Mail, Message
13from hashlib import sha256
14from sqlite3 import connect
15from io import BytesIO
16import random
17import ipfshttpclient
18
19# Create Flask app
20app = Flask(__name__)
21
22# Configure the app
23app.config["TEMPLATES_AUTO_RELOAD"] = True
24email = "YOUR_USERNAME"
25password = "YOUR_PASSWORD"
26mail_settings = {
27 "MAIL_SERVER": "smtp.gmail.com",
28 "MAIL_PORT": 465,
29 "MAIL_USE_TLS": False,
30 "MAIL_USE_SSL": True,
31 "MAIL_USERNAME": email,
32 "MAIL_PASSWORD": password
33}
34app.config.update(mail_settings)
35
36# Create the mail and link it to flask
37mail = Mail(app)
38
39# Create IPFS client
40client = ipfshttpclient.connect("/ip4/127.0.0.1/tcp/5001")
41
42# Connect to sqlite
43connection = connect("C:\\Users\\Dhruv\\PycharmProjects\\DocumentValidation\\documents.db", check_same_thread=False)
44cursor = connection.cursor()
45
46# Create table if not already created
47table = '''CREATE TABLE IF NOT EXISTS Documents
48 (ID VARCHAR(16) PRIMARY KEY,
49 HASH VARCHAR(64))'''
50cursor.execute(table)
51
52
53@app.route("/")
54def index():
55 """ Ask the user to enter the document """
56 return render_template("index.html")
57
58
59@app.route("/send_mail", methods=["GET", "POST"])
60def send_mail():
61 """ Send mail with the content accepted from the form """
62
63 if request.method == "POST":
64
65 # Get all parameters from the form
66 sender = request.form.get("sender")
67 recipient = request.form.get("recipient")
68 subject = request.form.get("subject")
69 content = request.form["content"]
70 file = request.files["file"]
71
72 # Generate id for the inputted document
73 key = ''.join(random.choice('0123456789ABCDEF') for i in range(16))
74
75 # Make sure key is unique
76 while True:
77 command = "SELECT * FROM Documents WHERE ID = '{}'".format(key)
78 cursor.execute(command)
79 result = cursor.fetchall()
80 if not result:
81 break
82 key = ''.join(random.choice('0123456789ABCDEF') for i in range(16))
83
84 # Upload the file to IPFS
85 ipfs_hash = client.add_bytes(file.read())
86
87 # Create the body of the mail
88 html = 'Sender : {} <br><br> {} <br><br> <a href="http://127.0.0.1:5000/verify?id={}">Verification Link</a> ' \
89 '<br><br> <a href="http://127.0.0.1:5000/download?key={}">Download link</a>'\
90 .format(sender, content, key, ipfs_hash)
91
92 # Store the hashcode in the table
93 file.seek(0)
94 hashcode = sha256(file.read()).hexdigest()
95 command = "INSERT INTO Documents (ID, HASH) VALUES ('{}', '{}')".format(key, hashcode)
96 cursor.execute(command)
97 connection.commit()
98
99 # Send the mail
100 with app.app_context():
101 # Create the message to be sent
102 message = Message(
103 subject=subject,
104 sender=app.config.get("MAIL_USERNAME"),
105 recipients=[recipient],
106 html=html
107 )
108
109 # Attach the file to it
110 file.seek(0)
111 message.attach("file.txt", "text/plain", file.read())
112
113 mail.send(message)
114
115 # Success
116 return render_template("success.html", code="The mail has been sent")
117
118 else:
119 # Access via post request
120 return render_template("index.html")
121
122
123@app.route("/verify", methods=["GET", "POST"])
124def verify():
125 """ Ask the user to upload the document to be verified """
126 return render_template("upload.html", url="/validate?id={}".format(request.args.get("id")))
127
128
129@app.route("/validate", methods=["GET", "POST"])
130def validate():
131 """ Display whether the document has been modified"""
132
133 if request.method == "POST":
134
135 # Get the required fields from the form and the url
136 file = request.files["file"]
137 key = request.args.get("id")
138
139 # Check all fields are present
140 if not key or not file:
141 return render_template("apology.html", code="All fields are not present")
142
143 # Query database
144 hashcode = sha256(file.read()).hexdigest()
145 command = "SELECT * FROM Documents WHERE ID = '{}' AND HASH = '{}'".format(key, hashcode)
146 cursor.execute(command)
147 result = cursor.fetchall()
148
149 # Display whether the document was tampered or not
150 if not result:
151 return render_template("success.html", code="The document has been modified")
152 else:
153 return render_template("success.html", code="The document has not been modified")
154
155 else:
156 return verify()
157
158
159@app.route("/download", methods=["GET", "POST"])
160def download():
161 """Get the required file from IPFS and send it to the user"""
162 key = request.args.get("key")
163
164 # Check key field has been provided
165 if not key:
166 return render_template("apology.html", code="The URL provided is incorrect")
167
168 # Check hash is correct
169 try:
170 byte = client.cat(key)
171 except ipfshttpclient.exceptions.ErrorResponse:
172 return render_template("apology.html", code="The URL provided is incorrect")
173
174 # Write the bytes to a file
175 file = BytesIO()
176 file.write(byte)
177 file.seek(0)
178
179 # Send the file to the user
180 return send_file(file, attachment_filename="file.txt", as_attachment=True)
181
182
183# Run the app
184if __name__ == "__main__":
185 app.run(
186 debug=True
187 )