Import Upstream version 0.69.0
[hcoop/debian/courier-authlib.git] / libs / rfc822 / rfc2047u.c
CommitLineData
d9898ee8 1/*
8d138742 2** Copyright 1998 - 2009 Double Precision, Inc. See COPYING for
d9898ee8 3** distribution information.
4*/
5
b0322a85 6#include "rfc822.h"
d9898ee8 7#include <stdio.h>
8#include <ctype.h>
9#include <string.h>
10#include <stdlib.h>
11#include <errno.h>
d50284c4 12#include <courier-unicode.h>
d9898ee8 13
8d138742 14#include "rfc822hdr.h"
d9898ee8 15#include "rfc2047.h"
16
8d138742
CE
17#if LIBIDN
18#include <idna.h>
19#include <stringprep.h>
20#endif
21
8d138742
CE
22
23static ssize_t rfc822_decode_rfc2047_atom(const char *str,
24 size_t cnt,
d9898ee8 25
8d138742
CE
26 void (*callback)(const char *,
27 const char *,
28 const char *,
29 size_t,
30 void *),
31 void *ptr);
d9898ee8 32
8d138742 33static int rfc2047_decode_unicode(const char *text,
b0322a85 34 const char *chset,
8d138742
CE
35 void (*callback)(const char *, size_t,
36 void *),
37 void *ptr);
d9898ee8 38
39struct decode_unicode_s {
b0322a85 40 const char *mychset;
d9898ee8 41
42 char *bufptr;
43 size_t bufsize;
44} ;
45
8d138742 46static void save_unicode_text(const char *p, size_t l, void *ptr)
d9898ee8 47{
8d138742
CE
48 struct decode_unicode_s *s=
49 (struct decode_unicode_s *)ptr;
50
d9898ee8 51 if (s->bufptr)
52 memcpy(s->bufptr+s->bufsize, p, l);
53
54 s->bufsize += l;
55}
56
8d138742 57struct rfc822_display_name_s {
b0322a85 58 const char *chset;
8d138742
CE
59 void (*print_func)(const char *, size_t, void *);
60 void *ptr;
61};
62
63static void unknown_charset(const char *chset,
b0322a85 64 const char *tochset,
8d138742
CE
65 void (*print_func)(const char *, size_t, void *),
66 void *ptr)
d9898ee8 67{
8d138742 68 static const char unknown[]="[unknown character set: ";
d9898ee8 69
8d138742
CE
70 (*print_func)(unknown, sizeof(unknown)-1, ptr);
71 (*print_func)(chset, strlen(chset), ptr);
b0322a85
CE
72 (*print_func)(" -> ", 4, ptr);
73 (*print_func)(tochset, strlen(tochset), ptr);
8d138742
CE
74 (*print_func)("]", 1, ptr);
75}
d9898ee8 76
8d138742
CE
77static void rfc822_display_addr_cb(const char *chset,
78 const char *lang,
79 const char *content,
80 size_t cnt,
81 void *dummy)
82{
8d138742
CE
83 struct rfc822_display_name_s *s=
84 (struct rfc822_display_name_s *)dummy;
85 char *ptr;
86 char *buf;
d9898ee8 87
8d138742
CE
88 buf=malloc(cnt+1);
89
90 if (!buf)
91 return;
92
93 memcpy(buf, content, cnt);
94 buf[cnt]=0;
95
d50284c4 96 ptr=unicode_convert_tobuf(buf, chset, s->chset, NULL);
8d138742
CE
97 free(buf);
98
99 if (ptr)
d9898ee8 100 {
8d138742
CE
101 (*s->print_func)(ptr, strlen(ptr), s->ptr);
102 free(ptr);
d9898ee8 103 }
b0322a85
CE
104 else
105 {
106 unknown_charset(chset, s->chset, s->print_func, s->ptr);
107 return;
108 }
8d138742
CE
109}
110
111static
112int rfc822_display_name_int(const struct rfc822a *rfcp, int index,
113 const char *chset,
114 void (*print_func)(const char *, size_t, void *),
115 void *ptr)
116{
117 struct rfc822_display_name_s s;
118 const struct rfc822addr *addrs;
119
120 struct rfc822token *i;
121 int prev_isatom=0;
122 int isatom=0;
123 ssize_t rc;
124
125 if (index < 0 || index >= rfcp->naddrs) return 0;
126
127 addrs=rfcp->addrs+index;
d9898ee8 128
8d138742
CE
129 if (!addrs->name)
130 return rfc822_display_addr(rfcp, index, chset, print_func, ptr);
131
132 if (chset == NULL)
d9898ee8 133 {
0e333c05 134 s.chset="utf-8";
d9898ee8 135 }
8d138742
CE
136 else
137 {
b0322a85 138 s.chset=chset;
8d138742
CE
139 }
140
141 s.print_func=print_func;
142 s.ptr=ptr;
d9898ee8 143
8d138742 144 for (i=addrs->name; i; i=i->next, prev_isatom=isatom)
d9898ee8 145 {
8d138742
CE
146 isatom=rfc822_is_atom(i->token);
147 if (isatom && prev_isatom)
148 (*print_func)(" ", 1, ptr);
149
150 if (i->token == '"' || i->token == '(')
d9898ee8 151 {
8d138742
CE
152 size_t l=i->len;
153 char *p, *q, *r;
154
155 if (i->token == '(')
156 {
157 if (l > 2)
158 l -= 2;
159 else
160 l=0;
161 }
162
163 p=malloc(l+1);
164
165 if (!p)
166 return -1;
167
168 if (l)
169 {
170 if (i->token == '(')
171 {
172 memcpy(p, i->ptr+1, l);
173 }
174 else
175 {
176 memcpy(p, i->ptr, l);
177 }
178 }
179
180
181 p[l]=0;
182
183 for (q=r=p; *q; *r++ = *q++)
184 if (*q == '\\' && q[1])
185 ++q;
186
187 *r=0;
188
189 if (chset == NULL)
190 {
191 (*print_func)(p, strlen(p), ptr);
192 }
193 else if (rfc822_display_hdrvalue("subject",
b0322a85 194 p, s.chset,
8d138742
CE
195 print_func,
196 NULL, ptr) < 0)
197 {
198 free(p);
199 return -1;
200 }
201 free(p);
202 continue;
203 }
204
205 if (i->token)
206 {
207 char c= (char)i->token;
208
209 (*print_func)(&c, 1, ptr);
210 continue;
211 }
212
213 rc=chset ? rfc822_decode_rfc2047_atom(i->ptr, i->len,
214 rfc822_display_addr_cb,
215 &s):0;
216
217 if (rc < 0)
218 return -1;
219
220 if (rc == 0)
221 {
222 (*print_func)(i->ptr, i->len, ptr);
223 continue;
224 }
225
226 if (i->next && i->next->token == 0)
227 {
228 rc=rfc822_decode_rfc2047_atom(i->next->ptr,
229 i->next->len,
230 NULL, NULL);
231
232 if (rc < 0)
233 return -1;
234
235 if (rc > 0)
236 isatom=0; /* Suppress the separating space */
d9898ee8 237 }
238 }
8d138742
CE
239 return 0;
240}
241
242int rfc822_display_name(const struct rfc822a *rfcp, int index,
243 const char *chset,
244 void (*print_func)(const char *, size_t, void *),
245 void *ptr)
246{
247 const struct rfc822addr *addrs;
248
249 if (index < 0 || index >= rfcp->naddrs) return 0;
250
251 addrs=rfcp->addrs+index;
d9898ee8 252
8d138742
CE
253 if (!addrs->tokens)
254 return 0;
d9898ee8 255
8d138742
CE
256 return rfc822_display_name_int(rfcp, index, chset,
257 print_func, ptr);
d9898ee8 258}
259
8d138742
CE
260char *rfc822_display_name_tobuf(const struct rfc822a *rfcp, int index,
261 const char *chset)
d9898ee8 262{
263 struct decode_unicode_s s;
8d138742 264 char *p;
d9898ee8 265
266 s.bufptr=0;
267 s.bufsize=1;
268
8d138742
CE
269 if (rfc822_display_name(rfcp, index, chset, save_unicode_text, &s) < 0)
270 return NULL;
d9898ee8 271 s.bufptr=p=malloc(s.bufsize);
8d138742 272 if (!p)
d9898ee8 273 return (0);
274
275 s.bufsize=0;
8d138742 276 if (rfc822_display_name(rfcp, index, chset, save_unicode_text, &s) < 0)
d9898ee8 277 {
8d138742 278 free(s.bufptr);
d9898ee8 279 return (0);
280 }
8d138742
CE
281 save_unicode_text("", 1, &s);
282
d9898ee8 283 return (p);
284}
285
8d138742
CE
286int rfc822_display_namelist(const struct rfc822a *rfcp,
287 const char *chset,
288 void (*print_func)(const char *, size_t, void *),
289 void *ptr)
290{
291 int n;
292
293 for (n=0; n<rfcp->naddrs; n++)
294 {
295 if (rfcp->addrs[n].tokens)
296 {
297 int err=rfc822_display_name(rfcp, n, chset,
298 print_func, ptr);
299
300 if (err < 0)
301 return err;
d9898ee8 302
8d138742
CE
303 (*print_func)("\n", 1, ptr);
304 }
305 }
306 return 0;
307}
308
309int rfc822_display_addr_str(const char *tok,
310 const char *chset,
311 void (*print_func)(const char *, size_t, void *),
312 void *ptr)
d9898ee8 313{
8d138742 314 const char *p;
8d138742
CE
315
316 p=strchr(tok,'@');
d9898ee8 317
8d138742
CE
318 if (!p)
319 p=tok;
320 else
321 ++p;
d9898ee8 322
b0322a85 323 if (chset != NULL)
8d138742 324 {
b0322a85 325 int err=0;
8d138742
CE
326 char *utf8_ptr;
327
328 if (p > tok)
329 (*print_func)(tok, p-tok, ptr);
330
331#if LIBIDN
b0322a85
CE
332 /*
333 ** Invalid UTF-8 can make libidn go off the deep end. Add
334 ** padding as a workaround.
335 */
336 {
337 size_t s=strlen(p)+16;
338 char *cpy=malloc(s);
339
340 if (!cpy)
341 return 0;
342 memset(cpy, 0, s);
343 strcpy(cpy, p);
344
345 err=idna_to_unicode_8z8z(cpy, &utf8_ptr, 0);
346 free(cpy);
347 }
348
8d138742
CE
349 if (err != IDNA_SUCCESS)
350 utf8_ptr=0;
351#else
352 utf8_ptr=0;
353#endif
354
355 if (utf8_ptr == 0)
356 (*print_func)(p, strlen(p), ptr);
357 else
358 {
d50284c4 359 char *q=unicode_convert_tobuf(utf8_ptr,
b0322a85
CE
360 "utf-8",
361 chset, NULL);
8d138742
CE
362 if (q)
363 {
364 (*print_func)(q, strlen(q), ptr);
365 free(q);
366 }
367 else
368 {
369 (*print_func)(p, strlen(p), ptr);
370 }
371 free(utf8_ptr);
372 }
373 }
374 else
375 {
376 (*print_func)(tok, strlen(tok), ptr);
377 }
378 return 0;
d9898ee8 379}
380
8d138742
CE
381int rfc822_display_addr(const struct rfc822a *rfcp, int index,
382 const char *chset,
383 void (*print_func)(const char *, size_t, void *),
384 void *ptr)
d9898ee8 385{
8d138742
CE
386 const struct rfc822addr *addrs;
387 char *tok;
388 int rc;
389
390 if (index < 0 || index >= rfcp->naddrs) return 0;
391
392 addrs=rfcp->addrs+index;
393
394 if (!addrs->tokens)
395 return 0;
396
397 tok=rfc822_gettok(addrs->tokens);
398
399 if (!tok)
400 return 0;
401
402 rc=rfc822_display_addr_str(tok, chset, print_func, ptr);
403 free(tok);
404 return rc;
d9898ee8 405}
406
8d138742
CE
407int rfc2047_print_unicodeaddr(const struct rfc822a *a,
408 const char *charset,
409 void (*print_func)(char, void *),
410 void (*print_separator)(const char *, void *),
411 void *ptr)
412{
413 const char *sep=NULL;
414 int n;
d9898ee8 415
8d138742
CE
416 for (n=0; n<a->naddrs; ++n)
417 {
418 struct decode_unicode_s nbuf;
419 const struct rfc822addr *addrs;
420 size_t i=0;
421 char *cpbuf;
422 int need_braces=0;
423
424 addrs=a->addrs+n;
425
426 nbuf.bufptr=0;
427 nbuf.bufsize=1;
428
429 if (rfc822_display_name_int(a, n, charset,
430 save_unicode_text, &nbuf) < 0)
431 return -1;
432
433 nbuf.bufptr=malloc(nbuf.bufsize);
434 nbuf.bufsize=0;
435 if (!nbuf.bufptr)
436 return -1;
437
438 if (rfc822_display_name_int(a, n, charset,
439 save_unicode_text, &nbuf) < 0)
440 {
441 free(nbuf.bufptr);
442 return -1;
443 }
444 nbuf.bufptr[nbuf.bufsize]=0;
445
446 if (addrs->tokens == 0)
447 {
448 size_t i;
449
450 if (nbuf.bufsize == 1) /* ; */
451 sep=0;
452
453 if (sep)
454 (*print_separator)(sep, ptr);
455
456 for (i=0; i<nbuf.bufsize; ++i)
457 (*print_func)(nbuf.bufptr[i], ptr);
458 free(nbuf.bufptr);
459 if (nbuf.bufsize > 1)
460 (*print_separator)(" ", ptr);
461 sep=NULL;
462 continue;
463 }
464 if (sep)
465 (*print_separator)(sep, ptr);
466
467 if (!addrs->name)
468 {
469 nbuf.bufsize=0;
470 nbuf.bufptr[0]=0;
471 }
472
473 for (i=0; i<nbuf.bufsize; i++)
474 if (strchr(RFC822_SPECIALS, nbuf.bufptr[i]))
475 break;
476
d50284c4 477 cpbuf=unicode_convert_tobuf(nbuf.bufptr, "utf-8", charset,
b0322a85
CE
478 NULL);
479
480 if (!cpbuf)
8d138742
CE
481 {
482 const char *errmsg="\"(unknown character set)\"";
483
484 while (*errmsg)
485 (*print_func)(*errmsg++, ptr);
486 need_braces=1;
487 }
488 else
489 {
8d138742
CE
490 if (i < nbuf.bufsize)
491 {
492 (*print_func)('"', ptr);
493
494 for (i=0; cpbuf[i]; ++i)
495 {
496 if (cpbuf[i] == '\\' ||
497 cpbuf[i] == '"')
498 (*print_func)('\\', ptr);
499 (*print_func)(cpbuf[i], ptr);
500 }
501 (*print_func)('"', ptr);
502 need_braces=1;
503 }
504 else
505 {
506 for (i=0; cpbuf[i]; ++i)
507 {
508 need_braces=1;
509 (*print_func)(cpbuf[i], ptr);
510 }
511 }
512
513 free(cpbuf);
514 }
515 free(nbuf.bufptr);
516
517 if (need_braces)
518 {
519 (*print_func)(' ', ptr);
520 (*print_func)('<', ptr);
521 }
522
523 nbuf.bufptr=0;
524 nbuf.bufsize=1;
525
526 if (rfc822_display_addr(a, n, charset,
527 save_unicode_text, &nbuf) < 0)
528 return -1;
529
530 nbuf.bufptr=malloc(nbuf.bufsize);
531 nbuf.bufsize=0;
532 if (!nbuf.bufptr)
533 return -1;
534
535 if (rfc822_display_addr(a, n, charset,
536 save_unicode_text, &nbuf) < 0)
537 {
538 free(nbuf.bufptr);
539 return -1;
540 }
541 for (i=0; i<nbuf.bufsize; i++)
542 (*print_func)(nbuf.bufptr[i], ptr);
543
544 free(nbuf.bufptr);
545
546 if (need_braces)
547 (*print_func)('>', ptr);
548 sep=", ";
549 }
550
551 return 0;
552}
553
554static int rfc2047_print_unicode_addrstr(const char *addrheader,
555 const char *charset,
556 void (*print_func)(char, void *),
557 void (*print_separator)(const char *, void *),
558 void (*err_func)(const char *, int, void *),
559 void *ptr)
560{
561 struct rfc822t *t;
562 struct rfc822a *a;
563 int rc;
564
565 t=rfc822t_alloc_new(addrheader, err_func, ptr);
566
567 if (!t)
568 return -1;
569
570 a=rfc822a_alloc(t);
571
572 if (!a)
573 {
574 rfc822t_free(t);
575 return -1;
576 }
577 rc=rfc2047_print_unicodeaddr(a, charset, print_func, print_separator,
578 ptr);
579 rfc822a_free(a);
580 rfc822t_free(t);
581 return (rc);
582}
583
584struct rfc822_display_hdrvalue_s {
585
8d138742
CE
586 void (*display_func)(const char *, size_t, void *);
587 void *ptr;
588};
589
590static void rfc822_display_hdrvalue_print_func(char c, void *ptr)
591{
592 struct rfc822_display_hdrvalue_s *s=
593 (struct rfc822_display_hdrvalue_s *)ptr;
594
595 (*s->display_func)(&c, 1, s->ptr);
596}
597
598static void rfc822_display_hdrvalue_print_separator(const char *cp, void *ptr)
599{
600 struct rfc822_display_hdrvalue_s *s=
601 (struct rfc822_display_hdrvalue_s *)ptr;
602
603 (*s->display_func)(cp, strlen(cp), s->ptr);
604 (*s->display_func)("", 0, s->ptr); /* Signal wrap point */
605}
606
607int rfc822_display_hdrvalue(const char *hdrname,
608 const char *hdrvalue,
609 const char *charset,
610 void (*display_func)(const char *, size_t,
611 void *),
612 void (*err_func)(const char *, int, void *),
613 void *ptr)
614{
615 struct rfc822_display_hdrvalue_s s;
616
617 s.display_func=display_func;
618 s.ptr=ptr;
619
620 if (rfc822hdr_is_addr(hdrname))
621 {
622 return rfc2047_print_unicode_addrstr(hdrvalue,
623 charset,
624 rfc822_display_hdrvalue_print_func,
625 rfc822_display_hdrvalue_print_separator,
626 NULL,
627 &s);
628 }
629
b0322a85 630 return rfc2047_decode_unicode(hdrvalue, charset, display_func, ptr);
8d138742
CE
631}
632
633struct rfc822_display_hdrvalue_tobuf_s {
634 void (*orig_err_func)(const char *, int, void *);
635 void *orig_ptr;
636
637 size_t cnt;
638 char *buf;
639};
640
641static void rfc822_display_hdrvalue_tobuf_cnt(const char *ptr, size_t cnt,
642 void *s)
643{
644 ((struct rfc822_display_hdrvalue_tobuf_s *)s)->cnt += cnt;
645}
646
647static void rfc822_display_hdrvalue_tobuf_save(const char *ptr, size_t cnt,
648 void *s)
649{
650 if (cnt)
651 memcpy(((struct rfc822_display_hdrvalue_tobuf_s *)s)->buf,
652 ptr, cnt);
653
654 ((struct rfc822_display_hdrvalue_tobuf_s *)s)->buf += cnt;
655}
656
657static void rfc822_display_hdrvalue_tobuf_errfunc(const char *ptr, int index,
658 void *s)
659{
660 void (*f)(const char *, int, void *)=
661 ((struct rfc822_display_hdrvalue_tobuf_s *)s)->orig_err_func;
662
663 if (f)
664 f(ptr, index,
665 ((struct rfc822_display_hdrvalue_tobuf_s *)s)->orig_ptr);
666}
667
668char *rfc822_display_addr_tobuf(const struct rfc822a *rfcp, int index,
669 const char *chset)
670{
671 struct rfc822_display_hdrvalue_tobuf_s nbuf;
672 int errcode;
673 char *ptr;
674
675 nbuf.buf=0;
676 nbuf.cnt=1;
677
678 errcode=rfc822_display_addr(rfcp, index, chset,
679 rfc822_display_hdrvalue_tobuf_cnt, &nbuf);
680
681 if (errcode < 0)
682 return NULL;
683
684 ptr=nbuf.buf=malloc(nbuf.cnt);
685 nbuf.cnt=0;
686 if (!ptr)
687 return NULL;
688
689 errcode=rfc822_display_addr(rfcp, index, chset,
690 rfc822_display_hdrvalue_tobuf_save, &nbuf);
691
692 if (errcode < 0)
693 {
694 free(nbuf.buf);
695 return NULL;
696 }
697 *nbuf.buf=0;
698 return ptr;
699}
700
701char *rfc822_display_hdrvalue_tobuf(const char *hdrname,
702 const char *hdrvalue,
703 const char *charset,
704 void (*err_func)(const char *, int,
705 void *),
706 void *ptr)
707{
708 struct rfc822_display_hdrvalue_tobuf_s s;
709 int errcode;
710 char *bufptr;
711
712 s.orig_err_func=err_func;
713 s.orig_ptr=ptr;
714 s.cnt=1;
715
716 errcode=rfc822_display_hdrvalue(hdrname, hdrvalue, charset,
717 rfc822_display_hdrvalue_tobuf_cnt,
718 rfc822_display_hdrvalue_tobuf_errfunc,
719 &s);
720
721 if (errcode < 0)
722 return NULL;
723
724 bufptr=s.buf=malloc(s.cnt);
725
726 if (!bufptr)
727 return NULL;
728
729 errcode=rfc822_display_hdrvalue(hdrname, hdrvalue, charset,
730 rfc822_display_hdrvalue_tobuf_save,
731 rfc822_display_hdrvalue_tobuf_errfunc,
732 &s);
733 if (errcode)
734 {
735 free(bufptr);
736 return NULL;
737 }
738 *s.buf=0;
739 return bufptr;
740}
741
742char *rfc822_display_addr_str_tobuf(const char *tok, const char *chset)
743{
744 struct rfc822_display_hdrvalue_tobuf_s s;
745 int errcode;
746 char *bufptr;
747
748 s.cnt=1;
749
750 errcode=rfc822_display_addr_str(tok, chset,
751 rfc822_display_hdrvalue_tobuf_cnt,
752 &s);
753
754 if (errcode < 0)
755 return NULL;
756
757 bufptr=s.buf=malloc(s.cnt);
758
759 if (!bufptr)
760 return NULL;
761
762 errcode=rfc822_display_addr_str(tok, chset,
763 rfc822_display_hdrvalue_tobuf_save,
764 &s);
765 if (errcode < 0)
766 {
767 free(bufptr);
768 return NULL;
769 }
770 *s.buf=0;
771 return bufptr;
772}
773
774
775static const char xdigit[]="0123456789ABCDEFabcdef";
776
777static const unsigned char decode64tab[]={
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
780 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
781 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 99, 0, 0,
782 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
783 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
784 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
785 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0,
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, 0, 0, 0, 0, 0,
789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
790 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
791 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
792 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
793 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
794};
795
796static int nyb(int c)
797{
798 const char *p;
799 int n;
800
801 p=strchr(xdigit, c);
802
803 if (!p)
804 return 0;
805
806 n=p-xdigit;
807
808 if (n > 15)
809 n -= 6;
810
811 return n;
812}
813
814static size_t decodebase64(const char *ptr, size_t cnt,
815 char *dec_buf)
816{
817 size_t i, j;
818 char a,b,c;
819 size_t k;
820
821 i=cnt / 4;
822 i=i*4;
823 k=0;
824 for (j=0; j<i; j += 4)
825 {
826 int w=decode64tab[(int)(unsigned char)ptr[j]];
827 int x=decode64tab[(int)(unsigned char)ptr[j+1]];
828 int y=decode64tab[(int)(unsigned char)ptr[j+2]];
829 int z=decode64tab[(int)(unsigned char)ptr[j+3]];
830
831 a= (w << 2) | (x >> 4);
832 b= (x << 4) | (y >> 2);
833 c= (y << 6) | z;
834 dec_buf[k++]=a;
835 if ( ptr[j+2] != '=')
836 dec_buf[k++]=b;
837 if ( ptr[j+3] != '=')
838 dec_buf[k++]=c;
839 }
840 return (k);
841}
842
843
844static ssize_t rfc822_decode_rfc2047_atom(const char *str,
845 size_t cnt,
846
847 void (*callback)(const char *,
848 const char *,
849 const char *,
850 size_t,
851 void *),
852 void *ptr)
853{
854 const char *chset_str;
855 const char *enc_str;
856 const char *content_str;
857
858 char *chset;
859 char *lang;
860
861 char *content;
862
863 size_t i;
864 size_t j;
865 size_t k;
866
867 size_t content_len;
868
869 if (cnt < 2 || str[0] != '=' || str[1] != '?')
870 return 0;
871
872 chset_str=str+2;
873
874 for (i=2; i<cnt; i++)
875 if (str[i] == '?')
876 break;
877
878 if (i >= cnt)
879 return 0;
880
881 enc_str= str + ++i;
882
883 for (; i < cnt; i++)
884 if (str[i] == '?')
885 break;
886
887 if (i >= cnt)
888 return 0;
889
890 content_str= str + ++i;
891
892 while (1)
893 {
894 if (cnt-i < 2)
895 return 0;
896
897 if (str[i] == '?' && str[i+1] == '=')
898 break;
899 ++i;
900 }
901
902 for (j=0; chset_str[j] != '?'; ++j)
903 ;
904
905 chset=malloc(j+1);
906
907 if (!chset)
908 return -1;
909
910 memcpy(chset, chset_str, j);
911 chset[j]=0;
912
913 lang=strchr(chset, '*'); /* RFC 2231 */
914
915 if (lang)
916 *lang++ = 0;
917 else
918 lang="";
919
920 content_len=str + i - content_str;
921
922 content=malloc(content_len+1);
923
924 if (!content)
925 {
926 free(chset);
927 return -1;
928 }
929
930 switch (*enc_str) {
931 case 'q':
932 case 'Q':
933
934 k=0;
935 for (j=0; j<content_len; j++)
936 {
937 char c;
938
939 if (content_str[j] == '=' && i-j >= 3)
940 {
941 content[k]=(char)(nyb(content_str[j+1])*16 +
942 nyb(content_str[j+2]));
943 ++k;
944 j += 2;
945 continue;
946 }
947
948 c=content_str[j];
949 if (c == '_')
950 c=' ';
951 content[k]=c;
952 ++k;
953 }
954 break;
955
956 case 'b':
957 case 'B':
958 k=decodebase64(content_str, content_len, content);
959 break;
960 default:
961 free(content);
962 free(chset);
963 return (0);
964 }
965
966 if (callback)
967 (*callback)(chset, lang, content, k, ptr);
968 free(content);
969 free(chset);
970 return i + 2;
971}
972
973int rfc2047_decoder(const char *text,
974 void (*callback)(const char *chset,
975 const char *lang,
976 const char *content,
977 size_t cnt,
978 void *dummy),
979 void *ptr)
980{
981 ssize_t rc;
982
983 while (text && *text)
984 {
985 size_t i;
986
987 for (i=0; text[i]; i++)
988 {
989 if (text[i] == '=' && text[i+1] == '?')
990 break;
991 }
992
993 if (i)
0e333c05 994 (*callback)("utf-8", "", text, i, ptr);
8d138742
CE
995
996 text += i;
997
998 if (!*text)
999 continue;
1000
1001 rc=rfc822_decode_rfc2047_atom(text, strlen(text),
1002 callback, ptr);
1003
1004 if (rc < 0)
1005 return -1;
1006
1007 if (rc == 0)
1008 {
0e333c05 1009 (*callback)("utf-8", "", text, 2, ptr);
8d138742
CE
1010 text += 2;
1011 continue;
1012 }
1013
1014 text += rc;
1015
1016 for (i=0; text[i]; i++)
1017 {
1018 if (strchr(" \t\r\n", text[i]) == NULL)
1019 break;
1020 }
1021
1022 if (text[i] != '=' || text[i+1] != '?')
1023 continue;
1024
1025 rc=rfc822_decode_rfc2047_atom(text+i, strlen(text+i), NULL,
1026 NULL);
1027
1028 if (rc < 0)
1029 return -1;
1030 if (rc > 0)
1031 text += i;
1032 }
1033
1034 return 0;
1035}
1036
1037static int rfc2047_decode_unicode(const char *text,
b0322a85 1038 const char *chset,
8d138742
CE
1039 void (*callback)(const char *, size_t,
1040 void *),
1041 void *ptr)
1042{
1043 struct rfc822_display_name_s s;
1044
b0322a85 1045 s.chset=chset;
8d138742
CE
1046 s.print_func=callback;
1047 s.ptr=ptr;
1048
1049 return rfc2047_decoder(text, rfc822_display_addr_cb, &s);
1050}