Example #1
0
bool http_header::build_response(string& out) const
{
	out.clear();

	if (status_ > 0)
	{
		if (cgi_mode_)
			out.format("STATUS: %d\r\n", status_);
		else
		{
			out = "HTTP/1.1 ";
			out << status_ << " " << http_status(status_) << "\r\n";

			time_t now = time(NULL);
			char buf[64];
			date_format(buf, sizeof(buf), now);
			out << "Date: " << buf << "\r\n";
			out << "Server: acl\r\n";
		}
	}

	if (!cookies_.empty())
	{
		std::list<HttpCookie*>::const_iterator it = cookies_.begin();
		for (; it != cookies_.end(); ++it)
		{
			out.format_append("Set-Cookie: %s=%s",
				(*it)->getName(), (*it)->getValue());
			const std::list<HTTP_PARAM*>& params = (*it)->getParams();
			std::list<HTTP_PARAM*>::const_iterator cit = params.begin();
			for (; cit != params.end(); ++ cit)
			{
				out.format_append("; %s=%s",
					(*cit)->name, (*cit)->value);
			}
			out << "\r\n";
		}
	}

	// 添加分段响应字段
	if (range_from_ >= 0 && range_to_ >= range_from_ && range_total_ > 0)
		out << "Content-Range: bytes=" << range_from_ << '-'
			<< range_to_ << '/' << range_total_ << "\r\n";

	// 如果是 gzip 压缩数据,当非 chunked 传输时,必须取消 Content-Length 字段,
	// 同时禁止保持长连接,即: Connection: close
	if (transfer_gzip_)
	{
		out << "Content-Encoding: gzip\r\n";

		if (!chunked_transfer_ && keep_alive_)
			const_cast<http_header*>(this)->keep_alive_ = false;
		if (content_length_ > 0)
			const_cast<http_header*>(this)->content_length_ = -1;
	}

	build_common(out);
	out << "\r\n";
	return true;
}
Example #2
0
bool mail_body::build(const char* in, size_t len, string& out) const
{
	out.format_append("Content-Type: %s;\r\n", content_type_.c_str());
	out.format_append("\tcharset=\"%s\"\r\n", charset_.c_str());
	out.format_append("Content-Transfer-Encoding: %s\r\n\r\n",
		transfer_encoding_.c_str());
	coder_->encode_update(in, (int) len, &out);
	coder_->encode_finish(&out);
	return true;
}
Example #3
0
static void append_recipients(string& out, const char* tagname,
	const std::list<char*>& recipients)
{
	if (recipients.empty())
		return;
	std::list<char*>::const_iterator cit = recipients.begin();
	out.format_append("%s: %s", tagname, *cit);
	++cit;
	if (cit == recipients.end())
	{
		out.append("\r\n");
		return;
	}
	for (; cit != recipients.end(); ++cit)
		out.format_append(",\r\n %s", *cit);
	out.append("\r\n");
}
Example #4
0
void mail_attach::build_header(const char* transfer_encoding, string& out)
{
	out.format_append("Content-Type: %s;\r\n", ctype_.c_str());
	out.format_append("\tname=\"%s\"\r\n", filename_.c_str());

	if (transfer_encoding && *transfer_encoding)
		out.format_append("Content-Transfer-Encoding: %s\r\n",
			transfer_encoding);

	if (cid_.empty())
		out.format_append("Content-Disposition: attachment;\r\n"
			"\tfilename=\"%s\"\r\n", filename_.c_str());
	else
		out.format_append("Content-ID: <%s>\r\n", cid_.c_str());

	out.append("\r\n");
}
Example #5
0
bool mail_body::save_relative(const char* html, size_t hlen,
	const char* text, size_t tlen,
	const std::vector<mail_attach*>& attachments,
	string& out) const
{
	if (!html || !hlen || !text || !tlen || attachments.empty())
	{
		logger_error("invalid input!");
		return false;
	}

	mail_message::create_boundary("0002",
		const_cast<mail_body*>(this)->boundary_);
	string ctype;
	ctype.format("multipart/relative;\r\n"
		"\ttype=\"multipart/alternative\";\r\n"
		"\tboundary=\"%s\"", boundary_.c_str());
	const_cast<mail_body*>(this)->set_content_type(ctype);

	out.format_append("Content-Type: %s\r\n\r\n", content_type_.c_str());
	out.append("\r\n");
	out.format_append("--%s\r\n", boundary_.c_str());

	// 递归一层,调用生成 alternative 格式数据
	mail_body body(charset_.c_str(), transfer_encoding_.c_str());
	bool ret = body.save_alternative(html, hlen, text, tlen, out);
	if (ret == false)
		return ret;

	out.append("\r\n");

	std::vector<mail_attach*>::const_iterator cit;
	for (cit = attachments.begin(); cit != attachments.end(); ++cit)
	{
		out.format_append("--%s\r\n", boundary_.c_str());
		if ((*cit)->save_to(coder_, out) == false)
			return false;
		out.append("\r\n");
	}

	out.format_append("\r\n--%s--\r\n", boundary_.c_str());

	return true;
}
Example #6
0
bool http_header::build_response(string& out) const
{
	out.clear();

	if (status_ > 0)
	{
		if (cgi_mode_)
			out.format("STATUS: %d\r\n", status_);
		else
		{
			out = "HTTP/1.1 ";
			out << status_ << " " << http_status(status_) << "\r\n";

			time_t now = time(NULL);
			char buf[64];
			date_format(buf, sizeof(buf), now);
			out << "Date: " << buf << "\r\n";
		}
	}

	if (!cookies_.empty())
	{
		std::list<HttpCookie*>::const_iterator it = cookies_.begin();
		for (; it != cookies_.end(); ++it)
		{
			out.format_append("Set-Cookie: %s=%s",
				(*it)->getName(), (*it)->getValue());
			const std::list<HTTP_PARAM*>& params = (*it)->getParams();
			std::list<HTTP_PARAM*>::const_iterator cit = params.begin();
			for (; cit != params.end(); ++ cit)
			{
				out.format_append("; %s=%s",
					(*cit)->name, (*cit)->value);
			}
			out << "\r\n";
		}
	}

	build_common(out);
	out << "\r\n";
	return true;
}
Example #7
0
bool mail_body::save_alternative(const char* html, size_t hlen,
	const char* text, size_t tlen, string& out) const
{
	if (!html || !hlen || !text || !tlen)
	{
		logger_error("invalid input!");
		return false;
	}

	mail_message::create_boundary("0003",
		const_cast<mail_body*>(this)->boundary_);
	string ctype;
	ctype.format("multipart/alternative;\r\n"
		"\tboundary=\"%s\"", boundary_.c_str());
	const_cast<mail_body*>(this)->set_content_type(ctype);

	out.format_append("Content-Type: %s\r\n\r\n", content_type_.c_str());
	out.format_append("--%s\r\n", boundary_.c_str());
	out.format_append("Content-Type: text/plain;\r\n");
	out.format_append("\tcharset=\"%s\"\r\n", charset_.c_str());
	out.format_append("Content-Transfer-Encoding: %s\r\n\r\n",
		transfer_encoding_.c_str());
	coder_->encode_update(text, (int) tlen, &out);
	coder_->encode_finish(&out);
	out.append("\r\n\r\n");

	out.format_append("--%s\r\n", boundary_.c_str());
	out.format_append("Content-Type: text/html;\r\n");
	out.format_append("\tcharset=\"%s\"\r\n", charset_.c_str());
	out.format_append("Content-Transfer-Encoding: %s\r\n\r\n",
		transfer_encoding_.c_str());
	coder_->encode_update(html, (int) hlen, &out);
	coder_->encode_finish(&out);
	out.append("\r\n\r\n");

	out.format_append("--%s--\r\n", boundary_.c_str());

	return true;
}
Example #8
0
void mime_head::build_head(string& out, bool clean)
{
	if (clean)
		out.clear();
	if (m_headers)
	{
		std::list<HEADER*>::const_iterator cit = m_headers->begin();
		for (; cit != m_headers->end(); ++cit)
		{
			out.format_append("%s: %s\r\n",
				(*cit)->name, (*cit)->value);
		}
	}
	char buf[64];
	rfc822 rfc;
	rfc.mkdate_cst(time(NULL), buf, sizeof(buf));
	out.format_append("Date: %s\r\n", buf);

	if (m_from)
		out.format_append("From: %s\r\n", m_from->c_str());
	if (m_replyto)
		out.format_append("Reply-To: %s\r\n", m_replyto->c_str());
	if (m_returnpath)
		out.format_append("Return-Path: %s\r\n", m_returnpath->c_str());
	if (m_tos)
		append_recipients(out, "To", *m_tos);
	if (m_ccs)
		append_recipients(out, "Cc", *m_ccs);
	if (m_bccs)
		append_recipients(out, "Bcc", *m_bccs);
	if (m_subject)
		out.format_append("Subject: %s\r\n", m_subject->c_str());
	out.append("MIME-Version: 1.0\r\n");
	out.format_append("Content-Type: %s/%s", get_ctype(), get_stype());
	if (m_boundary)
		out.format_append(";\r\n\tboundary=\"%s\"\r\n",
			m_boundary->c_str());
	else
		out.append("\r\n");

	out.append("\r\n");
}
Example #9
0
bool query::append_key(string& buf, char* key)
{
	acl_lowercase(key);
	std::map<string, query_param*>::iterator it = params_.find(key);
	if (it == params_.end())
	{
		logger_warn("unknown key: %s", key);
		buf.append(key);
		return false;
	}

	char fmt[256];

	query_param* param = it->second;
	switch (param->type)
	{
	case DB_PARAM_CHAR:
		buf.format_append("'%c'", param->v.c);
		break;
	case DB_PARAM_SHORT:
		buf.format_append("%d", param->v.s);
		break;
	case DB_PARAM_INT32:
		buf.format_append("%d", param->v.n);
		break;
	case DB_PARAM_INT64:
		buf.format_append("%lld", param->v.l);
		break;
	case DB_PARAM_STR:
		buf.format_append("'%s'",
			escape(param->v.S, param->dlen, buf_).c_str());
		break;
	case DB_PARAM_FLOAT:
		safe_snprintf(fmt, sizeof(fmt), "%%.%df", param->precision);
		buf.format_append(fmt, param->v.f);
		break;
	case DB_PARAM_DOUBLE:
		safe_snprintf(fmt, sizeof(fmt), "%%.%df", param->precision);
		buf.format_append(fmt, param->v.d);
		break;
	default:
		logger_error("unknown type: %d", param->type);
		break;
	}

	return true;
}
Example #10
0
bool http_header::build_request(string& buf) const
{
	if (url_ == NULL || *url_ == 0)
	{
		logger_error("url empty");
		return (false);
	}

	buf.format("%s %s", method_s_, url_);

	if (!params_.empty())
	{
		buf << '?';
		acl::string tmp;
		int i = 0;
		std::list<HTTP_PARAM*>::const_iterator it = params_.begin();
		for (; it != params_.end(); ++it)
		{
			if (i > 0)
				buf += '&';
			else
				i++;

			// 需要对参数进行 URL 编码

			tmp.url_encode((*it)->name);
			buf += tmp.c_str();

			// 允许参数值为空指针
			if ((*it)->value == NULL)
				continue;

			buf += '=';

			// 允许参数值为空串
			if (*((*it)->value) == 0)
				continue;

			tmp.url_encode((*it)->value);
			buf += tmp.c_str();
		}
	}
	buf += " HTTP/1.1\r\n";
	if (accept_compress_)
		// 因为目前的 zlib_stream 仅支持于此
		buf += "Accept-Encoding: gzip\r\n";

	if (host_[0] != 0)
		buf.format_append("Host: %s\r\n", host_);

	if (!cookies_.empty())
	{
		buf += "Cookie: ";
		std::list<HttpCookie*>::const_iterator it = cookies_.begin();
		for (; it != cookies_.end(); ++it)
		{
			if (it != cookies_.begin())
				buf += "; ";
			buf << (*it)->getName() << "=" << (*it)->getValue();
		}
		buf += "\r\n";
	}

	// 添加分段请求字段
	if (range_from_ >= 0)
	{
		buf << "Range: bytes=" << range_from_ << '-';
		if (range_to_ >= range_from_)
			buf << range_to_;
		buf += "\r\n";
	}

	build_common(buf);
	buf += "\r\n";

	return (true);
}