⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 headers.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				}
			}
			if (quoteit)
			{
				if (bp == &buf[1])
					bp--;
				else
					*bp++ = '"';
				while ((c = *p++) != '<')
				{
					if (bp < buflim)
						*bp++ = c;
				}
				*bp++ = c;
			}
			copylev = 0;
			putgmac = quoteit = FALSE;
			continue;
		}

		if (c == '>')
		{
			if (anglelev > 0)
			{
				anglelev--;
				if (!skipping)
				{
					realanglelev--;
					buflim++;
				}
			}
			else if (!skipping)
			{
				/* syntax error: unmatched > */
				if (copylev > 0)
					bp--;
				quoteit = TRUE;
				continue;
			}
			if (copylev++ <= 0)
				*bp++ = c;
			continue;
		}

		/* must be a real address character */
	putg:
		if (copylev <= 0 && !putgmac)
		{
			if (bp > bufhead && bp[-1] == ')')
				*bp++ = ' ';
			*bp++ = MACROEXPAND;
			*bp++ = 'g';
			putgmac = TRUE;
		}
	}

	/* repair any syntactic damage */
	if (realqmode)
		*bp++ = '"';
	while (realcmtlev-- > 0)
		*bp++ = ')';
	while (realanglelev-- > 0)
		*bp++ = '>';
	*bp++ = '\0';

	if (tTd(33, 1))
	{
		dprintf("crackaddr=>`");
		xputs(buf);
		dprintf("'\n");
	}

	return buf;
}
/*
**  PUTHEADER -- put the header part of a message from the in-core copy
**
**	Parameters:
**		mci -- the connection information.
**		hdr -- the header to put.
**		e -- envelope to use.
**		flags -- MIME conversion flags.
**
**	Returns:
**		none.
**
**	Side Effects:
**		none.
*/

/*
 * Macro for fast max (not available in e.g. DG/UX, 386/ix).
 */
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif /* ! MAX */

void
putheader(mci, hdr, e, flags)
	register MCI *mci;
	HDR *hdr;
	register ENVELOPE *e;
	int flags;
{
	register HDR *h;
	char buf[MAX(MAXLINE,BUFSIZ)];
	char obuf[MAXLINE];

	if (tTd(34, 1))
		dprintf("--- putheader, mailer = %s ---\n",
			mci->mci_mailer->m_name);

	/*
	**  If we're in MIME mode, we're not really in the header of the
	**  message, just the header of one of the parts of the body of
	**  the message.  Therefore MCIF_INHEADER should not be turned on.
	*/

	if (!bitset(MCIF_INMIME, mci->mci_flags))
		mci->mci_flags |= MCIF_INHEADER;

	for (h = hdr; h != NULL; h = h->h_link)
	{
		register char *p = h->h_value;

		if (tTd(34, 11))
		{
			dprintf("  %s: ", h->h_field);
			xputs(p);
		}

		/* Skip empty headers */
		if (h->h_value == NULL)
			continue;

		/* heuristic shortening of MIME fields to avoid MUA overflows */
		if (MaxMimeFieldLength > 0 &&
		    wordinclass(h->h_field,
				macid("{checkMIMEFieldHeaders}", NULL)))
		{
			if (fix_mime_header(h->h_value))
			{
				sm_syslog(LOG_ALERT, e->e_id,
					  "Truncated MIME %s header due to field size (possible attack)",
					  h->h_field);
				if (tTd(34, 11))
					dprintf("  truncated MIME %s header due to field size (possible attack)\n",
						h->h_field);
			}
		}

		if (MaxMimeHeaderLength > 0 &&
		    wordinclass(h->h_field,
				macid("{checkMIMETextHeaders}", NULL)))
		{
			if (strlen(h->h_value) > (size_t)MaxMimeHeaderLength)
			{
				h->h_value[MaxMimeHeaderLength - 1] = '\0';
				sm_syslog(LOG_ALERT, e->e_id,
					  "Truncated long MIME %s header (possible attack)",
					  h->h_field);
				if (tTd(34, 11))
					dprintf("  truncated long MIME %s header (possible attack)\n",
						h->h_field);
			}
		}

		if (MaxMimeHeaderLength > 0 &&
		    wordinclass(h->h_field,
				macid("{checkMIMEHeaders}", NULL)))
		{
			if (shorten_rfc822_string(h->h_value, MaxMimeHeaderLength))
			{
				sm_syslog(LOG_ALERT, e->e_id,
					  "Truncated long MIME %s header (possible attack)",
					  h->h_field);
				if (tTd(34, 11))
					dprintf("  truncated long MIME %s header (possible attack)\n",
						h->h_field);
			}
		}

		/*
		**  Suppress Content-Transfer-Encoding: if we are MIMEing
		**  and we are potentially converting from 8 bit to 7 bit
		**  MIME.  If converting, add a new CTE header in
		**  mime8to7().
		*/
		if (bitset(H_CTE, h->h_flags) &&
		    bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
			   mci->mci_flags) &&
		    !bitset(M87F_NO8TO7, flags))
		{
			if (tTd(34, 11))
				dprintf(" (skipped (content-transfer-encoding))\n");
			continue;
		}

		if (bitset(MCIF_INMIME, mci->mci_flags))
		{
			if (tTd(34, 11))
				dprintf("\n");
			put_vanilla_header(h, p, mci);
			continue;
		}

		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
		    (h->h_macro == '\0' ||
		     macvalue(h->h_macro & 0377, e) == NULL))
		{
			if (tTd(34, 11))
				dprintf(" (skipped)\n");
			continue;
		}

		/* handle Resent-... headers specially */
		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
		{
			if (tTd(34, 11))
				dprintf(" (skipped (resent))\n");
			continue;
		}

		/* suppress return receipts if requested */
		if (bitset(H_RECEIPTTO, h->h_flags) &&
		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
		{
			if (tTd(34, 11))
				dprintf(" (skipped (receipt))\n");
			continue;
		}

		/* macro expand value if generated internally */
		if (bitset(H_DEFAULT, h->h_flags) ||
		    bitset(H_BINDLATE, h->h_flags))
		{
			expand(p, buf, sizeof buf, e);
			p = buf;
			if (*p == '\0')
			{
				if (tTd(34, 11))
					dprintf(" (skipped -- null value)\n");
				continue;
			}
		}

		if (bitset(H_BCC, h->h_flags))
		{
			/* Bcc: field -- either truncate or delete */
			if (bitset(EF_DELETE_BCC, e->e_flags))
			{
				if (tTd(34, 11))
					dprintf(" (skipped -- bcc)\n");
			}
			else
			{
				/* no other recipient headers: truncate value */
				(void) snprintf(obuf, sizeof obuf, "%s:",
					h->h_field);
				putline(obuf, mci);
			}
			continue;
		}

		if (tTd(34, 11))
			dprintf("\n");

		if (bitset(H_FROM|H_RCPT, h->h_flags))
		{
			/* address field */
			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);

			if (bitset(H_FROM, h->h_flags))
				oldstyle = FALSE;
			commaize(h, p, oldstyle, mci, e);
		}
		else
		{
			put_vanilla_header(h, p, mci);
		}
	}

	/*
	**  If we are converting this to a MIME message, add the
	**  MIME headers (but not in MIME mode!).
	*/

#if MIME8TO7
	if (bitset(MM_MIME8BIT, MimeMode) &&
	    bitset(EF_HAS8BIT, e->e_flags) &&
	    !bitset(EF_DONT_MIME, e->e_flags) &&
	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
	    hvalue("MIME-Version", e->e_header) == NULL)
	{
		putline("MIME-Version: 1.0", mci);
		if (hvalue("Content-Type", e->e_header) == NULL)
		{
			snprintf(obuf, sizeof obuf,
				"Content-Type: text/plain; charset=%s",
				defcharset(e));
			putline(obuf, mci);
		}
		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
			putline("Content-Transfer-Encoding: 8bit", mci);
	}
#endif /* MIME8TO7 */
}
/*
**  PUT_VANILLA_HEADER -- output a fairly ordinary header
**
**	Parameters:
**		h -- the structure describing this header
**		v -- the value of this header
**		mci -- the connection info for output
**
**	Returns:
**		none.
*/

static void
put_vanilla_header(h, v, mci)
	HDR *h;
	char *v;
	MCI *mci;
{
	register char *nlp;
	register char *obp;
	int putflags;
	char obuf[MAXLINE];

	putflags = PXLF_HEADER;
	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
		putflags |= PXLF_STRIP8BIT;
	(void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
	obp = obuf + strlen(obuf);
	while ((nlp = strchr(v, '\n')) != NULL)
	{
		int l;

		l = nlp - v;
		if (SPACELEFT(obuf, obp) - 1 < (size_t)l)
			l = SPACELEFT(obuf, obp) - 1;

		snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
		putxline(obuf, strlen(obuf), mci, putflags);
		v += l + 1;
		obp = obuf;
		if (*v != ' ' && *v != '\t')
			*obp++ = ' ';
	}
	snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
		(int) sizeof obuf - (obp - obuf) - 1, v);
	putxline(obuf, strlen(obuf), mci, putflags);
}
/*
**  COMMAIZE -- output a header field, making a comma-translated list.
**
**	Parameters:
**		h -- the header field to output.
**		p -- the value to put in it.
**		oldstyle -- TRUE if this is an old style header.
**		mci -- the connection information.
**		e -- the envelope containing the message.
**
**	Returns:
**		none.
**
**	Side Effects:
**		outputs "p" to file "fp".
*/

void
commaize(h, p, oldstyle, mci, e)
	register HDR *h;
	register char *p;
	bool oldstyle;
	register MCI *mci;
	register ENVELOPE *e;
{
	register char *obp;
	int opos;
	int omax;
	bool firstone = TRUE;
	int putflags = PXLF_HEADER;
	char obuf[MAXLINE + 3];

	/*
	**  Output the address list translated by the
	**  mailer and with commas.
	*/

	if (tTd(14, 2))
		dprintf("commaize(%s: %s)\n", h->h_field, p);

	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
		putflags |= PXLF_STRIP8BIT;

	obp = obuf;
	(void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field);
	opos = strlen(h->h_field) + 2;
	if (opos > 202)
		opos = 202;
	obp += opos;
	omax = mci->mci_mailer->m_linelimit - 2;
	if (omax < 0 || omax > 78)
		omax = 78;

	/*
	**  Run through the list of values.
	*/

	while (*p != '\0')
	{
		register char *name;
		register int c;
		char savechar;
		int flags;
		auto int status;

		/*
		**  Find the end of the name.  New style names
		**  end with a comma, old style names end with
		**  a space character.  However, spaces do not
		**  necessarily delimit an old-style name -- at
		**  signs mean keep going.
		*/

		/* find end of name */
		while ((isascii(*p) && isspace(*p)) || *p == ',')
			p++;
		name = p;
		for (;;)
		{
			auto char *oldp;
			char pvpbuf[PSBUFSIZE];

			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
				       sizeof pvpbuf, &oldp, NULL);
			p = oldp;

			/* look to see if we have an at sign */
			while (*p != '\0' && isascii(*p) && isspace(*p))
				p++;

			if (*p != '@')
			{
				p = oldp;
				break;
			}
			p += *p == '@' ? 1 : 2;
			while (*p != '\0' && isascii(*p) && isspace(*p))
				p++;
		}
		/* at the end of one complete name */

		/* strip off trailing white space */
		while (p >= name &&
		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
			p--;
		if (++p == name)
			continue;
		savechar = *p;
		*p = '\0';

		/* translate the name to be relative */
		flags = RF_HEADERADDR|RF_ADDDOMAIN;
		if (bitset(H_FROM, h->h_flags))
			flags |= RF_SENDERADDR;
#if USERDB
		else if (e->e_from.q_mailer != NULL &&
			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
		{
			char *q;

			q = udbsender(name);
			if (q != NULL)
				name = q;
		}
#endif /* USERDB */
		status = EX_OK;
		name = remotename(name, mci->mci_mailer, flags, &status, e);
		if (*name == '\0')
		{
			*p = savechar;
			continue;
		}
		name = denlstring(name, FALSE, TRUE);

		/*
		**  record data progress so DNS timeouts
		**  don't cause DATA timeouts
		*/

		DataProgress = TRUE;

		/* output the name with nice formatting */
		opos += strlen(name);
		if (!firstone)
			opos += 2;
		if (opos > omax && !firstone)
		{
			snprintf(obp, SPACELEFT(obuf, obp), ",\n");
			putxline(obuf, strlen(obuf), mci, putflags);
			obp = obuf;
			(void) strlcpy(obp, "        ", sizeof obp);
			opos = strlen(obp);
			obp += opos;
			opos += strlen(name);
		}
		else if (!firstone)
		{
			snprintf(obp, SPACELEFT(obuf, obp), ", ");
			obp += 2;
		}

		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
			*obp++ = c;
		firstone = FALSE;
		*p = savechar;
	}
	*obp = '\0';
	putxline(obuf, strlen(obuf), mci, putflags);
}
/*
**  COPYHEADER -- copy header list
**
**	This routine is the equivalent of newstr for header lists
**
**	Parameters:
**		header -- list of header structures to copy.
**
**	Returns:
**		a copy of 'header'.
**
**	Side Effects:
**		none.
*/

HDR *
copyheader(header)
	register HDR *header;
{
	register HDR *newhdr;
	HDR *ret;
	register HDR **tail = &ret;

	while (header != NULL)
	{
		newhdr = (HDR *) xalloc(sizeof *newhdr);
		STRUCTCOPY(*header, *newhdr);
		*tail = newhdr;
		tail = &newhdr->h_link;
		header = header->h_link;
	}
	*tail = NULL;

	return ret;
}
/*
**  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
**
**	Run through all of the parameters of a MIME header and
**	possibly truncate and rebalance the parameter according
**	to MaxMimeFieldLength.
**
**	Parameters:
**		string -- the full header
**
**	Returns:
**		TRUE if the header was modified, FALSE otherwise
**
**	Side Effects:
**		string modified in place
*/

static bool
fix_mime_header(string)
	char *string;
{
	bool modified = FALSE;
	char *begin = string;
	char *end;

	if (string == NULL || *string == '\0')
		return FALSE;

	/* Split on each ';' */
	while ((end = find_character(begin, ';')) != NULL)
	{
		char save = *end;
		char *bp;

		*end = '\0';

		/* Shorten individual parameter */
		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
			modified = TRUE;

		/* Collapse the possibly shortened string with rest */
		bp = begin + strlen(begin);
		if (bp != end)
		{
			char *ep = end;

			*end = save;
			end = bp;

			/* copy character by character due to overlap */
			while (*ep != '\0')
				*bp++ = *ep++;
			*bp = '\0';
		}
		else
			*end = save;
		if (*end == '\0')
			break;

		/* Move past ';' */
		begin = end + 1;
	}
	return modified;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -