#!/usr/bin/env python3 """ Main script including runserver and delete-paste. """ import sys import re import hashlib import _thread as thread from zerobin.utils import ( settings, SettingsValidationError, drop_privileges, ensure_var_env, hash_password, ) from zerobin.routes import get_app from zerobin.paste import Paste from bottle import run import clize def runserver( *, host="", port="", debug=None, user="", group="", settings_file="", compressed_static=None, version=False, paste_id_length=None, server="cherrypy", ): if version: print("0bin V%s" % settings.VERSION) sys.exit(0) settings.HOST = host or settings.HOST settings.PORT = port or settings.PORT settings.USER = user or settings.USER settings.GROUP = group or settings.GROUP settings.PASTE_ID_LENGTH = paste_id_length or settings.PASTE_ID_LENGTH settings.DEBUG = bool(debug) if debug is not None else settings.DEBUG ensure_var_env() try: _, app = get_app(debug, settings_file, compressed_static, settings=settings) except SettingsValidationError as err: print("Configuration error: %s" % err.message, file=sys.stderr) sys.exit(1) thread.start_new_thread(drop_privileges, (settings.USER, settings.GROUP)) if settings.DEBUG: print(f"Admin URL: http://{settings.HOST}:{settings.PORT}{settings.ADMIN_URL}") run( app, host=settings.HOST, port=settings.PORT, reloader=True, server=server, ) else: run(app, host=settings.HOST, port=settings.PORT, server=server) # The regex parse the url and separate the paste's id from the decription key # After the '/paste/' part, there is several caracters, identified as # the uuid of the paste. Followed by a '#', the decryption key of the paste. paste_url = re.compile("/paste/(?P.*)#(?P.*)") def unpack_paste(paste): """Take either the ID or the URL of a paste, and return its ID""" try_url = paste_url.search(paste) if try_url: return try_url.group("paste_id") return paste def delete_paste(*pastes, quiet=False): """ Remove pastes, given its ID or its URL quiet: Don't print anything pastes: List of pastes, given by ID or URL """ for paste_uuid in map(unpack_paste, pastes): try: Paste.load(paste_uuid).delete() if not quiet: print("Paste {} is removed".format(paste_uuid)) except ValueError: if not quiet: print("Paste {} doesn't exist".format(paste_uuid)) def print_admin_url(): """ Print the route to the 0bin admin. The admin route is generated by zerobin so that bots won't easily bruteforce it. To get the full URL, simply preppend your website domain name to it. E.G: If this command prints: "/admin/f1cc3972a4b933c734b37906940cf69886161492ee4eb7c1faff5d7b5e92efb8" Then the admin url is: "http://yourdomain.com/admin/f1cc3972a4b933c734b37906940cf69886161492ee4eb7c1faff5d7b5e92efb8" Adapt "http" and "yourdomain.com" to your configuration. In debug mode, the dev server will print the url when starting. """ ensure_var_env() print(settings.ADMIN_URL) def set_admin_password(password): """ Set the password for the admin It will be stored as a scrypt hash in a file in the var dir. """ ensure_var_env() settings.ADMIN_PASSWORD_FILE.write_bytes(hash_password(password)) def main(): subcommands = [runserver, delete_paste, print_admin_url, set_admin_password] subcommand_names = [ clize.util.name_py2cli(name) for name in clize.util.dict_from_names(subcommands).keys() ] if len(sys.argv) < 2 or sys.argv[1] not in subcommand_names: sys.argv.insert(1, subcommand_names[0]) clize.run(runserver, delete_paste, print_admin_url, set_admin_password)