
    i''                     l    d dl Z d dlZd dlZd dlZd dlZd dlmZ d ad Z G d d          Z	d	dZ
d ZdS )
    N)to_normal_strc                 *   t          |           } |                     d          s| dz   } t          j        dd|           }t          j        dd|          }t          j        dd|          }t          j        dd	|          }d
|vrbd|v sJ t          j                            t          j        j                                      d          }t          j        dd
| d|          }d	                    t          t                      |                                                    d                              dz   }|| k    rt          dz  ad }t          j        d          } |t                    r|j        }n|j        }ddddt           dg}	 ddl}t)          |                    |                     d          |                    d          d	                    }	n#  d| d|g}	Y nxY w |d	                    ||	z                        |S )a  This function receives some ical as it's given from the server, checks for
    breakages with the standard, and attempts to fix up known issues:

    1) COMPLETED MUST be a datetime in UTC according to the RFC, but sometimes
    a date is given. (Google Calendar?) SOGo!  Ref https://github.com/home-assistant/core/issues/106671


    2) The RFC does not specify any range restrictions on the dates,
    but clearly it doesn't make sense with a CREATED-timestamp that is
    centuries or decades before RFC2445 was published in 1998.
    Apparently some calendar servers generate nonsensical CREATED
    timestamps while other calendar servers can't handle CREATED
    timestamps prior to 1970.  Probably it would make more sense to
    drop the CREATED line completely rather than moving it from the
    end of year 0AD to the beginning of year 1970. (Google Calendar)

    3) iCloud apparently duplicates the DTSTAMP property sometimes -
    keep the first DTSTAMP encountered (arguably the DTSTAMP with earliest value
    should be kept).

    4) ref https://github.com/python-caldav/caldav/issues/37,
    X-APPLE-STRUCTURED-EVENT attribute sometimes comes with trailing
    white space.  I've decided to remove all trailing spaces, since
    they seem to cause a traceback with vobject and those lines are
    simply ignored by icalendar.

    5) Zimbra can apparently create events with both dtstart, dtend
    and duration set - which is forbidden according to the RFC.  We
    should probably verify that the data is consistent.  As for now,
    we'll just drop DURATION or DTEND (whatever comes last).

    6) On FOSSDEM I was presented with icalendar data missing the
    DTSTAMP field.  This is mandatory according to the RFC.

    All logic here is done with on the ical string, and not on
    icalendar objects.  There are two reasons for it, originally
    optimization (not having to parse the icalendar data and create an
    object, if it's to be tossed away again shortly afterwards), but
    also because broken icalendar data may cause the instantiation of
    an icalendar object to break.

    TODO: this should probably be moved out from the library.
    
z!COMPLETED(?:;VALUE=DATE)?:(\d+)\szCOMPLETED:\g<1>T120000ZzCREATED:00001231T000000ZzCREATED:19700101T000000Zz\\+('\")z\1z *$ z	
DTSTAMP:z
ENDtzz%Y%m%dT%H%M%SZz(
END:(VTODO|VEVENT|VJOURNAL))   c                     | | dz
  z   S )Nr	    )ns    J/root/projects/butler/venv/lib/python3.11/site-packages/caldav/lib/vcal.py<lambda>zfix.<locals>.<lambda>m   s    a!e$5     caldavz4Ical data was modified to avoid compatibility issuesz4(Your calendar server breaks the icalendar standard)zFThis is probably harmless, particularly if not editing events or tasksz(error count: z - this error is ratelimited)r   N)linetermz
Original: z
Modified: )r   endswithresubdatetimenowtimezoneutcstrftimejoinfilterLineFilterDiscardingDuplicatesstripsplitfixup_error_loggingslogging	getLoggerwarningdebugdiffliblistunified_diff)
eventfixeddtstampfixed2is_power_of_twologgerloglog_messager$   diffs
             r   fixr0      s3   X %  E>>$  F79SUZ[[E F-/I5QQEF;u--E F5"e$$E 5  %#''8+<+@'AAJJK[\\8:Sw:S:S:SUZ[[ YYv<>>@S@STX@Y@YZZ[[^bbF
 	!55"8,,?/00 	.CC,C CBTP1PPP	
	?NNN,,U[[->->T@R@R]_,``aaDD	? %v>DDDDIIkD())***Ms   AG% %G/c                        e Zd ZdZddZd ZdS )r   zNeeds to be a class because it keeps track of whether a certain
    group of date line was already encountered within a vobject.
    This must be called line by line in order on the complete text, at
    least comprising the complete vobject.
    returnNc                 "    d| _         d| _        d S Nr   )stampedended)selfs    r   __init__z'LineFilterDiscardingDuplicates.__init__   s    


r   c                    |                     d          rd| _        d| _        n]t          j        d|          r| j        rdS | xj        dz  c_        n.t          j        d|          r| j        rdS | xj        dz  c_        dS )NzBEGIN:Vr   z(DURATION|DTEND|DUE)[:;]Fr	   zDTSTAMP[:;]T)
startswithr5   r6   r   match)r7   lines     r   __call__z'LineFilterDiscardingDuplicates.__call__   s    ??9%% 	DLDJJX0$77 	z uJJ!OJJJXmT** 	| uLLALLtr   )r2   N)__name__
__module____qualname____doc__r8   r=   r   r   r   r   r      sA                r   r   en_DKc           	      <   t          |           } d|v r|                    d          |d<   | r t          j        d| t          j                  st          j                    }|d}	 t          j        j        |                     }n7#  t          j        j        	                                |                     }Y nxY w|
                    |           |                    d          sd| pdvr|d	k    rd
|d<   n||                                                     d          s'dt          |                                           z   dz   } t
          j                            |           }|j        d         }d} |                    d          s|                    dd|z              |                    d          s|                    dd           |                    d          sX|                    d          sC|                    dt"          j                            t"          j        j                             |                    d          s<|                    d          s'|                    dt+          j                               i }|D ]
}||         t/          ||         t"          j                  r:||         j        s-||                             t"          j        j                  ||<   |dv rF||         D ]<}|                    dt5          |          d|                                id           =|                    d          r||         ||dd         <   |                    |d           |                    |||                    |rt9          ||           t          |                                          }	| rL|                                 r8t          j        d|                                 dz   |	t          j        d           }	|	S )!a  Creates some icalendar based on properties given as parameters.
    It basically creates an icalendar object with all the boilerplate,
    some sensible defaults, the properties given and returns it as a
    string.

    TODO: timezones not supported so far
    class_classz^BEGIN:VNVEVENTstatusz
STATUS:r   VTODOzNEEDS-ACTIONzBEGIN:VCALENDARzBEGIN:VCALENDAR
z
END:VCALENDAR
r   prodidz-//python-caldav//caldav//versionz2.0r)   r   uid)childparentz
related-toreltypeT)
parametersencodealarm_   z^END:Vz
END:Vr	   )flagscount)r   popr   search	MULTILINE	icalendarCalendarcalcomponent_factoryComponentFactoryadd_componentgetr   r:   	from_icalsubcomponentsaddr   r   r   r   uuiduuid1
isinstancetzinfo
astimezonestrupper	add_alarmto_icalr   )
ical_fragmentobjtypelanguagepropsmy_instance	componentalarmpropvaluerets
             r   create_icalru      s    "-00M58,,g 	*mR\ R R (**?G	V!7@BBII	V!7HHJJ7SUUIII!!),,,
 		(##	-M$7R887"",E(O ""$$//0ABB 	#mM4G4G4I4I&J&JJM``   (22=AA-a0	 ??8$$ K">"IJJJ??9%% *	5)))==## REIIi,@,@ Ri!2!6!6(:K:O!6!P!PQQQ== +		%(8(8 +eTZ\\***E 1 1;"%+x'899 L%+BT L#Dk44X5F5JKKd***"4[  EMM$E

$-tzz||#<#	 "     ** 1"'+d122h dD)))dE$K000 &+u%%%
++--
.
.C 
,,.. 
f!!I-,
 
 
 Js   &B 2B9c                     t          j                    }|D ]}|                    |||                    | j        d                             |           | S r4   )rX   Alarmra   r`   r]   )icalrq   iarr   s       r   ri   ri      sZ    			B " "
tU4[!!!!q''+++Kr   )NNrB   )r   r    r   rb   rX   caldav.lib.python_utilitiesr   r   r0   r   ru   ri   r   r   r   <module>r{      s      				      5 5 5 5 5 5  $f f fR       <Q Q Q Qh    r   