
    qiwb                        S r SSKrSSKrSSKJr  SSKJr  SSKJr  SSK	J
r
JrJrJr  SSKJrJrJr  SSKJr  S	r\R*                  " \5      rS
r SrSSSSS/SS\R4                  R7                  \S5      \R4                  R7                  \S5      /S.SSSSS/SS\R4                  R7                  \S5      /S.SSR9                  5       SS/SS\R4                  R7                  \S5      /S./rS  rS! r " S" S#\5      r  " S$ S%\5      r! " S& S'\5      r" " S( S)\5      r# " S* S+\5      r$ " S, S-\$5      r% " S. S/\$5      r& " S0 S1\5      r'g)2aN  
Sample implementation of a DAV provider that provides a browsable,
multi-categorized resource tree.

Note that this is simply an example with no concrete real world benefit.
But it demonstrates some techniques to customize WsgiDAV.

Compared to a published file system, we have these main differences:

#. A resource like ``My doc 1`` has several attributes like ``key``,
   ``orga``, ``tags``, ``status``, ``description``.
   Also there may be a list of attached files.
#. These attributes are used to dynamically create a virtual hierarchy.
   For example, if ``status`` is ``draft``, a collection
   ``<share>/by_status/draft/`` is created and the resource is mapped to
   ``<share>/by_status/draft/My doc 1``.
#. The resource ``My doc 1`` is rendered as a collection, that contains
   some virtual descriptive files and the attached files.
#. The same resource may be referenced using different paths
   For example ``<share>/by_tag/cool/My doc 1``,
   ``<share>/by_tag/hot/My doc 1``, and ``<share>/by_key/1`` map to the same
   resource.
   Only the latter is considered the *real-path*, all others are
   *virtual-paths*.
#. The attributes are exposed as live properties, like "{virtres:}key",
   "{virtres:}tags", and "{virtres:}description".
   Some of them are even writable. Note that modifying an attribute may also
   change the dynamically created tree structure.
   For example changing "{virtres:}status" from 'draft' to 'published' will
   make the resource appear as ``<share>/by_status/published/My doc 1``.
#. This provider implements native delete/move/copy methods, to change the
   semantics of these operations for the virtual '/by_tag/' collection.
   For example issuing a DELETE on ``<share>/by_tag/cool/My doc 1`` will
   simply remove the 'cool' tag from that resource.
#. Virtual collections and artifacts cannot be locked.
   However a resource can be locked.
   For example locking ``<share>/by_tag/cool/My doc 1`` will also lock
   ``<share>/by_key/1``.
#. Some paths may be hidden, i.e. by_key is not browsable (but can be referenced)
   TODO: is this WebDAV compliant?

The *database* is a simple hard coded variable ``_resourceData``, that contains
a list of resource description dictionaries.

A resource is served as an collection, which is generated on-the-fly and
contains some virtual files (*artifacts*).

In general, a URL is interpreted like this::

  <share>/<category-type>/<category-key>/<resource-name>/<artifact-name>


An example layout::

    <share>/
        by_tag/
            cool/
                My doc 1/
                    .Info.html
                    .Info.txt
                    .Description.txt
                    MySpec.pdf
                    MySpec.doc
                My doc 2/
            hot/
                My doc 1/
                My doc 2/
            nice/
                My doc 2/
                My doc 3
        by_orga/
            development/
                My doc 3/
            marketing/
                My doc 1/
                My doc 2/
        by_status/
            draft/
                My doc 2
            published/
                My doc 1
                My doc 3
        by_key/
            1/
            2/
            3/

When accessed using WebDAV, the following URLs both return the same resource
'My doc 1'::

    <share>/by_tag/cool/My doc 1
    <share>/by_tag/hot/My doc 1
    <share>/by_key/1
    N)BytesIO)quote)util)HTTP_FORBIDDENHTTP_INTERNAL_ERRORDAVError#PRECONDITION_CODE_ProtectedProperty)DAVCollectionDAVNonCollectionDAVProvider)join_urizreStructuredText eni    zc:\temp\virtfiles1zMy doc 1developmentcoolhotdraftz/This resource contains two specification files.z
MySpec.docz
MySpec.pdf)keytitleorgatagsstatusdescriptionresPathList2zMy doc 2nice	publishedz This resource contains one file.z
My URS.doc3u   My doc (euro:€, uuml:��)	marketingzLong text describing itc                    U [         R                  ;   d   eU S:X  a-  [         Vs/ s H  o"R                  S5      U:X  d  M  UPM     sn$ U S:X  a.  [         Vs/ s H  o"R                  S5      U:X  d  M  UPM     nnU$ U S:X  a,  [         Vs/ s H  o!UR                  S5      ;   d  M  UPM     nnW$ s  snf s  snf s  snf ) 	by_statusr   by_orgar   by_tagr   )RootCollection_visibleMemberNames_resourceDataget)attrNameattrValdataresLists       Y/home/kali/flask_env/lib/python3.13/site-packages/wsgidav/samples/virtual_dav_provider.py_get_res_list_by_attrr-      s    ~99999;!.P((82D2OPP	Y	$1QMDXXf5E5P4MQ N 
X	$1QMD@P5P4MQN QQQs#   B2B2B74B7B<(B<c                 8    [          H  nUS   U :X  d  M  Us  $    g)r    r   N)r&   )r   r*   s     r,   _get_res_by_keyr/      s"    ;#K      c                   F   ^  \ rS rSrSrSr\S-   rU 4S jrS rS r	Sr
U =r$ )	r$      zResolve top-level requests '/'.)r"   r#   r!   )by_keyc                 &   > [         TU ]  SU5        g )N/super__init__)selfenviron	__class__s     r,   r8   RootCollection.__init__   s    g&r0   c                     U R                   $ N)r%   r9   s    r,   get_member_namesRootCollection.get_member_names   s    '''r0   c                 v    XR                   ;   a*  [        [        U R                  U5      U R                  5      $ g r>   )_validMemberNamesCategoryTypeCollectionr   pathr:   )r9   names     r,   
get_memberRootCollection.get_member   s-    ))))(499d*CT\\RRr0    )__name__
__module____qualname____firstlineno____doc__r%   rC   r8   r@   rG   __static_attributes____classcell__r;   s   @r,   r$   r$      s+    )<+k9'( r0   r$   c                   >   ^  \ rS rSrSrU 4S jrS rS rS rSr	U =r
$ )rD      z/Resolve '/catType' URLs, for example '/by_tag'.c                 $   > [         TU ]  X5        g r>   r6   r9   rE   r:   r;   s      r,   r8   CategoryTypeCollection.__init__       'r0   c                 
    SS0$ )NtypezCategory typerI   r?   s    r,   get_display_info'CategoryTypeCollection.get_display_info   s    ((r0   c                 t   / n[          H  nU R                  S:X  a!  US   U;  a  UR                  US   5        M2  M4  U R                  S:X  a!  US   U;  a  UR                  US   5        Mc  Me  U R                  S:X  d  Mw  US    H  nX1;  d  M
  UR                  U5        M     M     UR                  5         U$ )Nr!   r   r"   r   r#   r   )r&   rF   appendsort)r9   namesr*   tags       r,   r@   'CategoryTypeCollection.get_member_names   s    !DyyK'>.LLh0 /i'<u,LLf. -h&<C'S) ( " 	

r0   c                    U R                   S:X  a>  [        U5      nU(       a+  [        [        U R                  U5      U R
                  U5      $ g [        [        U R                  U5      U R
                  U R                   5      $ )Nr3   )rF   r/   VirtualResourcer   rE   r:   CategoryCollectionr9   rF   r*   s      r,   rG   !CategoryTypeCollection.get_member   s_    99 "4(D&x		4'@$,,PTUU!(499d";T\\499UUr0   rI   rJ   rK   rL   rM   rN   r8   rZ   r@   rG   rO   rP   rQ   s   @r,   rD   rD      s!    9()"V Vr0   rD   c                   >   ^  \ rS rSrSrU 4S jrS rS rS rSr	U =r
$ )rd      z8Resolve '/catType/cat' URLs, for example '/by_tag/cool'.c                 0   > [         TU ]  X5        X0l        g r>   )r7   r8   catType)r9   rE   r:   rk   r;   s       r,   r8   CategoryCollection.__init__   s    'r0   c                 
    SS0$ )NrY   CategoryrI   r?   s    r,   rZ   #CategoryCollection.get_display_info   s    
##r0   c                     [        U R                  U R                  5       Vs/ s H  oS   PM	     nnUR                  5         U$ s  snf Nr   )r-   rk   rF   r^   )r9   r*   r_   s      r,   r@   #CategoryCollection.get_member_names   sE    &;DLL$))&T
&TdM&T 	 
 	

	
s   Ac                     [        U R                  U R                  5       H9  nUS   U:X  d  M  [        [	        U R
                  U5      U R                  U5      s  $    g rq   )r-   rk   rF   rc   r   rE   r:   re   s      r,   rG   CategoryCollection.get_member  sL    )$,,		BDG}$&x		4'@$,,PTUU C r0   )rk   rg   rQ   s   @r,   rd   rd      s    B$ r0   rd   c                      ^  \ rS rSrSrSr/ SQrU 4S jrS rS r	S r
S	 rS
 rS rS rU 4S jrU 4S jrSS jrSrU =r$ )rc   i  zGA virtual 'resource', displayed as a collection of artifacts and files.)	.Info.txt
.Info.html.Description.txt){virtres:}key{virtres:}title{virtres:}status{virtres:}orga{virtres:}tags{virtres:}descriptionc                 0   > [         TU ]  X5        X0l        g r>   r7   r8   r*   r9   rE   r:   r*   r;   s       r,   r8   VirtualResource.__init__  s    '	r0   c                 
    SS0$ )NrY   zVirtual ResourcerI   r?   s    r,   rZ    VirtualResource.get_display_info"  s    *++r0   c                     [        U R                  5      nU R                  S    H3  n[        R                  R                  U5      nUR                  U5        M5     U$ Nr   )list_artifactNamesr*   osrE   basenamer]   )r9   r_   frF   s       r,   r@    VirtualResource.get_member_names%  sL    T(()=)A77##A&DLL * r0   c                 p   XR                   ;   a5  [        [        U R                  U5      U R                  U R
                  5      $ U R
                  S    H_  n[        R                  R                  U5      nX1:X  d  M)  [        [        U R                  U5      U R                  U R
                  U5      s  $    g r   )	r   VirtualArtifactr   rE   r:   r*   r   r   VirtualResFile)r9   rF   	file_pathfnames       r,   rG   VirtualResource.get_member,  s    &&&"8DIIt#<dllDIIVV=1IGG$$Y/E}%TYY-t||TYY	  2 r0   c                    SU R                   ;  a  [        [        5      e[        R                  " U R                   R                  S5      SS5      u  pnUS:X  d   eX R                  S   ;   d   eU R                  S   R                  U5        g)z2Change semantic of DELETE to remove resource tags./by_tag/r5      r#   r   T)rE   r   r   r   
save_splitstripr*   remove)r9   rk   r`   _rests       r,   handle_deleteVirtualResource.handle_delete7  s|     TYY&>**"oodiiooc.BCKe("""ii''''		&  %r0   c                    SU;  a  [        [        5      e[        R                  " UR	                  S5      SS5      u  p4nUS:X  d   eX@R
                  S   ;  a  U R
                  S   R                  U5        g)z-Change semantic of COPY to add resource tags.r   r5   r   r#   r   T)r   r   r   r   r   r*   r]   )r9   	dest_pathdepth_infinityrk   r`   r   s         r,   handle_copyVirtualResource.handle_copyC  sn     Y&>**"ooiooc.BCKe("""ii''IIf$$S)r0   c                    SU R                   ;  a  [        [        5      eSU;  a  [        [        5      e[        R                  " U R                   R                  S5      SS5      u  p#nUS:X  d   eX0R                  S   ;   d   eU R                  S   R                  U5        [        R                  " UR                  S5      SS5      u  p#nUS:X  d   eX0R                  S   ;  a  U R                  S   R                  U5        g)z0Change semantic of MOVE to change resource tags.r   r5   r   r#   r   T)	rE   r   r   r   r   r   r*   r   r]   )r9   r   rk   r`   r   s        r,   handle_moveVirtualResource.handle_moveN  s     TYY&>**Y&>**"oodiiooc.BCKe("""ii''''		&  %"ooiooc.BCKe("""ii''IIf$$S)r0   c                 j    SU R                   S   -  n[        U R                  R                  U-   5      $ )Nz
/by_key/%sr   )r*   r   provider
share_pathr9   refPaths     r,   get_ref_urlVirtualResource.get_ref_url_  s/    5!11T]]--788r0   c                `   > [         TU ]  US9nUR                  [        R                  5        U$ )zaReturn list of supported property names in Clark Notation.

See DAVResource.get_property_names()
)
is_allprop)r7   get_property_namesextendrc   _supportedProps)r9   r   propNameListr;   s      r,   r   "VirtualResource.get_property_namesc  s1     w1Z1HO;;<r0   c                 <  > US:X  a  U R                   S   $ US:X  a  U R                   S   $ US:X  a  U R                   S   $ US:X  a  U R                   S   $ US	:X  a  S
R                  U R                   S   5      $ US:X  a  U R                   S   $ [        TU ]  U5      $ )z:Return the value of a property.

See get_property_value()
ry   r   rz   r   r{   r   r|   r   r}   ,r   r~   r   )r*   joinr7   get_property_value)r9   rF   r;   s     r,   r   "VirtualResource.get_property_valuen  s     ?"99U##&&99W%%''99X&&%%99V$$%%88DIIf-..,,99]++w)$//r0   c                 .   Uc  [        [        5      eUS:X  a)  UR                  R                  S5      U R                  S'   gUS:X  a  UR                  U R                  S'   gU[
        R                  ;   a  [        [        [        S9e[        [        5      e)zDSet or remove property value.

See DAVResource.set_property_value()
Nr}   r   r   r~   r   )err_condition)r   r   textsplitr*   rc   r   r	   )r9   rF   valuedry_runs       r,   set_property_value"VirtualResource.set_property_value  s    
 =>**## %

 0 0 5DIIf 	 ,,',zzDIIm$ 	 _444.Q 
 >**r0   r*   )F)rJ   rK   rL   rM   rN   r   r   r8   rZ   r@   rG   r   r   r   r   r   r   r   rO   rP   rQ   s   @r,   rc   rc     sP    QNO,	
	"9	0, r0   rc   c                   \   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
S	 rS
 rS rSrU =r$ )_VirtualNonCollectioni  z5Abstract base class for all non-collection resources.c                 $   > [         TU ]  X5        g r>   r6   rU   s      r,   r8   _VirtualNonCollection.__init__  rW   r0   c                     g r>   rI   r?   s    r,   get_content_length(_VirtualNonCollection.get_content_length      r0   c                     g r>   rI   r?   s    r,   get_content_type&_VirtualNonCollection.get_content_type  r   r0   c                     g r>   rI   r?   s    r,   get_creation_date'_VirtualNonCollection.get_creation_date  r   r0   c                     U R                   $ r>   )rF   r?   s    r,   get_display_name&_VirtualNonCollection.get_display_name  s    yyr0   c                     [         er>   )NotImplementedErrorr?   s    r,   rZ   &_VirtualNonCollection.get_display_info  s    !!r0   c                     g r>   rI   r?   s    r,   get_etag_VirtualNonCollection.get_etag  r   r0   c                     g r>   rI   r?   s    r,   get_last_modified'_VirtualNonCollection.get_last_modified  r   r0   c                     g)NFrI   r?   s    r,   support_ranges$_VirtualNonCollection.support_ranges  s    r0   rI   )rJ   rK   rL   rM   rN   r8   r   r   r   r   rZ   r   r   r   rO   rP   rQ   s   @r,   r   r     s8    ?(" r0   r   c                   P   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
S	 rS
rU =r$ )r   i  z1A virtual file, containing resource descriptions.c                 0   > [         TU ]  X5        X0l        g r>   r   r   s       r,   r8   VirtualArtifact.__init__  s    '	r0   c                 P    [        U R                  5       R                  5       5      $ r>   )lenget_contentreadr?   s    r,   r   "VirtualArtifact.get_content_length  s    4##%**,--r0   c                 F    U R                   R                  S5      (       a  gg)Nz.txtz
text/plain	text/html)rF   endswithr?   s    r,   r    VirtualArtifact.get_content_type  s    99f%%r0   c                 
    SS0$ )NrY   zVirtual info filerI   r?   s    r,   rZ    VirtualArtifact.get_display_info  s    +,,r0   c                     g)NTrI   r?   s    r,   prevent_lockingVirtualArtifact.prevent_locking  r   r0   c                     SR                  U R                  S   U R                  5      n[        U R                  R
                  U-   5      $ Nz/by_key/{}/{}r   )formatr*   rF   r   r   r   r   s     r,   r   VirtualArtifact.get_ref_url  s;    !((5)9499ET]]--788r0   c                 .   U R                   S    Vs/ s H)  nS[        R                  R                  U5       SU S3PM+     nnU R                   R	                  5       nSR                  U5      US'   U R                  S:X  a  SU-  nOU R                  S	:X  a  U R                   S
   S[        U R                   S
   5      -  U R                   S   SSU R                   S   -  SU R                   S   -  SSR                  U R                   S   5      -  SU R                   S   -  /nSR                  U5      nO=U R                  S:X  a  U R                   S   nO[        [        SU R                  -  5      e[        [        R                  " U5      5      $ s  snf )Nr   z	<a href='z'>z</a>
z, 	fileLinksrw   a0              <html><head>
            <title>%(title)s</title>
            </head><body>
            <h1>%(title)s</h1>
            <table>
            <tr>
                <td>Description</td>
                <td>%(description)s</td>
            </tr><tr>
                <td>Status</td>
                <td>%(status)s</td>
            </tr><tr>
                <td>Tags</td>
                <td>%(tags)s</td>
            </tr><tr>
                <td>Orga unit</td>
                <td>%(orga)s</td>
            </tr><tr>
                <td>Files</td>
                <td>%(fileLinks)s</td>
            </tr><tr>
                <td>Key</td>
                <td>%(key)s</td>
            </tr>
            </table>
            <p>This is a virtual WsgiDAV resource called '%(title)s'.</p>
            </body></html>rv   r   =r   r    z
Status: %sr   zOrga:   %8sr   zTags:   '%s'z', 'r   z
Key:    %sr   
rx   zInvalid artifact '%s')r*   r   rE   r   copyr   rF   r   r   r   r   r   to_bytes)r9   r   r   dicthtmlliness         r,   r   VirtualArtifact.get_content  s    YY}-
- ((+,Bqc8- 	 
 yy~~ IIi0[99$8 9 > YY+%		'"c$))G,--		-(tyy22		& 11TYYv->!??tyy//	E 99U#DYY,,99]+D.0G$))0STTt}}T*++m
s   0Fr   )rJ   rK   rL   rM   rN   r8   r   r   rZ   r   r   r   rO   rP   rQ   s   @r,   r   r     s.    ;
.
-97, 7,r0   r   c                   V   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
S	 rS
 rSrU =r$ )r   i"  zCRepresents an existing file, that is a member of a VirtualResource.c                    > [         R                  R                  U5      (       d  [        R	                  SU-  5        [
        TU ]  X5        X0l        X@l        g )Nz"VirtualResFile(%r) does not exist.)	r   rE   exists_loggererrorr7   r8   r*   r   )r9   rE   r:   r*   r   r;   s        r,   r8   VirtualResFile.__init__%  s?    ww~~i((MM>JK'	"r0   c                 h    [         R                  " U R                  5      nU[        R                     $ r>   )r   statr   ST_SIZEr9   statresultss     r,   r   !VirtualResFile.get_content_length,  s#    ggdnn-4<<((r0   c                     [         R                  R                  U R                  5      (       d  g[        R
                  " U R                  5      $ )Nr   )r   rE   isfiler   r   guess_mime_typer?   s    r,   r   VirtualResFile.get_content_type0  s3    ww~~dnn--
 ##DNN33r0   c                 h    [         R                  " U R                  5      nU[        R                     $ r>   )r   r  r   ST_CTIMEr  s     r,   r    VirtualResFile.get_creation_date9  #    ggdnn-4==))r0   c                 
    SS0$ )NrY   zContent filerI   r?   s    r,   rZ   VirtualResFile.get_display_info=  s    ''r0   c                 h    [         R                  " U R                  5      nU[        R                     $ r>   )r   r  r   ST_MTIMEr  s     r,   r    VirtualResFile.get_last_modified@  r  r0   c                     SR                  U R                  S   [        R                  R	                  U R
                  5      5      n[        U R                  R                  U-   5      $ r   )	r   r*   r   rE   r   r   r   r   r   r   s     r,   r   VirtualResFile.get_ref_urlD  sO    !((IIebgg..t~~>
 T]]--788r0   c                 8    [        U R                  S[        5      $ )Nrb)openr   BUFFER_SIZEr?   s    r,   r   VirtualResFile.get_contentJ  s    
 DNND+66r0   )r*   r   )rJ   rK   rL   rM   rN   r8   r   r   r   rZ   r   r   r   rO   rP   rQ   s   @r,   r   r   "  s3    M#)4*(*97 7r0   r   c                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )VirtualResourceProvideriU  z?
DAV provider that serves a VirtualResource derived structure.
c                 8   > [         TU ]  5         [        U l        g r>   )r7   r8   r&   resourceData)r9   r;   s    r,   r8    VirtualResourceProvider.__init__Z  s    )r0   c                     [         R                  SU-  5        U =R                  S-  sl        [        U5      nUR	                  SU5      $ )zReturn _VirtualResource object for path.

path is expected to be
    categoryType/category/name/artifact
for example:
    'by_tag/cool/My doc 2/info.html'

See DAVProvider.get_resource_inst()
zget_resource_inst('%s')   r    )r   info_count_get_resource_instr$   resolve)r9   rE   r:   roots       r,   get_resource_inst)VirtualResourceProvider.get_resource_inst^  sB     	.56%%*%g&||B%%r0   )r  )	rJ   rK   rL   rM   rN   r8   r'  rO   rP   rQ   s   @r,   r  r  U  s    *& &r0   r  )(rN   r   r  ior   urllib.parser   wsgidavr   wsgidav.dav_errorr   r   r   r	   wsgidav.dav_providerr
   r   r   wsgidav.utilr   __docformat__get_module_loggerrJ   r   r  FILE_FOLDERrE   r   encoder&   r-   r/   r$   rD   rd   rc   r   r   r   r  rI   r0   r,   <module>r3     s  ]| 
      N M !%

 
 
*
 # HGGLLl3GGLLl3
  9[,?@ 4;;=0[,?@-D	] &!V] !VH 6Om Oj, TQ,+ Q,n-7* -7f&k &r0   