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