# Path: src/bepasty/constants.py
# COMPLETE = 'complete'
# 
# FILENAME = 'filename'
# 
# LOCKED = 'locked'
# 
# SIZE = 'size'
# 
# TIMESTAMP_DOWNLOAD = 'timestamp-download'
# 
# TYPE = 'type'
# 
# Path: src/bepasty/utils/date_funcs.py
# def delete_if_lifetime_over(item, name):
#     """
#     :return: True if file was deleted
#     """
#     if 0 < item.meta[TIMESTAMP_MAX_LIFE] < time.time():
#         try:
#             current_app.storage.remove(name)
#         except OSError:
#             pass
#         return True
#     return False
# 
# Path: src/bepasty/utils/formatters.py
# class CustomHtmlFormatter(HtmlFormatter):
#     """Custom HTML formatter. Adds an option to wrap lines into HTML <p> tags."""
#     def __init__(self, **options):
#         super().__init__(**options)
#         self.lineparagraphs = options.get('lineparagraphs', '')
# 
#     def _wrap_lineparagraphs(self, inner):
#         """Wrap lines into <p> tags
# 
#         :param inner: iterator of tuples of format (code, text)
#         :return: iterator of tuples containing updated wrapped lines
#         """
#         s = self.lineparagraphs
#         i = self.linenostart - 1
#         for t, line in inner:
#             if t:
#                 i += 1
#                 yield 1, '<p id="%s-%d">%s</p>' % (s, i, line)
#             else:
#                 yield 0, line
# 
#     def format_unencoded(self, tokensource, outfile):
#         """Format by wrapping pieces of text according to the user's options
# 
#         :param tokensource: iterator of tuples of format (code, text)
#         :param outfile: output file handler
#         """
#         source = self._format_lines(tokensource)
#         if self.hl_lines:
#             source = self._highlight_lines(source)
#         if not self.nowrap:
#             if self.linenos == 2:
#                 source = self._wrap_inlinelinenos(source)
#             if self.lineanchors:
#                 source = self._wrap_lineanchors(source)
#             if self.linespans:
#                 source = self._wrap_linespans(source)
#             if self.lineparagraphs:
#                 source = self._wrap_lineparagraphs(source)
#             source = self.wrap(source, outfile)
#             if self.linenos == 1:
#                 source = self._wrap_tablelinenos(source)
#             if self.full:
#                 source = self._wrap_full(source, outfile)
# 
#         for t, piece in source:
#             outfile.write(piece)
# 
# Path: src/bepasty/utils/permissions.py
# ADMIN = 'admin'
# 
# READ = 'read'
# 
# def may(permission):
#     """
#     check whether the current user has the permission <permission>
#     """
#     return permission in flaskg.permissions
# 
# Path: src/bepasty/views/index.py
# def contenttypes_list():
#     contenttypes = [
#         'text/x-bepasty-redirect',  # redirect / link shortener service
#     ]
#     for lexer_info in get_all_lexers():
#         contenttypes.extend(lexer_info[3])
#     return contenttypes
# 
# Path: src/bepasty/views/filelist.py
# def file_infos(names=None):
#     """
#     iterates over storage files metadata.
#     note: we put the storage name into the metadata as ID
# 
#     :param names: None means "all items"
#                   otherwise give a list of storage item names
#     """
#     storage = current_app.storage
#     if names is None:
#         names = list(storage)
#     for name in names:
#         try:
#             with storage.open(name) as item:
#                 meta = dict(item.meta)
#                 if not meta:
#                     # we got empty metadata, this happens for 0-byte .meta files.
#                     # ignore it for now.
#                     continue
#                 if delete_if_lifetime_over(item, name):
#                     continue
#                 meta[ID] = name
#                 yield meta
#         except OSError as e:
#             if e.errno != errno.ENOENT:
#                 raise
#         except pickle.UnpicklingError:
#             # corrupted meta file, just ignore it for now
#             pass


import errno
import time
from flask import current_app, render_template, Markup, url_for, request
from flask.views import MethodView
from werkzeug.exceptions import NotFound, Forbidden
from pygments import highlight
from pygments.lexers import get_lexer_for_mimetype
from pygments.util import ClassNotFound as NoPygmentsLexer
from ..constants import COMPLETE, FILENAME, LOCKED, SIZE, TIMESTAMP_DOWNLOAD, TYPE
from ..utils.date_funcs import delete_if_lifetime_over
from ..utils.formatters import CustomHtmlFormatter
from ..utils.permissions import ADMIN, READ, may
from .index import contenttypes_list
from .filelist import file_infos
        return False
    if use_pygments:
        # if we use pygments, special restrictions apply
        item_type = 'HIGHLIGHT_TYPES'
    # create a tuple list [(content_type_prefix, max_size), ...] with long prefixes first
    ct_size = sorted(current_app.config['MAX_RENDER_SIZE'].items(), key=lambda e: len(e[0]), reverse=True)
    for ct, size in ct_size:
        if item_type.startswith(ct):
            return item_size <= size
    # there should be one entry with ct == '', so we should never get here:
    return False


class DisplayView(MethodView):
    def get(self, name):
        if not may(READ):
            raise Forbidden()
        try:
            item = current_app.storage.openwrite(name)
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise NotFound()
            raise

        with item as item:
            complete = item.meta[COMPLETE]
            if not complete and not may(ADMIN):
                error = 'Upload incomplete. Try again later.'
                return render_template('error.html', heading=item.meta[FILENAME], body=error), 409


# Path: src/bepasty/constants.py
# COMPLETE = 'complete'
# 
# FILENAME = 'filename'
# 
# LOCKED = 'locked'
# 
# SIZE = 'size'
# 
# TIMESTAMP_DOWNLOAD = 'timestamp-download'
# 
# TYPE = 'type'
# 
# Path: src/bepasty/utils/date_funcs.py
# def delete_if_lifetime_over(item, name):
#     """
#     :return: True if file was deleted
#     """
#     if 0 < item.meta[TIMESTAMP_MAX_LIFE] < time.time():
#         try:
#             current_app.storage.remove(name)
#         except OSError:
#             pass
#         return True
#     return False
# 
# Path: src/bepasty/utils/formatters.py
# class CustomHtmlFormatter(HtmlFormatter):
#     """Custom HTML formatter. Adds an option to wrap lines into HTML <p> tags."""
#     def __init__(self, **options):
#         super().__init__(**options)
#         self.lineparagraphs = options.get('lineparagraphs', '')
# 
#     def _wrap_lineparagraphs(self, inner):
#         """Wrap lines into <p> tags
# 
#         :param inner: iterator of tuples of format (code, text)
#         :return: iterator of tuples containing updated wrapped lines
#         """
#         s = self.lineparagraphs
#         i = self.linenostart - 1
#         for t, line in inner:
#             if t:
#                 i += 1
#                 yield 1, '<p id="%s-%d">%s</p>' % (s, i, line)
#             else:
#                 yield 0, line
# 
#     def format_unencoded(self, tokensource, outfile):
#         """Format by wrapping pieces of text according to the user's options
# 
#         :param tokensource: iterator of tuples of format (code, text)
#         :param outfile: output file handler
#         """
#         source = self._format_lines(tokensource)
#         if self.hl_lines:
#             source = self._highlight_lines(source)
#         if not self.nowrap:
#             if self.linenos == 2:
#                 source = self._wrap_inlinelinenos(source)
#             if self.lineanchors:
#                 source = self._wrap_lineanchors(source)
#             if self.linespans:
#                 source = self._wrap_linespans(source)
#             if self.lineparagraphs:
#                 source = self._wrap_lineparagraphs(source)
#             source = self.wrap(source, outfile)
#             if self.linenos == 1:
#                 source = self._wrap_tablelinenos(source)
#             if self.full:
#                 source = self._wrap_full(source, outfile)
# 
#         for t, piece in source:
#             outfile.write(piece)
# 
# Path: src/bepasty/utils/permissions.py
# ADMIN = 'admin'
# 
# READ = 'read'
# 
# def may(permission):
#     """
#     check whether the current user has the permission <permission>
#     """
#     return permission in flaskg.permissions
# 
# Path: src/bepasty/views/index.py
# def contenttypes_list():
#     contenttypes = [
#         'text/x-bepasty-redirect',  # redirect / link shortener service
#     ]
#     for lexer_info in get_all_lexers():
#         contenttypes.extend(lexer_info[3])
#     return contenttypes
# 
# Path: src/bepasty/views/filelist.py
# def file_infos(names=None):
#     """
#     iterates over storage files metadata.
#     note: we put the storage name into the metadata as ID
# 
#     :param names: None means "all items"
#                   otherwise give a list of storage item names
#     """
#     storage = current_app.storage
#     if names is None:
#         names = list(storage)
#     for name in names:
#         try:
#             with storage.open(name) as item:
#                 meta = dict(item.meta)
#                 if not meta:
#                     # we got empty metadata, this happens for 0-byte .meta files.
#                     # ignore it for now.
#                     continue
#                 if delete_if_lifetime_over(item, name):
#                     continue
#                 meta[ID] = name
#                 yield meta
#         except OSError as e:
#             if e.errno != errno.ENOENT:
#                 raise
#         except pickle.UnpicklingError:
#             # corrupted meta file, just ignore it for now
#             pass


# Path: src/bepasty/views/display.py
import errno
import time
from flask import current_app, render_template, Markup, url_for, request
from flask.views import MethodView
from werkzeug.exceptions import NotFound, Forbidden
from pygments import highlight
from pygments.lexers import get_lexer_for_mimetype
from pygments.util import ClassNotFound as NoPygmentsLexer
from ..constants import COMPLETE, FILENAME, LOCKED, SIZE, TIMESTAMP_DOWNLOAD, TYPE
from ..utils.date_funcs import delete_if_lifetime_over
from ..utils.formatters import CustomHtmlFormatter
from ..utils.permissions import ADMIN, READ, may
from .index import contenttypes_list
from .filelist import file_infos

        return False
    if use_pygments:
        # if we use pygments, special restrictions apply
        item_type = 'HIGHLIGHT_TYPES'
    # create a tuple list [(content_type_prefix, max_size), ...] with long prefixes first
    ct_size = sorted(current_app.config['MAX_RENDER_SIZE'].items(), key=lambda e: len(e[0]), reverse=True)
    for ct, size in ct_size:
        if item_type.startswith(ct):
            return item_size <= size
    # there should be one entry with ct == '', so we should never get here:
    return False


class DisplayView(MethodView):
    def get(self, name):
        if not may(READ):
            raise Forbidden()
        try:
            item = current_app.storage.openwrite(name)
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise NotFound()
            raise

        with item as item:
            complete = item.meta[COMPLETE]
            if not complete and not may(ADMIN):
                error = 'Upload incomplete. Try again later.'
                return render_template('error.html', heading=item.meta[FILENAME], body=error), 409


            if item.meta[LOCKED] and not may(ADMIN):