#ifdef RCS
static char rcsid[]=
"$Id: fields.c,v 1.31 2001/08/04 07:09:42 guenther Exp $";
#endif
#include "includes.h"
#include "formail.h"
#include "sublib.h"
#include "shell.h"
#include "common.h"
#include "fields.h"
#include "ecommon.h"
#include "formisc.h"
struct field*findf(p,ah)const struct field*const p;register struct field**ah;
{ size_t i;int uhead;char*chp;register struct field*h;
uhead=ah==&uheader||ah==&Uheader;
for(i=p->id_len,chp=(char*)p->fld_text,h= *ah;h;h= *(ah= &h->fld_next))
if(i>=h->id_len&&!strncasecmp(chp,h->fld_text,h->id_len))
{ if(i>h->id_len&&uhead)
*ah=0,(*(ah=addfield(ah,chp,i)))->fld_next=h,(h= *ah)->fld_ref=0;
return h;
}
return (struct field*)0;
}
void cleanheader P((void))
{ struct field**pp,*p;char*cp;
for(pp=&rdheader;p= *pp;pp= &(*pp)->fld_next)
if((cp=p->fld_text+p->id_len-1,*cp==HEAD_DELIMITER)&&
(*--cp==' '||*cp=='\t'))
{ char*q=cp++;int diff;
while(*--q==' '||*q=='\t');
tmemmove(++q,cp,p->Tot_len-p->id_len+1);
p->id_len-=(diff=cp-q);
p->Tot_len-=diff;
}
}
void clear_uhead(hdr)register struct field*hdr;
{ for(;hdr;hdr=hdr->fld_next)
hdr->fld_ref=0;
}
struct field**addfield(pointer,text,totlen)struct field**pointer;
const char*const text;const size_t totlen;
{ register struct field*p,**pp;int idlen;
for(pp=pointer;*pp;pp= &(*pp)->fld_next);
(*pp=p=malloc(FLD_HEADSIZ+totlen))->fld_next=0;idlen=breakfield(text,totlen);
p->id_len=idlen>0?idlen:pp==&rdheader?0:-idlen;
tmemmove(p->fld_text,text,p->Tot_len=totlen);
return pp;
}
struct field*delfield(pointer)struct field**pointer;
{ struct field*fldp;
*pointer=(fldp= *pointer)->fld_next;free(fldp);
return *pointer;
}
void concatenate(fldp)struct field*const fldp;
{ register char*p;register size_t l;
l=fldp->Tot_len;
if(!eqFrom_(p=fldp->fld_text))
while(l--)
if(*p++=='\n'&&l)
p[-1]=' ';
}
static void extractfield(p)register const struct field*p;
{ if(xheader||Xheader)
{ if(findf(p,&xheader))
{ char*chp,*echp;
echp=(chp=(char*)p->fld_text+p->id_len)+(int)(p->Tot_len-p->id_len-1);
if(zap)
{ chp=skpspace(chp);
while(chp<echp)
{ switch(*--echp)
{ case ' ':case '\t':continue;
}
echp++;
break;
}
}
putssn(chp,echp-chp);putcs('\n');
return;
}
if(!findf(p,&Xheader))
return;
}
lputssn(p->fld_text,p->Tot_len);
}
void flushfield(pointer)register struct field**pointer;
{ register struct field*p,*q;
for(p= *pointer,*pointer=0;p;p=q)
q=p->fld_next,extractfield(p),free(p);
}
void dispfield(p)register const struct field*p;
{ for(;p;p=p->fld_next)
if(p->id_len+1<p->Tot_len)
extractfield(p);
}
int readhead P((void))
{ int idlen;
getline();
if((idlen=breakfield(buf,buffilled))<=0)
return 0;
if(idlen==STRLEN(FROM)&&eqFrom_(buf))
{ if(rdheader)
return 0;
for(;buflast=='>';getline());
}
else
for(;;getline())
{ switch(buflast)
{ case ' ':case '\t':
continue;
}
break;
}
addbuf();
return 1;
}
void addbuf P((void))
{ addfield(&rdheader,buf,buffilled);buffilled=0;
}