1690b4b262658994fdd7dbf77dc7273d42740577
[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         struct icaltimetype tt;
161
162         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 2, ICAL_ANY_PROPERTY);
163
164
165         p = icalcomponent_get_first_property(cal, Kind);
166         if (p != NULL) {
167                 struct icaltimetype *t;
168                 time_t ttt;
169                 WCTemplputParams *DynamicTP;
170
171                 DynamicTP = (WCTemplputParams*) malloc(sizeof(WCTemplputParams) + 
172                                                        sizeof(struct icaltimetype));
173                 t = (struct icaltimetype *) ((char*)DynamicTP) + sizeof(WCTemplputParams);
174                 switch (Kind)
175                 {
176                 case ICAL_DTSTART_PROPERTY:
177                         *t = icalproperty_get_dtstart(p);
178                         break;
179                 case ICAL_DTEND_PROPERTY:
180                         tt = icalproperty_get_dtend(p);
181                         ttt = icaltime_as_timet(tt);
182                         break;
183                 default:
184                         memset(t, 0, sizeof(struct icaltimetype));
185                         break;
186                 }
187         
188                 StackDynamicContext (TP, 
189                                      DynamicTP, 
190                                      t,
191                                      CTX_ICALTIME,
192                                      0,
193                                      TP->Tokens,
194                                      ReleaseIcalTimeCtx,
195                                      TP->Tokens->Params[1]->lvalue);
196
197                 return 1;
198         }
199         return 0;
200 }
201
202
203 int cond_ICalTimeIsDate(StrBuf *Target, WCTemplputParams *TP)
204 {
205         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
206         return t->is_date;
207 }
208
209 void tmplput_ICalTime_Date(StrBuf *Target, WCTemplputParams *TP)
210 {
211         struct tm d_tm;
212         long len;
213         char buf[256];
214         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
215
216         memset(&d_tm, 0, sizeof d_tm);
217         d_tm.tm_year = t->year - 1900;
218         d_tm.tm_mon = t->month - 1;
219         d_tm.tm_mday = t->day;
220         len = wc_strftime(buf, sizeof(buf), "%x", &d_tm);
221         StrBufAppendBufPlain(Target, buf, len, 0);
222 }
223 void tmplput_ICalTime_Time(StrBuf *Target, WCTemplputParams *TP)
224 {
225         long len;
226         char buf[256];
227         struct icaltimetype *t = (struct icaltimetype *) CTX(CTX_ICALTIME);
228         time_t tt;
229
230         tt = icaltime_as_timet(*t);
231         len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
232         StrBufAppendBufPlain(Target, buf, len, 0);
233 }
234
235 void tmplput_ICalDate(StrBuf *Target, WCTemplputParams *TP)
236 {
237         icalcomponent *cal = (icalcomponent *) CTX(CTX_ICAL);
238         icalproperty *p;
239         icalproperty_kind Kind;
240         struct icaltimetype t;
241         time_t tt;
242         char buf[256];
243
244         Kind = (icalproperty_kind) GetTemplateTokenNumber(Target, TP, 0, ICAL_ANY_PROPERTY);
245         p = icalcomponent_get_first_property(cal, Kind);
246         if (p != NULL) {
247                 long len;
248                 t = icalproperty_get_dtend(p);
249                 tt = icaltime_as_timet(t);
250                 len = webcit_fmt_date(buf, 256, tt, DATEFMT_FULL);
251                 StrBufAppendBufPlain(Target, buf, len, 0);
252         }
253 }
254
255 void tmplput_CtxICalPropertyDate(StrBuf *Target, WCTemplputParams *TP)
256 {
257         icalproperty *p = (icalproperty *) CTX(CTX_ICALPROPERTY);
258         struct icaltimetype t;
259         time_t tt;
260         char buf[256];
261
262         long len;
263         t = icalproperty_get_dtend(p);
264         tt = icaltime_as_timet(t);
265         len = webcit_fmt_date(buf, sizeof(buf), tt, DATEFMT_FULL);
266         StrBufAppendBufPlain(Target, buf, len, 0);
267 }
268
269
270
271 void render_MIME_ICS_TPL(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
272 {
273         icalproperty_method the_method = ICAL_METHOD_NONE;
274         icalproperty *method = NULL;
275         icalcomponent *cal;
276         icalcomponent *c;
277         WCTemplputParams SubTP;
278         WCTemplputParams SubSubTP;
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         memset(&SubTP, 0, sizeof(WCTemplputParams));
293         memset(&SubSubTP, 0, sizeof(WCTemplputParams));
294         SubTP.Filter.ContextType = CTX_ICAL;
295
296         /*//ical_dezonify(cal); */
297
298         /* If the component has subcomponents, recurse through them. */
299         c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
300
301         c = (c != NULL) ? c : cal;
302         SubTP.Context = c;
303
304         method = icalcomponent_get_first_property(c, ICAL_METHOD_PROPERTY);
305         if (method != NULL) {
306                 the_method = icalproperty_get_method(method);
307         }
308
309         StackContext (&SubTP, 
310                       &SubSubTP, 
311                       &the_method,
312                       CTX_ICALMETHOD,
313                       0,
314                       SubTP.Tokens);
315         FlushStrBuf(Mime->Data);
316         DoTemplate(HKEY("ical_attachment_display"), Mime->Data, &SubTP);
317
318         /*/ cal_process_object(Mime->Data, cal, 0, Mime->msgnum, ChrPtr(Mime->PartNum)); */
319
320         /* Free the memory we obtained from libical's constructor */
321         StrBufPlain(Mime->ContentType, HKEY("text/html"));
322         StrBufAppendPrintf(WC->trailing_javascript,
323                 "eventEditAllDay();             \n"
324                 "RecurrenceShowHide();          \n"
325                 "EnableOrDisableCheckButton();  \n"
326         );
327
328         UnStackContext(&SubSubTP);
329         icalcomponent_free(cal);
330 }
331 void CreateIcalComponendKindLookup(void)
332 {
333         int i = 0;
334
335         IcalComponentMap = NewHash (1, NULL);
336         while (icalproperty_kind_map[i].NameLen != 0) {
337                 RegisterNS(icalproperty_kind_map[i].Name, 
338                            icalproperty_kind_map[i].NameLen, 
339                            0, 
340                            10, 
341                            tmplput_ICalItem,
342                            NULL, 
343                            CTX_ICAL);
344                 Put(IcalComponentMap, 
345                     icalproperty_kind_map[i].Name, 
346                     icalproperty_kind_map[i].NameLen, 
347                     &icalproperty_kind_map[i],
348                     reference_free_handler);
349                            
350                            
351                 i++;
352         }
353 }
354
355
356
357
358 int cond_ICalIsMethod(StrBuf *Target, WCTemplputParams *TP)
359 {
360         icalproperty_method *the_method = (icalproperty_method *) CTX(CTX_ICALMETHOD);
361         icalproperty_method which_method;
362
363         which_method = GetTemplateTokenNumber(Target, TP, 3, ICAL_METHOD_X);
364         return *the_method == which_method;
365 }
366
367
368
369
370
371
372
373
374
375
376
377 void 
378 InitModule_ICAL_SUBST
379 (void)
380 {
381         RegisterCTX(CTX_ICAL);
382 //*
383         RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS_TPL, 1, 501);
384         RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS_TPL, 1, 500);
385 //*/
386
387         CreateIcalComponendKindLookup ();
388         RegisterConditional("COND:ICAL:PROPERTY", 1, cond_ICalHaveItem, CTX_ICAL);
389         RegisterConditional("COND:ICAL:IS:A", 1, cond_ICalIsA, CTX_ICAL);
390
391         RegisterCTX(CTX_ICALPROPERTY);
392         RegisterNamespace("ICAL:ITEM", 1, 2, tmplput_ICalItem, NULL, CTX_ICAL);
393         RegisterNamespace("ICAL:PROPERTY:STR", 0, 1, tmplput_CtxICalProperty, NULL, CTX_ICALPROPERTY);
394         RegisterNamespace("ICAL:PROPERTY:DATE", 0, 1, tmplput_CtxICalPropertyDate, NULL, CTX_ICALPROPERTY);
395
396         RegisterCTX(CTX_ICALMETHOD);
397         RegisterConditional("COND:ICAL:METHOD", 1, cond_ICalIsMethod, CTX_ICALMETHOD);
398
399
400         RegisterCTX(CTX_ICALTIME);
401         RegisterConditional("COND:ICAL:DT:PROPERTY", 1, cond_ICalHaveTimeItem, CTX_ICAL);
402         RegisterConditional("COND:ICAL:DT:ISDATE", 0, cond_ICalTimeIsDate, CTX_ICALTIME);
403         RegisterNamespace("ICAL:DT:DATE", 0, 1, tmplput_ICalTime_Date, NULL, CTX_ICALTIME);
404         RegisterNamespace("ICAL:DT:DATETIME", 0, 1, tmplput_ICalTime_Time, NULL, CTX_ICALTIME);
405 }
406
407 void 
408 ServerShutdownModule_ICAL
409 (void)
410 {
411         DeleteHash(&IcalComponentMap);
412 }
413
414
415
416