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