
    iJ3              
       $   d 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	 ddl
mZmZ ddlmZ dd	lmZ d
dlmZmZmZmZ  ej        e          Z	 d$dededefdZ	 	 d%dedededee         fdZ	 	 d%dedededee         fdZ	 	 d%dedededefdZ 	 	 d%dedededee         fdZ!de"de"fdZ#de	de	ee	         z  fdZ$de	de%e"ee	         e"dz  f         fdZ&dee	         de'e"ef         fdZ(de	defd Z)d!e"dz  ddfd"Z*d!e"dz  defd#Z+dS )&z
Pure functions for parsing CalDAV XML responses.

All functions in this module are pure - they take XML bytes in and return
structured data out, with no side effects or I/O.
    N)Any)unquote)etree)_Element)cdavdav)error)URL   )CalendarQueryResultMultistatusResponsePropfindResultSyncCollectionResultFbody	huge_treereturnc                    t          j        |          }t          j        | |          }g }d}t          |          }|D ]}|j        t
          j        j        k    r|j        }$|j        t
          j        j        k    r?t          |          \  }}	}
t          |	          }|
rt          |
          nd}|                    t          |||                     t          ||          S )aX  
    Parse a 207 Multi-Status response body.

    Args:
        body: Raw XML response bytes
        huge_tree: Allow parsing very large XML documents

    Returns:
        Structured MultistatusResponse with parsed results

    Raises:
        XMLSyntaxError: If body is not valid XML
        ResponseError: If response indicates an error
    r   N   )href
propertiesstatus)	responses
sync_token)r   	XMLParser
fromstring_strip_to_multistatustagr   	SyncTokentextResponse_parse_response_element_extract_properties_status_to_codeappendr   r   )r   r   parsertreer   r   response_elementselemr   	propstatsr   r   status_codes                V/root/projects/butler/venv/lib/python3.11/site-packages/caldav/protocol/xml_parsers.py_parse_multistatusr-      s   $ _y111FD&))D&(I!J .d33! 
 
8s}(((J8s|'''"9$"?"?i(33
17@of---S%"  	
 	
 	
 	
 zJJJJ       r+   c                     |dk    rg S |dvrt          j        d|           | sg S t          | |          }|j        S )a  
    Parse a PROPFIND response.

    Args:
        body: Raw XML response bytes
        status_code: HTTP status code of the response
        huge_tree: Allow parsing very large XML documents

    Returns:
        List of PropfindResult with properties for each resource
      r   r/   zPROPFIND failed with status r   )r	   ResponseErrorr-   r   )r   r+   r   results       r,   _parse_propfind_responser5   J   sa      c	*$$!"N"N"NOOO 		:::Fr.   c           	         |dvrt          j        d|           | sg S t          j        |          }t          j        | |          }g }t          |          }|D ]}|j        t          j        j        k    rt          |          \  }}	}
|
rt          |
          nd}d}d}|	D ]q}|                    t          j        j                  }|)|D ]E}|j        t          j        j        k    r|j        }$|j        t          j        j        k    r|j        }Fr|                    t%          ||||                     |S )a  
    Parse a calendar-query REPORT response.

    Args:
        body: Raw XML response bytes
        status_code: HTTP status code of the response
        huge_tree: Allow parsing very large XML documents

    Returns:
        List of CalendarQueryResult with calendar data
    r2   zREPORT failed with status r   r   Nr   etagcalendar_datar   )r	   r3   r   r   r   r   r   r   r!   r"   r$   findPropr   CalendarDatar    GetEtagr%   r   )r   r+   r   r&   r'   resultsr(   r)   r   r*   r   status_code_elemr9   r8   propstatpropchilds                    r,   _parse_calendar_query_responserC   g   s     *$$!"L{"L"LMMM 	_y111FD&))D)+G-d33! 
 
8s|'''"9$"?"?i6<E?6222#$( " 		& 		&H==..D| & &9 1 555$)JMMY#+/11 :D	& 	+'	  	
 	
 	
 	
 Nr.   c           	      B   |dvrt          j        d|           | st                      S t          j        |          }t          j        | |          }g }g }d}t          |          }|D ] }	|	j        t          j	        j        k    r|	j
        }%|	j        t          j        j        k    r@t          |	          \  }
}}|rt          |          nd}|dk    r|                    |
           d}d}|D ]q}|                    t          j        j                  }|)|D ]E}|j        t"          j        j        k    r|j
        }$|j        t          j        j        k    r|j
        }Fr|                    t)          |
|||                     "t          |||          S )	a3  
    Parse a sync-collection REPORT response.

    Args:
        body: Raw XML response bytes
        status_code: HTTP status code of the response
        huge_tree: Allow parsing very large XML documents

    Returns:
        SyncCollectionResult with changed items, deleted hrefs, and new sync token
    r2   z#sync-collection failed with status r   Nr   r1   r7   )changeddeletedr   )r	   r3   r   r   r   r   r   r   r   r   r    r!   r"   r$   r%   r:   r;   r   r<   r=   r   )r   r+   r   r&   r'   rE   rF   r   r(   r)   r   r*   r   r?   r9   r8   r@   rA   rB   s                      r,   _parse_sync_collection_responserG      s     *$$!"U"U"UVVV &#%%%_y111FD&))D)+GG!J-d33! %
 %
8s}(((J8s|'''"9$"?"?i6<E?6222# s""NN4   $(! 		& 		&H==..D| & &9 1 555$)JMMY#+/11 :D	& 	+'	  	
 	
 	
 	
     r.   c                 $    t          | ||          S )ah  
    Parse a calendar-multiget REPORT response.

    This is the same format as calendar-query, so we delegate to that parser.

    Args:
        body: Raw XML response bytes
        status_code: HTTP status code of the response
        huge_tree: Allow parsing very large XML documents

    Returns:
        List of CalendarQueryResult with calendar data
    )rC   )r   r+   r   s      r,   !_parse_calendar_multiget_responserI      s    $ *$YGGGr.   r    c                     d| v r|                      dd          } t          |           }d|v r!t          t          |          j                  }|S )u   
    Normalize an href string from a DAV response element.

    Handles the Confluence double-encoding bug (%2540 → %40) and converts
    absolute URLs to path-only strings so callers always work with paths.
    z%2540z%40:)replacer   r
   path)r    r   s     r,   _normalize_hrefrN   
  sP     $||GU++4==D d{{s4yy~&&Kr.   r'   c                     | j         dk    r;t          |           dk    r(| d         j         t          j        j         k    r| d         S | j         t          j        j         k    r| S | gS )aN  
    Strip outer elements to get to the multistatus content.

    The general format is:
        <xml><multistatus>
            <response>...</response>
            <response>...</response>
        </multistatus></xml>

    But sometimes multistatus and/or xml element is missing.
    Returns the element(s) containing responses.
    xmlr   )r   lenr   MultiStatus)r'   s    r,   r   r     s[     x5SYY]]tAw{co>Q/Q/QAwx3?&&&6Mr.   responsec                 H   d}d}g }| D ]}|j         t          j        j         k    r|j        }t	          |           3|j         t          j        j         k    rt          |j        pd          }d|j         t          j        j         k    r|                    |           |pd||fS )z{
    Parse a single DAV:response element.

    Returns:
        Tuple of (href, propstat elements list, status string)
    N )	r   r   Statusr    _validate_statusHrefrN   PropStatr%   )rS   r   r   r*   r)   s        r,   r"   r"   1  s     FD "I # #8sz~%%YFV$$$$X%%"49?33DDX)))T"""JB	6**r.   r*   c                 H   i }| D ]}|                     t          j        j                  }||j        r
d|j        v r9|                     t          j        j                  }|`|D ]9}|j        }t          |          dk    r|j        ||<   't          |          ||<   :|S )z
    Extract properties from propstat elements into a dict.

    Args:
        propstats: List of propstat elements

    Returns:
        Dict mapping property tag to value (text or element)
    N 404 r   )r:   r   rV   r   r    r;   rQ   _element_to_value)r*   r   r@   status_elemrA   rB   r   s          r,   r#   r#   J  s     "$J ; ;mmCJN33"{'7"+*** }}SX\**<  	; 	;E)C5zzQ"'*
3 #4E":":
3	; r.   r)   c                 |   t          |           dk    r| j        S | j        }|t          j        j        k    rd | D             S |t          j        j        k    rd | D             S |t          j        j        k    r)d | D             }t          |          dk    r|d         n|S |t          j        j        k    rd | D             S |t          j	        j        k    r1| D ],}|j        t          j
        j        k    r|j        r	|j        c S -dS g }| D ]}|j        r|                    |j                   $|                    d          r)|                    |                    d                     bt          |          dk    r|                    |j                   t          |          dk    r|d         S |r|S | S )	z
    Convert an XML element to a Python value.

    For simple elements, returns text content.
    For complex elements with children, returns dict or list.
    Handles special CalDAV elements like supported-calendar-component-set.
    r   c                 b    g | ],}|                     d           |                     d           -S )name)get.0rB   s     r,   
<listcomp>z%_element_to_value.<locals>.<listcomp>  s5    IIIeuyy7H7HI		&!!IIIr.   c                 ^    g | ]*}|j         t          j        j         k    |j        #|j        +S  r   r   rX   r    rb   s     r,   rd   z%_element_to_value.<locals>.<listcomp>  s1    YYYu	SX\0I0Iej0I
0I0I0Ir.   c                 ^    g | ]*}|j         t          j        j         k    |j        #|j        +S rf   rg   rb   s     r,   rd   z%_element_to_value.<locals>.<listcomp>  s1    ZZZchl1J1Juz1J1J1J1Jr.   r   c                     g | ]	}|j         
S rf   )r   rb   s     r,   rd   z%_element_to_value.<locals>.<listcomp>  s    ,,,e	,,,r.   Nr`   )rQ   r    r   r   SupportedCalendarComponentSetCalendarUserAddressSetCalendarHomeSetr   ResourceTypeCurrentUserPrincipalrX   r%   ra   )r)   r   hrefsrB   children_textss        r,   r\   r\   p  s    4yyA~~y (C d0444IItIIII d)---YYYYYY d"&&&ZZZZZu::??uQxx5 c""",,t,,,, c&*** 	" 	"EyCHL((UZ(z!!!t N - -: 	-!!%*----YYv 	-!!%))F"3"34444ZZ1__!!%),,,
>aa  	  Kr.   r   c                 r      dS d}t           fd|D                       st          j                   dS )z
    Validate a status string like "HTTP/1.1 404 Not Found".

    200, 201, 207, and 404 are considered acceptable statuses.

    Args:
        status: Status string from response

    Raises:
        ResponseError: If status indicates an error
    N)z 200 z 201 z 207 r[   c              3       K   | ]}|v V  	d S )Nrf   )rc   coder   s     r,   	<genexpr>z#_validate_status.<locals>.<genexpr>  s'      55$tv~555555r.   )anyr	   r3   )r   
acceptables   ` r,   rW   rW     sT     ~5J5555*55555 *!&)))* *r.   c                     | sdS |                                  }t          |          dk    r&	 t          |d                   S # t          $ r Y nw xY wdS )z
    Extract status code from status string like "HTTP/1.1 200 OK".

    Args:
        status: Status string

    Returns:
        Integer status code (defaults to 200 if parsing fails)
    r      r   )splitrQ   int
ValueError)r   partss     r,   r$   r$     si      sLLNNE
5zzQ	uQx==  	 	 	D	 3s   A 
AA)F)r/   F),__doc__loggingtypingr   urllib.parser   lxmlr   
lxml.etreer   caldav.elementsr   r   
caldav.libr	   caldav.lib.urlr
   typesr   r   r   r   	getLogger__name__logbytesboolr-   rz   listr5   rC   rG   rI   strrN   r   tupler"   dictr#   r\   rW   r$   rf   r.   r,   <module>r      s{                                   % % % % % % % %             a a a a a a a a a a a ag!!
 /K /K
/K/K /K /K /K /Kh  
  
.	   > ; ;
;; ; 

	; ; ; ;@ J J
JJ J 	J J J J^ H H
HH H 

	H H H H0# #    & XX-F    (++
3Xd
*++ + + +2#4> #d38n # # # #L8H 8 8 8 8 8v*S4Z *D * * * *(C$J 3      r.   