Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions paste/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand All @@ -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))

Expand All @@ -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
Expand All @@ -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('/<string(length=4):b64>')
@paste.route('/<string(length=4):b64>/<lexer>')
@paste.route('/<string(length=4):b66>')
@paste.route('/<string(length=4):b66>/<lexer>')
@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:
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 8 additions & 5 deletions url/views.py
Original file line number Diff line number Diff line change
@@ -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('/<string(length=3):b85>')
@url.route('/<string(length=3):b66>')
@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:
Expand All @@ -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)
34 changes: 11 additions & 23 deletions util.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand All @@ -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)