import datetime import random from flask import Blueprint, current_app, render_template, request, session, redirect, url_for, abort try: import markdown has_markdown = True except ImportError: has_markdown = False import pygments from pygments import highlight from pygments.lexers import get_all_lexers, get_lexer_by_name from pygments.formatters import HtmlFormatter from . import db app = Blueprint(__name__, 'pastepy') base62_alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' class PasteError(Exception): pass class UnknownSyntaxError(PasteError): pass class CustomHtmlFormatter(HtmlFormatter): def wrap(self, source, outfile): yield 0, '
'
        line = 1
        for i, t in source:
            yield i, '{}'.format(i, t)
            line += 1
        yield 0, '
' def init_lexers(): all_lexers = dict([(x[0], x[1][0]) for x in get_all_lexers()]) lexers = [] removed = [] for cat, ls in current_app.config['CATEGORIES']: for l in ls: removed.append(l) lexers.append((cat, [(x, all_lexers[x]) for x in ls if x in all_lexers])) for l in removed: try: del all_lexers[l] except KeyError: pass rendered = [] if has_markdown: rendered.append(('Rendered markdown', 'md-render')) if len(rendered): lexers.append(('Rendered', rendered)) lexers.append(('Others' if current_app.config['CATEGORIES'] else 'Syntax', sorted(all_lexers.items(), key = lambda l: l[0].lower()))) current_app.config['LEXERS'] = lexers current_app.config['FORMATTER'] = CustomHtmlFormatter(linenos='table', lineanchors='line', anchorlinenos=True) init_lexers() @app.route('/') @app.route('/paste') def paste(): context = { 'title': current_app.config['PASTEBIN_NAME'], 'header': current_app.config['PASTEBIN_NAME'], } return render_template('paste.html', **context) def get_formatted(syntax, text): if syntax == 'md-render' and has_markdown: text = markdown.markdown(text, extensions=current_app.config['MARKDOWN_EXTENSIONS']) lexername = 'Rendered markdown' else: try: lex = get_lexer_by_name(syntax or 'text') except pygments.util.ClassNotFound: raise UnknownSyntaxError(syntax) lexername = lex.name text = highlight(text, lex, current_app.config['FORMATTER']) return (lexername, text) def add_paste(): nick = request.form.get('nick') syntax = request.form.get('syntax') title = request.form.get('title') text = request.form.get('text').replace('\r', '') with db.session_scope() as db_session: paste_hash = ''.join(random.choice(base62_alphabet) for x in range(5)) paste = db.Paste(paste_hash, nick, datetime.datetime.utcnow(), syntax, title, text, request.remote_addr) db_session.add(paste) if 'remember_me' in request.form: session['nick'] = nick else: session.pop('nick', None) if 'remember_syntax' in request.form: session['syntax'] = syntax else: session.pop('syntax', None) return redirect(url_for('.view_paste', paste_hash=paste_hash)) def render_preview(): try: lexername, text = get_formatted(request.form['syntax'], request.form['text']) except UnknownSyntaxError: abort(500, 'Could not find lexer "{}".'.format(request.form['syntax'])) nick = request.form['nick'] or 'Anonymous' title = request.form['title'] or 'Untitled' return render_template('view.html', title='Preview', hash=None, nick=nick, date='{} UTC'.format(datetime.datetime.utcnow().ctime()), syntax=lexername, pastetitle=title, text=text, rendered=(lexername or '').startswith('Rendered '), ) @app.route('/paste', methods=['POST']) def post_paste(): if request.form['type'] == 'Preview': return render_preview() if request.form['type'] == 'Paste': return add_paste() abort(404) @app.route('/view/') @app.route('/full/', endpoint='view_full') def view_paste(paste_hash): with db.session_scope() as db_session: try: cache = db_session.query(db.Cache).filter_by(paste_hash=paste_hash).one() paste = cache.paste except db.NoResultFound: try: paste = db_session.query(db.Paste).filter_by(hash=paste_hash).one() except db.NoResultFound: abort(404) try: lexername, text = get_formatted(paste.syntax, paste.text) except UnknownSyntaxError: abort(500, 'Could not find the lexer "{}"'.format(paste.syntax)) cache = db.Cache(paste_hash, lexername, text) db_session.add(cache) template = 'full.html' if request.endpoint.endswith('.view_full') else 'view.html' return render_template(template, title='View paste \u2013 {}'.format(paste.title or 'Untitled'), hash=paste_hash, date='{} UTC'.format(paste.date.ctime()), nick=paste.nick or 'Anonymous', syntax=cache.syntax_name, pastetitle=paste.title or 'Untitled', text=cache.text, rendered=(cache.syntax_name or '').startswith('Rendered '), ) @app.route('/highlight_stylesheet') def highlight_stylesheet(): return current_app.config['FORMATTER'].get_style_defs(), 200, {'Content-Type': 'text/css'} @app.route('/raw/') def raw(paste_hash): with db.session_scope() as db_session: try: paste = db_session.query(db.Paste).filter_by(hash=paste_hash).one() except db.NoResultFound: abort(404) return paste.text, 200, {'Content-Type': 'text/plain'}