예제 #1
0
파일: enqueue.c 프로젝트: lucasad/OpenSMTPD
static void
send_header(FILE *fout, const char *line, size_t len)
{
	int	i;

	if (strncasecmp("To:", line, 3) != 0 &&
	    strncasecmp("Cc:", line, 3) != 0 &&
	    strncasecmp("Bcc:", line, 4) != 0 &&
	    strncasecmp("From:", line, 5) != 0) {
		send_line(fout, 0, "%.*s", (int)len, line);
		return;
	}
	if (len >= sizeof pstate.buf) {
		send_line(fout, 0, "%.*s", (int)len, line);
		return;
	}

	/* XXX
	 * To, Cc and Bcc may need rewrite, we can reuse the
	 * msg recipients field since former content has already
	 * been used at this point.
	 */
	memset(&pstate, 0, sizeof(pstate));
	memcpy(pstate.buf, line, len);
	pstate.buf[len] = 0;
	pstate.wpos = len - 1;
	msg.rcpts = NULL;
	msg.rcpt_cnt = 0;

	if (strncasecmp("From:", line, 5) == 0) {
		parse_addr_terminal(1);
		send_line(fout, 0, "%s\n", msg.from);
	}
	else {
		parse_addr_terminal(0);
		for (i = 0; i < msg.rcpt_cnt; ++i)
			if (*msg.rcpts[i] != '\0')
				send_line(fout, 0, "%s%s%s\n", i > 0 ? "\t" : "",
				    msg.rcpts[i], i < msg.rcpt_cnt - 1 ? "," : "");
	}
}
예제 #2
0
파일: enqueue.c 프로젝트: jcarnat/OpenSMTPD
static void
parse_addr(char *s, size_t len, int is_from)
{
	size_t	 pos = 0;
	int	 terminal = 0;

	/* unless this is a continuation... */
	if (!WSP(s[pos]) && s[pos] != ',' && s[pos] != ';') {
		/* ... skip over everything before the ':' */
		for (; pos < len && s[pos] != ':'; pos++)
			;	/* nothing */
		/* ... and check & reset parser state */
		parse_addr_terminal(is_from);
	}

	/* skip over ':' ',' ';' and whitespace */
	for (; pos < len && !pstate.quote && (WSP(s[pos]) || s[pos] == ':' ||
	    s[pos] == ',' || s[pos] == ';'); pos++)
		;	/* nothing */

	for (; pos < len; pos++) {
		if (!pstate.esc && !pstate.quote && s[pos] == '(')
			pstate.comment++;
		if (!pstate.comment && !pstate.esc && s[pos] == '"')
			pstate.quote = !pstate.quote;

		if (!pstate.comment && !pstate.quote && !pstate.esc) {
			if (s[pos] == ':') {	/* group */
				for(pos++; pos < len && WSP(s[pos]); pos++)
					;	/* nothing */
				pstate.wpos = 0;
			}
			if (s[pos] == '\n' || s[pos] == '\r')
				break;
			if (s[pos] == ',' || s[pos] == ';') {
				terminal = 1;
				break;
			}
			if (s[pos] == '<') {
				pstate.brackets = 1;
				pstate.wpos = 0;
			}
			if (pstate.brackets && s[pos] == '>')
				terminal = 1;
		}

		if (!pstate.comment && !terminal && (!(!(pstate.quote ||
		    pstate.esc) && (s[pos] == '<' || WSP(s[pos]))))) {
			if (pstate.wpos >= sizeof(pstate.buf))
				errx(1, "address exceeds buffer size");
			pstate.buf[pstate.wpos++] = s[pos];
		}

		if (!pstate.quote && pstate.comment && s[pos] == ')')
			pstate.comment--;

		if (!pstate.esc && !pstate.comment && !pstate.quote &&
		    s[pos] == '\\')
			pstate.esc = 1;
		else
			pstate.esc = 0;
	}

	if (terminal)
		parse_addr_terminal(is_from);

	for (; pos < len && (s[pos] == '\r' || s[pos] == '\n'); pos++)
		;	/* nothing */

	if (pos < len)
		parse_addr(s + pos, len - pos, is_from);
}
예제 #3
0
파일: enqueue.c 프로젝트: jcarnat/OpenSMTPD
static int
parse_message(FILE *fin, int get_from, int tflag, FILE *fout)
{
	char	*buf;
	size_t	 len;
	u_int	 i, cur = HDR_NONE;
	u_int	 header_seen = 0, header_done = 0;

	bzero(&pstate, sizeof(pstate));
	for (;;) {
		buf = fgetln(fin, &len);
		if (buf == NULL && ferror(fin))
			err(1, "fgetln");
		if (buf == NULL && feof(fin))
			break;
		if (buf == NULL || len < 1)
			err(1, "fgetln weird");

		/* account for \r\n linebreaks */
		if (len >= 2 && buf[len - 2] == '\r' && buf[len - 1] == '\n')
			buf[--len - 1] = '\n';

		if (len == 1 && buf[0] == '\n')		/* end of header */
			header_done = 1;

		if (!WSP(buf[0])) {	/* whitespace -> continuation */
			if (cur == HDR_FROM)
				parse_addr_terminal(1);
			if (cur == HDR_TO || cur == HDR_CC || cur == HDR_BCC)
				parse_addr_terminal(0);
			cur = HDR_NONE;
		}

		/* not really exact, if we are still in headers */
		if (len + (buf[len - 1] == '\n' ? 0 : 1) >= LINESPLIT)
			msg.need_linesplit = 1;

		for (i = 0; !header_done && cur == HDR_NONE &&
		    i < nitems(keywords); i++)
			if (len > strlen(keywords[i].word) &&
			    !strncasecmp(buf, keywords[i].word,
			    strlen(keywords[i].word)))
				cur = keywords[i].type;

		if (cur != HDR_NONE)
			header_seen = 1;

		if (cur != HDR_BCC) {
			fprintf(fout, "%.*s", (int)len, buf);
			if (buf[len - 1] != '\n')
				fputc('\n', fout);
			if (ferror(fout))
				err(1, "write error");
		}

		/*
		 * using From: as envelope sender is not sendmail compatible,
		 * but I really want it that way - maybe needs a knob
		 */
		if (cur == HDR_FROM) {
			msg.saw_from++;
			if (get_from)
				parse_addr(buf, len, 1);
		}

		if (tflag && (cur == HDR_TO || cur == HDR_CC || cur == HDR_BCC))
			parse_addr(buf, len, 0);

		if (cur == HDR_DATE)
			msg.saw_date++;
		if (cur == HDR_MSGID)
			msg.saw_msgid++;
		if (cur == HDR_MIME_VERSION)
			msg.saw_mime_version = 1;
		if (cur == HDR_CONTENT_TYPE)
			msg.saw_content_type = 1;
		if (cur == HDR_CONTENT_DISPOSITION)
			msg.saw_content_disposition = 1;
		if (cur == HDR_CONTENT_TRANSFER_ENCODING)
			msg.saw_content_transfer_encoding = 1;
		if (cur == HDR_USER_AGENT)
			msg.saw_user_agent = 1;
	}

	return (!header_seen);
}