Andreas Krennmair:
[apps/madmutt.git] / rfc2047.c
1 /*
2  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
3  * Copyright (C) 2000-2001 Edmund Grimley Evans <edmundo@rano.org>
4  * 
5  *     This program is free software; you can redistribute it and/or modify
6  *     it under the terms of the GNU General Public License as published by
7  *     the Free Software Foundation; either version 2 of the License, or
8  *     (at your option) any later version.
9  * 
10  *     This program is distributed in the hope that it will be useful,
11  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *     GNU General Public License for more details.
14  * 
15  *     You should have received a copy of the GNU General Public License
16  *     along with this program; if not, write to the Free Software
17  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
18  */ 
19
20 #include "mutt.h"
21 #include "mime.h"
22 #include "charset.h"
23 #include "rfc2047.h"
24
25 #include <ctype.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 /* If you are debugging this file, comment out the following line. */
32 /*#define NDEBUG*/
33
34 #ifdef NDEBUG
35 #define assert(x)
36 #else
37 #include <assert.h>
38 #endif
39
40 #define ENCWORD_LEN_MAX 75
41 #define ENCWORD_LEN_MIN 9 /* strlen ("=?.?.?.?=") */
42
43 #define HSPACE(x) ((x) == '\0' || (x) == ' ' || (x) == '\t')
44
45 #define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80)
46
47 extern char RFC822Specials[];
48
49 typedef size_t (*encoder_t) (char *, ICONV_CONST char *, size_t,
50                              const char *);
51
52 static size_t convert_string (ICONV_CONST char *f, size_t flen,
53                               const char *from, const char *to,
54                               char **t, size_t *tlen)
55 {
56   iconv_t cd;
57   char *buf, *ob;
58   size_t obl, n;
59   int e;
60
61   cd = mutt_iconv_open (to, from, 0);
62   if (cd == (iconv_t)(-1))
63     return (size_t)(-1);
64   obl = 4 * flen + 1;
65   ob = buf = safe_malloc (obl);
66   n = iconv (cd, &f, &flen, &ob, &obl);
67   if (n == (size_t)(-1) || iconv (cd, 0, 0, &ob, &obl) == (size_t)(-1))
68   {
69     e = errno;
70     FREE (&buf);
71     iconv_close (cd);
72     errno = e;
73     return (size_t)(-1);
74   }
75   *ob = '\0';
76   
77   *tlen = ob - buf;
78
79   safe_realloc (&buf, ob - buf + 1);
80   *t = buf;
81   iconv_close (cd);
82
83   return n;
84 }
85
86 char *mutt_choose_charset (const char *fromcode, const char *charsets,
87                       char *u, size_t ulen, char **d, size_t *dlen)
88 {
89   char canonical_buff[LONG_STRING];
90   char *e = 0, *tocode = 0;
91   size_t elen = 0, bestn = 0;
92   const char *p, *q;
93
94   for (p = charsets; p; p = q ? q + 1 : 0)
95   {
96     char *s, *t;
97     size_t slen, n;
98
99     q = strchr (p, ':');
100
101     n = q ? q - p : strlen (p);
102
103     if (!n ||
104         /* Assume that we never need more than 12 characters of
105            encoded-text to encode a single character. */
106         n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12))
107       continue;
108
109     t = safe_malloc (n + 1);
110     memcpy (t, p, n);
111     t[n] = '\0';
112
113     n = convert_string (u, ulen, fromcode, t, &s, &slen);
114     if (n == (size_t)(-1))
115       continue;
116
117     if (!tocode || n < bestn)
118     {
119       bestn = n;
120       FREE (&tocode);
121       tocode = t;
122       if (d)
123       {
124         FREE (&e);
125         e = s;
126       }
127       else
128         FREE (&s);
129       elen = slen;
130       if (!bestn)
131         break;
132     }
133     else
134     {
135       FREE (&t);
136       FREE (&s);
137     }
138   }
139   if (tocode)
140   {
141     if (d)
142       *d = e;
143     if (dlen)
144       *dlen = elen;
145     
146     mutt_canonical_charset (canonical_buff, sizeof (canonical_buff), tocode);
147     mutt_str_replace (&tocode, canonical_buff);
148   }
149   return tocode;
150 }
151
152 static size_t b_encoder (char *s, ICONV_CONST char *d, size_t dlen,
153                          const char *tocode)
154 {
155   char *s0 = s;
156
157   memcpy (s, "=?", 2), s += 2;
158   memcpy (s, tocode, strlen (tocode)), s += strlen (tocode);
159   memcpy (s, "?B?", 3), s += 3;
160   for (;;)
161   {
162     if (!dlen)
163       break;
164     else if (dlen == 1)
165     {
166       *s++ = B64Chars[(*d >> 2) & 0x3f];
167       *s++ = B64Chars[(*d & 0x03) << 4];
168       *s++ = '=';
169       *s++ = '=';
170       break;
171     }
172     else if (dlen == 2)
173     {
174       *s++ = B64Chars[(*d >> 2) & 0x3f];
175       *s++ = B64Chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
176       *s++ = B64Chars[(d[1] & 0x0f) << 2];
177       *s++ = '=';
178       break;
179     }
180     else
181     {
182       *s++ = B64Chars[(*d >> 2) & 0x3f];
183       *s++ = B64Chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
184       *s++ = B64Chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)];
185       *s++ = B64Chars[d[2] & 0x3f];
186       d += 3, dlen -= 3;
187     }
188   }
189   memcpy (s, "?=", 2), s += 2;
190   return s - s0;
191 }
192
193 static size_t q_encoder (char *s, ICONV_CONST char *d, size_t dlen,
194                          const char *tocode)
195 {
196   char hex[] = "0123456789ABCDEF";
197   char *s0 = s;
198
199   memcpy (s, "=?", 2), s += 2;
200   memcpy (s, tocode, strlen (tocode)), s += strlen (tocode);
201   memcpy (s, "?Q?", 3), s += 3;
202   while (dlen--)
203   {
204     unsigned char c = *d++;
205     if (c == ' ')
206       *s++ = '_';
207     else if (c >= 0x7f || c < 0x20 || c == '_' ||  strchr (MimeSpecials, c))
208     {
209       *s++ = '=';
210       *s++ = hex[(c & 0xf0) >> 4];
211       *s++ = hex[c & 0x0f];
212     }
213     else
214       *s++ = c;
215   }
216   memcpy (s, "?=", 2), s += 2;
217   return s - s0;
218 }
219
220 /*
221  * Return 0 if and set *encoder and *wlen if the data (d, dlen) could
222  * be converted to an encoded word of length *wlen using *encoder.
223  * Otherwise return an upper bound on the maximum length of the data
224  * which could be converted.
225  * The data is converted from fromcode (which must be stateless) to
226  * tocode, unless fromcode is 0, in which case the data is assumed to
227  * be already in tocode, which should be 8-bit and stateless.
228  */
229 static size_t try_block (ICONV_CONST char *d, size_t dlen,
230                          const char *fromcode, const char *tocode,
231                          encoder_t *encoder, size_t *wlen)
232 {
233   char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
234   iconv_t cd;
235   ICONV_CONST char *ib;
236   char *ob, *p;
237   size_t ibl, obl;
238   int count, len, len_b, len_q;
239
240   if (fromcode)
241   {
242     cd = mutt_iconv_open (tocode, fromcode, 0);
243     assert (cd != (iconv_t)(-1));
244     ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - strlen (tocode);
245     if (iconv (cd, &ib, &ibl, &ob, &obl) == (size_t)(-1) ||
246         iconv (cd, 0, 0, &ob, &obl) == (size_t)(-1))
247     {
248       assert (errno == E2BIG);
249       iconv_close (cd);
250       assert (ib > d);
251       return (ib - d == dlen) ? dlen : ib - d + 1;
252     }
253     iconv_close (cd);
254   }
255   else
256   {
257     if (dlen > sizeof (buf1) - strlen (tocode))
258       return sizeof (buf1) - strlen (tocode) + 1;
259     memcpy (buf1, d, dlen);
260     ob = buf1 + dlen;
261   }
262
263   count = 0;
264   for (p = buf1; p < ob; p++)
265   {
266     unsigned char c = *p;
267     assert (strchr (MimeSpecials, '?'));
268     if (c >= 0x7f || c < 0x20 || *p == '_' ||
269         (c != ' ' && strchr (MimeSpecials, *p)))
270       ++count;
271   }
272
273   len = ENCWORD_LEN_MIN - 2 + strlen (tocode);
274   len_b = len + (((ob - buf1) + 2) / 3) * 4;
275   len_q = len + (ob - buf1) + 2 * count;
276
277   /* Apparently RFC 1468 says to use B encoding for iso-2022-jp. */
278   if (!ascii_strcasecmp (tocode, "ISO-2022-JP"))
279     len_q = ENCWORD_LEN_MAX + 1;
280
281   if (len_b < len_q && len_b <= ENCWORD_LEN_MAX)
282   {
283     *encoder = b_encoder;
284     *wlen = len_b;
285     return 0;
286   }
287   else if (len_q <= ENCWORD_LEN_MAX)
288   {
289     *encoder = q_encoder;
290     *wlen = len_q;
291     return 0;
292   }
293   else
294     return dlen;
295 }
296
297 /*
298  * Encode the data (d, dlen) into s using the encoder.
299  * Return the length of the encoded word.
300  */
301 static size_t encode_block (char *s, char *d, size_t dlen,
302                             const char *fromcode, const char *tocode,
303                             encoder_t encoder)
304 {
305   char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
306   iconv_t cd;
307   ICONV_CONST char *ib;
308   char *ob;
309   size_t ibl, obl, n1, n2;
310
311   if (fromcode)
312   {
313     cd = mutt_iconv_open (tocode, fromcode, 0);
314     assert (cd != (iconv_t)(-1));
315     ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - strlen (tocode);
316     n1 = iconv (cd, &ib, &ibl, &ob, &obl);
317     n2 = iconv (cd, 0, 0, &ob, &obl);
318     assert (n1 != (size_t)(-1) && n2 != (size_t)(-1));
319     iconv_close (cd);
320     return (*encoder) (s, buf1, ob - buf1, tocode);
321   }
322   else
323     return (*encoder) (s, d, dlen, tocode);
324 }
325
326 /*
327  * Discover how much of the data (d, dlen) can be converted into
328  * a single encoded word. Return how much data can be converted,
329  * and set the length *wlen of the encoded word and *encoder.
330  * We start in column col, which limits the length of the word.
331  */
332 static size_t choose_block (char *d, size_t dlen, int col,
333                             const char *fromcode, const char *tocode,
334                             encoder_t *encoder, size_t *wlen)
335 {
336   size_t n, nn;
337   int utf8 = fromcode && !ascii_strcasecmp (fromcode, "UTF-8");
338
339   n = dlen;
340   for (;;)
341   {
342     assert (d + n > d);
343     nn = try_block (d, n, fromcode, tocode, encoder, wlen);
344     if (!nn && (col + *wlen <= ENCWORD_LEN_MAX + 1 || n <= 1))
345       break;
346     n = (nn ? nn : n) - 1;
347     assert (n > 0);
348     if (utf8)
349       while (n > 1 && CONTINUATION_BYTE(d[n]))
350         --n;
351   }
352   return n;
353 }
354
355 /*
356  * Place the result of RFC-2047-encoding (d, dlen) into the dynamically
357  * allocated buffer (e, elen). The input data is in charset fromcode
358  * and is converted into a charset chosen from charsets.
359  * Return 1 if the conversion to UTF-8 failed, 2 if conversion from UTF-8
360  * failed, otherwise 0. If conversion failed, fromcode is assumed to be
361  * compatible with us-ascii and the original data is used.
362  * The input data is assumed to be a single line starting at column col;
363  * if col is non-zero, the preceding character was a space.
364  */
365 static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
366                            const char *fromcode, const char *charsets,
367                            char **e, size_t *elen, char *specials)
368 {
369   int ret = 0;
370   char *buf;
371   size_t bufpos, buflen;
372   char *u, *t0, *t1, *t;
373   char *s0, *s1;
374   size_t ulen, r, n, wlen;
375   encoder_t encoder;
376   char *tocode1 = 0;
377   const char *tocode;
378   char *icode = "UTF-8";
379
380   /* Try to convert to UTF-8. */
381   if (convert_string (d, dlen, fromcode, icode, &u, &ulen))
382   {
383     ret = 1; 
384     icode = 0;
385     u = safe_malloc ((ulen = dlen) + 1);
386     memcpy (u, d, dlen);
387     u[ulen] = 0;
388   }
389
390   /* Find earliest and latest things we must encode. */
391   s0 = s1 = t0 = t1 = 0;
392   for (t = u; t < u + ulen; t++)
393   {
394     if ((*t & 0x80) || 
395         (*t == '=' && t[1] == '?' && (t == u || HSPACE(*(t-1)))))
396     {
397       if (!t0) t0 = t;
398       t1 = t;
399     }
400     else if (specials && strchr (specials, *t))
401     {
402       if (!s0) s0 = t;
403       s1 = t;
404     }
405   }
406
407   /* If we have something to encode, include RFC822 specials */
408   if (t0 && s0 && s0 < t0)
409     t0 = s0;
410   if (t1 && s1 && s1 > t1)
411     t1 = s1;
412
413   if (!t0)
414   {
415     /* No encoding is required. */
416     *e = u;
417     *elen = ulen;
418     return ret;
419   }
420
421   /* Choose target charset. */
422   tocode = fromcode;
423   if (icode)
424   {
425     if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0)))
426       tocode = tocode1;
427     else
428       ret = 2, icode = 0;
429   }
430
431   /* Hack to avoid labelling 8-bit data as us-ascii. */
432   if (!icode && mutt_is_us_ascii (tocode))
433     tocode = "unknown-8bit";
434   
435   /* Adjust t0 for maximum length of line. */
436   t = u + (ENCWORD_LEN_MAX + 1) - col - ENCWORD_LEN_MIN;
437   if (t < u)  t = u;
438   if (t < t0) t0 = t;
439   
440
441   /* Adjust t0 until we can encode a character after a space. */
442   for (; t0 > u; t0--)
443   {
444     if (!HSPACE(*(t0-1)))
445       continue;
446     t = t0 + 1;
447     if (icode)
448       while (t < u + ulen && CONTINUATION_BYTE(*t))
449         ++t;
450     if (!try_block (t0, t - t0, icode, tocode, &encoder, &wlen) &&
451         col + (t0 - u) + wlen <= ENCWORD_LEN_MAX + 1)
452       break;
453   }
454
455   /* Adjust t1 until we can encode a character before a space. */
456   for (; t1 < u + ulen; t1++)
457   {
458     if (!HSPACE(*t1))
459       continue;
460     t = t1 - 1;
461     if (icode)
462       while (CONTINUATION_BYTE(*t))
463         --t;
464     if (!try_block (t, t1 - t, icode, tocode, &encoder, &wlen) &&
465         1 + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
466       break;
467   }
468
469   /* We shall encode the region [t0,t1). */
470
471   /* Initialise the output buffer with the us-ascii prefix. */
472   buflen = 2 * ulen;
473   buf = safe_malloc (buflen);
474   bufpos = t0 - u;
475   memcpy (buf, u, t0 - u);
476
477   col += t0 - u;
478
479   t = t0;
480   for (;;)
481   {
482     /* Find how much we can encode. */
483     n = choose_block (t, t1 - t, col, icode, tocode, &encoder, &wlen);
484     if (n == t1 - t)
485     {
486       /* See if we can fit the us-ascii suffix, too. */
487       if (col + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
488         break;
489       n = t1 - t - 1;
490       if (icode)
491         while (CONTINUATION_BYTE(t[n]))
492           --n;
493       assert (t + n >= t);
494       if (!n)
495       {
496         /* This should only happen in the really stupid case where the
497            only word that needs encoding is one character long, but
498            there is too much us-ascii stuff after it to use a single
499            encoded word. We add the next word to the encoded region
500            and try again. */
501         assert (t1 < u + ulen);
502         for (t1++; t1 < u + ulen && !HSPACE(*t1); t1++)
503           ;
504         continue;
505       }
506       n = choose_block (t, n, col, icode, tocode, &encoder, &wlen);
507     }
508
509     /* Add to output buffer. */
510 #define LINEBREAK "\n\t"
511     if (bufpos + wlen + strlen (LINEBREAK) > buflen)
512     {
513       buflen = bufpos + wlen + strlen (LINEBREAK);
514       safe_realloc (&buf, buflen);
515     }
516     r = encode_block (buf + bufpos, t, n, icode, tocode, encoder);
517     assert (r == wlen);
518     bufpos += wlen;
519     memcpy (buf + bufpos, LINEBREAK, strlen (LINEBREAK));
520     bufpos += strlen (LINEBREAK);
521 #undef LINEBREAK
522
523     col = 1;
524
525     t += n;
526   }
527
528   /* Add last encoded word and us-ascii suffix to buffer. */
529   buflen = bufpos + wlen + (u + ulen - t1);
530   safe_realloc (&buf, buflen + 1);
531   r = encode_block (buf + bufpos, t, t1 - t, icode, tocode, encoder);
532   assert (r == wlen);
533   bufpos += wlen;
534   memcpy (buf + bufpos, t1, u + ulen - t1);
535
536   FREE (&tocode1);
537   FREE (&u);
538
539   buf[buflen] = '\0';
540   
541   *e = buf;
542   *elen = buflen + 1;
543   return ret;
544 }
545
546 void _rfc2047_encode_string (char **pd, int encode_specials, int col)
547 {
548   char *e;
549   size_t elen;
550   char *charsets;
551
552   if (!Charset || !*pd)
553     return;
554
555   charsets = SendCharset;
556   if (!charsets || !*charsets)
557     charsets = "UTF-8";
558
559   rfc2047_encode (*pd, strlen (*pd), col,
560                   Charset, charsets, &e, &elen,
561                   encode_specials ? RFC822Specials : NULL);
562
563   FREE (pd);
564   *pd = e;
565 }
566
567 void rfc2047_encode_adrlist (ADDRESS *addr, const char *tag)
568 {
569   ADDRESS *ptr = addr;
570   int col = tag ? strlen (tag) + 2 : 32;
571   
572   while (ptr)
573   {
574     if (ptr->personal)
575       _rfc2047_encode_string (&ptr->personal, 1, col);
576 #ifdef EXACT_ADDRESS
577     if (ptr->val)
578       _rfc2047_encode_string (&ptr->val, 1, col);
579 #endif
580     ptr = ptr->next;
581   }
582 }
583
584 static int rfc2047_decode_word (char *d, const char *s, size_t len)
585 {
586   const char *pp, *pp1;
587   char *pd, *d0;
588   const char *t, *t1;
589   int enc = 0, count = 0;
590   char *charset = NULL;
591
592   pd = d0 = safe_malloc (strlen (s));
593
594   for (pp = s; (pp1 = strchr (pp, '?')); pp = pp1 + 1)
595   {
596     count++;
597     switch (count)
598     {
599       case 2:
600         /* ignore language specification a la RFC 2231 */        
601         t = pp1;
602         if ((t1 = memchr (pp, '*', t - pp)))
603           t = t1;
604         charset = safe_malloc (t - pp + 1);
605         memcpy (charset, pp, t - pp);
606         charset[t-pp] = '\0';
607         break;
608       case 3:
609         if (toupper ((unsigned char) *pp) == 'Q')
610           enc = ENCQUOTEDPRINTABLE;
611         else if (toupper ((unsigned char) *pp) == 'B')
612           enc = ENCBASE64;
613         else
614         {
615           FREE (&charset);
616           FREE (&d0);
617           return (-1);
618         }
619         break;
620       case 4:
621         if (enc == ENCQUOTEDPRINTABLE)
622         {
623           for (; pp < pp1; pp++)
624           {
625             if (*pp == '_')
626               *pd++ = ' ';
627             else if (*pp == '=' &&
628                      (!(pp[1] & ~127) && hexval(pp[1]) != -1) &&
629                      (!(pp[2] & ~127) && hexval(pp[2]) != -1))
630             {
631               *pd++ = (hexval(pp[1]) << 4) | hexval(pp[2]);
632               pp += 2;
633             }
634             else
635               *pd++ = *pp;
636           }
637           *pd = 0;
638         }
639         else if (enc == ENCBASE64)
640         {
641           int c, b = 0, k = 0;
642
643           for (; pp < pp1; pp++)
644           {
645             if (*pp == '=')
646               break;
647             if ((*pp & ~127) || (c = base64val(*pp)) == -1)
648               continue;
649             if (k + 6 >= 8)
650             {
651               k -= 2;
652               *pd++ = b | (c >> k);
653               b = c << (8 - k);
654             }
655             else
656             {
657               b |= c << (k + 2);
658               k += 6;
659             }
660           }
661           *pd = 0;
662         }
663         break;
664     }
665   }
666   
667   if (charset)
668     mutt_convert_string (&d0, charset, Charset, M_ICONV_HOOK_FROM);
669   strfcpy (d, d0, len);
670   FREE (&charset);
671   FREE (&d0);
672   return (0);
673 }
674
675 /*
676  * Find the start and end of the first encoded word in the string.
677  * We use the grammar in section 2 of RFC 2047, but the "encoding"
678  * must be B or Q. Also, we don't require the encoded word to be
679  * separated by linear-white-space (section 5(1)).
680  */
681 static const char *find_encoded_word (const char *s, const char **x)
682 {
683   const char *p, *q;
684
685   q = s;
686   while ((p = strstr (q, "=?")))
687   {
688     for (q = p + 2;
689          0x20 < *q && *q < 0x7f && !strchr ("()<>@,;:\"/[]?.=", *q);
690          q++)
691       ;
692     if (q[0] != '?' || !strchr ("BbQq", q[1]) || q[2] != '?')
693       continue;
694     for (q = q + 3; 0x20 <= *q && *q < 0x7f && *q != '?'; q++)
695       ;
696     if (q[0] != '?' || q[1] != '=')
697     {
698       --q;
699       continue;
700     }
701
702     *x = q + 2;
703     return p;
704   }
705
706   return 0;
707 }
708
709 /* try to decode anything that looks like a valid RFC2047 encoded
710  * header field, ignoring RFC822 parsing rules
711  */
712 void rfc2047_decode (char **pd)
713 {
714   const char *p, *q;
715   size_t n;
716   int found_encoded = 0;
717   char *d0, *d;
718   const char *s = *pd;
719   size_t dlen;
720
721   if (!s || !*s)
722     return;
723
724   dlen = 4 * strlen (s); /* should be enough */
725   d = d0 = safe_malloc (dlen + 1);
726
727   while (*s && dlen > 0)
728   {
729     if (!(p = find_encoded_word (s, &q)))
730     {
731       /* no encoded words */
732       strncpy (d, s, dlen);
733       d += dlen;
734       break;
735     }
736
737     if (p != s)
738     {
739       n = (size_t) (p - s);
740       /* ignore spaces between encoded words */
741       if (!found_encoded || strspn (s, " \t\r\n") != n)
742       {
743         if (n > dlen)
744           n = dlen;
745         memcpy (d, s, n);
746         d += n;
747         dlen -= n;
748       }
749     }
750
751     rfc2047_decode_word (d, p, dlen);
752     found_encoded = 1;
753     s = q;
754     n = mutt_strlen (d);
755     dlen -= n;
756     d += n;
757   }
758   *d = 0;
759
760   FREE (pd);
761   *pd = d0;
762   mutt_str_adjust (pd);
763 }
764
765 void rfc2047_decode_adrlist (ADDRESS *a)
766 {
767   while (a)
768   {
769     if (a->personal && strstr (a->personal, "=?") != NULL) {
770       rfc2047_decode (&a->personal);
771     }
772 #ifdef EXACT_ADDRESS
773     if (a->val && strstr (a->val, "=?") != NULL)
774       rfc2047_decode (&a->val);
775 #endif
776     a = a->next;
777   }
778 }