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 
save_unicode_text(const char * p,size_t l,void * ptr)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 
unknown_charset(const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc822_display_addr_cb(const char * chset,const char * lang,const char * content,size_t cnt,void * dummy)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
rfc822_display_name_int(const struct rfc822a * rfcp,int index,const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc822_display_name(const struct rfc822a * rfcp,int index,const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc822_display_name_tobuf(const struct rfc822a * rfcp,int index,const char * chset)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 
rfc822_display_namelist(const struct rfc822a * rfcp,const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc822_display_addr_str(const char * tok,const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc822_display_addr(const struct rfc822a * rfcp,int index,const char * chset,void (* print_func)(const char *,size_t,void *),void * ptr)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 
rfc2047_print_unicodeaddr(const struct rfc822a * a,const char * charset,void (* print_func)(char,void *),void (* print_separator)(const char *,void *),void * ptr)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 
rfc2047_print_unicode_addrstr(const char * addrheader,const char * charset,void (* print_func)(char,void *),void (* print_separator)(const char *,void *),void (* err_func)(const char *,int,void *),void * ptr)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 
rfc822_display_hdrvalue_print_func(char c,void * ptr)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 
rfc822_display_hdrvalue_print_separator(const char * cp,void * ptr)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 
rfc822_display_hdrvalue(const char * hdrname,const char * hdrvalue,const char * charset,void (* display_func)(const char *,size_t,void *),void (* err_func)(const char *,int,void *),void * ptr)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 
rfc822_display_hdrvalue_tobuf_cnt(const char * ptr,size_t cnt,void * s)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 
rfc822_display_hdrvalue_tobuf_save(const char * ptr,size_t cnt,void * s)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 
rfc822_display_hdrvalue_tobuf_errfunc(const char * ptr,int index,void * s)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 
rfc822_display_addr_tobuf(const struct rfc822a * rfcp,int index,const char * chset)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 
rfc822_display_hdrvalue_tobuf(const char * hdrname,const char * hdrvalue,const char * charset,void (* err_func)(const char *,int,void *),void * ptr)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 
rfc822_display_addr_str_tobuf(const char * tok,const char * chset)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 
nyb(int c)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 
decodebase64(const char * ptr,size_t cnt,char * dec_buf)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 
rfc822_decode_rfc2047_atom(const char * str,size_t cnt,void (* callback)(const char *,const char *,const char *,size_t,void *),void * ptr)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 
rfc2047_decoder(const char * text,void (* callback)(const char * chset,const char * lang,const char * content,size_t cnt,void * dummy),void * ptr)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 
rfc2047_decode_unicode(const char * text,const struct unicode_info * u,void (* callback)(const char *,size_t,void *),void * ptr)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 }
1059