Пример #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;
}
Пример #2
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);
}
Пример #3
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);
}
Пример #4
0
static const char *xml_parse_meta_text(ACL_XML *xml, const char *data)
{
	int   ch;

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

	while ((ch = *data) != 0) {
		if (xml->curr_node->quote) {
			if (ch == xml->curr_node->quote) {
				xml->curr_node->quote = 0;
			}
			ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		} else if (IS_QUOTE(ch)) {
			if (xml->curr_node->quote == 0) {
				xml->curr_node->quote = ch;
			}
			ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		} else if (ch == '<') {
			xml->curr_node->nlt++;
			ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		} else if (ch == '>') {
			if (xml->curr_node->nlt == 0) {
				char *last;
				size_t off;

				data++;
				xml->curr_node->status = ACL_XML_S_MEND;
				if ((xml->curr_node->flag & ACL_XML_F_META_QM) == 0)
					break;

				last = acl_vstring_end(xml->curr_node->text) - 1;
				if (last < STR(xml->curr_node->text) || *last != '?')
					break;
				off = ACL_VSTRING_LEN(xml->curr_node->text) - 1;
				if (off == 0)
					break;
				ACL_VSTRING_AT_OFFSET(xml->curr_node->text, off);
				ACL_VSTRING_TERMINATE(xml->curr_node->text);
				xml_meta_attr(xml->curr_node);
				break;
			}
			xml->curr_node->nlt--;
			ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		} else {
			ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		}
		data++;
	}

	ACL_VSTRING_TERMINATE(xml->curr_node->text);
	return (data);
}
Пример #5
0
int acl_xml_decode(const char *in, ACL_VSTRING *out)
{
    int   n = 0, len;
    const char *ptr = in, *pre;
    const ACL_TOKEN *token;
    const XML_SPEC *spec;

    acl_pthread_once(&__token_once, xml_decode_init);
    if (__token_tree == NULL)
        acl_msg_fatal("__token_tree null");

    while (*ptr != 0) {
        pre = ptr;
        token = acl_token_tree_match(__token_tree, &ptr, NULL, NULL);
        if (token == NULL) {
            pre = markup_unescape(pre, out);
            len = (int) (ptr - pre);
            if (len > 0)
                acl_vstring_memcat(out, pre, len);
            break;
        }
        spec = (const XML_SPEC*) token->ctx;
        acl_assert(spec != NULL);

        len = (int) (ptr - pre - spec->len);
        if (len > 0)
            acl_vstring_memcat(out, pre, len);
        acl_vstring_strcat(out, spec->str);
        n++;
    }

    ACL_VSTRING_TERMINATE(out);
    return (n);
}
Пример #6
0
static const char *xml_parse_left_em(ACL_XML *xml, const char *data)
{
	if (*data == '-') {
		if (xml->curr_node->meta[1] != '-') {
			xml->curr_node->meta[1] = '-';
		} else if (xml->curr_node->meta[2] != '-') {
			xml->curr_node->meta[0] = 0;
			xml->curr_node->meta[1] = 0;
			xml->curr_node->meta[2] = 0;
			xml->curr_node->flag |= ACL_XML_F_META_CM;
			xml->curr_node->status = ACL_XML_S_MCMT;
		}
		data++;
	} else {
		if (xml->curr_node->meta[1] == '-') {
			ACL_VSTRING_ADDCH(xml->curr_node->ltag, '-');
			xml->curr_node->meta[1] = 0;
		}
		xml->curr_node->flag |= ACL_XML_F_META_EM;
		xml->curr_node->status = ACL_XML_S_MTAG;
	}

	ACL_VSTRING_TERMINATE(xml->curr_node->ltag);
	return (data);
}
Пример #7
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);
}
Пример #8
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--;
	}
}
Пример #9
0
static const char *tok822_comment(TOK822 *tp, const char *str)
{
	int     level = 1;
	int     ch;

	/*
	 * XXX We cheat by storing comments in their external form. Otherwise it
	 * would be a royal pain to preserve \ before (. That would require a
	 * recursive parser; the easy to implement stack-based recursion would be
	 * too expensive.
	 */
	ACL_VSTRING_ADDCH(tp->vstr, '(');

	while ((ch = *(const unsigned char *) str) != 0) {
		ACL_VSTRING_ADDCH(tp->vstr, ch);
		str++;
		if (ch == '(') {			/* comments can nest! */
			level++;
		} else if (ch == ')') {
			if (--level == 0)
				break;
		} else if (ch == '\\') {
			if ((ch = *(unsigned char *) str) == 0)
				break;
			ACL_VSTRING_ADDCH(tp->vstr, ch);
			str++;
		}
	}
	ACL_VSTRING_TERMINATE(tp->vstr);
	return (str);
}
Пример #10
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);
}
Пример #11
0
static const char *xml_meta_attr_value(ACL_XML_ATTR *attr, const char *data)
{
	int   ch;

	SKIP_SPACE(data);
	if (*data == 0)
		return data;
	if (IS_QUOTE(*data))
		attr->quote = *data++;

	while ((ch = *data) != 0) {
		if (attr->backslash) {
			if (ch == 'b')
				ADDCH(attr->value, '\b');
			else if (ch == 'f')
				ADDCH(attr->value, '\f');
			else if (ch == 'n')
				ADDCH(attr->value, '\n');
			else if (ch == 'r')
				ADDCH(attr->value, '\r');
			else if (ch == 't')
				ADDCH(attr->value, '\t');
			else
				ADDCH(attr->value, ch);
			attr->backslash = 0;
		} else if (ch == '\\') {
			if (attr->part_word) {
				ADDCH(attr->value, ch);
				attr->part_word = 0;
			} else
				attr->backslash = 1;
		} else if (attr->quote) {
			if (ch == attr->quote) {
				data++;
				break;
			}
			ADDCH(attr->value, ch);
		} else if (IS_SPACE(ch)) {
			data++;
			break;
		} else {
			ADDCH(attr->value, ch);
			if ((attr->node->xml->flag & ACL_XML_FLAG_PART_WORD)) {
				if (attr->part_word)
					attr->part_word = 0;
				else if (ch < 0)
					attr->part_word = 1;
			}
		}
		data++;
	}

	ACL_VSTRING_TERMINATE(attr->value);
	return data;
}
Пример #12
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);
}
Пример #13
0
static const char *xml_parse_meta_tag(ACL_XML *xml, const char *data)
{
	int   ch;

	while ((ch = *data) != 0) {
		data++;
		if (IS_SPACE(ch)) {
			xml->curr_node->status = ACL_XML_S_MTXT;
			break;
		}
		ACL_VSTRING_ADDCH(xml->curr_node->ltag, ch);
	}
	ACL_VSTRING_TERMINATE(xml->curr_node->ltag);
	return (data);
}
Пример #14
0
static const char *xml_parse_attr(ACL_XML *xml, const char *data)
{
	int   ch;
	ACL_XML_ATTR *attr = xml->curr_node->curr_attr;

	if (attr == NULL || LEN(attr->name) == 0) {
		SKIP_SPACE(data);	/* 略过 ' ', '\t' */
		if (*data == 0)
			return (NULL);
		SKIP_WHILE(*data == '=', data);
		if (*data == 0)
			return (NULL);
	}

	if (*data == '>') {
		xml->curr_node->status = ACL_XML_S_LGT;
		xml_parse_check_self_closed(xml);
		xml->curr_node->curr_attr = NULL;
		data++;
		return (data);
	}

	xml->curr_node->last_ch = *data;
	if (*data == '/') {
		data++;
		return (data);
	}

	if (attr == NULL) {
		attr = acl_xml_attr_alloc(xml->curr_node);
		xml->curr_node->curr_attr = attr;
	}

	while ((ch = *data) != 0) {
		xml->curr_node->last_ch = ch;
		if (ch == '=') {
			xml->curr_node->status = ACL_XML_S_AVAL;
			data++;
			break;
		}
		if (!IS_SPACE(ch))
			ACL_VSTRING_ADDCH(attr->name, ch);
		data++;
	}

	ACL_VSTRING_TERMINATE(attr->name);
	return (data);
}
Пример #15
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);
	}
}
Пример #16
0
static const char *xml_meta_attr_name(ACL_XML_ATTR *attr, const char *data)
{
	int   ch;

	while ((ch = *data) != 0) {
		if (ch == '=') {
			data++;
			ACL_VSTRING_TERMINATE(attr->name);
			break;
		}
		if (!IS_SPACE(ch))
			ACL_VSTRING_ADDCH(attr->name, ch);
		data++;
	}
	return data;
}
Пример #17
0
int acl_xml_encode(const char *in, ACL_VSTRING *out)
{
    int  n = 0;

    while (*in) {
        if (__charmap[(unsigned char)(*in)] != NULL) {
            acl_vstring_strcat(out,
                               __charmap[(unsigned char)(*in)]);
            n++;
        } else
            ACL_VSTRING_ADDCH(out, (*in));
        in++;
    }

    ACL_VSTRING_TERMINATE(out);
    return (n);
}
Пример #18
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);
}
Пример #19
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);
}
Пример #20
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));
}
Пример #21
0
static const char *xml_parse_text(ACL_XML *xml, const char *data)
{
	int   ch;

	if (LEN(xml->curr_node->text) == 0) {
		SKIP_SPACE(data);
		if (*data == 0)
			return (NULL);
	}

	while ((ch = *data) != 0) {
		if (ch == '<') {
			xml->curr_node->status = ACL_XML_S_RLT;
			data++;
			break;
		}
		ACL_VSTRING_ADDCH(xml->curr_node->text, ch);
		data++;
	}

	ACL_VSTRING_TERMINATE(xml->curr_node->text);

	if (xml->curr_node->status != ACL_XML_S_RLT)
		return (data);

	if ((xml->curr_node->flag & ACL_XML_F_SELF_CL)) {
		/* 如果该标签是自关闭类型,则应使父结点直接跳至右边 '/' 处理位置,
		 * 同时使本结点跳至右边 '>' 处理位置
		 */
		ACL_XML_NODE *parent = acl_xml_node_parent(xml->curr_node);
		if (parent != xml->root)
			parent->status = ACL_XML_S_RLT;
		xml->curr_node->status = ACL_XML_S_RGT;
	}

	if (LEN(xml->curr_node->text) == 0)
		return (data);

	return (data);
}
Пример #22
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, '>');
}
Пример #23
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);
}
Пример #24
0
int acl_xml_encode(const char *in, ACL_VSTRING *out)
{
    const unsigned char *ptr = (const unsigned char*) in;
    int  n = 0;
    size_t len = strlen(in);

    len += len / 2;

    ACL_VSTRING_SPACE(out, (int) len);

    while (*ptr) {
        if (__charmap[*ptr] != NULL) {
            acl_vstring_strcat(out, __charmap[*ptr]);
            n++;
        } else {
            ACL_VSTRING_ADDCH(out, *ptr);
        }
        ptr++;
    }

    ACL_VSTRING_TERMINATE(out);
    return n;
}
Пример #25
0
static const char *xml_parse_right_lt(ACL_XML *xml, const char *data)
{
	ACL_XML_NODE *node;

	SKIP_SPACE(data);
	if (*data == 0)
		return (NULL);
	if (*data == '/') {
		xml->curr_node->status = ACL_XML_S_RTAG;
		data++;
		return (data);
	} else if ((xml->curr_node->flag & ACL_XML_F_LEAF)) {
		ACL_VSTRING_ADDCH(xml->curr_node->text, '<');
		ACL_VSTRING_ADDCH(xml->curr_node->text, *data);
		ACL_VSTRING_TERMINATE(xml->curr_node->text);
		xml->curr_node->status = ACL_XML_S_TXT;
		data++;
		return (data);
	}

	/* 说明遇到了当前结点的子结点 */

	/* 重新设置当前结点状态,以便于其可以找到 "</" */
	xml->curr_node->status = ACL_XML_S_TXT;

	/* 创建新的子结点,并将其加入至当前结点的子结点集合中 */

	node = acl_xml_node_alloc(xml);
	acl_xml_node_add_child(xml->curr_node, node);
	node->depth = xml->curr_node->depth + 1;
	if (node->depth > xml->depth)
		xml->depth = node->depth;
	xml->curr_node = node;
	xml->curr_node->status = ACL_XML_S_LLT;
	return (data);
}
Пример #26
0
HTTP_HDR_REQ *http_hdr_req_create(const char *url,
	const char *method, const char *version)
{
	const char *myname = "http_hdr_req_create";
	HTTP_HDR_REQ *hdr_req;
	ACL_VSTRING *req_line = acl_vstring_alloc(256);
	HTTP_HDR_ENTRY *entry;
	const char *ptr;
	static char *__user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.0"
		"; zh-CN; rv:1.9.0.3) Gecko/2008092417 ACL/3.0.6";

	if (url == NULL || *url == 0) {
		acl_msg_error("%s(%d): url invalid", myname, __LINE__);
		return NULL;
	}
	if (method == NULL || *method == 0) {
		acl_msg_error("%s(%d): method invalid", myname, __LINE__);
		return NULL;
	}
	if (version == NULL || *version == 0) {
		acl_msg_error("%s(%d): version invalid", myname, __LINE__);
		return NULL;
	}

	acl_vstring_strcpy(req_line, method);
	acl_vstring_strcat(req_line, " ");

	if (strncasecmp(url, "http://", sizeof("http://") - 1) == 0)
		url += sizeof("http://") - 1;
	else if (strncasecmp(url, "https://", sizeof("https://") - 1) == 0)
		url += sizeof("https://") -1;
	ptr = strchr(url, '/');
	if (ptr)
		acl_vstring_strcat(req_line, ptr);
	else {
		ACL_VSTRING_ADDCH(req_line, '/');
		ACL_VSTRING_TERMINATE(req_line);
	}

	acl_vstring_strcat(req_line, " ");
	acl_vstring_strcat(req_line, version);

	entry = http_hdr_entry_new(acl_vstring_str(req_line));
	acl_vstring_free(req_line);

	if (entry == NULL) {
		acl_msg_error("%s(%d): http_hdr_entry_new return null for (%s)",
			myname, __LINE__, acl_vstring_str(req_line));
		return NULL;
	}

	hdr_req = http_hdr_req_new();
	http_hdr_append_entry(&hdr_req->hdr, entry);
	hdr_req->flag |= (HTTP_HDR_REQ_FLAG_PARSE_PARAMS | HTTP_HDR_REQ_FLAG_PARSE_COOKIE);
	if (http_hdr_req_line_parse(hdr_req) < 0) {
		http_hdr_req_free(hdr_req);
		return NULL;
	}

	hdr_req->host[0] = 0;
	__get_host_from_url(hdr_req->host, sizeof(hdr_req->host), url);
	if (hdr_req->host[0] != 0)
		http_hdr_put_str(&hdr_req->hdr, "Host", hdr_req->host);
	http_hdr_put_str(&hdr_req->hdr, "Connection", "Close");
	http_hdr_put_str(&hdr_req->hdr, "User-Agent", __user_agent);

	return hdr_req;
}
Пример #27
0
static int vstring_extend(ACL_VBUF *bp, ssize_t incr)
{
	const char *myname = "vstring_extend";
	ssize_t used = (ssize_t) (bp->ptr - bp->data), new_len;
	ACL_VSTRING *vp = (ACL_VSTRING *) bp;

	if (vp->maxlen > 0 && (ssize_t) ACL_VSTRING_LEN(vp) >= vp->maxlen) {
		ACL_VSTRING_AT_OFFSET(vp, vp->maxlen - 1);
		ACL_VSTRING_TERMINATE(vp);
		acl_msg_warn("%s(%d), %s: overflow maxlen: %ld, %ld",
			__FILE__, __LINE__, myname, (long) vp->maxlen,
			(long) ACL_VSTRING_LEN(vp));
		bp->flags |= ACL_VBUF_FLAG_EOF;
		return ACL_VBUF_EOF;
	}

#ifdef ACL_WINDOWS
	if (bp->fd == ACL_FILE_INVALID && (bp->flags & ACL_VBUF_FLAG_FIXED))
#else
	if (bp->fd < 0 && (bp->flags & ACL_VBUF_FLAG_FIXED))
#endif
	{
		acl_msg_warn("%s(%d), %s: can't extend fixed buffer",
			__FILE__, __LINE__, myname);
		return ACL_VBUF_EOF;
	}

	/*
	 * Note: vp->vbuf.len is the current buffer size (both on entry and on
	 * exit of this routine). We round up the increment size to the buffer
	 * size to avoid silly little buffer increments. With really large
	 * strings we might want to abandon the length doubling strategy, and
	 * go to fixed increments.
	 */
#ifdef INCR_NO_DOUBLE
	/* below come from redis-server/sds.c/sdsMakeRoomFor, which can
	 * avoid memory double growing too large --- 2015.2.2, zsx
	 */
	new_len = bp->len + incr;
	if (new_len < MAX_PREALLOC)
		new_len *= 2;
	else
		new_len += MAX_PREALLOC;
#else
	new_len = bp->len + (bp->len > incr ? bp->len : incr);
#endif

	if (vp->maxlen > 0 && new_len > vp->maxlen)
		new_len = vp->maxlen;

	if (vp->slice)
		bp->data = (unsigned char *) acl_slice_pool_realloc(
			__FILE__, __LINE__, vp->slice, bp->data, new_len);
	else if (vp->dbuf) {
		const unsigned char *data = bp->data;
		bp->data = (unsigned char *) acl_dbuf_pool_alloc(
			vp->dbuf, new_len);
		memcpy(bp->data, data, used);
		acl_dbuf_pool_free(vp->dbuf, data);
	} else if (bp->fd != ACL_FILE_INVALID) {
#ifdef ACL_UNIX
		acl_off_t off = new_len - 1;
		if (acl_lseek(bp->fd, off, SEEK_SET) != (acl_off_t) off)
			acl_msg_fatal("lseek failed: %s, off: %lld",
				acl_last_serror(), off);
		if (acl_file_write(bp->fd, "\0", 1, 0, NULL, NULL)
			== ACL_VSTREAM_EOF)
		{
			acl_msg_fatal("write error: %s", acl_last_serror());
		}
#endif
	} else
		bp->data = (unsigned char *) acl_myrealloc(bp->data, new_len);

	bp->len = new_len;
	bp->ptr = bp->data + used;
	bp->cnt = bp->len - used;

	return 0;
}
Пример #28
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);
}
Пример #29
0
static const char *json_tag(ACL_JSON *json, const char *data)
{
	ACL_JSON_NODE *node = json->curr_node;
	int   ch;

	while ((ch = *data) != 0) {
		/* 如果前面有引号,则需要找到结尾引号 */
		if (node->quote) {
			if (node->backslash) {
				if (ch == 'b')
					ADDCH(node->ltag, '\b');
				else if (ch == 'f')
					ADDCH(node->ltag, '\f');
				else if (ch == 'n')
					ADDCH(node->ltag, '\n');
				else if (ch == 'r')
					ADDCH(node->ltag, '\r');
				else if (ch == 't')
					ADDCH(node->ltag, '\t');
				else
					ADDCH(node->ltag, ch);
				node->backslash = 0;
			}

			/* 当为双字节汉字时,第一个字节为的高位为 1,
			 * 第二个字节为 92,正好与转义字符相同
			 */
			else if (ch == '\\') {
				/* 处理半个汉字的情形 */
				if (node->part_word) {
					ADDCH(node->ltag, ch);
					node->part_word = 0;
				} else
					node->backslash = 1;
			} else if (ch == node->quote) {
				ACL_JSON_NODE *parent;

				parent = acl_json_node_parent(node);

				acl_assert(parent);

				/* 数组对象的子结点允许为单独的字符串或对象 */
				if (parent->left_ch == '[')
					json->status = ACL_JSON_S_NEXT;

				/* 标签值分析结束,下一步需要找到冒号 */
				else
					json->status = ACL_JSON_S_COLON;

				node->quote = 0;
				node->part_word = 0;
				data++;
				break;
			}

			/* 是否兼容后半个汉字为转义符 '\' 的情况 */
			else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) {
				ADDCH(node->ltag, ch);

				/* 处理半个汉字的情形 */
				if (node->part_word)
					node->part_word = 0;
				else if (ch < 0)
					node->part_word = 1;
			} else {
				ADDCH(node->ltag, ch);
			}
		}

		/* 分析标签名前没有引号的情况 */

		else if (node->backslash) {
			ADDCH(node->ltag, ch);
			node->backslash = 0;
		}

		/* 当为双字节汉字时,第一个字节为的高位为 1,
		 * 第二个字节为 92,正好与转义字符相同
		 */
		else if (ch == '\\') {
			/* 处理半个汉字的情形 */
			if (node->part_word) {
				ADDCH(node->ltag, ch);
				node->part_word = 0;
			} else
				node->backslash = 1;
		} else if (IS_SPACE(ch) || ch == ':') {
			/* 标签名分析结束,下一步需要找到冒号 */
			json->status = ACL_JSON_S_COLON;
			node->part_word = 0;
			break;
		}

		/* 是否兼容后半个汉字为转义符 '\' 的情况 */
		else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) {
			ADDCH(node->ltag, ch);

			/* 处理半个汉字的情形 */
			if (node->part_word)
				node->part_word = 0;
			else if (ch < 0)
				node->part_word = 1;
		} else {
			ADDCH(node->ltag, ch);
		}
		data++;
	}

	/* 如果标签名非空,则需要保证以 0 结尾 */
	if (LEN(node->ltag) > 0)
		ACL_VSTRING_TERMINATE(node->ltag);

	return data;
}
Пример #30
0
static const char *json_string(ACL_JSON *json, const char *data)
{
	ACL_JSON_NODE *node = json->curr_node;
	int   ch;

	/* 当文本长度为 0 时,可以认为还未遇到有效的字符 */

	if (LEN(node->text) == 0) {
		/* 先过滤开头没用的空格 */
		SKIP_SPACE(data);
		if (*data == 0)
			return NULL;
	}

	/* 说明本结点是叶结点 */

	while ((ch = *data) != 0) {
		/* 如果开始有引号,则需要以该引号作为结尾符 */
		if (node->quote) {
			if (node->backslash) {
				if (ch == 'b')
					ADDCH(node->text, '\b');
				else if (ch == 'f')
					ADDCH(node->text, '\f');
				else if (ch == 'n')
					ADDCH(node->text, '\n');
				else if (ch == 'r')
					ADDCH(node->text, '\r');
				else if (ch == 't')
					ADDCH(node->text, '\t');
				else
					ADDCH(node->text, ch);
				node->backslash = 0;
			}

			/* 当为双字节汉字时,第一个字节为的高位为 1,
			 * 第二个字节有可能为 92,正好与转义字符相同
			 */
			else if (ch == '\\') {
				/* 处理半个汉字的情况,如果前一个字节是前
				 * 半个汉字,则当前的转义符当作后半个汉字
				 */
				if (node->part_word) {
					ADDCH(node->text, ch);
					node->part_word = 0;
				} else
					node->backslash = 1;
			} else if (ch == node->quote) {
				node->quote = 0;

				/* 切换至查询该结点的兄弟结点的过程 */
				json->status = ACL_JSON_S_STREND;
				node->part_word = 0;
				data++;
				break;
			}

			/* 是否兼容后半个汉字为转义符 '\' 的情况 */
			else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) {
				ADDCH(node->text, ch);

				/* 若前一个字节为前半个汉字,则当前字节
				 * 为后半个汉字,正好为一个完整的汉字
				 */
				if (node->part_word)
					node->part_word = 0;

				/* 前一个字节非前半个汉字且当前字节高位
				 * 为 1,则表明当前字节为前半个汉字
				 */
				else if (ch < 0)
					node->part_word = 1;
			} else {
				ADDCH(node->text, ch);
			}
		} else if (node->backslash) {
			ADDCH(node->text, ch);
			node->backslash = 0;
		} else if (ch == '\\') {
			if (node->part_word) {
				ADDCH(node->text, ch);
				node->part_word = 0;
			} else
				node->backslash = 1;
		} else if (IS_SPACE(ch) || ch == ',' || ch == ';'
			|| ch == '}' || ch == ']')
		{
			/* 切换至查询该结点的兄弟结点的过程 */
			json->status = ACL_JSON_S_STREND;
			break;
		}

		/* 是否兼容后半个汉字为转义符 '\' 的情况 */
		else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) {
			ADDCH(node->text, ch);

			/* 处理半个汉字的情形 */
			if (node->part_word)
				node->part_word = 0;
			else if (ch < 0)
				node->part_word = 1;
		} else {
			ADDCH(node->text, ch);
		}
		data++;
	}

	if (LEN(node->text) > 0)
		ACL_VSTRING_TERMINATE(node->text);

	return data;
}