Lighttpd逻辑篇(一):Request.c

//作者:京东瀚览家居官方旗舰店   <--点击关注

//文件名:Request.c

 

#include <sys/stat.h>

#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include "request.h"
#include "keyvalue.h"
#include "log.h"


/* 判断host 格式是否正确,正确返回0 ,否则返回-1 */
static int request_check_hostname(server *srv, connection *con, buffer *host) {
	enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
	size_t i;
	int label_len = 0;
	size_t host_len;
	char *colon;
	int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
	int level = 0;

	UNUSED(srv);
	UNUSED(con);

	/*
	 *       hostport      = host [ ":" port ]
	 *       host          = hostname | IPv4address | IPv6address
	 *       hostname      = *( domainlabel "." ) toplabel [ "." ]
	 *       domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
	 *       toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
	 *       IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
	 *       IPv6address   = "[" ... "]"
	 *       port          = *digit
	 */

	/* no Host: */
	/* 空或长度为0 , 也认为符合host 格式而返回0 */
	if (!host || host->used == 0) return 0;

	host_len = host->used - 1;

	/* IPv6 adress */
	if (host->ptr[0] == '[') {
		char *c = host->ptr + 1;
		int colon_cnt = 0;

		/* check portnumber */
		for (; *c && *c != ']'; c++) {
			if (*c == ':') {
				if (++colon_cnt > 7) {
					return -1;
				}
			} else if (!light_isxdigit(*c)) {
				return -1;
			}
		}

		/* missing ] */
		if (!*c) {
			return -1;
		}

		/* check port */
		if (*(c+1) == ':') {
			for (c += 2; *c; c++) {
				if (!light_isdigit(*c)) {
					return -1;
				}
			}
		}
		return 0;
	}

/* IP4 地址处理*/
	if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
		char *c = colon + 1;

		/* check portnumber */
		for (; *c; c++) {
			if (!light_isdigit(*c)) return -1;
		}
              /* 求得IP4 的host 实际长度*/
		/* remove the port from the host-len */
		host_len = colon - host->ptr;
	}

	/* Host is empty */
	if (host_len == 0) return -1;

	/* if the hostname ends in a "." strip it */
	if (host->ptr[host_len-1] == '.') host_len -= 1;

	/* scan from the right and skip the \0 */
	for (i = host_len - 1; i + 1 > 0; i--) {
		const char c = host->ptr[i];

		switch (stage) {
		case TOPLABEL:
			if (c == '.') {
				/* only switch stage, if this is not the last character */
				if (i != host_len - 1) {
					if (label_len == 0) {
						return -1;
					}

					/* check the first character at right of the dot */
					if (is_ip == 0) {
						if (!light_isalpha(host->ptr[i+1])) {
							return -1;
						}
					} else if (!light_isdigit(host->ptr[i+1])) {
						is_ip = 0;
					} else if ('-' == host->ptr[i+1]) {
						return -1;
					} else {
						/* just digits */
						is_ip = 1;
					}

					stage = DOMAINLABEL;

					label_len = 0;
					level++;
				} else if (i == 0) {
					/* just a dot and nothing else is evil */
					return -1;
				}
			} else if (i == 0) {
				/* the first character of the hostname */
				if (!light_isalpha(c)) {
					return -1;
				}
				label_len++;
			} else {
				if (c != '-' && !light_isalnum(c)) {
					return -1;
				}
				if (is_ip == -1) {
					if (!light_isdigit(c)) is_ip = 0;
				}
				label_len++;
			}

			break;
		case DOMAINLABEL:
			if (is_ip == 1) {
				if (c == '.') {
					if (label_len == 0) {
						return -1;
					}

					label_len = 0;
					level++;
				} else if (!light_isdigit(c)) {
					return -1;
				} else {
					label_len++;
				}
			} else {
				if (c == '.') {
					if (label_len == 0) {
						return -1;
					}

					/* c is either - or alphanum here */
					if ('-' == host->ptr[i+1]) {
						return -1;
					}

					label_len = 0;
					level++;
				} else if (i == 0) {
					if (!light_isalnum(c)) {
						return -1;
					}
					label_len++;
				} else {
					if (c != '-' && !light_isalnum(c)) {
						return -1;
					}
					label_len++;
				}
			}

			break;
		}
	}

	/* a IP has to consist of 4 parts */
	if (is_ip == 1 && level != 3) {
		return -1;
	}

	if (label_len == 0) {
		return -1;
	}

	return 0;
}

#if 0
#define DUMP_HEADER
#endif

/* 将b内保存的类似于"val1 , val2, val3, val4" 的字符串按"," 分割*/
/*  并保存到vals 数组内, 并且会去除val 前后的空格*/
int http_request_split_value(array *vals, buffer *b) {
	char *s;
	size_t i;
	int state = 0;
	/*
	 * parse
	 *
	 * val1, val2, val3, val4
	 *
	 * into a array (more or less a explode() incl. striping of whitespaces
	 */

	if (b->used == 0) return 0;

	s = b->ptr;

	for (i =0; i < b->used - 1; ) {
		char *start = NULL, *end = NULL;
		data_string *ds;

		switch (state) {
		case 0: /* ws */

			/* skip ws */
			/* 跳过开头的空白字符*/
			for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);


			state = 1;
			break;
		case 1: /* value */
			start = s;

			for (; *s != ',' && i < b->used - 1; i++, s++);
			end = s - 1; /* 删除末尾的空白字符*/

			for (; (*end == ' ' || *end == '\t') && end > start; end--);

			if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
				ds = data_string_init();
			}

			buffer_copy_string_len(ds->value, start, end-start+1);
			array_insert_unique(vals, (data_unset *)ds);

			if (*s == ',') {
				state = 0;
				i++;
				s++;
			} else {
				/* end of string */

				state = 2;
			}
			break;
		default:
			i++;
			break;
		}
	}
	return 0;
}

/* 检测c是否为合法的uri 字符*/
int request_uri_is_valid_char(unsigned char c) {
	if (c <= 32) return 0;
	if (c == 127) return 0;
	if (c == 255) return 0;

	return 1;
}

/* 解析客户端请求*/
/* 返回1 表示有后续的POST 数据到达, 就会进入CON_STATE_READ_POST 状态*/
int http_request_parse(server *srv, connection *con) {
/* 头域是由关键字( field-name)、冒号和可选值(field-value) 组成的(即message-header=field-name":"[field-value]) */
/* 这里设置is_key 用于标记区分当前处理的字符属于哪部分.*/
/* 1表示属于关键字部分, 为0表示属于field-value 部分*/
	char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
	int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
	char *value = NULL, *key = NULL;

	enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;

	int line = 0;

	int request_line_stage = 0;
	size_t i, first;

	int done = 0;

	/*
	 * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值