2 * Copyright (c) 1996-2012 by the citadel.org team
4 * This program is open source software. You can redistribute it and/or
5 * modify it under the terms of the GNU General Public License, version 3.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
15 extern IcalKindEnumMap icalproperty_kind_map[];
16 extern IcalMethodEnumMap icalproperty_method_map[];
18 HashList *IcalComponentMap = NULL;
19 CtxType CTX_ICAL = CTX_NONE;
20 CtxType CTX_ICALPROPERTY = CTX_NONE;
21 CtxType CTX_ICALMETHOD = CTX_NONE;
22 CtxType CTX_ICALTIME = CTX_NONE;
23 CtxType CTX_ICALATTENDEE = CTX_NONE;
24 CtxType CTX_ICALCONFLICT = CTX_NONE;
26 void tmplput_ICalItem(StrBuf *Target, WCTemplputParams *TP)
28 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
30 icalproperty_kind Kind;
33 Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY);
34 p = icalcomponent_get_first_property(cal, Kind);
36 str = icalproperty_get_comment (p);
37 StrBufAppendTemplateStr(Target, TP, str, 1);
41 void tmplput_CtxICalProperty(StrBuf *Target, WCTemplputParams *TP)
43 icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY);
46 str = icalproperty_get_comment (p);
47 StrBufAppendTemplateStr(Target, TP, str, 0);
50 int ReleaseIcalSubCtx(StrBuf *Target, WCTemplputParams *TP)
52 WCTemplputParams *TPP = TP;
57 int cond_ICalIsA(StrBuf *Target, WCTemplputParams *TP)
59 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
60 icalcomponent_kind c = GetTemplateTokenNumber(Target, TP, 2, ICAL_NO_COMPONENT);
61 return icalcomponent_isa(cal) == c;
64 int cond_ICalHaveItem(StrBuf *Target, WCTemplputParams *TP)
66 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
68 icalproperty_kind Kind;
70 Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 2, ICAL_ANY_PROPERTY);
71 p = icalcomponent_get_first_property(cal, Kind);
73 WCTemplputParams *DynamicTP;
75 DynamicTP = (WCTemplputParams*) malloc(sizeof(WCTemplputParams));
76 StackDynamicContext (TP,
83 TP->Tokens->Params[1]->lvalue);
90 int ReleaseIcalTimeCtx(StrBuf *Target, WCTemplputParams *TP)
92 WCTemplputParams *TPP = TP;
99 int cond_ICalHaveTimeItem(StrBuf *Target, WCTemplputParams *TP)
101 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
103 icalproperty_kind Kind;
105 Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 2, ICAL_ANY_PROPERTY);
106 p = icalcomponent_get_first_property(cal, Kind);
108 struct icaltimetype *t;
109 struct icaltimetype tt;
110 WCTemplputParams *DynamicTP;
112 DynamicTP = (WCTemplputParams*) malloc(sizeof(WCTemplputParams) +
113 sizeof(struct icaltimetype));
114 t = (struct icaltimetype *) &DynamicTP[1];
115 memset(&tt, 0, sizeof(struct icaltimetype));
118 case ICAL_DTSTART_PROPERTY:
119 tt = icalproperty_get_dtstart(p);
121 case ICAL_DTEND_PROPERTY:
122 tt = icalproperty_get_dtend(p);
127 memcpy(t, &tt, sizeof(struct icaltimetype));
129 StackDynamicContext (TP,
136 TP->Tokens->Params[1]->lvalue);
144 int cond_ICalTimeIsDate(StrBuf *Target, WCTemplputParams *TP)
146 struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
150 void tmplput_ICalTime_Date(StrBuf *Target, WCTemplputParams *TP)
155 struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
157 memset(&d_tm, 0, sizeof d_tm);
158 d_tm.tm_year = t->year - 1900;
159 d_tm.tm_mon = t->month - 1;
160 d_tm.tm_mday = t->day;
161 len = wc_strftime(buf, sizeof(buf), "%x", &d_tm);
162 StrBufAppendBufPlain(Target, buf, len, 0);
164 void tmplput_ICalTime_Time(StrBuf *Target, WCTemplputParams *TP)
168 struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
171 tt = icaltime_as_timet(*t);
172 len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
173 StrBufAppendBufPlain(Target, buf, len, 0);
176 void tmplput_ICalDate(StrBuf *Target, WCTemplputParams *TP)
178 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
180 icalproperty_kind Kind;
181 struct icaltimetype t;
185 Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY);
186 p = icalcomponent_get_first_property(cal, Kind);
189 t = icalproperty_get_dtend(p);
190 tt = icaltime_as_timet(t);
191 len = webcit_fmt_date(buf, 256, tt, DATEFMT_FULL);
192 StrBufAppendBufPlain(Target, buf, len, 0);
196 void tmplput_CtxICalPropertyDate(StrBuf *Target, WCTemplputParams *TP)
198 icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY);
199 struct icaltimetype t;
204 t = icalproperty_get_dtend(p);
205 tt = icaltime_as_timet(t);
206 len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
207 StrBufAppendBufPlain(Target, buf, len, 0);
212 void render_MIME_ICS_TPL(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
214 wc_mime_attachment *Mime = CTX(CTX_MIME_ATACH);
215 icalproperty_method the_method = ICAL_METHOD_NONE;
216 icalproperty *method = NULL;
217 icalcomponent *cal = NULL;
218 icalcomponent *c = NULL;
219 WCTemplputParams SubTP;
220 WCTemplputParams SuperTP;
222 static int divcount = 0;
224 if (StrLength(Mime->Data) == 0) {
227 if (StrLength(Mime->Data) > 0) {
228 cal = icalcomponent_new_from_string(ChrPtr(Mime->Data));
231 StrBufAppendPrintf(Mime->Data, _("There was an error parsing this calendar item."));
232 StrBufAppendPrintf(Mime->Data, "<br>\n");
236 putlbstr("divname", ++divcount);
239 putbstr("cal_partnum", NewStrBufDup(Mime->PartNum));
240 putlbstr("msgnum", Mime->msgnum);
242 memset(&SubTP, 0, sizeof(WCTemplputParams));
243 memset(&SuperTP, 0, sizeof(WCTemplputParams));
245 /*//ical_dezonify(cal); */
247 /* If the component has subcomponents, recurse through them. */
248 c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
249 c = (c != NULL) ? c : cal;
251 method = icalcomponent_get_first_property(cal, ICAL_METHOD_PROPERTY);
252 if (method != NULL) {
253 the_method = icalproperty_get_method(method);
263 StackContext (&SuperTP,
269 FlushStrBuf(Mime->Data);
270 /// DoTemplate(HKEY("ical_attachment_display"), Mime->Data, &SubTP);
271 DoTemplate(HKEY("ical_edit"), Mime->Data, &SubTP);
273 /*/ cal_process_object(Mime->Data, cal, 0, Mime->msgnum, ChrPtr(Mime->PartNum)); */
275 /* Free the memory we obtained from libical's constructor */
276 StrBufPlain(Mime->ContentType, HKEY("text/html"));
277 StrBufAppendPrintf(WC->trailing_javascript,
278 "eventEditAllDay(); \n"
279 "RecurrenceShowHide(); \n"
280 "EnableOrDisableCheckButton(); \n"
283 UnStackContext(&SuperTP);
284 UnStackContext(&SubTP);
285 icalcomponent_free(cal);
287 void CreateIcalComponendKindLookup(void)
291 IcalComponentMap = NewHash (1, NULL);
292 while (icalproperty_kind_map[i].NameLen != 0) {
293 RegisterNS(icalproperty_kind_map[i].Name,
294 icalproperty_kind_map[i].NameLen,
300 Put(IcalComponentMap,
301 icalproperty_kind_map[i].Name,
302 icalproperty_kind_map[i].NameLen,
303 &icalproperty_kind_map[i],
304 reference_free_handler);
314 int cond_ICalIsMethod(StrBuf *Target, WCTemplputParams *TP)
316 icalproperty_method *the_method = (icalproperty_method *) CTX(CTX_ICALMETHOD);
317 icalproperty_method which_method;
319 which_method = GetTemplateTokenNumber(Target, TP, 2, ICAL_METHOD_X);
320 return *the_method == which_method;
324 typedef struct CalendarConflict
327 long existing_msgnum;
328 StrBuf *conflict_event_uid;
329 StrBuf *conflict_event_summary;
331 void DeleteConflict(void *vConflict)
333 CalendarConflict *c = (CalendarConflict *) vConflict;
335 FreeStrBuf(&c->conflict_event_uid);
336 FreeStrBuf(&c->conflict_event_summary);
339 HashList *iterate_FindConflict(StrBuf *Target, WCTemplputParams *TP)
342 HashList *Conflicts = NULL;
343 CalendarConflict *Conflict;
344 wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
346 serv_printf("ICAL conflicts|%ld|%s|", Mime->msgnum, ChrPtr(Mime->PartNum));
349 StrBuf_ServGetln(Line);
350 if (GetServerStatus(Line, NULL) == 1)
352 const char *Pos = NULL;
355 Conflicts = NewHash(1, Flathash);
356 while(!Done && (StrBuf_ServGetln(Line) >= 0) )
357 if ( (StrLength(Line)==3) &&
358 !strcmp(ChrPtr(Line), "000"))
363 Conflict = (CalendarConflict *) malloc(sizeof(CalendarConflict));
364 Conflict->conflict_event_uid = NewStrBufPlain(NULL, StrLength(Line));
365 Conflict->conflict_event_summary = NewStrBufPlain(NULL, StrLength(Line));
367 Conflict->existing_msgnum = StrBufExtractNext_long(Line, &Pos, '|');
368 StrBufSkip_NTokenS(Line, &Pos, '|', 1);
369 StrBufExtract_NextToken(Conflict->conflict_event_uid, Line, &Pos, '|');
370 StrBufExtract_NextToken(Conflict->conflict_event_summary, Line, &Pos, '|');
371 Conflict->is_update = StrBufExtractNext_long(Line, &Pos, '|');
373 Put(Conflicts, IKEY(n), Conflict, DeleteConflict);
379 syslog(LOG_DEBUG, "...done.\n");
385 void tmplput_ConflictEventMsgID(StrBuf *Target, WCTemplputParams *TP)
387 CalendarConflict *C = (CalendarConflict *) CTX(CTX_ICALCONFLICT);
388 char buf[sizeof(long) * 16];
390 snprintf(buf, sizeof(buf), "%ld", C->existing_msgnum);
391 StrBufAppendTemplateStr(Target, TP, buf, 0);
393 void tmplput_ConflictEUID(StrBuf *Target, WCTemplputParams *TP)
395 CalendarConflict *C = (CalendarConflict *) CTX(CTX_ICALCONFLICT);
397 StrBufAppendTemplate(Target, TP, C->conflict_event_uid, 0);
399 void tmplput_ConflictSummary(StrBuf *Target, WCTemplputParams *TP)
401 CalendarConflict *C = (CalendarConflict *) CTX(CTX_ICALCONFLICT);
403 StrBufAppendTemplate(Target, TP, C->conflict_event_summary, 0);
405 int cond_ConflictIsUpdate(StrBuf *Target, WCTemplputParams *TP)
407 CalendarConflict *C = (CalendarConflict *) CTX(CTX_ICALCONFLICT);
411 typedef struct CalAttendee
414 icalparameter_partstat partstat;
417 void DeleteAtt(void *vAtt)
419 CalAttendee *att = (CalAttendee*) vAtt;
420 FreeStrBuf(&att->AttendeeStr);
424 HashList *iterate_get_ical_attendees(StrBuf *Target, WCTemplputParams *TP)
426 icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
427 icalparameter *partstat_param;
430 HashList *Attendees = NULL;
434 /* If the component has attendees, iterate through them. */
435 for (p = icalcomponent_get_first_property(cal, ICAL_ATTENDEE_PROPERTY);
437 p = icalcomponent_get_next_property(cal, ICAL_ATTENDEE_PROPERTY)) {
438 ch = icalproperty_get_attendee(p);
439 if ((ch != NULL) && !strncasecmp(ch, "MAILTO:", 7)) {
440 Att = (CalAttendee*) malloc(sizeof(CalAttendee));
442 /** screen name or email address */
443 Att->AttendeeStr = NewStrBufPlain(ch + 7, -1);
444 StrBufTrim(Att->AttendeeStr);
446 /** participant status */
447 partstat_param = icalproperty_get_first_parameter(
449 ICAL_PARTSTAT_PARAMETER
451 if (partstat_param == NULL) {
452 Att->partstat = ICAL_PARTSTAT_X;
455 Att->partstat = icalparameter_get_partstat(partstat_param);
457 if (Attendees == NULL)
458 Attendees = NewHash(1, Flathash);
459 Put(Attendees, IKEY(n), Att, DeleteAtt);
466 void tmplput_ICalAttendee(StrBuf *Target, WCTemplputParams *TP)
468 CalAttendee *Att = (CalAttendee*) CTX(CTX_ICALATTENDEE);
469 StrBufAppendTemplate(Target, TP, Att->AttendeeStr, 0);
471 int cond_ICalAttendeeState(StrBuf *Target, WCTemplputParams *TP)
473 CalAttendee *Att = (CalAttendee*) CTX(CTX_ICALATTENDEE);
474 icalparameter_partstat which_partstat;
476 which_partstat = GetTemplateTokenNumber(Target, TP, 2, ICAL_PARTSTAT_X);
477 return Att->partstat == which_partstat;
479 /* If the component has subcomponents, recurse through them. * /
480 for (c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
482 c = icalcomponent_get_next_component(cal, ICAL_ANY_COMPONENT)) {
483 // Recursively process subcomponent
484 cal_process_object(Target, c, recursion_level+1, msgnum, cal_partnum);
490 InitModule_ICAL_SUBST
493 RegisterCTX(CTX_ICAL);
495 RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS_TPL, 1, 501);
496 RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS_TPL, 1, 500);
499 CreateIcalComponendKindLookup ();
500 RegisterConditional("COND:ICAL:PROPERTY", 1, cond_ICalHaveItem, CTX_ICAL);
501 RegisterConditional("COND:ICAL:IS:A", 1, cond_ICalIsA, CTX_ICAL);
504 RegisterIterator("ICAL:CONFLICT", 0, NULL, iterate_FindConflict,
505 NULL, DeleteHash, CTX_MIME_ATACH, CTX_ICALCONFLICT, IT_NOFLAG);
506 RegisterNamespace("ICAL:CONFLICT:MSGID", 0, 1, tmplput_ConflictEventMsgID, NULL, CTX_ICALCONFLICT);
507 RegisterNamespace("ICAL:CONFLICT:EUID", 0, 1, tmplput_ConflictEUID, NULL, CTX_ICALCONFLICT);
508 RegisterNamespace("ICAL:CONFLICT:SUMMARY", 0, 1, tmplput_ConflictSummary, NULL, CTX_ICALCONFLICT);
509 RegisterConditional("ICAL:CONFLICT:IS:UPDATE", 0, cond_ConflictIsUpdate, CTX_ICALCONFLICT);
512 RegisterCTX(CTX_ICALATTENDEE);
513 RegisterIterator("ICAL:ATTENDEES", 0, NULL, iterate_get_ical_attendees,
514 NULL, DeleteHash, CTX_ICALATTENDEE, CTX_ICAL, IT_NOFLAG);
515 RegisterNamespace("ICAL:ATTENDEE", 1, 2, tmplput_ICalAttendee, NULL, CTX_ICALATTENDEE);
516 RegisterConditional("COND:ICAL:ATTENDEE", 1, cond_ICalAttendeeState, CTX_ICALATTENDEE);
518 RegisterCTX(CTX_ICALPROPERTY);
519 RegisterNamespace("ICAL:ITEM", 1, 2, tmplput_ICalItem, NULL, CTX_ICAL);
520 RegisterNamespace("ICAL:PROPERTY:STR", 0, 1, tmplput_CtxICalProperty, NULL, CTX_ICALPROPERTY);
521 RegisterNamespace("ICAL:PROPERTY:DATE", 0, 1, tmplput_CtxICalPropertyDate, NULL, CTX_ICALPROPERTY);
523 RegisterCTX(CTX_ICALMETHOD);
524 RegisterConditional("COND:ICAL:METHOD", 1, cond_ICalIsMethod, CTX_ICALMETHOD);
527 RegisterCTX(CTX_ICALTIME);
528 RegisterConditional("COND:ICAL:DT:PROPERTY", 1, cond_ICalHaveTimeItem, CTX_ICAL);
529 RegisterConditional("COND:ICAL:DT:ISDATE", 0, cond_ICalTimeIsDate, CTX_ICALTIME);
530 RegisterNamespace("ICAL:DT:DATE", 0, 1, tmplput_ICalTime_Date, NULL, CTX_ICALTIME);
531 RegisterNamespace("ICAL:DT:DATETIME", 0, 1, tmplput_ICalTime_Time, NULL, CTX_ICALTIME);
535 ServerShutdownModule_ICAL
538 DeleteHash(&IcalComponentMap);