Ejemplo n.º 1
0
int acl_xml_decode(const char *in, ACL_VSTRING *out)
{
    int   n = 0, len = (int) strlen(in);
    const char *ptr = in, *pre;
    const ACL_TOKEN *token;
    const XML_SPEC *spec;

    ACL_VSTRING_SPACE(out, len);

    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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
static void test61(void)
{
	ACL_VSTRING* buf;
	buf = acl_vstring_alloc(256);

	acl_vstring_strcpy(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");

	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");

	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");

	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");

	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");
	acl_vstring_strcat(buf, "hello world!");

	acl_vstring_free(buf);
}
Ejemplo n.º 5
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
}
Ejemplo n.º 6
0
static void get_url(const char *method, const char *url,
	const char *proxy, const char *dump)
{
	/* 创建 HTTP 请求头 */
	HTTP_HDR_REQ *hdr_req = http_hdr_req_create(url, method, "HTTP/1.1");
	ACL_VSTREAM *stream;
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	HTTP_HDR_RES *hdr_res;
	HTTP_RES *res;
	ACL_FILE *fp = NULL;
	const char *ptr;
	int   ret;

	/* 输出 HTTP 请求头内容 */

	http_hdr_print(&hdr_req->hdr, "---request hdr---");

	/* 如果设定代理服务器,则连接代理服务器地址,
	 * 否则使用 HTTP 请求头里指定的地址
	 */

	if (*proxy)
		acl_vstring_strcpy(buf, proxy);
	else
		acl_vstring_strcpy(buf, http_hdr_req_host(hdr_req));

	/* 获得远程 HTTP 服务器的连接地址 */

	ptr = acl_vstring_memchr(buf, ':');
	if (ptr == NULL)
		acl_vstring_strcat(buf, ":80");
	else {
		int   port;
		ptr++;
		port = atoi(ptr);
		if (port <= 0 || port >= 65535) {
			printf("http server's addr(%s) invalid\n", acl_vstring_str(buf));
			acl_vstring_free(buf);
			http_hdr_req_free(hdr_req);
			return;
		}
	}

	/* 连接远程 http 服务器 */

	stream = acl_vstream_connect(acl_vstring_str(buf) /* 服务器地址 */,
			ACL_BLOCKING /* 采用阻塞方式 */,
			10 /* 连接超时时间为 10 秒 */,
			10 /* 网络 IO 操作超时时间为 10 秒 */,
			4096 /* stream 流缓冲区大小为 4096 字节 */);
	if (stream == NULL) {
		printf("connect addr(%s) error(%s)\n",
			acl_vstring_str(buf), acl_last_serror());
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 构建 HTTP 请求头数据 */

	http_hdr_build_request(hdr_req, buf);

	/* 向 HTTP 服务器发送请求 */

	ret = acl_vstream_writen(stream, acl_vstring_str(buf), ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF) {
		printf("write to server error(%s)\n", acl_last_serror());
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 创建一个 HTTP 响应头对象 */

	hdr_res = http_hdr_res_new();

	/* 读取 HTTP 服务器响应头*/

	ret = http_hdr_res_get_sync(hdr_res, stream, 10 /* IO 超时时间为 10 秒 */);
	if (ret < 0) {
		printf("get http reply header error(%s)\n", acl_last_serror());
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	if (http_hdr_res_parse(hdr_res) < 0) {
		printf("parse http reply header error\n");
		http_hdr_print(&hdr_res->hdr, "--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 如果需要转储至磁盘则需要先打开文件 */

	if (dump != NULL) {
		fp = acl_fopen(dump, "w+");
		if (fp == NULL)
			printf("open file(%s) error(%s)\n",
				dump, acl_last_serror());
	}

	/* 如果 HTTP 响应没有数据体则仅输出 HTTP 响应头即可 */

	if (hdr_res->hdr.content_length == 0
		|| (hdr_res->hdr.content_length == -1
			&& !hdr_res->hdr.chunked
			&& hdr_res->reply_status > 300
			&& hdr_res->reply_status < 400))
	{
		if (fp)
			http_hdr_fprint(ACL_FSTREAM(fp), &hdr_res->hdr,
				"--- reply http header ---");
		else
			http_hdr_fprint(ACL_VSTREAM_OUT, &hdr_res->hdr,
				"--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 输出 HTTP 响应头 */

	http_hdr_print(&hdr_res->hdr, "--- reply http header ---");

	/* 创建 HTTP 响应体对象 */

	res = http_res_new(hdr_res);

	/* 如果有数据体则开始读取 HTTP 响应数据体部分 */
	while (1) {
		http_off_t  n;
		char  buf2[4096];
		
		n = http_res_body_get_sync(res, stream, buf2, sizeof(buf2) - 1);
		if (n <= 0)
			break;

		if (fp) {
			if (acl_fwrite(buf2, (size_t) n, 1, fp) == (size_t) EOF) {
				printf("write to dump file(%s) error(%s)\n",
					dump, acl_last_serror());
				break;
			}
		} else {
			buf2[n] = 0;
			printf("%s", buf2);
		}
	}

	if (fp)
		acl_fclose(fp);
	http_res_free(res);  /* 释放 HTTP 响应对象, hdr_res 会在此函数内部自动被释放 */
	acl_vstream_close(stream);  /* 关闭网络流 */
	acl_vstring_free(buf);  /* 释放内存区 */
	http_hdr_req_free(hdr_req);  /* 释放 HTTP 请求头对象 */
}
Ejemplo n.º 7
0
static int mac_expand_callback(int type, ACL_VSTRING *buf, char *ptr)
{
    MAC_EXP *mc = (MAC_EXP *) ptr;
    int     lookup_mode;
    const char *text;
    char   *cp, *pp = NULL;
    int     ch;
    ssize_t len;
	size_t  size;

    /*
     * Sanity check.
     */
    if (mc->level++ > 100) {
	acl_msg_warn("unreasonable macro call nesting: \"%s\"", acl_vstring_str(buf));
	mc->status |= MAC_PARSE_ERROR;
    }
    if (mc->status & MAC_PARSE_ERROR)
	return (mc->status);

    /*
     * $Name etc. reference.
     * 
     * In order to support expansion of lookup results, we must save the lookup
     * result. We use the input buffer since it will not be needed anymore.
     */
    if (type == MAC_PARSE_EXPR) {

	/*
	 * Look for the ? or : delimiter. In case of a syntax error, return
	 * without doing damage, and issue a warning instead.
	 */
	for (cp = acl_vstring_str(buf); /* void */ ; cp++) {
	    if ((ch = *cp) == 0) {
		lookup_mode = MAC_EXP_MODE_USE;
		break;
	    }
	    if (ch == '?' || ch == ':') {
		*cp++ = 0;
		lookup_mode = MAC_EXP_MODE_TEST;
		break;
	    }
	    if (!ACL_ISALNUM(ch) && ch != '_') {
		acl_msg_warn("macro name syntax error: \"%s\"", acl_vstring_str(buf));
		mc->status |= MAC_PARSE_ERROR;
		return (mc->status);
	    }
	}

	/*
	 * Look up the named parameter.
	 */
	text = mc->lookup(acl_vstring_str(buf), lookup_mode, mc->context, &pp, &size);

	/*
	 * Perform the requested substitution.
	 */
	switch (ch) {
	case '?':
	    if (text != 0 && *text != 0)
		mac_parse(cp, mac_expand_callback, (char *) mc);
	    break;
	case ':':
	    if (text == 0 || *text == 0)
		mac_parse(cp, mac_expand_callback, (char *) mc);
	    break;
	default:
	    if (text == 0) {
		mc->status |= MAC_PARSE_UNDEF;
	    } else if (*text == 0) {
		 /* void */ ;
	    } else if (mc->flags & MAC_EXP_FLAG_RECURSE) {
		acl_vstring_strcpy(buf, text);
		mac_parse(acl_vstring_str(buf), mac_expand_callback, (char *) mc);
	    } else {
		len = (int) ACL_VSTRING_LEN(mc->result);
		acl_vstring_strcat(mc->result, text);
		if (mc->filter) {
		    cp = acl_vstring_str(mc->result) + len;
		    while (*(cp += strspn(cp, mc->filter)))
			*cp++ = '_';
		}
	    }
	    break;
	}
    }

    /*
     * Literal text.
     */
    else {
	acl_vstring_strcat(mc->result, acl_vstring_str(buf));
    }

    mc->level--;
	if (pp)
		free(pp);

    return (mc->status);
}