aboutsummaryrefslogblamecommitdiff
path: root/flakes/paste/paste/paste.py
blob: 86666b8697d1b4a8ab969842bcc608e75190fb5d (plain) (tree)



























































































































                                                                                                               
import os
import secrets
from flask import Flask, abort, request, Response, url_for
from pygments.formatters.html import HtmlFormatter
from pygments import highlight
import pygments.lexers as lexers
import base64
import magic
import mimetypes

magic = magic.Magic(mime=True)

config = {
        "directory": os.environ["PASTE_DIRECTORY"],
        "self_paste_id": "abcd123",
        "max_content_length": 16 * 1000 * 1000
        }

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = config["max_content_length"]

def file_location(paste_id):
    if paste_id == config["self_paste_id"]:
        return os.path.realpath(__file__)
    else:
        return os.path.join(config['directory'], paste_id + ".dat")

def read_paste(paste_id):
    file = file_location(paste_id)
    if os.path.isfile(file):
        content = open(file, "rb").read()
        mime = magic.from_buffer(content)
        if mime.startswith("text/x-script."):
            mime="text/plain"
        return (content, mime)
    else:
        abort(404)

def generate_paste_id(n=3, attempts=0):
    path = secrets.token_hex(n)[:n]
    file = file_location(path)
    if os.path.isfile(file):
        attempts = attempts + 1
        if attempts > 5:
            n = n + 1
        return generate_paste_id(n, attempts)
    return path

@app.route('/', methods=["GET"])
def index():
    return Response('''<pre>
$ curl -X POST --data-binary @{self} {host}
{paste}

-> GET {paste}
   guesses mimetype
-> GET {paste}/raw
   text/plain
-> GET {paste}/bin
   application/octet-stream
-> GET {paste}/b64
   base64 encoded
-> GET {paste}/ub64
   tries to decode base64
-> GET {paste}/python
   pretty-print python (replace with anything known by pygments)
-> GET {paste}/guess
   pretty-print (language guessed by pygments)
-> GET {paste}/download
   force download of file
</pre>
<a href="{paste}/py">Get the source</a>
'''.format(host=url_for('post_paste', _external=True, _scheme="https"),
                 paste=url_for('get_paste', _external=True, _scheme="https", paste_id=config["self_paste_id"]),
                 self=os.path.basename(__file__)
                 ), mimetype="text/html")

@app.route('/', methods=["POST"])
def post_paste():
    content = request.get_data()
    paste_id = generate_paste_id()
    with open(file_location(paste_id), "wb") as f:
        f.write(content)
    return url_for('get_paste', _external=True, _scheme="https", paste_id=paste_id) + "\n"


@app.route('/<paste_id>', methods=["GET"])
def get_paste(paste_id):
    content, mime = read_paste(paste_id)
    return Response(content, mimetype=mime)

@app.route('/<paste_id>/<lang>', methods=["GET"])
def get_paste_with(paste_id, lang):
    content, mime = read_paste(paste_id)
    if lang == "raw":
        return Response(content, mimetype="text/plain")
    elif lang == "bin":
        return Response(content, mimetype="application/octet-stream")
    elif lang == "b64":
        return Response(base64.encodebytes(content), mimetype="text/plain")
    elif lang == "download":
        extension = mimetypes.guess_extension(mime, strict=False)
        if extension is None:
            cd = "attachment"
        else:
            cd = 'attachment; filename="{}{}"'.format(paste_id, extension)
        return Response(content, mimetype=mime,
                headers={"Content-Disposition": cd})
    elif lang == "ub64":
        try:
            return base64.b64decode(content)
        except:
            abort(400)
    try:
        if lang == "guess":
            lexer = lexers.guess_lexer(content)
        else:
            lexer = lexers.find_lexer_class_by_name(lang)()
    except:
        abort(400)
    fmter = HtmlFormatter(
        noclasses=True, full=True, style="colorful", linenos="table")

    return Response(highlight(content, lexer, fmter), mimetype="text/html")