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