示例#1
0
文件: ezmlm-get.c 项目: abh/ezmlm-idx
void copymsg(int fd,char format)
/* Copy archive message "msg" itself from open file handle fd, in "format" */
{
  int match;
  int flaginheader;
  int flagskipblanks;
  int flaggoodfield;

  switch(format) {
    case VIRGIN:
    case NATIVE:
      substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
      for (;;) {
        if (getln(&sstext,&line,&match,'\n') == -1)
           strerr_die2sys(111,FATAL,MSG1(ERR_READ,line.s));
        if (match) {
           qmail_put(&qq,line.s,line.len);
	   msgsize += line.len;
        } else
           break;
      }
      break;
    case MIME:
    case MIXED:
      flaginheader = 1;
      flaggoodfield = 0;
      substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
      for (;;) {
        if (getln(&sstext,&line,&match,'\n') == -1)
           strerr_die2sys(111,FATAL,MSG1(ERR_READ,line.s));
        if (match) {
          if (flaginheader) {
            if (line.len == 1) {
              flaginheader = 0;
              flaggoodfield = 1;
            } else if (line.s[0] != ' ' && line.s[0] != '\t') {
              flaggoodfield = 0;
              if (constmap(&digheadersmap,line.s,
			byte_chr(line.s,line.len,':')))
                flaggoodfield = 1;
            }
            if (flaggoodfield) {
              qmail_put(&qq,line.s,line.len);		/* header */
	      msgsize += line.len;
	    }
          } else {
            qmail_put(&qq,line.s,line.len);		/* body */
	    msgsize += line.len;
	  }
        } else
          break;
      }
      break;
    case RFC1153:		/* Not worth optimizing. Rarely used */
      flaginheader = 1;
      flagskipblanks = 1;	/* must skip terminal blanks acc to rfc1153 */
      archtype = ' ';		/* rfc1153 requires ordered headers */
      if (!stralloc_copys(&archblanklines,"")) die_nomem();
      substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
      for (;;) {
        if (getln(&sstext,&line,&match,'\n') == -1)
           strerr_die2sys(111,FATAL,MSG1(ERR_READ,line.s));
        if (match) {
          if (flaginheader) {
            if (line.len == 1) {
              flaginheader = 0;
              if (archdate.len) {
                qmail_put(&qq,archdate.s,archdate.len);
                archdate.len = 0;
		msgsize += archdate.len;
              }
              if (archto.len) {
                qmail_put(&qq,archto.s,archto.len);
		msgsize += archto.len;
                archto.len = 0;
              }
              if (archfrom.len) {
                qmail_put(&qq,archfrom.s,archfrom.len);
		msgsize += archfrom.len;
                archfrom.len = 0;
              }
              if (archcc.len) {
                qmail_put(&qq,archcc.s,archcc.len);
		msgsize += archcc.len;
                archcc.len = 0;
              }
              if (archsubject.len) {
                qmail_put(&qq,archsubject.s,archsubject.len);
		msgsize += archsubject.len;
                archsubject.len = 0;
              }
              if (archmessageid.len) {
                qmail_put(&qq,archmessageid.s,archmessageid.len);
		msgsize += archmessageid.len;
                archmessageid.len = 0;
              }
              if (archkeywords.len) {
                qmail_put(&qq,archkeywords.s,archkeywords.len);
		msgsize += archkeywords.len;
                archkeywords.len = 0;
              }
              qmail_puts(&qq,"\n");
            } else if (line.s[0] == ' ' || line.s[0] == '\t') {
              switch (archtype) {	/* continuation lines */
                case ' ':
                  break;
                case 'D':
                  if (!stralloc_cat(&archdate,&line)) die_nomem(); break;
                case 'F':
                  if (!stralloc_cat(&archfrom,&line)) die_nomem(); break;
                case 'T':
                  if (!stralloc_cat(&archto,&line)) die_nomem(); break;
                case 'C':
                  if (!stralloc_cat(&archcc,&line)) die_nomem(); break;
                case 'S':
                  if (!stralloc_cat(&archsubject,&line)) die_nomem(); break;
                case 'M':
                  if (!stralloc_cat(&archmessageid,&line)) die_nomem(); break;
                case 'K':
                  if (!stralloc_cat(&archkeywords,&line)) die_nomem(); break;
                default:
                  strerr_die2x(111,FATAL,
                      "Program error: Bad archive header type");
              }
            } else {
              archtype = ' ';
              if (case_startb(line.s,line.len,"cc:")) {
                archtype='C';
                if (!stralloc_copy(&archcc,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"date:")) {
                archtype='D';
                if (!stralloc_copy(&archdate,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"from:")) {
                archtype='F';
                if (!stralloc_copy(&archfrom,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"keywords:")) {
                archtype='K';
                if (!stralloc_copy(&archkeywords,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"message-id:")) {
                archtype='M';
                if (!stralloc_copy(&archmessageid,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"subject:")) {
                archtype='S';
                if (!stralloc_copy(&archsubject,&line)) die_nomem();
              }
              else if (case_startb(line.s,line.len,"to:")) {
                archtype='T';
                if (!stralloc_copy(&archto,&line)) die_nomem();
              }
            }
          } else if (line.len == 1) {
            if (!flagskipblanks)
              if (!stralloc_copys(&archblanklines,"\n")) die_nomem();
          } else {
            if (archblanklines.len) {
              qmail_put(&qq,archblanklines.s,archblanklines.len);
              archblanklines.len = 0;
            }
            flagskipblanks = 0;
            qmail_put(&qq,line.s,line.len);
	    msgsize += line.len;
          }
        } else
          break;
      }
      break;
    default:
      strerr_die2x(100,FATAL,"Program error: bad format in copymsg()");
  }
}
示例#2
0
char *
filter_mail(char *mail, int *done)
{
	char			*domain, *alias;
	unsigned int		at;
	int			round;
#ifdef DASH_EXT
	unsigned int 		i;
#endif

	if (mail == (char *)0) {
		ext = 0;
		return 0;
	}

	at = str_rchr(mail, '@');
	if (at == 0 || mail[at] != '@') {
		ext = 0;
		return 0;
	}
	domain = mail + at + 1;

	if (adok) {
		alias = constmap(&ad_map, domain, str_len(domain));
		if (alias && *alias)
			domain = alias;
	}

	if (ext == 0) {
		ext = at;
		extcnt = -1;
		*done = 0;
	} else {
		if (extcnt == 0) {
			*done = 1;
			ext = 0;
			return 0;
		}
#ifdef DASH_EXT
		/*
		 * limit ext to the first DASH_EXT_LEVELS extensions.
		 * We will only check for (DASH_EXT_LEVELS = 4):
		 * [email protected]
		 * [email protected]
		 * [email protected]
		 * [email protected]
		 * [email protected]
		 * [email protected]
		 */
		if (ext == at)
			for (i = 0, ext = 0, extcnt = 1;
			    ext < at && extcnt <= DASH_EXT_LEVELS; ext++)
				if (mail[ext] == *auto_break) extcnt++;
		while (ext != 0 && --ext > 0) {
			if (mail[ext] == *auto_break) break;
		}
		extcnt--;
#else
#error XXX XXX 
		/* basic qmail-ldap behavior test for [email protected] and
		   [email protected] */
		ext = 0;
		extcnt = 0;
#endif
	}
	
	for (round = 0; round < 2; round++) {
		switch (round) {
		case 0:
			/* build the search string for the email address */
			/* mail address */
			if (!filter_start(&filter) ||
			    !stralloc_cats(&filter, "(|(") ||
			    !stralloc_cats(&filter, LDAP_MAIL) ||
			    !stralloc_cats(&filter, "="))
				return 0;
			break;
		case 1:
			/* mailalternate address */
			if (!stralloc_cats(&filter, ")(") ||
			    !stralloc_cats(&filter, LDAP_MAILALTERNATE) ||
			    !stralloc_cats(&filter, "="))
				return 0;
			break;
		}

		/* username till current '-' or '@' */
		if (!filter_escape(&filter, mail, ext))
			return 0;
		/* do not append catchall in the first round */
		if (ext != at) {
			/* catchall or default */
			if (extcnt > 0) /* add '-' */
				if (!stralloc_cats(&filter, auto_break))
					return 0;
			if (!stralloc_cats(&filter, LDAP_CATCH_ALL))
				return 0;
		}
		/* @domain.com */
		if (!stralloc_append(&filter, "@") ||
		    !filter_escape(&filter, domain, str_len(domain)))
			return 0;
	}

	if (!stralloc_cats(&filter, "))") ||
	    !filter_end(&filter))
		return 0;

	if (extcnt == 0)
		*done = 1;

	if (mail[0] == *auto_break) *done = 1; // OSC: do not do DASH_EXT loop if first char is auto_break
	return filter.s;
}
示例#3
0
int main(int argc,char **argv)
{
  unsigned long maxmsgsize = 0L;
  unsigned long minmsgsize = 0L;
  unsigned long msgsize = 0L;
  char linetype = ' ';
  char *cp, *cpstart, *cpafter;
  const char *dir;
  const char *err;
  const char *sender;
  unsigned int len;
  int match;

  getconfopt(argc,argv,options,-1,&dir);
  if (dir) {
    startup(dir);
    flagparsemime = 1;		/* only if dir do we have mimeremove/reject */
    if (getconf_line(&line,"msgsize",0)) {
      if (!stralloc_0(&line)) die_nomem();
      len = scan_ulong(line.s,&maxmsgsize);
      if (line.s[len] == ':')
        scan_ulong(line.s+len+1,&minmsgsize);
    }
    if (flagforward) {
      if (!stralloc_copys(&mydtline,"Delivered-To: command forwarder for "))
	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();
    }
  } else {
    flagtook = 1;		/* if no "dir" we can't get outlocal/outhost */
    flagforward = 0;		/* nor forward requests */
  }

  sender = get_sender();
  if (!sender)
    die_sender();
  if (!*sender)
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

  if (flagparsemime) {		/* set up MIME parsing */
    if (getconf(&mimeremove,"mimekeep",0))
      mimeremoveflag = 1;
    else
      getconf(&mimeremove,"mimeremove",0);
    constmap_init(&mimeremovemap,mimeremove.s,mimeremove.len,0);
    getconf(&mimereject,"mimereject",0);
    constmap_init(&mimerejectmap,mimereject.s,mimereject.len,0);
  }
  if (flagheaderreject && dir) {
    getconf(&headerreject,"headerreject",0);
    constmap_init(&headerrejectmap,headerreject.s,headerreject.len,0);
  }
  for (;;) {
    if (getln(&ssin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    if (!match) break;
    if (flagheaderreject && dir)
      if (constmap(&headerrejectmap,line.s,byte_chr(line.s,line.len,':')))
        strerr_die2x(100,FATAL,MSG(ERR_MAILING_LIST));

    if (line.len == 1) break;
    cp = line.s; len = line.len;
    if ((*cp == ' ' || *cp == '\t')) {
      switch(linetype) {
	case 'T': if (!stralloc_catb(&to,cp,len-1)) die_nomem(); break;
	case 'S': if (!stralloc_catb(&subject,cp,len-1)) die_nomem(); break;
	case 'C': if (!stralloc_catb(&content,cp,len-1)) die_nomem(); break;
	case 'P': if (!stralloc_catb(&precd,cp,len-1)) die_nomem(); break;
	default: break;
      }
    } else {
      if (!flagtook &&
		(case_startb(cp,len,"to:") || case_startb(cp,len,"cc:"))) {
	linetype = 'T';		/* cat so that To/Cc don't overwrite */
        if (!stralloc_catb(&to,line.s + 3,line.len - 4)) die_nomem();
      } else if ((flagneedsubject || flagrejectcommands) &&
			 case_startb(cp,len,"subject:")) {
	if (!stralloc_copyb(&subject,cp+8,len-9)) die_nomem();
	linetype = 'S';
      } else if (case_startb(cp,len,"content-type:")) {
	if (!stralloc_copyb(&content,cp+13,len-14)) die_nomem();
	linetype = 'C';
      } else if (case_startb(cp,len,"precedence:")) {
	if (!stralloc_copyb(&precd,cp+11,len-12)) die_nomem();
	linetype = 'P';
      } else {
	if (flagforward && line.len == mydtline.len) {
	  if (!byte_diff(line.s,line.len,mydtline.s))
            strerr_die2x(100,FATAL,MSG(ERR_LOOPING));
        }
        linetype = ' ';
      }
    }
  }
  if (precd.len >= 4 &&
		(!case_diffb(precd.s + precd.len - 4,4,"junk") ||
		!case_diffb(precd.s + precd.len - 4,4,"bulk")))
	  strerr_die1x(99,MSG(ERR_JUNK));	/* ignore precedence junk/bulk */
  cp = subject.s;
  len = subject.len;
  while (len && (cp[len-1] == ' ' || cp[len-1] == '\t')) --len;
  while (len && ((*cp == ' ') || (*cp == '\t'))) { ++cp; --len; }
  flaghavesubject = 1;

  if (flagbody)
    if ((len > 9 && case_starts(cp,"subscribe"))
	|| (len > 11 && case_starts(cp,"unsubscribe")))
      flaghavecommand = 1;

  switch(len) {
    case 0: flaghavesubject = 0; break;
    case 4: if (!case_diffb("help",4,cp)) flaghavecommand = 1; break;
    case 6:	/* Why can't they just leave an empty subject empty? */
	    if (!case_diffb("(null)",6,cp))
              flaghavesubject = 0;
            else
	    if (!case_diffb("(none)",6,cp))
              flaghavesubject = 0;
            else
              if (!case_diffb("remove",6,cp))
	        flaghavecommand = 1;
            break;
    case 9: if (!case_diffb("subscribe",9,cp)) flaghavecommand = 1; break;
    case 11: if (!case_diffb("unsubscribe",11,cp)) flaghavecommand = 1; break;
    case 12: if (!case_diffb("(no subject)",12,cp)) flaghavesubject = 0; break;
    default: break;
  }

  if (!flagtook && !getto(&to))
    strerr_die2x(exitquiet,FATAL,MSG(ERR_NO_ADDRESS));

  if (flagneedsubject && !flaghavesubject)
    strerr_die2x(100,FATAL,MSG(ERR_NO_SUBJECT));

  if (flagrejectcommands && flaghavecommand) {
    if (flagforward) {			/* flagforward => forward */
      if (qmail_open(&qq) == -1)	/* open queue */
	strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));
      qmail_put(&qq,mydtline.s,mydtline.len);
      if (seek_begin(0) == -1)
	strerr_die2sys(111,FATAL,MSG(ERR_SEEK_INPUT));
      if (qmail_copy(&qq,&ssin2,copylines) != 0)
	strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      if (!stralloc_copy(&to,&outlocal)) die_nomem();
      if (!stralloc_cats(&to,"-request@")) die_nomem();
      if (!stralloc_cat(&to,&outhost)) die_nomem();
      if (!stralloc_0(&to)) die_nomem();
      qmail_from(&qq,sender);
      qmail_to(&qq,to.s);
      if (*(err = qmail_close(&qq)) == '\0') {
        strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
        strerr_die2x(99,"ezmlm-request: info: forward qp ",strnum);
      } else
        strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);
    } else
      strerr_die2x(100,FATAL,MSG(ERR_SUBCOMMAND));
  }

  if (content.len) {			/* MIME header */
    cp = content.s;
    len = content.len;
    while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
    cpstart = cp;
    if (*cp == '"') {			/* might be commented */
      ++cp; cpstart = cp;
      while (len && *cp != '"') { ++cp; --len; }
    } else {
      while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
        ++cp; --len;
      }
    }

    if (flagparsemime)
      if ((!!constmap(&mimeremovemap,cpstart,cp-cpstart) ^ mimeremoveflag) ||
	  constmap(&mimerejectmap,cpstart,cp-cpstart)) {
	*(cp) = (char) 0;
	strerr_die2x(100,FATAL,MSG1(ERR_BAD_TYPE,cpstart));
      }

    cpafter = content.s+content.len;
    while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
      ++cp;
      while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
      if (case_startb(cp,cpafter - cp,"boundary=")) {
        cp += 9;			/* after boundary= */
        if (cp < cpafter && *cp == '"') {
          ++cp;
          cpstart = cp;
          while (cp < cpafter && *cp != '"') ++cp;
	  if (cp == cpafter)
		strerr_die1x(100,MSG(ERR_MIME_QUOTE));
        } else {
          cpstart = cp;
          while (cp < cpafter &&
             *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
        }
        if (!stralloc_copys(&boundary,"--")) die_nomem();
        if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
		die_nomem();
	break;
      }
    }		/* got boundary, now parse for parts */
  }

  for (;;) {
    if (getln(&ssin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    if (!match) break;
    if (line.len == 1) {
      flagcheck = 0;
      continue;
		/* Doesn't do continuation lines. _very_ unusual, and worst */
		/* case one slips through that shouldn't have */
    } else if (flagcheck && case_startb(line.s,line.len,"content-type:")) {
        cp = line.s + 13;
	len = line.len - 14;			/* zap '\n' */
        while (*cp == ' ' || *cp == '\t') { ++cp; --len; }
        cpstart = cp;
	if (*cp == '"') {			/* quoted */
	  ++cp; cpstart = cp;
	  while (len && *cp != '"') { ++cp; --len; }
        } else {				/* not quoted */
          while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
	    ++cp; --len;
	  }
        }
	if (flagparsemime && constmap(&mimerejectmap,cpstart,cp-cpstart)) {
          *cp = '\0';
          strerr_die2x(100,FATAL,MSG1(ERR_BAD_PART,cpstart));
        }
    } else if (boundary.len && *line.s == '-' && line.len > boundary.len &&
	!str_diffn(line.s,boundary.s,boundary.len)) {
        flagcheck = 1;
    } else {
      if (!msgsize && flagbody)
	if (case_startb(line.s,line.len,"subscribe") ||
		case_startb(line.s,line.len,"unsubscribe"))
	  strerr_die2x(100,FATAL,MSG(ERR_BODYCOMMAND));
      if (!flagcheck) {
	  msgsize += line.len;
	  if (maxmsgsize && msgsize > maxmsgsize) {
	    strnum[fmt_ulong(strnum,maxmsgsize)] = 0;
	    strerr_die2x(100,FATAL,MSG1(ERR_MAX_SIZE,strnum));
	  }
      }
    }
  }
  if (msgsize < minmsgsize) {
    strnum[fmt_ulong(strnum,minmsgsize)] = 0;
        strerr_die2x(100,FATAL,MSG1(ERR_MIN_SIZE,strnum));
  }
  _exit(0);
}