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