ó
ú2ec           @   sæ   d  Z  d d l Z d d l Z d d l Z d d l Z d d l Z d d l Td d l Td Z d Z	 d d d d	 g Z
 d e f d
 „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d	 e f d „  ƒ  YZ d S(   s¦   
This module handles sending static content such as in-memory data or
files.  At this time it has cache helpers and understands the
if-modified-since request header.
iÿÿÿÿN(   t   *i   i   t   DataAppt   FileAppt   DirectoryAppt   ArchiveStorec           B   s\   e  Z d  Z d
 Z d d d „ Z d „  Z d d „ Z d „  Z d „  Z	 d „  Z
 d	 „  Z RS(   s¨  
    Returns an application that will send content in a single chunk,
    this application has support for setting cache-control and for
    responding to conditional (or HEAD) requests.

    Constructor Arguments:

        ``content``     the content being sent to the client

        ``headers``     the headers to send /w the response

        The remaining ``kwargs`` correspond to headers, where the
        underscore is replaced with a dash.  These values are only
        added to the headers if they are not already provided; thus,
        they can be used for default values.  Examples include, but
        are not limited to:

            ``content_type``
            ``content_encoding``
            ``content_location``

    ``cache_control()``

        This method provides validated construction of the ``Cache-Control``
        header as well as providing for automated filling out of the
        ``EXPIRES`` header for HTTP/1.0 clients.

    ``set_content()``

        This method provides a mechanism to set the content after the
        application has been constructed.  This method does things
        like changing ``Last-Modified`` and ``Content-Length`` headers.

    t   GETt   HEADc         K   s   t  | t d  ƒ t f ƒ s! t ‚ d  |  _ d  |  _ d  |  _ d |  _ | d  k	 r] | |  _	 n  | pf g  |  _
 x9 | j ƒ  D]+ \ } } t | ƒ } | j |  j
 | ƒ qy Wt j |  j
 d t ƒt |  j
 ƒ sà t j |  j
 ƒ n  | d  k	 rü |  j | ƒ n  d  S(   Ni    t   bytes(   t
   isinstancet   typet   Nonet   listt   AssertionErrort   expirest   contentt   content_lengtht   last_modifiedt   allowed_methodst   headerst   itemst
   get_headert   updatet   ACCEPT_RANGESt   Truet   CONTENT_TYPEt   set_content(   t   selfR   R   R   t   kwargst   kt   vt   header(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   __init__;   s     !				c         K   s"   t  j |  j |  p d  |  _ |  S(   N(   t   CACHE_CONTROLt   applyR   R
   R   (   R   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   cache_controlN   s    c         C   sn   | d  k	 s t ‚ | d  k r0 t j ƒ  |  _ n	 | |  _ | |  _ t | ƒ |  _ t j |  j	 d |  j ƒ|  S(   Nt   time(
   R
   R   R#   R   R   t   lenR   t   LAST_MODIFIEDR   R   (   R   R   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   R   s    		c         K   s   t  j |  j |  |  S(   N(   t   CONTENT_DISPOSITIONR!   R   (   R   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   content_disposition]   s    c         C   sg   | d j  ƒ  } | |  j k rW t d | d d d j |  j ƒ f g ƒ} | | | ƒ S|  j | | ƒ S(   Nt   REQUEST_METHODs   You cannot %s a fileR   t   Allowt   ,(   t   upperR   t   HTTPMethodNotAllowedt   joint   get(   R   t   environt   start_responset   methodt   exc(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   __call__a   s    
c         C   s   d |  j  |  j f S(   Ns   "%s-%s"(   R   R   (   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   calculate_etagj   s    c         C   sé  |  j  } |  j ƒ  } t j | | ƒ |  j d  k	 rN t j | d |  j ƒn  y€ t j | ƒ } | rÍ xd | D]Y } | | k s‹ | d k rm x$ t	 d t
 ƒ D] } | j | ƒ q› W| d | ƒ d g Sqm Wn  Wn  t k
 rð } | j | | ƒ SX| sŒyo t j | ƒ }	 |	 d  k	 re|	 t |  j ƒ k rex$ t	 d t
 ƒ D] } | j | ƒ q:W| d | ƒ d g SWqŒt k
 rˆ} | j | | ƒ SXn  d |  j d }
 } t j | ƒ } | rId | d k rId t | d ƒ k rI| d d \ }
 } | pÿ|  j d } | |  j k s|
 | k rIt d	 |  j t | ƒ f ƒ j | | ƒ Sn  | |
 d } t j | d
 |
 d | d |  j ƒt j | | ƒ | sž| |  j k r®| d | ƒ n | d | ƒ |  j d  k	 rß|  j |
 | d !g S|
 | f S(   Nt   deltaR    t   entitys   304 Not Modifiedt    i    i   R   sW   Range request was made beyond the end of the content,
which is %s long.
  Range: %s
t
   first_bytet	   last_bytet   total_lengths   206 Partial Contents   200 OK(   R   R4   t   ETAGR   R   R
   t   EXPIRESt   IF_NONE_MATCHt   parset   list_headersR   t   deletet   HTTPBadRequestt   wsgi_applicationt   IF_MODIFIED_SINCEt   intR   R   t   RANGER$   t   HTTPRequestRangeNotSatisfiablet   CONTENT_RANGEt   CONTENT_LENGTHR   (   R   R/   R0   R   t   current_etagt   client_etagst   etagt   headt   excet   client_clockt   lowerR+   t   rangeR   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR.   m   s^    
,
(   R   R   N(   t   __name__t
   __module__t   __doc__R   R
   R   R"   R   R'   R3   R4   R.   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR      s   "					c           B   s8   e  Z d  Z d d „ Z d „  Z e d „ Z d „  Z RS(   sÁ   
    Returns an application that will send the file at the given
    filename.  Adds a mime type based on ``mimetypes.guess_type()``.
    See DataApp for the arguments beyond ``filename``.
    c         K   ss   | |  _  |  j ƒ  \ } } | r: d | k r: | | d <n  | rY d | k rY | | d <n  t j |  d  | |  d  S(   Nt   content_typet   content_encoding(   t   filenamet
   guess_typeR   R   R
   (   R   RV   R   R   RT   RU   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   ±   s    	c         C   s   t  j |  j ƒ S(   N(   t	   mimetypesRW   RV   (   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyRW   º   s    c         C   s´   t  j |  j ƒ } | r/ | j |  j k r/ d  S| j |  _ | j t k  r‚ t |  j d ƒ } |  j | j	 ƒ  | j ƒ | j
 ƒ  n. d  |  _ | j |  _ t j |  j d |  j ƒd  S(   Nt   rbR#   (   t   ost   statRV   t   st_mtimeR   t   st_sizet
   CACHE_SIZEt   openR   t   readt   closeR
   R   R   R%   R   R   (   R   t   forceR[   t   fh(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   ½   s    	c         C   su  | d j  ƒ  d k } d t | ƒ j ƒ  k rA |  j d t ƒ n
 |  j ƒ  |  j sá t j j |  j	 ƒ s t
 d d d |  j	 ƒ} | | | ƒ Sy t |  j	 d ƒ } Wqá t t f k
 rÝ } t d	 | ƒ } | j | | ƒ SXn  t j |  | | ƒ } t | t ƒ r| rd
 g S| S| \ } }	 | r/d
 g S| j | ƒ | j d d  ƒ }
 |
 ra|
 | t ƒ St | d |	 ƒSd  S(   NR(   R   s	   max-age=0Rb   s   The resource does not existt   comments   No file at %rRY   s,   You are not permitted to view this file (%s)R7   s   wsgi.file_wrappert   size(   R+   R    RO   R   R   R   RZ   t   patht   existsRV   t   HTTPNotFoundR_   t   IOErrort   OSErrort   HTTPForbiddenRB   R   R.   R   R   t   seekR
   t
   BLOCK_SIZEt	   _FileIter(   R   R/   R0   t   is_headR2   t   filet   et   retvalRO   R   t   file_wrapper(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR.   Í   s<    
	N(	   RQ   RR   RS   R
   R   RW   t   FalseR   R.   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   ª   s
   		Rn   c           B   s8   e  Z d d d  „ Z d „  Z d „  Z e Z d „  Z RS(   c         C   s%   | |  _  | |  _ | p t |  _ d  S(   N(   Rp   Re   Rm   t
   block_size(   R   Rp   Ru   Re   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   ò   s    		c         C   s   |  S(   N(    (   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   __iter__÷   s    c         C   sj   |  j  } |  j d  k	 rE | |  j k r3 |  j } n  |  j | 8_ n  |  j j | ƒ } | sf t ‚ n  | S(   N(   Ru   Re   R
   Rp   R`   t   StopIteration(   R   t
   chunk_sizet   data(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   nextú   s    		c         C   s   |  j  j ƒ  d  S(   N(   Rp   Ra   (   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyRa     s    N(   RQ   RR   R
   R   Rv   Rz   t   __next__Ra   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyRn   ð   s
   		
c           B   s&   e  Z d  Z d „  Z e Z d „  Z RS(   s  
    Returns an application that dispatches requests to corresponding FileApps based on PATH_INFO.
    FileApp instances are cached. This app makes sure not to serve any files that are not in a subdirectory.
    To customize FileApp creation override ``DirectoryApp.make_fileapp``
    c         C   sm   t  j j | ƒ |  _ |  j j t  j j ƒ sE |  j t  j j 7_ n  t  j j |  j ƒ s` t ‚ i  |  _ d  S(   N(   RZ   Rf   t   abspatht   endswitht   sept   isdirR   t   cached_apps(   R   Rf   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR     s
    c         C   sÃ   | d } |  j  j | ƒ } | d  k r¶ t j j |  j | j d ƒ ƒ } t j j | ƒ j |  j ƒ ss t	 ƒ  } q¶ t j j
 | ƒ r¤ |  j | ƒ } | |  j  | <q¶ t d | ƒ } n  | | | ƒ S(   Nt	   PATH_INFOt   /Rd   (   R€   R.   R
   RZ   Rf   R-   t   lstript   normpatht
   startswithRk   t   isfilet   make_fileappRh   (   R   R/   R0   t	   path_infot   appRf   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR3     s    
!(   RQ   RR   RS   R   R   R‡   R3   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   
  s   	c           B   s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   s§  
    Returns an application that serves up a DataApp for items requested
    in a given zip or tar archive.

    Constructor Arguments:

        ``filepath``    the path to the archive being served

    ``cache_control()``

        This method provides validated construction of the ``Cache-Control``
        header as well as providing for automated filling out of the
        ``EXPIRES`` header for HTTP/1.0 clients.
    c         C   sƒ   t  j | ƒ r' t  j | d ƒ |  _ n7 t j | ƒ rN t j | d ƒ |  _ n t d | ƒ ‚ d  |  _	 t
 j
 ƒ  |  _ i  |  _ d  S(   Nt   rs"   filepath '%s' is not a zip or tar (   t   zipfilet
   is_zipfilet   ZipFilet   archivet   tarfilet
   is_tarfilet   TarFileCompatR   R
   R   R#   R   t   cache(   R   t   filepath(    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   9  s    	c         K   s"   t  j |  j |  p d  |  _ |  S(   N(   R    R!   R   R
   R   (   R   R   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR"   D  s    c   
      C   so  | j  d d ƒ } | j d ƒ r. | d } n  |  j j  | ƒ } | rS | | | ƒ Sy |  j j | ƒ } Wn. t k
 r™ t d | ƒ } | j | | ƒ SX| j j	 d ƒ rÌ t d | ƒ } | j | | ƒ St
 j | j ƒ \ } } | d  k	 rt d  d | d | ƒ}	 n t d  d | ƒ}	 |	 j |  j j | ƒ t j | j d
 ƒ ƒ |	 |  j | <|  j |	 _ |	 | | ƒ S(   NR   R7   R‚   i   s(   The file requested, '%s', was not found.s$   Path requested, '%s', is not a file.RT   RU   i    (   i    i    i    (   R.   R…   R’   RŽ   t   getinfot   KeyErrorRh   RB   RV   R}   RX   RW   R
   R   R   R`   R#   t   mktimet	   date_timeR   (
   R   R/   R0   Rf   t   applicationt   infoR2   RT   RU   R‰   (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR3   H  s0    (   RQ   RR   RS   R   R"   R3   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyR   )  s   		i   (   RS   RZ   R#   RX   R‹   R   t   paste.httpexceptionst   paste.httpheadersR^   Rm   t   __all__t   objectR   R   Rn   R   R   (    (    (    s7   /usr/local/lib/python2.7/dist-packages/paste/fileapp.pyt   <module>
   s   <

•F