WebCit now handles the 'local message' flag correctly.
[citadel.git] / webcit / msg_renderers.c
1 #include "webcit.h"
2 #include "webserver.h"
3 #include "dav.h"
4
5 CtxType CTX_MAILSUM = CTX_NONE;
6 CtxType CTX_MIME_ATACH = CTX_NONE;
7
8 HashList *MsgHeaderHandler = NULL;
9 HashList *DflMsgHeaderHandler = NULL;
10 HashList *DflEnumMsgHeaderHandler = NULL;
11
12
13 static inline void CheckConvertBufs(struct wcsession *WCC)
14 {
15         if (WCC->ConvertBuf1 == NULL)
16                 WCC->ConvertBuf1 = NewStrBuf();
17         if (WCC->ConvertBuf2 == NULL)
18                 WCC->ConvertBuf2 = NewStrBuf();
19 }
20
21 /*
22  * message index functions
23  */
24
25
26 void DestroyMimeParts(wc_mime_attachment *Mime)
27 {
28         FreeStrBuf(&Mime->Name);
29         FreeStrBuf(&Mime->FileName);
30         FreeStrBuf(&Mime->PartNum);
31         FreeStrBuf(&Mime->Disposition);
32         FreeStrBuf(&Mime->ContentType);
33         FreeStrBuf(&Mime->Charset);
34         FreeStrBuf(&Mime->Data);
35 }
36
37 void DestroyMime(void *vMime)
38 {
39         wc_mime_attachment *Mime = (wc_mime_attachment*)vMime;
40         DestroyMimeParts(Mime);
41         free(Mime);
42 }
43
44 void DestroyMessageSummary(void *vMsg)
45 {
46         message_summary *Msg = (message_summary*) vMsg;
47
48         FreeStrBuf(&Msg->from);
49         FreeStrBuf(&Msg->to);
50         FreeStrBuf(&Msg->subj);
51         FreeStrBuf(&Msg->reply_inreplyto);
52         FreeStrBuf(&Msg->reply_references);
53         FreeStrBuf(&Msg->cccc);
54         FreeStrBuf(&Msg->ReplyTo);
55         FreeStrBuf(&Msg->AllRcpt);
56         FreeStrBuf(&Msg->Room);
57         FreeStrBuf(&Msg->Rfca);
58         FreeStrBuf(&Msg->EnvTo);
59         DeleteHash(&Msg->Attachments);  /* list of Attachments */
60         DeleteHash(&Msg->Submessages);
61         DeleteHash(&Msg->AttachLinks);
62         DeleteHash(&Msg->AllAttach);
63         free(Msg);
64 }
65
66 int EvaluateMsgHdrEnum(eMessageField f, message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
67 {
68         void *vHdr;
69         headereval* Hdr = NULL;
70         if (GetHash(DflEnumMsgHeaderHandler, IKEY(f), &vHdr) &&
71             (vHdr != NULL)) {
72                 Hdr = (headereval*)vHdr;
73         }
74         if (Hdr == NULL)
75                 return -1;
76         Hdr->evaluator(Msg, HdrLine, FoundCharset);
77         return Hdr->Type;
78 }
79
80 int EvaluateMsgHdr(const char *HeaderName, long HdrNLen, message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
81 {
82         void *vHdr;
83         headereval* Hdr = NULL;
84         if (HdrNLen == 4) {
85                 if (GetHash(DflMsgHeaderHandler, HeaderName, HdrNLen, &vHdr) &&
86                     (vHdr != NULL)) {
87                         Hdr = (headereval*)vHdr;
88                 }
89         }
90         if (Hdr == NULL && GetHash(MsgHeaderHandler, HeaderName, HdrNLen, &vHdr) &&
91             (vHdr != NULL)) {
92                 Hdr = (headereval*)vHdr;
93         }
94         if (Hdr == NULL)
95                 return -1;
96         Hdr->evaluator(Msg, HdrLine, FoundCharset);
97         return Hdr->Type;
98 }
99
100 void RegisterMsgHdr(const char *HeaderName, long HdrNLen, ExamineMsgHeaderFunc evaluator, int type)
101 {
102         headereval *ev;
103         ev = (headereval*) malloc(sizeof(headereval));
104         ev->evaluator = evaluator;
105         ev->Type = type;
106
107         if (HdrNLen == 4) {
108                 eMessageField f;
109                 if (GetFieldFromMnemonic(&f, HeaderName)) {
110                         Put(DflMsgHeaderHandler, HeaderName, HdrNLen, ev, NULL);
111                         Put(DflEnumMsgHeaderHandler, IKEY(f), ev, reference_free_handler);
112                         return;
113                 }
114         }
115         Put(MsgHeaderHandler, HeaderName, HdrNLen, ev, NULL);
116 }
117
118 void RegisterMimeRenderer(const char *HeaderName, long HdrNLen, 
119                           RenderMimeFunc MimeRenderer,
120                           int InlineRenderable,
121                           int Priority)
122 {
123         RenderMimeFuncStruct *f;
124
125         f = (RenderMimeFuncStruct*) malloc(sizeof(RenderMimeFuncStruct));
126         f->f = MimeRenderer;
127         Put(MimeRenderHandler, HeaderName, HdrNLen, f, NULL);
128         if (InlineRenderable)
129                 RegisterEmbeddableMimeType(HeaderName, HdrNLen, 10000 - Priority);
130 }
131
132 /*----------------------------------------------------------------------------*/
133
134 /*
135  *  comparator for two longs in descending order.
136  */
137 int longcmp_r(const void *s1, const void *s2) {
138         long l1;
139         long l2;
140
141         l1 = *(long *)GetSearchPayload(s1);
142         l2 = *(long *)GetSearchPayload(s2);
143
144         if (l1 > l2) return(-1);
145         if (l1 < l2) return(+1);
146         return(0);
147 }
148
149 /*
150  *  comparator for longs; descending order.
151  */
152 int qlongcmp_r(const void *s1, const void *s2) {
153         long l1 = (long) s1;
154         long l2 = (long) s2;
155
156         if (l1 > l2) return(-1);
157         if (l1 < l2) return(+1);
158         return(0);
159 }
160
161  
162 /*
163  * comparator for message summary structs by ascending subject.
164  */
165 int summcmp_subj(const void *s1, const void *s2) {
166         message_summary *summ1;
167         message_summary *summ2;
168         
169         summ1 = (message_summary *)GetSearchPayload(s1);
170         summ2 = (message_summary *)GetSearchPayload(s2);
171         return strcasecmp(ChrPtr(summ1->subj), ChrPtr(summ2->subj));
172 }
173
174 /*
175  * comparator for message summary structs by descending subject.
176  */
177 int summcmp_rsubj(const void *s1, const void *s2) {
178         message_summary *summ1;
179         message_summary *summ2;
180         
181         summ1 = (message_summary *)GetSearchPayload(s1);
182         summ2 = (message_summary *)GetSearchPayload(s2);
183         return strcasecmp(ChrPtr(summ2->subj), ChrPtr(summ1->subj));
184 }
185 /*
186  * comparator for message summary structs by descending subject.
187  */
188 int groupchange_subj(const void *s1, const void *s2) {
189         message_summary *summ1;
190         message_summary *summ2;
191         
192         summ1 = (message_summary *)s1;
193         summ2 = (message_summary *)s2;
194         return ChrPtr(summ2->subj)[0] != ChrPtr(summ1->subj)[0];
195 }
196
197 /*
198  * comparator for message summary structs by ascending sender.
199  */
200 int summcmp_sender(const void *s1, const void *s2) {
201         message_summary *summ1;
202         message_summary *summ2;
203         
204         summ1 = (message_summary *)GetSearchPayload(s1);
205         summ2 = (message_summary *)GetSearchPayload(s2);
206         return strcasecmp(ChrPtr(summ1->from), ChrPtr(summ2->from));
207 }
208
209 /*
210  * comparator for message summary structs by descending sender.
211  */
212 int summcmp_rsender(const void *s1, const void *s2) {
213         message_summary *summ1;
214         message_summary *summ2;
215         
216         summ1 = (message_summary *)GetSearchPayload(s1);
217         summ2 = (message_summary *)GetSearchPayload(s2);
218         return strcasecmp(ChrPtr(summ2->from), ChrPtr(summ1->from));
219 }
220 /*
221  * comparator for message summary structs by descending sender.
222  */
223 int groupchange_sender(const void *s1, const void *s2) {
224         message_summary *summ1;
225         message_summary *summ2;
226         
227         summ1 = (message_summary *)s1;
228         summ2 = (message_summary *)s2;
229         return strcasecmp(ChrPtr(summ2->from), ChrPtr(summ1->from)) != 0;
230
231 }
232
233 /*
234  * comparator for message summary structs by ascending date.
235  */
236 int summcmp_date(const void *s1, const void *s2) {
237         message_summary *summ1;
238         message_summary *summ2;
239         
240         summ1 = (message_summary *)GetSearchPayload(s1);
241         summ2 = (message_summary *)GetSearchPayload(s2);
242
243         if (summ1->date < summ2->date) return -1;
244         else if (summ1->date > summ2->date) return +1;
245         else return 0;
246 }
247
248 /*
249  * comparator for message summary structs by descending date.
250  */
251 int summcmp_rdate(const void *s1, const void *s2) {
252         message_summary *summ1;
253         message_summary *summ2;
254         
255         summ1 = (message_summary *)GetSearchPayload(s1);
256         summ2 = (message_summary *)GetSearchPayload(s2);
257
258         if (summ1->date < summ2->date) return +1;
259         else if (summ1->date > summ2->date) return -1;
260         else return 0;
261 }
262
263 /*
264  * comparator for message summary structs by descending date.
265  */
266 const long DAYSECONDS = 24 * 60 * 60;
267 int groupchange_date(const void *s1, const void *s2) {
268         message_summary *summ1;
269         message_summary *summ2;
270         
271         summ1 = (message_summary *)s1;
272         summ2 = (message_summary *)s2;
273
274         return (summ1->date % DAYSECONDS) != (summ2->date %DAYSECONDS);
275 }
276
277
278 /*----------------------------------------------------------------------------*/
279 /* Don't wanna know... or? */
280 void examine_pref(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
281 void examine_suff(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
282 void examine_path(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
283 void examine_content_encoding(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
284 {
285 /* TODO: do we care? */
286 }
287
288
289 void examine_exti(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
290 {
291         /* we don't care */
292 }
293
294 void examine_nhdr(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
295 {
296         Msg->nhdr = 0;
297         if (!strncasecmp(ChrPtr(HdrLine), "yes", 8))
298                 Msg->nhdr = 1;
299 }
300 int Conditional_ANONYMOUS_MESSAGE(StrBuf *Target, WCTemplputParams *TP)
301 {
302         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
303         return Msg->nhdr != 0;
304 }
305
306 void examine_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
307 {
308         Msg->format_type = StrToi(HdrLine);
309                         
310 }
311
312 void examine_from(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
313 {
314         wcsession *WCC = WC;
315
316         CheckConvertBufs(WCC);
317         FreeStrBuf(&Msg->from);
318         Msg->from = NewStrBufPlain(NULL, StrLength(HdrLine));
319         StrBuf_RFC822_2_Utf8(Msg->from, 
320                              HdrLine, 
321                              WCC->DefaultCharset, 
322                              FoundCharset,
323                              WCC->ConvertBuf1,
324                              WCC->ConvertBuf2);
325 }
326 void tmplput_MAIL_SUMM_FROM(StrBuf *Target, WCTemplputParams *TP)
327 {
328         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
329         StrBufAppendTemplate(Target, TP, Msg->from, 0);
330 }
331
332 void examine_subj(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
333 {
334         wcsession *WCC = WC;
335
336         CheckConvertBufs(WCC);
337         FreeStrBuf(&Msg->subj);
338         Msg->subj = NewStrBufPlain(NULL, StrLength(HdrLine));
339         StrBuf_RFC822_2_Utf8(Msg->subj, 
340                              HdrLine, 
341                              WCC->DefaultCharset, 
342                              FoundCharset,
343                              WCC->ConvertBuf1,
344                              WCC->ConvertBuf2);
345 }
346 void tmplput_MAIL_SUMM_SUBJECT(StrBuf *Target, WCTemplputParams *TP)
347 {
348         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
349
350         if (TP->Tokens->nParameters == 4)
351         {
352                 const char *pch;
353                 long len;
354                 
355                 GetTemplateTokenString(Target, TP, 3, &pch, &len);
356                 if ((len > 0)&&
357                     (strstr(ChrPtr(Msg->subj), pch) == NULL))
358                 {
359                         GetTemplateTokenString(Target, TP, 2, &pch, &len);
360                         StrBufAppendBufPlain(Target, pch, len, 0);
361                 }
362         }
363         StrBufAppendTemplate(Target, TP, Msg->subj, 0);
364 }
365
366 /*
367  * Conditional returns true if the message has a Subject and it is nonzero in length
368  */
369 int Conditional_MAIL_SUMM_SUBJECT(StrBuf *Target, WCTemplputParams *TP) {
370         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
371         return StrLength(Msg->subj) > 0;
372 }
373
374
375 /*
376  * Conditional returns true if the message originated on the local system
377  */
378 int Conditional_MAIL_LOCAL(StrBuf *Target, WCTemplputParams *TP) {
379         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
380         return (Msg->is_local ? 1 : 0);
381 }
382
383
384 void examine_msgn(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {
385         wcsession *WCC = WC;
386         long Offset = 0;
387         const char *pOffset;
388
389         CheckConvertBufs(WCC);
390         FreeStrBuf(&Msg->reply_inreplyto);
391         Msg->reply_inreplyto = NewStrBufPlain(NULL, StrLength(HdrLine));
392         pOffset = strchr(ChrPtr(HdrLine), '/');
393         if (pOffset != NULL) {
394                 Offset = pOffset - ChrPtr(HdrLine);
395         }
396         Msg->reply_inreplyto_hash = ThreadIdHashOffset(HdrLine, Offset);
397         StrBuf_RFC822_2_Utf8(Msg->reply_inreplyto, 
398                              HdrLine, 
399                              WCC->DefaultCharset,
400                              FoundCharset,
401                              WCC->ConvertBuf1,
402                              WCC->ConvertBuf2);
403 }
404 void tmplput_MAIL_SUMM_INREPLYTO(StrBuf *Target, WCTemplputParams *TP)
405 {
406         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
407         StrBufAppendTemplate(Target, TP, Msg->reply_inreplyto, 0);
408 }
409
410 int Conditional_MAIL_SUMM_UNREAD(StrBuf *Target, WCTemplputParams *TP)
411 {
412         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
413         return (Msg->Flags & MSGFLAG_READ) != 0;
414 }
415
416 void examine_wefw(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
417 {
418         wcsession *WCC = WC;
419         long Offset = 0;
420         const char *pOffset;
421
422         CheckConvertBufs(WCC);
423         FreeStrBuf(&Msg->reply_references);
424         Msg->reply_references = NewStrBufPlain(NULL, StrLength(HdrLine));
425         pOffset = strchr(ChrPtr(HdrLine), '/');
426         if (pOffset != NULL) {
427                 Offset = pOffset - ChrPtr(HdrLine);
428         }
429         Msg->reply_references_hash = ThreadIdHashOffset(HdrLine, Offset);
430         StrBuf_RFC822_2_Utf8(Msg->reply_references, 
431                              HdrLine, 
432                              WCC->DefaultCharset, 
433                              FoundCharset,
434                              WCC->ConvertBuf1,
435                              WCC->ConvertBuf2);
436 }
437 void tmplput_MAIL_SUMM_REFIDS(StrBuf *Target, WCTemplputParams *TP)
438 {
439         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
440         StrBufAppendTemplate(Target, TP, Msg->reply_references, 0);
441 }
442
443 void examine_replyto(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
444 {
445         wcsession *WCC = WC;
446
447         CheckConvertBufs(WCC);
448         FreeStrBuf(&Msg->ReplyTo);
449         Msg->ReplyTo = NewStrBufPlain(NULL, StrLength(HdrLine));
450         StrBuf_RFC822_2_Utf8(Msg->ReplyTo, 
451                              HdrLine, 
452                              WCC->DefaultCharset, 
453                              FoundCharset,
454                              WCC->ConvertBuf1,
455                              WCC->ConvertBuf2);
456         if (Msg->AllRcpt == NULL)
457                 Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
458         if (StrLength(Msg->AllRcpt) > 0) {
459                 StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
460         }
461         StrBufAppendBuf(Msg->AllRcpt, Msg->ReplyTo, 0);
462 }
463 void tmplput_MAIL_SUMM_REPLYTO(StrBuf *Target, WCTemplputParams *TP)
464 {
465         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
466         StrBufAppendTemplate(Target, TP, Msg->ReplyTo, 0);
467 }
468
469 void examine_cccc(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
470 {
471         wcsession *WCC = WC;
472
473         CheckConvertBufs(WCC);
474         FreeStrBuf(&Msg->cccc);
475         Msg->cccc = NewStrBufPlain(NULL, StrLength(HdrLine));
476         StrBuf_RFC822_2_Utf8(Msg->cccc, 
477                              HdrLine, 
478                              WCC->DefaultCharset, 
479                              FoundCharset,
480                              WCC->ConvertBuf1,
481                              WCC->ConvertBuf2);
482         if (Msg->AllRcpt == NULL)
483                 Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
484         if (StrLength(Msg->AllRcpt) > 0) {
485                 StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
486         }
487         StrBufAppendBuf(Msg->AllRcpt, Msg->cccc, 0);
488 }
489 void tmplput_MAIL_SUMM_CCCC(StrBuf *Target, WCTemplputParams *TP)
490 {
491         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
492         StrBufAppendTemplate(Target, TP, Msg->cccc, 0);
493 }
494
495
496 void examine_room(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
497 {
498         if ((StrLength(HdrLine) > 0) &&
499             (strcasecmp(ChrPtr(HdrLine), ChrPtr(WC->CurRoom.name)))) {
500                 FreeStrBuf(&Msg->Room);
501                 Msg->Room = NewStrBufDup(HdrLine);              
502         }
503 }
504
505
506 void tmplput_MAIL_SUMM_ORGROOM(StrBuf *Target, WCTemplputParams *TP)
507 {
508         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
509         StrBufAppendTemplate(Target, TP, Msg->Room, 0);
510 }
511
512
513 void examine_rfca(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
514 {
515         FreeStrBuf(&Msg->Rfca);
516         Msg->Rfca = NewStrBufDup(HdrLine);
517 }
518
519
520 void examine_locl(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
521 {
522         Msg->is_local = 1;
523 }
524
525
526 void tmplput_MAIL_SUMM_RFCA(StrBuf *Target, WCTemplputParams *TP)
527 {
528         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
529         StrBufAppendTemplate(Target, TP, Msg->Rfca, 0);
530 }
531 int Conditional_MAIL_SUMM_RFCA(StrBuf *Target, WCTemplputParams *TP)
532 {
533         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
534         return StrLength(Msg->Rfca) > 0;
535 }
536 int Conditional_MAIL_SUMM_CCCC(StrBuf *Target, WCTemplputParams *TP)
537 {
538         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
539         return StrLength(Msg->cccc) > 0;
540 }
541 int Conditional_MAIL_SUMM_REPLYTO(StrBuf *Target, WCTemplputParams *TP)
542 {
543         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
544         return StrLength(Msg->ReplyTo) > 0;
545 }
546
547 void examine_nvto(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
548 {
549         wcsession *WCC = WC;
550
551         CheckConvertBufs(WCC);
552         FreeStrBuf(&Msg->EnvTo);
553         Msg->EnvTo = NewStrBufPlain(NULL, StrLength(HdrLine));
554         StrBuf_RFC822_2_Utf8(Msg->EnvTo, 
555                              HdrLine, 
556                              WCC->DefaultCharset, 
557                              FoundCharset,
558                              WCC->ConvertBuf1,
559                              WCC->ConvertBuf2);
560 }
561
562
563 void examine_rcpt(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
564 {
565         wcsession *WCC = WC;
566
567         CheckConvertBufs(WCC);
568         FreeStrBuf(&Msg->to);
569         Msg->to = NewStrBufPlain(NULL, StrLength(HdrLine));
570         StrBuf_RFC822_2_Utf8(Msg->to, 
571                              HdrLine, 
572                              WCC->DefaultCharset, 
573                              FoundCharset,
574                              WCC->ConvertBuf1,
575                              WCC->ConvertBuf2);
576         if (Msg->AllRcpt == NULL)
577                 Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
578         if (StrLength(Msg->AllRcpt) > 0) {
579                 StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
580         }
581         StrBufAppendBuf(Msg->AllRcpt, Msg->to, 0);
582 }
583 void tmplput_MAIL_SUMM_TO(StrBuf *Target, WCTemplputParams *TP)
584 {
585         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
586         StrBufAppendTemplate(Target, TP, Msg->to, 0);
587 }
588 int Conditional_MAIL_SUMM_TO(StrBuf *Target, WCTemplputParams *TP) 
589 {
590         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
591         return StrLength(Msg->to) != 0;
592 }
593 int Conditional_MAIL_SUMM_SUBJ(StrBuf *Target, WCTemplputParams *TP) 
594 {
595         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
596         return StrLength(Msg->subj) != 0;
597 }
598 void tmplput_MAIL_SUMM_ALLRCPT(StrBuf *Target, WCTemplputParams *TP)
599 {
600         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
601         StrBufAppendTemplate(Target, TP, Msg->AllRcpt, 0);
602 }
603
604
605
606 void tmplput_SUMM_COUNT(StrBuf *Target, WCTemplputParams *TP)
607 {
608         StrBufAppendPrintf(Target, "%d", GetCount( WC->summ));
609 }
610
611 HashList *iterate_get_mailsumm_All(StrBuf *Target, WCTemplputParams *TP)
612 {
613         return WC->summ;
614 }
615 void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
616 {
617         Msg->date = StrTol(HdrLine);
618 }
619
620 void tmplput_MAIL_SUMM_DATE_BRIEF(StrBuf *Target, WCTemplputParams *TP)
621 {
622         char datebuf[64];
623         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
624         webcit_fmt_date(datebuf, 64, Msg->date, DATEFMT_BRIEF);
625         StrBufAppendBufPlain(Target, datebuf, -1, 0);
626 }
627
628 void tmplput_MAIL_SUMM_EUID(StrBuf *Target, WCTemplputParams *TP)
629 {
630         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
631         StrBufAppendTemplate(Target, TP, Msg->euid, 0);
632 }
633
634 void tmplput_MAIL_SUMM_DATE_FULL(StrBuf *Target, WCTemplputParams *TP)
635 {
636         char datebuf[64];
637         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
638         webcit_fmt_date(datebuf, 64, Msg->date, DATEFMT_FULL);
639         StrBufAppendBufPlain(Target, datebuf, -1, 0);
640 }
641 void tmplput_MAIL_SUMM_DATE_NO(StrBuf *Target, WCTemplputParams *TP)
642 {
643         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
644         StrBufAppendPrintf(Target, "%ld", Msg->date, 0);
645 }
646
647
648
649 void render_MAIL(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
650 {
651         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
652         const StrBuf *TemplateMime;
653
654         if (Mime->Data == NULL) 
655                 Mime->Data = NewStrBufPlain(NULL, Mime->length);
656         else 
657                 FlushStrBuf(Mime->Data);
658         read_message(Mime->Data, HKEY("view_submessage"), Mime->msgnum, Mime->PartNum, &TemplateMime, TP);
659 /*
660         if ( (!IsEmptyStr(mime_submessages)) && (!section[0]) ) {
661                 for (i=0; i<num_tokens(mime_submessages, '|'); ++i) {
662                         extract_token(buf, mime_submessages, i, '|', sizeof buf);
663                         / ** use printable_view to suppress buttons * /
664                         wc_printf("<blockquote>");
665                         read_message(Mime->msgnum, 1, ChrPtr(Mime->Section));
666                         wc_printf("</blockquote>");
667                 }
668         }
669 */
670 }
671
672 void render_MIME_ICS(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
673 {
674         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
675         if (StrLength(Mime->Data) == 0) {
676                 MimeLoadData(Mime);
677         }
678         if (StrLength(Mime->Data) > 0) {
679                 cal_process_attachment(Mime);
680         }
681 }
682
683
684
685 void examine_mime_part(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
686 {
687         const char *Ptr = NULL;
688         wc_mime_attachment *Mime;
689         StrBuf *Buf;
690         wcsession *WCC = WC;
691
692         CheckConvertBufs(WCC);  
693         Mime = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
694         memset(Mime, 0, sizeof(wc_mime_attachment));
695         Mime->msgnum = Msg->msgnum;
696         Buf = NewStrBuf();
697
698         Mime->Name = NewStrBuf();
699         StrBufExtract_NextToken(Buf, HdrLine, &Ptr, '|');
700         StrBuf_RFC822_2_Utf8(Mime->Name, 
701                              Buf, 
702                              WCC->DefaultCharset, 
703                              FoundCharset,
704                              WCC->ConvertBuf1,
705                              WCC->ConvertBuf2);
706         StrBufTrim(Mime->Name);
707
708         StrBufExtract_NextToken(Buf, HdrLine, &Ptr, '|');
709         Mime->FileName = NewStrBuf();
710         StrBuf_RFC822_2_Utf8(Mime->FileName, 
711                              Buf, 
712                              WCC->DefaultCharset, 
713                              FoundCharset,
714                              WCC->ConvertBuf1,
715                              WCC->ConvertBuf2);
716         StrBufTrim(Mime->FileName);
717
718         Mime->PartNum = NewStrBuf();
719         StrBufExtract_NextToken(Mime->PartNum, HdrLine, &Ptr, '|');
720         StrBufTrim(Mime->PartNum);
721         if (strchr(ChrPtr(Mime->PartNum), '.') != NULL) 
722                 Mime->level = 2;
723         else
724                 Mime->level = 1;
725
726         Mime->Disposition = NewStrBuf();
727         StrBufExtract_NextToken(Mime->Disposition, HdrLine, &Ptr, '|');
728
729         Mime->ContentType = NewStrBuf();
730         StrBufExtract_NextToken(Mime->ContentType, HdrLine, &Ptr, '|');
731         StrBufTrim(Mime->ContentType);
732         StrBufLowerCase(Mime->ContentType);
733         if (!strcmp(ChrPtr(Mime->ContentType), "application/octet-stream")) {
734                 StrBufPlain(Mime->ContentType, 
735                             GuessMimeByFilename(SKEY(Mime->FileName)), -1);
736         }
737
738         Mime->length = StrBufExtractNext_int(HdrLine, &Ptr, '|');
739
740         StrBufSkip_NTokenS(HdrLine, &Ptr, '|', 1);  /* cbid?? */
741
742         Mime->Charset = NewStrBuf();
743         StrBufExtract_NextToken(Mime->Charset, HdrLine, &Ptr, '|');
744
745
746         if ( (StrLength(Mime->FileName) == 0) && (StrLength(Mime->Name) > 0) ) {
747                 StrBufAppendBuf(Mime->FileName, Mime->Name, 0);
748         }
749
750         if (StrLength(Msg->PartNum) > 0) {
751                 StrBuf *tmp;
752                 StrBufPrintf(Buf, "%s.%s", ChrPtr(Msg->PartNum), ChrPtr(Mime->PartNum));
753                 tmp = Mime->PartNum;
754                 Mime->PartNum = Buf;
755                 Buf = tmp;
756         }
757
758         if (Msg->AllAttach == NULL)
759                 Msg->AllAttach = NewHash(1,NULL);
760         Put(Msg->AllAttach, SKEY(Mime->PartNum), Mime, DestroyMime);
761         FreeStrBuf(&Buf);
762 }
763
764
765 void evaluate_mime_part(StrBuf *Target, WCTemplputParams *TP)
766 {
767         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
768         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
769         void *vMimeRenderer;
770
771         /* just print the root-node */
772         if ((Mime->level >= 1) &&
773             GetHash(MimeRenderHandler, SKEY(Mime->ContentType), &vMimeRenderer) &&
774             vMimeRenderer != NULL)
775         {
776                 Mime->Renderer = (RenderMimeFuncStruct*) vMimeRenderer;
777                 if (Msg->Submessages == NULL)
778                         Msg->Submessages = NewHash(1,NULL);
779                 Put(Msg->Submessages, SKEY(Mime->PartNum), Mime, reference_free_handler);
780         }
781         else if ((Mime->level >= 1) &&
782                  (!strcasecmp(ChrPtr(Mime->Disposition), "inline"))
783                  && (!strncasecmp(ChrPtr(Mime->ContentType), "image/", 6)) ){
784                 if (Msg->AttachLinks == NULL)
785                         Msg->AttachLinks = NewHash(1,NULL);
786                 Put(Msg->AttachLinks, SKEY(Mime->PartNum), Mime, reference_free_handler);
787         }
788         else if ((Mime->level >= 1) &&
789                  (StrLength(Mime->ContentType) > 0) &&
790                   ( (!strcasecmp(ChrPtr(Mime->Disposition), "attachment")) 
791                     || (!strcasecmp(ChrPtr(Mime->Disposition), "inline"))
792                     || (!strcasecmp(ChrPtr(Mime->Disposition), ""))))
793         {               
794                 if (Msg->AttachLinks == NULL)
795                         Msg->AttachLinks = NewHash(1,NULL);
796                 Put(Msg->AttachLinks, SKEY(Mime->PartNum), Mime, reference_free_handler);
797                 if ((strcasecmp(ChrPtr(Mime->ContentType), "application/octet-stream") == 0) && 
798                     (StrLength(Mime->FileName) > 0)) {
799                         FlushStrBuf(Mime->ContentType);
800                         StrBufAppendBufPlain(Mime->ContentType,
801                                              GuessMimeByFilename(SKEY(Mime->FileName)),
802                                              -1, 0);
803                 }
804         }
805 }
806
807 void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, WCTemplputParams *TP)
808 {
809         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
810         StrBufAppendPrintf(Target, "%ld", GetCount(Msg->Attachments));
811 }
812
813 void examine_text(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
814 {
815         if (Msg->MsgBody->Data == NULL)
816                 Msg->MsgBody->Data = NewStrBufPlain(NULL, SIZ);
817         else
818                 FlushStrBuf(Msg->MsgBody->Data);
819 }
820
821 void examine_msg4_partnum(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
822 {
823         Msg->MsgBody->PartNum = NewStrBufDup(HdrLine);
824         StrBufTrim(Msg->MsgBody->PartNum);
825 }
826
827 void examine_content_lengh(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
828 {
829         Msg->MsgBody->length = StrTol(HdrLine);
830         Msg->MsgBody->size_known = 1;
831 }
832
833 void examine_content_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
834 {
835         StrBuf *Token;
836         StrBuf *Value;
837         const char* sem;
838         const char *eq;
839         int len;
840         StrBufTrim(HdrLine);
841         Msg->MsgBody->ContentType = NewStrBufDup(HdrLine);
842         sem = strchr(ChrPtr(HdrLine), ';');
843
844         if (sem != NULL) {
845                 Token = NewStrBufPlain(NULL, StrLength(HdrLine));
846                 Value = NewStrBufPlain(NULL, StrLength(HdrLine));
847                 len = sem - ChrPtr(HdrLine);
848                 StrBufCutAt(Msg->MsgBody->ContentType, len, NULL);
849                 while (sem != NULL) {
850                         while (isspace(*(sem + 1)))
851                                 sem ++;
852                         StrBufCutLeft(HdrLine, sem - ChrPtr(HdrLine));
853                         sem = strchr(ChrPtr(HdrLine), ';');
854                         if (sem != NULL)
855                                 len = sem - ChrPtr(HdrLine);
856                         else
857                                 len = StrLength(HdrLine);
858                         FlushStrBuf(Token);
859                         FlushStrBuf(Value);
860                         StrBufAppendBufPlain(Token, ChrPtr(HdrLine), len, 0);
861                         eq = strchr(ChrPtr(Token), '=');
862                         if (eq != NULL) {
863                                 len = eq - ChrPtr(Token);
864                                 StrBufAppendBufPlain(Value, eq + 1, StrLength(Token) - len - 1, 0); 
865                                 StrBufCutAt(Token, len, NULL);
866                                 StrBufTrim(Value);
867                         }
868                         StrBufTrim(Token);
869
870                         if (EvaluateMsgHdr(SKEY(Token), Msg, Value, FoundCharset) < 0)
871                                 syslog(LOG_WARNING, "don't know how to handle content type sub-header[%s]\n", ChrPtr(Token));
872                 }
873                 FreeStrBuf(&Token);
874                 FreeStrBuf(&Value);
875         }
876 }
877
878
879 int ReadOneMessageSummary(message_summary *Msg, StrBuf *FoundCharset, StrBuf *Buf)
880 {
881         const char *buf;
882         const char *ebuf;
883         int nBuf;
884         long len;
885         
886         serv_printf("MSG0 %ld|1", Msg->msgnum); /* ask for headers only */
887         
888         StrBuf_ServGetln(Buf);
889         if (GetServerStatus(Buf, NULL) != 1) {
890                 return 0;
891         }
892
893         while (len = StrBuf_ServGetln(Buf),
894                (len >= 0) && 
895                ((len != 3)  ||
896                 strcmp(ChrPtr(Buf), "000")))
897         {
898                 buf = ChrPtr(Buf);
899                 ebuf = strchr(ChrPtr(Buf), '=');
900                 nBuf = ebuf - buf;
901                 
902                 if (EvaluateMsgHdr(buf, nBuf, Msg, Buf, FoundCharset) < 0)
903                         syslog(LOG_INFO, "Don't know how to handle Message Headerline [%s]", ChrPtr(Buf));
904         }
905         return 1;
906 }
907
908 void tmplput_MAIL_SUMM_N(StrBuf *Target, WCTemplputParams *TP)
909 {
910         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
911         StrBufAppendPrintf(Target, "%ld", Msg->msgnum);
912 }
913
914
915 void tmplput_MAIL_SUMM_PERMALINK(StrBuf *Target, WCTemplputParams *TP)
916 {
917         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
918         StrBuf *perma_link;
919         const StrBuf *View;
920
921         perma_link = NewStrBufPlain(HKEY("/readfwd?go="));
922         StrBufUrlescAppend(perma_link, WC->CurRoom.name, NULL);
923         View = sbstr("view");
924         if (View != NULL) {
925                 StrBufAppendBufPlain(perma_link, HKEY("?view="), 0);
926                 StrBufAppendBuf(perma_link, View, 0);
927         }
928         StrBufAppendBufPlain(perma_link, HKEY("?start_reading_at="), 0);
929         StrBufAppendPrintf(perma_link, "%ld#%ld", Msg->msgnum, Msg->msgnum);
930         StrBufAppendBuf(Target, perma_link, 0);
931         FreeStrBuf(&perma_link);
932 }
933
934
935 int Conditional_MAIL_MIME_ALL(StrBuf *Target, WCTemplputParams *TP)
936 {
937         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
938         return GetCount(Msg->Attachments) > 0;
939 }
940
941 int Conditional_MAIL_MIME_SUBMESSAGES(StrBuf *Target, WCTemplputParams *TP)
942 {
943         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
944         return GetCount(Msg->Submessages) > 0;
945 }
946
947 int Conditional_MAIL_MIME_ATTACHLINKS(StrBuf *Target, WCTemplputParams *TP)
948 {
949         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
950         return GetCount(Msg->AttachLinks) > 0;
951 }
952
953 int Conditional_MAIL_MIME_ATTACH(StrBuf *Target, WCTemplputParams *TP)
954 {
955         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
956         return GetCount(Msg->AllAttach) > 0;
957 }
958
959 void tmplput_QUOTED_MAIL_BODY(StrBuf *Target, WCTemplputParams *TP)
960 {
961         const StrBuf *Mime;
962         long MsgNum;
963         StrBuf *Buf;
964
965         MsgNum = LBstr(TKEY(0));
966         Buf = NewStrBuf();
967         read_message(Buf, HKEY("view_message_replyquote"), MsgNum, NULL, &Mime, TP);
968         StrBufAppendTemplate(Target, TP, Buf, 1);
969         FreeStrBuf(&Buf);
970 }
971
972 void tmplput_EDIT_MAIL_BODY(StrBuf *Target, WCTemplputParams *TP)
973 {
974         const StrBuf *Mime;
975         long MsgNum;
976         StrBuf *Buf;
977
978         MsgNum = LBstr(TKEY(0));
979         Buf = NewStrBuf();
980         read_message(Buf, HKEY("view_message_edit"), MsgNum, NULL, &Mime, TP);
981         StrBufAppendTemplate(Target, TP, Buf, 1);
982         FreeStrBuf(&Buf);
983 }
984
985 void tmplput_EDIT_WIKI_BODY(StrBuf *Target, WCTemplputParams *TP)
986 {
987         const StrBuf *Mime;
988         long msgnum;
989         StrBuf *Buf;
990
991         /* Insert the existing content of the wiki page into the editor.  But we only want
992          * to do this the first time -- if the user is uploading an attachment we don't want
993          * to do it again.
994          */
995         if (!havebstr("attach_button")) {
996                 StrBuf *wikipage = NewStrBufDup(sbstr("page"));
997                 putbstr("format", NewStrBufPlain(HKEY("plain")));
998                 str_wiki_index(wikipage);
999                 msgnum = locate_message_by_uid(ChrPtr(wikipage));
1000                 FreeStrBuf(&wikipage);
1001                 if (msgnum >= 0L) {
1002                         Buf = NewStrBuf();
1003                         read_message(Buf, HKEY("view_message_wikiedit"), msgnum, NULL, &Mime, TP);
1004                         StrBufAppendTemplate(Target, TP, Buf, 1);
1005                         FreeStrBuf(&Buf);
1006                 }
1007         }
1008 }
1009
1010 void tmplput_MAIL_BODY(StrBuf *Target, WCTemplputParams *TP)
1011 {
1012         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
1013         StrBufAppendTemplate(Target, TP, Msg->MsgBody->Data, 0);
1014 }
1015
1016
1017 void render_MAIL_variformat(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
1018 {
1019         /* Messages in legacy Citadel variformat get handled thusly... */
1020         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
1021         StrBuf *TTarget = NewStrBufPlain(NULL, StrLength(Mime->Data));
1022         FmOut(TTarget, "JUSTIFY", Mime->Data);
1023         FreeStrBuf(&Mime->Data);
1024         Mime->Data = TTarget;
1025 }
1026
1027 void render_MAIL_text_plain(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
1028 {
1029         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
1030         const char *ptr, *pte;
1031         const char *BufPtr = NULL;
1032         StrBuf *Line;
1033         StrBuf *Line1;
1034         StrBuf *Line2;
1035         StrBuf *TTarget;
1036         long Linecount;
1037         long nEmptyLines;
1038         int bn = 0;
1039         int bq = 0;
1040         int i;
1041         long len;
1042 #ifdef HAVE_ICONV
1043         StrBuf *cs = NULL;
1044         int ConvertIt = 1;
1045         iconv_t ic = (iconv_t)(-1) ;
1046 #endif
1047
1048         if ((StrLength(Mime->Data) == 0) && (Mime->length > 0)) {
1049                 FreeStrBuf(&Mime->Data);
1050                 MimeLoadData(Mime);
1051         }
1052
1053 #ifdef HAVE_ICONV
1054         if (ConvertIt) {
1055                 if (StrLength(Mime->Charset) != 0)
1056                         cs = Mime->Charset;
1057                 else if (StrLength(FoundCharset) > 0)
1058                         cs = FoundCharset;
1059                 else if (StrLength(WC->DefaultCharset) > 0)
1060                         cs = WC->DefaultCharset;
1061                 if (cs == NULL) {
1062                         ConvertIt = 0;
1063                 }
1064                 else if (!strcasecmp(ChrPtr(cs), "utf-8")) {
1065                         ConvertIt = 0;
1066                 }
1067                 else if (!strcasecmp(ChrPtr(cs), "us-ascii")) {
1068                         ConvertIt = 0;
1069                 }
1070                 else {
1071                         ctdl_iconv_open("UTF-8", ChrPtr(cs), &ic);
1072                         if (ic == (iconv_t)(-1) ) {
1073                                 syslog(LOG_WARNING, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
1074                                         __FILE__, __LINE__, ChrPtr(Mime->Charset), strerror(errno));
1075                         }
1076                 }
1077         }
1078 #endif
1079         Line = NewStrBufPlain(NULL, SIZ);
1080         Line1 = NewStrBufPlain(NULL, SIZ);
1081         Line2 = NewStrBufPlain(NULL, SIZ);
1082         TTarget = NewStrBufPlain(NULL, StrLength(Mime->Data));
1083         Linecount = 0;
1084         nEmptyLines = 0;
1085         if (StrLength(Mime->Data) > 0) 
1086                 do 
1087                 {
1088                         StrBufSipLine(Line, Mime->Data, &BufPtr);
1089                         bq = 0;
1090                         i = 0;
1091                         ptr = ChrPtr(Line);
1092                         len = StrLength(Line);
1093                         pte = ptr + len;
1094                 
1095                         while ((ptr < pte) &&
1096                                ((*ptr == '>') ||
1097                                 isspace(*ptr)))
1098                         {
1099                                 if (*ptr == '>')
1100                                         bq++;
1101                                 ptr ++;
1102                                 i++;
1103                         }
1104                         if (i > 0) StrBufCutLeft(Line, i);
1105                 
1106                         if (StrLength(Line) == 0) {
1107                                 if (Linecount == 0)
1108                                         continue;
1109                                 StrBufAppendBufPlain(TTarget, HKEY("<tt></tt><br>\n"), 0);
1110
1111                                 nEmptyLines ++;
1112                                 continue;
1113                         }
1114                         nEmptyLines = 0;
1115                         for (i = bn; i < bq; i++)                               
1116                                 StrBufAppendBufPlain(TTarget, HKEY("<blockquote>"), 0);
1117                         for (i = bq; i < bn; i++)                               
1118                                 StrBufAppendBufPlain(TTarget, HKEY("</blockquote>"), 0);
1119 #ifdef HAVE_ICONV
1120                         if (ConvertIt) {
1121                                 StrBufConvert(Line, Line1, &ic);
1122                         }
1123 #endif
1124                         StrBufAppendBufPlain(TTarget, HKEY("<tt>"), 0);
1125                         UrlizeText(Line1, Line, Line2);
1126
1127                         StrEscAppend(TTarget, Line1, NULL, 0, 0);
1128                         StrBufAppendBufPlain(TTarget, HKEY("</tt><br>\n"), 0);
1129                         bn = bq;
1130                         Linecount ++;
1131                 }
1132         while ((BufPtr != StrBufNOTNULL) &&
1133                (BufPtr != NULL));
1134
1135         if (nEmptyLines > 0)
1136                 StrBufCutRight(TTarget, nEmptyLines * (sizeof ("<tt></tt><br>\n") - 1));
1137         for (i = 0; i < bn; i++)                                
1138                 StrBufAppendBufPlain(TTarget, HKEY("</blockquote>"), 0);
1139
1140         StrBufAppendBufPlain(TTarget, HKEY("</i><br>"), 0);
1141 #ifdef HAVE_ICONV
1142         if (ic != (iconv_t)(-1) ) {
1143                 iconv_close(ic);
1144         }
1145 #endif
1146
1147         FreeStrBuf(&Mime->Data);
1148         Mime->Data = TTarget;
1149         FlushStrBuf(Mime->ContentType);
1150         StrBufAppendBufPlain(Mime->ContentType, HKEY("text/html"), 0);
1151         FlushStrBuf(Mime->Charset);
1152         StrBufAppendBufPlain(Mime->Charset, HKEY("UTF-8"), 0);
1153         FreeStrBuf(&Line);
1154         FreeStrBuf(&Line1);
1155         FreeStrBuf(&Line2);
1156 }
1157
1158 void render_MAIL_html(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
1159 {
1160         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
1161         StrBuf *Buf;
1162
1163         if (StrLength(Mime->Data) == 0)
1164                 return;
1165
1166         Buf = NewStrBufPlain(NULL, StrLength(Mime->Data));
1167
1168         /* HTML is fun, but we've got to strip it first */
1169         output_html(ChrPtr(Mime->Charset), 
1170                     (WC->CurRoom.view == VIEW_WIKI ? 1 : 0), 
1171                     Mime->msgnum,
1172                     Mime->Data, Buf);
1173         FreeStrBuf(&Mime->Data);
1174         Mime->Data = Buf;
1175 }
1176
1177
1178 void render_MAIL_UNKNOWN(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
1179 {
1180         wc_mime_attachment *Mime = (wc_mime_attachment *) CTX(CTX_MIME_ATACH);
1181         /* Unknown weirdness */
1182         FlushStrBuf(Mime->Data);
1183         StrBufAppendBufPlain(Mime->Data, _("I don't know how to display "), -1, 0);
1184         StrBufAppendBuf(Mime->Data, Mime->ContentType, 0);
1185         StrBufAppendBufPlain(Mime->Data, HKEY("<br>\n"), 0);
1186 }
1187
1188
1189 HashList *iterate_get_mime_All(StrBuf *Target, WCTemplputParams *TP)
1190 {
1191         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
1192         return Msg->Attachments;
1193 }
1194 HashList *iterate_get_mime_Submessages(StrBuf *Target, WCTemplputParams *TP)
1195 {
1196         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
1197         return Msg->Submessages;
1198 }
1199 HashList *iterate_get_mime_AttachLinks(StrBuf *Target, WCTemplputParams *TP)
1200 {
1201         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
1202         return Msg->AttachLinks;
1203 }
1204 HashList *iterate_get_mime_Attachments(StrBuf *Target, WCTemplputParams *TP)
1205 {
1206         message_summary *Msg = (message_summary*) CTX(CTX_MAILSUM);
1207         return Msg->AllAttach;
1208 }
1209
1210 void tmplput_MIME_Name(StrBuf *Target, WCTemplputParams *TP)
1211 {
1212         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1213         StrBufAppendTemplate(Target, TP, mime->Name, 0);
1214 }
1215
1216 void tmplput_MIME_FileName(StrBuf *Target, WCTemplputParams *TP)
1217 {
1218         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1219         StrBufAppendTemplate(Target, TP, mime->FileName, 0);
1220 }
1221
1222 void tmplput_MIME_PartNum(StrBuf *Target, WCTemplputParams *TP)
1223 {
1224         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1225         StrBufAppendTemplate(Target, TP, mime->PartNum, 0);
1226 }
1227
1228 void tmplput_MIME_MsgNum(StrBuf *Target, WCTemplputParams *TP)
1229 {
1230         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1231         StrBufAppendPrintf(Target, "%ld", mime->msgnum);
1232 }
1233
1234 void tmplput_MIME_Disposition(StrBuf *Target, WCTemplputParams *TP)
1235 {
1236         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1237         StrBufAppendTemplate(Target, TP, mime->Disposition, 0);
1238 }
1239
1240 void tmplput_MIME_ContentType(StrBuf *Target, WCTemplputParams *TP)
1241 {
1242         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1243         StrBufAppendTemplate(Target, TP, mime->ContentType, 0);
1244 }
1245
1246 void examine_charset(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
1247 {
1248         Msg->MsgBody->Charset = NewStrBufDup(HdrLine);
1249 }
1250
1251 void tmplput_MIME_Charset(StrBuf *Target, WCTemplputParams *TP)
1252 {
1253         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1254         StrBufAppendTemplate(Target, TP, mime->Charset, 0);
1255 }
1256
1257 void tmplput_MIME_Data(StrBuf *Target, WCTemplputParams *TP)
1258 {
1259         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1260         if (mime->Renderer != NULL)
1261                 mime->Renderer->f(Target, TP, NULL);
1262         StrBufAppendTemplate(Target, TP, mime->Data, 0);
1263         /* TODO: check whether we need to load it now? */
1264 }
1265
1266 void tmplput_MIME_LoadData(StrBuf *Target, WCTemplputParams *TP)
1267 {
1268         wcsession *WCC = WC;    
1269         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1270         wc_mime_attachment *att;
1271         
1272         if (( (!strcasecmp(ChrPtr(mime->Disposition), "inline"))||
1273               (!strcasecmp(ChrPtr(mime->Disposition), "attachment"))) && 
1274             (strcasecmp(ChrPtr(mime->ContentType), "application/ms-tnef")!=0))
1275         {
1276                 
1277                 int n;
1278                 char N[64];
1279                 /* steal this mime part... */
1280                 att = malloc(sizeof(wc_mime_attachment));
1281                 memcpy(att, mime, sizeof(wc_mime_attachment));
1282                 memset(mime, 0, sizeof(wc_mime_attachment));
1283
1284                 if (att->Data == NULL) 
1285                         MimeLoadData(att);
1286
1287                 if (WCC->attachments == NULL)
1288                         WCC->attachments = NewHash(1, NULL);
1289                 /* And add it to the list. */
1290                 n = snprintf(N, sizeof N, "%d", GetCount(WCC->attachments) + 1);
1291                 Put(WCC->attachments, N, n, att, DestroyMime);
1292         }
1293 }
1294
1295 void tmplput_MIME_Length(StrBuf *Target, WCTemplputParams *TP)
1296 {
1297         wc_mime_attachment *mime = (wc_mime_attachment*) CTX(CTX_MIME_ATACH);
1298         StrBufAppendPrintf(Target, "%ld", mime->length);
1299 }
1300
1301 HashList *iterate_get_registered_Attachments(StrBuf *Target, WCTemplputParams *TP)
1302 {
1303         return WC->attachments;
1304 }
1305
1306 void get_registered_Attachments_Count(StrBuf *Target, WCTemplputParams *TP)
1307 {
1308         StrBufAppendPrintf(Target, "%ld", GetCount (WC->attachments));
1309 }
1310
1311 void servcmd_do_search(char *buf, long bufsize)
1312 {
1313         snprintf(buf, bufsize, "MSGS SEARCH|%s", bstr("query"));
1314 }
1315
1316 void servcmd_headers(char *buf, long bufsize)
1317 {
1318         snprintf(buf, bufsize, "MSGS ALL");
1319 }
1320
1321 void servcmd_readfwd(char *buf, long bufsize)
1322 {
1323         snprintf(buf, bufsize, "MSGS ALL");
1324 }
1325
1326 void servcmd_readgt(char *buf, long bufsize)
1327 {
1328         snprintf(buf, bufsize, "MSGS GT|%s", bstr("gt"));
1329 }
1330
1331 void servcmd_readlt(char *buf, long bufsize)
1332 {
1333         snprintf(buf, bufsize, "MSGS LT|%s", bstr("lt"));
1334 }
1335
1336 void servcmd_readnew(char *buf, long bufsize)
1337 {
1338         snprintf(buf, bufsize, "MSGS NEW");
1339 }
1340
1341 void servcmd_readold(char *buf, long bufsize)
1342 {
1343         snprintf(buf, bufsize, "MSGS OLD");
1344 }
1345
1346
1347 /* DO NOT REORDER OR REMOVE ANY OF THESE */
1348 readloop_struct rlid[] = {
1349         { {HKEY("do_search")},  servcmd_do_search       },
1350         { {HKEY("headers")},    servcmd_headers         },
1351         { {HKEY("readfwd")},    servcmd_readfwd         },
1352         { {HKEY("readnew")},    servcmd_readnew         },
1353         { {HKEY("readold")},    servcmd_readold         },
1354         { {HKEY("readgt")},     servcmd_readgt          },
1355         { {HKEY("readlt")},     servcmd_readlt          }
1356 };
1357
1358 const char* fieldMnemonics[] = {
1359         "from", /* A -> eAuthor       */
1360         "exti", /* E -> eXclusivID    */
1361         "rfca", /* F -> erFc822Addr   */
1362         "msgn", /* I -> emessageId    */
1363         "jrnl", /* J -> eJournal      */
1364         "rep2", /* K -> eReplyTo      */
1365         "list", /* L -> eListID       */
1366         "text", /* M -> eMesageText   */
1367         "room", /* O -> eOriginalRoom */
1368         "path", /* P -> eMessagePath  */
1369         "rcpt", /* R -> eRecipient    */
1370         "spec", /* S -> eSpecialField */
1371         "time", /* T -> eTimestamp    */
1372         "subj", /* U -> eMsgSubject   */
1373         "nvto", /* V -> eenVelopeTo   */
1374         "wefw", /* W -> eWeferences   */
1375         "cccc", /* Y -> eCarbonCopY   */
1376         "nhdr", /* % -> eHeaderOnly   */
1377         "type", /* % -> eFormatType   */
1378         "part", /* % -> eMessagePart  */
1379         "suff", /*      eSubFolder    */
1380         "pref", /*      ePrefix       */
1381         "locl"  /*      eIsLocal      */
1382 };
1383 HashList *msgKeyLookup = NULL;
1384
1385
1386 int GetFieldFromMnemonic(eMessageField *f, const char *c) {
1387         void *v = NULL;
1388         if (GetHash(msgKeyLookup, c, 4, &v)) {
1389                 *f = (eMessageField) v;
1390                 return 1;
1391         }
1392         return 0;
1393 }
1394
1395
1396 void FillMsgKeyLookupTable(void) {
1397         long i = 0;
1398
1399         msgKeyLookup = NewHash (1, FourHash);
1400
1401         while (i != eLastHeader) {
1402                 if (fieldMnemonics[i] != NULL) {
1403                         Put(msgKeyLookup, fieldMnemonics[i], 4, (void*)i, reference_free_handler);
1404                 }
1405                 i++;
1406         }
1407 }
1408
1409
1410 void 
1411 InitModule_MSGRENDERERS
1412 (void)
1413 {
1414         RegisterCTX(CTX_MAILSUM);
1415         RegisterCTX(CTX_MIME_ATACH);
1416
1417         RegisterSortFunc(HKEY("date"), 
1418                          NULL, 0,
1419                          summcmp_date,
1420                          summcmp_rdate,
1421                          groupchange_date,
1422                          CTX_MAILSUM);
1423         RegisterSortFunc(HKEY("subject"), 
1424                          NULL, 0,
1425                          summcmp_subj,
1426                          summcmp_rsubj,
1427                          groupchange_subj,
1428                          CTX_MAILSUM);
1429         RegisterSortFunc(HKEY("sender"),
1430                          NULL, 0,
1431                          summcmp_sender,
1432                          summcmp_rsender,
1433                          groupchange_sender,
1434                          CTX_MAILSUM);
1435
1436         RegisterNamespace("SUMM:COUNT", 0, 0, tmplput_SUMM_COUNT, NULL, CTX_NONE);
1437
1438         /* iterate over all known mails in WC->summ */
1439         RegisterIterator("MAIL:SUMM:MSGS", 0, NULL, iterate_get_mailsumm_All, NULL,NULL, CTX_MAILSUM, CTX_NONE, IT_NOFLAG);
1440
1441         RegisterNamespace("MAIL:SUMM:EUID", 0, 1, tmplput_MAIL_SUMM_EUID, NULL, CTX_MAILSUM);
1442         RegisterNamespace("MAIL:SUMM:DATEBRIEF", 0, 0, tmplput_MAIL_SUMM_DATE_BRIEF, NULL, CTX_MAILSUM);
1443         RegisterNamespace("MAIL:SUMM:DATEFULL", 0, 0, tmplput_MAIL_SUMM_DATE_FULL, NULL, CTX_MAILSUM);
1444         RegisterNamespace("MAIL:SUMM:DATENO",  0, 0, tmplput_MAIL_SUMM_DATE_NO,  NULL, CTX_MAILSUM);
1445         RegisterNamespace("MAIL:SUMM:N",       0, 0, tmplput_MAIL_SUMM_N,        NULL, CTX_MAILSUM);
1446         RegisterNamespace("MAIL:SUMM:PERMALINK", 0, 0, tmplput_MAIL_SUMM_PERMALINK, NULL, CTX_MAILSUM);
1447         RegisterNamespace("MAIL:SUMM:FROM",    0, 2, tmplput_MAIL_SUMM_FROM,     NULL, CTX_MAILSUM);
1448         RegisterNamespace("MAIL:SUMM:TO",      0, 2, tmplput_MAIL_SUMM_TO,       NULL, CTX_MAILSUM);
1449         RegisterNamespace("MAIL:SUMM:SUBJECT", 0, 4, tmplput_MAIL_SUMM_SUBJECT,  NULL, CTX_MAILSUM);
1450         RegisterNamespace("MAIL:SUMM:NTATACH", 0, 0, tmplput_MAIL_SUMM_NATTACH,  NULL, CTX_MAILSUM);
1451         RegisterNamespace("MAIL:SUMM:CCCC", 0, 2, tmplput_MAIL_SUMM_CCCC, NULL, CTX_MAILSUM);
1452         RegisterNamespace("MAIL:SUMM:REPLYTO", 0, 2, tmplput_MAIL_SUMM_REPLYTO, NULL, CTX_MAILSUM);
1453         RegisterNamespace("MAIL:SUMM:ALLRCPT", 0, 2, tmplput_MAIL_SUMM_ALLRCPT,  NULL, CTX_MAILSUM);
1454         RegisterNamespace("MAIL:SUMM:ORGROOM", 0, 2, tmplput_MAIL_SUMM_ORGROOM,  NULL, CTX_MAILSUM);
1455         RegisterNamespace("MAIL:SUMM:RFCA", 0, 2, tmplput_MAIL_SUMM_RFCA, NULL, CTX_MAILSUM);
1456         RegisterNamespace("MAIL:SUMM:REFIDS", 0, 1, tmplput_MAIL_SUMM_REFIDS,  NULL, CTX_MAILSUM);
1457         RegisterNamespace("MAIL:SUMM:INREPLYTO", 0, 2, tmplput_MAIL_SUMM_INREPLYTO,  NULL, CTX_MAILSUM);
1458         RegisterNamespace("MAIL:BODY", 0, 2, tmplput_MAIL_BODY,  NULL, CTX_MAILSUM);
1459         RegisterNamespace("MAIL:QUOTETEXT", 1, 2, tmplput_QUOTED_MAIL_BODY,  NULL, CTX_NONE);
1460         RegisterNamespace("MAIL:EDITTEXT", 1, 2, tmplput_EDIT_MAIL_BODY,  NULL, CTX_NONE);
1461         RegisterNamespace("MAIL:EDITWIKI", 1, 2, tmplput_EDIT_WIKI_BODY,  NULL, CTX_NONE);
1462         RegisterConditional("COND:MAIL:SUMM:RFCA", 0, Conditional_MAIL_SUMM_RFCA,  CTX_MAILSUM);
1463         RegisterConditional("COND:MAIL:SUMM:CCCC", 0, Conditional_MAIL_SUMM_CCCC,  CTX_MAILSUM);
1464         RegisterConditional("COND:MAIL:SUMM:REPLYTO", 0, Conditional_MAIL_SUMM_REPLYTO,  CTX_MAILSUM);
1465         RegisterConditional("COND:MAIL:SUMM:UNREAD", 0, Conditional_MAIL_SUMM_UNREAD, CTX_MAILSUM);
1466         RegisterConditional("COND:MAIL:SUMM:SUBJECT", 0, Conditional_MAIL_SUMM_SUBJECT, CTX_MAILSUM);
1467         RegisterConditional("COND:MAIL:ANON", 0, Conditional_ANONYMOUS_MESSAGE, CTX_MAILSUM);
1468         RegisterConditional("COND:MAIL:TO", 0, Conditional_MAIL_SUMM_TO, CTX_MAILSUM);
1469         RegisterConditional("COND:MAIL:SUBJ", 0, Conditional_MAIL_SUMM_SUBJ, CTX_MAILSUM);
1470         RegisterConditional("COND:MAIL:LOCAL", 0, Conditional_MAIL_LOCAL, CTX_MAILSUM);
1471
1472         /* do we have mimetypes to iterate over? */
1473         RegisterConditional("COND:MAIL:MIME:ATTACH", 0, Conditional_MAIL_MIME_ALL, CTX_MAILSUM);
1474         RegisterConditional("COND:MAIL:MIME:ATTACH:SUBMESSAGES", 0, Conditional_MAIL_MIME_SUBMESSAGES, CTX_MAILSUM);
1475         RegisterConditional("COND:MAIL:MIME:ATTACH:LINKS", 0, Conditional_MAIL_MIME_ATTACHLINKS, CTX_MAILSUM);
1476         RegisterConditional("COND:MAIL:MIME:ATTACH:ATT", 0, Conditional_MAIL_MIME_ATTACH, CTX_MAILSUM);
1477         RegisterIterator("MAIL:MIME:ATTACH", 0, NULL, iterate_get_mime_All, NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM, IT_NOFLAG);
1478         RegisterIterator("MAIL:MIME:ATTACH:SUBMESSAGES", 0, NULL, iterate_get_mime_Submessages, NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM, IT_NOFLAG);
1479         RegisterIterator("MAIL:MIME:ATTACH:LINKS", 0, NULL, iterate_get_mime_AttachLinks, NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM, IT_NOFLAG);
1480         RegisterIterator("MAIL:MIME:ATTACH:ATT", 0, NULL, iterate_get_mime_Attachments, NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM, IT_NOFLAG);
1481
1482         /* Parts of a mime attachent */
1483         RegisterNamespace("MAIL:MIME:NAME", 0, 2, tmplput_MIME_Name, NULL, CTX_MIME_ATACH);
1484         RegisterNamespace("MAIL:MIME:FILENAME", 0, 2, tmplput_MIME_FileName, NULL, CTX_MIME_ATACH);
1485         RegisterNamespace("MAIL:MIME:PARTNUM", 0, 2, tmplput_MIME_PartNum, NULL, CTX_MIME_ATACH);
1486         RegisterNamespace("MAIL:MIME:MSGNUM", 0, 2, tmplput_MIME_MsgNum, NULL, CTX_MIME_ATACH);
1487         RegisterNamespace("MAIL:MIME:DISPOSITION", 0, 2, tmplput_MIME_Disposition, NULL, CTX_MIME_ATACH);
1488         RegisterNamespace("MAIL:MIME:CONTENTTYPE", 0, 2, tmplput_MIME_ContentType, NULL, CTX_MIME_ATACH);
1489         RegisterNamespace("MAIL:MIME:CHARSET", 0, 2, tmplput_MIME_Charset, NULL, CTX_MIME_ATACH);
1490         RegisterNamespace("MAIL:MIME:LENGTH", 0, 2, tmplput_MIME_Length, NULL, CTX_MIME_ATACH);
1491         RegisterNamespace("MAIL:MIME:DATA", 0, 2, tmplput_MIME_Data, NULL, CTX_MIME_ATACH);
1492
1493         /* load the actual attachment into WC->attachments; no output!!! */
1494         RegisterNamespace("MAIL:MIME:LOADDATA", 0, 0, tmplput_MIME_LoadData, NULL, CTX_MIME_ATACH);
1495
1496         /* iterate the WC->attachments; use the above tokens for their contents */
1497         RegisterIterator("MSG:ATTACHNAMES", 0, NULL, iterate_get_registered_Attachments, NULL, NULL, CTX_MIME_ATACH, CTX_NONE, IT_NOFLAG);
1498         RegisterNamespace("MSG:NATTACH", 0, 0, get_registered_Attachments_Count,  NULL, CTX_NONE);
1499
1500         /* mime renderers translate an attachment into webcit viewable html text */
1501         RegisterMimeRenderer(HKEY("message/rfc822"), render_MAIL, 0, 150);
1502 //*
1503         RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS, 1, 501);
1504         RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS, 1, 500);
1505 //*/
1506         RegisterMimeRenderer(HKEY("text/x-citadel-variformat"), render_MAIL_variformat, 1, 2);
1507         RegisterMimeRenderer(HKEY("text/plain"), render_MAIL_text_plain, 1, 3);
1508         RegisterMimeRenderer(HKEY("text"), render_MAIL_text_plain, 1, 1);
1509         RegisterMimeRenderer(HKEY("text/x-markdown"), render_MAIL_text_plain, 1, 1);
1510         RegisterMimeRenderer(HKEY("text/html"), render_MAIL_html, 1, 100);
1511         RegisterMimeRenderer(HKEY(""), render_MAIL_UNKNOWN, 0, 0);
1512
1513         /* these headers are citserver replies to MSG4 and friends. one evaluator for each */
1514         RegisterMsgHdr(HKEY("nhdr"), examine_nhdr, 0);
1515         RegisterMsgHdr(HKEY("exti"), examine_exti, 0);
1516         RegisterMsgHdr(HKEY("type"), examine_type, 0);
1517         RegisterMsgHdr(HKEY("from"), examine_from, 0);
1518         RegisterMsgHdr(HKEY("subj"), examine_subj, 0);
1519         RegisterMsgHdr(HKEY("msgn"), examine_msgn, 0);
1520         RegisterMsgHdr(HKEY("wefw"), examine_wefw, 0);
1521         RegisterMsgHdr(HKEY("cccc"), examine_cccc, 0);
1522         RegisterMsgHdr(HKEY("rep2"), examine_replyto, 0);
1523         RegisterMsgHdr(HKEY("room"), examine_room, 0);
1524         RegisterMsgHdr(HKEY("rfca"), examine_rfca, 0);
1525         RegisterMsgHdr(HKEY("rcpt"), examine_rcpt, 0);
1526         RegisterMsgHdr(HKEY("nvto"), examine_nvto, 0);
1527         RegisterMsgHdr(HKEY("time"), examine_time, 0);
1528         RegisterMsgHdr(HKEY("part"), examine_mime_part, 0);
1529         RegisterMsgHdr(HKEY("locl"), examine_locl, 0);
1530         RegisterMsgHdr(HKEY("text"), examine_text, 1);
1531
1532         /* these are the content-type headers we get in front of a message; put it into the same hash since it doesn't clash. */
1533         RegisterMsgHdr(HKEY("X-Citadel-MSG4-Partnum"), examine_msg4_partnum, 0);
1534         RegisterMsgHdr(HKEY("Content-type"), examine_content_type, 0);
1535         RegisterMsgHdr(HKEY("Content-length"), examine_content_lengh, 0);
1536         RegisterMsgHdr(HKEY("Content-transfer-encoding"), examine_content_encoding, 0); /* do we care? */
1537         RegisterMsgHdr(HKEY("charset"), examine_charset, 0);
1538
1539         /* Don't care about these... */
1540         RegisterMsgHdr(HKEY("pref"), examine_pref, 0);
1541         RegisterMsgHdr(HKEY("suff"), examine_suff, 0);
1542         RegisterMsgHdr(HKEY("path"), examine_path, 0);
1543 }
1544
1545 void 
1546 InitModule2_MSGRENDERERS
1547 (void)
1548 {
1549         /* and finalize the anouncement to the server... */
1550         CreateMimeStr();
1551 }
1552 void 
1553 ServerStartModule_MSGRENDERERS
1554 (void)
1555 {
1556         DflMsgHeaderHandler = NewHash (1, FourHash);
1557         DflEnumMsgHeaderHandler = NewHash (1, Flathash);
1558         MsgHeaderHandler = NewHash(1, NULL);
1559         MimeRenderHandler = NewHash(1, NULL);
1560         ReadLoopHandler = NewHash(1, NULL);
1561         FillMsgKeyLookupTable();
1562 }
1563
1564 void 
1565 ServerShutdownModule_MSGRENDERERS
1566 (void)
1567 {
1568         DeleteHash(&DflMsgHeaderHandler);
1569         DeleteHash(&DflEnumMsgHeaderHandler);
1570
1571
1572         DeleteHash(&MsgHeaderHandler);
1573         DeleteHash(&MimeRenderHandler);
1574         DeleteHash(&ReadLoopHandler);
1575         DeleteHash(&msgKeyLookup);
1576 }
1577
1578 void 
1579 SessionDestroyModule_MSGRENDERERS
1580 (wcsession *sess)
1581 {
1582         DeleteHash(&sess->attachments);
1583         FreeStrBuf(&sess->ConvertBuf1);
1584         FreeStrBuf(&sess->ConvertBuf2);
1585 }