/usr/share/syncevolution/xml/scripting/11calendar.xml is in syncevolution-common 1.2.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | <!-- define script macros for scripts that are used by both vCalendar 1.0 and iCalendar 2.0 -->
<macro name="VCALENDAR_INCOMING_SCRIPT"><![CDATA[
STRING MATCHES[];
STRING CAT,CN,EM;
INTEGER i;
// make sure we have all trailing and leading spaces eliminated
DESCRIPTION=NORMALIZED(DESCRIPTION);
SUMMARY=NORMALIZED(SUMMARY);
// eliminate description that is the same as summary
if (DESCRIPTION==SUMMARY) DESCRIPTION=EMPTY;
// calendar or todo
if (ISEVENT) {
// VEVENT
// - handle duration cases
if (ISDURATION(DURATION)) {
if (DTEND==EMPTY) DTEND = DTSTART + DURATION;
if (DTSTART==EMPTY) DTSTART = DTEND - DURATION;
}
// - detect alldays in vCalendar 1.0 (0:00-0:00 or 23:59 localtime)
i = ALLDAYCOUNT(DTSTART,DTEND,TRUE);
if (ITEMDATATYPE()=="vCalendar10" && i>0) {
// DTSTART and DTEND represent allday event, make them date-only values
// - convert start to user zone (or floating) so it represents midnight
DTSTART = CONVERTTOUSERZONE(DTSTART);
MAKEALLDAY(DTSTART,DTEND,i);
}
else {
// iCalendar 2.0 - only if DTSTART is a date-only value this really is an allday
if (ISDATEONLY(DTSTART)) {
// reshape to make sure we don't have invalid zero-duration alldays (old OCS 9 servers)
MAKEALLDAY(DTSTART,DTEND,i);
}
}
// Make sure that all EXDATE times are in the same timezone as the start
// time. Some servers send them as UTC, which is all fine and well, but
// only if the timezone definition doesn't change. Also, libical does not
// handle such UTC EXDATEs, so let's convert it while the UTC and
// time zone definition (hopefully) are in sync.
if (TIMEZONE(DTSTART) != "UTC" && !ISFLOATING(DTSTART)) {
i = 0;
timestamp exdate;
while (i<SIZE(EXDATES)) {
exdate = EXDATES[i];
if (!ISDATEONLY(exdate) &&
(TIMEZONE(exdate) == "UTC" || ISFLOATING(exdate))) {
// "unfloat" floating time stamps: not sure whether that occcurs
// in practice, but it looks as wrong as UTC EXDATEs
EXDATES[i] = CONVERTTOZONE(exdate,DTSTART,TRUE);
}
i=i+1;
}
}
// If vcalendar1.0, rrule is not secondly, minutely, or hourly, we strip time information
// and only reserve date information
if (ITEMDATATYPE()=="vCalendar10" && RR_FREQ!="h" && RR_FREQ!="m" && RR_FREQ!="s") {
timestamp exdate;
i = 0;
while (i<SIZE(EXDATES)) {
exdate = EXDATES[i];
if (!ISDATEONLY(exdate)) {
EXDATES[i] = DATEONLY(exdate);
}
i=i+1;
}
}
// Transform absolute alarm time back to relative time (mirrors the code in
// VCALENDAR_OUTGOING_SCRIPT, see also BMC #11233). This applies to all
// events, recurring or not, if the "alarmTimeToUTC" workaround is applied.
// With a peer which cannot distinguish between absolute and relative
// alarms we better treat all alarms as relative, because that is presented
// more nicely to the user on the local side.
if (ITEMDATATYPE()=="vCalendar10" &&
ALARM_TIME!=EMPTY &&
!ISDURATION(ALARM_TIME) &&
SESSIONVAR("alarmTimeToUTC")) {
ALARM_TIME = ALARM_TIME - DTSTART;
}
// - shape attendees (and make sure ATTENDEES[] is assigned even for empty email addresses)
i=0;
while(i<SIZE(ATTENDEES) || i<SIZE(ATTENDEE_CNS)) {
PARSEEMAILSPEC(ATTENDEES[i], CN, EM);
ATTENDEES[i] = EM; // pure email address
// in case we have no specific common name, use the one extracted from the email
// This catches the vCalendar 1.0 case and eventually ill-formed iCalendar 2.0 as well
if (ATTENDEE_CNS[i]==EMPTY)
ATTENDEE_CNS[i]=CN;
// default participation status to needs-action
if (ATTENDEE_PARTSTATS[i]==EMPTY)
ATTENDEE_PARTSTATS[i]=1; // 1=needs action
i=i+1;
}
// - shape organizer
PARSEEMAILSPEC(ORGANIZER, CN, EM);
ORGANIZER = EM; // pure email address
if (ORGANIZER_CN==EMPTY)
ORGANIZER_CN=CN;
}
else {
// VTODO
// - make sure we have at least a summary
if (SUMMARY==EMPTY) SUMMARY=DESCRIPTION; // use description if we don't have a summary
if (SUMMARY==EMPTY) SUMMARY="unnamed"; // set dummy summary if we still don't have one
// due shaping for non-iCalendar 2.0
if (ITEMDATATYPE()=="vCalendar10" && ALLDAYCOUNT(DUE,DUE,TRUE,TRUE)>0) {
DUE = DATEONLY(DUE);
}
if (ITEMDATATYPE()=="vCalendar10") {
$VCALENDAR_10TO20_PRIORITY_CONVERSION;
}
}
// a workaround for funambol: adding 'action' for 'alarm'
// if item data type is vCalendar1.0, also add 'action' for 'alarm'.
// This is a workaround for Mobical.net, which uses vCalendar1.0.
if (ALARM_TIME!=EMPTY && ALARM_ACTION==EMPTY) {
ALARM_ACTION = "DISPLAY";
}
]]></macro>
<macro name="VCALENDAR_OUTGOING_SCRIPT"><![CDATA[
// set UTC time of generation for iCalendar 2.0 DTSTAMP
DGENERATED = NOW();
// make sure we have all trailing and leading spaces eliminated
DESCRIPTION=NORMALIZED(DESCRIPTION);
SUMMARY=NORMALIZED(SUMMARY);
if (ISEVENT) {
// VEVENT
// - combine attendee email address and common name into single string for vCalendar 1.0
if (ITEMDATATYPE()=="vCalendar10") {
i=0;
while(i<SIZE(ATTENDEES)) {
ATTENDEES[i] = MAKEEMAILSPEC(ATTENDEE_CNS[i], ATTENDEES[i]);
i=i+1;
}
ORGANIZER = MAKEEMAILSPEC(ORGANIZER_CN, ORGANIZER);
}
}
else {
// VTODO
// interal representation is iCalendar20
if (ITEMDATATYPE()=="vCalendar10") {
$VCALENDAR_20TO10_PRIORITY_CONVERSION;
}
}
// make sure we have at least a summary
if (SUMMARY==EMPTY) SUMMARY=SUBSTR(DESCRIPTION,0,32); // derive from description
if (SUMMARY==EMPTY) SUMMARY="unnamed"; // in case description is empty as well
// make sure that we have a DESCRIPTION, because some peers only support that;
// can be avoided for peers where we are certain (from CtCaps) that they can
// receive the text as part of the summary
if (ISAVAILABLE(SUMMARY)!=TRUE && DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY;
// do NOT send duration (some servers crash when doing so)
DURATION = UNASSIGNED;
// shape alarm
if (ALARM_TIME!=EMPTY) {
if (ITEMDATATYPE()=="iCalendar20") {
if (ALARM_ACTION==EMPTY) ALARM_ACTION = "AUDIO";
}
else {
if (ALARM_MSG==EMPTY) ALARM_MSG="alarm";
}
}
// for 'ALARM_TIME', convert duration time to UTC time
// This workaround is for Mobical.net which can't understand duration time.
// Also used with phones. The interpretation at least by Nokia
// is that the absolute alarm time repeats together with the
// event (BMC #11233). VCALENDAR_INCOMING_SCRIPT has the
// corresponding transformation back (important for recurring events).
if (SESSIONVAR("alarmTimeToUTC") && ITEMDATATYPE()=="vCalendar10"
&& ALARM_TIME!=EMPTY && ISDURATION(ALARM_TIME)) {
TIMESTAMP ts;
if (ALARM_REL==2)
ts = DTEND; // relative to end
else {
if (ISEVENT)
ts = DTSTART; // relative to start for events
else
ts = DUE; // relative to due for todos
}
ALARM_TIME = CONVERTTOUSERZONE(POINTINTIME(ts), TRUE) + ALARM_TIME;
ALARM_TIME = CONVERTTOZONE(ALARM_TIME, "UTC");
}
]]></macro>
<!-- Uses the UID/RECURRENCE-ID fields as the only criteria for
comparing calendar data if the VCALENDAR_COMPARE_UID session
variable is true, else does a normal comparison of the
fields. That comparison is based on the datatype definition
and ignores UID because it is not trusted to be
preserved and/or implemented by peers.
In case of a UID match, the DMODIFIED fields are compared
to determine the older item.
-->
<macro name="VCALENDAR_COMPARE_SCRIPT"><![CDATA[
INTEGER RES;
if (COMPARISONMODE() != "age" && SESSIONVAR("VCALENDAR_COMPARE_UID") ) {
if (TARGET.UID == REFERENCE.UID &&
TARGET.ORIGSTART == REFERENCE.ORIGSTART) {
RES = 0;
} else {
RES = -999;
}
} else {
RES = COMPAREFIELDS();
}
return RES;
]]></macro>
|