
    qiEI                         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J	r	J
r
Jr  SSKJr  Sr\R                  " S5      rS	 rS
 rS rS rS r " S S5      rg)a  
Implements the `LockManager` object that provides the locking functionality.

The LockManager requires a LockStorageDict object to implement persistence.
Two alternative lock storage classes are defined in the lock_storage module:

- wsgidav.lock_man.lock_storage.LockStorageDict
- wsgidav.lock_man.lock_storage.LockStorageShelve


The lock data model is a dictionary with these fields:

    root:
        Resource URL.
    principal:
        Name of the authenticated user that created the lock.
    type:
        Must be 'write'.
    scope:
        Must be 'shared' or 'exclusive'.
    depth:
        Must be '0' or 'infinity'.
    owner:
        String identifying the owner.
    timeout:
        Seconds remaining until lock expiration.
        This value is passed to create() and refresh()
    expire:
        Converted timeout for persistence: expire = time() + timeout.
    token:
        Automatically generated unique token.

    N)pformat)util)HTTP_LOCKEDDAVErrorDAVErrorConditionPRECONDITION_CODE_LockConflict)ReadWriteLockreStructuredTextzwsgidav.lock_manc                  n    S[         R                  " [        [        R                  " S5      5      5      -   $ )Nzopaquelocktoken:   )r   to_strhexrandomgetrandbits     R/home/kali/flask_env/lib/python3.13/site-packages/wsgidav/lock_man/lock_manager.pygenerate_lock_tokenr   =   s&    C0B0B30G,H IIIr   c                 l    U (       d   e[         R                  " U 5      n SU R                  S5      -   n U $ )N/)r   r   strip)paths    r   normalize_lock_rootr   A   s.    K4;;tDC DKr   c                 f    [        U S   5      nUS:  =(       a    U[        R                  " 5       :  $ )Nexpirer   )floattime)lockr   s     r   is_lock_expiredr   I   s*    4>"FQ;/6DIIK//r   c           	         U (       d  gU S   S:  a  SR                  U S   5      nOBSR                  [        R                  " U S   5      U S   [        R                  " 5       -
  5      nSR                  U R	                  SS5      S	S
 U R	                  S5      U R	                  S5      U R	                  S5      U R	                  S5      U5      $ )zReturn readable rep.z
Lock: Noner   r   zInfinite ({})z{} (in {} seconds)z-Lock(<{}..>, {!r}, {}, {}, depth-{}, until {}tokenz??????????????????????????????      root	principalscopedepth)formatr   get_log_timer   get)	lock_dictr   s     r   lock_stringr,   N   s    Q ''	((;<%,,i12Ih4G$))+4U
 ;AAgx(B/fk"gg r   c                    [         R                  " U S   5      (       d   eU S   R                  S5      (       d   eU S   S:X  d   eU S   S;   d   eU S   S;   d   e[         R                  " U S	   5      (       d   U 5       e[	        U S
   5      nUS:  d  US:X  d   S5       e[         R                  " U S   5      (       d   eSU ;   a!  [         R                  " U S   5      (       d   eg g )Nr$   r   typewriter&   shared	exclusiver'   0infinityownertimeoutr   ztimeout must be positive or -1r%   r!   )r   is_str
startswithis_bytesr   )r   r7   s     r   validate_lockr<   e   s    ;;tF|$$$$<""3''''<7"""=3333=----==g''--'DO$GQ;'R-I)II';;tK())))${{4=)))) r   c                       \ rS rSrSrSrS rS rS rSS jr	S r
S	 rS
S.S jrS
S.S jrS rS rSS.S jrS
S.S jrS rS rSS.S jrS rS rSrg
)LockManagerw   zA
Implements locking functionality using a custom storage layer.

i:	 c                     [        US5      (       d   e[        5       U l        Xl        U R                  R	                  5         g)z(
storage:
    LockManagerStorage object
get_lock_listN)hasattrr	   _lockstorageopen)selfrD   s     r   __init__LockManager.__init__   s5    
 w0000"_
r   c                 8    U R                   R                  5         g )N)rD   closerF   s    r   __del__LockManager.__del__   s    r   c                 P    U R                   R                   SU R                  < S3$ )N())	__class____name__rD   rK   s    r   __repr__LockManager.__repr__   s%    ..))*!DLL+;1==r   c           	         0 n0 n0 n0 n[         R                  U  SU 35        U R                  R                  SSSSS9 H  nUS   n[	        U5      XW'   UR                  US   / 5      R                  U5        UR                  US   / 5      R                  U5        UR                  US	   / 5      R                  U5        M     [         R                  S
[        USSS9 35        U(       ad  [         R                  S[        USSS9 35        [         R                  S[        USSS9 35        [         R                  S[        USSS9 35        g g )Nz: r   TFinclude_rootinclude_children
token_onlyr!   r%   r6   r$   zLocks:
r      )indentwidthzLocks by URL:
   zLocks by principal:
zLocks by owner:
)_loggerinforD   rA   r,   
setdefaultappendr   )rF   msgurlDict	ownerDictuserDict	tokenDictr   toks           r   _dumpLockManager._dump   sN   		vRu%&LL..dTe / 
D w-C(.IN[ 126==cB  g3::3?tF|R077<
 	x	!3 GHIJLL?771C+P*QRSLL'#(N'OP LL,WYqPS-T,UVW r   c                     Uc  [         R                  nOUS:  a  SnUUUUUUUS.nU R                  R                  Xh5        U$ )ae  Acquire lock and return lock_dict.

principal
    Name of the principal.
lock_type
    Must be 'write'.
lock_scope
    Must be 'shared' or 'exclusive'.
lock_depth
    Must be '0' or 'infinity'.
lock_owner
    String identifying the owner.
path
    Resource URL.
timeout
    Seconds to live

This function does NOT check, if the new lock creates a conflict!
r   r8   )r$   r.   r&   r'   r6   r7   r%   )r>   LOCK_TIME_OUT_DEFAULTrD   create)	rF   r%   	lock_type
lock_scope
lock_depth
lock_ownerr   r7   r+   s	            r   _generate_lockLockManager._generate_lock   sX    , ?!77Gq[G "
	 	D,r   c          	         [        U5      nU R                  R                  5          U R                  XX4X5        U R	                  XrX4XQU5      U R                  R                  5         $ ! U R                  R                  5         f = f)zCheck for permissions and acquire a lock.

On success return new lock dictionary.
On error raise a DAVError with an embedded DAVErrorCondition.
)r   rC   acquire_write_check_lock_permissionrq   release)	rF   urlrm   rn   ro   rp   r7   r%   
token_lists	            r   acquireLockManager.acquire   st    " "#&

  "		!''

 &&jjw JJ DJJ s   &A( (BNr7   c                Z    Uc  [         R                  nU R                  R                  XS9$ )z0Set new timeout for lock, if existing and valid.r{   )r>   rk   rD   refresh)rF   r!   r7   s      r   r}   LockManager.refresh   s*    ?!77G||##E#;;r   keyc                `    US;   d   eU R                   R                  U5      nUb  Uc  U$ X2   $ )zReturn lock_dict, or None, if not found or invalid.

Side effect: if lock is expired, it will be purged and None is returned.

key:
    name of lock attribute that will be returned instead of a dictionary.
)	Nr.   r&   r'   r6   r$   r7   r%   r!   )rD   r*   )rF   r!   r   r   s       r   get_lockLockManager.get_lock   sG      

 

 
	
 

 ||&;$,Kyr   c                 :    U R                   R                  U5        g)zDelete lock.N)rD   delete)rF   r!   s     r   rv   LockManager.release  s    E"r   c                 (    U R                  USS9U:H  $ )zCReturn True, if <token> exists, is valid, and bound to <principal>.r%   r   )r   )rF   r!   r%   s      r   is_token_locked_by_user#LockManager.is_token_locked_by_user  s    }}U}4	AAr   F	recursivec                T    [        U5      nU R                  R                  USUSS9nU$ )zReturn list of lock_dict, if <url> is protected by at least one direct, valid lock.

Side effect: expired locks for this url are purged.
TFrV   )r   rD   rA   )rF   rw   r   lockLists       r   get_url_lock_listLockManager.get_url_lock_list  s7    
 "#&<<--dY5 . 
 r   )r%   c                   [        U5      n/ nUnU(       ar  U R                  R                  USSSS9nU H1  nXA:w  a  US   S:w  a  M  Ub
  X&S   :X  d  M   UR                  U5        M3     [        R
                  " U5      nU(       a  Mr  U$ )zReturn a list of valid lockDicts, that protect <path> directly or indirectly.

If a principal is given, only locks owned by this principal are returned.
Side effect: expired locks for this path and all parents are purged.
TFrV   r'   r5   r%   )r   rD   rA   ra   r   get_uri_parent)rF   rw   r%   r   u	lock_listr   s          r   get_indirect_url_lock_list&LockManager.get_indirect_url_lock_list  s     "#&22u 3 I "8W ;
 $	+5F(FOOD) " ##A&A a r   c                 @    U R                  U5      n[        U5      S:  $ )z'Return True, if url is directly locked.r   )r   len)rF   rw   r   s      r   is_url_lockedLockManager.is_url_locked8  s!    ))#.8}q  r   c                 `    U R                  USS9nU=(       a    [        R                  " X15      $ )z?Check, if url (or any of it's parents) is locked by lock_token.r$   r   )r   r   is_equal_or_child_uri)rF   rw   
lock_tokenlockUrls       r   is_url_locked_by_token"LockManager.is_url_locked_by_token=  s*    --
-7C455gCCr   c                   U R                   R                  5          U R                  XS9nU H  nU R                  US   5        M     U R                   R                  5         g ! U R                   R                  5         f = f)Nr   r!   )rC   rt   r   rv   )rF   rw   r   r   r   s        r   remove_all_locks_from_url%LockManager.remove_all_locks_from_urlB  sg    

  "	!--c-GH T']+ ! JJ DJJ s   ,A# #A?c                    US:X  d   eUS;   d   eUS;   d   e[         R                  SU SU SU SU S3	5        [        [        5      nU R                  R                  5          UnU(       a  U R                  U5      n	U	 H}  n
[         R                  SU S[        U
5       35        X:w  a  U
S   S	:w  a  M7  U
S
   S:X  a  US:X  a  MH  [         R                  S[        U
5       35        UR                  U
S   5        M     [        R                  " U5      nU(       a  M  US	:X  az  U R                  R                  USSSS9nU HX  n
[        R                  " XS   5      (       d   e[         R                  S[        U
5       35        UR                  U
S   5        MZ     U R                  R                  5         [        UR                   5      S:  a  [#        [$        US9eg! U R                  R                  5         f = f)a  Check, if <principal> can lock <url>, otherwise raise an error.

If locking <url> would create a conflict, DAVError(HTTP_LOCKED) is
raised. An embedded DAVErrorCondition contains the conflicting resource.

@see http://www.webdav.org/specs/rfc4918.html#lock-model

- Parent locks WILL NOT be conflicting, if they are depth-0.
- Exclusive depth-infinity parent locks WILL be conflicting, even if
  they are owned by <principal>.
- Child locks WILL NOT be conflicting, if we request a depth-0 lock.
- Exclusive child locks WILL be conflicting, even if they are owned by
  <principal>. (7.7)
- It is not enough to check whether a lock is owned by <principal>, but
  also the token must be passed with the request. (Because <principal>
  may run two different applications on his client.)
- <principal> cannot lock-exclusive, if he holds a parent shared-lock.
  (This would only make sense, if he was the only shared-lock holder.)
- TODO: litmus tries to acquire a shared lock on one resource twice
  (locks: 27 'double_sharedlock') and fails, when we return HTTP_LOCKED.
  So we allow multi shared locks on a resource even for the same
  principal.

@param url: URL that shall be locked
@param lock_type: "write"
@param lock_scope: "shared"|"exclusive"
@param lock_depth: "0"|"infinity"
@param token_list: list of lock tokens, that the user submitted in If: header
@param principal: name of the principal requesting a lock

@return: None (or raise)
r/   r0   r3   zcheckLockPermission(, rP   z    check parent r'   r5   r&   r1     -> DENIED due to locked parent r$   FTrV    -> DENIED due to locked child r   err_conditionN)r^   debugr   r   rC   acquire_readr   r,   add_hrefr   r   rD   rA   is_child_urirv   r   hrefsr   r   )rF   rw   rm   rn   ro   rx   r%   errcondr   r   r   
child_ockss               r   ru   "LockManager._check_lock_permissionK  s   F G###4444...."3%r*R
|2i[PQR	

 $$BC

!!	!A 2215	%DMM$5aS;t;L:M"NOxDMZ$? g(2zX7M !MM:;t;L:MN $$T&\2 & ''*! !$ Z'!\\77edu 8 
 'D,,Sv,????MM$CKPTDUCV"WX$$T&\2	 ' JJ  w}}!;g>> JJ s   %B:G# !B G# #G?c                L   [         R                  " U5      (       d   eUS;   d   e[        R                  SU SU SU SU S3	5        [	        [
        5      nU R                  R                  5          UnU(       a  U R                  U5      n[        R                  SU 35        U H|  n[        R                  S[        U5       35        Xa:w  a  US   S:w  a  M4  XHS	   :X  a  US
   U;   a  MG  [        R                  S[        U5       35        UR                  US   5        M~     [         R                  " U5      nU(       a  M  US:X  az  U R                  R                  USSSS9n	U	 HX  n[         R                  " XS   5      (       d   e[        R                  S[        U5       35        UR                  US   5        MZ     U R                  R                  5         [!        UR"                  5      S:  a  [%        [&        US9eg! U R                  R                  5         f = f)am  Check, if <principal> can modify <url>, otherwise raise HTTP_LOCKED.

If modifying <url> is prevented by a lock, DAVError(HTTP_LOCKED) is
raised. An embedded DAVErrorCondition contains the conflicting locks.

<url> may be modified by <principal>, if it is not currently locked
directly or indirectly (i.e. by a locked parent).
For depth-infinity operations, <url> also must not have locked children.

It is not enough to check whether a lock is owned by <principal>, but
also the token must be passed with the request. Because <principal> may
run two different applications.

See http://www.webdav.org/specs/rfc4918.html#lock-model
    http://www.webdav.org/specs/rfc4918.html#rfc.section.7.4

TODO: verify assumptions:
- Parent locks WILL NOT be conflicting, if they are depth-0.
- Exclusive child locks WILL be conflicting, even if they are owned by <principal>.

@param url: URL that shall be modified, created, moved, or deleted
@param depth: "0"|"infinity"
@param token_list: list of lock tokens, that the principal submitted in If: header
@param principal: name of the principal requesting a lock

@return: None or raise error
r3   zcheck_write_permission(r   rP   z  checking z
     lock=r'   r5   r%   r!   r   r$   FTrV   r   r   r   N)r   r9   r^   r   r   r   rC   r   r   r,   r   r   rD   rA   r   rv   r   r   r   r   )
rF   rw   r'   rx   r%   r   r   r   r   r   s
             r   check_write_permission"LockManager.check_write_permission  s   8 {{3))))%cU"UG2j\I;aP	

 $$BC

!"	!A 2215	A3/0%DMMJ{4/@.A"BCxDMZ$? ";&77DMZ<W   >{4?P>QR  ((f6 & ''*# !& 
"!\\77edu 8 
 'D,,Sv,????MM$CKPTDUCV"WX$$T&\2	 ' JJ  w}}!;g>> JJ s   2CH B H H#)rC   rD   ) )rR   
__module____qualname____firstlineno____doc__rk   rG   rL   rS   rh   rq   ry   r}   r   rv   r   r   r   r   r   r   ru   r   __static_attributes__r   r   r   r>   r>   w   s    
 #>X2&P!< )- < &* 0#B 38 	 <@ 2!
D
 ;@ !VpNr   r>   )r   r   r   pprintr   wsgidavr   wsgidav.dav_errorr   r   r   r   wsgidav.rw_lockr	   __docformat__get_module_loggerr^   r   r   r   r,   r<   r>   r   r   r   <module>r      sd   
 B      *"

 
 !3
4J0
.*$z zr   