class HTTPException(Exception):
    """
    Baseclass for all HTTP exceptions.  This exception can be called as WSGI
    application to render a default error page or you can catch the subclasses
    of it independently and render nicer error messages.
    """

    code = 555
    description = 'Unknown http exception'

    def __init__(self, description=None):
        Exception.__init__(self)
        if description is not None:
            self.description = description

    @property
    def name(self):
        """The status name."""
        return HTTP_STATUS_CODES.get(self.code, 'Unknown Error')

    def get_description(self):
        """Get the description."""
        return u'%s' % self.description

    def get_body(self):
        """Get the HTML body."""
        return text_type((u'%(description)s') % {
            'description':  self.get_description()
        })

    def get_headers(self):
        """Get a list of headers."""
        return [('Content-Type', 'text/plain')]


    def __str__(self):
        return '%d: %s' % (self.code, self.name)

    def __repr__(self):
        return '<%s \'%s\'>' % (self.__class__.__name__, self) class BadRequest(HTTPException):
    """*400* `Bad Request`

    Raise if the browser sends something to the application the application
    or server cannot handle.
    """
    code = 400
    description = (
        'The browser (or proxy) sent a request that this server could '
        'not understand.'
    ) class cached_property(object):
    """ A property that is only computed once per instance and then replaces
        itself with an ordinary attribute. Deleting the attribute resets the
        property. """

    def __init__(self, func):
        self.__doc__ = getattr(func, '__doc__')
        self.func = func

    def __get__(self, obj, cls=None):
        if obj is None: return self
        if self.func.__name__ not in obj.__dict__:
            obj.__dict__[self.func.__name__] = self.func(obj)
        value = obj.__dict__[self.func.__name__]
        return value class MultiDict(DictMixin):
    """ This dict stores multiple values per key, but behaves exactly like a
        normal dict in that it returns only the newest value for any given key.
        There are special methods available to access the full list of values.

        Basic Usage:

            >>> d = MultiDict([('a', 'b'), ('a', 'c')])
            >>> d
            MultiDict([('a', 'b'), ('a', 'c')])
            >>> d['a']
            'b'
            >>> d.getlist('a')
            ['b', 'c']
            >>> 'a' in d
            True
    """

    def __init__(self, *a, **kwargs):
        self.dict = {}
        for pl in a:
            for k, v in pl:
                l = self.dict.setdefault(k, [])
                l.append(v)
        for k, v in kwargs.items():
            l = self.dict.setdefault(k, [])
            l.append(v)

    def __len__(self):
        return len(self.dict)

    def __iter__(self):
        return iter(self.dict)

    def __contains__(self, key):
        return key in self.dict

    def __delitem__(self, key):
        del self.dict[key]

    def __getitem__(self, key):
        return self.dict[key][0]

    def __setitem__(self, key, value):
        self.append(key, value)

    def keys(self):
        return self.dict.keys()

    if PY2:
        def values(self):
            return [v[0] for v in self.dict.values()]

        def items(self):
            return [(k, v[0]) for k, v in self.dict.items()]

        def iterkeys(self):
            return self.dict.iterkeys()

        def itervalues(self):
            return (v[0] for v in self.dict.itervalues())

        def iteritems(self):
            return ((k, v[0]) for k, v in self.dict.iteritems())

        def iterallitems(self):
            return ((k, v) for k, vl in self.dict.iteritems() for v in vl)

        def allitems(self):
            return [(k, v) for k, vl in self.dict.iteritems() for v in vl]

    else:
        def values(self):
            return (v[0] for v in self.dict.values())

        def items(self):
            return ((k, v[0]) for k, v in self.dict.items())

        def allitems(self):
            return ((k, v) for k, vl in self.dict.items() for v in vl)

        iterkeys = keys
        itervalues = values
        iteritems = items
        iterallitems = allitems


    def get(self, key, default=None, index=0, type=None):
        """ Return the most recent value for a key.
            Args:

              * default: The default value to be returned if the key is not
                   present or the type conversion fails.
              * index: An index for the list of available values.
              * type: If defined, this callable is used to cast the value
                    into a specific type. Exception are suppressed and result in
                    the default value to be returned.
        """
        try:
            val = self.dict[key][index]
            return type(val) if type else val
        except Exception:
            pass
        return default

    def append(self, key, value):
        """ Add a new value to the list of values for this key. """
        self.dict.setdefault(key, []).append(value)

    def replace(self, key, value):
        """ Replace the list of values with a single value. """
        self.dict[key] = [value]

    def getall(self, key):
        """ Return a (possibly empty) list of values for a key. """
        return self.dict.get(key) or []

    #: Aliases for WTForms to mimic other multi-dict APIs (Django)
    getone = get
    getlist = getall class FileUpload(object):
    def __init__(self, fileobj, name, filename, headers=None):
        """ Wrapper for file uploads. """
        #: Open file(-like) object (BytesIO buffer or temporary file)
        self.file = fileobj
        #: Name of the upload form field
        self.name = name
        #: Raw filename as sent by the client (may contain unsafe characters)
        self.raw_filename = filename
        #: A `HeaderDict` with additional headers (e.g. content-type)
        self.headers = HeaderDict(headers) if headers else HeaderDict()

    content_type = HeaderProperty('Content-Type')
    content_length = HeaderProperty('Content-Length', reader=int, default=-1)

    @cached_property
    def filename(self):
        """ Name of the file on the client file system, but normalized to ensure
            file system compatibility. An empty filename is returned as 'empty'.
            Only ASCII letters, digits, dashes, underscores and dots are
            allowed in the final filename. Accents are removed, if possible.
            Whitespace is replaced by a single dash. Leading or tailing dots
            or dashes are removed. The filename is limited to 255 characters.
        """
        fname = self.raw_filename
        if not isinstance(fname, text_type):
            fname = fname.decode('utf8', 'ignore')
        fname = normalize('NFKD', fname)
        fname = fname.encode('ASCII', 'ignore').decode('ASCII')
        fname = os.path.basename(fname.replace('\\', os.path.sep))
        fname = re.sub(r'[^a-zA-Z0-9-_.\s]', '', fname).strip()
        fname = re.sub(r'[-\s]+', '-', fname).strip('.-')
        return fname[:255] or 'empty'

    def _copy_file(self, fp, chunk_size=2 ** 16):
        read, write, offset = self.file.read, fp.write, self.file.tell()
        while 1:
            buf = read(chunk_size)
            if not buf: break
            write(buf)
        self.file.seek(offset)

    def save(self, destination, overwrite=False, chunk_size=2 ** 16):
        """ Save file to disk or copy its content to an open file(-like) object.
            If *destination* is a directory, `filename` is added to the
            path. Existing files are not overwritten by default (IOError).

            Args:

              * destination: File path, directory or file(-like) object.
              * overwrite: If True, replace existing files. (default: False)
              * chunk_size: Bytes to read at a time. (default: 64kb)
        """
        if isinstance(destination, string_types):  # Except file-likes here
            if os.path.isdir(destination):
                destination = os.path.join(destination, self.filename)
            if not overwrite and os.path.exists(destination):
                raise IOError('File exists.')
            with open(destination, 'wb') as fp:
                self._copy_file(fp, chunk_size)
        else:
            self._copy_file(destination, chunk_size) class FormsDict(MultiDict):
    """ This `MultiDict` subclass is used to store request form data.
        Additionally to the normal dict-like item access methods (which return
        unmodified data as native strings), this container also supports
        attribute-like access to its values. Attributes are automatically de-
        or recoded to match `input_encoding` (default: 'utf8'). Missing
        attributes default to an empty string. """

    #: Encoding used for attribute values.
    input_encoding = 'utf8'
    #: If true (default), unicode strings are first encoded with `latin1`
    #: and then decoded to match `input_encoding`.
    recode_unicode = True

    def _fix(self, s, encoding=None):
        if isinstance(s, text_type) and self.recode_unicode:  # Python 3 WSGI
            return s.encode('latin1').decode(encoding or self.input_encoding)
        elif isinstance(s, bytes):  # Python 2 WSGI
            return s.decode(encoding or self.input_encoding)
        else:
            return s

    def getunicode(self, name, default=None, encoding=None):
        """ Return the value as a unicode string, or the default. """
        try:
            return self._fix(self[name], encoding)
        except (UnicodeError, KeyError):
            return default

    def __getattr__(self, name, default=text_type()):
        # Without this guard, pickle generates a cryptic TypeError:
        if name.startswith('__') and name.endswith('__'):
            return super(FormsDict, self).__getattr__(name)
        return self.getunicode(name, default=default) class WSGIHeaders(DictMixin):
    """ This dict-like class wraps a WSGI environ dict and provides convenient
        access to HTTP_* fields. Keys and values are native strings
        (2.x bytes or 3.x unicode) and keys are case-insensitive. If the WSGI
        environment contains non-native string values, these are de- or encoded
        using a lossless 'latin1' character set.
        The API will remain stable even on changes to the relevant PEPs.
        Currently PEP 333, 444 and 3333 are supported. (PEP 444 is the only one
        that uses non-native strings.)
    """
    #: List of keys that do not have a ``HTTP_`` prefix.
    cgikeys = ('CONTENT_TYPE', 'CONTENT_LENGTH')

    def __init__(self, environ):
        self.environ = environ

    def _ekey(self, key):
        """ Translate header field name to CGI/WSGI environ key. """
        key = key.replace('-', '_').upper()
        if key in self.cgikeys:
            return key
        return 'HTTP_' + key

    def raw(self, key, default=None):
        """ Return the header value as is (may be bytes or unicode). """
        return self.environ.get(self._ekey(key), default)

    def __getitem__(self, key):
        val = self.environ[self._ekey(key)]
        if not PY2:
            if isinstance(val, text_type):
                val = val.encode('latin1').decode('utf8')
            else:
                val = val.decode('utf8')
        return val

    def __setitem__(self, key, value):
        raise TypeError("%s is read-only." % self.__class__)

    def __delitem__(self, key):
        raise TypeError("%s is read-only." % self.__class__)

    def __iter__(self):
        for key in self.environ:
            if key[:5] == 'HTTP_':
                yield _hkey(key[5:])
            elif key in self.cgikeys:
                yield _hkey(key)

    def keys(self):
        return [x for x in self]

    def __len__(self):
        return len(self.keys())

    def __contains__(self, key):
        return self._ekey(key) in self.environ PY2 = sys.version_info[0] == 2
    def reraise(tp, value, tb=None):
def to_bytes(s, enc='utf8'):
def to_unicode(s, enc='utf8', err='strict'): def urldecode(qs):
    def __contains__(self, k):
    def __getattr__(self, k):
    def __setattr__(self, k, v):
    def __delattr__(self, k):
    def __init__(self, func):
    def __get__(self, obj, cls=None):
class ConfigDict(dict):
class cached_property(object): def parse_content_type(content_type):
    parts = content_type.split(';')
    params = {}
    for part in parts[1:]:
        if '=' not in part:
            break
        k, v = part.strip().split('=', 1)
        params[k] = v
    return (parts[0], params) def parse_date(ims):
    """ Parse rfc1123, rfc850 and asctime timestamps and return UTC epoch. """
    try:
        ts = email.utils.parsedate_tz(ims)
        return time.mktime(ts[:8] + (0, )) - (ts[9] or 0) - time.timezone
    except (TypeError, ValueError, IndexError, OverflowError):
        return None def parse_auth(header):
    """ Parse rfc2617 HTTP authentication header string (basic) and return (user,pass) tuple or None"""
    try:
        method, data = header.split(None, 1)
        if method.lower() == 'basic':
            user, pwd = to_unicode(base64.b64decode(to_bytes(data))).split(':', 1)
            return user, pwd
    except (KeyError, ValueError, Exception):
        return None def parse_content_type(content_type):
    parts = content_type.split(';')
    params = {}
    for part in parts[1:]:
        if '=' not in part:
            break
        k, v = part.strip().split('=', 1)
        params[k] = v
    return (parts[0], params) def parse_range_header(header, maxlen=0):
    """ Yield (start, end) ranges parsed from a HTTP Range header. Skip
        unsatisfiable ranges. The end index is non-inclusive."""
    if not header or header[:6] != 'bytes=': return
    ranges = [r.split('-', 1) for r in header[6:].split(',') if '-' in r]
    for start, end in ranges:
        try:
            if not start:  # bytes=-100    -> last 100 bytes
                start, end = max(0, maxlen - int(end)), maxlen
            elif not end:  # bytes=100-    -> all but the first 99 bytes
                start, end = int(start), maxlen
            else:  # bytes=100-200 -> bytes 100-200 (inclusive)
                start, end = int(start), min(int(end) + 1, maxlen)
            if 0 <= start < end <= maxlen:
                yield start, end
        except ValueError:
            pass class BadRequest(HTTPException):
    """*400* `Bad Request`

    Raise if the browser sends something to the application the application
    or server cannot handle.
    """
    code = 400
    description = (
        'The browser (or proxy) sent a request that this server could '
        'not understand.'
    )
from functools import update_wrapper
from datetime import datetime, timedelta
from tempfile import TemporaryFile
from .exceptions import HTTPException, BadRequest
from .utils import cached_property
from .datastructures import MultiDict, FileUpload, FormsDict, WSGIHeaders
from ._compat import (PY2, to_bytes, string_types, text_type,
     integer_types, to_unicode, to_native, BytesIO)
    from Cookie import SimpleCookie
    from http.cookies import SimpleCookie
from .utils import (urlencode, urldecode, urlquote, urlunquote, urljoin, json)
from .http import (parse_content_type, parse_date, parse_auth, parse_content_type, parse_range_header)
from .exceptions import BadRequest
import cgi
                for part in self.iter_body(read_func, MEMFILE_MAX):
                    body.write(part)
        self.environ['wsgi.input'] = body
        body.seek(0)
        return body

    def parse_form_data(self):
        post = FormsDict()
        # We default to application/x-www-form-urlencoded for everything that
        # is not multipart and take the fast path (also: 3.1 workaround)
        if not self.content_type.startswith('multipart/'):
            pairs = urldecode(to_unicode(self.get_data()))
            for key, value in pairs:
                post[key] = value
            return post

        safe_env = {'QUERY_STRING': ''}  # Build a safe environment for cgi
        for key in ('REQUEST_METHOD', 'CONTENT_TYPE', 'CONTENT_LENGTH'):
            if key in self.environ:
                safe_env[key] = self.environ[key]
        args = dict(fp=self.stream, environ=safe_env, keep_blank_values=True)
        if not PY2:
            args['encoding'] = 'utf8'
        data = cgi.FieldStorage(**args)
        self.environ['_cgi.FieldStorage'] = data  #http://bugs.python.org/issue18394
        data = data.list or []
        for item in data:
            if item.filename:
                post[item.name] = FileUpload(item.file, item.name,
                                             item.filename, item.headers)
            else:
                post[item.name] = item.value
        return post

    @cached_property
    def parsed_form_data(self):
        return self.parse_form_data()

    @cached_property
    def form(self):
        form = FormsDict()
        for name, item in self.parsed_form_data.allitems():
            if not isinstance(item, FileUpload):
                form[name] = item
        return form

    @cached_property
    def values(self):
        """Combined multi dict for `args` and `form`."""
        args = []
        for d in self.args, self.form:
            if not isinstance(d, MultiDict):
                for k, v in d.items():
                    args.append((k, v))
            else:
                for k, v in d.iterallitems():
                    args.append((k, v))
        return MultiDict(args)

    @cached_property
    def files(self):
        files = FormsDict()
        for name, item in self.parsed_form_data.allitems():
            if isinstance(item, FileUpload):
                files[name] = item
        return files

    def get_host(self):
        """Return the real host for the given WSGI environment.  This first checks
        the `X-Forwarded-Host` header, then the normal `Host` header, and finally
        the `SERVER_NAME` environment variable (using the first one it finds).
        """
        environ = self.environ
        if 'HTTP_X_FORWARDED_HOST' in environ:
            rv = environ['HTTP_X_FORWARDED_HOST'].split(',', 1)[0].strip()
        elif 'HTTP_HOST' in environ:
            rv = environ['HTTP_HOST']
        else:
            rv = environ['SERVER_NAME']
            if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \
               in (('https', '443'), ('http', '80')):
                rv += ':%s'%(environ['SERVER_PORT'])
        return rv


    def get_content_length(self):
        """Returns the content length from the WSGI environment as
        integer.  If it's not available `None` is returned.
        """
        content_length = self.environ.get('CONTENT_LENGTH')
        if content_length is not None:
            try:
                return max(0, int(content_length))
            except (ValueError, TypeError):
                pass
        return 0

    def get_current_url(self, root_only=False, strip_querystring=False, host_only=False):
        """A handy helper function that recreates the full URL as IRI for the
        current request or parts of it.  Here an example:

            >>> get_current_url()
            'http://localhost/script/?param=foo'
            >>> get_current_url(root_only=True)
            'http://localhost/script/'
            >>> get_current_url(host_only=True)
            'http://localhost/'
            >>> get_current_url(strip_querystring=True)
            'http://localhost/script/'

        """
        environ = self.environ
        tmp = [environ['wsgi.url_scheme'], '://', self.get_host()]
        cat = tmp.append
        if host_only:
            return ''.join(tmp) + '/'
        cat(urlquote(environ.get('SCRIPT_NAME', '')).rstrip('/'))
        cat('/')
        if not root_only:
            print(type(environ.get('PATH_INFO')))

            cat(urlquote(environ.get('PATH_INFO', '').lstrip('/')))