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