ICAL-SUBST: work on viewing
[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 *) ((char*)DynamicTP) + sizeof(WCTemplputParams);
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(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
269 {
270         icalproperty_method the_method = ICAL_METHOD_NONE;
271         icalproperty *method = NULL;
272         icalcomponent *cal;
273         icalcomponent *c;
274         WCTemplputParams SubTP;
275         WCTemplputParams SuperTP;
276         static int divcount = 0;
277
278         if (StrLength(Mime->Data) == 0) {
279                 MimeLoadData(Mime);
280         }
281         if (StrLength(Mime->Data) > 0) {
282                 cal = icalcomponent_new_from_string(ChrPtr(Mime->Data));
283         }
284         if (cal == NULL) {
285                 StrBufAppendPrintf(Mime->Data, _("There was an error parsing this calendar item."));
286                 StrBufAppendPrintf(Mime->Data, "<br>\n");
287                 return;
288         }
289
290         putlbstr("divname",  ++divcount);
291         putbstr("cal_partnum", NewStrBufDup(Mime->PartNum));
292         putlbstr("msgnum", Mime->msgnum);
293
294         memset(&SubTP, 0, sizeof(WCTemplputParams));
295         memset(&SuperTP, 0, sizeof(WCTemplputParams));
296
297         /*//ical_dezonify(cal); */
298
299         /* If the component has subcomponents, recurse through them. */
300         c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
301         c = (c != NULL) ? c : cal;
302
303         method = icalcomponent_get_first_property(cal, ICAL_METHOD_PROPERTY);
304         if (method != NULL) {
305                 the_method = icalproperty_get_method(method);
306         }
307
308         SuperTP.Context = &the_method;
309         SuperTP.Filter.ContextType = CTX_ICALMETHOD,
310
311         StackContext (&SuperTP, 
312                       &SubTP, 
313                       c,
314                       CTX_ICAL,
315                       0,
316                       SuperTP.Tokens);
317         FlushStrBuf(Mime->Data);
318         DoTemplate(HKEY("ical_attachment_display"), Mime->Data, &SubTP);
319
320         /*/ cal_process_object(Mime->Data, cal, 0, Mime->msgnum, ChrPtr(Mime->PartNum)); */
321
322         /* Free the memory we obtained from libical's constructor */
323         StrBufPlain(Mime->ContentType, HKEY("text/html"));
324         StrBufAppendPrintf(WC->trailing_javascript,
325                 "eventEditAllDay();             \n"
326                 "RecurrenceShowHide();          \n"
327                 "EnableOrDisableCheckButton();  \n"
328         );
329
330         UnStackContext(&SubTP);
331         icalcomponent_free(cal);
332 }
333 void CreateIcalComponendKindLookup(void)
334 {
335         int i = 0;
336
337         IcalComponentMap = NewHash (1, NULL);
338         while (icalproperty_kind_map[i].NameLen != 0) {
339                 RegisterNS(icalproperty_kind_map[i].Name, 
340                            icalproperty_kind_map[i].NameLen, 
341                            0, 
342                            10, 
343                            tmplput_ICalItem,
344                            NULL, 
345                            CTX_ICAL);
346                 Put(IcalComponentMap, 
347                     icalproperty_kind_map[i].Name, 
348                     icalproperty_kind_map[i].NameLen, 
349                     &icalproperty_kind_map[i],
350                     reference_free_handler);
351                            
352                            
353                 i++;
354         }
355 }
356
357
358
359
360 int cond_ICalIsMethod(StrBuf *Target, WCTemplputParams *TP)
361 {
362         icalproperty_method *the_method = (icalproperty_method *) CTX(CTX_ICALMETHOD);
363         icalproperty_method which_method;
364
365         which_method = GetTemplateTokenNumber(Target, TP, 2, ICAL_METHOD_X);
366         return *the_method == which_method;
367 }
368
369
370
371
372
373
374
375 void tmplput_Conflict(StrBuf *Target, WCTemplputParams *TP)
376 {}
377
378 HashList* IterateGetAttendees()
379 {
380 /*
381         /* If the component has attendees, iterate through them. * /
382         for (p = icalcomponent_get_first_property(cal, ICAL_ATTENDEE_PROPERTY); 
383              (p != NULL); 
384              p = icalcomponent_get_next_property(cal, ICAL_ATTENDEE_PROPERTY)) {
385                 StrBufAppendPrintf(Target, "<dt>");
386                 StrBufAppendPrintf(Target, _("Attendee:"));
387                 StrBufAppendPrintf(Target, "</dt><dd>");
388                 ch = icalproperty_get_attendee(p);
389                 if ((ch != NULL) && !strncasecmp(buf, "MAILTO:", 7)) {
390
391                         /** screen name or email address * /
392                         safestrncpy(buf, ch + 7, sizeof(buf));
393                         striplt(buf);
394                         StrEscAppend(Target, NULL, buf, 0, 0);
395                         StrBufAppendPrintf(Target, " ");
396
397                         /** participant status * /
398                         partstat_as_string(buf, p);
399                         StrEscAppend(Target, NULL, buf, 0, 0);
400                 }
401                 StrBufAppendPrintf(Target, "</dd>\n");
402         }
403 */
404         return NULL;
405         /* If the component has subcomponents, recurse through them. * /
406         for (c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
407              (c != 0);
408              c = icalcomponent_get_next_component(cal, ICAL_ANY_COMPONENT)) {
409                 /* Recursively process subcomponent * /
410                 cal_process_object(Target, c, recursion_level+1, msgnum, cal_partnum);
411         }
412         */
413 }
414
415
416
417 void 
418 InitModule_ICAL_SUBST
419 (void)
420 {
421         RegisterCTX(CTX_ICAL);
422 //*
423         RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS_TPL, 1, 501);
424         RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS_TPL, 1, 500);
425 //*/
426
427         CreateIcalComponendKindLookup ();
428         RegisterConditional("COND:ICAL:PROPERTY", 1, cond_ICalHaveItem, CTX_ICAL);
429         RegisterConditional("COND:ICAL:IS:A", 1, cond_ICalIsA, CTX_ICAL);
430
431         RegisterNamespace("ICAL:SERV:CHECK:CONFLICT", 0, 0, tmplput_Conflict, NULL, CTX_ICAL);
432
433         RegisterCTX(CTX_ICALPROPERTY);
434         RegisterNamespace("ICAL:ITEM", 1, 2, tmplput_ICalItem, NULL, CTX_ICAL);
435         RegisterNamespace("ICAL:PROPERTY:STR", 0, 1, tmplput_CtxICalProperty, NULL, CTX_ICALPROPERTY);
436         RegisterNamespace("ICAL:PROPERTY:DATE", 0, 1, tmplput_CtxICalPropertyDate, NULL, CTX_ICALPROPERTY);
437
438         RegisterCTX(CTX_ICALMETHOD);
439         RegisterConditional("COND:ICAL:METHOD", 1, cond_ICalIsMethod, CTX_ICALMETHOD);
440
441
442         RegisterCTX(CTX_ICALTIME);
443         RegisterConditional("COND:ICAL:DT:PROPERTY", 1, cond_ICalHaveTimeItem, CTX_ICAL);
444         RegisterConditional("COND:ICAL:DT:ISDATE", 0, cond_ICalTimeIsDate, CTX_ICALTIME);
445         RegisterNamespace("ICAL:DT:DATE", 0, 1, tmplput_ICalTime_Date, NULL, CTX_ICALTIME);
446         RegisterNamespace("ICAL:DT:DATETIME", 0, 1, tmplput_ICalTime_Time, NULL, CTX_ICALTIME);
447 }
448
449 void 
450 ServerShutdownModule_ICAL
451 (void)
452 {
453         DeleteHash(&IcalComponentMap);
454 }
455
456
457
458