aboutsummaryrefslogtreecommitdiff
path: root/flakes/paste/paste/paste.py
blob: 86666b8697d1b4a8ab969842bcc608e75190fb5d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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")