Back to index

courier  0.68.2
rfc2047u.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2009 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 #include      "rfc822.h"
00007 #include      <stdio.h>
00008 #include      <ctype.h>
00009 #include      <string.h>
00010 #include      <stdlib.h>
00011 #include      <errno.h>
00012 
00013 #include      "rfc822hdr.h"
00014 #include      "rfc2047.h"
00015 #include      "../unicode/unicode.h"
00016 
00017 #if LIBIDN
00018 #include <idna.h>
00019 #include <stringprep.h>
00020 #endif
00021 
00022 
00023 static ssize_t rfc822_decode_rfc2047_atom(const char *str,
00024                                      size_t cnt,
00025 
00026                                      void (*callback)(const char *,
00027                                                     const char *,
00028                                                     const char *,
00029                                                     size_t,
00030                                                     void *),
00031                                      void *ptr);
00032 
00033 static int rfc2047_decode_unicode(const char *text,
00034                               const char *chset,
00035                               void (*callback)(const char *, size_t,
00036                                              void *),
00037                               void *ptr);
00038 
00039 struct decode_unicode_s {
00040        const char *mychset;
00041 
00042        char *bufptr;
00043        size_t bufsize;
00044 } ;
00045 
00046 static void save_unicode_text(const char *p, size_t l, void *ptr)
00047 {
00048        struct decode_unicode_s *s=
00049               (struct decode_unicode_s *)ptr;
00050 
00051        if (s->bufptr)
00052               memcpy(s->bufptr+s->bufsize, p, l);
00053 
00054        s->bufsize += l;
00055 }
00056 
00057 struct rfc822_display_name_s {
00058        const char *chset;
00059        void (*print_func)(const char *, size_t, void *);
00060        void *ptr;
00061 };
00062 
00063 static void unknown_charset(const char *chset,
00064                          const char *tochset,
00065                          void (*print_func)(const char *, size_t, void *),
00066                          void *ptr)
00067 {
00068        static const char unknown[]="[unknown character set: ";
00069 
00070        (*print_func)(unknown, sizeof(unknown)-1, ptr);
00071        (*print_func)(chset, strlen(chset), ptr);
00072        (*print_func)(" -> ", 4, ptr);
00073        (*print_func)(tochset, strlen(tochset), ptr);
00074        (*print_func)("]", 1, ptr);
00075 }
00076 
00077 static void rfc822_display_addr_cb(const char *chset,
00078                                const char *lang,
00079                                const char *content,
00080                                size_t cnt,
00081                                void *dummy)
00082 {
00083        struct rfc822_display_name_s *s=
00084               (struct rfc822_display_name_s *)dummy;
00085        char *ptr;
00086        char *buf;
00087 
00088        buf=malloc(cnt+1);
00089 
00090        if (!buf)
00091               return;
00092 
00093        memcpy(buf, content, cnt);
00094        buf[cnt]=0;
00095 
00096        ptr=libmail_u_convert_tobuf(buf, chset, s->chset, NULL);
00097        free(buf);
00098 
00099        if (ptr)
00100        {
00101               (*s->print_func)(ptr, strlen(ptr), s->ptr);
00102               free(ptr);
00103        }
00104        else
00105        {
00106               unknown_charset(chset, s->chset, s->print_func, s->ptr);
00107               return;
00108        }
00109 }
00110 
00111 static
00112 int rfc822_display_name_int(const struct rfc822a *rfcp, int index,
00113                          const char *chset,
00114                          void (*print_func)(const char *, size_t, void *),
00115                          void *ptr)
00116 {
00117        struct rfc822_display_name_s s;
00118        const struct rfc822addr *addrs;
00119 
00120        struct rfc822token *i;
00121        int    prev_isatom=0;
00122        int    isatom=0;
00123        ssize_t rc;
00124 
00125        if (index < 0 || index >= rfcp->naddrs)   return 0;
00126 
00127        addrs=rfcp->addrs+index;
00128 
00129        if (!addrs->name)
00130               return rfc822_display_addr(rfcp, index, chset, print_func, ptr);
00131 
00132        if (chset == NULL)
00133        {
00134               s.chset="iso-8859-1";
00135        }
00136        else
00137        {
00138               s.chset=chset;
00139        }
00140 
00141        s.print_func=print_func;
00142        s.ptr=ptr;
00143 
00144        for (i=addrs->name; i; i=i->next, prev_isatom=isatom)
00145        {
00146               isatom=rfc822_is_atom(i->token);
00147               if (isatom && prev_isatom)
00148                      (*print_func)(" ", 1, ptr);
00149 
00150               if (i->token == '"' || i->token == '(')
00151               {
00152                      size_t l=i->len;
00153                      char *p, *q, *r;
00154 
00155                      if (i->token == '(')
00156                      {
00157                             if (l > 2)
00158                                    l -= 2;
00159                             else
00160                                    l=0;
00161                      }
00162 
00163                      p=malloc(l+1);
00164 
00165                      if (!p)
00166                             return -1;
00167 
00168                      if (l)
00169                      {
00170                             if (i->token == '(')
00171                             {
00172                                    memcpy(p, i->ptr+1, l);
00173                             }
00174                             else
00175                             {
00176                                    memcpy(p, i->ptr, l);
00177                             }
00178                      }
00179 
00180 
00181                      p[l]=0;
00182 
00183                      for (q=r=p; *q; *r++ = *q++)
00184                             if (*q == '\\' && q[1])
00185                                    ++q;
00186 
00187                      *r=0;
00188 
00189                      if (chset == NULL)
00190                      {
00191                             (*print_func)(p, strlen(p), ptr);
00192                      }
00193                      else if (rfc822_display_hdrvalue("subject",
00194                                                   p, s.chset,
00195                                                   print_func,
00196                                                   NULL, ptr) < 0)
00197                      {
00198                             free(p);
00199                             return -1;
00200                      }
00201                      free(p);
00202                      continue;
00203               }
00204 
00205               if (i->token)
00206               {
00207                      char c= (char)i->token;
00208 
00209                      (*print_func)(&c, 1, ptr);
00210                      continue;
00211               }
00212 
00213               rc=chset ? rfc822_decode_rfc2047_atom(i->ptr, i->len,
00214                                                 rfc822_display_addr_cb,
00215                                                 &s):0;
00216 
00217               if (rc < 0)
00218                      return -1;
00219 
00220               if (rc == 0)
00221               {
00222                      (*print_func)(i->ptr, i->len, ptr);
00223                      continue;
00224               }
00225 
00226               if (i->next && i->next->token == 0)
00227               {
00228                      rc=rfc822_decode_rfc2047_atom(i->next->ptr,
00229                                                 i->next->len,
00230                                                 NULL, NULL);
00231 
00232                      if (rc < 0)
00233                             return -1;
00234 
00235                      if (rc > 0)
00236                             isatom=0; /* Suppress the separating space */
00237               }
00238        }
00239        return 0;
00240 }
00241 
00242 int rfc822_display_name(const struct rfc822a *rfcp, int index,
00243                      const char *chset,
00244                      void (*print_func)(const char *, size_t, void *),
00245                      void *ptr)
00246 {
00247        const struct rfc822addr *addrs;
00248 
00249        if (index < 0 || index >= rfcp->naddrs)   return 0;
00250 
00251        addrs=rfcp->addrs+index;
00252 
00253        if (!addrs->tokens)
00254               return 0;
00255 
00256        return rfc822_display_name_int(rfcp, index, chset,
00257                                    print_func, ptr);
00258 }
00259 
00260 char *rfc822_display_name_tobuf(const struct rfc822a *rfcp, int index,
00261                             const char *chset)
00262 {
00263        struct decode_unicode_s s;
00264        char *p;
00265 
00266        s.bufptr=0;
00267        s.bufsize=1;
00268 
00269        if (rfc822_display_name(rfcp, index, chset, save_unicode_text, &s) < 0)
00270               return NULL;
00271        s.bufptr=p=malloc(s.bufsize);
00272        if (!p)
00273               return (0);
00274 
00275        s.bufsize=0;
00276        if (rfc822_display_name(rfcp, index, chset, save_unicode_text, &s) < 0)
00277        {
00278               free(s.bufptr);
00279               return (0);
00280        }
00281        save_unicode_text("", 1, &s);
00282 
00283        return (p);
00284 }
00285 
00286 int rfc822_display_namelist(const struct rfc822a *rfcp,
00287                          const char *chset,
00288                          void (*print_func)(const char *, size_t, void *),
00289                          void *ptr)
00290 {
00291        int n;
00292 
00293        for (n=0; n<rfcp->naddrs; n++)
00294        {
00295               if (rfcp->addrs[n].tokens)
00296               {
00297                      int err=rfc822_display_name(rfcp, n, chset,
00298                                               print_func, ptr);
00299 
00300                      if (err < 0)
00301                             return err;
00302 
00303                      (*print_func)("\n", 1, ptr);
00304               }
00305        }
00306        return 0;
00307 }
00308 
00309 int rfc822_display_addr_str(const char *tok,
00310                          const char *chset,
00311                          void (*print_func)(const char *, size_t, void *),
00312                          void *ptr)
00313 {
00314        const char *p;
00315 
00316        p=strchr(tok,'@');
00317 
00318        if (!p)
00319               p=tok;
00320        else
00321               ++p;
00322 
00323        if (chset != NULL)
00324        {
00325               int err=0;
00326               char *utf8_ptr;
00327 
00328               if (p > tok)
00329                      (*print_func)(tok, p-tok, ptr);
00330 
00331 #if LIBIDN
00332               err=idna_to_unicode_8z8z(p, &utf8_ptr, 0);
00333               if (err != IDNA_SUCCESS)
00334                      utf8_ptr=0;
00335 #else
00336               utf8_ptr=0;
00337 #endif
00338 
00339               if (utf8_ptr == 0)
00340                      (*print_func)(p, strlen(p), ptr);
00341               else
00342               {
00343                      char *q=libmail_u_convert_tobuf(utf8_ptr,
00344                                                  "utf-8",
00345                                                  chset, NULL);
00346                      if (q)
00347                      {
00348                             (*print_func)(q, strlen(q), ptr);
00349                             free(q);
00350                      }
00351                      else
00352                      {
00353                             (*print_func)(p, strlen(p), ptr);
00354                      }
00355                      free(utf8_ptr);
00356               }
00357        }
00358        else
00359        {
00360               (*print_func)(tok, strlen(tok), ptr);
00361        }
00362        return 0;
00363 }
00364 
00365 int rfc822_display_addr(const struct rfc822a *rfcp, int index,
00366                      const char *chset,
00367                      void (*print_func)(const char *, size_t, void *),
00368                      void *ptr)
00369 {
00370        const struct rfc822addr *addrs;
00371        char *tok;
00372        int rc;
00373 
00374        if (index < 0 || index >= rfcp->naddrs)   return 0;
00375 
00376        addrs=rfcp->addrs+index;
00377 
00378        if (!addrs->tokens)
00379               return 0;
00380 
00381        tok=rfc822_gettok(addrs->tokens);
00382 
00383        if (!tok)
00384               return 0;
00385 
00386        rc=rfc822_display_addr_str(tok, chset, print_func, ptr);
00387        free(tok);
00388        return rc;
00389 }
00390 
00391 int rfc2047_print_unicodeaddr(const struct rfc822a *a,
00392                            const char *charset,
00393                            void (*print_func)(char, void *),
00394                            void (*print_separator)(const char *, void *),
00395                            void *ptr)
00396 {
00397        const char *sep=NULL;
00398        int n;
00399 
00400        for (n=0; n<a->naddrs; ++n)
00401        {
00402               struct decode_unicode_s nbuf;
00403               const struct rfc822addr *addrs;
00404               size_t i=0;
00405               char *cpbuf;
00406               int need_braces=0;
00407 
00408               addrs=a->addrs+n;
00409 
00410               nbuf.bufptr=0;
00411               nbuf.bufsize=1;
00412 
00413               if (rfc822_display_name_int(a, n, charset,
00414                                        save_unicode_text, &nbuf) < 0)
00415                      return -1;
00416 
00417               nbuf.bufptr=malloc(nbuf.bufsize);
00418               nbuf.bufsize=0;
00419               if (!nbuf.bufptr)
00420                      return -1;
00421 
00422               if (rfc822_display_name_int(a, n, charset,
00423                                        save_unicode_text, &nbuf) < 0)
00424               {
00425                      free(nbuf.bufptr);
00426                      return -1;
00427               }
00428               nbuf.bufptr[nbuf.bufsize]=0;
00429 
00430               if (addrs->tokens == 0)
00431               {
00432                      size_t i;
00433 
00434                      if (nbuf.bufsize == 1) /* ; */
00435                             sep=0;
00436 
00437                      if (sep)
00438                             (*print_separator)(sep, ptr);
00439 
00440                      for (i=0; i<nbuf.bufsize; ++i)
00441                             (*print_func)(nbuf.bufptr[i], ptr);
00442                      free(nbuf.bufptr);
00443                      if (nbuf.bufsize > 1)
00444                             (*print_separator)(" ", ptr);
00445                      sep=NULL;
00446                      continue;
00447               }
00448               if (sep)
00449                      (*print_separator)(sep, ptr);
00450 
00451               if (!addrs->name)
00452               {
00453                      nbuf.bufsize=0;
00454                      nbuf.bufptr[0]=0;
00455               }
00456 
00457               for (i=0; i<nbuf.bufsize; i++)
00458                      if (strchr(RFC822_SPECIALS, nbuf.bufptr[i]))
00459                             break;
00460 
00461               cpbuf=libmail_u_convert_tobuf(nbuf.bufptr, "utf-8", charset,
00462                                          NULL);
00463 
00464               if (!cpbuf)
00465               {
00466                      const char *errmsg="\"(unknown character set)\"";
00467 
00468                      while (*errmsg)
00469                             (*print_func)(*errmsg++, ptr);
00470                      need_braces=1;
00471               }
00472               else
00473               {
00474                      if (i < nbuf.bufsize)
00475                      {
00476                             (*print_func)('"', ptr);
00477 
00478                             for (i=0; cpbuf[i]; ++i)
00479                             {
00480                                    if (cpbuf[i] == '\\' ||
00481                                        cpbuf[i] == '"')
00482                                           (*print_func)('\\', ptr);
00483                                    (*print_func)(cpbuf[i], ptr);
00484                             }
00485                             (*print_func)('"', ptr);
00486                             need_braces=1;
00487                      }
00488                         else
00489                         {
00490                                 for (i=0; cpbuf[i]; ++i)
00491                             {
00492                                    need_braces=1;
00493                                         (*print_func)(cpbuf[i], ptr);
00494                             }
00495                         }
00496 
00497                      free(cpbuf);
00498               }
00499               free(nbuf.bufptr);
00500 
00501               if (need_braces)
00502               {
00503                      (*print_func)(' ', ptr);
00504                      (*print_func)('<', ptr);
00505               }
00506 
00507               nbuf.bufptr=0;
00508               nbuf.bufsize=1;
00509 
00510               if (rfc822_display_addr(a, n, charset,
00511                                    save_unicode_text, &nbuf) < 0)
00512                      return -1;
00513 
00514               nbuf.bufptr=malloc(nbuf.bufsize);
00515               nbuf.bufsize=0;
00516               if (!nbuf.bufptr)
00517                      return -1;
00518 
00519               if (rfc822_display_addr(a, n, charset,
00520                                    save_unicode_text, &nbuf) < 0)
00521               {
00522                      free(nbuf.bufptr);
00523                      return -1;
00524               }
00525               for (i=0; i<nbuf.bufsize; i++)
00526                      (*print_func)(nbuf.bufptr[i], ptr);
00527 
00528               free(nbuf.bufptr);
00529 
00530               if (need_braces)
00531                      (*print_func)('>', ptr);
00532               sep=", ";
00533        }
00534 
00535        return 0;
00536 }
00537 
00538 static int rfc2047_print_unicode_addrstr(const char *addrheader,
00539                                     const char *charset,
00540                                     void (*print_func)(char, void *),
00541                                     void (*print_separator)(const char *, void *),
00542                                     void (*err_func)(const char *, int, void *),
00543                                     void *ptr)
00544 {
00545        struct rfc822t *t;
00546        struct rfc822a *a;
00547        int rc;
00548 
00549        t=rfc822t_alloc_new(addrheader, err_func, ptr);
00550 
00551        if (!t)
00552               return -1;
00553 
00554        a=rfc822a_alloc(t);
00555 
00556        if (!a)
00557        {
00558               rfc822t_free(t);
00559               return -1;
00560        }
00561        rc=rfc2047_print_unicodeaddr(a, charset, print_func, print_separator,
00562                                  ptr);
00563        rfc822a_free(a);
00564        rfc822t_free(t);
00565        return (rc);
00566 }
00567 
00568 struct rfc822_display_hdrvalue_s {
00569 
00570        void (*display_func)(const char *, size_t, void *);
00571        void *ptr;
00572 };
00573 
00574 static void rfc822_display_hdrvalue_print_func(char c, void *ptr)
00575 {
00576        struct rfc822_display_hdrvalue_s *s=
00577               (struct rfc822_display_hdrvalue_s *)ptr;
00578 
00579        (*s->display_func)(&c, 1, s->ptr);
00580 }
00581 
00582 static void rfc822_display_hdrvalue_print_separator(const char *cp, void *ptr)
00583 {
00584        struct rfc822_display_hdrvalue_s *s=
00585               (struct rfc822_display_hdrvalue_s *)ptr;
00586 
00587        (*s->display_func)(cp, strlen(cp), s->ptr);
00588        (*s->display_func)("", 0, s->ptr); /* Signal wrap point */
00589 }
00590 
00591 int rfc822_display_hdrvalue(const char *hdrname,
00592                          const char *hdrvalue,
00593                          const char *charset,
00594                          void (*display_func)(const char *, size_t,
00595                                            void *),
00596                          void (*err_func)(const char *, int, void *),
00597                          void *ptr)
00598 {
00599        struct rfc822_display_hdrvalue_s s;
00600 
00601        s.display_func=display_func;
00602        s.ptr=ptr;
00603 
00604        if (rfc822hdr_is_addr(hdrname))
00605        {
00606               return rfc2047_print_unicode_addrstr(hdrvalue,
00607                                                charset,
00608                                                rfc822_display_hdrvalue_print_func,
00609                                                rfc822_display_hdrvalue_print_separator,
00610                                                NULL,
00611                                                &s);
00612        }
00613 
00614        return rfc2047_decode_unicode(hdrvalue, charset, display_func, ptr);
00615 }
00616 
00617 struct rfc822_display_hdrvalue_tobuf_s {
00618        void (*orig_err_func)(const char *, int, void *);
00619        void *orig_ptr;
00620 
00621        size_t cnt;
00622        char *buf;
00623 };
00624 
00625 static void rfc822_display_hdrvalue_tobuf_cnt(const char *ptr, size_t cnt,
00626                                          void *s)
00627 {
00628        ((struct rfc822_display_hdrvalue_tobuf_s *)s)->cnt += cnt;
00629 }
00630 
00631 static void rfc822_display_hdrvalue_tobuf_save(const char *ptr, size_t cnt,
00632                                           void *s)
00633 {
00634        if (cnt)
00635               memcpy(((struct rfc822_display_hdrvalue_tobuf_s *)s)->buf,
00636                      ptr, cnt);
00637 
00638        ((struct rfc822_display_hdrvalue_tobuf_s *)s)->buf += cnt;
00639 }
00640 
00641 static void rfc822_display_hdrvalue_tobuf_errfunc(const char *ptr, int index,
00642                                             void *s)
00643 {
00644        void (*f)(const char *, int, void *)=
00645               ((struct rfc822_display_hdrvalue_tobuf_s *)s)->orig_err_func;
00646 
00647        if (f)
00648               f(ptr, index,
00649                 ((struct rfc822_display_hdrvalue_tobuf_s *)s)->orig_ptr);
00650 }
00651 
00652 char *rfc822_display_addr_tobuf(const struct rfc822a *rfcp, int index,
00653                             const char *chset)
00654 {
00655        struct rfc822_display_hdrvalue_tobuf_s nbuf;
00656        int errcode;
00657        char *ptr;
00658 
00659        nbuf.buf=0;
00660        nbuf.cnt=1;
00661 
00662        errcode=rfc822_display_addr(rfcp, index, chset,
00663                                 rfc822_display_hdrvalue_tobuf_cnt, &nbuf);
00664 
00665        if (errcode < 0)
00666               return NULL;
00667 
00668        ptr=nbuf.buf=malloc(nbuf.cnt);
00669        nbuf.cnt=0;
00670        if (!ptr)
00671               return NULL;
00672 
00673        errcode=rfc822_display_addr(rfcp, index, chset,
00674                                 rfc822_display_hdrvalue_tobuf_save, &nbuf);
00675 
00676        if (errcode < 0)
00677        {
00678               free(nbuf.buf);
00679               return NULL;
00680        }
00681        *nbuf.buf=0;
00682        return ptr;
00683 }
00684 
00685 char *rfc822_display_hdrvalue_tobuf(const char *hdrname,
00686                                 const char *hdrvalue,
00687                                 const char *charset,
00688                                 void (*err_func)(const char *, int,
00689                                                void *),
00690                                 void *ptr)
00691 {
00692        struct rfc822_display_hdrvalue_tobuf_s s;
00693        int errcode;
00694        char *bufptr;
00695 
00696        s.orig_err_func=err_func;
00697        s.orig_ptr=ptr;
00698        s.cnt=1;
00699 
00700        errcode=rfc822_display_hdrvalue(hdrname, hdrvalue, charset,
00701                                    rfc822_display_hdrvalue_tobuf_cnt,
00702                                    rfc822_display_hdrvalue_tobuf_errfunc,
00703                                    &s);
00704 
00705        if (errcode < 0)
00706               return NULL;
00707 
00708        bufptr=s.buf=malloc(s.cnt);
00709 
00710        if (!bufptr)
00711               return NULL;
00712 
00713        errcode=rfc822_display_hdrvalue(hdrname, hdrvalue, charset,
00714                                    rfc822_display_hdrvalue_tobuf_save,
00715                                    rfc822_display_hdrvalue_tobuf_errfunc,
00716                                    &s);
00717        if (errcode)
00718        {
00719               free(bufptr);
00720               return NULL;
00721        }
00722        *s.buf=0;
00723        return bufptr;
00724 }
00725 
00726 char *rfc822_display_addr_str_tobuf(const char *tok, const char *chset)
00727 {
00728        struct rfc822_display_hdrvalue_tobuf_s s;
00729        int errcode;
00730        char *bufptr;
00731 
00732        s.cnt=1;
00733 
00734        errcode=rfc822_display_addr_str(tok, chset,
00735                                    rfc822_display_hdrvalue_tobuf_cnt,
00736                                    &s);
00737 
00738        if (errcode < 0)
00739               return NULL;
00740 
00741        bufptr=s.buf=malloc(s.cnt);
00742 
00743        if (!bufptr)
00744               return NULL;
00745 
00746        errcode=rfc822_display_addr_str(tok, chset,
00747                                    rfc822_display_hdrvalue_tobuf_save,
00748                                    &s);
00749        if (errcode < 0)
00750        {
00751               free(bufptr);
00752               return NULL;
00753        }
00754        *s.buf=0;
00755        return bufptr;
00756 }
00757 
00758 
00759 static const char xdigit[]="0123456789ABCDEFabcdef";
00760 
00761 static const unsigned char decode64tab[]={
00762         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00763         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00764         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
00765        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0, 99,  0,  0,
00766         0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
00767        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
00768         0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00769        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0,
00770         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00771         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00772         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00773         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00774         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00775         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00776         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00777         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
00778 };
00779 
00780 static int nyb(int c)
00781 {
00782        const char    *p;
00783        int n;
00784 
00785        p=strchr(xdigit, c);
00786 
00787        if (!p)
00788               return 0;
00789 
00790        n=p-xdigit;
00791 
00792        if (n > 15)
00793               n -= 6;
00794 
00795        return n;
00796 }
00797 
00798 static size_t decodebase64(const char *ptr, size_t cnt,
00799                         char *dec_buf)
00800 {
00801        size_t  i, j;
00802        char    a,b,c;
00803        size_t  k;
00804 
00805        i=cnt / 4;
00806        i=i*4;
00807        k=0;
00808        for (j=0; j<i; j += 4)
00809        {
00810               int     w=decode64tab[(int)(unsigned char)ptr[j]];
00811               int     x=decode64tab[(int)(unsigned char)ptr[j+1]];
00812               int     y=decode64tab[(int)(unsigned char)ptr[j+2]];
00813               int     z=decode64tab[(int)(unsigned char)ptr[j+3]];
00814 
00815               a= (w << 2) | (x >> 4);
00816               b= (x << 4) | (y >> 2);
00817               c= (y << 6) | z;
00818               dec_buf[k++]=a;
00819               if ( ptr[j+2] != '=')
00820                      dec_buf[k++]=b;
00821               if ( ptr[j+3] != '=')
00822                      dec_buf[k++]=c;
00823        }
00824        return (k);
00825 }
00826 
00827 
00828 static ssize_t rfc822_decode_rfc2047_atom(const char *str,
00829                                      size_t cnt,
00830 
00831                                      void (*callback)(const char *,
00832                                                     const char *,
00833                                                     const char *,
00834                                                     size_t,
00835                                                     void *),
00836                                      void *ptr)
00837 {
00838        const char *chset_str;
00839        const char *enc_str;
00840        const char *content_str;
00841 
00842        char *chset;
00843        char *lang;
00844 
00845        char *content;
00846 
00847        size_t i;
00848        size_t j;
00849        size_t k;
00850 
00851        size_t content_len;
00852 
00853        if (cnt < 2 || str[0] != '=' || str[1] != '?')
00854               return 0;
00855 
00856        chset_str=str+2;
00857 
00858        for (i=2; i<cnt; i++)
00859               if (str[i] == '?')
00860                      break;
00861 
00862        if (i >= cnt)
00863               return 0;
00864 
00865        enc_str= str + ++i;
00866 
00867        for (; i < cnt; i++)
00868               if (str[i] == '?')
00869                      break;
00870 
00871        if (i >= cnt)
00872               return 0;
00873 
00874        content_str= str + ++i;
00875 
00876        while (1)
00877        {
00878               if (cnt-i < 2)
00879                      return 0;
00880 
00881               if (str[i] == '?' && str[i+1] == '=')
00882                      break;
00883               ++i;
00884        }
00885 
00886        for (j=0; chset_str[j] != '?'; ++j)
00887               ;
00888 
00889        chset=malloc(j+1);
00890 
00891        if (!chset)
00892               return -1;
00893 
00894        memcpy(chset, chset_str, j);
00895        chset[j]=0;
00896 
00897        lang=strchr(chset, '*');  /* RFC 2231 */
00898 
00899        if (lang)
00900               *lang++ = 0;
00901        else
00902               lang="";
00903 
00904        content_len=str + i - content_str;
00905 
00906        content=malloc(content_len+1);
00907 
00908        if (!content)
00909        {
00910               free(chset);
00911               return -1;
00912        }
00913 
00914        switch (*enc_str) {
00915        case 'q':
00916        case 'Q':
00917 
00918               k=0;
00919               for (j=0; j<content_len; j++)
00920               {
00921                      char c;
00922 
00923                      if (content_str[j] == '=' && i-j >= 3)
00924                      {
00925                             content[k]=(char)(nyb(content_str[j+1])*16 +
00926                                             nyb(content_str[j+2]));
00927                             ++k;
00928                             j += 2;
00929                             continue;
00930                      }
00931 
00932                      c=content_str[j];
00933                      if (c == '_')
00934                             c=' ';
00935                      content[k]=c;
00936                      ++k;
00937               }
00938               break;
00939 
00940        case 'b':
00941        case 'B':
00942               k=decodebase64(content_str, content_len, content);
00943               break;
00944        default:
00945               free(content);
00946               free(chset);
00947               return (0);
00948        }
00949 
00950        if (callback)
00951               (*callback)(chset, lang, content, k, ptr);
00952        free(content);
00953        free(chset);
00954        return i + 2;
00955 }
00956 
00957 int rfc2047_decoder(const char *text,
00958                   void (*callback)(const char *chset,
00959                                  const char *lang,
00960                                  const char *content,
00961                                  size_t cnt,
00962                                  void *dummy),
00963                   void *ptr)
00964 {
00965        ssize_t rc;
00966 
00967        while (text && *text)
00968        {
00969               size_t i;
00970 
00971               for (i=0; text[i]; i++)
00972               {
00973                      if (text[i] == '=' && text[i+1] == '?')
00974                             break;
00975               }
00976 
00977               if (i)
00978                      (*callback)("iso-8859-1", "", text, i, ptr);
00979 
00980               text += i;
00981 
00982               if (!*text)
00983                      continue;
00984 
00985               rc=rfc822_decode_rfc2047_atom(text, strlen(text),
00986                                          callback, ptr);
00987 
00988               if (rc < 0)
00989                      return -1;
00990 
00991               if (rc == 0)
00992               {
00993                      (*callback)("iso-8859-1", "", text, 2, ptr);
00994                      text += 2;
00995                      continue;
00996               }
00997 
00998               text += rc;
00999 
01000               for (i=0; text[i]; i++)
01001               {
01002                      if (strchr(" \t\r\n", text[i]) == NULL)
01003                             break;
01004               }
01005 
01006               if (text[i] != '=' || text[i+1] != '?')
01007                      continue;
01008 
01009               rc=rfc822_decode_rfc2047_atom(text+i, strlen(text+i), NULL,
01010                                          NULL);
01011 
01012               if (rc < 0)
01013                      return -1;
01014               if (rc > 0)
01015                      text += i;
01016        }
01017 
01018        return 0;
01019 }
01020 
01021 static int rfc2047_decode_unicode(const char *text,
01022                               const char *chset,
01023                               void (*callback)(const char *, size_t,
01024                                              void *),
01025                               void *ptr)
01026 {
01027        struct rfc822_display_name_s s;
01028 
01029        s.chset=chset;
01030        s.print_func=callback;
01031        s.ptr=ptr;
01032 
01033        return rfc2047_decoder(text, rfc822_display_addr_cb, &s);
01034 }