Use template responses

This commit is contained in:
Mia Herkt 2020-12-29 04:06:52 +01:00
parent 5db62c2dbf
commit d815d6855f
Signed by untrusted user: mia
GPG key ID: 72E154B8622EC191
6 changed files with 79 additions and 105 deletions

119
fhost.py
View file

@ -19,12 +19,12 @@
and limitations under the License. and limitations under the License.
""" """
from flask import Flask, abort, escape, make_response, redirect, request, send_from_directory, url_for, Response from flask import Flask, abort, make_response, redirect, request, send_from_directory, url_for, Response, render_template
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand from flask_migrate import Migrate, MigrateCommand
from jinja2.exceptions import *
from hashlib import sha256 from hashlib import sha256
from humanize import naturalsize
from magic import Magic from magic import Magic
from mimetypes import guess_extension from mimetypes import guess_extension
import os, sys import os, sys
@ -192,7 +192,7 @@ def store_file(f, addr):
if existing: if existing:
if existing.removed: if existing.removed:
return legal() abort(451)
epath = getpath(existing.sha256) epath = getpath(existing.sha256)
@ -256,7 +256,7 @@ def store_file(f, addr):
def store_url(url, addr): def store_url(url, addr):
if is_fhost_url(url): if is_fhost_url(url):
return segfault(508) abort(400)
h = { "Accept-Encoding" : "identity" } h = { "Accept-Encoding" : "identity" }
r = requests.get(url, stream=True, verify=False, headers=h) r = requests.get(url, stream=True, verify=False, headers=h)
@ -277,12 +277,9 @@ def store_url(url, addr):
return store_file(f, addr) return store_file(f, addr)
else: else:
hl = naturalsize(l, binary = True) abort(413)
hml = naturalsize(app.config["MAX_CONTENT_LENGTH"], binary=True)
return "Remote file too large ({0} > {1}).\n".format(hl, hml), 413
else: else:
return "Could not determine remote file size (no Content-Length in response header; shoot admin).\n", 411 abort(411)
@app.route("/<path:path>") @app.route("/<path:path>")
def get(path): def get(path):
@ -294,7 +291,7 @@ def get(path):
if f and f.ext == p[1]: if f and f.ext == p[1]:
if f.removed: if f.removed:
return legal() abort(451)
fpath = getpath(f.sha256) fpath = getpath(f.sha256)
@ -351,76 +348,7 @@ def fhost():
abort(400) abort(400)
else: else:
fmts = list(app.config["FHOST_EXT_OVERRIDE"]) return render_template("index.html")
fmts.sort()
maxsize = naturalsize(app.config["MAX_CONTENT_LENGTH"], binary=True)
maxsizenum, maxsizeunit = maxsize.split(" ")
maxsizenum = float(maxsizenum)
maxsizehalf = maxsizenum / 2
if maxsizenum.is_integer():
maxsizenum = int(maxsizenum)
if maxsizehalf.is_integer():
maxsizehalf = int(maxsizehalf)
return """<pre>
THE NULL POINTER
================
HTTP POST files here:
curl -F'file=@yourfile.png' {0}
You can also POST remote URLs:
curl -F'url=http://example.com/image.jpg' {0}
Or you can shorten URLs:
curl -F'shorten=http://example.com/some/long/url' {0}
File URLs are valid for at least 30 days and up to a year (see below).
Shortened URLs do not expire.
Maximum file size: {1}
Not allowed: {5}
FILE RETENTION PERIOD
---------------------
retention = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
days
365 | \\
| \\
| \\
| \\
| \\
| \\
| ..
| \\
197.5 | ----------..-------------------------------------------
| ..
| \\
| ..
| ...
| ..
| ...
| ....
| ......
30 | ....................
0{2}{3}
{4}
ABUSE
-----
If you would like to request permanent deletion, please contact lachs0r via
IRC on Freenode, or send an email to lachs0r@(this domain).
Please allow up to 24 hours for a response.
</pre>
""".format(fhost_url(),
maxsize, str(maxsizehalf).rjust(27), str(maxsizenum).rjust(27),
maxsizeunit.rjust(54),
", ".join(app.config["FHOST_MIME_BLACKLIST"]))
@app.route("/robots.txt") @app.route("/robots.txt")
def robots(): def robots():
@ -428,35 +356,18 @@ def robots():
Disallow: / Disallow: /
""" """
def legal():
return "451 Unavailable For Legal Reasons\n", 451
@app.errorhandler(400) @app.errorhandler(400)
@app.errorhandler(404) @app.errorhandler(404)
@app.errorhandler(411)
@app.errorhandler(413)
@app.errorhandler(414) @app.errorhandler(414)
@app.errorhandler(415) @app.errorhandler(415)
def segfault(e): @app.errorhandler(451)
def ehandler(e):
try:
return render_template(f"{e.code}.html", id=id), e.code
except TemplateNotFound:
return "Segmentation fault\n", e.code return "Segmentation fault\n", e.code
@app.errorhandler(404)
def notfound(e):
return u"""<pre>Process {0} stopped
* thread #1: tid = {0}, {1:#018x}, name = '{2}'
frame #0:
Process {0} stopped
* thread #8: tid = {0}, {3:#018x} fhost`get(path='{4}') + 27 at fhost.c:139, name = 'fhost/responder', stop reason = invalid address (fault address: 0x30)
frame #0: {3:#018x} fhost`get(path='{4}') + 27 at fhost.c:139
136 get(SrvContext *ctx, const char *path)
137 {{
138 StoredObj *obj = ctx->store->query(shurl_debase(path));
-> 139 switch (obj->type) {{
140 case ObjTypeFile:
141 ctx->serve_file_id(obj->id);
142 break;
(lldb) q</pre>
""".format(os.getpid(), id(app), "fhost", id(get), escape(request.path)), e.code
@manager.command
def debug(): def debug():
app.config["FHOST_USE_X_ACCEL_REDIRECT"] = False app.config["FHOST_USE_X_ACCEL_REDIRECT"] = False
app.run(debug=True, port=4562,host="0.0.0.0") app.run(debug=True, port=4562,host="0.0.0.0")

15
templates/404.html Normal file
View file

@ -0,0 +1,15 @@
{% set pid = range(20,100)|random %}
<pre>Process {{ pid }} stopped
* thread #1: tid = {{ pid }}, {{ "{:#018x}".format(id(g)) }}, name = 'fhost'
frame #0:
Process {{ pid }} stopped
* thread #8: tid = {{ pid }}, {{ "{:#018x}".format(id(request)) }} fhost`get(path='{{ request.path }}') + 27 at fhost.c:139, name = 'fhost/responder', stop reason = invalid address (fault address: 0x30)
frame #0: {3:#018x} fhost`get(path='{{ request.path }}') + 27 at fhost.c:139
136 get(SrvContext *ctx, const char *path)
137 {
138 StoredObj *obj = ctx->store->query(shurl_debase(path));
-> 139 switch (obj->type) {
140 case ObjTypeFile:
141 ctx->serve_file_id(obj->id);
142 break;
(lldb) q</pre>

1
templates/411.html Normal file
View file

@ -0,0 +1 @@
Could not determine remote file size (no Content-Length in response header; shoot admin).

1
templates/413.html Normal file
View file

@ -0,0 +1 @@
Remote file too large ({{ request.headers["content-length"]|filesizeformat(True) }} > {{ config["MAX_CONTENT_LENGTH"]|filesizeformat(True) }}).

1
templates/451.html Normal file
View file

@ -0,0 +1 @@
451 Unavailable For Legal Reasons

45
templates/index.html Normal file
View file

@ -0,0 +1,45 @@
<pre>
THE NULL POINTER
================
{% set fhost_url = url_for("fhost", _external=True).rstrip("/") %}
HTTP POST files here:
curl -F'file=@yourfile.png' {{ fhost_url }}
You can also POST remote URLs:
curl -F'url=http://example.com/image.jpg' {{ fhost_url }}
Or you can shorten URLs:
curl -F'shorten=http://example.com/some/long/url' {{ fhost_url }}
File URLs are valid for at least 30 days and up to a year (see below).
Shortened URLs do not expire.
{% set max_size = config["MAX_CONTENT_LENGTH"]|filesizeformat(True) %}
Maximum file size: {{ max_size }}
Not allowed: {{ config["FHOST_MIME_BLACKLIST"]|join(", ") }}
FILE RETENTION PERIOD
---------------------
retention = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
days
365 | \\
| \\
| \\
| \\
| \\
| \\
| ..
| \\
197.5 | ----------..-------------------------------------------
| ..
| \\
| ..
| ...
| ..
| ...
| ....
| ......
30 | ....................
0{{ ((config["MAX_CONTENT_LENGTH"]/2)|filesizeformat(True)).split(" ")[0].rjust(27) }}{{ max_size.split(" ")[0].rjust(27) }}
{{ max_size.split(" ")[1].rjust(54) }}
</pre>