ó
`¾Tc           @   sê   d  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
 m Z d d l m Z m Z d d l m Z d d	 l m Z d d
 l m Z d d l	 m Z 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, start_response)

            # 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, start_response)

            # get a response object here
            response = ...

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

    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
iÿÿÿÿN(   t   new(   t   time(   t   sha1(   t	   iteritemst	   text_type(   t   url_quote_plust   url_unquote_plus(   t   _date_to_unix(   t   ModificationTrackingDict(   t   safe_str_cmp(   t	   to_nativet   UnquoteErrorc           B   s   e  Z d  Z RS(   s6   Internal exception used to signal failures on quoting.(   t   __name__t
   __module__t   __doc__(    (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   i   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   sG   t  j |  | p d ƒ | d  k	 r1 t | ƒ } n  | |  _ | |  _ d  S(   N(    (   R   t   __init__t   Nonet   bytest
   secret_keyR    (   t   selft   dataR   R    (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   ”   s
    	c         C   s/   d |  j  j t j |  ƒ |  j r' d p* d f S(   Ns	   <%s %s%s>t   *t    (   t	   __class__R   t   dictt   __repr__t   should_save(   R   (    (    sc   /var/www/send.findwatt.com/datamanager/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   (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   ¤   s    c         C   sX   |  j  d k	 r$ |  j  j | ƒ } n  |  j rT d j t j | ƒ 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   N(	   t   serialization_methodR   t   dumpst   quote_base64t   joint   base64t	   b64encodet
   splitlinest   strip(   t   clst   value(    (    sc   /var/www/send.findwatt.com/datamanager/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&   (    (    sc   /var/www/send.findwatt.com/datamanager/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&   (    (    sc   /var/www/send.findwatt.com/datamanager/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   replaceR/   i   R0   R.   t   =R-   R,   (    N(    (    (    (   t
   isinstanceR   R8   t   splitt
   ValueErrort
   IndexErrorR2   R   R3   R9   R   R7   R
   t   UnicodeErrorR!   R(   t	   TypeErrorR	   R:   R   R+   R   R   t   False(   R%   t   stringR   t   base64_hashR   R5   R=   t   itemR>   R&   t   client_hash(    (    sc   /var/www/send.findwatt.com/datamanager/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   getRM   (   R%   t   requestR>   R   R   (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   load_cookie  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   R?   t
   set_cookie(   R   t   responseR>   R;   t   session_expiresRT   RU   RV   RW   RX   t   forceR   (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   save_cookie/  s
    N(   R   R   R   t   staticmethodt   _default_hashR3   t   pickleR   t   TrueR   R   R   R   t   propertyR   t   classmethodR'   R+   R?   RM   RR   RH   R]   (    (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyR   m   s    		7(   R   R`   R!   R2   R    R   t   hashlibR   R_   t   werkzeug._compatR   R   t   werkzeug.urlsR   R   t   werkzeug._internalR   t   werkzeug.contrib.sessionsR   t   werkzeug.securityR	   R
   R*   R   R   (    (    (    sc   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/werkzeug/contrib/securecookie.pyt   <module>Z   s   