예제 #1
0
파일: main.c 프로젝트: 1514louluo/acl
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);
}
예제 #2
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);
}
예제 #3
0
파일: http_error.c 프로젝트: 10jschen/acl
void http_error_reply(HTTP_CLIENT *http_client, int status, const char *msg)
{
	static __thread ACL_VSTRING *__buf = NULL;
	const ACL_VSTRING *str;
	const char *ptr;
	struct iovec iov[2];

	if (__buf == NULL) {
		__buf = acl_vstring_alloc(256);
		acl_pthread_atexit_add(__buf, free_buf);
	}

	ptr = http_tmpl_title(status);
	str = http_tmpl_get(status);
	
	if (msg == NULL || *msg == 0)
		msg = acl_vstring_str(str);

	acl_vstring_sprintf(__buf, reply_error_fmt, status, ptr);
	
	iov[0].iov_base = acl_vstring_str(__buf);
	iov[0].iov_len  = ACL_VSTRING_LEN(__buf);
	iov[1].iov_base = (char*) msg;
	iov[1].iov_len  = strlen(msg);

	acl_aio_writev(http_client->stream, iov, 2);
}
예제 #4
0
파일: json.cpp 프로젝트: nitsel88/acl
const char* json_node::tag_name(void) const
{
	if (node_me_->ltag && ACL_VSTRING_LEN(node_me_->ltag) > 0)
		return (acl_vstring_str(node_me_->ltag));
	else
		return (NULL);
}
예제 #5
0
파일: xml.cpp 프로젝트: 2202877/acl
const char* xml_node::id(void) const
{
	if (node_->id && ACL_VSTRING_LEN(node_->id) > 0)
		return acl_vstring_str(node_->id);
	else
		return NULL;
}
예제 #6
0
파일: json.cpp 프로젝트: nitsel88/acl
const char* json_node::get_text(void) const
{
	if (node_me_->text && ACL_VSTRING_LEN(node_me_->text) > 0)
		return acl_vstring_str(node_me_->text);
	else
		return NULL;
}
예제 #7
0
파일: json.cpp 프로젝트: nitsel88/acl
bool json_node::set_tag(const char* name)
{
	if (name == NULL || *name == 0)
		return false;
	if (node_me_->ltag == NULL || ACL_VSTRING_LEN(node_me_->ltag) == 0)
		return false;
	acl_vstring_strcpy(node_me_->ltag, name);
	return true;
}
예제 #8
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);
}
예제 #9
0
파일: main.c 프로젝트: 1514louluo/acl
static void b64_decode(const char *ptr)
{
	ACL_VSTRING *str = acl_vstring_alloc(1);
	const char *p;

#define DECODE(b,x,l) { \
	if (acl_vstring_base64_decode((b),(x),(l)) == 0) { \
		printf("bad base64 encoded string: %s\r\n", (x)); \
		exit (1); \
	} \
}
	DECODE(str, ptr, strlen(ptr));

	p = acl_vstring_str(str);
	printf(">>>decode result:|%s|\n>>>orignal str: {%s}, len: %d\n", p, ptr, (int) ACL_VSTRING_LEN(str));
	b64_encode(p);
	printf("len: %d, %d\n", (int) ACL_VSTRING_LEN(str), (int) strlen(p));

	acl_vstring_free(str);
}
예제 #10
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);
}
예제 #11
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);
}
예제 #12
0
파일: name_mask.c 프로젝트: 10jschen/acl
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));
}
예제 #13
0
static void vstring_extend(ACL_VBUF *bp, int incr)
{
	const char *myname = "vstring_extend";
	unsigned used = bp->ptr - bp->data;
	int     new_len;
	ACL_VSTRING *vp = (ACL_VSTRING *) bp->ctx;

	if (vp->maxlen > 0 && (int) ACL_VSTRING_LEN(vp) > vp->maxlen)
		acl_msg_warn("%s(%d), %s: reached the maxlen: %d",
			__FILE__, __LINE__, myname, vp->maxlen);

	/*
	 * 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.
	 */
	/* new_len = bp->len + (bp->len > incr ? bp->len : incr); */
	/* 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;

	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);
	} 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;
}
예제 #14
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);
}
예제 #15
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);
}
예제 #16
0
파일: http_util.c 프로젝트: 1514louluo/acl
int http_util_req_open(HTTP_UTIL *http_util)
{
	const char *myname = "http_util_req_open";
	int   ret;

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

	http_util->stream = acl_vstream_connect(http_util->server_addr,
			ACL_BLOCKING /* 采用阻塞方式 */,
			http_util->conn_timeout /* 连接超时时间 */,
			http_util->rw_timeout /* 网络 IO 操作超时时间 */,
			4096 /* stream 流缓冲区大小为 4096 字节 */);
	if (http_util->stream == NULL) {
		acl_msg_error("%s(%d): connect %s error(%s)",
			myname, __LINE__, http_util->server_addr,
			acl_last_serror());
		return (-1);
	}

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

	http_hdr_build_request(http_util->hdr_req, http_util->req_buf);

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

	ret = acl_vstream_writen(http_util->stream,
			acl_vstring_str(http_util->req_buf),
			ACL_VSTRING_LEN(http_util->req_buf));
	if (ret == ACL_VSTREAM_EOF) {
		acl_msg_error("%s(%d): send request to server(%s) error(%s)",
			myname, __LINE__, http_util->server_addr,
			acl_last_serror());
		return (-1);
	}

	return (0);
}
예제 #17
0
static void notify_thread(void *arg)
{
	const char *myname = "notify_thread";
	WARN_INFO *info = (WARN_INFO*) arg;
	ACL_VSTREAM *client;
	ACL_VSTRING *buf;
	int   ret;

	buf = acl_vstring_alloc(256);
	acl_vstring_sprintf(buf, "PROC=%s|PID=%d|RCPT=%s|info=%s\r\n",
		info->path, info->pid, info->notify_recipients, info->desc);

	client = acl_vstream_connect(info->notify_addr,
		ACL_BLOCKING, 60, 60, 1024);
	if (client == NULL) {
		acl_msg_error("%s(%d): connect %s error, info(%s)", myname,
			__LINE__, info->notify_addr, acl_vstring_str(buf));
		acl_vstring_free(buf);
		warn_info_free(info);
		return;
	}

	/* 禁止将该句柄传递给子进程 */
	acl_close_on_exec(ACL_VSTREAM_SOCK(client), ACL_CLOSE_ON_EXEC);

	ret = acl_vstream_writen(client, acl_vstring_str(buf),
		ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF)
		acl_msg_error("%s(%d): write to notify server error, info(%s)",
			myname, __LINE__, acl_vstring_str(buf));
	else
		acl_msg_info("%s(%d): notify ok!", myname, __LINE__);

	acl_vstream_close(client);
	acl_vstring_free(buf);
	warn_info_free(info);
}
예제 #18
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);
}
예제 #19
0
파일: main.c 프로젝트: 1514louluo/acl
static void test_string(ACL_FILE_HANDLE fd, ssize_t max, int debug)
{
	ACL_VSTRING *vp = acl_vstring_mmap_alloc(fd, 1, max);
	const char *s = "hello world!";

	printf("-------------------------------------------------------\r\n");
	incr_string(vp, max - 1, NULL, debug);

	printf("-------------------------------------------------------\r\n");
	incr_string(vp, max - 1 - strlen(s), s, debug);

	printf("-------------------------------------------------------\r\n");
	incr_string(vp, max, NULL, debug);

	printf("-------------------------------------------------------\r\n");
	incr_string(vp, max + 2, NULL, debug);

	printf("-------------------------------------------------------\r\n");
	acl_vstring_strcat(vp, s);
	incr_string(vp, max - strlen(s) - 1, NULL, debug);

	printf("-------------------------------------------------------\r\n");
	acl_vstring_strcat(vp, s);
	incr_string(vp, max, NULL, debug);

	printf("-------------------------------------------------------\r\n");
	acl_vstring_strcat(vp, s);
	incr_string(vp, max + 10, NULL, debug);

	printf(">>>[%s]\r\n", acl_vstring_str(vp));
	printf(">>>len: %ld, %ld, %p, %p\r\n",
		(long) strlen(acl_vstring_str(vp)),
		(long) ACL_VSTRING_LEN(vp),
		acl_vstring_str(vp), acl_vstring_end(vp));
	acl_vstring_free(vp);
}
예제 #20
0
파일: sms_notify.c 프로젝트: 1514louluo/acl
static int sms_send(ACL_VSTREAM *client, const char *phone, const char *proc,
	int pid, const char *info, const char *ip)
{
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	ACL_XML *xml = acl_xml_alloc();
	char  res[1024];
	int   ret;

	acl_vstring_sprintf(buf, "<send_sms phone=\"%s\" message=\"proc:%s, pid:%d, ip:%s, info:%s\" />",
			phone, proc, pid, ip, info);
	if (acl_vstream_writen(client, acl_vstring_str(buf), ACL_VSTRING_LEN(buf))
		== ACL_VSTREAM_EOF)
	{
		acl_msg_error("write to sms server error, msg: %s",
			acl_vstring_str(buf));
		acl_vstring_free(buf);
		return (-1);
	}

	acl_msg_info(">>send: %s", acl_vstring_str(buf));
	acl_vstring_free(buf);

	while (1) {
		ret = acl_vstream_read(client, res, sizeof(res) - 1);
		if (ret == ACL_VSTREAM_EOF)
			return (-1);
		res[ret] = 0;
		acl_xml_parse(xml, res);
		if (acl_xml_is_complete(xml, "send_sms")) {
			acl_msg_info("send ok!(%s)", res);
			break;
		}
	}

	return (0);
}
예제 #21
0
void *CHttpClient::DoRequestThread(void* arg)
{
	CHttpClient *phClient = (CHttpClient*) arg;
	HTTP_HDR_REQ *hdr_req = NULL;
	HTTP_HDR_RES *hdr_res = NULL;
	HTTP_RES *http_res = NULL;
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	ACL_VSTREAM *server = NULL;
	const char *pHost = NULL;
	ACL_VSTREAM *fp = NULL;
	int   ret;
	UINT  nForward = 0;
	time_t begin = 0;
	struct timeval begin_tv, end_tv;
	double time_cost = 0;

#undef RETURN
#define RETURN(_x_) do  \
{  \
	if (hdr_req)  \
		http_hdr_req_free(hdr_req);  \
	if (buf)  \
		acl_vstring_free(buf);  \
	if (hdr_res)  \
		http_hdr_res_free(hdr_res);  \
	if (http_res) {  \
		http_res->hdr_res = NULL;  \
		http_res_free(http_res);  \
	}  \
	if (server)  \
		acl_vstream_close(server);  \
	if (fp)  \
		acl_vstream_close(fp);  \
	gettimeofday(&end_tv, NULL); \
	time_cost = stamp_sub(&end_tv, &begin_tv); \
	if (time_cost >= 0) \
		phClient->ReportTime(time_cost); \
	phClient->ReportComplete(); \
	return (_x_);  \
} while(0)

	const char *pUrl = phClient->m_sReqUrl.GetString();
	hdr_req = http_hdr_req_create(pUrl, phClient->m_bPostMethod ? "POST" : "GET",
		phClient->m_bHttp11 ? "HTTP/1.1" : "HTTP/1.0");
	ASSERT(hdr_req);

	if (phClient->m_bZip)
		http_hdr_put_str(&hdr_req->hdr, "Accept-Encoding", "gzip, deflate");
	if (phClient->m_bKeepAlive)
		http_hdr_entry_replace(&hdr_req->hdr, "Connection", "Keep-Alive", 1);
	if (phClient->m_bPostMethod)
		http_hdr_put_int(&hdr_req->hdr, "Content-Length",
			(int) phClient->m_sHttpBody.GetLength());
	if (!phClient->m_sAccept.IsEmpty())
		http_hdr_put_str(&hdr_req->hdr, "Accept", phClient->m_sAccept.GetString());
	if (!phClient->m_sCtype.IsEmpty())
		http_hdr_put_str(&hdr_req->hdr, "Content-Type", phClient->m_sCtype.GetString());

	if (phClient->m_sHttpHdrAppend.GetLength() > 0) {
		ACL_ARGV *argv;
		HTTP_HDR_ENTRY *entry;
		int   i;
		
		argv = acl_argv_split(phClient->m_sHttpHdrAppend.GetString(), "\r\n");
		for (i = 0; i < argv->argc; i++) {
			entry = http_hdr_entry_new(argv->argv[i]);
			if (entry == NULL)
				continue;
			http_hdr_append_entry(&hdr_req->hdr, entry);
		}
		acl_argv_free(argv);
	}

FORWARD:

	http_hdr_build_request(hdr_req, buf);
	pHost = http_hdr_req_host(hdr_req);
	ASSERT(pHost);

	phClient->ReportReqHdr(acl_vstring_str(buf), (int) ACL_VSTRING_LEN(buf));

	CString serverAddr;

	if (phClient->m_bUseAddr)
		serverAddr.Format("%s", phClient->m_sServerAddr);
	if (serverAddr.GetLength() == 0)
		serverAddr.Format("%s", pHost);
	if (strchr(serverAddr.GetString(), ':') == NULL)
		serverAddr.AppendFormat(":80");

	time(&begin);
	gettimeofday(&begin_tv, NULL);
	server = acl_vstream_connect(serverAddr.GetString(),
				ACL_BLOCKING, 10, 10, 4096);
	if (server == NULL) {
		CString msg;

		msg.Format("Connect server(%s) error", serverAddr.GetString());
		phClient->ReportErrConnect(msg.GetString());
		RETURN (NULL);
	}

	if (phClient->m_bLocalSave && fp == NULL) {
		fp = acl_vstream_fopen(phClient->m_sLocalFile.GetString(),
			O_WRONLY | O_CREAT | O_TRUNC, 0600, 4096);
		if (fp == NULL) {
			acl_msg_error("%s(%d): can't create file(%s)",
				__FILE__, __LINE__, phClient->m_sLocalFile.GetString());
			RETURN (NULL);
		}
	}

	ret = acl_vstream_writen(server, acl_vstring_str(buf), ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF) {
		acl_msg_error("%s(%d): write error", __FILE__, __LINE__);
		RETURN (NULL);
	}

	if (phClient->m_bPostMethod && !phClient->m_sHttpBody.IsEmpty())
	{
		if (acl_vstream_writen(server, phClient->m_sHttpBody.GetString(),
			phClient->m_sHttpBody.GetLength()) == ACL_VSTREAM_EOF)
		{
			acl_msg_error("%s(%d): write body error", __FILE__, __LINE__);
			RETURN (NULL);
		}
	}

	hdr_res = http_hdr_res_new();
	if (http_hdr_res_get_sync(hdr_res, server, 10) < 0) {
		acl_msg_error("%s(%d): get res hdr error", __FILE__, __FILE__, __LINE__);
		RETURN (NULL);
	}

	if (http_hdr_res_parse(hdr_res) < 0) {
		acl_msg_error("%s(%d): parse hdr_res error", __FILE__, __LINE__);
		RETURN (NULL);
	}

	http_hdr_build(&hdr_res->hdr, buf);
	phClient->ReportResHdr(acl_vstring_str(buf), (int) ACL_VSTRING_LEN(buf));
	phClient->ReportResContentLength((int) hdr_res->hdr.content_length);

	if (hdr_res->reply_status > 300	&& hdr_res->reply_status < 400) {
		const char* pLocation;
		HTTP_HDR_REQ *hdr_req_tmp;

		if (!phClient->m_bForwardAuto)
			RETURN (NULL);

		if (nForward++ >= phClient->m_nMaxTry) {
			acl_msg_error("%s(%d): too many redirect, nForward(%d)",
				__FILE__, __LINE__, nForward);
			RETURN (NULL);
		}

		pLocation = http_hdr_entry_value(&hdr_res->hdr, "Location");
		if (pLocation == NULL || *pLocation == 0) {
			acl_msg_error("%s(%d): 302 reply with no Location", __FILE__, __LINE__);
			RETURN (NULL);
		}

		hdr_req_tmp = http_hdr_req_rewrite(hdr_req, pLocation);
		if (hdr_req_tmp == NULL)
			RETURN (NULL);
		http_hdr_req_free(hdr_req);
		http_hdr_res_free(hdr_res);
		hdr_req = hdr_req_tmp;
		goto FORWARD;
	}

	http_res = http_res_new(hdr_res);
	while (1) {
		char  tmp_buf[4096];

		ret = (int) http_res_body_get_sync2(http_res, server,
				tmp_buf, sizeof(tmp_buf) - 1);
		if (ret <= 0)
			break;

		phClient->ReportResBody(tmp_buf, ret);
		phClient->ReportResDownLength((int)(time(NULL) - begin), ret);

		if (fp != NULL && acl_vstream_writen(fp, tmp_buf, ret) == ACL_VSTREAM_EOF) {
			acl_msg_error("%s(%d): write to file error", __FILE__, __LINE__);
			break;
		}
	}
	RETURN (NULL);
}
예제 #22
0
파일: main.c 프로젝트: 1514louluo/acl
#include <stdio.h>
#include <stdlib.h>

static char *html = \
"<html>\r\n"
"<head> <title> 'hello world!' </title> </head>\r\n"
"<body> \"hello && world!\" </body>\r\n"
"</html>\r\n";

int main(int argc acl_unused, char *argv[] acl_unused)
{
	ACL_VSTRING *buf1 = acl_vstring_alloc(32);
	ACL_VSTRING *buf2 = acl_vstring_alloc(32);

	acl_xml_encode(html, buf1);
	printf(">>> xml encode: len(%d)\n%s",(int) ACL_VSTRING_LEN(buf1), acl_vstring_str(buf1));

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

	acl_xml_decode(acl_vstring_str(buf1), buf2);
	printf(">>> xml decode: len(%d)\n%s", (int) ACL_VSTRING_LEN(buf2), acl_vstring_str(buf2));

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

	ACL_VSTRING_RESET(buf1);
	ACL_VSTRING_RESET(buf2);

	acl_html_encode(html, buf1);
	printf(">>> html encode: len(%d)\n%s", (int) ACL_VSTRING_LEN(buf1), acl_vstring_str(buf1));

	printf("------------------------------------------\n");
예제 #23
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);
}
예제 #24
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);
}
예제 #25
0
파일: service_ipc.c 프로젝트: 10jschen/acl
static ACL_MSGIO *__ipc_listener = NULL;
static char __ipc_addr[256];
static module_service_main_fn __service_callback = NULL;

/* 某个线程服务实例接收到一个新的远程客户端连接请求 */

static int msg_ipc_accept(int msg_type acl_unused, ACL_MSGIO *mio acl_unused,
        const ACL_MSGIO_INFO *info, void *arg)
{
	IPC_CTX ctx;
	ACL_VSTREAM *stream;
	ACL_ASTREAM *client;
	SERVICE *service = (SERVICE*) arg;

	memcpy(&ctx, acl_vstring_str(info->body.buf), ACL_VSTRING_LEN(info->body.buf));

	/* 打开异步流 */
	stream = acl_vstream_fdopen(ctx.fd, O_RDWR, var_cfg_aio_buf_size,
			0, ACL_VSTREAM_TYPE_SOCK);
	client = acl_aio_open(ctx.aio, stream);

	/* 开始处理该客户端连接 */
	__service_callback(service, client);
	return (0);
}

/* 单线程实例非阻塞处理过程 */

static void *service_thread(void *arg)
{
예제 #26
0
파일: main.c 프로젝트: 1514louluo/acl
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 请求头对象 */
}
예제 #27
0
파일: mac_parse.c 프로젝트: 1514louluo/acl
int     mac_parse(const char *value, MAC_PARSE_FN action, char *context)
{
    const char *myname = "mac_parse";
    ACL_VSTRING *buf = acl_vstring_alloc(1);	/* result buffer */
    const char *vp;			/* value pointer */
    const char *pp;			/* open_paren pointer */
    const char *ep;			/* string end pointer */
    static char open_paren[] = "({";
    static char close_paren[] = ")}";
    int     level;
    int     status = 0;

#define SKIP(start, var, cond) \
        for (var = start; *var && (cond); var++);

    acl_debug(DEBUG_MAC, 2) ("%s: %s", myname, value);

    for (vp = value; *vp;) {
	if (*vp != '$') {			/* ordinary character */
	    ACL_VSTRING_ADDCH(buf, *vp);
	    vp += 1;
	} else if (vp[1] == '$') {		/* $$ becomes $ */
	    ACL_VSTRING_ADDCH(buf, *vp);
	    vp += 2;
	} else {				/* found bare $ */
	    if (ACL_VSTRING_LEN(buf) > 0)
		MAC_PARSE_ACTION(status, MAC_PARSE_LITERAL, buf, context);
	    vp += 1;
	    pp = open_paren;
	    if (*vp == *pp || *vp == *++pp) {	/* ${x} or $(x) */
		level = 1;
		vp += 1;
		for (ep = vp; level > 0; ep++) {
		    if (*ep == 0) {
			acl_msg_warn("truncated macro reference: \"%s\"", value);
			status |= MAC_PARSE_ERROR;
			break;
		    }
		    if (*ep == *pp)
			level++;
		    if (*ep == close_paren[pp - open_paren])
			level--;
		}
		if (status & MAC_PARSE_ERROR)
		    break;
		acl_vstring_strncat(buf, vp, level > 0 ? ep - vp : ep - vp - 1);
		vp = ep;
	    } else {				/* plain $x */
		SKIP(vp, ep, ACL_ISALNUM(*ep) || *ep == '_');
		acl_vstring_strncat(buf, vp, ep - vp);
		vp = ep;
	    }
	    if (ACL_VSTRING_LEN(buf) == 0) {
		status |= MAC_PARSE_ERROR;
		acl_msg_warn("empty macro name: \"%s\"", value);
		break;
	    }
	    MAC_PARSE_ACTION(status, MAC_PARSE_EXPR, buf, context);
	}
    }
    if (ACL_VSTRING_LEN(buf) > 0 && (status & MAC_PARSE_ERROR) == 0)
	MAC_PARSE_ACTION(status, MAC_PARSE_LITERAL, buf, context);

    /*
     * Cleanup.
     */
    acl_vstring_free(buf);

    return (status);
}
예제 #28
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;
}
예제 #29
0
파일: mac_expand.c 프로젝트: 1514louluo/acl
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);
}