diff --git a/app.py b/app.py index 0361245..508ac4d 100644 --- a/app.py +++ b/app.py @@ -5,10 +5,11 @@ import os from dataclasses import dataclass from pathlib import Path -from flask import Flask, jsonify, render_template, send_from_directory, abort +from flask import Flask, jsonify, render_template, send_from_directory, abort, request from pygments import highlight from pygments.formatters import HtmlFormatter from pygments.lexers import TextLexer, get_lexer_for_filename +from pygments.util import ClassNotFound app = Flask(__name__, static_folder=None) @@ -53,14 +54,14 @@ def get_repositories(): description_file = os.path.join(repo_path, "description") if os.path.exists(description_file): try: - with open(description_file, "r") as f: + with open(description_file, "r", encoding="utf-8") as f: description = f.read().strip() if ( description == "Unnamed repository; edit this file 'description' to name the repository." ): description = "No description available" - except _ as _: + except OSError: pass display_name = item @@ -99,29 +100,52 @@ def serve_scripts(filename): @app.route("/gist/") def serve_gist(filename): - file_path = os.path.join(GIST_PATH, filename) + base = Path(GIST_PATH).resolve() + target = (base / filename).resolve() + if base not in target.parents and base != target: + abort(404) - if not os.path.exists(file_path) or not os.path.isfile(file_path): + if not target.exists() or not target.is_file(): abort(404) try: - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() + content = target.read_text(encoding="utf-8") except UnicodeDecodeError: return "Binary file cannot be displayed", 400 + except OSError: + abort(404) try: - lexer = get_lexer_for_filename(filename) - except: + lexer = get_lexer_for_filename(target.name) + except ClassNotFound: lexer = TextLexer() - formatter = HtmlFormatter(style="default", cssclass="highlight", linenos=True, noclasses=True, cssstyles="padding: 20px; font-size: 18px; background-color: #f8f8f8;") + formatter = HtmlFormatter( + style="default", + cssclass="highlight", + linenos=True, + noclasses=True, + cssstyles="padding: 20px; font-size: 18px; background-color: #f8f8f8;", + ) highlighted = highlight(content, lexer, formatter) - highlighted = highlighted.replace('', '') + highlighted = highlighted.replace( + '', '' + ) return render_template("gist.html", filename=filename, highlighted_code=highlighted) +@app.route("/") +def serve_gist_root(filename): + head = filename.split("/", 1)[0] + if head in {"styles", "scripts", "api", "gist"}: + abort(404) + host = request.host.split(":", 1)[0] + if host in {"gist.barrettruth.com", "localhost", "127.0.0.1"}: + return serve_gist(filename) + abort(404) + + @app.errorhandler(404) def not_found(error): return render_template("404.html"), 404 @@ -141,4 +165,5 @@ def get_repo(repo_id): if __name__ == "__main__": - app.run(host="0.0.0.0", port=8000, debug=True) + app.run(host="0.0.0.0", port=5000, debug=True) + diff --git a/wsgi.py b/wsgi.py index 11e7de6..6026b0f 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,4 +1,4 @@ from app import app if __name__ == "__main__": - app.run() \ No newline at end of file + app.run()