diff --git a/paste/views.py b/paste/views.py index bd31d36..3c40c2c 100644 --- a/paste/views.py +++ b/paste/views.py @@ -7,7 +7,7 @@ from db import cursor from paste import model -from util import highlight, redirect, request_content, id_url, b64_id, id_b64 +from util import highlight, redirect, request_content, id_url, b66_int, int_b66 paste = Blueprint('paste', __name__) @@ -30,7 +30,7 @@ def post(): if not id: id, uuid = model.insert(content) - url = id_url(b64=id_b64(id, filename=filename)) + url = id_url(b66=int_b66(id, filename=filename)) uuid = UUID(bytes=uuid) if uuid else '[redacted]' return redirect(url, "{}\nuuid: {}\n".format(url, uuid)) @@ -45,12 +45,12 @@ def put(uuid): id, _ = model.get_digest(content) if id: - url = id_url(b64=id_b64(id)) + url = id_url(b66=int_b66(id)) return redirect(url, "Paste already exists.\n", 409) id = model.put(uuid, content) if id: - url = id_url(b64=id_b64(id, filename=filename)) + url = id_url(b66=int_b66(id, filename=filename)) return redirect(url, "{} updated.\n".format(url), 200) return "Not found.\n", 404 @@ -61,19 +61,20 @@ def delete(uuid): uuid = UUID(uuid).bytes id = model.delete(uuid) if id: - url = id_url(b64=id_b64(id)) + url = id_url(b66=int_b66(id)) return redirect(url, "{} deleted.\n".format(url), 200) return "Not found.\n", 404 -@paste.route('/') -@paste.route('//') +@paste.route('/') +@paste.route('//') @cursor -def get(b64, lexer=None): - id = b64_id(b64) - if not id: +def get(b66, lexer=None): + try: + id = b66_int(b66) + except ValueError: return "Invalid id.\n", 400 - mimetype, _ = guess_type(b64) + mimetype, _ = guess_type(b66) content = model.get_content(id) if not content: diff --git a/requirements.txt b/requirements.txt index 4834efd..ab0b981 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,5 @@ Flask>=0.11-dev Werkzeug>=0.10-dev PyYAML>=3.11 mysql-connector-python>=2.0.2 -bitstring>=3.1.3 Pygments>=2.0.1 requests>=2.5.0 diff --git a/url/views.py b/url/views.py index bfbc67e..63f4c9b 100644 --- a/url/views.py +++ b/url/views.py @@ -1,15 +1,18 @@ from flask import Blueprint from db import cursor -from util import redirect, request_content, id_url, b85_id, id_b85 +from util import redirect, request_content, id_url, int_b66, b66_int from url import model url = Blueprint('url', __name__) -@url.route('/') +@url.route('/') @cursor -def get(b85): - id = b85_id(b85) +def get(b66): + try: + id = b66_int(b66) + except ValueError: + return 'Invalid id.\n', 400 content = model.get_content(id) if not content: @@ -32,5 +35,5 @@ def post(): if not id: id = model.insert(content) - url = id_url(b85=id_b85(id)) + url = id_url(b66=int_b66(id, 3)) return redirect(url, "{}\n".format(url), 200) diff --git a/util.py b/util.py index 612c9f7..825b081 100644 --- a/util.py +++ b/util.py @@ -1,9 +1,4 @@ from os import path -from base64 import urlsafe_b64encode, urlsafe_b64decode, b85encode, b85decode -from bitstring import Bits -import binascii - -from urllib.parse import quote, unquote from flask import Response, render_template, current_app, request, url_for @@ -12,6 +7,8 @@ from pygments.formatters import HtmlFormatter from pygments.util import ClassNotFound +b66c = 'QwdJxskgt6BE.levhL0zWNj8~1P_ZbHDq7YrpGOIX5CyimfK-cMoAR49FaUn3VT2Su' + def redirect(location, rv, code=302): response = current_app.response_class(rv, code) response.headers['Location'] = location @@ -38,26 +35,17 @@ def request_content(): return None, None -def id_b64(id, filename=None): - b64 = urlsafe_b64encode(Bits(length=24, int=int(id)).bytes) +def int_b66(i, length=4, filename=None): + i = int(i) + b66 = '' + while i != 0: + i, n = divmod(i, len(b66c)) + b66 = b66c[n] + b66 ext = path.splitext(filename)[1] if filename else None - return b''.join((b64, ext.encode('utf-8'))) if ext else b64 - -def b64_id(b64): - root, _ = path.splitext(b64) - - try: - return Bits(bytes=urlsafe_b64decode(root)).int - except binascii.Error: - pass - -def id_b85(id): - b85 = b85encode(Bits(length=16, int=int(id)).bytes) - return quote(b85) + return '{:{zero}>{length}}'.format(''.join(b66, ext) if ext else b66, length=length, zero=b66c[0]) -def b85_id(b85): - b85 = unquote(b85) - return Bits(bytes=b85decode(b85)).int +def b66_int(s): + return sum(b66c.index(c) * len(b66c) ** (len(s) - i - 1) for i, c in enumerate(s)) def id_url(**kwargs): return url_for('.get', _external=True, _scheme='https', **kwargs)