* ignore path/suff/pref headers.
[citadel.git] / webcit / msg_renderers.c
1 /*----------------------------------------------------------------------------*/
2 #include "webcit.h"
3 #include "webserver.h"
4
5 /**
6  * message index functions
7  */
8
9 void DestroyMimeParts(wc_mime_attachment *Mime)
10 {
11         FreeStrBuf(&Mime->Name);
12         FreeStrBuf(&Mime->FileName);
13         FreeStrBuf(&Mime->PartNum);
14         FreeStrBuf(&Mime->Disposition);
15         FreeStrBuf(&Mime->ContentType);
16         FreeStrBuf(&Mime->Charset);
17         FreeStrBuf(&Mime->Data);
18 }
19
20 void DestroyMime(void *vMime)
21 {
22         wc_mime_attachment *Mime = (wc_mime_attachment*)vMime;
23         DestroyMimeParts(Mime);
24         free(Mime);
25 }
26
27 void DestroyMessageSummary(void *vMsg)
28 {
29         message_summary *Msg = (message_summary*) vMsg;
30
31         FreeStrBuf(&Msg->from);
32         FreeStrBuf(&Msg->to);
33         FreeStrBuf(&Msg->subj);
34         FreeStrBuf(&Msg->reply_inreplyto);
35         FreeStrBuf(&Msg->reply_references);
36         FreeStrBuf(&Msg->cccc);
37         FreeStrBuf(&Msg->hnod);
38         FreeStrBuf(&Msg->AllRcpt);
39         FreeStrBuf(&Msg->Room);
40         FreeStrBuf(&Msg->Rfca);
41         FreeStrBuf(&Msg->OtherNode);
42
43         FreeStrBuf(&Msg->reply_to);
44
45         DeleteHash(&Msg->Attachments);  /**< list of Accachments */
46         DeleteHash(&Msg->Submessages);
47         DeleteHash(&Msg->AttachLinks);
48         DeleteHash(&Msg->AllAttach);
49         free(Msg);
50 }
51
52
53
54 void RegisterMsgHdr(const char *HeaderName, long HdrNLen, ExamineMsgHeaderFunc evaluator, int type)
55 {
56         headereval *ev;
57         ev = (headereval*) malloc(sizeof(headereval));
58         ev->evaluator = evaluator;
59         ev->Type = type;
60         Put(MsgHeaderHandler, HeaderName, HdrNLen, ev, NULL);
61 }
62
63 void RegisterMimeRenderer(const char *HeaderName, long HdrNLen, RenderMimeFunc MimeRenderer)
64 {
65         Put(MimeRenderHandler, HeaderName, HdrNLen, MimeRenderer, reference_free_handler);
66         
67 }
68
69 /*----------------------------------------------------------------------------*/
70
71 /*
72  * qsort() compatible function to compare two longs in descending order.
73  */
74 int longcmp_r(const void *s1, const void *s2) {
75         long l1;
76         long l2;
77
78         l1 = *(long *)GetSearchPayload(s1);
79         l2 = *(long *)GetSearchPayload(s2);
80
81         if (l1 > l2) return(-1);
82         if (l1 < l2) return(+1);
83         return(0);
84 }
85
86 /*
87  * qsort() compatible function to compare two longs in descending order.
88  */
89 int qlongcmp_r(const void *s1, const void *s2) {
90         long l1 = (long) s1;
91         long l2 = (long) s2;
92
93         if (l1 > l2) return(-1);
94         if (l1 < l2) return(+1);
95         return(0);
96 }
97
98  
99 /*
100  * qsort() compatible function to compare two message summary structs by ascending subject.
101  */
102 int summcmp_subj(const void *s1, const void *s2) {
103         message_summary *summ1;
104         message_summary *summ2;
105         
106         summ1 = (message_summary *)GetSearchPayload(s1);
107         summ2 = (message_summary *)GetSearchPayload(s2);
108         return strcasecmp(ChrPtr(summ1->subj), ChrPtr(summ2->subj));
109 }
110
111 /*
112  * qsort() compatible function to compare two message summary structs by descending subject.
113  */
114 int summcmp_rsubj(const void *s1, const void *s2) {
115         message_summary *summ1;
116         message_summary *summ2;
117         
118         summ1 = (message_summary *)GetSearchPayload(s1);
119         summ2 = (message_summary *)GetSearchPayload(s2);
120         return strcasecmp(ChrPtr(summ2->subj), ChrPtr(summ1->subj));
121 }
122
123 /*
124  * qsort() compatible function to compare two message summary structs by ascending sender.
125  */
126 int summcmp_sender(const void *s1, const void *s2) {
127         message_summary *summ1;
128         message_summary *summ2;
129         
130         summ1 = (message_summary *)GetSearchPayload(s1);
131         summ2 = (message_summary *)GetSearchPayload(s2);
132         return strcasecmp(ChrPtr(summ1->from), ChrPtr(summ2->from));
133 }
134
135 /*
136  * qsort() compatible function to compare two message summary structs by descending sender.
137  */
138 int summcmp_rsender(const void *s1, const void *s2) {
139         message_summary *summ1;
140         message_summary *summ2;
141         
142         summ1 = (message_summary *)GetSearchPayload(s1);
143         summ2 = (message_summary *)GetSearchPayload(s2);
144         return strcasecmp(ChrPtr(summ2->from), ChrPtr(summ1->from));
145 }
146
147 /*
148  * qsort() compatible function to compare two message summary structs by ascending date.
149  */
150 int summcmp_date(const void *s1, const void *s2) {
151         message_summary *summ1;
152         message_summary *summ2;
153         
154         summ1 = (message_summary *)GetSearchPayload(s1);
155         summ2 = (message_summary *)GetSearchPayload(s2);
156
157         if (summ1->date < summ2->date) return -1;
158         else if (summ1->date > summ2->date) return +1;
159         else return 0;
160 }
161
162 /*
163  * qsort() compatible function to compare two message summary structs by descending date.
164  */
165 int summcmp_rdate(const void *s1, const void *s2) {
166         message_summary *summ1;
167         message_summary *summ2;
168         
169         summ1 = (message_summary *)GetSearchPayload(s1);
170         summ2 = (message_summary *)GetSearchPayload(s2);
171
172         if (summ1->date < summ2->date) return +1;
173         else if (summ1->date > summ2->date) return -1;
174         else return 0;
175 }
176
177 /*----------------------------------------------------------------------------*/
178 /* Don't wanna know... or? */
179 void examine_pref(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
180 void examine_suff(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
181 void examine_path(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset) {return;}
182
183 void examine_nhdr(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
184 {
185         Msg->nhdr = 0;
186         if (!strncasecmp(ChrPtr(HdrLine), "yes", 8))
187                 Msg->nhdr = 1;
188 }
189 int Conditional_ANONYMOUS_MESSAGE(WCTemplateToken *Tokens, void *Context, int ContextType)
190 {
191         message_summary *Msg = (message_summary*) Context;
192         return Msg->nhdr != 0;
193 }
194
195
196 void examine_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
197 {
198         Msg->format_type = StrToi(HdrLine);
199                         
200 }
201
202 void examine_from(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
203 {
204         FreeStrBuf(&Msg->from);
205         Msg->from = NewStrBufPlain(NULL, StrLength(HdrLine));
206         StrBuf_RFC822_to_Utf8(Msg->from, HdrLine, WC->DefaultCharset, FoundCharset);
207 }
208 void tmplput_MAIL_SUMM_FROM(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
209 {
210         message_summary *Msg = (message_summary*) Context;
211         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->from, 0);
212 }
213
214
215
216 void examine_subj(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
217 {
218         FreeStrBuf(&Msg->subj);
219         Msg->subj = NewStrBufPlain(NULL, StrLength(HdrLine));
220         StrBuf_RFC822_to_Utf8(Msg->subj, HdrLine, WC->DefaultCharset, FoundCharset);
221 }
222 void tmplput_MAIL_SUMM_SUBJECT(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
223 {/////TODO: Fwd: and RE: filter!!
224         message_summary *Msg = (message_summary*) Context;
225         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->subj, 0);
226 }
227
228
229 void examine_msgn(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
230 {
231         FreeStrBuf(&Msg->reply_inreplyto);
232         Msg->reply_inreplyto = NewStrBufPlain(NULL, StrLength(HdrLine));
233         StrBuf_RFC822_to_Utf8(Msg->reply_inreplyto, HdrLine, WC->DefaultCharset, FoundCharset);
234 }
235 void tmplput_MAIL_SUMM_INREPLYTO(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
236 {
237         message_summary *Msg = (message_summary*) Context;
238         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->reply_inreplyto, 0);
239 }
240
241 int Conditional_MAIL_SUMM_UNREAD(WCTemplateToken *Tokens, void *Context, int ContextType)
242 {
243         message_summary *Msg = (message_summary*) Context;
244         return Msg->is_new != 0;
245 }
246
247 void examine_wefw(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
248 {
249         FreeStrBuf(&Msg->reply_references);
250         Msg->reply_references = NewStrBufPlain(NULL, StrLength(HdrLine));
251         StrBuf_RFC822_to_Utf8(Msg->reply_references, HdrLine, WC->DefaultCharset, FoundCharset);
252 }
253 void tmplput_MAIL_SUMM_REFIDS(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
254 {
255         message_summary *Msg = (message_summary*) Context;
256         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->reply_references, 0);
257 }
258
259
260 void examine_cccc(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
261 {
262         FreeStrBuf(&Msg->cccc);
263         Msg->cccc = NewStrBufPlain(NULL, StrLength(HdrLine));
264         StrBuf_RFC822_to_Utf8(Msg->cccc, HdrLine, WC->DefaultCharset, FoundCharset);
265         if (Msg->AllRcpt == NULL)
266                 Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
267         if (StrLength(Msg->AllRcpt) > 0) {
268                 StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
269         }
270         StrBufAppendBuf(Msg->AllRcpt, Msg->cccc, 0);
271 }
272 void tmplput_MAIL_SUMM_CCCC(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
273 {
274         message_summary *Msg = (message_summary*) Context;
275         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->cccc, 0);
276 }
277
278
279
280
281 void examine_room(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
282 {
283         if ((StrLength(HdrLine) > 0) &&
284             (strcasecmp(ChrPtr(HdrLine), WC->wc_roomname))) {
285                 FreeStrBuf(&Msg->Room);
286                 Msg->Room = NewStrBufDup(HdrLine);              
287         }
288 }
289 void tmplput_MAIL_SUMM_ORGROOM(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
290 {
291         message_summary *Msg = (message_summary*) Context;
292         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->Room, 0);
293 }
294
295
296 void examine_rfca(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
297 {
298         FreeStrBuf(&Msg->Rfca);
299         Msg->Rfca = NewStrBufDup(HdrLine);
300 }
301 void tmplput_MAIL_SUMM_RFCA(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
302 {
303         message_summary *Msg = (message_summary*) Context;
304         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->Rfca, 0);
305 }
306 int Conditional_MAIL_SUMM_RFCA(WCTemplateToken *Tokens, void *Context, int ContextType)
307 {
308         message_summary *Msg = (message_summary*) Context;
309         return StrLength(Msg->Rfca) > 0;
310 }
311
312 void examine_node(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
313 {
314         if ( (StrLength(HdrLine) > 0) &&
315              ((WC->room_flags & QR_NETWORK)
316               || ((strcasecmp(ChrPtr(HdrLine), serv_info.serv_nodename)
317                    && (strcasecmp(ChrPtr(HdrLine), serv_info.serv_fqdn)))))) {
318                 FreeStrBuf(&Msg->OtherNode);
319                 Msg->OtherNode = NewStrBufDup(HdrLine);
320         }
321 }
322 void tmplput_MAIL_SUMM_OTHERNODE(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
323 {
324         message_summary *Msg = (message_summary*) Context;
325         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->OtherNode, 0);
326 }
327 int Conditional_MAIL_SUMM_OTHERNODE(WCTemplateToken *Tokens, void *Context, int ContextType)
328 {
329         message_summary *Msg = (message_summary*) Context;
330         return StrLength(Msg->OtherNode) > 0;
331 }
332
333
334 void examine_rcpt(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
335 {
336         FreeStrBuf(&Msg->to);
337         Msg->to = NewStrBufPlain(NULL, StrLength(HdrLine));
338         StrBuf_RFC822_to_Utf8(Msg->to, HdrLine, WC->DefaultCharset, FoundCharset);
339         if (Msg->AllRcpt == NULL)
340                 Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
341         if (StrLength(Msg->AllRcpt) > 0) {
342                 StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
343         }
344         StrBufAppendBuf(Msg->AllRcpt, Msg->to, 0);
345 }
346 void tmplput_MAIL_SUMM_TO(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
347 {
348         message_summary *Msg = (message_summary*) Context;
349         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->to, 0);
350 }
351 void tmplput_MAIL_SUMM_ALLRCPT(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
352 {
353         message_summary *Msg = (message_summary*) Context;
354         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->AllRcpt, 0);
355 }
356
357
358
359 void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
360 {
361         Msg->date = StrTol(HdrLine);
362 }
363 void tmplput_MAIL_SUMM_DATE_STR(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
364 {
365         char datebuf[64];
366         message_summary *Msg = (message_summary*) Context;
367         webcit_fmt_date(datebuf, Msg->date, 1);
368         StrBufAppendBufPlain(Target, datebuf, -1, 0);
369 }
370 void tmplput_MAIL_SUMM_DATE_NO(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
371 {
372         message_summary *Msg = (message_summary*) Context;
373         StrBufAppendPrintf(Target, "%ld", Msg->date, 0);
374 }
375
376
377
378 void render_MAIL(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
379 {
380         Mime->Data = NewStrBufPlain(NULL, Mime->length);
381         read_message(Mime->Data, HKEY("view_submessage"), Mime->msgnum, 0, Mime->PartNum);
382 /*
383         if ( (!IsEmptyStr(mime_submessages)) && (!section[0]) ) {
384                 for (i=0; i<num_tokens(mime_submessages, '|'); ++i) {
385                         extract_token(buf, mime_submessages, i, '|', sizeof buf);
386                         / ** use printable_view to suppress buttons * /
387                         wprintf("<blockquote>");
388                         read_message(Mime->msgnum, 1, ChrPtr(Mime->Section));
389                         wprintf("</blockquote>");
390                 }
391         }
392 */
393 }
394
395 void render_MIME_VCard(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
396 {
397         MimeLoadData(Mime);
398         if (StrLength(Mime->Data) > 0) {
399                 StrBuf *Buf;
400                 Buf = NewStrBuf();
401                 /** If it's my vCard I can edit it */
402                 if (    (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
403                         || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
404                         || (WC->wc_view == VIEW_ADDRESSBOOK)
405                         ) {
406                         StrBufAppendPrintf(Buf, "<a href=\"edit_vcard?msgnum=%ld&partnum=%s\">",
407                                 Mime->msgnum, ChrPtr(Mime->PartNum));
408                         StrBufAppendPrintf(Buf, "[%s]</a>", _("edit"));
409                 }
410
411                 /* In all cases, display the full card */
412                 display_vcard(Buf, ChrPtr(Mime->Data), 0, 1, NULL, Mime->msgnum);
413                 FreeStrBuf(&Mime->Data);
414                 Mime->Data = Buf;
415         }
416
417 }
418 void render_MIME_ICS(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
419 {
420         MimeLoadData(Mime);
421         if (StrLength(Mime->Data) > 0) {
422                 cal_process_attachment(Mime);
423         }
424 }
425
426
427
428 void examine_mime_part(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
429 {
430         wc_mime_attachment *Mime;
431         StrBuf *Buf;
432         
433         Mime = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
434         memset(Mime, 0, sizeof(wc_mime_attachment));
435         Mime->msgnum = Msg->msgnum;
436         Buf = NewStrBuf();
437
438         Mime->Name = NewStrBuf();
439         StrBufExtract_token(Buf, HdrLine, 0, '|');
440         StrBuf_RFC822_to_Utf8(Mime->Name, Buf, WC->DefaultCharset, FoundCharset);
441         StrBufTrim(Mime->Name);
442
443         StrBufExtract_token(Buf, HdrLine, 1, '|');
444         Mime->FileName = NewStrBuf();
445         StrBuf_RFC822_to_Utf8(Mime->FileName, Buf, WC->DefaultCharset, FoundCharset);
446         StrBufTrim(Mime->FileName);
447
448         Mime->PartNum = NewStrBuf();
449         StrBufExtract_token(Mime->PartNum, HdrLine, 2, '|');
450         StrBufTrim(Mime->PartNum);
451         if (strchr(ChrPtr(Mime->PartNum), '.') != NULL)
452                 Mime->level = 2;
453         else
454                 Mime->level = 1;
455
456         Mime->Disposition = NewStrBuf();
457         StrBufExtract_token(Mime->Disposition, HdrLine, 3, '|');
458
459         Mime->ContentType = NewStrBuf();
460         StrBufExtract_token(Mime->ContentType, HdrLine, 4, '|');
461         StrBufTrim(Mime->ContentType);
462         StrBufLowerCase(Mime->ContentType);
463
464         Mime->length = StrBufExtract_int(HdrLine, 5, '|');
465
466         if ( (StrLength(Mime->FileName) == 0) && (StrLength(Mime->Name) > 0) ) {
467                 StrBufAppendBuf(Mime->FileName, Mime->Name, 0);
468         }
469
470         if (StrLength(Msg->PartNum) > 0) {
471                 StrBuf *tmp;
472                 StrBufPrintf(Buf, "%s.%s", ChrPtr(Msg->PartNum), ChrPtr(Mime->PartNum));
473                 tmp = Mime->PartNum;
474                 Mime->PartNum = Buf;
475                 Buf = tmp;
476         }
477
478         if (Msg->AllAttach == NULL)
479                 Msg->AllAttach = NewHash(1,NULL);
480         Put(Msg->AllAttach, SKEY(Mime->PartNum), Mime, DestroyMime);
481         FreeStrBuf(&Buf);
482 }
483
484
485 void evaluate_mime_part(message_summary *Msg, wc_mime_attachment *Mime)
486 {
487         void *vMimeRenderer;
488
489         /* just print the root-node */
490         if ((Mime->level == 1) &&
491             GetHash(MimeRenderHandler, SKEY(Mime->ContentType), &vMimeRenderer) &&
492             vMimeRenderer != NULL)
493         {
494                 Mime->Renderer = (RenderMimeFunc) vMimeRenderer;
495                 if (Msg->Submessages == NULL)
496                         Msg->Submessages = NewHash(1,NULL);
497                 Put(Msg->Submessages, SKEY(Mime->PartNum), Mime, reference_free_handler);
498         }
499         else if ((Mime->level == 1) &&
500                  (!strcasecmp(ChrPtr(Mime->Disposition), "inline"))
501                  && (!strncasecmp(ChrPtr(Mime->ContentType), "image/", 6)) ){
502                 if (Msg->AttachLinks == NULL)
503                         Msg->AttachLinks = NewHash(1,NULL);
504                 Put(Msg->AttachLinks, SKEY(Mime->PartNum), Mime, reference_free_handler);
505         }
506         else if ((Mime->level == 1) &&
507                  (StrLength(Mime->ContentType) > 0) &&
508                   ( (!strcasecmp(ChrPtr(Mime->Disposition), "attachment")) 
509                     || (!strcasecmp(ChrPtr(Mime->Disposition), "inline"))
510                     || (!strcasecmp(ChrPtr(Mime->Disposition), ""))))
511         {               
512                 if (Msg->AttachLinks == NULL)
513                         Msg->AttachLinks = NewHash(1,NULL);
514                 Put(Msg->AttachLinks, SKEY(Mime->PartNum), Mime, reference_free_handler);
515                 if ((strcasecmp(ChrPtr(Mime->ContentType), "application/octet-stream") == 0) && 
516                     (StrLength(Mime->FileName) > 0)) {
517                         FlushStrBuf(Mime->ContentType);
518                         StrBufAppendBufPlain(Mime->ContentType,
519                                              GuessMimeByFilename(SKEY(Mime->FileName)),
520                                              -1, 0);
521                 }
522         }
523 }
524
525 void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
526 {
527         message_summary *Msg = (message_summary*) Context;
528         StrBufAppendPrintf(Target, "%ld", GetCount(Msg->Attachments));
529 }
530
531
532
533
534
535
536
537 void examine_hnod(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
538 {
539         FreeStrBuf(&Msg->hnod);
540         Msg->hnod = NewStrBufPlain(NULL, StrLength(HdrLine));
541         StrBuf_RFC822_to_Utf8(Msg->hnod, HdrLine, WC->DefaultCharset, FoundCharset);
542 }
543 void tmplput_MAIL_SUMM_H_NODE(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
544 {
545         message_summary *Msg = (message_summary*) Context;
546         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->hnod, 0);
547 }
548 int Conditional_MAIL_SUMM_H_NODE(WCTemplateToken *Tokens, void *Context, int ContextType)
549 {
550         message_summary *Msg = (message_summary*) Context;
551         return StrLength(Msg->hnod) > 0;
552 }
553
554
555
556 void examine_text(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
557 {
558         Msg->MsgBody->Data = NewStrBuf();
559 }
560
561 void examine_msg4_partnum(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
562 {
563         Msg->MsgBody->PartNum = NewStrBufDup(HdrLine);
564         StrBufTrim(Msg->MsgBody->PartNum);/////TODO: striplt == trim?
565 }
566
567 void examine_content_encoding(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
568 {
569 ////TODO: do we care?
570 }
571
572 void examine_content_lengh(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
573 {
574         Msg->MsgBody->length = StrTol(HdrLine);
575         Msg->MsgBody->size_known = 1;
576 }
577
578 void examine_content_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
579 {
580         void *vHdr;
581         headereval *Hdr;
582         StrBuf *Token;
583         StrBuf *Value;
584         const char* sem;
585         const char *eq;
586         int len;
587         StrBufTrim(HdrLine);
588         Msg->MsgBody->ContentType = NewStrBufDup(HdrLine);
589         sem = strchr(ChrPtr(HdrLine), ';');
590
591         if (sem != NULL) {
592                 Token = NewStrBufPlain(NULL, StrLength(HdrLine));
593                 Value = NewStrBufPlain(NULL, StrLength(HdrLine));
594                 len = sem - ChrPtr(HdrLine);
595                 StrBufCutAt(Msg->MsgBody->ContentType, len, NULL);
596                 while (sem != NULL) {
597                         while (isspace(*(sem + 1)))
598                                 sem ++;
599                         StrBufCutLeft(HdrLine, sem - ChrPtr(HdrLine));
600                         sem = strchr(ChrPtr(HdrLine), ';');
601                         if (sem != NULL)
602                                 len = sem - ChrPtr(HdrLine);
603                         else
604                                 len = StrLength(HdrLine);
605                         FlushStrBuf(Token);
606                         FlushStrBuf(Value);
607                         StrBufAppendBufPlain(Token, ChrPtr(HdrLine), len, 0);
608                         eq = strchr(ChrPtr(Token), '=');
609                         if (eq != NULL) {
610                                 len = eq - ChrPtr(Token);
611                                 StrBufAppendBufPlain(Value, eq + 1, StrLength(Token) - len - 1, 0); 
612                                 StrBufCutAt(Token, len, NULL);
613                                 StrBufTrim(Value);
614                         }
615                         StrBufTrim(Token);
616
617                         if (GetHash(MsgHeaderHandler, SKEY(Token), &vHdr) &&
618                             (vHdr != NULL)) {
619                                 Hdr = (headereval*)vHdr;
620                                 Hdr->evaluator(Msg, Value, FoundCharset);
621                         }
622                         else lprintf(1, "don't know how to handle content type sub-header[%s]\n", ChrPtr(Token));
623                 }
624                 FreeStrBuf(&Token);
625                 FreeStrBuf(&Value);
626         }
627 }
628
629 void tmplput_MAIL_SUMM_N(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
630 {
631         message_summary *Msg = (message_summary*) Context;
632         StrBufAppendPrintf(Target, "%ld", Msg->msgnum);
633 }
634
635
636
637 int Conditional_MAIL_MIME_ALL(WCTemplateToken *Tokens, void *Context, int ContextType)
638 {
639         message_summary *Msg = (message_summary*) Context;
640         return GetCount(Msg->Attachments) > 0;
641 }
642
643 int Conditional_MAIL_MIME_SUBMESSAGES(WCTemplateToken *Tokens, void *Context, int ContextType)
644 {
645         message_summary *Msg = (message_summary*) Context;
646         return GetCount(Msg->Submessages) > 0;
647 }
648
649 int Conditional_MAIL_MIME_ATTACHLINKS(WCTemplateToken *Tokens, void *Context, int ContextType)
650 {
651         message_summary *Msg = (message_summary*) Context;
652         return GetCount(Msg->AttachLinks) > 0;
653 }
654
655 int Conditional_MAIL_MIME_ATTACH(WCTemplateToken *Tokens, void *Context, int ContextType)
656 {
657         message_summary *Msg = (message_summary*) Context;
658         return GetCount(Msg->AllAttach) > 0;
659 }
660
661
662
663 /*----------------------------------------------------------------------------*/
664 void tmplput_QUOTED_MAIL_BODY(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
665 {
666         long MsgNum;
667         StrBuf *Buf;
668
669         MsgNum = LBstr(Tokens->Params[0]->Start, Tokens->Params[0]->len);
670         Buf = NewStrBuf();
671         read_message(Buf, HKEY("view_message_replyquote"), MsgNum, 0, NULL);
672         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Buf, 1);
673         FreeStrBuf(&Buf);
674 }
675
676 void tmplput_MAIL_BODY(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
677 {
678         message_summary *Msg = (message_summary*) Context;
679         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, Msg->MsgBody->Data, 0);
680 }
681
682
683 void render_MAIL_variformat(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
684 {
685         /* Messages in legacy Citadel variformat get handled thusly... */
686         StrBuf *Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
687         FmOut(Target, "JUSTIFY", Mime->Data);
688         FreeStrBuf(&Mime->Data);
689         Mime->Data = Target;
690 }
691
692 void render_MAIL_text_plain(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
693 {
694         StrBuf *cs = NULL;
695         const char *ptr, *pte;
696         const char *BufPtr = NULL;
697         StrBuf *Line;
698         StrBuf *Line1;
699         StrBuf *Line2;
700         StrBuf *Target;
701
702         int ConvertIt = 1;
703         int bn = 0;
704         int bq = 0;
705         int i, n, done = 0;
706         long len;
707 #ifdef HAVE_ICONV
708         iconv_t ic = (iconv_t)(-1) ;
709 #endif
710
711         if ((StrLength(Mime->Data) == 0) && (Mime->length > 0)) {
712                 FreeStrBuf(&Mime->Data);
713                 Mime->Data = NewStrBufPlain(NULL, Mime->length);
714                 if (!read_message(Mime->Data, HKEY("view_submessage"), Mime->msgnum, 0, Mime->PartNum))
715                         return;
716         }
717
718         /* Boring old 80-column fixed format text gets handled this way... */
719         if ((strcasecmp(ChrPtr(Mime->Charset), "us-ascii") == 0) &&
720             (strcasecmp(ChrPtr(Mime->Charset), "UTF-8") == 0))
721                 ConvertIt = 0;
722
723 #ifdef HAVE_ICONV
724         if (ConvertIt) {
725                 if (StrLength(Mime->Charset) != 0)
726                         cs = Mime->Charset;
727                 else if (StrLength(FoundCharset) > 0)
728                         cs = FoundCharset;
729                 else if (StrLength(WC->DefaultCharset) > 0)
730                         cs = WC->DefaultCharset;
731                 if (cs == NULL) {
732                         ConvertIt = 0;
733                 }
734                 else {
735                         ctdl_iconv_open("UTF-8", ChrPtr(cs), &ic);
736                         if (ic == (iconv_t)(-1) ) {
737                                 lprintf(5, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
738                                         __FILE__, __LINE__, ChrPtr(Mime->Charset), strerror(errno));
739                         }
740                 }
741         }
742 #endif
743         Line = NewStrBuf();
744         Line1 = NewStrBuf();
745         Line2 = NewStrBuf();
746         Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
747
748         while ((n = StrBufSipLine(Line, Mime->Data, &BufPtr), n >= 0) && !done)
749         {
750                 done = n == 0;
751                 bq = 0;
752                 i = 0;
753                 ptr = ChrPtr(Line);
754                 len = StrLength(Line);
755                 pte = ptr + len;
756                 
757                 while ((ptr < pte) &&
758                        ((*ptr == '>') ||
759                         isspace(*ptr)))
760                 {
761                         if (*ptr == '>')
762                                 bq++;
763                         ptr ++;
764                         i++;
765                 }
766                 if (i > 0) StrBufCutLeft(Line, i);
767                 
768                 if (StrLength(Line) == 0)
769                         continue;
770
771                 for (i = bn; i < bq; i++)                               
772                         StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
773                 for (i = bq; i < bn; i++)                               
774                         StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
775
776                 if (ConvertIt == 1) {
777                         StrBufConvert(Line, Line1, &ic);
778                 }
779
780                 StrBufAppendBufPlain(Target, HKEY("<tt>"), 0);
781                 UrlizeText(Line1, Line, Line2);
782
783                 StrEscAppend(Target, Line1, NULL, 0, 0);
784                 StrBufAppendBufPlain(Target, HKEY("</tt><br />\n"), 0);
785                 bn = bq;
786         }
787
788         for (i = 0; i < bn; i++)                                
789                 StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
790
791         StrBufAppendBufPlain(Target, HKEY("</i><br />"), 0);
792 #ifdef HAVE_ICONV
793         if (ic != (iconv_t)(-1) ) {
794                 iconv_close(ic);
795         }
796 #endif
797         FreeStrBuf(&Mime->Data);
798         Mime->Data = Target;
799         FreeStrBuf(&Line);
800         FreeStrBuf(&Line1);
801         FreeStrBuf(&Line2);
802 }
803
804 void render_MAIL_html(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
805 {
806         StrBuf *Buf;
807         /* HTML is fun, but we've got to strip it first */
808         if (StrLength(Mime->Data) == 0)
809                 return;
810
811         Buf = NewStrBufPlain(NULL, StrLength(Mime->Data));
812
813         output_html(ChrPtr(Mime->Charset), 
814                     (WC->wc_view == VIEW_WIKI ? 1 : 0), 
815                     StrToi(Mime->PartNum), 
816                     Mime->Data, Buf);
817         FreeStrBuf(&Mime->Data);
818         Mime->Data = Buf;
819 }
820
821 void render_MAIL_UNKNOWN(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
822 {
823         /* Unknown weirdness */
824         FlushStrBuf(Mime->Data);
825         StrBufAppendBufPlain(Mime->Data, _("I don't know how to display "), -1, 0);
826         StrBufAppendBuf(Mime->Data, Mime->ContentType, 0);
827         StrBufAppendBufPlain(Mime->Data, HKEY("<br />\n"), 0);
828 }
829
830
831
832
833
834
835 HashList *iterate_get_mime_All(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
836 {
837         message_summary *Msg = (message_summary*) Context;
838         return Msg->Attachments;
839 }
840 HashList *iterate_get_mime_Submessages(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
841 {
842         message_summary *Msg = (message_summary*) Context;
843         return Msg->Submessages;
844 }
845 HashList *iterate_get_mime_AttachLinks(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
846 {
847         message_summary *Msg = (message_summary*) Context;
848         return Msg->AttachLinks;
849 }
850 HashList *iterate_get_mime_Attachments(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
851 {
852         message_summary *Msg = (message_summary*) Context;
853         return Msg->AllAttach;
854 }
855
856 void tmplput_MIME_Name(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
857 {
858         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
859         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->Name, 0);
860 }
861
862 void tmplput_MIME_FileName(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
863 {
864         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
865         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->FileName, 0);
866 }
867
868 void tmplput_MIME_PartNum(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
869 {
870         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
871         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->PartNum, 0);
872 }
873
874 void tmplput_MIME_MsgNum(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
875 {
876         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
877         StrBufAppendPrintf(Target, "%ld", mime->msgnum);
878 }
879
880 void tmplput_MIME_Disposition(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
881 {
882         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
883         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->Disposition, 0);
884 }
885
886 void tmplput_MIME_ContentType(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
887 {
888         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
889         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->ContentType, 0);
890 }
891
892 void examine_charset(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
893 {
894         Msg->MsgBody->Charset = NewStrBufDup(HdrLine);
895 }
896
897 void tmplput_MIME_Charset(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
898 {
899         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
900         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->Charset, 0);
901 }
902
903 void tmplput_MIME_Data(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
904 {
905         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
906         if (mime->Renderer != NULL)
907                 mime->Renderer(mime, NULL, NULL);
908         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, mime->Data, 0);
909  /// TODO: check whether we need to load it now?
910 }
911
912 void tmplput_MIME_Length(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
913 {
914         wc_mime_attachment *mime = (wc_mime_attachment*) Context;
915         StrBufAppendPrintf(Target, "%ld", mime->length);
916 }
917
918 HashList *iterate_get_registered_Attachments(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
919 {
920         return WC->attachments;
921 }
922
923 void tmplput_ATT_Length(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
924 {
925         wc_attachment *att = (wc_attachment*) Context;
926         StrBufAppendPrintf(Target, "%ld", att->length);
927 }
928
929 void tmplput_ATT_Contenttype(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
930 {
931         wc_attachment *att = (wc_attachment*) Context;
932         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, att->content_type, 0);
933 }
934
935 void tmplput_ATT_FileName(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
936 {
937         wc_attachment *att = (wc_attachment*) Context;
938         StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, att->filename, 0);
939 }
940
941
942 void servcmd_do_search(char *buf, long bufsize)
943 {
944         snprintf(buf, bufsize, "MSGS SEARCH|%s", bstr("query"));
945 }
946
947 void servcmd_headers(char *buf, long bufsize)
948 {
949         snprintf(buf, bufsize, "MSGS ALL");
950 }
951
952 void servcmd_readfwd(char *buf, long bufsize)
953 {
954         snprintf(buf, bufsize, "MSGS ALL");
955 }
956
957 void servcmd_readnew(char *buf, long bufsize)
958 {
959         snprintf(buf, bufsize, "MSGS NEW");
960 }
961
962 void servcmd_readold(char *buf, long bufsize)
963 {
964         snprintf(buf, bufsize, "MSGS OLD");
965 }
966
967
968 readloop_struct rlid[] = {
969         { {HKEY("do_search")}, servcmd_do_search},
970         { {HKEY("headers")},   servcmd_headers},
971         { {HKEY("readfwd")},   servcmd_readfwd},
972         { {HKEY("readnew")},   servcmd_readnew},
973         { {HKEY("readold")},   servcmd_readold}
974 };
975
976
977
978
979                 
980
981
982
983
984 void 
985 InitModule_MSGRENDERERS
986 (void)
987 {
988         RegisterSortFunc(HKEY("date"), 
989                          NULL, 0,
990                          summcmp_date,
991                          summcmp_rdate,
992                          CTX_MAILSUM);
993         RegisterSortFunc(HKEY("subject"), 
994                          NULL, 0,
995                          summcmp_subj,
996                          summcmp_rsubj,
997                          CTX_MAILSUM);
998         RegisterSortFunc(HKEY("sender"),
999                          NULL, 0,
1000                          summcmp_sender,
1001                          summcmp_rsender,
1002                          CTX_MAILSUM);
1003
1004         RegisterNamespace("MAIL:SUMM:DATESTR", 0, 0, tmplput_MAIL_SUMM_DATE_STR, CTX_MAILSUM);
1005         RegisterNamespace("MAIL:SUMM:DATENO",  0, 0, tmplput_MAIL_SUMM_DATE_NO,  CTX_MAILSUM);
1006         RegisterNamespace("MAIL:SUMM:N",       0, 0, tmplput_MAIL_SUMM_N,        CTX_MAILSUM);
1007         RegisterNamespace("MAIL:SUMM:FROM",    0, 2, tmplput_MAIL_SUMM_FROM,     CTX_MAILSUM);
1008         RegisterNamespace("MAIL:SUMM:TO",      0, 2, tmplput_MAIL_SUMM_TO,       CTX_MAILSUM);
1009         RegisterNamespace("MAIL:SUMM:SUBJECT", 0, 4, tmplput_MAIL_SUMM_SUBJECT,  CTX_MAILSUM);
1010         RegisterNamespace("MAIL:SUMM:NTATACH", 0, 0, tmplput_MAIL_SUMM_NATTACH,  CTX_MAILSUM);
1011         RegisterNamespace("MAIL:SUMM:CCCC", 0, 2, tmplput_MAIL_SUMM_CCCC,  CTX_MAILSUM);
1012         RegisterNamespace("MAIL:SUMM:H_NODE", 0, 2, tmplput_MAIL_SUMM_H_NODE,  CTX_MAILSUM);
1013         RegisterNamespace("MAIL:SUMM:ALLRCPT", 0, 2, tmplput_MAIL_SUMM_ALLRCPT,  CTX_MAILSUM);
1014         RegisterNamespace("MAIL:SUMM:ORGROOM", 0, 2, tmplput_MAIL_SUMM_ORGROOM,  CTX_MAILSUM);
1015         RegisterNamespace("MAIL:SUMM:RFCA", 0, 2, tmplput_MAIL_SUMM_RFCA,  CTX_MAILSUM);
1016         RegisterNamespace("MAIL:SUMM:OTHERNODE", 2, 0, tmplput_MAIL_SUMM_OTHERNODE,  CTX_MAILSUM);
1017         RegisterNamespace("MAIL:SUMM:REFIDS", 0, 0, tmplput_MAIL_SUMM_REFIDS,  CTX_MAILSUM);
1018         RegisterNamespace("MAIL:SUMM:INREPLYTO", 0, 2, tmplput_MAIL_SUMM_INREPLYTO,  CTX_MAILSUM);
1019         RegisterNamespace("MAIL:BODY", 0, 2, tmplput_MAIL_BODY,  CTX_MAILSUM);
1020         RegisterNamespace("MAIL:QUOTETEXT", 1, 2, tmplput_QUOTED_MAIL_BODY,  CTX_NONE);
1021         RegisterNamespace("ATT:SIZE", 0, 1, tmplput_ATT_Length, CTX_ATT);
1022         RegisterNamespace("ATT:TYPE", 0, 1, tmplput_ATT_Contenttype, CTX_ATT);
1023         RegisterNamespace("ATT:FILENAME", 0, 1, tmplput_ATT_FileName, CTX_ATT);
1024
1025         RegisterConditional(HKEY("MAIL:SUMM:RFCA"), 0, Conditional_MAIL_SUMM_RFCA,  CTX_MAILSUM);
1026         RegisterConditional(HKEY("COND:MAIL:SUMM:UNREAD"), 0, Conditional_MAIL_SUMM_UNREAD, CTX_MAILSUM);
1027         RegisterConditional(HKEY("COND:MAIL:SUMM:H_NODE"), 0, Conditional_MAIL_SUMM_H_NODE, CTX_MAILSUM);
1028         RegisterConditional(HKEY("COND:MAIL:SUMM:OTHERNODE"), 0, Conditional_MAIL_SUMM_OTHERNODE, CTX_MAILSUM);
1029         RegisterConditional(HKEY("COND:MAIL:ANON"), 0, Conditional_ANONYMOUS_MESSAGE, CTX_MAILSUM);
1030
1031         RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH"), 0, Conditional_MAIL_MIME_ALL, CTX_MAILSUM);
1032         RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:SUBMESSAGES"), 0, Conditional_MAIL_MIME_SUBMESSAGES, CTX_MAILSUM);
1033         RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:LINKS"), 0, Conditional_MAIL_MIME_ATTACHLINKS, CTX_MAILSUM);
1034         RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:ATT"), 0, Conditional_MAIL_MIME_ATTACH, CTX_MAILSUM);
1035
1036         RegisterIterator("MAIL:MIME:ATTACH", 0, NULL, iterate_get_mime_All, 
1037                          NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
1038         RegisterIterator("MAIL:MIME:ATTACH:SUBMESSAGES", 0, NULL, iterate_get_mime_Submessages, 
1039                          NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
1040         RegisterIterator("MAIL:MIME:ATTACH:LINKS", 0, NULL, iterate_get_mime_AttachLinks, 
1041                          NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
1042         RegisterIterator("MAIL:MIME:ATTACH:ATT", 0, NULL, iterate_get_mime_Attachments, 
1043                          NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
1044
1045         RegisterNamespace("MAIL:MIME:NAME", 0, 2, tmplput_MIME_Name, CTX_MIME_ATACH);
1046         RegisterNamespace("MAIL:MIME:FILENAME", 0, 2, tmplput_MIME_FileName, CTX_MIME_ATACH);
1047         RegisterNamespace("MAIL:MIME:PARTNUM", 0, 2, tmplput_MIME_PartNum, CTX_MIME_ATACH);
1048         RegisterNamespace("MAIL:MIME:MSGNUM", 0, 2, tmplput_MIME_MsgNum, CTX_MIME_ATACH);
1049         RegisterNamespace("MAIL:MIME:DISPOSITION", 0, 2, tmplput_MIME_Disposition, CTX_MIME_ATACH);
1050         RegisterNamespace("MAIL:MIME:CONTENTTYPE", 0, 2, tmplput_MIME_ContentType, CTX_MIME_ATACH);
1051         RegisterNamespace("MAIL:MIME:CHARSET", 0, 2, tmplput_MIME_Charset, CTX_MIME_ATACH);
1052         RegisterNamespace("MAIL:MIME:LENGTH", 0, 2, tmplput_MIME_Length, CTX_MIME_ATACH);
1053         RegisterNamespace("MAIL:MIME:DATA", 0, 2, tmplput_MIME_Data, CTX_MIME_ATACH);
1054
1055         RegisterIterator("MSG:ATTACHNAMES", 0, NULL, iterate_get_registered_Attachments, 
1056                          NULL, NULL, CTX_ATT, CTX_NONE);
1057
1058         RegisterMimeRenderer(HKEY("message/rfc822"), render_MAIL);
1059         RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard);
1060         RegisterMimeRenderer(HKEY("text/vcard"), render_MIME_VCard);
1061         RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS);
1062         RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS);
1063
1064         RegisterMimeRenderer(HKEY("text/x-citadel-variformat"), render_MAIL_variformat);
1065         RegisterMimeRenderer(HKEY("text/plain"), render_MAIL_text_plain);
1066         RegisterMimeRenderer(HKEY("text"), render_MAIL_text_plain);
1067         RegisterMimeRenderer(HKEY("text/html"), render_MAIL_html);
1068         RegisterMimeRenderer(HKEY(""), render_MAIL_UNKNOWN);
1069
1070         RegisterMsgHdr(HKEY("nhdr"), examine_nhdr, 0);
1071         RegisterMsgHdr(HKEY("type"), examine_type, 0);
1072         RegisterMsgHdr(HKEY("from"), examine_from, 0);
1073         RegisterMsgHdr(HKEY("subj"), examine_subj, 0);
1074         RegisterMsgHdr(HKEY("msgn"), examine_msgn, 0);
1075         RegisterMsgHdr(HKEY("wefw"), examine_wefw, 0);
1076         RegisterMsgHdr(HKEY("cccc"), examine_cccc, 0);
1077         RegisterMsgHdr(HKEY("hnod"), examine_hnod, 0);
1078         RegisterMsgHdr(HKEY("room"), examine_room, 0);
1079         RegisterMsgHdr(HKEY("rfca"), examine_rfca, 0);
1080         RegisterMsgHdr(HKEY("node"), examine_node, 0);
1081         RegisterMsgHdr(HKEY("rcpt"), examine_rcpt, 0);
1082         RegisterMsgHdr(HKEY("time"), examine_time, 0);
1083         RegisterMsgHdr(HKEY("part"), examine_mime_part, 0);
1084         RegisterMsgHdr(HKEY("text"), examine_text, 1);
1085         RegisterMsgHdr(HKEY("X-Citadel-MSG4-Partnum"), examine_msg4_partnum, 0);
1086         RegisterMsgHdr(HKEY("Content-type"), examine_content_type, 0);
1087         RegisterMsgHdr(HKEY("Content-length"), examine_content_lengh, 0);
1088         RegisterMsgHdr(HKEY("Content-transfer-encoding"), examine_content_encoding, 0);
1089         RegisterMsgHdr(HKEY("charset"), examine_charset, 0);
1090
1091         /* Don't care... */
1092         RegisterMsgHdr(HKEY("pref"), examine_pref, 0);
1093         RegisterMsgHdr(HKEY("suff"), examine_suff, 0);
1094         RegisterMsgHdr(HKEY("path"), examine_path, 0);
1095 }