m
bIc           @   s  d  Z  d d d !Z d k Z d k Td k l Z l Z d k l Z d k	 l
 Z
 d	 k l Z d
 k l Z l Z d k l Z d k l Z d k l Z d k l Z d k l Z d k l Z d k Z d k Z d k Z d k Z d k l Z l  Z  d k! Z! y d k" l# Z# Wn d k# l# Z# n Xd Z$ d Z% e i& e$ e%  Z' d   Z( d Z) d Z* d Z+ e* Z, d Z- d Z. d Z/ e. Z0 d d d d e1 d  Z2 d e e
 f d     YZ3 e i4 e3  d S(   s   
      ExtFile product module.
      The ExtFile-Product works like the Zope File-product, but stores
      the uploaded file externally in a repository-direcory.

      $Id: ExtFile.py 5740 2006-01-22 11:38:09Z roug $
s   $Release: 1.1.2 $i
   iN(   t   *(   s   getSecurityManagers   ClassSecurityInfo(   s
   SimpleItem(   s   PropertyManager(   s   BeforeDeleteException(   s   DTMLFiles   MessageDialog(   s   guess_content_type(   s   rfc1123_date(   s   DateTime(   s   WriteLockInterface(   s   choose_boundary(   s   HTTPRangeSupport(   s   joins   isfile(   s   StringIOsJ    ,+&;()[]{}ݟtJ   ___________AAAAAAaaaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOOOooooooSssUUUUuuuuYYyyZzc         C   s   t  i |  t  S(   sX    Cleanup an id
        Should be more thorough and e.g. remove trailing dots/spaces
    N(   t   stringt	   translatet   strt   TRANSMAP(   R   (    (    t<   /home2/kennisonb/webapps/zope/Zope/Products/Photo/ExtFile.pyt
   cleanup_idD   s     i    i   i   s   %n%c%et    c   	      C   s}  | d j o t |  t d  j	 og t | d  oW | i } | t t i | d  t i | d  t i | d   d } t |  } n | o |  i
   }  |  i | t | |   |  i |  i | |  | d j	 ol t   } | i d |   o
 d } n& | i d	 } t i | i   d  } t d
 d d d | d |  Sqyn+ | d j	 o t d
 d d d d d  Sn d S(   s   Add a ExtFile to a folder.R   t   filenamet   /s   \t   :i   s   View management screenss   ./manage_maini    t   titlet   Createdt   messages(   The ExtFile %s was successfully created!t   actions   Error!s   You must specify a file!N(   t   idt   typet   filet   hasattrR	   t   maxR   t   rfindR   t   selft   thist
   _setObjectt   ExtFileR   t   _getObt   manage_file_uploadt   content_typet   REQUESTt   Nonet   getSecurityManagert   securityt   checkPermissiont   ppatht   PARENTSt   pobjt   joint   getPhysicalPatht   MessageDialog(	   R   R   R   R   R   R   R"   R$   R    (    (    R   t   manage_addExtFileW   s.     6		
	
	R   c           B   sw  t  Z d  Z e f Z h  d d <d d <h  d d <d d <h  d d <d d <f Z h  d d <d	 d
 <h  d d <d	 d <h  d d <d	 d <h  d d <d	 d <h  d d <d	 d <f Z e   Z e i	 d d  e i	 d d  e i	 d d
  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d  e i	 d d   e i	 d d!  d" Z
 d# d$ g Z d d e d%  Z d&   Z d'   Z e Z d(   Z d)   Z e i	 d d*  d+   Z d,   Z d-   Z e i	 d d.  d d/  Z e i d0  d1   Z e i d2  d3   Z d4   Z d5   Z e Z d6   Z e d7  Z e d8 e     Z! d d e d9  Z" e d: e     Z# d d e d;  Z$ e Z% d<   Z& e d=  Z' d>   Z( d? d@  Z) dA   Z* dB   Z+ dC   Z, dD   Z- dE   Z. dF   Z/ dG   Z0 dH   Z1 e dI  Z2 dJ   Z3 RS(K   s4   An External ExtFile allows indexing and conversions.R   R   R   R   t   descrR   t   labelt   EditR   t   manage_mains   View/DownloadR   t   Uploadt   manage_uploadFormt
   Propertiest   manage_propertiesFormt   Securityt   manage_accesss   Change permissionss   Change Photot   manage_editExtFileR   t   PUTs
   FTP accesst   manage_FTPstatt   manage_FTPgett   manage_FTPlistt   Viewt	   is_brokent   get_sizet   getContentTypet   _get_filenamet   __str__R   t   vart   photosc         C   sC   | |  _  | |  _ t |  _ g  |  _ d |  _ | |  _ | |  _ d S(   s    Initialize a new instance of ExtFile
            If a extFile is created through FTP, self.absolute_url doesn't work.
        i    N(	   R   R   R   t   __version__R	   t   file_uploadedR   t   parent_patht   _v_parent_path(   R   R   R   R   RB   (    (    R   t   __init__   s     						c         C   s
   |  i   S(   N(   R   t
   index_html(   R   (    (    R   R=      s    c         C   s   d S(   Ni   (    (   R   (    (    R   t   __len__   s    c         C   s   |  i   } y( t i i |  } t i i |  } Wn t	 d |  i
 | f  n X| i d t |   | i d |  | i d |  i  d S(   t    s   %s (%s)s   Last-Modifieds   Content-Lengths   Content-TypeR   N(   R   R<   R	   t   ost   patht   getsizet   filesizet   getmtimet	   filemtimet   cant_read_excR   t   RESPONSEt	   setHeadert   rfc1123_dateR   (   R   R   RO   R	   RM   RK   (    (    R   t   HEAD   s      c         C   s7   t  i d  |  |  t |  d  p d |  _ n d  S(   Nt   __setstate__RA   i   (   R   t   inheritedAttributeR   t   stateR   RA   (   R   RU   (    (    R   RS      s    RE   c         C   s   d } | o% t t d d |  i    } d } n` |  i   } |  i } t |  p |  i	   n t |  p" t t d d d d  } d } n |  i
 | | | |  d S(   s   
            Returns the contents of the file.  Also, sets the
            Content-Type HTTP header to the objects content type.
        i    t   Productst   Photos	   image/gift   iconss
   broken.gifN(   t   iconR%   t   SOFTWARE_HOMER   t   getIconPathR	   R   R<   t   isfilet   _undot   _output_fileR   RO   (   R   R   RO   R	   R   RY   (    (    R   RE      s     
	 
c         C   s  d } y( t i i |  } t i i |  } Wn | d |  i	 | f  n X| i d d!  } | d! j	 o t i | d  d } y t t |  i    } Wn d! } n X| d! j	 o t |  } | d j oh | | j o[ | i d t |   | i d |  | i d |  | i d	 d
  | i d  d SqAqEn | i d d!  } | i d d!  } | d! j	 ot i |  } | d! j	 o t |  d j o2 | d  d j o! | |  i    j o
 d! } qMqQt i | d  d } y t t |  i    } Wn d! } n X| d! j	 o' t |  } | | j o
 d! } qMqQn | o	d } x, | D]$ \ } }
 | | j  o d } PqeqeW| po | i d d |  | i d	 d
  | i d t |   | i d |  | i d |  | i d  d Sn t |  d j o | d \ } }
 |
 | }	 | i d t |   | i d |  | i d |	  | i d	 d
  | i d d | |
 d | f  | i d  t& | d  } |  i( | | | |	  | i)   d Sqat*   } d t |  t |  d t |  t |  t d |  }	 x: | D]2 \ } }
 |	 t d | |
 d f  |
 | }	 q+W| i d |	  | i d	 d
  | i d t |   | i d d |  | i d  d } t& | d  } xn | D]f \ } }
 | i- d |  | i- d |  | i- d | |
 d | f  |  i( | | | |
 |  qW| i- d  |  | i)   d Sqen | i d t |   | i d |  | i d |  | i d	 d
  |  i. | |  d S("   se   
            Write the necesary header information for
            (possibly) chunked output
        s   Can't read: s   %s (%s)s   If-Modified-Sincet   ;i    s   Last-Modifieds   Content-Types   Content-Lengths   Accept-Rangest   bytesi0  R   t   Ranges   If-Rangei   i   t   tss   Content-Ranges
   bytes */%di  s   bytes %d-%d/%di   t   rbi   i1   s   %ds   %d%ds!   multipart/byteranges; boundary=%ss   
--%s
s   Content-Type: %s
s!   Content-Range: bytes %d-%d/%d

s
   
--%s--
N(/   RN   RH   RI   RJ   R	   RK   RL   RM   R   R   R   t
   get_headerR   t   headerR   t   splitt   longt   DateTimet   timeTimet	   mod_sincet   last_modRO   RP   RQ   R   t	   setStatust   ranget   if_ranget   HTTPRangeSupportt
   parseRanget   rangest   lent
   http__etagt   datet   satisfiablet   startt   endt   sizet   opent   fdt   _writesegmentt   closet   choose_boundaryt   boundaryt   post   writet   _copy(   R   R   RO   R	   R   Rj   R   Re   Rn   Rx   Rw   Rv   RK   RN   R~   Ru   Rq   Rz   Rt   RM   Rk   Rm   (    (    R   R^      s      	  
$  
 			
		
	@ *	 
c         C   s   d |  i    d S(   s8    The default view of the contents of the File or Image. t   RedirectN(   R   t   absolute_url(   R   (    (    R   t   view_image_or_file  s     t   linkc         K   sz   | d j o |  i   } n d |  i   } x6 | i   D]( } | i |  } d | | | f } q: Wd | | f } | S(   s$    return a HTML link tag to the file R   s   <a href="%s"s
   %s %s="%s"s	   %s>%s</a>N(
   t   textR   t   title_or_idR   t   strgt   argst   keyst   keyt   gett   value(   R   R   R   R   R   R   (    (    R   R     s       t   icon_gifc         C   s;   t  t d d |  i    } d } |  i | | | |  d S(   s)    return an icon for the file's MIME-Type RV   RW   s	   image/gifN(	   R%   RZ   R   R[   R	   R   R^   R   RO   (   R   R   RO   R	   R   (    (    R   R     s
     t	   icon_htmlc         C   s   d |  i   S(   s8    The icon embedded in html with a link to the real file s"   <img src="%s/icon_gif" border="0">N(   R   R   (   R   (    (    R   R     s     c         C   s@   |  i   } t |  p# |  i   t |  p d Sq< n d S(   s@    Check if external file exists and return true (1) or false (0) i   i    N(   R   R<   t   fnR\   R]   (   R   R   (    (    R   R9     s     
c         C   sg   |  i p d Sn |  i   } t |  p |  i   n t |  o t i |  d } n d } | S(   s'    Returns the size of the file or image i    i   N(	   R   RA   R<   R   R\   R]   RH   t   statRx   (   R   R   Rx   (    (    R   R:     s     
  c         C   s   |  i |  i    S(   s:    Returns a formatted stringified version of the file size N(   R   t   _bytetostringR:   (   R   (    (    R   Rx     s     c         C   s   | d j o |  i  } n t } x  |  i D] } t | |  } q* Wt |  t	 i
 j o$ xA | D] } t | |  } q` Wn! | d j o t | |  } n | S(   so    Generate the full filename, including directories from
            self._repository and self.filename
        R   N(   R	   R   R   t   INSTANCE_HOMERI   t   _repositoryt   itemR%   R   t   typest   ListType(   R   R	   R   RI   (    (    R   R<     s      
  s   dtml/extFileEditc         C   so   | d j o | |  _  n |  i | j o | |  _ n | d j	 o' d |  i } |  i |  | d | Sn d S(   s    Manage the edited values R   s'   The properties of %s have been changed!t   manage_tabs_messageN(   R   R   R   R   R   R   R   R,   (   R   R   R   R   R   (    (    R   R3     s     s   dtml/docUploadc         C   s   |  i |  i  } |  i | |  i |   y | i d  Wn n X| i   } |  i
 | | d  |  i | p |  i  |  _ | |  _ | i   d |  _ | d j	 o  d } |  i |  | d | Sn d S(   s"    Upload file from local directory i    id   i   s#   The file was uploaded successfully!R   N(   R   t   _get_ufnR	   t   new_fnR   R   R<   t   seekt   readt   contentt   _get_content_typeR   R   R|   RA   R   R   R   R,   (   R   R   R   R   R   R   R   (    (    R   R     s        	
	c         C   s  |  i | |  |  i | |  | i d d  } | d } |  i	 |  i
  } |  i | |  i |   y | i d  Wn n Xd |  _ y5 |  i | | i d  |  i | p |  i  |  _ Wn7 t t j o# t i |  i |   d |  _ qn
 X| |  _
 | i d  | S(   s    Handle HTTP/FTP PUT requests s   content-typet   BODYFILEi    i   id   i   N(   R   t	   dav__initR   RO   t   dav__simpleifhandlerRd   R   R   t   instreamR   R	   R   R   R<   R   RA   R   R   R   t   UNDO_POLICYt   ALWAYS_BACKUPRH   t   removeRl   (   R   R   RO   R   R   R   (    (    R   R4     s.     
  		 	c         C   s   t  | d d  } | o | i d  o | d } nK t |  t d  j	 o | i } n t	 t  | d |  | |  \ } } | S(   s    Determine the mime-type t   headerss   content-typeR   R	   N(   t   getattrR   R   R   t   has_keyR   R   t   bodyt   datat   guess_content_typeR   t   enc(   R   R   R   R   R   R   R   (    (    R   R     s      c         C   s   | i |  d d >} | | j  o
 | } n | } yb x[ | d j oM | i |  } | i	 |  | t
 |  } | | j  o
 | } q: | } q: WWn) t j
 o t d |  i t f  n Xd S(   s8    Write a segment of the file. The file is already open. i   i   i    s   %s (%s)N(   R   R   Rv   t	   blocksizet   lengtht   nextsizeR   t   blockt	   outstreamR   Rr   t   IOErrorR   R   R	   (   R   R   R   Rv   R   R   R   R   (    (    R   R{     s"     

 
i @  c   
      C   s  t  |  t i j o| y t | d  } Wn\ t j
 oP |  i   y t | d  } Wq t j
 o t d |  i	 | f  q Xn Xd } n | } d } t  |  t i j oI y t | d  } Wn) t j
 o t d |  i	 | f  n Xd } n | } d } y d d >}	 | i |	  } | i |  | d } xK t |  |	 j o7 | d j o* | d } | i |	  } | i |  q?WWn) t j
 o t d |  i	 t f  n X| o | i   n | o | i   n d S(	   s3   Read binary data from infile and write it to outfile
            infile and outfile may be strings, in which case a file with that
            name is opened, or filehandles, in which case they are accessed
            directly.
            A block is 131072 bytes. maxblocks prevents it from >2GB
        Rc   s   %s (%s)i   i    t   wbi   i   N(   R   t   infileR   t
   StringTypeRy   R   R   R   R]   R   t   close_int   outfileR   t	   close_outR   R   R   R   t	   maxblocksRr   R	   R|   (
   R   R   R   R   R   R   R   R   R   R   (    (    R   R   5  sJ     
 



  
  c         C   s   t  |  } | d j oh | d } d } | d j o | d } d } n d | } | d  } | d d j o | d  } q n d	 } d
 | } | d | } | S(   sq    Convert an int-value (file-size in bytes) to an String
            with the file-size in Byte, KB or MB
        i  i   t   KBt   MBs   %4.2fi   i   t   .t   Bytess   %4.0fRG   N(   t   floatR   R`   t   typR   (   R   R   R   R`   R   (    (    R   R   b  s      




 
c         C   sa   |  i g  j o d Sn |  i   } t |  o+ t | d  o |  i |  d |  _ n d S(   s+    restore filename after undo or copy-paste Ns   .undoi   (   R   R	   R<   R   R\   t   _restorefileRA   (   R   R   (    (    R   R]   v  s     c         C   s/   y t  i | | d  Wn n Xd |  _ d S(   s     Move the file to the undo file s   .undoi    N(   RH   t   renameR	   R   RA   (   R   R	   (    (    R   t   _deletefile  s       c         C   s   |  i | |  d S(   sT    Copy a file in the repository
            This actually involves copying two files N(   R   R   t   old_fnR   (   R   R   R   (    (    R   t	   _copyfile  s     c         C   s&   y t  i | d |  Wn n Xd S(   s    Recover the file from undo s   .undoN(   RH   R   R	   (   R   R	   (    (    R   R     s
       c         C   sz   t  t j p | g  j o |  i   } n | } | o> |  i |  } t  t j o |  i |  qv |  i	 |  n | S(   sp    If no unique filename has been generated, generate one
            otherwise, return the existing one.
        N(
   R   R   R	   R   t   _get_new_ufnR   R<   R   R   R   (   R   R	   R   R   (    (    R   R     s     c         C   s"  t  |  d  o# |  i o t i |  i d  }	 n  t i |  i d  d  d  }	 t d |	  }	 t i	 |  i
 d  } | d o |  i
 |  }
 |  i
 | } n |  i
 }
 d } g  } t t j o
 |	 } n t t j ox d } d } |
 } xc t |  D]Q } t |  | | | j  o | i | d  q | i | |   | | } q Wn t } t i | d	  d
 j o1 t i | d	 d  } t t   i d   } n d
 } d } t i | d  d j o | t  n t i | d  d
 j oe t  |  d  o< |  i" i# d  o) |  i" d i$ } t i | d |  } qPt i | d d  } n t i | d  d
 j o+ t i& |	 d  } t i | d |  } n t i | d  d
 j p t i | d  d
 j o. t i | d |
  } t i | d |  } n |  i' |  } t) i( i* |  p. d } y t) i, |  WqD| |  qDXn | o# t- | t i | d |   } n t- | t i | d d   } xL t/ |  p t/ | d  o- | d } t- | t i | d |   } qW| o t i | d |  } n t i | d d  } | i |  | S(   s    Create a new unique filename RC   R
   i   iR   R   i   t   _s   %ti    s   %cs
   %m%d%H%M%Ss   Invalid file format: s   %uR   t   AUTHENTICATED_USERs   %ps   %ns   %es   Can't create directory: s   .undoN(0   R   R   RC   R   Rf   t   rel_url_listR   t   filterR   R   R   R   t   id_namet   id_extt   dirst
   REPOSITORYt	   SYNC_ZODBt   SLICEDt   slice_deptht   slice_widtht   tempRm   t   iRr   t   appendt   FILE_FORMATt
   fileformatt   findt   replacet   intRh   t   strftimet   countert   invalid_format_excR   R   t   namet   usert
   joinfieldsR<   RI   RH   t   isdirt	   mkdir_exct   makedirsR%   R   R\   (   R   R   R   R   R   R   R   R   R   R   R   RI   R   R   R   R   R   (    (    R   R     s|     	
 #2# 
$ c         C   sj   |  i   } |  i   } t |  o |  i | |  i |   n | |  _ d |  _ t	 i
 d  |  |  S(   s    When a copy of the object is created (zope copy-paste-operation),
            this function is called by CopySupport.py. A copy of the external 
            file is created and self.filename is changed.
            Called AFTER manage_afterAdd
        i   t   manage_afterCloneN(   R   R<   R   R   R   R\   R   R	   RA   R   RT   R   (   R   R   R   R   (    (    R   R     s     		c         C   s   |  i d j o |  i g  j o |  i   } | p
 |  i   } t |  o |  i | |  i |   n3 t | d  o! |  i | d |  i |   n | |  _ d |  _ n t	 i
 d  |  | |  S(   s   This method is called, whenever _setObject in ObjectManager gets
            called. This is the case after a normal add and if the object is a
            result of cut-paste- or rename-operation. In the first case, the
            external files doesn't exist yet, otherwise it was renamed to .undo
            by manage_beforeDelete before and must be restored by _undo().

            When FTP PUT: __init__, PUT, _setObject called and
            file_uploaded == 1, filename!=[]

            When cut-n-paste: file_uploaded set to 0 in manage_beforeDelete and
            file is renamed to x.undo. Filename points to original file.

            When copy-n-paste: file_uploaded == 1, and filename points to
            original file.
        i    s   .undoi   t   manage_afterAddN(   R   RA   R	   R<   R   R   R   R\   R   R   RT   R   t	   container(   R   R   R   R   R   (    (    R   R     s      !	c         C   s;   |  i   } |  i |  d |  _ t i d  |  | |  S(   s]   This method is called, when the object is deleted. To support
            undo-functionality and because this happens too, when the object
            is moved (cut-paste) or renamed, the external file is not deleted.
            It are just renamed to filename.undo and remains in the
            repository, until it is deleted manually.
        i    t   manage_beforeDeleteN(	   R   R<   R   R   RA   R   RT   R   R   (   R   R   R   R   (    (    R   R   !  s
     	(4   t   __name__t
   __module__t   __doc__t   WriteLockInterfacet   __implements__t   _propertiest   manage_optionst   ClassSecurityInfoR    t   declareProtectedt	   meta_typeR   R   RD   R=   RF   t   HEAD__roles__RR   RS   RE   R^   R   R   t   declarePublicR   R   R9   R:   t   rawsizeRx   R<   t   DTMLFilet   globalsR,   R3   R.   R   R6   R4   R   R{   R   R   R]   R   R   R   R   R   R   R   R   (    (    (    R   R   w   sz    	Eo								
					
			-								W	(5   R   R@   t   Globalst   __main__t   AccessControlR   R   t   OFS.SimpleItemt
   SimpleItemt   OFS.PropertyManagert   PropertyManagert   OFS.ObjectManagert   BeforeDeleteExceptionR   R'   t   zope.app.content_typesR   t   webdav.commonRQ   Rh   t   webdav.WriteLockInterfaceR   t	   mimetoolsR}   t
   ZPublisherRo   t   urllibRH   R   R   t   os.pathR%   R\   R   t	   cStringIOt   StringIOt	   bad_charst
   good_charst	   maketransR   R   t   FLATR   R   R   R   t   BACKUP_ON_DELETER   R   R   R(   R   t   InitializeClass(&   R   R   R   R   Rh   R   R   R\   R   R  R(   Ro   R@   R   R  R   R   R   R   R   R   R   R   R   RQ   R'   R   R  R%   R  R   R   R	  R   R   R}   RH   R  (    (    R   t   ?   sL   	$	  	   