Ejemplo n.º 1
0
/**
 * Fills @val with second part of special HTTP header containing the header
 * value.
 */
void
tfw_http_msg_hdr_val(TfwStr *hdr, unsigned id, TfwStr *val)
{
	static const size_t hdr_lens[] = {
		[TFW_HTTP_HDR_HOST]	= sizeof("Host:") - 1,
		[TFW_HTTP_HDR_CONTENT_LENGTH] = sizeof("Content-Length:") - 1,
		[TFW_HTTP_HDR_CONTENT_TYPE] = sizeof("Content-Type:") - 1,
		[TFW_HTTP_HDR_CONNECTION] = sizeof("Connection:") - 1,
		[TFW_HTTP_HDR_X_FORWARDED_FOR] = sizeof("X-Forwarded-For:") - 1,
		[TFW_HTTP_HDR_USER_AGENT] = sizeof("User-Agent:") - 1,
		[TFW_HTTP_HDR_COOKIE] = sizeof("Cookie:") - 1,
	};

	TfwStr *c, *end;
	int nlen = hdr_lens[id];

	BUG_ON(TFW_STR_DUP(hdr));
	BUG_ON(id >= TFW_HTTP_HDR_RAW);

	/* Only Host: header is allowed to be empty
	 * If header string is plain, it is always empty header.
	 * Not empty headers are compount strings. */
	BUG_ON(id == TFW_HTTP_HDR_HOST ? (nlen > hdr->len) :
		(nlen >= hdr->len || TFW_STR_PLAIN(hdr)));

	*val = *hdr;

	/* Field value, if it exist, lies in the separate chunk.
	 * So we skip several first chunks, containing field name,
	 * to get the field value. If we have field with empty value,
	 * we get an empty string with val->len = 0 and val->ptr from the
	 * last name's chunk, but it is unimportant.
	 */
	TFW_STR_FOR_EACH_CHUNK(c, hdr, end) {
		BUG_ON(!c->len);

		if (nlen > 0) {
			nlen -= c->len;
			val->len -= c->len;
		}
		else if (unlikely(((char *)c->ptr)[0] == ' '
				  || ((char *)c->ptr)[0] == '\t'))
		{
			/*
			 * RFC 7230: skip OWS before header field.
			 * In most cases OWS is on the same chunk with
			 * the header name.
			 * Header field-value always begins at new chunk.
			 */
			val->len -= c->len;
		}
		else {
			break;
		}
		TFW_STR_CHUNKN_SUB(val, 1);
	}
Ejemplo n.º 2
0
/**
 * Fills @val with second part of specula HTTP header containing the header
 * value.
 */
void
tfw_http_msg_hdr_val(TfwStr *hdr, int id, TfwStr *val)
{
	static const size_t hdr_lens[] = {
		[TFW_HTTP_HDR_HOST]	= sizeof("Host:") - 1,
		[TFW_HTTP_HDR_CONTENT_LENGTH] = sizeof("Content-Length:") - 1,
		[TFW_HTTP_HDR_CONNECTION] = sizeof("Connection:") - 1,
		[TFW_HTTP_HDR_X_FORWARDED_FOR] = sizeof("X-Forwarded-For:") - 1,
	};

	TfwStr *c;
	int nlen = hdr_lens[id];

	BUG_ON(TFW_STR_PLAIN(hdr));
	BUG_ON(TFW_STR_DUP(hdr));
	BUG_ON(nlen >= hdr->len);
	BUG_ON(id >= TFW_HTTP_HDR_RAW);

	*val = *hdr;
	val->len -= nlen;

	TFW_STR_FOR_EACH_CHUNK(c, hdr, {
		BUG_ON(!c->len);
		BUG_ON(c->len >= val->len);

		if (nlen > 0) {
			nlen -= val->len;
		}
		else if (unlikely(((char *)c->ptr)[0] == ' '
				  || ((char *)c->ptr)[0] == '\t'))
		{
			/*
			 * RFC 7230: skip OWS before header field.
			 * In most cases OWS is on the same chunk with
			 * the header name.
			 * Header field always begins at new chunk.
			 */
			val->len -= c->len;
		}
		else {
			break;
		}
		TFW_STR_CHUNKN_SUB(val, 1);
	});
Ejemplo n.º 3
0
void
tfw_str_del_chunk(TfwStr *str, int id)
{
	unsigned int cn = TFW_STR_CHUNKN(str);

	if (unlikely(TFW_STR_PLAIN(str)))
		return;
	BUG_ON(TFW_STR_DUP(str));
	BUG_ON(id >= cn);

	if (TFW_STR_CHUNKN(str) == 2) {
		/* Just fall back to plain string. */
		*str = *((TfwStr *)str->ptr + (id ^ 1));
		return;
	}

	str->len -= TFW_STR_CHUNK(str, id)->len;
	TFW_STR_CHUNKN_SUB(str, 1);
	/* Move all chunks after @id. */
	memmove((TfwStr *)str->ptr + id, (TfwStr *)str->ptr + id + 1,
		(cn - id - 1) * sizeof(TfwStr));
}