ó
‰]c           @   s0  d  Z  d d l Z d d l Z d d l Z d d l m Z d d l m Z d d l	 m	 Z	 d d l
 m Z d d l
 m Z d d	 l
 m Z d d
 l
 m Z d d l m Z d d l m Z d d l m Z d d l m Z d d l m Z e j d e d d ƒd e f d „  ƒ  YZ d e f d „  ƒ  YZ d S(   sÔ  
    werkzeug.contrib.securecookie
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    This module implements a cookie that is not alterable from the client
    because it adds a checksum the server checks for.  You can use it as
    session replacement if all you have is a user id or something to mark
    a logged in user.

    Keep in mind that the data is still readable from the client as a
    normal cookie is.  However you don't have to store and flush the
    sessions you have at the server.

    Example usage:

    >>> from werkzeug.contrib.securecookie import SecureCookie
    >>> x = SecureCookie({"foo": 42, "baz": (1, 2, 3)}, "deadbeef")

    Dumping into a string so that one can store it in a cookie:

    >>> value = x.serialize()

    Loading from that string again:

    >>> x = SecureCookie.unserialize(value, "deadbeef")
    >>> x["baz"]
    (1, 2, 3)

    If someone modifies the cookie and the checksum is wrong the unserialize
    method will fail silently and return a new empty `SecureCookie` object.

    Keep in mind that the values will be visible in the cookie so do not
    store data in a cookie you don't want the user to see.

    Application Integration
    =======================

    If you are using the werkzeug request objects you could integrate the
    secure cookie into your application like this::

        from werkzeug.utils import cached_property
        from werkzeug.wrappers import BaseRequest
        from werkzeug.contrib.securecookie import SecureCookie

        # don't use this key but a different one; you could just use
        # os.urandom(20) to get something random
        SECRET_KEY = '\xfa\xdd\xb8z\xae\xe0}4\x8b\xea'

        class Request(BaseRequest):

            @cached_property
            def client_session(self):
                data = self.cookies.get('session_data')
                if not data:
                    return SecureCookie(secret_key=SECRET_KEY)
                return SecureCookie.unserialize(data, SECRET_KEY)

        def application(environ, start_response):
            request = Request(environ)

            # get a response object here
            response = ...

            if request.client_session.should_save:
                session_data = request.client_session.serialize()
                response.set_cookie('session_data', session_data,
                                    httponly=True)
            return response(environ, start_response)

    A less verbose integration can be achieved by using shorthand methods::

        class Request(BaseRequest):

            @cached_property
            def client_session(self):
                return SecureCookie.load_cookie(self, secret_key=COOKIE_SECRET)

        def application(environ, start_response):
            request = Request(environ)

            # get a response object here
            response = ...

            request.client_session.save_cookie(response)
            return response(environ, start_response)

    :copyright: 2007 Pallets
    :license: BSD-3-Clause
iÿÿÿÿN(   t   sha1(   t   new(   t   timei   (   t	   iteritems(   t	   text_type(   t   to_bytes(   t	   to_native(   t   _date_to_unix(   t   ModificationTrackingDict(   t   safe_str_cmp(   t   url_quote_plus(   t   url_unquote_plussž   'werkzeug.contrib.securecookie' is deprecated as of version 0.15 and will be removed in version 1.0. It has moved to https://github.com/pallets/secure-cookie.t
   stacklevelt   UnquoteErrorc           B   s   e  Z d  Z RS(   s6   Internal exception used to signal failures on quoting.(   t   __name__t
   __module__t   __doc__(    (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   u   s   t   SecureCookiec        
   B   sÂ   e  Z d  Z e e ƒ Z e Z e Z	 d d e d „ Z d „  Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z d d „ Z e d „  ƒ Z e d d d	 „ ƒ Z d d d d d
 d d e e d „	 Z RS(   sá  Represents a secure cookie.  You can subclass this class and provide
    an alternative mac method.  The import thing is that the mac method
    is a function with a similar interface to the hashlib.  Required
    methods are update() and digest().

    Example usage:

    >>> x = SecureCookie({"foo": 42, "baz": (1, 2, 3)}, "deadbeef")
    >>> x["foo"]
    42
    >>> x["baz"]
    (1, 2, 3)
    >>> x["blafasel"] = 23
    >>> x.should_save
    True

    :param data: the initial data.  Either a dict, list of tuples or `None`.
    :param secret_key: the secret key.  If not set `None` or not specified
                       it has to be set before :meth:`serialize` is called.
    :param new: The initial value of the `new` flag.
    c         C   so   t  j |  | p d ƒ | d  k	 r4 t | d ƒ } n  | |  _ | |  _ |  j t k rk t j	 d d d ƒn  d  S(   Ns   utf-8s«   The default 'SecureCookie.serialization_method' will change from pickle to json in version 1.0. To upgrade existing tokens, override 'unquote' to try pickle if json fails.R   i   (    (
   R   t   __init__t   NoneR   t
   secret_keyR   t   serialization_methodt   picklet   warningst   warn(   t   selft   dataR   R   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   £   s    		c         C   s/   d |  j  j t j |  ƒ |  j r' d n d f S(   Ns	   <%s %s%s>t   *t    (   t	   __class__R   t   dictt   __repr__t   should_save(   R   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   µ   s    	c         C   s   |  j  S(   s‚   True if the session should be saved.  By default this is only true
        for :attr:`modified` cookies, not :attr:`new`.
        (   t   modified(   R   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR    ¼   s    c         C   sa   |  j  d k	 r$ |  j  j | ƒ } n  |  j r] d j t j t | d ƒ ƒ j ƒ  ƒ j	 ƒ  } n  | S(   sž   Quote the value for the cookie.  This can be any object supported
        by :attr:`serialization_method`.

        :param value: the value to quote.
        R   t   utf8N(
   R   R   t   dumpst   quote_base64t   joint   base64t	   b64encodeR   t
   splitlinest   strip(   t   clst   value(    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   quoteÃ   s    	*c         C   sh   yG |  j  r t j | ƒ } n  |  j d k	 rB |  j j | ƒ } n  | SWn t k
 rc t ƒ  ‚ n Xd S(   sœ   Unquote the value for the cookie.  If unquoting does not work a
        :exc:`UnquoteError` is raised.

        :param value: the value to unquote.
        N(   R$   R&   t	   b64decodeR   R   t   loadst	   ExceptionR   (   R*   R+   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   unquoteÒ   s    	c         C   sö   |  j  d	 k r t d ƒ ‚ n  | r7 t | ƒ |  d <n  g  } t |  j  d	 |  j ƒ } xm t |  j ƒ  ƒ D]Y \ } } | j d t	 | ƒ |  j
 | ƒ j d ƒ f j d ƒ ƒ | j d | d ƒ qh Wd j t j | j ƒ  ƒ j ƒ  d j | ƒ g ƒ S(
   s{  Serialize the secure cookie into a string.

        If expires is provided, the session will be automatically invalidated
        after expiration when you unseralize it. This provides better
        protection against session cookie theft.

        :param expires: an optional expiration date for the cookie (a
                        :class:`datetime.datetime` object)
        s   no secret key definedt   _expiress   %s=%st   asciit   |iÿÿÿÿt   ?t   &N(   R   R   t   RuntimeErrorR   t   hmact   hash_methodt   sortedt   itemst   appendR
   R,   t   decodet   encodet   updateR%   R&   R'   t   digestR)   (   R   t   expirest   resultt   mact   keyR+   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt	   serializeå   s    
(
c         C   s&  t  | t ƒ r$ | j d d ƒ } n  t  | t ƒ rH | j d d ƒ } n  y | j d d ƒ \ } } Wn t t f k
 rƒ d
 } n“Xi  } t | d |  j ƒ } x™ | j d ƒ D]ˆ } | j	 d | ƒ d | k rÜ d } Pn  | j d d ƒ \ } }	 t
 | j d ƒ ƒ } y t | ƒ } Wn t k
 r,n X|	 | | <q¯ Wy t j | ƒ }
 Wn t k
 rkd } }
 n X| d k	 rt |
 | j ƒ  ƒ ry4 x- t | ƒ D] \ } }	 |  j |	 ƒ | | <qWWn t k
 rÚd } qXd	 | k rt ƒ  | d	 k rd } q| d	 =qn d } |  | | t ƒ S(   sè   Load the secure cookie from a serialized string.

        :param string: the cookie value to unserialize.
        :param secret_key: the secret key used to serialize the cookie.
        :return: a new :class:`SecureCookie`.
        s   utf-8t   replaceR4   i   R5   R3   t   =R2   R1   (    N(    (    (    (   t
   isinstanceR   R=   t   splitt
   ValueErrort
   IndexErrorR7   R   R8   R>   R   R<   R   t   UnicodeErrorR&   R-   t	   TypeErrorR	   R?   R   R0   R   R   t   False(   R*   t   stringR   t   base64_hashR   R:   RB   t   itemRC   R+   t   client_hash(    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   unserializeþ   sL    
!
	t   sessionc         C   s5   | j  j | ƒ } | s% |  d | ƒ S|  j | | ƒ S(   s  Loads a :class:`SecureCookie` from a cookie in request.  If the
        cookie is not set, a new :class:`SecureCookie` instanced is
        returned.

        :param request: a request object that has a `cookies` attribute
                        which is a dict of all cookie values.
        :param key: the name of the cookie.
        :param secret_key: the secret key used to unquote the cookie.
                           Always provide the value even though it has
                           no default!
        R   (   t   cookiest   getRR   (   R*   t   requestRC   R   R   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   load_cookie5  s    t   /c         C   s_   |
 s |  j  r[ |  j | p | ƒ } | j | | d | d | d | d | d | d |	 ƒn  d S(   s=  Saves the SecureCookie in a cookie on response object.  All
        parameters that are not described here are forwarded directly
        to :meth:`~BaseResponse.set_cookie`.

        :param response: a response object that has a
                         :meth:`~BaseResponse.set_cookie` method.
        :param key: the name of the cookie.
        :param session_expires: the expiration date of the secure cookie
                                stored information.  If this is not provided
                                the cookie `expires` date is used instead.
        R@   t   max_aget   patht   domaint   securet   httponlyN(   R    RD   t
   set_cookie(   R   t   responseRC   R@   t   session_expiresRY   RZ   R[   R\   R]   t   forceR   (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   save_cookieG  s    N(   R   R   R   t   staticmethodt   _default_hashR8   R   R   t   TrueR$   R   R   R   t   propertyR    t   classmethodR,   R0   RD   RR   RW   RM   Rb   (    (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   y   s,   	7(   R   R&   R   R   t   hashlibR    Rd   R7   R   R   t   _compatR   R   R   R   t	   _internalR   t   contrib.sessionsR   t   securityR	   t   urlsR
   R   R   t   DeprecationWarningR/   R   R   (    (    (    s<   lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   <module>Z   s*   