Beispiel #1
0
def display_paste(paste_id):

    now = datetime.now()
    keep_alive = False
    try:
        paste = Paste.load(paste_id)
        # Delete the paste if it expired:
        if not isinstance(paste.expiration, datetime):
            # burn_after_reading contains the paste creation date
            # if this read appends 10 seconds after the creation date
            # we don't delete the paste because it means it's the redirection
            # to the paste that happens during the paste creation
            try:
                keep_alive = paste.expiration.split('#')[1]
                keep_alive = datetime.strptime(keep_alive,
                                               '%Y-%m-%d %H:%M:%S.%f')
                keep_alive = now < keep_alive + timedelta(seconds=10)
            except IndexError:
                keep_alive = False
            if not keep_alive:
                paste.delete()

        elif paste.expiration < now:
            paste.delete()
            raise ValueError()

    except (TypeError, ValueError):
        return error404(ValueError)

    context = {'paste': paste, 'keep_alive': keep_alive}
    return dmerge(context, GLOBAL_CONTEXT)
Beispiel #2
0
def display_paste(paste_id):

    now = datetime.now()
    keep_alive = False
    try:
        paste = Paste.load(paste_id)
        # Delete the paste if it expired:
        if not isinstance(paste.expiration, datetime):
            # burn_after_reading contains the paste creation date
            # if this read appends 10 seconds after the creation date
            # we don't delete the paste because it means it's the redirection
            # to the paste that happens during the paste creation
            try:
                keep_alive = paste.expiration.split('#')[1]
                keep_alive = datetime.strptime(keep_alive,
                                               '%Y-%m-%d %H:%M:%S.%f')
                keep_alive = now < keep_alive + timedelta(seconds=10)
            except IndexError:
                keep_alive = False
            if not keep_alive:
                paste.delete()

        elif paste.expiration < now:
            paste.delete()
            raise ValueError()

    except (TypeError, ValueError):
        return error404(ValueError)

    context = {'paste': paste, 'keep_alive': keep_alive}
    return dmerge(context, GLOBAL_CONTEXT)
Beispiel #3
0
def create_paste():

    # Reject what is too small, too big, or what does not seem encrypted to
    # limit a abuses
    content = request.forms.get("content", "")
    if '{"iv":' not in content or not (0 < len(content) < settings.MAX_SIZE):
        return {"status": "error", "message": "Wrong data payload."}

    expiration = request.forms.get("expiration", "burn_after_reading")
    title = request.forms.get("title", "")

    paste = Paste(
        expiration=expiration,
        content=content,
        uuid_length=settings.PASTE_ID_LENGTH,
        title=title,
    )
    paste.save()

    # If refresh time elapsed pick up, update the counter
    if settings.DISPLAY_COUNTER:

        paste.increment_counter()

        now = datetime.now()
        timeout = GLOBAL_CONTEXT["refresh_counter"] + timedelta(
            seconds=settings.REFRESH_COUNTER)
        if timeout < now:
            GLOBAL_CONTEXT["pastes_count"] = Paste.get_pastes_count()
            GLOBAL_CONTEXT["refresh_counter"] = now

    return {"status": "ok", "paste": paste.uuid, "owner_key": paste.owner_key}
Beispiel #4
0
def delete_paste(quiet=False, *pastes):
    """
    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))
Beispiel #5
0
def create_paste():
    try:
        body = urlparse.parse_qs(
            request.body.read(int(settings.MAX_SIZE * 1.1)))
    except ValueError:
        return {'status': 'error', 'message': "Wrong data payload."}

    try:

        content = "".join(x.decode('utf8') for x in body[b'content'])
    except (UnicodeDecodeError, KeyError):
        return {
            'status': 'error',
            'message': "Encoding error: the paste couldn't be saved."
        }

    if '{"iv":' not in content:  # reject silently non encrypted content
        return {'status': 'error', 'message': "Wrong data payload."}

    # check size of the paste. if more than settings return error
    # without saving paste.  prevent from unusual use of the
    # system.  need to be improved
    if 0 < len(content) < settings.MAX_SIZE:
        expiration = body.get(b'expiration', ['burn_after_reading'])[0]
        paste = Paste(expiration=expiration.decode('utf8'),
                      content=content,
                      uuid_length=settings.PASTE_ID_LENGTH)
        paste.save()

        # display counter
        if settings.DISPLAY_COUNTER:

            #increment paste counter
            paste.increment_counter()

            # if refresh time elapsed pick up new counter value
            now = datetime.now()
            timeout = (GLOBAL_CONTEXT['refresh_counter'] +
                       timedelta(seconds=settings.REFRESH_COUNTER))
            if timeout < now:
                GLOBAL_CONTEXT['pastes_count'] = Paste.get_pastes_count()
                GLOBAL_CONTEXT['refresh_counter'] = now

        return {'status': 'ok', 'paste': paste.uuid}

    return {
        'status':
        'error',
        'message':
        "Serveur error: the paste couldn't be saved. "
        "Please try later."
    }
Beispiel #6
0
def delete_paste(paste_id):

    try:
        paste = Paste.load(paste_id)
    except (TypeError, ValueError):
        return error404(ValueError)

    if paste.owner_key != request.forms.get("owner_key", None):
        return HTTPResponse(status=403, body="Wrong owner key")

    paste.delete()

    return {
        "status": "ok",
        "message": "Paste deleted",
    }
Beispiel #7
0
def clean_expired_pastes(
    *,
    dry_run=False,
    verbose=False,
    config_dir="",
    data_dir="",
):
    """ Clean expired file pastes and empty paste directories

        This features delete files from the data dir, make sure it's safe.

        Use "dry_run" and "verbose" options to check first
    """

    ensure_app_context(config_dir=config_dir, data_dir=data_dir)

    print("Deleting expired pastes...")
    i = 0
    for p in Paste.iter_all():
        if p.has_expired:
            if not dry_run:
                p.delete()
            if verbose:
                print(p.path, "has expired")
            i += 1
    if dry_run:
        print(f"{i} pastes would have been deleted")
    else:
        print(f"{i} pastes deleted")

    print("Deleting empty paste directories...")
    i = 0
    for p in settings.DATA_DIR.rglob("*"):
        try:
            if p.is_dir() and not next(p.iterdir(), None):
                if not dry_run:
                    p.rmdir()
                if verbose:
                    print(p, "is empty")
                i += 1
        except OSError as e:
            print(f'Error while processing "{p}: {e}')
    if dry_run:
        print(f"{i} directories would have been deleted")
    else:
        print(f"{i} directories deleted")
    print("Done")
Beispiel #8
0
def admin():
    session = request.environ.get("beaker.session")
    if not session or not session.get("is_authenticated"):
        redirect(ADMIN_LOGIN_URL)

    paste_id = request.forms.get("paste", "")
    if paste_id:
        try:
            if "/paste/" in paste_id:
                paste_id = urlparse(paste_id).path.split("/paste/")[-1]
            paste = Paste.load(paste_id)
            paste.delete()
        except (TypeError, ValueError, FileNotFoundError):
            return {
                "status": "error",
                "message": f"Cannot find paste '{paste_id}'",
                **GLOBAL_CONTEXT,
            }

        return {"status": "ok", "message": "Paste deleted", **GLOBAL_CONTEXT}

    return {"status": "ok", "message": "", **GLOBAL_CONTEXT}
Beispiel #9
0
def create_paste():
    try:
        body = urlparse.parse_qs(request.body.read(int(settings.MAX_SIZE * 1.1)))
    except ValueError:
        return {'status': 'error', 'message': "Wrong data payload."}

    try:

        content = "".join(x.decode('utf8') for x in body[b'content'])
    except (UnicodeDecodeError, KeyError):
        return {'status': 'error',
                'message': "Encoding error: the paste couldn't be saved."}

    if '{"iv":' not in content:  # reject silently non encrypted content
        return {'status': 'error', 'message': "Wrong data payload."}

    # check size of the paste. if more than settings return error
    # without saving paste.  prevent from unusual use of the
    # system.  need to be improved
    if 0 < len(content) < settings.MAX_SIZE:
        expiration = body.get(b'expiration', ['burn_after_reading'])[0]
        paste = Paste(expiration=expiration.decode('utf8'), content=content,
                      uuid_length=settings.PASTE_ID_LENGTH)
        paste.save()

        # display counter
        if settings.DISPLAY_COUNTER:

            #increment paste counter
            paste.increment_counter()

            # if refresh time elapsed pick up new counter value
            now = datetime.now()
            timeout = (GLOBAL_CONTEXT['refresh_counter']
                       + timedelta(seconds=settings.REFRESH_COUNTER))
            if timeout < now:
                GLOBAL_CONTEXT['pastes_count'] = Paste.get_pastes_count()
                GLOBAL_CONTEXT['refresh_counter'] = now

        return {'status': 'ok', 'paste': paste.uuid}

    return {'status': 'error',
            'message': "Serveur error: the paste couldn't be saved. "
                       "Please try later."}
Beispiel #10
0
def post_admin_page(admin_url):

    # If ADMIN_SECRET doesn't exist, return 404 error
    if not hasattr(settings, 'ADMIN_SECRET'):
        return error404(ValueError)

    # Verification process
    admin_secret = settings.ADMIN_SECRET
    good_url = admin_url == admin_secret['url']
    good_pwd = request.forms.get('inputPassword') == admin_secret['password']

    if good_url and good_pwd:
        try:
            Paste(request.forms.get('inputUuid')).delete()
            confirmation = True
        except FileNotFoundError:
            confirmation = False
    else:
        confirmation = False

    # Confirmation evaluate to True if the paste has been removed,
    # or to False if an error occured

    return get_admin_page(admin_url, confirmation)
Beispiel #11
0
# add project dir and libs dir to the PYTHON PATH to ensure they are
# importable
from zerobin.utils import (settings, SettingsValidationError, drop_privileges,
                           dmerge)

import bottle
from bottle import (Bottle, run, static_file, view, request)

import clize

from zerobin.paste import Paste

app = Bottle()
GLOBAL_CONTEXT = {
    'settings': settings,
    'pastes_count': Paste.get_pastes_count(),
    'refresh_counter': datetime.now()
}


@app.route('/')
@view('home')
def index():
    return GLOBAL_CONTEXT


@app.route('/faq/')
@view('faq')
def faq():
    return GLOBAL_CONTEXT
Beispiel #12
0
# add project dir and libs dir to the PYTHON PATH to ensure they are
# importable
from zerobin.utils import (settings, SettingsValidationError,
                           drop_privileges, dmerge)

import bottle
from bottle import (Bottle, run, static_file, view, request)

from zerobin.paste import Paste


app = Bottle()
GLOBAL_CONTEXT = {
    'settings': settings,
    'pastes_count': Paste.get_pastes_count(),
    'refresh_counter': datetime.now()
}


@app.route('/')
@view('home')
def index():
    return GLOBAL_CONTEXT


@app.route('/faq/')
@view('faq')
def faq():
    return GLOBAL_CONTEXT
Beispiel #13
0
from zerobin import __version__
from zerobin.utils import (
    SettingsValidationError,
    ensure_app_context,
    check_password,
    settings,
)
from zerobin.paste import Paste

ensure_app_context()

GLOBAL_CONTEXT = {
    "settings": settings,
    "VERSION": __version__,
    "pastes_count": Paste.get_pastes_count(),
    "refresh_counter": datetime.now(),
}

app = Bottle()

ADMIN_LOGIN_URL = settings.ADMIN_URL + "login/"


@app.route("/")
@view("home")
def index():
    return GLOBAL_CONTEXT


@app.get("/faq/")