Beispiel #1
0
static void acl_xml_node_reset(ACL_XML_NODE *node)
{
    ACL_VSTRING_RESET(node->ltag);
    ACL_VSTRING_RESET(node->rtag);
    ACL_VSTRING_RESET(node->text);
    ACL_VSTRING_TERMINATE(node->ltag);
    ACL_VSTRING_TERMINATE(node->rtag);
    ACL_VSTRING_TERMINATE(node->text);

    node->id = NULL;

    if (node->attr_list)
        acl_array_clean(node->attr_list,
                        (void (*)(void*)) acl_xml_attr_free);
    node->parent = NULL;
    acl_ring_init(&node->children);
    node->depth = 0;

    acl_ring_init(&node->node);
    node->curr_attr = NULL;
    node->quote = 0;
    node->last_ch = 0;
    node->nlt = 0;
    node->meta[0] = 0;
    node->flag = 0;
    node->status = ACL_XML_S_NXT;
}
Beispiel #2
0
static void __hdr_reset(HTTP_HDR_REQ *hh, int clear_cookies)
{
	hh->port = 80;
	hh->method[0] = 0;
	hh->host[0] = 0;
	hh->flag = 0;

	if (hh->url_part) {
		ACL_VSTRING_RESET(hh->url_part);
		ACL_VSTRING_TERMINATE(hh->url_part);
	}

	if (hh->url_path) {
		ACL_VSTRING_RESET(hh->url_path);
		ACL_VSTRING_TERMINATE(hh->url_path);
	}

	if (hh->url_params) {
		ACL_VSTRING_RESET(hh->url_params);
		ACL_VSTRING_TERMINATE(hh->url_params);
	}

	if (hh->file_path) {
		ACL_VSTRING_RESET(hh->file_path);
		ACL_VSTRING_TERMINATE(hh->file_path);
	}

	if (hh->params_table)
		acl_htable_reset(hh->params_table, __request_args_free_fn);

	if (clear_cookies && hh->cookies_table)
		acl_htable_reset(hh->cookies_table, __cookies_args_free_fn);
}
Beispiel #3
0
static void test_buffer_gets(void)
{
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	const ACL_VSTRING *pbuf;
	const char *src;
	size_t   i, n;
	unsigned char ch = (unsigned char) -1;

	for (i = 0; i < sizeof(string_tab) / sizeof(char*); i++) {
		printf("%s", string_tab[i]);
	}

	printf("------------------------------------------------------------\r\n");

	for (i = 0; i < sizeof(string_tab) / sizeof(char*); i++) {
		src = string_tab[i];
		n = strlen(src);
		while (1) {
			const char *psrc_saved = src;
			pbuf = acl_buffer_gets_nonl(buf, &src, n);
			if (pbuf) {
				printf("%s\n", STR(pbuf));
				ACL_VSTRING_RESET(buf);
				n -= src - psrc_saved;
				if (n == 0)
					break;
			} else
				break;
		}
	}

	printf("------------------------------------------------------------\r\n");

	for (i = 0; i < sizeof(string_tab) / sizeof(char*); i++) {
		src = string_tab[i];
		n = strlen(src);
		while (1) {
			const char *psrc_saved = src;
			pbuf = acl_buffer_gets(buf, &src, n);
			if (pbuf) {
				printf("%s", STR(pbuf));
				ACL_VSTRING_RESET(buf);
				n -= src - psrc_saved;
				if (n == 0)
					break;
			} else
				break;
		}
	}

	acl_vstring_free(buf);
	printf(">>>>>>>>>max ch: %d\n", ch);
}
Beispiel #4
0
ACL_VSTRING *acl_hex_decode(ACL_VSTRING *result, const char *in, int len)
{
	const unsigned char *cp;
	int     count;
	unsigned int hex;
	unsigned int bin;

	ACL_VSTRING_RESET(result);
	for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) {
		if (count < 2)
			return (0);
		hex = cp[0];
		if (hex >= '0' && hex <= '9')
			bin = (hex - '0') << 4;
		else if (hex >= 'A' && hex <= 'F')
			bin = (hex - 'A' + 10) << 4;
		else if (hex >= 'a' && hex <= 'f')
			bin = (hex - 'a' + 10) << 4;
		else
			return (0);
		hex = cp[1];
		if (hex >= '0' && hex <= '9')
			bin |= (hex - '0') ;
		else if (hex >= 'A' && hex <= 'F')
			bin |= (hex - 'A' + 10) ;
		else if (hex >= 'a' && hex <= 'f')
			bin |= (hex - 'a' + 10) ;
		else
			return (0);
		ACL_VSTRING_ADDCH(result, bin);
	}
	ACL_VSTRING_TERMINATE(result);
	return (result);
}
Beispiel #5
0
void acl_token_name(const ACL_TOKEN *token, ACL_VSTRING *buf)
{
	int   i, n;
	char *ptr, *pend, ch;
	const ACL_TOKEN *token_iter;

	ACL_VSTRING_RESET(buf);
	token_iter = token;
	while (token_iter && token_iter->parent != NULL) {
		ACL_VSTRING_ADDCH(buf, token_iter->ch);
		token_iter = token_iter->parent;
	}

	ACL_VSTRING_TERMINATE(buf);

	pend = acl_vstring_end(buf) - 1;
	ptr = STR(buf);
	i = 0;
	n = (int) (pend - ptr + 1) / 2;
	while (i < n) {
		ch = *ptr;
		*ptr = *pend;
		*pend = ch;
		i++;
		ptr++;
		pend--;
	}
}
Beispiel #6
0
static void incr_string(ACL_VSTRING *vp, int len, const char* s, int debug)
{
	int   i;

	printf("max: %ld, len: %ld, cnt: %ld\r\n", (long) vp->maxlen,
		vp->vbuf.len, vp->vbuf.cnt);

	for (i = 0; i < len; i++)
		ACL_VSTRING_ADDCH(vp, 'x');

	if (s && *s)
		acl_vstring_sprintf_append(vp, "%s", s);
	else
		ACL_VSTRING_TERMINATE(vp);

	if (debug)
		printf("[%s]\r\n", acl_vstring_str(vp));

	printf("strlen: %ld, ACL_VSTRING_LEN: %ld, max: %ld\r\n",
		(long) strlen(acl_vstring_str(vp)),
		(long) ACL_VSTRING_LEN(vp), (long) vp->maxlen);

	printf("Enter any key to continue ...\r\n\r\n");
	getchar();

	ACL_VSTRING_RESET(vp);
	ACL_VSTRING_TERMINATE(vp);
}
Beispiel #7
0
static void token_tree_test(const char *tokens, const char *test_tab[])
{
	ACL_TOKEN *token_tree;
	ACL_TOKEN *token;
	const char *ptr, *psaved;
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	int   i;

	token_tree = acl_token_tree_create(tokens);
	acl_token_tree_print(token_tree);

	for (i = 0; test_tab[i] != NULL; i++) {
		ptr = psaved = test_tab[i];
		token = acl_token_tree_match(token_tree, &ptr, ";", NULL);
		if (token) {
			ACL_VSTRING_RESET(buf);
			acl_token_name(token, buf);
			printf("match %s %s, token's name: %s\n", psaved,
				(token->flag & ACL_TOKEN_F_DENY) ? "DENY"
				: (token->flag & ACL_TOKEN_F_PASS ? "PASS" : "NONE"),
				STR(buf));
		} else
			printf("match %s none\n", psaved);
	}

	acl_token_tree_destroy(token_tree);
	acl_vstring_free(buf);
}
Beispiel #8
0
static int chunked_trailer(ACL_ASTREAM *astream, HTTP_CHAT_CTX *ctx)
{
	HTTP_BODY_NOTIFY notify = ctx->notify.body_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	char *data;
	int   dlen;

	sbuf = acl_aio_gets_peek(astream);
	if (sbuf == NULL)
		return (0);

	data = acl_vstring_str(sbuf);
	dlen = (int) ACL_VSTRING_LEN(sbuf);
	ACL_VSTRING_RESET(sbuf);

	ctx->body_len += dlen;

	if (strcmp(data, "\r\n") == 0 || strcmp(data, "\n") == 0) {
		DISABLE_READ(astream);
		if ((dlen = notify(HTTP_CHAT_OK, data, dlen, arg)) < 0)
			return (-1);
		return (1);
	}
	if (notify(HTTP_CHAT_CHUNK_TRAILER, data, dlen, arg) < 0)
		return (-1);
	return (0);
}
Beispiel #9
0
int     tls_scache_lookup(TLS_SCACHE *cp, char *cache_id, ACL_VSTRING *session)
{
    char *hex_data;
    size_t size;

    /*
     * Logging.
     */
    if (cp->verbose)
	acl_msg_info("lookup %s session id=%s", cp->cache_label, cache_id);

    /*
     * Initialize. Don't leak data.
     */
    if (session)
	ACL_VSTRING_RESET(session);

    /*
     * Search the cache database.
     */
    if ((DICT_GET(cp->db, cache_id, strlen(cache_id), &hex_data, &size)) == 0)
	return (0);

    /*
     * Decode entry and delete if expired or malformed.
     */
    if (tls_scache_decode(cp, cache_id, hex_data, (int) strlen(hex_data), session) == 0) {
	tls_scache_delete(cp, cache_id);
	acl_myfree(hex_data);
	return (0);
    } else {
	acl_myfree(hex_data);
	return (1);
    }
}
Beispiel #10
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;
}
Beispiel #11
0
void charset_conv::update_finish(acl::string* out)
{
#ifdef  HAVE_H_ICONV
	if (m_pInBuf && LEN(m_pInBuf) > 0 && m_addInvalid)
	{
		out->append(STR(m_pInBuf), LEN(m_pInBuf));
		ACL_VSTRING_RESET(m_pInBuf);
	}
#endif
}
Beispiel #12
0
static int chunked_data(ACL_ASTREAM *astream, HTTP_CHAT_CTX *ctx)
{
	HTTP_BODY_NOTIFY notify = ctx->notify.body_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	char *data;
	int   dlen, ret;

	if (ctx->chunked) {
		ret = (int) HTTP_LEN_ROUND(ctx);
		sbuf = acl_aio_readn_peek(astream, ret);
	} else if (ctx->hdr->content_length <= 0) {
		sbuf = acl_aio_read_peek(astream);
	} else {
		ret = (int) HTTP_LEN_ROUND(ctx);
		sbuf = acl_aio_readn_peek(astream, ret);
	}

	if (sbuf == NULL) {
		return (0);
	}

	data = acl_vstring_str(sbuf);
	dlen = (int) ACL_VSTRING_LEN(sbuf);
	ACL_VSTRING_RESET(sbuf);

	ctx->body_len += dlen;
	ctx->read_cnt += dlen;

	if (ctx->chunk_len > 0 && ctx->read_cnt >= ctx->chunk_len) {
		if (!ctx->chunked) {
			/* xxx: 禁止连续读 */
			DISABLE_READ(astream);
			if (notify(HTTP_CHAT_OK, data, dlen, arg) < 0)
				return (-1);
			return (1);
		}

		if (notify(HTTP_CHAT_DATA, data, dlen, arg) < 0)
			return (-1);

		/* 设置标志位开始读取块数据体的分隔行数据 */
		ctx->status = CHAT_S_CHUNK_SEP;
		return (0);
	}

	if (notify(HTTP_CHAT_DATA, data, dlen, arg) < 0)
		return (-1);
	return (0);
}
Beispiel #13
0
ACL_VSTRING *acl_hex_encode(ACL_VSTRING *result, const char *in, int len)
{
	const unsigned char *cp;
	int     ch;
	int     count;

	ACL_VSTRING_RESET(result);
	for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) {
		ch = *cp;
		ACL_VSTRING_ADDCH(result, acl_hex_chars[(ch >> 4) & 0xf]);
		ACL_VSTRING_ADDCH(result, acl_hex_chars[ch & 0xf]);
	}
	ACL_VSTRING_TERMINATE(result);
	return (result);
}
Beispiel #14
0
static int hdr_can_read(ACL_ASTREAM *astream, void *context)
{
	HTTP_CHAT_CTX *ctx = (HTTP_CHAT_CTX *) context;
	HTTP_HDR *hdr = ctx->hdr;
	HTTP_HDR_NOTIFY notify = ctx->notify.hdr_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	char *data;
	int   dlen;
	int   ret;

	while (1) {
		if ((ret = acl_aio_can_read(astream)) == ACL_VSTREAM_EOF) {
			notify(HTTP_CHAT_ERR_IO, arg);
			return (-1);
		} else if (ret == 0) {
			break;
		}
		sbuf = acl_aio_gets_nonl_peek(astream);
		if (sbuf == NULL) {
			break;
		}
		data = acl_vstring_str(sbuf);
		dlen = (int) ACL_VSTRING_LEN(sbuf);
		ACL_VSTRING_RESET(sbuf);

		ret = hdr_ready(hdr, data, dlen);
		switch (ret) {
		case HTTP_CHAT_CONTINUE:
			break;
		case HTTP_CHAT_OK:
			DISABLE_READ(astream);
			if (notify(ret, arg) < 0) {
				return (0);
			}
			return (0);
		default:
			DISABLE_READ(astream);
			(void) notify(ret, arg);
			return (0);
		}
	}

	acl_aio_enable_read(astream, hdr_can_read, ctx);
	return (0);
}
Beispiel #15
0
ACL_VSTRING *escape(ACL_VSTRING *result, const char *data, ssize_t len)
{
	int     ch;

	ACL_VSTRING_RESET(result);
	while (len-- > 0) {
		ch = *UCHAR(data++);
		if (ACL_ISASCII(ch)) {
			if (ACL_ISPRINT(ch)) {
				if (ch == '\\')
					ACL_VSTRING_ADDCH(result, ch);
				ACL_VSTRING_ADDCH(result, ch);
				continue;
			} else if (ch == '\a') {		/* \a -> audible bell */
				acl_vstring_strcat(result, "\\a");
				continue;
			} else if (ch == '\b') {		/* \b -> backspace */
				acl_vstring_strcat(result, "\\b");
				continue;
			} else if (ch == '\f') {		/* \f -> formfeed */
				acl_vstring_strcat(result, "\\f");
				continue;
			} else if (ch == '\n') {		/* \n -> newline */
				acl_vstring_strcat(result, "\\n");
				continue;
			} else if (ch == '\r') {		/* \r -> carriagereturn */
				acl_vstring_strcat(result, "\\r");
				continue;
			} else if (ch == '\t') {		/* \t -> horizontal tab */
				acl_vstring_strcat(result, "\\t");
				continue;
			} else if (ch == '\v') {		/* \v -> vertical tab */
				acl_vstring_strcat(result, "\\v");
				continue;
			}
		}
		if (ACL_ISDIGIT(*UCHAR(data)))
			acl_vstring_sprintf_append(result, "\\%03d", ch);
		else
			acl_vstring_sprintf_append(result, "\\%d", ch);
	}
	ACL_VSTRING_TERMINATE(result);
	return (result);
}
Beispiel #16
0
ACL_VSTRING *tok822_internalize(ACL_VSTRING *vp, TOK822 *tree, int flags)
{
	TOK822 *tp;

	if (flags & TOK822_STR_WIPE)
		ACL_VSTRING_RESET(vp);

	for (tp = tree; tp; tp = tp->next) {
		switch (tp->type) {
		case ',':
			ACL_VSTRING_ADDCH(vp, tp->type);
			if (flags & TOK822_STR_LINE) {
				ACL_VSTRING_ADDCH(vp, '\n');
				continue;
			}
			break;
		case TOK822_ADDR:
			tok822_internalize(vp, tp->head, TOK822_STR_NONE);
			break;
		case TOK822_COMMENT:
		case TOK822_ATOM:
		case TOK822_QSTRING:
			acl_vstring_strcat(vp, acl_vstring_str(tp->vstr));
			break;
		case TOK822_DOMLIT:
			ACL_VSTRING_ADDCH(vp, '[');
			acl_vstring_strcat(vp, acl_vstring_str(tp->vstr));
			ACL_VSTRING_ADDCH(vp, ']');
			break;
		case TOK822_STARTGRP:
			ACL_VSTRING_ADDCH(vp, ':');
			break;
		default:
			if (tp->type >= TOK822_MINTOK)
				acl_msg_panic("tok822_internalize: unknown operator %d", tp->type);
			ACL_VSTRING_ADDCH(vp, tp->type);
		}
		if (tok822_append_space(tp))
			ACL_VSTRING_ADDCH(vp, ' ');
	}
	if (flags & TOK822_STR_TERM)
		ACL_VSTRING_TERMINATE(vp);
	return (vp);
}
Beispiel #17
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));
}
Beispiel #18
0
ACL_TOKEN *acl_token_tree_create2(const char *s, const char *sep)
{
	const char *myname = "acl_token_tree_create";
	ACL_ARGV *argv;
	ACL_ITER  iter;
	unsigned int   flag;
	ACL_TOKEN *token_tree;
	const ACL_TOKEN *token;
	ACL_VSTRING *buf;

	token_tree = acl_token_new();
	if (s == NULL || *s == 0)
		return (token_tree);

	buf = acl_vstring_alloc(256);
	argv = acl_argv_split(s, sep);
	acl_foreach(iter, argv) {
		char *word = (char*) iter.ptr;
		char *ptr = strchr(word, '|');

		flag = ACL_TOKEN_F_STOP;
		if (ptr) {
			*ptr++ = 0;
			if (*ptr == 'D' || *ptr == 'd')
				flag |= ACL_TOKEN_F_DENY;
			if (*ptr == 'P' || *ptr == 'p')
				flag |= ACL_TOKEN_F_PASS;
		}
		token = acl_token_tree_add(token_tree, word, flag, NULL);
		if (token == NULL) {
			acl_msg_info("%s(%d): word(%s) discard",
				myname, __LINE__, word);
		} else {
			ACL_VSTRING_RESET(buf);
			acl_token_name(token, buf);
			/*
			acl_msg_info("%s(%d): add word(%s) ok, token's name(%s)",
				myname, __LINE__, word, STR(buf));
			*/
		}
	}
Beispiel #19
0
const char *acl_token_name1(const ACL_TOKEN *token)
{
	static acl_pthread_key_t buf_key = (acl_pthread_key_t) ACL_TLS_OUT_OF_INDEXES;
	ACL_VSTRING *buf;
	static ACL_VSTRING *__buf_unsafe = NULL;

	buf = (ACL_VSTRING*) acl_pthread_tls_get(&buf_key);
	if (buf == NULL) {
		if (buf_key == (acl_pthread_key_t) ACL_TLS_OUT_OF_INDEXES) {
			if (__buf_unsafe == NULL)
				__buf_unsafe = acl_vstring_alloc(256);
			buf = __buf_unsafe;
		} else {
			buf = acl_vstring_alloc(256);
			acl_pthread_tls_set(buf_key, buf,
				(void (*)(void*)) acl_vstring_free);
		}
	}
	ACL_VSTRING_RESET(buf);
	acl_token_name(token, buf);
	return (STR(buf));
}
Beispiel #20
0
static int chunked_data_endl(ACL_ASTREAM *astream, HTTP_CHAT_CTX *ctx)
{
	HTTP_BODY_NOTIFY notify = ctx->notify.body_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	char *data;
	int   dlen;

	sbuf = acl_aio_gets_peek(astream);
	if (sbuf == NULL)
		return (0);

	data = acl_vstring_str(sbuf);
	dlen = (int) ACL_VSTRING_LEN(sbuf);
	ACL_VSTRING_RESET(sbuf);

	ctx->body_len += dlen;

	if (notify(HTTP_CHAT_CHUNK_DATA_ENDL, data, dlen, arg) < 0)
		return (-1);
	ctx->status = CHAT_S_CHUNK_HDR;
	return (0);
}
Beispiel #21
0
int     mac_expand(ACL_VSTRING *result, const char *pattern, int flags,
		           const char *filter,
		           MAC_EXP_LOOKUP_FN lookup, char *context)
{
    MAC_EXP mc;
    int     status;

    /*
     * Bundle up the request and do the substitutions.
     */
    mc.result = result;
    mc.flags = flags;
    mc.filter = filter;
    mc.lookup = lookup;
    mc.context = context;
    mc.status = 0;
    mc.level = 0;
    ACL_VSTRING_RESET(result);
    status = mac_parse(pattern, mac_expand_callback, (char *) &mc);
    ACL_VSTRING_TERMINATE(result);

    return (status);
}
Beispiel #22
0
static int hdr_gets_ready(ACL_ASTREAM *astream, void *context,
	char *data, int dlen)
{
	HTTP_CHAT_CTX *ctx = (HTTP_CHAT_CTX *) context;
	HTTP_HDR *hdr = ctx->hdr;
	HTTP_HDR_NOTIFY notify = ctx->notify.hdr_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	int   ret;

	while (1) {
		ret = hdr_ready(hdr, data, dlen);
		switch (ret) {
		case HTTP_CHAT_CONTINUE:
			break;
		case HTTP_CHAT_OK:
			acl_aio_del_read_hook(astream, hdr_gets_ready, context);
			if (notify(ret, arg) < 0) {
				return (-1);
			}
			return (0);
		default:
			acl_aio_del_read_hook(astream, hdr_gets_ready, context);
			(void) notify(ret, arg);
			return (-1);
		}
		sbuf = acl_aio_gets_nonl_peek(astream);
		if (sbuf == NULL)
			break;
		data = acl_vstring_str(sbuf);
		dlen = (int) ACL_VSTRING_LEN(sbuf);
		ACL_VSTRING_RESET(sbuf);
	}

	acl_aio_gets_nonl(astream);
	return (0);
}
Beispiel #23
0
static int chunked_hdr(ACL_ASTREAM *astream, HTTP_CHAT_CTX *ctx)
{
	HTTP_BODY_NOTIFY notify = ctx->notify.body_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf;
	char *data, *ptr;
	int   dlen;

	sbuf = acl_aio_gets_peek(astream);
	if (sbuf == NULL)
		return (0);

	data = acl_vstring_str(sbuf);
	dlen = (int) ACL_VSTRING_LEN(sbuf);
	ACL_VSTRING_RESET(sbuf);

	ctx->body_len += dlen;
	ctx->read_cnt = 0;

	ptr = strchr(data, ' ');
	if (ptr)
		*ptr = 0;
	ctx->chunk_len = strtoul(data, NULL, 16);
	if (ptr)
		*ptr = ' ';

	if (notify(HTTP_CHAT_CHUNK_HDR, data, dlen, arg) < 0)
		return (-1);

	if (ctx->chunk_len == 0) {
		ctx->status = CHAT_S_CHUNK_TAL;
		return (0);
	}

	ctx->status = CHAT_S_CHUNK_DAT;
	return (0);
}
Beispiel #24
0
ACL_VSTRING *unescape(ACL_VSTRING *result, const char *data)
{
	int     ch;
	int     oval;
	int     i;

#define UCHAR(cp)	((const unsigned char *) (cp))
#define ISOCTAL(ch)	(ACL_ISDIGIT(ch) && (ch) != '8' && (ch) != '9')

	ACL_VSTRING_RESET(result);

	while ((ch = *UCHAR(data++)) != 0) {
		if (ch == '\\') {
			if ((ch = *UCHAR(data++)) == 0)
				break;
			switch (ch) {
			case 'a':				/* \a -> audible bell */
				ch = '\a';
				break;
			case 'b':				/* \b -> backspace */
				ch = '\b';
				break;
			case 'f':				/* \f -> formfeed */
				ch = '\f';
				break;
			case 'n':				/* \n -> newline */
				ch = '\n';
				break;
			case 'r':				/* \r -> carriagereturn */
				ch = '\r';
				break;
			case 't':				/* \t -> horizontal tab */
				ch = '\t';
				break;
			case 'v':				/* \v -> vertical tab */
				ch = '\v';
				break;
			case '0':				/* \nnn -> ASCII value */
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
				for (oval = ch - '0', i = 0;
					i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch);
					i++, data++) {
					oval = (oval << 3) | (ch - '0');
				}
				ch = oval;
				break;
			default:				/* \any -> any */
				break;
			}
		}
		ACL_VSTRING_ADDCH(result, ch);
	}
	ACL_VSTRING_TERMINATE(result);
	return (result);
}
Beispiel #25
0
ACL_VSTRING *tok822_externalize(ACL_VSTRING *vp, TOK822 *tree, int flags)
{
	ACL_VSTRING *tmp;
	TOK822 *tp;
	ssize_t start = 0;
	TOK822 *addr = 0;
	ssize_t addr_len = 0;

	/*
	 * Guard against a Sendmail buffer overflow (CERT advisory CA-2003-07).
	 * The problem was that Sendmail could store too much non-address text
	 * (comments, phrases, etc.) into a static 256-byte buffer.
	 * 
	 * When the buffer fills up, fixed Sendmail versions remove comments etc.
	 * and reduce the information to just <$g>, which expands to <address>.
	 * No change is made when an address expression (text separated by
	 * commas) contains no address. This fix reportedly also protects
	 * Sendmail systems that are still vulnerable to this problem.
	 * 
	 * Postfix takes the same approach, grudgingly. To avoid unnecessary damage,
	 * Postfix removes comments etc. only when the amount of non-address text
	 * in an address expression (text separated by commas) exceeds 250 bytes.
	 * 
	 * With Sendmail, the address part of an address expression is the
	 * right-most <> instance in that expression. If an address expression
	 * contains no <>, then Postfix guarantees that it contains at most one
	 * non-comment string; that string is the address part of the address
	 * expression, so there is no ambiguity.
	 * 
	 * Finally, we note that stress testing shows that other code in Sendmail
	 * 8.12.8 bluntly truncates ``text <address>'' to 256 bytes even when
	 * this means chopping the <address> somewhere in the middle. This is a
	 * loss of control that we're not entirely comfortable with. However,
	 * unbalanced quotes and dangling backslash do not seem to influence the
	 * way that Sendmail parses headers, so this is not an urgent problem.
	 */
#define MAX_NONADDR_LENGTH 250

#define RESET_NONADDR_LENGTH { \
	start = ACL_VSTRING_LEN(vp); \
	addr = 0; \
	addr_len = 0; \
}

#define ENFORCE_NONADDR_LENGTH do { \
	if (addr && (ssize_t) ACL_VSTRING_LEN(vp) - addr_len > start + MAX_NONADDR_LENGTH) \
		strip_address(vp, start, addr->head); \
} while(0)

	if (flags & TOK822_STR_WIPE)
		ACL_VSTRING_RESET(vp);

	if (flags & TOK822_STR_TRNC)
		RESET_NONADDR_LENGTH;

	for (tp = tree; tp; tp = tp->next) {
		switch (tp->type) {
		case ',':
			if (flags & TOK822_STR_TRNC)
				ENFORCE_NONADDR_LENGTH;
			ACL_VSTRING_ADDCH(vp, tp->type);
			ACL_VSTRING_ADDCH(vp, (flags & TOK822_STR_LINE) ? '\n' : ' ');
			if (flags & TOK822_STR_TRNC)
				RESET_NONADDR_LENGTH;
			continue;

			/*
			 * XXX In order to correctly externalize an address, it is not
			 * sufficient to quote individual atoms. There are higher-level
			 * rules that say when an address localpart needs to be quoted.
			 * We wing it with the quote_822_local() routine, which ignores
			 * the issue of atoms in the domain part that would need quoting.
			 */
		case TOK822_ADDR:
			addr = tp;
			tmp = acl_vstring_alloc(100);
			tok822_internalize(tmp, tp->head, TOK822_STR_TERM);
			addr_len = ACL_VSTRING_LEN(vp);
			quote_822_local_flags(vp, acl_vstring_str(tmp),
				QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND);
			addr_len = ACL_VSTRING_LEN(vp) - addr_len;
			acl_vstring_free(tmp);
			break;
		case TOK822_ATOM:
		case TOK822_COMMENT:
			acl_vstring_strcat(vp, acl_vstring_str(tp->vstr));
			break;
		case TOK822_QSTRING:
			ACL_VSTRING_ADDCH(vp, '"');
			tok822_copy_quoted(vp, acl_vstring_str(tp->vstr), "\"\\\r\n");
			ACL_VSTRING_ADDCH(vp, '"');
			break;
		case TOK822_DOMLIT:
			ACL_VSTRING_ADDCH(vp, '[');
			tok822_copy_quoted(vp, acl_vstring_str(tp->vstr), "\\\r\n");
			ACL_VSTRING_ADDCH(vp, ']');
			break;
		case TOK822_STARTGRP:
			ACL_VSTRING_ADDCH(vp, ':');
			break;
		case '<':
			if (tp->next && tp->next->type == '>') {
				addr = tp;
				addr_len = 0;
			}
			ACL_VSTRING_ADDCH(vp, '<');
			break;
		default:
			if (tp->type >= TOK822_MINTOK)
				acl_msg_panic("tok822_externalize: unknown operator %d", tp->type);
			ACL_VSTRING_ADDCH(vp, tp->type);
		}
		if (tok822_append_space(tp))
			ACL_VSTRING_ADDCH(vp, ' ');
	}
	if (flags & TOK822_STR_TRNC)
		ENFORCE_NONADDR_LENGTH;

	if (flags & TOK822_STR_TERM)
		ACL_VSTRING_TERMINATE(vp);
	return (vp);
}
Beispiel #26
0
const char *acl_getenv_list(void)
{
	const char *myname = "acl_getenv_list";
#ifdef ACL_WINDOWS
	static acl_pthread_key_t buf_key = ACL_TLS_OUT_OF_INDEXES;
	ACL_VSTRING *buf;
	LPTSTR lpszVariable;
	LPVOID lpvEnv;
	int   i = 0, ch = 0;

	buf = (ACL_VSTRING*) acl_pthread_tls_get(&buf_key);
	if (buf == NULL) {
		if (buf_key == ACL_TLS_OUT_OF_INDEXES) {
			acl_msg_error("%s(%d): acl_pthread_tls_get error(%s)",
				myname, __LINE__, acl_last_serror());
			return (NULL);
		}
		buf = acl_vstring_alloc(256);
		acl_pthread_tls_set(buf_key, buf, (void (*)(void*)) free_vstring);
	} else
		ACL_VSTRING_RESET(buf);

	lpvEnv = GetEnvironmentStrings();
	for (lpszVariable = (LPTSTR) lpvEnv; *lpszVariable; lpszVariable++) {
		if (i++ > 0)
			acl_vstring_strcat(buf, ", ");
		while (*lpszVariable) {
			ACL_VSTRING_ADDCH(buf, *lpszVariable++);
			ch = *lpszVariable;
		}
	}
	FreeEnvironmentStrings(lpvEnv);
	ACL_VSTRING_TERMINATE(buf);
	return (acl_vstring_str(buf));
#else
	static acl_pthread_key_t buf_key = (acl_pthread_key_t) ACL_TLS_OUT_OF_INDEXES;
	ACL_VSTRING *buf;
	extern char **environ;
	char **pptr = environ;
	int   i = 0;

	buf = (ACL_VSTRING*) acl_pthread_tls_get(&buf_key);
	if (buf == NULL) {
		if (buf_key == (acl_pthread_key_t) ACL_TLS_OUT_OF_INDEXES) {
			acl_msg_error("%s(%d): acl_pthread_tls_get error(%s)",
				myname, __LINE__, acl_last_serror());
			return (NULL);
		}
		buf = acl_vstring_alloc(256);
		acl_pthread_tls_set(buf_key, buf, (void (*)(void*)) free_vstring);
	} else
		ACL_VSTRING_RESET(buf);

	while (*pptr) {
		if (i++ > 0)
			acl_vstring_strcat(buf, ", ");
		acl_vstring_strcat(buf, *pptr);
		pptr++;
	}
	return (acl_vstring_str(buf));
#endif
}
Beispiel #27
0
bool charset_conv::update(const char* in, size_t len, acl::string* out)
{
#ifdef  HAVE_H_ICONV
	if (in == NULL)
		logger_fatal("in null");
	if (out == NULL)
		logger_fatal("out null");

	if (EQ(m_fromCharset, m_toCharset))
	{
		out->append(in, len);
		return (true);
	}

	if (m_iconv == (iconv_t) -1)
	{
		logger_error("m_iconv invalid");
		m_errmsg = "m_iconv invalid";
		return (false);
	}

	// 去掉有些 UTF-8 文档中开始的 UTF-8 引导符
	if (*m_pUtf8Pre)
	{
		while (len > 0)
		{
			if (*m_pUtf8Pre == 0x00)
				break;
			else if (*m_pUtf8Pre != *in)
			{
				// 必须使 UTF-8 前缀失效
				m_pUtf8Pre = &UTF8_HEADER[3];
				break;
			}
			m_pUtf8Pre++;
			in++;
			len--;
		}
	}

	if (len == 0)
		return (true);

	if (m_pInBuf == NULL)
		m_pInBuf = acl_vstring_alloc(len);

	if (m_pOutBuf == NULL)
		m_pOutBuf = acl_vstring_alloc(len);
	else
		ACL_VSTRING_SPACE(m_pOutBuf, len);

	// 先将输入数据进行缓冲
	if (*m_pUtf8Pre && m_pUtf8Pre - UTF8_HEADER > 0)
		acl_vstring_memcpy(m_pInBuf, UTF8_HEADER,
			m_pUtf8Pre - UTF8_HEADER);
	acl_vstring_memcat(m_pInBuf, in, len);
	ACL_VSTRING_TERMINATE(m_pInBuf);

	char  *pIn, *pOut;
	size_t ret, nIn, nOut;

	while (true)
	{
		nIn  = LEN(m_pInBuf);
		if (nIn == 0)
			break;
		pIn  = STR(m_pInBuf);
		pOut = STR(m_pOutBuf);
		nOut = SIZE(m_pOutBuf);

#ifdef	WIN32
# ifdef USE_WIN_ICONV
		ret = __iconv(m_iconv, (const char**) &pIn, &nIn,
				&pOut, &nOut);
# else
		int   err;
		ret = __iconv(m_iconv, (const char**) &pIn, &nIn,
				&pOut, &nOut, &err);
		errno = err;
# endif // USE_WIN_ICONV
#elif defined(ACL_SUNOS5) || defined(ACL_FREEBSD)
		ret = __iconv(m_iconv, (const char**) &pIn, &nIn, &pOut, &nOut);
#else
		ret = __iconv(m_iconv, &pIn, &nIn, &pOut, &nOut);
#endif


		if (ret != (size_t) -1)
		{
			if ((ret = SIZE(m_pOutBuf) - nOut) > 0)
				out->append(STR(m_pOutBuf), ret);
			else  // xxx
				out->append(in, len);
			ACL_VSTRING_RESET(m_pInBuf);
			break;
		}
		else if (errno == E2BIG)
		{
			if ((ret = SIZE(m_pOutBuf) - nOut) > 0)
				out->append(STR(m_pOutBuf), ret);
			if (pIn > STR(m_pInBuf) && nIn < LEN(m_pInBuf))
				acl_vstring_memmove(m_pInBuf, pIn, nIn);
			// 扩大内存空间
			ACL_VSTRING_SPACE(m_pOutBuf, SIZE(m_pOutBuf) * 2);
			continue;
		}
		else if (errno == EILSEQ)
		{
			char *pNil = NULL;
			size_t zero = 0;

			// 重置状态, 似乎也没啥用处
#ifdef	WIN32
# ifdef USE_WIN_ICONV
			__iconv(m_iconv, (const char**) &pNil,
				&zero, &pNil, &zero);
# else
			__iconv(m_iconv, (const char**) &pNil,
				&zero, &pNil, &zero, NULL);
# endif
#elif defined(ACL_SUNOS5) || defined(ACL_FREEBSD)
			__iconv(m_iconv, (const char**) &pNil,
				&zero, &pNil, &zero);
#else
			__iconv(m_iconv, &pNil, &zero, &pNil, &zero);
#endif

			// 遇到无效的多字节序列,pIn 指向第一个无效的位置

			// 先拷贝已经转换的数据
			if ((ret = SIZE(m_pOutBuf) - nOut) > 0)
				out->append(STR(m_pOutBuf), ret);

			if (nIn == 0)
			{
				ACL_VSTRING_RESET(m_pInBuf);
				break;
			}

			acl_assert(pIn >= STR(m_pInBuf));

			// 跳过无效字节
			(*out) += (char)(*pIn); // 直接拷贝无效字节
			nIn--;
			pIn++;
			if (nIn > 0)
				acl_vstring_memmove(m_pInBuf, pIn, nIn);
			else
				ACL_VSTRING_RESET(m_pInBuf);
		}
		else if (errno == EINVAL)
		{
			char *pNil = NULL;
			size_t zero = 0;

			// 重置状态, 似乎也没啥用处
#ifdef	WIN32
# ifdef USE_WIN_ICONV
			__iconv(m_iconv, (const char**) &pNil,
				&zero, &pNil, &zero);
# else
			__iconv(m_iconv, (const char**) &pNil,
				&zero, &pNil, &zero, NULL);
# endif // USE_WIN_ICONV
#elif defined(ACL_SUNOS5) || defined(ACL_FREEBSD)
			__iconv(m_iconv, (const char**) &pNil, &zero, &pNil, &zero);
#else
			__iconv(m_iconv, &pNil, &zero, &pNil, &zero);
#endif

			// 输入的多字节序列不完整,pIn 指向该不完整的位置

			// 先拷贝已经转换的数据
			if ((ret = SIZE(m_pOutBuf) - nOut) > 0)
				out->append(STR(m_pOutBuf), ret);

			// 移动数据,将未转换的数据移至缓冲区起始位置
			if (nIn > 0)
				acl_vstring_memmove(m_pInBuf, pIn, nIn);
			else
				ACL_VSTRING_RESET(m_pInBuf);
			break;
		}
		else if (LEN(m_pInBuf) > 0)
		{
			// 如果遇到了无效的字符集,根据设置的标志位
			// 决定是否直接拷贝
			if (m_addInvalid)
			{
				out->append(STR(m_pInBuf), LEN(m_pInBuf));
				ACL_VSTRING_RESET(m_pInBuf);
			}
			break;
		}
		else
			break;
	}

	return (true);
#else
	(void) in;
	(void) len;
	(void) out;
	logger_error("no iconv lib");
	m_errmsg = "no iconv lib";
	return (false);
#endif
}
Beispiel #28
0
static int chunked_data(ACL_ASTREAM *astream, HTTP_CHAT_CTX *ctx)
{
	HTTP_BODY_NOTIFY notify = ctx->notify.body_notify;
	void *arg = ctx->arg;
	ACL_VSTRING *sbuf = NULL;
	char *data;
	int   dlen, ret;

	if (ctx->chunked) {
		ret = (int) HTTP_LEN_ROUND(ctx);
		sbuf = acl_aio_readn_peek(astream, ret);
	} else if (ctx->hdr->content_length <= 0)
		sbuf = acl_aio_read_peek(astream);
	else {
		ret = (int) HTTP_LEN_ROUND(ctx);
		if (ret <= 0) {
			/* 说明本次 HTTP 数据已经读完且遇到对方关闭
			 * 或对方发来了多余的数据,所以需要返回 -1
			 */
			DISABLE_READ(astream);
			if (notify(HTTP_CHAT_OK, NULL, 0, arg) < 0)
				return (-1);
			return (-1);
		} else
			sbuf = acl_aio_readn_peek(astream, ret);
	}

	if (sbuf == NULL)
		return (0);

	data = acl_vstring_str(sbuf);
	dlen = (int) ACL_VSTRING_LEN(sbuf);
	ACL_VSTRING_RESET(sbuf);

	ctx->body_len += dlen;
	ctx->read_cnt += dlen;

	if (ctx->chunk_len > 0 && ctx->read_cnt >= ctx->chunk_len) {
		if (!ctx->chunked) {
			/* 如果读到完了整块数据且非 CHUNK 传输,
			 * 则认为读完 HTTP 响应
			 */
			/* xxx: 禁止连续读 */
			DISABLE_READ(astream);
			if (notify(HTTP_CHAT_OK, data, dlen, arg) < 0)
				return (-1);
			return (1);
		}

		/* 对于 chunk 传输,读完本数据块 */
		if (notify(HTTP_CHAT_DATA, data, dlen, arg) < 0)
			return (-1);

		/* 设置标志位开始读取块数据体的分隔行数据 */
		ctx->status = CHAT_S_CHUNK_SEP;
		return (0);
	}

	if (notify(HTTP_CHAT_DATA, data, dlen, arg) < 0)
		return (-1);
	return (0);
}
Beispiel #29
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);
}