From owner-FreeBSD-users-jp@jp.freebsd.org  Sun Aug 12 23:23:24 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id XAA07905;
	Sun, 12 Aug 2001 23:23:24 +0900 (JST)
	(envelope-from owner-FreeBSD-users-jp@jp.FreeBSD.org)
Received: from gateway.variant (3D72FA7D.osaka.meta.ne.jp [61.114.250.125])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with SMTP id XAA07900
	for <FreeBSD-users-jp@jp.freebsd.org>; Sun, 12 Aug 2001 23:23:22 +0900 (JST)
	(envelope-from kuroko@nettaxi.com)
Received: (qmail 97320 invoked from network); 12 Aug 2001 14:25:29 -0000
Received: from unknown (HELO dosv1) (192.168.1.1)
  by 192.168.1.254 with SMTP; 12 Aug 2001 14:25:29 -0000
Message-ID: <025b01c1233a$b4a4a950$0101a8c0@dosv1>
From: "Kenichi Ikinaga" <kuroko@nettaxi.com>
To: <FreeBSD-users-jp@jp.freebsd.org>
References: <000d01c12196$e3cda240$0101a8c0@dosv1>
Date: Sun, 12 Aug 2001 23:25:57 +0900
MIME-Version: 1.0
Content-Type: multipart/mixed;
	boundary="----=_NextPart_000_0258_01C12386.23871650"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4133.2400
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
Reply-To: FreeBSD-users-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: FreeBSD-users-jp 63513
Subject: [FreeBSD-users-jp 63513] Re: ezmlm
 =?ISO-2022-JP?B?GyRCJE4lPyUwQ1Y0OTUhRz0bKEI=?= 
Errors-To: owner-FreeBSD-users-jp@jp.freebsd.org
Sender: owner-FreeBSD-users-jp@jp.freebsd.org
X-Originator: kuroko@nettaxi.com

This is a multi-part message in MIME format.

------=_NextPart_000_0258_01C12386.23871650
Content-Type: text/plain;
	charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit

$B<+8J%l%9$G$9!#(B

ezmlm-send.c$B$r$J$s$H$+=q$-49$($F$$$?$H$3$m(B
$B9XFI<T$N%a!<%k%"%I%l%9$r0l?M$@$1<hF@$9$k$3$H$,2DG=$K$J$j$^$7$?!#(B
$BE:IU$G$=$N%=!<%9$r$D$1$^$9!#(B

$BM}A[$G$O(B
$B9XFI<T0l?ML\$N%a!<%k$N:G8e!'(B
hoge1@foo.bar
$BFs?ML\$N%a!<%k$N:G8e!'(B
hoge2@foo.bar
$B$H$J$C$FM_$7$$$N$K!"(B

$B8=<B$G$O(B
$B9XFI<T0l?ML\$N%a!<%k$N:G8e!'(B
hoge1@foo.bar
$BFs?ML\$N%a!<%k$N:G8e!'(B
hoge1@foo.bar
$B$H$J$C$F$$$^$9!#(B

$B%a!<%k$rAw$k$?$S$KAw?.$9$k%"%I%l%9$,$+$o$k$O$:$J$N$K!&!&!&(B
$B$J$<$J$s$@$m$&!#(B

-----
$B@8D9!!8-0l!?(BKenichi Ikinaga
Variant Network
kuroko@nettaxi.com
kuroko@priest.dyndns.org

------=_NextPart_000_0258_01C12386.23871650
Content-Type: application/octet-stream;
	name="ezmlm-send.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ezmlm-send.c"

/* $Id: ezmlm-send.c,v 1.77 1999/10/29 02:49:14 lindberg Exp $*/
/* $Name: ezmlm-idx-040 $*/
#include "stralloc.h"
#include "subfd.h"
#include "strerr.h"
#include "error.h"
#include "qmail.h"
#include "env.h"
#include "lock.h"
#include "sig.h"
#include "open.h"
#include "getln.h"
#include "case.h"
#include "scan.h"
#include "str.h"
#include "fmt.h"
#include "readwrite.h"
#include "exit.h"
#include "substdio.h"
#include "getconf.h"
#include "constmap.h"
#include "byte.h"
#include "sgetopt.h"
#include "quote.h"
#include "subscribe.h"
#include "mime.h"
#include "errtxt.h"
#include "makehash.h"
#include "cookie.h"
#include "idx.h"
#include "copy.h"

int flagnoreceived =3D 1;		/* suppress received headers by default. =
They*/
				/* are still archived. =3D0 =3D> archived and */
				/* copied. */
int flaglog =3D 1;		/* for lists with mysql support, use tags */
				/* and log traffic to the database */
#define FATAL "ezmlm-send: fatal: "

char tobuf[25];                /* kuroko add */

void die_usage()
{
  strerr_die1x(100,"ezmlm-send: usage: ezmlm-send [-cClLqQrR] [-h =
header] dir");
}
void die_nomem()
{
  strerr_die2x(111,FATAL,ERR_NOMEM);
}

	/* for writing new index file indexn later moved to index. */
substdio ssindexn;
char indexnbuf[1024];

char strnum[FMT_ULONG];
char szmsgnum[FMT_ULONG];
char hash[HASHLEN];

stralloc fnadir =3D {0};
stralloc fnaf =3D {0};
stralloc fnif =3D {0};
stralloc fnifn =3D {0};
stralloc fnsub =3D {0};
stralloc line =3D {0};
stralloc qline =3D {0};
stralloc lines =3D {0};
stralloc subject =3D {0};
stralloc from =3D {0};
stralloc received =3D {0};
stralloc prefix =3D {0};
stralloc content =3D {0};
stralloc boundary =3D {0};
stralloc charset =3D {0};
stralloc dcprefix =3D {0};
stralloc dummy =3D {0};
stralloc qmqpservers =3D {0};

void die_indexn()
{
  strerr_die4x(111,FATAL,ERR_WRITE,fnifn.s,": ");
}

void *psql =3D (void *) 0;

unsigned long innum;
unsigned long outnum;
unsigned long msgnum;
unsigned long hash_lo =3D 0L;
unsigned long hash_hi =3D 52L;
unsigned long msgsize =3D 0L;
unsigned long cumsize =3D 0L;	/* cumulative archive size bytes / 256 */
char flagcd =3D '\0';		/* no transfer-encoding for trailer */
char encin =3D '\0';
int flagindexed;
int flagfoundokpart;		/* Found something to pass on. If multipart */
				/* we set to 0 and then set to 1 for any */
				/* acceptable mime part. If 0 -> reject */
int flagreceived;
int flagprefixed;
unsigned int serial =3D 0;
int flagarchived;
int fdarchive;
int fdindex;
int fdindexn;
char hashout[COOKIE+1];

substdio ssarchive;
char archivebuf[1024];

int flagsublist;
stralloc sublist =3D {0};
stralloc mailinglist =3D {0};
stralloc outlocal =3D {0};
stralloc outhost =3D {0};
stralloc headerremove =3D {0};
struct constmap headerremovemap;
stralloc mimeremove =3D {0};
struct constmap mimeremovemap;
char *dir;

struct qmail qq;
substdio ssin;
char inbuf[1024];
substdio ssout;
char outbuf[1];

char textbuf[512];
substdio sstext;

unsigned int mywrite(fd,buf,len)
int fd;
char *buf;
unsigned int len;
{
  qmail_put(&qq,buf,len);
  return len;
}

int subto(s,l)
char *s;
unsigned int l;
{
  qmail_put(&qq,"T",1);
  qmail_put(&qq,s,l);
  qmail_put(&qq,"",1);
  return (int) l;
}

void die_archive()
{
  strerr_die4sys(111,FATAL,ERR_WRITE,fnaf.s,": ");
}
void die_numnew()
{
  strerr_die3sys(111,FATAL,ERR_CREATE,"numnew: ");
}

void qa_put(buf,len) char *buf; unsigned int len;
{
  qmail_put(&qq,buf,len);
  if (flagarchived)
    if (substdio_put(&ssarchive,buf,len) =3D=3D -1) die_archive();
}

void qa_puts(buf) char *buf;
{
  qmail_puts(&qq,buf);
  if (flagarchived)
    if (substdio_puts(&ssarchive,buf) =3D=3D -1) die_archive();
}

int sublistmatch(sender)
char *sender;
{
  unsigned int i;
  unsigned int j;

  j =3D str_len(sender);
  if (j < sublist.len) return 0;

  i =3D byte_rchr(sublist.s,sublist.len,'@');
  if (i =3D=3D sublist.len) return 1;

  if (byte_diff(sublist.s,i,sender)) return 0;
  if (case_diffb(sublist.s + i,sublist.len - i,sender + j - (sublist.len =
- i)))
    return 0;

  return 1;
}

substdio ssnumnew;
char numnewbuf[16];

char buf0[256];
substdio ss0 =3D SUBSTDIO_FDBUF(read,0,buf0,sizeof(buf0));

void numwrite()
{		/* this one deals with msgnum, not outnum! */
  int fd;

  fd =3D open_trunc("numnew");
  if (fd =3D=3D -1) die_numnew();
  substdio_fdbuf(&ssnumnew,write,fd,numnewbuf,sizeof(numnewbuf));
  if (substdio_put(&ssnumnew,strnum,fmt_ulong(strnum,msgnum)) =3D=3D -1)
    die_numnew();
  if (substdio_puts(&ssnumnew,":") =3D=3D -1) die_numnew();
  if (substdio_put(&ssnumnew,strnum,fmt_ulong(strnum,cumsize)) =3D=3D =
-1)
    die_numnew();

  if (substdio_puts(&ssnumnew,"\n") =3D=3D -1) die_numnew();
  if (substdio_flush(&ssnumnew) =3D=3D -1) die_numnew();
  if (fsync(fd) =3D=3D -1) die_numnew();
  if (close(fd) =3D=3D -1) die_numnew(); /* NFS stupidity */
  if (rename("numnew","num") =3D=3D -1)
    strerr_die3sys(111,FATAL,ERR_MOVE,"numnew: ");
}

stralloc mydtline =3D {0};

int idx_copy_insertsubject()
/* copies old index file up to but not including msg, then adds a line =
with */
/* 'sub' trimmed of reply indicators, then closes the new index and =
moves it*/
/* to the name 'index'. Errors are dealt with directly, and if the =
routine  */
/* returns, it was successful. 'fatal' points to a program-specific =
error   */
/* string. Sub is not destroyed, but from is!!!                          =
   */
/* returns 1 if reply-indicators were found, 0 otherwise.                =
   */
/* no terminal \n or \0 in any of the strallocs! */
{
  char *cp;
  unsigned long idx;
  int match;
  int r;
  unsigned int pos;

  if (!stralloc_copys(&fnadir,"archive/")) die_nomem();
  if (!stralloc_catb(&fnadir,strnum,fmt_ulong(strnum,outnum / 100)))
	die_nomem();
  if (!stralloc_copy(&fnif,&fnadir)) die_nomem();
  if (!stralloc_copy(&fnifn,&fnif)) die_nomem();
  if (!stralloc_cats(&fnif,"/index")) die_nomem();
  if (!stralloc_cats(&fnifn,"/indexn")) die_nomem();
  if (!stralloc_0(&fnif)) die_nomem();
  if (!stralloc_0(&fnifn)) die_nomem();
  if (!stralloc_0(&fnadir)) die_nomem();

			/* may not exists since we run before ezmlm-send */
  if (mkdir(fnadir.s,0755) =3D=3D -1)
    if (errno !=3D error_exist)
      strerr_die4x(111,FATAL,ERR_CREATE,fnadir.s,": ");

			/* Open indexn */
  fdindexn =3D open_trunc(fnifn.s);
  if (fdindexn =3D=3D -1)
    strerr_die4x(111,FATAL,ERR_WRITE,fnifn.s,": ");

			/* set up buffers for indexn */
  substdio_fdbuf(&ssindexn,write,fdindexn,indexnbuf,sizeof(indexnbuf));

  concatHDR(subject.s,subject.len,&lines,FATAL);	/* make 1 line */
  decodeHDR(lines.s,lines.len,&qline,charset.s,FATAL);	/* decode mime */
  r =3D unfoldHDR(qline.s,qline.len,&lines,charset.s,&dcprefix,1,FATAL);
						 /* trim mime */

  fdindex =3D open_read(fnif.s);
  if (fdindex =3D=3D -1) {
    if (errno !=3D error_noent)
      strerr_die4x(111,FATAL,ERR_OPEN, fnif.s, ": ");
  } else {
    substdio_fdbuf(&ssin,read,fdindex,inbuf,sizeof(inbuf));
    for(;;) {
      if (getln(&ssin,&qline,&match,'\n') =3D=3D -1)
        strerr_die4sys(111,FATAL,ERR_READ, fnif.s, ": ");
      if (!match)
        break;
      pos =3D scan_ulong(qline.s,&idx);
      if (!idx)				/* "impossible!" */
        strerr_die2x(111,FATAL,ERR_BAD_INDEX);
      if (idx >=3D outnum)
        break;				/* messages always come in order */
      if (substdio_put(&ssindexn,qline.s,qline.len) =3D=3D -1)
        die_indexn();
      if (qline.s[pos] =3D=3D ':') {	/* has author line */
        if (getln(&ssin,&qline,&match,'\n') =3D=3D -1)
          strerr_die4x(111,FATAL,ERR_READ, fnif.s, ": ");
        if (!match && qline.s[0] !=3D '\t')	/* "impossible! */
          strerr_die2x(111,FATAL,ERR_BAD_INDEX);
        if (substdio_put(&ssindexn,qline.s,qline.len) =3D=3D -1)
          die_indexn();
      }
    }
    close(fdindex);
  }
  if (!stralloc_copyb(&qline,strnum,fmt_ulong(strnum,outnum))) =
die_nomem();
  if (!stralloc_cats(&qline,": ")) die_nomem();	/* ':' for new ver */
  makehash(lines.s,lines.len,hash);
  if (!stralloc_catb(&qline,hash,HASHLEN)) die_nomem();
  if (!stralloc_cats(&qline," ")) die_nomem();
  if (r & 1)		/* reply */
    if (!stralloc_cats(&qline,"Re: ")) die_nomem();
  if (!stralloc_cat(&qline,&lines)) die_nomem();
  if (!stralloc_cats(&qline,"\n\t")) die_nomem();
  if (!stralloc_cat(&qline,&received)) die_nomem();
  if (!stralloc_cats(&qline,";")) die_nomem();

  concatHDR(from.s,from.len,&lines,FATAL);
  mkauthhash(lines.s,lines.len,hash);

  if (!stralloc_catb(&qline,hash,HASHLEN)) die_nomem();
  if (!stralloc_cats(&qline," ")) die_nomem();

  =
decodeHDR(cp,author_name(&cp,lines.s,lines.len),&from,charset.s,FATAL);
  (void) unfoldHDR(from.s,from.len,&lines,charset.s,&dcprefix,0,FATAL);
  if (!stralloc_cat(&qline,&lines)) die_nomem();

  if (!stralloc_cats(&qline,"\n")) die_nomem();
  if (substdio_put(&ssindexn,qline.s,qline.len) =3D=3D -1) die_indexn();
  if (substdio_flush(&ssindexn) =3D=3D -1) die_indexn();
  if (fsync(fdindexn) =3D=3D -1) die_indexn();
  if (fchmod(fdindexn,MODE_ARCHIVE | 0700) =3D=3D -1) die_indexn();
  if (close(fdindexn) =3D=3D -1) die_indexn(); /* NFS stupidity */
  if (rename(fnifn.s,fnif.s) =3D=3D -1)
    strerr_die4x(111,FATAL,ERR_MOVE,fnifn.s,": ");
  return r;
}

void transferenc()
{
	if (flagcd) {
	  qmail_puts(&qq,"\nContent-Transfer-Encoding: ");
          if (flagcd =3D=3D 'Q')
            qmail_puts(&qq,"Quoted-printable\n\n");
          else
	    qmail_puts(&qq,"base64\n\n");
        } else
          qmail_puts(&qq,"\n\n");
}

void getcharset()
{
    if (getconf_line(&charset,"charset",0,FATAL,dir)) {
      if (charset.len >=3D 2 && charset.s[charset.len - 2] =3D=3D ':') {
        if (charset.s[charset.len - 1] =3D=3D 'B' ||
			charset.s[charset.len - 1] =3D=3D 'Q') {
          flagcd =3D charset.s[charset.len - 1];
          charset.s[charset.len - 2] =3D '\0';
        }
      }
    } else
      if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem();

    if (!stralloc_0(&charset)) die_nomem();
}

int dumsubto(s,l)     /* kuroko add */
char *s;
unsigned int l;
{
	int i;
	for(i =3D 0;i < 25;i++) tobuf[i] =3D '\0';
	for(i =3D 0;i < l;i++) tobuf[i] =3D s[i];
}

void main(argc,argv)
int argc;
char **argv;
{
  unsigned long subs;
  int fdlock;
  char *sender;
  char *mlheader =3D (char *) 0;
  char *ret;
  char *err;
  int flagmlwasthere;
  int flagqmqp =3D 0;	/* don't use qmqp by default */
  int flaglistid =3D 0;	/* no listid header added */
  int match;
  unsigned int i;
  int r,fd;
  int flaginheader;
  int flagbadfield;
  int flagbadpart;
  int flagseenext;
  int flagsubline;
  int flagfromline;
  int flagcontline;
  int flagarchiveonly;
  int flagtrailer;
  unsigned int pos;
  int opt;
  char *cp, *cpstart, *cpafter;

  umask(022);
  sig_pipeignore();

  while ((opt =3D getopt(argc,argv,"cCh:H:lLrRqQs:S:vV")) !=3D opteof)
    switch(opt) {
      case 'c': case 'C': break;	/* ignore for backwards compat */
      case 'h':
      case 'H': mlheader =3D optarg;	/* Alternative sublist check header =
*/
                mlheader[str_chr(mlheader,':')] =3D '\0';
                break;
      case 'l': flaglog =3D 1; break;
      case 'L': flaglog =3D 0; break;
      case 'r': flagnoreceived =3D 0; break;
      case 'R': flagnoreceived =3D 1; break;
      case 's':
      case 'S':	pos =3D scan_ulong(optarg,&hash_lo);
		if (!optarg[pos++]) break;
		(void) scan_ulong(optarg+pos,&hash_hi);
		if (hash_hi > 52L) hash_hi =3D 52L;
		if (hash_lo > hash_hi) hash_lo =3D hash_hi;

 break;
      case 'q': flagqmqp =3D 0; break;
      case 'Q': flagqmqp =3D 1; break;
      case 'v':
      case 'V': strerr_die2x(0,
		"ezmlm-send version: ezmlm-0.53+",EZIDX_VERSION);
      default:
	die_usage();
    }


  dir =3D argv[optind++];
  if (!dir) die_usage();

  sender =3D env_get("SENDER");

  if (chdir(dir) =3D=3D -1)
    strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": ");

  fdlock =3D open_append("lock");
  if (fdlock =3D=3D -1)
    strerr_die4sys(111,FATAL,ERR_OPEN,dir,"/lock: ");
  if (lock_ex(fdlock) =3D=3D -1)
    strerr_die4sys(111,FATAL,ERR_OBTAIN,dir,"/lock: ");

  flagarchived =3D getconf_line(&line,"archived",0,FATAL,dir);
  flagindexed =3D getconf_line(&line,"indexed",0,FATAL,dir);
  getcharset();
  flagprefixed =3D getconf_line(&prefix,"prefix",0,FATAL,dir);
  if (prefix.len) {		/* encoding and serial # support */
				/* no sanity checks - you put '\n' or '\0' */
				/* into the coded string, you pay */

    decodeHDR(prefix.s,prefix.len,&line,charset.s,FATAL);
    (void) =
unfoldHDR(line.s,line.len,&dcprefix,charset.s,&dummy,0,FATAL);
    if (!stralloc_copy(&dcprefix,&line)) die_nomem();
    serial =3D byte_rchr(prefix.s,prefix.len,'#');
  }
  if ((fd =3D open_read("text/trailer")) =3D=3D -1) {	/* see if there is =
a trailer */
    if (errno =3D=3D error_noent) flagtrailer =3D 0;
    else strerr_die2sys(111,ERR_OPEN,"text/trailer: ");
  } else {
    close(fd);
    flagtrailer =3D 1;
  }

  getconf(&mimeremove,"mimeremove",0,FATAL,dir);

  if (getconf_line(&line,"num",0,FATAL,dir)) {	/* Now non-FATAL, def=3D0 =
*/
    if (!stralloc_0(&line)) die_nomem();
    cp =3D line.s + scan_ulong(line.s,&msgnum);
    ++msgnum;
    if (*cp++ =3D=3D ':')
      scan_ulong(cp,&cumsize);
  } else
    msgnum =3D 1L;			/* if num not there */

  getconf_line(&outhost,"outhost",1,FATAL,dir);
  getconf_line(&outlocal,"outlocal",1,FATAL,dir);
  set_cpoutlocal(&outlocal);
  set_cpouthost(&outhost);
  flagsublist =3D getconf_line(&sublist,"sublist",0,FATAL,dir);

  if (flagqmqp) {			/* forward compatibility ;-) */
    if (!stralloc_copys(&line,QMQPSERVERS)) die_nomem();
    if (!stralloc_cats(&line,"/0")) die_nomem();
    if (!stralloc_0(&line)) die_nomem();
    (void) getconf_line(&qmqpservers,line.s,0,FATAL,dir);
  }

  getconf(&headerremove,"headerremove",1,FATAL,dir);
  if =
(!constmap_init(&headerremovemap,headerremove.s,headerremove.len,0))
	die_nomem();

  if (!stralloc_copys(&mydtline,"Delivered-To: mailing list ")) =
die_nomem();
  if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem();
  if (!stralloc_cats(&mydtline,"@")) die_nomem();
  if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem();
  if (!stralloc_cats(&mydtline,"\n")) die_nomem();

  if (sender) {
    if (!*sender)
      strerr_die2x(100,FATAL,ERR_BOUNCE);
    if (str_equal(sender,"#@[]"))
      strerr_die2x(100,FATAL,ERR_BOUNCE);
    if (flagsublist)
      if (!sublistmatch(sender))
        strerr_die2x(100,FATAL,ERR_NOT_PARENT);
  }
  innum =3D msgnum;				/* innum =3D incoming */
  outnum =3D msgnum;				/* outnum =3D outgoing */
  if (flagsublist && !flagarchived) {		/* msgnum =3D archive */
    pos =3D byte_rchr(sublist.s,sublist.len,'@');	/* checked in =
sublistmatch */
    if (str_start(sender+pos,"-return-"))
      pos +=3D 8;
      pos +=3D scan_ulong(sender+pos,&innum);
      if (!flagarchived && innum && sender[pos] =3D=3D '-')
        outnum =3D innum;
  }
  szmsgnum[fmt_ulong(szmsgnum,outnum)] =3D '\0';
  set_cpnum(szmsgnum);				/* for copy */

  if (flagarchived) {
    if (!stralloc_copys(&fnadir,"archive/")) die_nomem();
    if (!stralloc_catb(&fnadir,strnum,
		fmt_ulong(strnum,outnum / 100))) die_nomem();
    if (!stralloc_copy(&fnaf,&fnadir)) die_nomem();
    if (!stralloc_cats(&fnaf,"/")) die_nomem();
    if (!stralloc_catb(&fnaf,strnum,fmt_uint0(strnum,
		(unsigned int) (outnum % 100),2))) die_nomem();
    if (!stralloc_0(&fnadir)) die_nomem();
    if (!stralloc_0(&fnaf)) die_nomem();

    if (mkdir(fnadir.s,0755) =3D=3D -1)
      if (errno !=3D error_exist)
	strerr_die4sys(111,FATAL,ERR_CREATE,fnadir.s,": ");
    fdarchive =3D open_trunc(fnaf.s);
    if (fdarchive =3D=3D -1)
      strerr_die4sys(111,FATAL,ERR_WRITE,fnaf.s,": ");

    =
substdio_fdbuf(&ssarchive,write,fdarchive,archivebuf,sizeof(archivebuf));=

						/* return-path to archive */
    if (!stralloc_copys(&line,"Return-Path: <")) die_nomem();
    if (sender) {				/* same as qmail-local */
      if (!quote2(&qline,sender)) die_nomem();
      for (i =3D 0;i < qline.len;++i) if (qline.s[i] =3D=3D '\n') =
qline.s[i] =3D '_';
      if (!stralloc_cat(&line,&qline)) die_nomem();
    }
    if (!stralloc_cats(&line,">\n")) die_nomem();
    if (substdio_put(&ssarchive,line.s,line.len) =3D=3D -1) =
die_archive();
  }

  if (flagqmqp) {
    if (qmail_open(&qq,&qmqpservers) =3D=3D -1)		/* open qmqp */
      strerr_die2sys(111,FATAL,ERR_QMAIL_QUEUE);
  } else if (qmail_open(&qq,(stralloc *) 0) =3D=3D -1)	/* open queue */
      strerr_die2sys(111,FATAL,ERR_QMAIL_QUEUE);

  if (!flagsublist) {
    getconf_line(&mailinglist,"mailinglist",1,FATAL,dir);
    qa_puts("Mailing-List: ");
    qa_put(mailinglist.s,mailinglist.len);
    if (getconf_line(&line,"listid",0,FATAL,dir)) {
      flaglistid =3D 1;
      qmail_puts(&qq,"\nList-ID: ");
      qmail_put(&qq,line.s,line.len);
    }
    qa_puts("\n");
  }
  copy(&qq,"headeradd",'H',FATAL);
  qa_put(mydtline.s,mydtline.len);

  flagmlwasthere =3D 0;
  flaginheader =3D 1;
  flagfoundokpart =3D 1;
  flagbadfield =3D 0;
  flagbadpart =3D 0;
  flagseenext =3D 0;
  flagsubline =3D 0;
  flagfromline =3D 0;
  flagreceived =3D 0;
  for (;;) {
    if (getln(&ss0,&line,&match,'\n') =3D=3D -1)
      strerr_die2sys(111,FATAL,ERR_READ_INPUT);
    if (flaginheader && match) {
      if (line.len =3D=3D 1) {		/* end of header */
	flaginheader =3D 0;
        if (flagindexed)		/* std entry */
          r =3D idx_copy_insertsubject();	/* all indexed lists */
        if (flagprefixed && !flagsublist) {
          qa_puts("Subject:");
          if (!flagindexed) {		/* non-indexed prefixed lists */
            concatHDR(subject.s,subject.len,&lines,FATAL);
            decodeHDR(lines.s,lines.len,&qline,charset.s,FATAL);
            r =3D unfoldHDR(qline.s,qline.len,&lines,
			charset.s,&dcprefix,1,FATAL);
          }
          if (!(r & 2)) {
            qmail_puts(&qq," ");
            if (serial =3D=3D prefix.len)
              qmail_put(&qq,prefix.s,prefix.len);
            else {
              qmail_put(&qq,prefix.s,serial);
              qmail_puts(&qq,szmsgnum);
              qmail_put(&qq,prefix.s+serial+1,prefix.len-serial-1);
            }
          }
          qa_put(subject.s,subject.len);
        }
		/* do other stuff to do with post header processing here */
	if (content.len) {		/* get MIME boundary, if exists */
          concatHDR(content.s,content.len,&qline,FATAL);
          if (!stralloc_copy(&content,&qline)) die_nomem();

	  if (flagtrailer &&		/* trailer only for some multipart */
		case_startb(content.s,content.len,"multipart/"))
	    if (!case_startb(content.s+10,content.len-10,"mixed") &&
		!case_startb(content.s+10,content.len-10,"digest") &&
		!case_startb(content.s+10,content.len-10,"parallel"))
	      flagtrailer =3D 0;

           cp =3D content.s;
           cpafter =3D cp + content.len;	/* check after each ';' */
           while ((cp +=3D byte_chr(cp,cpafter-cp,';')) !=3D cpafter) {
             ++cp;
             while (cp < cpafter &&
			(*cp =3D=3D ' ' || *cp =3D=3D '\t' || *cp =3D=3D '\n')) ++cp;
             if (case_startb(cp,cpafter-cp,"boundary=3D")) {
               cp +=3D 9;			/* after boundary=3D */
               if (*cp =3D=3D '"') {	/* quoted boundary */
                 ++cp;
                 cpstart =3D cp;
                 while (cp < cpafter && *cp !=3D '"') ++cp;
		 if (cp =3D=3D cpafter)
			strerr_die1x(100,ERR_MIME_QUOTE);
               } else {			/* non-quoted boundary */
                 cpstart =3D cp;		/* find terminator of boundary */
                 while (cp < cpafter && *cp !=3D ';' &&
			*cp !=3D ' ' && *cp !=3D '\t' && *cp !=3D '\n') ++cp;
               }
               if (!stralloc_copys(&boundary,"--")) die_nomem();
               if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
			die_nomem();
	         flagfoundokpart =3D 0;
               if =
(!constmap_init(&mimeremovemap,mimeremove.s,mimeremove.len,0))
			die_nomem();
               flagbadpart =3D 1;		/* skip before first boundary */
               qa_puts("\n");		/* to make up for the lost '\n' */
            }
          }
        }
      } else if ((*line.s !=3D ' ') && (*line.s !=3D '\t')) {
        flagsubline =3D 0;
        flagfromline =3D 0;
        flagbadfield =3D 0;
        flagarchiveonly =3D 0;
        flagcontline =3D 0;
	if (constmap(&headerremovemap,line.s,byte_chr(line.s,line.len,':')))
	  flagbadfield =3D 1;
        if ((flagnoreceived || !flagreceived) &&
		case_startb(line.s,line.len,"Received:")) {
            if (!flagreceived) {		/* get date from first rec'd */
              flagreceived =3D 1;			/* line (done by qmail) */
              pos =3D byte_chr(line.s,line.len,';');
              if (pos !=3D line.len)		/* has '\n' */
                if (!stralloc_copyb(&received,line.s+pos+2,line.len - =
pos - 3))
                  die_nomem();
            } else {				/* suppress, but archive */
              flagarchiveonly =3D 1;		/* but do not suppress the */
              flagbadfield =3D 1;			/* top one added by qmail */
            }
	} else if (case_startb(line.s,line.len,"Mailing-List:"))
	  flagmlwasthere =3D 1;		/* sublists always ok ezmlm masters */
	else if (mlheader && case_startb(line.s,line.len,mlheader))
	  flagmlwasthere =3D 1;		/* mlheader treated as ML */
        else if ((mimeremove.len || flagtrailer) &&	/* else no MIME =
need*/
		case_startb(line.s,line.len,"Content-Type:")) {
          if (!stralloc_copyb(&content,line.s+13,line.len-13)) =
die_nomem();
          flagcontline =3D 1;
	} else if (case_startb(line.s,line.len,"Subject:")) {
          if (!stralloc_copyb(&subject,line.s+8,line.len-8)) =
die_nomem();
	  flagsubline =3D 1;
          if (flagprefixed && !flagsublist)	/* don't prefix for sublists =
*/
	    flagbadfield =3D 1;			/* we'll print our own */
        } else if (flagtrailer &&
		 case_startb(line.s,line.len,"Content-Transfer-Encoding:")) {
          cp =3D line.s + 26;
          cpafter =3D cp + line.len;
          while (cp < cpafter && (*cp =3D=3D ' ' || *cp =3D=3D '\t')) =
++cp;
          if (case_startb(cp,cpafter-cp,"base64")) encin =3D 'B';
          else if (case_startb(cp,cpafter-cp,"Quoted-Printable")) encin =
=3D 'Q';
        } else if (flaglistid && =
case_startb(line.s,line.len,"list-id:"))
	  flagbadfield =3D 1;		/* suppress if we added our own */
	else if (flagindexed) {

          if (case_startb(line.s,line.len,"From:")) {
            flagfromline =3D 1;
            if (!stralloc_copyb(&from,line.s+5,line.len-5)) die_nomem();
          }
        } else if (line.len =3D=3D mydtline.len)
	  if (!byte_diff(line.s,line.len,mydtline.s))
            strerr_die2x(100,FATAL,ERR_LOOPING);
      } else {			/* continuation lines */
        if (flagsubline) {
	  if (!stralloc_cat(&subject,&line)) die_nomem();
        } else if (flagfromline) {
	  if (!stralloc_cat(&from,&line)) die_nomem();
        } else if (flagcontline) {
          if (!stralloc_cat(&content,&line)) die_nomem();
        }
      }
    } else				/* body */
      msgsize +=3D line.len;		/* always for tstdig support */

    if (!(flaginheader && flagbadfield)) {
      if (boundary.len && line.len > boundary.len &&
		!str_diffn(line.s,boundary.s,boundary.len)) {
        if (line.s[boundary.len] =3D=3D '-' && line.s[boundary.len+1] =
=3D=3D '-') {
          flagbadpart =3D 0;		/* end boundary should be output */
          if (flagtrailer) {
            qmail_puts(&qq,"\n");
            qmail_put(&qq,boundary.s,boundary.len);
            qmail_puts(&qq,"\nContent-Type: text/plain; charset=3D");
            qmail_puts(&qq,charset.s);
            transferenc();		/* trailer for multipart message */
	    copy(&qq,"text/trailer",flagcd,FATAL);
            if (flagcd =3D=3D 'B')	{	/* need to do our own flushing */
              encodeB("",0,&qline,2,FATAL);
              qmail_put(&qq,qline.s,qline.len);
            }
	  }
        } else {			/* new part */
            flagbadpart =3D 1;		/* skip lines */
            if (!stralloc_copy(&lines,&line)) die_nomem();	/* but save =
*/
            flagseenext =3D 1;		/* need to check Cont-type */
        }
      } else if (flagseenext) {		/* last was boundary, now stored */
        if (case_startb(line.s,line.len,"content-type:")) {
          flagseenext =3D 0;		/* done thinking about it */
          cp =3D line.s + 13;			/* start of type */
          while (*cp =3D=3D ' ' || *cp =3D=3D '\t') ++cp;
          cpstart =3D cp;			/* end of type */
          while (*cp !=3D '\n' && *cp !=3D '\t' && *cp !=3D ' ' && *cp =
!=3D ';') ++cp;
	  if (constmap(&mimeremovemap,cpstart,cp-cpstart)) {
            flagbadpart =3D 1;
          } else {
	    flagfoundokpart =3D 1;
            qa_put(lines.s,lines.len);	/* saved lines */
            flagbadpart =3D 0;		/* do this part */
          }
        } else if (line.len =3D=3D 1) {	/* end of content desc */
          flagbadpart =3D 0;		/* default type, so ok */
          flagseenext =3D 0;		/* done thinking about it */
        } else				/* save line in cont desc */
          if (!stralloc_cat(&lines,&line)) die_nomem();
      }
      if (!flagbadpart)
        qa_put(line.s,line.len);

    } else if (flagarchiveonly && flagarchived)	/* received headers */
      if (substdio_put(&ssarchive,line.s,line.len) =3D=3D -1) =
die_archive();
    if (!match)
      break;
  }
  if (!boundary.len && flagtrailer) {
    qmail_puts(&qq,"\n");		/* trailer for non-multipart message */
    if (!encin || encin =3D=3D 'Q') {	/* can add for QP, but not for =
base64 */
      putsubs(dir, hash_lo+1L, hash_hi, dumsubto, 1, FATAL);   /* kuroko =
add */
      set_cptarget(tobuf);             /*  kuroko add */=20
      copy(&qq,"text/trailer",encin,FATAL);
      qmail_puts(&qq,"\n");		/* no need to flush for plain/QP */
    }
  }

  cumsize +=3D (msgsize + 128L) >> 8;	/* round to 256 byte 'records' */
					/* check message tag */
  if (flagsublist) {			/* sublists need tag if selected/suppt*/
    if (flaglog)
      if ((ret =3D checktag(dir,innum,hash_lo+1L,"m",(char *) =
0,hashout))) {
        if (*ret) strerr_die2x(111,FATAL,ret);
        else strerr_die2x(100,FATAL,ERR_NOT_PARENT);
      }
    if (!flagmlwasthere)		/* sublists need ML header */
      strerr_die2x(100,FATAL,ERR_SUBLIST);
  } else				/* others are not allowed to have one */
    if (flagmlwasthere)
      strerr_die2x(100,FATAL,ERR_MAILING_LIST);
  if (!flagfoundokpart)			/* all parts were on the strip list */
      strerr_die2x(100,FATAL,ERR_BAD_ALL);

  if (flagarchived) {
    if (substdio_flush(&ssarchive) =3D=3D -1) die_archive();
    if (fsync(fdarchive) =3D=3D -1) die_archive();
    if (fchmod(fdarchive,MODE_ARCHIVE | 0700) =3D=3D -1) die_archive();
    if (close(fdarchive) =3D=3D -1) die_archive(); /* NFS stupidity */
  }

  if (flaglog) {
    tagmsg(dir,innum,sender,"m",hashout,qq.msgbytes,53L,FATAL);
    hashout[COOKIE] =3D '\0';
  }

  numwrite();
  if (!stralloc_copy(&line,&outlocal)) die_nomem();
  if (!stralloc_cats(&line,"-return-")) die_nomem();
  if (!stralloc_cats(&line,szmsgnum)) die_nomem();
  if (!stralloc_cats(&line,"-@")) die_nomem();
  if (!stralloc_cat(&line,&outhost)) die_nomem();
  if (!stralloc_cats(&line,"-@[]")) die_nomem();
  if (!stralloc_0(&line)) die_nomem();
  qmail_from(&qq,line.s);       /* envelope sender */
  subs =3D putsubs(dir,hash_lo,hash_hi,subto,1,FATAL);	/* subscribers */
  /* set_cptarget(tobuf);     /* kuroko add */
  /* copy(&qq, "text/trailer",encin,FATAL);   /* kuroko add */
  if (flagsublist) hash_lo++;

  if (*(err =3D qmail_close(&qq)) =3D=3D '\0') {
      if (flaglog)				/* mysql logging */
	(void) logmsg(dir,outnum,hash_lo,subs,flagsublist ? 3 : 4);
      closesql();
      strnum[fmt_ulong(strnum,qmail_qp(&qq))] =3D 0;
      strerr_die2x(0,"ezmlm-send: info: qp ",strnum);
  } else {
      --msgnum;
      cumsize -=3D (msgsize + 128L) >> 8;
      numwrite();
      strerr_die3x(111,FATAL,ERR_TMP_QMAIL_QUEUE,err + 1);
  }
}

------=_NextPart_000_0258_01C12386.23871650--

