ffacf41f471a3016e5dd818b45d14cdbd24614c0
[citadel.git] / webcit / ical_subst.c
1 /*
2  * Copyright (c) 1996-2012 by the citadel.org team
3  *
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.
6  *
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.
11  */
12
13 #include "webcit.h"
14
15 extern IcalKindEnumMap icalproperty_kind_map[];
16 extern IcalMethodEnumMap icalproperty_method_map[];
17
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 #if 0
25 void SortPregetMatter(HashList *Cals)
26 {
27         disp_cal *Cal;
28         void *vCal;
29         const char *Key;
30         long KLen;
31         IcalEnumMap *SortMap[10];
32         IcalEnumMap *Map;
33         void *vSort;
34         const char *Next = NULL;
35         const StrBuf *SortVector;
36         StrBuf *SortBy;
37         int i = 0;
38         HashPos *It;
39
40         SortVector = SBSTR("ICALSortVec");
41         if (SortVector == NULL)
42                 return;
43
44         for (i = 0; i < 10; i++) SortMap[i] = NULL;
45         SortBy = NewStrBuf();
46         while (StrBufExtract_NextToken(SortBy, SortVector, &Next, ':') > 0) {
47                 GetHash(IcalComponentMap, SKEY(SortBy), &vSort);
48                 Map = (IcalEnumMap*) vSort;
49                 SortMap[i] = Map;
50                 i++;
51                 if (i > 9)
52                         break;
53         }
54
55         if (i == 0)
56                 return;
57
58         switch (SortMap[i - 1]->map) {
59                 /*      case */
60
61         default:
62                 break;
63         }
64
65         It = GetNewHashPos(Cals, 0);
66         while (GetNextHashPos(Cals, It, &KLen, &Key, &vCal)) {
67                 i = 0;
68                 Cal = (disp_cal*) vCal;
69                 Cal->Status = icalcomponent_get_status(Cal->cal);
70                 Cal->SortBy = Cal->cal;
71                 
72
73                 while ((SortMap[i] != NULL) && 
74                        (Cal->SortBy != NULL)) 
75                 {
76                         /****Cal->SortBy = icalcomponent_get_first_property(Cal->SortBy, SortMap[i++]->map); */
77                 }
78         }
79 }
80 #endif
81
82
83 void tmplput_ICalItem(StrBuf *Target, WCTemplputParams *TP)
84 {
85         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
86         icalproperty *p;
87         icalproperty_kind Kind;
88         const char *str;
89
90         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY);
91         p = icalcomponent_get_first_property(cal, Kind);
92         if (p != NULL) {
93                 str = icalproperty_get_comment (p);
94                 StrBufAppendTemplateStr(Target, TP, str, 1);
95         }
96 }
97
98 void tmplput_CtxICalProperty(StrBuf *Target, WCTemplputParams *TP)
99 {
100         icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY);
101         const char *str;
102
103         str = icalproperty_get_comment (p);
104         StrBufAppendTemplateStr(Target, TP, str, 0);
105 }
106
107 int ReleaseIcalSubCtx(StrBuf *Target, WCTemplputParams *TP)
108 {
109         WCTemplputParams *TPP = TP;
110         UnStackContext(TP);
111         free(TPP);
112         return 0;
113 }
114 int cond_ICalIsA(StrBuf *Target, WCTemplputParams *TP)
115 {
116         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
117         icalcomponent_kind c = GetTemplateTokenNumber(Target, TP, 2, ICAL_NO_COMPONENT);
118         return icalcomponent_isa(cal) == c;
119 }
120
121 int cond_ICalHaveItem(StrBuf *Target, WCTemplputParams *TP)
122 {
123         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
124         icalproperty *p;
125         icalproperty_kind Kind;
126
127         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 2, ICAL_ANY_PROPERTY);
128         p = icalcomponent_get_first_property(cal, Kind);
129         if (p != NULL) {
130                 WCTemplputParams *DynamicTP;
131         
132                 DynamicTP = (WCTemplputParams*) malloc(sizeof(WCTemplputParams));
133                 StackDynamicContext (TP, 
134                                      DynamicTP, 
135                                      p,
136                                      CTX_ICALPROPERTY,
137                                      0,
138                                      TP->Tokens,
139                                      ReleaseIcalSubCtx,
140                                      TP->Tokens->Params[1]->lvalue);
141
142                 return 1;
143         }
144         return 0;
145 }
146
147 int ReleaseIcalTimeCtx(StrBuf *Target, WCTemplputParams *TP)
148 {
149         WCTemplputParams *TPP = TP;
150
151         UnStackContext(TP);
152         free(TPP);
153         return 0;
154 }
155
156 int cond_ICalHaveTimeItem(StrBuf *Target, WCTemplputParams *TP)
157 {
158         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
159         icalproperty *p;
160         icalproperty_kind Kind;
161
162         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 2, ICAL_ANY_PROPERTY);
163         p = icalcomponent_get_first_property(cal, Kind);
164         if (p != NULL) {
165                 struct icaltimetype *t;
166                 struct icaltimetype tt;
167                 WCTemplputParams *DynamicTP;
168
169                 DynamicTP = (WCTemplputParams*) malloc(sizeof(WCTemplputParams) + 
170                                                        sizeof(struct icaltimetype));
171                 t = (struct icaltimetype *) &DynamicTP[1];
172                 memset(&tt, 0, sizeof(struct icaltimetype));
173                 switch (Kind)
174                 {
175                 case ICAL_DTSTART_PROPERTY:
176                         tt = icalproperty_get_dtstart(p);
177                         break;
178                 case ICAL_DTEND_PROPERTY:
179                         tt = icalproperty_get_dtend(p);
180                         break;
181                 default:
182                         break;
183                 }
184                 memcpy(t, &tt, sizeof(struct icaltimetype));
185
186                 StackDynamicContext (TP, 
187                                      DynamicTP, 
188                                      t,
189                                      CTX_ICALTIME,
190                                      0,
191                                      TP->Tokens,
192                                      ReleaseIcalTimeCtx,
193                                      TP->Tokens->Params[1]->lvalue);
194
195                 return 1;
196         }
197         return 0;
198 }
199
200
201 int cond_ICalTimeIsDate(StrBuf *Target, WCTemplputParams *TP)
202 {
203         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
204         return t->is_date;
205 }
206
207 void tmplput_ICalTime_Date(StrBuf *Target, WCTemplputParams *TP)
208 {
209         struct tm d_tm;
210         long len;
211         char buf[256];
212         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
213
214         memset(&d_tm, 0, sizeof d_tm);
215         d_tm.tm_year = t->year - 1900;
216         d_tm.tm_mon = t->month - 1;
217         d_tm.tm_mday = t->day;
218         len = wc_strftime(buf, sizeof(buf), "%x", &d_tm);
219         StrBufAppendBufPlain(Target, buf, len, 0);
220 }
221 void tmplput_ICalTime_Time(StrBuf *Target, WCTemplputParams *TP)
222 {
223         long len;
224         char buf[256];
225         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
226         time_t tt;
227
228         tt = icaltime_as_timet(*t);
229         len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
230         StrBufAppendBufPlain(Target, buf, len, 0);
231 }
232
233 void tmplput_ICalDate(StrBuf *Target, WCTemplputParams *TP)
234 {
235         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
236         icalproperty *p;
237         icalproperty_kind Kind;
238         struct icaltimetype t;
239         time_t tt;
240         char buf[256];
241
242         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY);
243         p = icalcomponent_get_first_property(cal, Kind);
244         if (p != NULL) {
245                 long len;
246                 t = icalproperty_get_dtend(p);
247                 tt = icaltime_as_timet(t);
248                 len = webcit_fmt_date(buf, 256, tt, DATEFMT_FULL);
249                 StrBufAppendBufPlain(Target, buf, len, 0);
250         }
251 }
252
253 void tmplput_CtxICalPropertyDate(StrBuf *Target, WCTemplputParams *TP)
254 {
255         icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY);
256         struct icaltimetype t;
257         time_t tt;
258         char buf[256];
259
260         long len;
261         t = icalproperty_get_dtend(p);
262         tt = icaltime_as_timet(t);
263         len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
264         StrBufAppendBufPlain(Target, buf, len, 0);
265 }
266
267
268
269 void render_MIME_ICS_TPL(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
270 {
271         wc_mime_attachment *Mime = CTX(CTX_MIME_ATACH);
272         icalproperty_method the_method = ICAL_METHOD_NONE;
273         icalproperty *method = NULL;
274         icalcomponent *cal;
275         icalcomponent *c;
276         WCTemplputParams SubTP;
277         WCTemplputParams SuperTP;
278
279         static int divcount = 0;
280
281         if (StrLength(Mime->Data) == 0) {
282                 MimeLoadData(Mime);
283         }
284         if (StrLength(Mime->Data) > 0) {
285                 cal = icalcomponent_new_from_string(ChrPtr(Mime->Data));
286         }
287         if (cal == NULL) {
288                 StrBufAppendPrintf(Mime->Data, _("There was an error parsing this calendar item."));
289                 StrBufAppendPrintf(Mime->Data, "<br>\n");
290                 return;
291         }
292
293         putlbstr("divname",  ++divcount);
294
295
296         putbstr("cal_partnum", NewStrBufDup(Mime->PartNum));
297         putlbstr("msgnum", Mime->msgnum);
298
299         memset(&SubTP, 0, sizeof(WCTemplputParams));
300         memset(&SuperTP, 0, sizeof(WCTemplputParams));
301
302         /*//ical_dezonify(cal); */
303
304         /* If the component has subcomponents, recurse through them. */
305         c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
306         c = (c != NULL) ? c : cal;
307
308         method = icalcomponent_get_first_property(cal, ICAL_METHOD_PROPERTY);
309         if (method != NULL) {
310                 the_method = icalproperty_get_method(method);
311         }
312
313         StackContext (TP,
314                       &SuperTP,
315                       &the_method,
316                       CTX_ICALMETHOD,
317                       0,
318                       TP->Tokens);
319
320         StackContext (&SuperTP, 
321                       &SubTP, 
322                       c,
323                       CTX_ICAL,
324                       0,
325                       SuperTP.Tokens);
326         FlushStrBuf(Mime->Data);
327         DoTemplate(HKEY("ical_attachment_display"), Mime->Data, &SubTP);
328
329         /*/ cal_process_object(Mime->Data, cal, 0, Mime->msgnum, ChrPtr(Mime->PartNum)); */
330
331         /* Free the memory we obtained from libical's constructor */
332         StrBufPlain(Mime->ContentType, HKEY("text/html"));
333         StrBufAppendPrintf(WC->trailing_javascript,
334                 "eventEditAllDay();             \n"
335                 "RecurrenceShowHide();          \n"
336                 "EnableOrDisableCheckButton();  \n"
337         );
338
339         UnStackContext(&SuperTP);
340         UnStackContext(&SubTP);
341         icalcomponent_free(cal);
342 }
343 void CreateIcalComponendKindLookup(void)
344 {
345         int i = 0;
346
347         IcalComponentMap = NewHash (1, NULL);
348         while (icalproperty_kind_map[i].NameLen != 0) {
349                 RegisterNS(icalproperty_kind_map[i].Name, 
350                            icalproperty_kind_map[i].NameLen, 
351                            0, 
352                            10, 
353                            tmplput_ICalItem,
354                            NULL, 
355                            CTX_ICAL);
356                 Put(IcalComponentMap, 
357                     icalproperty_kind_map[i].Name, 
358                     icalproperty_kind_map[i].NameLen, 
359                     &icalproperty_kind_map[i],
360                     reference_free_handler);
361                            
362                            
363                 i++;
364         }
365 }
366
367
368
369
370 int cond_ICalIsMethod(StrBuf *Target, WCTemplputParams *TP)
371 {
372         icalproperty_method *the_method = (icalproperty_method *) CTX(CTX_ICALMETHOD);
373         icalproperty_method which_method;
374
375         which_method = GetTemplateTokenNumber(Target, TP, 2, ICAL_METHOD_X);
376         return *the_method == which_method;
377 }
378
379
380
381 void tmplput_Conflict(StrBuf *Target, WCTemplputParams *TP)
382 {}
383
384
385 HashList *iterate_get_ical_attendees(StrBuf *Target, WCTemplputParams *TP)
386 {
387         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
388         icalparameter *partstat_param;
389         icalproperty *p;
390         CalAttendee *Att;
391         HashList *Attendees = NULL;
392         const char *ch;
393         int n = 0;
394
395         /* If the component has attendees, iterate through them. */
396         for (p = icalcomponent_get_first_property(cal, ICAL_ATTENDEE_PROPERTY); 
397              (p != NULL); 
398              p = icalcomponent_get_next_property(cal, ICAL_ATTENDEE_PROPERTY)) {
399                 ch = icalproperty_get_attendee(p);
400                 if ((ch != NULL) && !strncasecmp(ch, "MAILTO:", 7)) {
401                         Att = (CalAttendee*) malloc(sizeof(CalAttendee));
402
403                         /** screen name or email address */
404                         Att->AttendeeStr = NewStrBufPlain(ch + 7, -1);
405                         StrBufTrim(Att->AttendeeStr);
406
407                         /** participant status */
408                         partstat_param = icalproperty_get_first_parameter(
409                                 p,
410                                 ICAL_PARTSTAT_PARAMETER
411                                 );
412                         if (partstat_param == NULL) {
413                                 Att->partstat = ICAL_PARTSTAT_X;
414                         }
415                         else {
416                                 Att->partstat = icalparameter_get_partstat(partstat_param);
417                         }
418                         if (Attendees == NULL)
419                                 Attendees = NewHash(1, Flathash);
420                         Put(Attendees, IKEY(n), Att, DeleteAtt);
421                         n++;
422                 }
423         }
424         return Attendees;
425 }
426
427 void tmplput_ICalAttendee(StrBuf *Target, WCTemplputParams *TP)
428 {
429         CalAttendee *Att = (CalAttendee*) CTX(CTX_ICALATTENDEE);
430         StrBufAppendTemplate(Target, TP, Att->AttendeeStr, 0);
431 }
432 int cond_ICalAttendeeState(StrBuf *Target, WCTemplputParams *TP)
433 {
434         CalAttendee *Att = (CalAttendee*) CTX(CTX_ICALATTENDEE);
435         icalparameter_partstat which_partstat;
436
437         which_partstat = GetTemplateTokenNumber(Target, TP, 2, ICAL_PARTSTAT_X);
438         return Att->partstat == which_partstat;
439 }
440         /* If the component has subcomponents, recurse through them. * /
441         for (c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
442              (c != 0);
443              c = icalcomponent_get_next_component(cal, ICAL_ANY_COMPONENT)) {
444                 /* Recursively process subcomponent * /
445                 cal_process_object(Target, c, recursion_level+1, msgnum, cal_partnum);
446         }
447         */
448
449
450 void 
451 InitModule_ICAL_SUBST
452 (void)
453 {
454         RegisterCTX(CTX_ICAL);
455 //*
456         RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS_TPL, 1, 501);
457         RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS_TPL, 1, 500);
458 //*/
459
460         CreateIcalComponendKindLookup ();
461         RegisterConditional("COND:ICAL:PROPERTY", 1, cond_ICalHaveItem, CTX_ICAL);
462         RegisterConditional("COND:ICAL:IS:A", 1, cond_ICalIsA, CTX_ICAL);
463
464         RegisterNamespace("ICAL:SERV:CHECK:CONFLICT", 0, 0, tmplput_Conflict, NULL, CTX_ICAL);
465
466         RegisterCTX(CTX_ICALATTENDEE);
467         RegisterIterator("ICAL:ATTENDEES", 0, NULL, iterate_get_ical_attendees, 
468                          NULL, NULL, CTX_ICALATTENDEE, CTX_ICAL, IT_NOFLAG);
469         RegisterNamespace("ICAL:ATTENDEE", 1, 2, tmplput_ICalAttendee, NULL, CTX_ICALATTENDEE);
470         RegisterConditional("COND:ICAL:ATTENDEE", 1, cond_ICalAttendeeState, CTX_ICALATTENDEE);
471
472         RegisterCTX(CTX_ICALPROPERTY);
473         RegisterNamespace("ICAL:ITEM", 1, 2, tmplput_ICalItem, NULL, CTX_ICAL);
474         RegisterNamespace("ICAL:PROPERTY:STR", 0, 1, tmplput_CtxICalProperty, NULL, CTX_ICALPROPERTY);
475         RegisterNamespace("ICAL:PROPERTY:DATE", 0, 1, tmplput_CtxICalPropertyDate, NULL, CTX_ICALPROPERTY);
476
477         RegisterCTX(CTX_ICALMETHOD);
478         RegisterConditional("COND:ICAL:METHOD", 1, cond_ICalIsMethod, CTX_ICALMETHOD);
479
480
481         RegisterCTX(CTX_ICALTIME);
482         RegisterConditional("COND:ICAL:DT:PROPERTY", 1, cond_ICalHaveTimeItem, CTX_ICAL);
483         RegisterConditional("COND:ICAL:DT:ISDATE", 0, cond_ICalTimeIsDate, CTX_ICALTIME);
484         RegisterNamespace("ICAL:DT:DATE", 0, 1, tmplput_ICalTime_Date, NULL, CTX_ICALTIME);
485         RegisterNamespace("ICAL:DT:DATETIME", 0, 1, tmplput_ICalTime_Time, NULL, CTX_ICALTIME);
486 }
487
488 void 
489 ServerShutdownModule_ICAL
490 (void)
491 {
492         DeleteHash(&IcalComponentMap);
493 }
494
495
496
497