2 ** Copyright 1998 - 2009 Double Precision, Inc. See COPYING for
3 ** distribution information.
14 #include "rfc822hdr.h"
16 #include "../unicode/unicode.h"
20 #include <stringprep.h>
23 static const char rcsid
[]="$Id: rfc2047u.c,v 1.11 2009/11/22 19:39:52 mrsam Exp $";
25 static ssize_t
rfc822_decode_rfc2047_atom(const char *str
,
28 void (*callback
)(const char *,
35 static int rfc2047_decode_unicode(const char *text
,
36 const struct unicode_info
*u
,
37 void (*callback
)(const char *, size_t,
41 struct decode_unicode_s
{
42 const struct unicode_info
*mychset
;
48 static void save_unicode_text(const char *p
, size_t l
, void *ptr
)
50 struct decode_unicode_s
*s
=
51 (struct decode_unicode_s
*)ptr
;
54 memcpy(s
->bufptr
+s
->bufsize
, p
, l
);
59 struct rfc822_display_name_s
{
60 const struct unicode_info
*u
;
61 void (*print_func
)(const char *, size_t, void *);
65 static void unknown_charset(const char *chset
,
66 void (*print_func
)(const char *, size_t, void *),
69 static const char unknown
[]="[unknown character set: ";
71 (*print_func
)(unknown
, sizeof(unknown
)-1, ptr
);
72 (*print_func
)(chset
, strlen(chset
), ptr
);
73 (*print_func
)("]", 1, ptr
);
76 static void rfc822_display_addr_cb(const char *chset
,
82 const struct unicode_info
*uchset
=unicode_find(chset
);
83 struct rfc822_display_name_s
*s
=
84 (struct rfc822_display_name_s
*)dummy
;
90 unknown_charset(chset
, s
->print_func
, s
->ptr
);
99 memcpy(buf
, content
, cnt
);
102 ptr
=unicode_xconvert(buf
, uchset
, s
->u
);
107 (*s
->print_func
)(ptr
, strlen(ptr
), s
->ptr
);
113 int rfc822_display_name_int(const struct rfc822a
*rfcp
, int index
,
115 void (*print_func
)(const char *, size_t, void *),
118 struct rfc822_display_name_s s
;
119 const struct rfc822addr
*addrs
;
121 struct rfc822token
*i
;
126 if (index
< 0 || index
>= rfcp
->naddrs
) return 0;
128 addrs
=rfcp
->addrs
+index
;
131 return rfc822_display_addr(rfcp
, index
, chset
, print_func
, ptr
);
139 s
.u
=unicode_find(chset
);
143 unknown_charset(chset
, print_func
, ptr
);
148 s
.print_func
=print_func
;
151 for (i
=addrs
->name
; i
; i
=i
->next
, prev_isatom
=isatom
)
153 isatom
=rfc822_is_atom(i
->token
);
154 if (isatom
&& prev_isatom
)
155 (*print_func
)(" ", 1, ptr
);
157 if (i
->token
== '"' || i
->token
== '(')
179 memcpy(p
, i
->ptr
+1, l
);
183 memcpy(p
, i
->ptr
, l
);
190 for (q
=r
=p
; *q
; *r
++ = *q
++)
191 if (*q
== '\\' && q
[1])
198 (*print_func
)(p
, strlen(p
), ptr
);
200 else if (rfc822_display_hdrvalue("subject",
214 char c
= (char)i
->token
;
216 (*print_func
)(&c
, 1, ptr
);
220 rc
=chset
? rfc822_decode_rfc2047_atom(i
->ptr
, i
->len
,
221 rfc822_display_addr_cb
,
229 (*print_func
)(i
->ptr
, i
->len
, ptr
);
233 if (i
->next
&& i
->next
->token
== 0)
235 rc
=rfc822_decode_rfc2047_atom(i
->next
->ptr
,
243 isatom
=0; /* Suppress the separating space */
249 int rfc822_display_name(const struct rfc822a
*rfcp
, int index
,
251 void (*print_func
)(const char *, size_t, void *),
254 const struct rfc822addr
*addrs
;
256 if (index
< 0 || index
>= rfcp
->naddrs
) return 0;
258 addrs
=rfcp
->addrs
+index
;
263 return rfc822_display_name_int(rfcp
, index
, chset
,
267 char *rfc822_display_name_tobuf(const struct rfc822a
*rfcp
, int index
,
270 struct decode_unicode_s s
;
276 if (rfc822_display_name(rfcp
, index
, chset
, save_unicode_text
, &s
) < 0)
278 s
.bufptr
=p
=malloc(s
.bufsize
);
283 if (rfc822_display_name(rfcp
, index
, chset
, save_unicode_text
, &s
) < 0)
288 save_unicode_text("", 1, &s
);
293 int rfc822_display_namelist(const struct rfc822a
*rfcp
,
295 void (*print_func
)(const char *, size_t, void *),
300 for (n
=0; n
<rfcp
->naddrs
; n
++)
302 if (rfcp
->addrs
[n
].tokens
)
304 int err
=rfc822_display_name(rfcp
, n
, chset
,
310 (*print_func
)("\n", 1, ptr
);
316 int rfc822_display_addr_str(const char *tok
,
318 void (*print_func
)(const char *, size_t, void *),
322 const struct unicode_info
*uiptr
;
331 if (chset
!= NULL
&& (uiptr
=unicode_find(chset
)) != NULL
)
337 (*print_func
)(tok
, p
-tok
, ptr
);
340 err
=idna_to_unicode_8z8z(p
, &utf8_ptr
, 0);
341 if (err
!= IDNA_SUCCESS
)
348 (*print_func
)(p
, strlen(p
), ptr
);
351 char *q
=unicode_xconvert(utf8_ptr
, &unicode_UTF8
,
356 (*print_func
)(q
, strlen(q
), ptr
);
361 (*print_func
)(p
, strlen(p
), ptr
);
368 (*print_func
)(tok
, strlen(tok
), ptr
);
373 int rfc822_display_addr(const struct rfc822a
*rfcp
, int index
,
375 void (*print_func
)(const char *, size_t, void *),
378 const struct rfc822addr
*addrs
;
382 if (index
< 0 || index
>= rfcp
->naddrs
) return 0;
384 addrs
=rfcp
->addrs
+index
;
389 tok
=rfc822_gettok(addrs
->tokens
);
394 rc
=rfc822_display_addr_str(tok
, chset
, print_func
, ptr
);
399 int rfc2047_print_unicodeaddr(const struct rfc822a
*a
,
401 void (*print_func
)(char, void *),
402 void (*print_separator
)(const char *, void *),
405 const char *sep
=NULL
;
407 const struct unicode_info
*charsetu
=unicode_find(charset
);
409 for (n
=0; n
<a
->naddrs
; ++n
)
411 struct decode_unicode_s nbuf
;
412 const struct rfc822addr
*addrs
;
422 if (rfc822_display_name_int(a
, n
, charset
,
423 save_unicode_text
, &nbuf
) < 0)
426 nbuf
.bufptr
=malloc(nbuf
.bufsize
);
431 if (rfc822_display_name_int(a
, n
, charset
,
432 save_unicode_text
, &nbuf
) < 0)
437 nbuf
.bufptr
[nbuf
.bufsize
]=0;
439 if (addrs
->tokens
== 0)
443 if (nbuf
.bufsize
== 1) /* ; */
447 (*print_separator
)(sep
, ptr
);
449 for (i
=0; i
<nbuf
.bufsize
; ++i
)
450 (*print_func
)(nbuf
.bufptr
[i
], ptr
);
452 if (nbuf
.bufsize
> 1)
453 (*print_separator
)(" ", ptr
);
458 (*print_separator
)(sep
, ptr
);
466 for (i
=0; i
<nbuf
.bufsize
; i
++)
467 if (strchr(RFC822_SPECIALS
, nbuf
.bufptr
[i
]))
472 const char *errmsg
="\"(unknown character set)\"";
475 (*print_func
)(*errmsg
++, ptr
);
480 cpbuf
=unicode_xconvert(nbuf
.bufptr
, &unicode_UTF8
,
489 if (i
< nbuf
.bufsize
)
491 (*print_func
)('"', ptr
);
493 for (i
=0; cpbuf
[i
]; ++i
)
495 if (cpbuf
[i
] == '\\' ||
497 (*print_func
)('\\', ptr
);
498 (*print_func
)(cpbuf
[i
], ptr
);
500 (*print_func
)('"', ptr
);
505 for (i
=0; cpbuf
[i
]; ++i
)
508 (*print_func
)(cpbuf
[i
], ptr
);
518 (*print_func
)(' ', ptr
);
519 (*print_func
)('<', ptr
);
525 if (rfc822_display_addr(a
, n
, charset
,
526 save_unicode_text
, &nbuf
) < 0)
529 nbuf
.bufptr
=malloc(nbuf
.bufsize
);
534 if (rfc822_display_addr(a
, n
, charset
,
535 save_unicode_text
, &nbuf
) < 0)
540 for (i
=0; i
<nbuf
.bufsize
; i
++)
541 (*print_func
)(nbuf
.bufptr
[i
], ptr
);
546 (*print_func
)('>', ptr
);
553 static int rfc2047_print_unicode_addrstr(const char *addrheader
,
555 void (*print_func
)(char, void *),
556 void (*print_separator
)(const char *, void *),
557 void (*err_func
)(const char *, int, void *),
564 t
=rfc822t_alloc_new(addrheader
, err_func
, ptr
);
576 rc
=rfc2047_print_unicodeaddr(a
, charset
, print_func
, print_separator
,
583 struct rfc822_display_hdrvalue_s
{
585 const struct unicode_info
*u
;
586 void (*display_func
)(const char *, size_t, void *);
590 static void rfc822_display_hdrvalue_print_func(char c
, void *ptr
)
592 struct rfc822_display_hdrvalue_s
*s
=
593 (struct rfc822_display_hdrvalue_s
*)ptr
;
595 (*s
->display_func
)(&c
, 1, s
->ptr
);
598 static void rfc822_display_hdrvalue_print_separator(const char *cp
, void *ptr
)
600 struct rfc822_display_hdrvalue_s
*s
=
601 (struct rfc822_display_hdrvalue_s
*)ptr
;
603 (*s
->display_func
)(cp
, strlen(cp
), s
->ptr
);
604 (*s
->display_func
)("", 0, s
->ptr
); /* Signal wrap point */
607 int rfc822_display_hdrvalue(const char *hdrname
,
608 const char *hdrvalue
,
610 void (*display_func
)(const char *, size_t,
612 void (*err_func
)(const char *, int, void *),
615 struct rfc822_display_hdrvalue_s s
;
617 s
.display_func
=display_func
;
620 if (rfc822hdr_is_addr(hdrname
))
622 return rfc2047_print_unicode_addrstr(hdrvalue
,
624 rfc822_display_hdrvalue_print_func
,
625 rfc822_display_hdrvalue_print_separator
,
630 s
.u
=unicode_find(charset
);
634 unknown_charset(charset
, display_func
, ptr
);
638 return rfc2047_decode_unicode(hdrvalue
, s
.u
, display_func
, ptr
);
641 struct rfc822_display_hdrvalue_tobuf_s
{
642 void (*orig_err_func
)(const char *, int, void *);
649 static void rfc822_display_hdrvalue_tobuf_cnt(const char *ptr
, size_t cnt
,
652 ((struct rfc822_display_hdrvalue_tobuf_s
*)s
)->cnt
+= cnt
;
655 static void rfc822_display_hdrvalue_tobuf_save(const char *ptr
, size_t cnt
,
659 memcpy(((struct rfc822_display_hdrvalue_tobuf_s
*)s
)->buf
,
662 ((struct rfc822_display_hdrvalue_tobuf_s
*)s
)->buf
+= cnt
;
665 static void rfc822_display_hdrvalue_tobuf_errfunc(const char *ptr
, int index
,
668 void (*f
)(const char *, int, void *)=
669 ((struct rfc822_display_hdrvalue_tobuf_s
*)s
)->orig_err_func
;
673 ((struct rfc822_display_hdrvalue_tobuf_s
*)s
)->orig_ptr
);
676 char *rfc822_display_addr_tobuf(const struct rfc822a
*rfcp
, int index
,
679 struct rfc822_display_hdrvalue_tobuf_s nbuf
;
686 errcode
=rfc822_display_addr(rfcp
, index
, chset
,
687 rfc822_display_hdrvalue_tobuf_cnt
, &nbuf
);
692 ptr
=nbuf
.buf
=malloc(nbuf
.cnt
);
697 errcode
=rfc822_display_addr(rfcp
, index
, chset
,
698 rfc822_display_hdrvalue_tobuf_save
, &nbuf
);
709 char *rfc822_display_hdrvalue_tobuf(const char *hdrname
,
710 const char *hdrvalue
,
712 void (*err_func
)(const char *, int,
716 struct rfc822_display_hdrvalue_tobuf_s s
;
720 s
.orig_err_func
=err_func
;
724 errcode
=rfc822_display_hdrvalue(hdrname
, hdrvalue
, charset
,
725 rfc822_display_hdrvalue_tobuf_cnt
,
726 rfc822_display_hdrvalue_tobuf_errfunc
,
732 bufptr
=s
.buf
=malloc(s
.cnt
);
737 errcode
=rfc822_display_hdrvalue(hdrname
, hdrvalue
, charset
,
738 rfc822_display_hdrvalue_tobuf_save
,
739 rfc822_display_hdrvalue_tobuf_errfunc
,
750 char *rfc822_display_addr_str_tobuf(const char *tok
, const char *chset
)
752 struct rfc822_display_hdrvalue_tobuf_s s
;
758 errcode
=rfc822_display_addr_str(tok
, chset
,
759 rfc822_display_hdrvalue_tobuf_cnt
,
765 bufptr
=s
.buf
=malloc(s
.cnt
);
770 errcode
=rfc822_display_addr_str(tok
, chset
,
771 rfc822_display_hdrvalue_tobuf_save
,
783 static const char xdigit
[]="0123456789ABCDEFabcdef";
785 static const unsigned char decode64tab
[]={
786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
789 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 99, 0, 0,
790 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
791 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
792 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
793 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0,
794 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
795 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
796 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
801 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
804 static int nyb(int c
)
822 static size_t decodebase64(const char *ptr
, size_t cnt
,
832 for (j
=0; j
<i
; j
+= 4)
834 int w
=decode64tab
[(int)(unsigned char)ptr
[j
]];
835 int x
=decode64tab
[(int)(unsigned char)ptr
[j
+1]];
836 int y
=decode64tab
[(int)(unsigned char)ptr
[j
+2]];
837 int z
=decode64tab
[(int)(unsigned char)ptr
[j
+3]];
839 a
= (w
<< 2) | (x
>> 4);
840 b
= (x
<< 4) | (y
>> 2);
843 if ( ptr
[j
+2] != '=')
845 if ( ptr
[j
+3] != '=')
852 static ssize_t
rfc822_decode_rfc2047_atom(const char *str
,
855 void (*callback
)(const char *,
862 const char *chset_str
;
864 const char *content_str
;
877 if (cnt
< 2 || str
[0] != '=' || str
[1] != '?')
882 for (i
=2; i
<cnt
; i
++)
898 content_str
= str
+ ++i
;
905 if (str
[i
] == '?' && str
[i
+1] == '=')
910 for (j
=0; chset_str
[j
] != '?'; ++j
)
918 memcpy(chset
, chset_str
, j
);
921 lang
=strchr(chset
, '*'); /* RFC 2231 */
928 content_len
=str
+ i
- content_str
;
930 content
=malloc(content_len
+1);
943 for (j
=0; j
<content_len
; j
++)
947 if (content_str
[j
] == '=' && i
-j
>= 3)
949 content
[k
]=(char)(nyb(content_str
[j
+1])*16 +
950 nyb(content_str
[j
+2]));
966 k
=decodebase64(content_str
, content_len
, content
);
975 (*callback
)(chset
, lang
, content
, k
, ptr
);
981 int rfc2047_decoder(const char *text
,
982 void (*callback
)(const char *chset
,
991 while (text
&& *text
)
995 for (i
=0; text
[i
]; i
++)
997 if (text
[i
] == '=' && text
[i
+1] == '?')
1002 (*callback
)(unicode_ISO8859_1
.chset
, "", text
, i
, ptr
);
1009 rc
=rfc822_decode_rfc2047_atom(text
, strlen(text
),
1017 (*callback
)(unicode_ISO8859_1
.chset
, "", text
, 2, ptr
);
1024 for (i
=0; text
[i
]; i
++)
1026 if (strchr(" \t\r\n", text
[i
]) == NULL
)
1030 if (text
[i
] != '=' || text
[i
+1] != '?')
1033 rc
=rfc822_decode_rfc2047_atom(text
+i
, strlen(text
+i
), NULL
,
1045 static int rfc2047_decode_unicode(const char *text
,
1046 const struct unicode_info
*u
,
1047 void (*callback
)(const char *, size_t,
1051 struct rfc822_display_name_s s
;
1054 s
.print_func
=callback
;
1057 return rfc2047_decoder(text
, rfc822_display_addr_cb
, &s
);