/*$Id: decodeHDR.c,v 1.2 1998/02/28 19:03:02 lindberg Exp $*/ /*$Name: ezmlm-idx-040 $*/ #include "stralloc.h" #include "strerr.h" #include "error.h" #include "case.h" #include "byte.h" #include "uint32.h" #include "mime.h" #include "errtxt.h" static void die_nomem(fatal) char *fatal; { strerr_die2x(111,fatal,ERR_NOMEM); } void decodeHDR(indata,n,outdata,charset,fatal) char *indata; unsigned int n; stralloc *outdata; char *charset; char *fatal; /* decodes indata depending on charset. May put '\n' and '\0' into out */ /* data and can take them as indata. */ { unsigned int pos; char *cp,*cpnext,*cpstart,*cpenc,*cptxt,*cpend,*cpafter; cpnext = indata; cpafter = cpnext + n; cpstart = cpnext; if (!stralloc_copys(outdata,"")) die_nomem(fatal); if (!stralloc_ready(outdata,n)) die_nomem(fatal); for (;;) { cpstart = cpstart + byte_chr(cpstart,cpafter-cpstart,'='); if (cpstart == cpafter) break; ++cpstart; if (*cpstart != '?') continue; ++cpstart; cpenc = cpstart + byte_chr(cpstart,cpafter-cpstart,'?'); if (cpenc == cpafter) continue; cpenc++; cptxt = cpenc + byte_chr(cpenc,cpafter-cpenc,'?'); if (cptxt == cpafter) continue; cptxt++; cpend = cptxt + byte_chr(cptxt,cpafter-cptxt,'?'); if (cpend == cpafter || *(cpend + 1) != '=') continue; /* We'll decode anything. On lists with many charsets, this may */ /* result in unreadable subjects, but that's the case even if */ /* no decoding is done. This way, the subject will be optimal */ /* for threading, but charset info is lost. We aim to correctly */ /* decode us-ascii and all iso-8859/2022 charsets. Exacly how */ /* these will be displayed depends on dir/charset. */ cp = cpnext; /* scrap lwsp between coded strings */ while (*cp == ' ' || *cp == '\t') cp++; if (cp != cpstart - 2) if (!stralloc_catb(outdata,cpnext, cpstart - cpnext - 2)) die_nomem(fatal); cpnext = cp + 1; cpstart = cpnext; switch (*cpenc) { case 'b': case 'B': pos = outdata->len; decodeB(cptxt,cpend-cptxt,outdata,2,fatal); cpnext = cpend + 2; cpstart = cpnext; break; case 'q': case 'Q': decodeQ(cptxt,cpend-cptxt,outdata,fatal); cpnext = cpend + 2; cpstart = cpnext; break; default: /* shouldn't happen, but let's be reasonable */ cpstart = cpend + 2; break; } } if (!stralloc_catb(outdata,cpnext,indata-cpnext+n)) die_nomem(fatal); }