diff --git a/settings.py b/settings.py
new file mode 100644
index 0000000..bbf6c2a
--- /dev/null
+++ b/settings.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python3
+DEBUG = True
+DATABASE = "urlshort.db"
+FOOBAR = "PONG"
+DEFAULT_SCHEMA = '''
+CREATE TABLE IF NOT EXISTS pastes (id INT PRIMARY KEY, paste_url TEXT NOT NULL, target TEXT NOT NULL, method_id INT NOT NULL, ip TEXT NOT NULL, timestamp TEXT NOT NULL);
+
+CREATE TABLE IF NOT EXISTS methods (id INT PRIMARY KEY, name TEXT NOT NULL);
+
+CREATE TABLE IF NOT EXISTS access (id INT PRIMARY KEY NOT NULL, paste_id TEXT NOT NULL, ip TEXT NOT NULL, user_agent TEXT NOT NULL);
+'''
diff --git a/templates/new_paste.html b/templates/new_paste.html
new file mode 100644
index 0000000..fa314b7
--- /dev/null
+++ b/templates/new_paste.html
@@ -0,0 +1,2 @@
+
+http://localhost:5000/{{paste_id}}
diff --git a/urlshort.db b/urlshort.db
new file mode 100644
index 0000000..57aceec
Binary files /dev/null and b/urlshort.db differ
diff --git a/urlshort.py b/urlshort.py
new file mode 100644
index 0000000..bf87ca3
--- /dev/null
+++ b/urlshort.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+from flask import Flask, g, request, render_template, redirect
+import sqlite3
+import random
+import string
+import math
+import time
+from flask_limiter import Limiter
+from contextlib import closing
+from urllib.parse import urlparse
+
+app = Flask(__name__)
+app.config.from_object("settings")
+limiter = Limiter(app, global_limits=["2 per minute", "100 per day"])
+
+@app.before_request
+def before_request():
+ g.db = connect_db()
+
+@app.teardown_request
+def teardown_request(exception):
+ db = getattr(g, "db", None)
+ if db is not None:
+ db.close()
+
+@app.route("/")
+@limiter.exempt
+def root():
+ return "Welcome to root!"
+
+@app.route("/")
+@limiter.exempt
+def paste(pasteID):
+ target = query_db("SELECT target FROM pastes WHERE paste_url = ?", [pasteID], one=True)
+ if target is None:
+ return "Shorturl not found!"
+ else:
+ url = urlparse(target["target"])
+ if url.scheme is "":
+ target = "http://" + url.path
+ else:
+ target = url.scheme + "://" + url.netloc + url.path
+ return redirect(target, 301)
+
+@app.route("/new")
+@limiter.exempt
+def new_paste():
+ target_url = request.args.get("target", "")
+ paste_id = add_redirect(target_url, 1)
+ return render_template("new_paste.html", paste_id=paste_id)
+
+def add_redirect(target_url, method_id):
+ paste_id = gen_new_id(5)
+ ip = request.remote_addr
+ timestamp = int(time.time())
+ db = getattr(g, "db", None)
+ if db is not None:
+ query = "INSERT INTO pastes (paste_url, target, method_id, ip, timestamp) VALUES (:paste_url, :target, :method_id, :ip, :timestamp);"
+ args = {"paste_url" : paste_id, "target" : target_url, "method_id" : "1", "ip" : ip, "timestamp" : timestamp}
+ db.cursor().execute(query, args)
+ db.commit()
+ db.close()
+ return paste_id
+
+def gen_new_id(length):
+ while True:
+ new_id = "".join([random.choice(string.ascii_letters + string.digits) for n in range(length)])
+ if query_db("SELECT * FROM pastes WHERE paste_url = ?", [new_id], one=True) is None:
+ break
+ return new_id
+
+def query_db(query, args=(), one=False):
+ with closing(connect_db()) as db:
+ db.row_factory = sqlite3.Row
+ cur = db.cursor().execute(query, args)
+ rv = cur.fetchall()
+ cur.close()
+ return (rv[0] if rv else None) if one else rv
+
+def init_db():
+ with closing(connect_db()) as db:
+ db.cursor().executescript(app.config["DEFAULT_SCHEMA"])
+ db.commit()
+
+def connect_db():
+ return sqlite3.connect(app.config["DATABASE"])
+
+if __name__ == "__main__":
+ app.run(debug=app.config["DEBUG"])