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