Пример #1
0
static const char *xml_parse_left_tag(ACL_XML *xml, const char *data)
{
	int   ch;

	if (LEN(xml->curr_node->ltag) == 0) {
		SKIP_SPACE(data);
	}

	while ((ch = *data) != 0) {
		data++;
		if (ch == '>') {
			xml->curr_node->status = ACL_XML_S_LGT;
			xml_parse_check_self_closed(xml);
			if ((xml->curr_node->flag & ACL_XML_F_SELF_CL)
				&& xml->curr_node->last_ch == '/')
			{
				acl_vstring_truncate(xml->curr_node->ltag,
					LEN(xml->curr_node->ltag) - 1);
			}
			break;
		} else if (IS_SPACE(ch)) {
			xml->curr_node->status = ACL_XML_S_ATTR;
			xml->curr_node->last_ch = ch;
			break;
		} else {
			ACL_VSTRING_ADDCH(xml->curr_node->ltag, ch);
			xml->curr_node->last_ch = ch;
		}
	}

	ACL_VSTRING_TERMINATE(xml->curr_node->ltag);
	return (data);
}
Пример #2
0
static void mime_header_line(MIME_NODE *node)
{
	const HEADER_OPTS *header_info;
	size_t len = LEN(node->buffer);
	char *ptr = strrchr(STR(node->buffer), '\n');

	if (ptr) {
		*ptr-- = 0;
		len--;
		if (ptr > STR(node->buffer)) {
			if (*ptr == '\r') {
				*ptr = 0;
				len--;
			}
		}
		if (len == 0)
			return;

		acl_vstring_truncate(node->buffer, len);
	}

	header_info = header_opts_find(STR(node->buffer), node->state->key_buffer);
	if (header_info) {
		if (header_info->type == HDR_CONTENT_TYPE)
			mime_content_type(node, header_info);
		else if (header_info->type == HDR_CONTENT_TRANSFER_ENCODING)
			mime_content_encoding(node, header_info);
		else if (node == node->state->root) {
			/* 说明邮件头 */

			if ((header_info->flags & HDR_OPT_RECIP)
				&& (header_info->flags & HDR_OPT_EXTRACT))
			{
				/* 分析收件人地址: To, Cc, Bcc */
				mail_rcpt(node, header_info);
			} else if ((header_info->flags & HDR_OPT_SENDER)) {
				/* 分析发件人地址: From, Sender,
				*  Replyto, Returnpath
				*/
				mail_from(node, header_info);
			} else if ((header_info->flags & HDR_OPT_SUBJECT)) {
				mail_subject(node, header_info);
			}
		} else if (header_info->type == HDR_CONTENT_DISPOSITION) {
			mime_content_disposition(node, header_info);
		}
	}

	if (node->header_list) {
		HEADER_NV *header = header_split(STR(node->buffer));
		if (header)
			node->header_list->push_back(node->header_list, header);
	}

	ACL_VSTRING_RESET(node->buffer); /* 清空缓冲区 */
	node->last_ch = 0;
	node->last_lf = 0;
}
Пример #3
0
void mime_state_downgrade(MIME_STATE *state, int rec_type,
	const char *text, ssize_t len)
{
	static char hexchars[] = "0123456789ABCDEF";
	const unsigned char *cp;
	MIME_NODE *node = state->curr_node;
	int     ch;

#define CU_CHAR_PTR(x)	((const unsigned char *) (x))
#define QP_ENCODE(buffer, ch) { \
	buffer += '='; \
	buffer += (char) hexchars[(ch >> 4) & 0xff]; \
	buffer += (char) hexchars[ch & 0xf]; \
}

	/*
	* Insert a soft line break when the output reaches a critical length
	* before we reach a hard line break.
	*/
	for (cp = CU_CHAR_PTR(text); cp < CU_CHAR_PTR(text + len); cp++) {
		/* Critical length before hard line break. */
		if (LEN(node->buffer) > 72) {
			node->buffer += '=';
		}
		/* Append the next character. */
		ch = *cp;
		if ((ch < 32 && ch != '\t') || ch == '=' || ch > 126) {
			QP_ENCODE(node->buffer, ch);
		} else {
			ADDCH(node->buffer, ch);
		}
	}

	/*
	* Flush output after a hard line break (i.e. the end of a REC_TYPE_NORM
	* record). Fix trailing whitespace as per the RFC: in the worst case,
	* the output length will grow from 73 characters to 75 characters.
	*/
	if (rec_type == REC_TYPE_NORM) {
		if (LEN(node->buffer) > 0
			&& ((ch = END(node->buffer)[-1]) == ' ' || ch == '\t'))
		{
			acl_vstring_truncate(node->buffer, LEN(node->buffer) - 1);
			QP_ENCODE(node->buffer, ch);
		}
		ACL_VSTRING_TERMINATE(node->buffer);
	}
}
Пример #4
0
const char *str_name_mask_opt(ACL_VSTRING *buf, const char *context,
		const NAME_MASK *table,
		int mask, int flags)
{
	const char *myname = "name_mask";
	const NAME_MASK *np;
	int     len;
	static ACL_VSTRING *my_buf = 0;
	int     delim = (flags & NAME_MASK_COMMA ? ',' :
			(flags & NAME_MASK_PIPE ? '|' : ' '));

	if (buf == 0) {
		if (my_buf == 0)
			my_buf = acl_vstring_alloc(1);
		buf = my_buf;
	}
	ACL_VSTRING_RESET(buf);

	for (np = table; mask != 0; np++) {
		if (np->name == 0) {
			if (flags & NAME_MASK_FATAL) {
				acl_msg_fatal("%s: unknown %s bit in mask: 0x%x",
						myname, context, mask);
			} else if (flags & NAME_MASK_RETURN) {
				acl_msg_warn("%s: unknown %s bit in mask: 0x%x",
						myname, context, mask);
				return (0);
			} else if (flags & NAME_MASK_NUMBER) {
				acl_vstring_sprintf_append(buf, "0x%x%c", mask, delim);
			}
			break;
		}
		if (mask & np->mask) {
			mask &= ~np->mask;
			acl_vstring_sprintf_append(buf, "%s%c", np->name, delim);
		}
	}
	if ((len = (int) ACL_VSTRING_LEN(buf)) > 0)
		acl_vstring_truncate(buf, len - 1);
	ACL_VSTRING_TERMINATE(buf);

	return (STR(buf));
}
Пример #5
0
static void strip_address(ACL_VSTRING *vp, ssize_t start, TOK822 *addr)
{
	ACL_VSTRING *tmp;

	/*
	 * Emit plain <address>. Discard any comments or phrases.
	 */
	ACL_VSTRING_TERMINATE(vp);
	acl_msg_warn("stripping too many comments from address: %.100s...",
			acl_vstring_str(vp) + start);
	//acl_printable(vstring_str(vp) + start, '?')); //zsx
	acl_vstring_truncate(vp, start);
	ACL_VSTRING_ADDCH(vp, '<');
	if (addr) {
		tmp = acl_vstring_alloc(100);
		tok822_internalize(tmp, addr, TOK822_STR_TERM);
		quote_822_local_flags(vp, acl_vstring_str(tmp),
			QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND);
		acl_vstring_free(tmp);
	}
	ACL_VSTRING_ADDCH(vp, '>');
}
Пример #6
0
ssize_t header_token(HEADER_TOKEN *token, ssize_t token_len,
	ACL_VSTRING *token_buffer, const char **ptr,
	const char *user_specials, int user_terminator)
{
	ssize_t comment_level;
	const unsigned char *cp;
	ssize_t len;
	int     ch;
	ssize_t tok_count;
	ssize_t n;

	/*
	 * Initialize.
	 */
	ACL_VSTRING_RESET(token_buffer);
	cp = CU_CHAR_PTR(*ptr);
	tok_count = 0;
	if (user_specials == 0)
		user_specials = LEX_822_SPECIALS;

	/*
	 * Main parsing loop.
	 * 
	 * XXX What was the reason to continue parsing when user_terminator is
	 * specified? Perhaps this was needed at some intermediate stage of
	 * development?
	 */
	while ((ch = *cp) != 0 && (user_terminator != 0 || tok_count < token_len)) {
		cp++;

		/*
		 * Skip RFC 822 linear white space.
		 */
		if (IS_SPACE_TAB_CR_LF(ch))
			continue;

		/*
		 * Terminator.
		 */
		if (ch == user_terminator)
			break;

		/*
		 * Skip RFC 822 comment.
		 */
		if (ch == '(') {
			comment_level = 1;
			while ((ch = *cp) != 0) {
				cp++;
				if (ch == '(') {  /* comments can nest! */
					comment_level++;
				} else if (ch == ')') {
					if (--comment_level == 0)
						break;
				} else if (ch == '\\') {
					if ((ch = *cp) == 0)
						break;
					cp++;
				}
			}
			continue;
		}

		/*
		 * Copy quoted text according to RFC 822.
		 */
		if (ch == '"') {
			if (tok_count < token_len) {
				token[tok_count].u.offset = LEN(token_buffer);
				token[tok_count].type = HEADER_TOK_QSTRING;
			}
			while ((ch = *cp) != 0) {
				cp++;
				if (ch == '"')
					break;
				if (ch == '\n') {		/* unfold */
					if (tok_count < token_len) {
						len = LEN(token_buffer);
						while (len > 0 && IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1]))
							len--;
						if (len < (ssize_t) LEN(token_buffer))
							acl_vstring_truncate(token_buffer, len);
					}
					continue;
				}
				if (ch == '\\') {
					if (tok_count < token_len)
						ACL_VSTRING_ADDCH(token_buffer, ch);

					if (*cp == 0)
						break;
					ch = *cp;
					cp++;
				}
				if (tok_count < token_len)
					ACL_VSTRING_ADDCH(token_buffer, ch);
			}
			if (tok_count < token_len) {
				ACL_VSTRING_ADDCH(token_buffer, 0);
				tok_count++;
			}
			continue;
		}

		/*
		 * Control, or special.
		 */
		if (strchr(user_specials, ch) || ACL_ISCNTRL(ch)) {
			if (tok_count < token_len) {
				token[tok_count].u.offset = LEN(token_buffer);
				token[tok_count].type = ch;
				ACL_VSTRING_ADDCH(token_buffer, ch);
				ACL_VSTRING_ADDCH(token_buffer, 0);
				tok_count++;
			}
			continue;
		}

		/*
		 * Token.
		 */
		else {
			if (tok_count < token_len) {
				token[tok_count].u.offset = LEN(token_buffer);
				token[tok_count].type = HEADER_TOK_TOKEN;
				ACL_VSTRING_ADDCH(token_buffer, ch);
			}
			while ((ch = *cp) != 0 && !IS_SPACE_TAB_CR_LF(ch)
				&& !ACL_ISCNTRL(ch) && !strchr(user_specials, ch)) {
					cp++;
					if (tok_count < token_len)
						ACL_VSTRING_ADDCH(token_buffer, ch);
				}
				if (tok_count < token_len) {
					ACL_VSTRING_ADDCH(token_buffer, 0);
					tok_count++;
				}
				continue;
		}
	}

	/*
	 * Ignore a zero-length item after the last terminator.
	 */
	if (tok_count == 0 && ch == 0)
		return (-1);

	/*
	 * Finalize. Fill in the string pointer array, now that the token buffer
	 * is no longer dynamically reallocated as it grows.
	 */
	*ptr = (const char *) cp;
	for (n = 0; n < tok_count; n++)
		token[n].u.value = STR(token_buffer) + token[n].u.offset;

	//if (acl_msg_verbose)
	//	acl_msg_info("header_token: %s %s %s",
	//		tok_count > 0 ? token[0].u.value : "",
	//		tok_count > 1 ? token[1].u.value : "",
	//		tok_count > 2 ? token[2].u.value : "");

	return (tok_count);
}