/** 
 * @brief Get token in a string separated by a delimiter (Single Char)
 * 	Spec ref R[15.1]
 * 
 * @param pp_token 
 * @param token_len
 * @param input_string
 * @param input_str_len
 * @param delim_char
 * @param next_ptr
 * 
 * @return 
 */
static inline rtsp_error_t rtsp_get_token(const char **pp_token, int32_t *token_len, const char *input_string, int32_t input_str_len,  char delim_char, const char **next_ptr){
	/* 
	 * TODO - $EN - delim_char can be changed to an array of characters which may be delimiters for a token
	 */

	int32_t scan_index = 0;
	rtsp_error_t e_ret_val = RTSP_E_FAILURE;
	if(!pp_token || !token_len || !input_string || input_str_len<=0){
		return (RTSP_E_INVALID_ARG);
	}

	while(scan_index < input_str_len){
		if(input_string[scan_index] == delim_char){
			/* Token end reached 
			 * Calling function has to ensure reliable delim_char as per spec
			 * */
			*pp_token = input_string;
			*token_len = scan_index+1;
			if (next_ptr)
				*next_ptr = &input_string[scan_index+1];
			e_ret_val = RTSP_E_SUCCESS;
			break;
		} else if(iscntrl(input_string[scan_index]) || is_tspecial(input_string[scan_index])){
			/* 
	 		 * Validates Token as per R[15.1]
	 		 */
			e_ret_val = RTSP_E_FAILURE;
			break;
		} else {
			scan_index++;
		}
	}

	return (e_ret_val);
}
Exemplo n.º 2
0
boost::tribool& RequestParser::consume(Request& req, Buffer::iterator it)
{
  static boost::tribool False(false);
  static boost::tribool True(true);
  static boost::tribool Indeterminate(boost::indeterminate);

  const char input = *it;

  if (++requestSize_ > MAX_REQUEST_HEADER_SIZE)
    return False;

  switch (httpState_)
  {
  case method_start:
    if (input == '\r')
    {
      /*
       * allow a new line before a request -- this seems to be
       * accepted practice when dealing with multiple requests
       * in one connection, separated by a CRLF.
       */
      httpState_ = expecting_newline_0;
      return Indeterminate;
    } else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      httpState_ = method;
      consumeToString(req.method, MAX_METHOD_SIZE);
      consumeChar(it);
      return Indeterminate;
    }
  case expecting_newline_0:
    if (input == '\n')
    {
      httpState_ = method_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case method:
    if (input == ' ')
    {
      consumeComplete(it);
      httpState_ = uri_start;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(it))
	return Indeterminate;
      else
	return False;
    }
  case uri_start:
    if (is_ctl(input))
    {
      return False;
    }
    else
    {
      httpState_ = uri;
      consumeToString(req.uri, MAX_URI_SIZE);
      consumeChar(it);
      return Indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      consumeComplete(it);

      httpState_ = http_version_h;
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(it))
	return Indeterminate;
      else
	return False;
    }
  case http_version_h:
    if (input == 'H')
    {
      httpState_ = http_version_t_1;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      httpState_ = http_version_t_2;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      httpState_ = http_version_p;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_p:
    if (input == 'P')
    {
      httpState_ = http_version_slash;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      httpState_ = http_version_major_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      httpState_ = http_version_major;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_major:
    if (input == '.')
    {
      httpState_ = http_version_minor_start;
      return Indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      httpState_ = http_version_minor;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_minor:
    if (input == '\r')
    {
      httpState_ = expecting_newline_1;
      return Indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      httpState_ = header_line_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case header_line_start:
    if (input == '\r')
    {
      httpState_ = expecting_newline_3;
      return Indeterminate;
    }
    else if ((input == ' ' || input == '\t') && haveHeader_)
    {
      // continuation of previous header
      httpState_ = header_lws;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      req.headers.push_back(Request::Header());
      haveHeader_ = true;
      consumeToString(req.headers.back().name, MAX_FIELD_NAME_SIZE);
      consumeChar(it);
      httpState_ = header_name;
      return Indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      httpState_ = expecting_newline_2;
      return Indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      httpState_ = header_value;
      consumeChar(it);
      return Indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      consumeComplete(it);
      httpState_ = space_before_header_value;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(it))
	return Indeterminate;
      else
	return False;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      consumeToString(req.headers.back().value, MAX_FIELD_VALUE_SIZE);
      httpState_ = header_value;

      return Indeterminate;
    }
    else
    {
      consumeToString(req.headers.back().value, MAX_FIELD_VALUE_SIZE);
      httpState_ = header_value;

      /* fall through */
    }
  case header_value:
    if (input == '\r')
    {
      consumeComplete(it);

      httpState_ = expecting_newline_2;
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(it))
	return Indeterminate;
      else
	return False;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      httpState_ = header_line_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case expecting_newline_3:
    if (input == '\n')
      return True;
    else
      return False;
  default:
    return False;
  }
}
Exemplo n.º 3
0
		bool parse_http_headers(Iterator begin, Iterator end, std::string& content_type, std::size_t& content_length, std::string& location)
		{
			enum
			{
				first_header_line_start,
				header_line_start,
				header_lws,
				header_name,
				space_before_header_value,
				header_value,
				linefeed,
				final_linefeed,
				fail
			} state = first_header_line_start;

			Iterator iter = begin;
			std::string reason;
			std::string name;
			std::string value;
			while (iter != end && state != fail)
			{
				char c = *iter++;
				switch (state)
				{
				case first_header_line_start:
					if (c == '\r')
						state = final_linefeed;
					else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
						state = fail;
					else
					{
						name.push_back(c);
						state = header_name;
					}
					break;
				case header_line_start:
					if (c == '\r')
					{
						check_header(name, value, content_type, content_length, location);
						name.clear();
						value.clear();
						state = final_linefeed;
					}
					else if (c == ' ' || c == '\t')
						state = header_lws;
					else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
						state = fail;
					else
					{
						check_header(name, value, content_type, content_length, location);
						name.clear();
						value.clear();
						name.push_back(c);
						state = header_name;
					}
					break;
				case header_lws:
					if (c == '\r')
						state = linefeed;
					else if (c == ' ' || c == '\t')
						; // Discard character.
					else if (is_ctl(c))
						state = fail;
					else
					{
						state = header_value;
						value.push_back(c);
					}
					break;
				case header_name:
					if (c == ':')
						state = space_before_header_value;
					else if (!is_char(c) || is_ctl(c) || is_tspecial(c))
						state = fail;
					else
						name.push_back(c);
					break;
				case space_before_header_value:
					state = (c == ' ') ? header_value : fail;
					break;
				case header_value:
					if (c == '\r')
						state = linefeed;
					else if (is_ctl(c))
						state = fail;
					else
						value.push_back(c);
					break;
				case linefeed:
					state = (c == '\n') ? header_line_start : fail;
					break;
				case final_linefeed:
					return (c == '\n');
				default:
					return false;
				}
			}
			return false;
		}
Exemplo n.º 4
0
		/// Handle the next character of input.
		result_type consume(char input)
		{
			switch (state_)
			{
			case METHOD_START:
				if (!is_char(input) || is_ctl(input) || is_tspecial(input))
				{
					return bad;
				}
				else
				{
					state_ = METHOD;
					method_.push_back(input);
					return indeterminate;
				}
			case METHOD:
				if (input == ' ')
				{
					state_ = URI;
					return indeterminate;
				}
				else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
				{
					return bad;
				}
				else
				{
					method_.push_back(input);
					return indeterminate;
				}
			case URI:
				if (input == ' ')
				{
					state_ = HTTP_VERSION_H;
					return indeterminate;
				}
				else if (is_ctl(input))
				{
					return bad;
				}
				else
				{
					url_.push_back(input);
					return indeterminate;
				}
			case HTTP_VERSION_H:
				if (input == 'H')
				{
					state_ = HTTP_VERSUIN_T_1;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSUIN_T_1:
				if (input == 'T')
				{
					state_ = HTTP_VERSION_T_2;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_T_2:
				if (input == 'T')
				{
					state_ = HTTP_VERSION_P;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_P:
				if (input == 'P')
				{
					state_ = HTTP_VERSION_SLASH;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_SLASH:
				if (input == '/')
				{
					version_major_ = 0;
					version_minor_ = 0;
					state_ = HTTP_VERSION_MAJOR_START;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_MAJOR_START:
				if (is_digit(input))
				{
					version_major_ = version_major_ * 10 + input - '0';
					state_ = HTTP_VERSION_MAJOR;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_MAJOR:
				if (input == '.')
				{
					state_ = HTTP_VERSION_MINOR_START;
					return indeterminate;
				}
				else if (is_digit(input))
				{
					version_major_ = version_major_ * 10 + input - '0';
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_MINOR_START:
				if (is_digit(input))
				{
					version_minor_ = version_minor_ * 10 + input - '0';
					state_ = HTTP_VERSION_MINOR;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HTTP_VERSION_MINOR:
				if (input == '\r')
				{
					state_ = EXPECTING_NEWLINE_1;
					return indeterminate;
				}
				else if (is_digit(input))
				{
					version_minor_ = version_minor_ * 10 + input - '0';
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case EXPECTING_NEWLINE_1:
				if (input == '\n')
				{
					state_ = HEADER_LINE_START;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case HEADER_LINE_START:
				if (input == '\r')
				{
					state_ = EXPECTING_NEWLINE_3;
					return indeterminate;
				}
				else if (header_.size() != 0 && (input == ' ' || input == '\t'))
				{
					state_ = HEADER_LWS;
					return indeterminate;
				}
				else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
				{
					return bad;
				}
				else
				{
					current_header_key_.clear();
					current_header_val_.clear();
					current_header_key_.push_back(input);
					state_ = HEADER_NAME;
					return indeterminate;
				}
			case HEADER_LWS:
				if (input == '\r')
				{
					state_ = EXPECTING_NEWLINE_2;
					return indeterminate;
				}
				else if (input == ' ' || input == '\t')
				{
					return indeterminate;
				}
				else if (is_ctl(input))
				{
					return bad;
				}
				else
				{
					state_ = HEADER_VALUE;
					current_header_val_.push_back(input);
					return indeterminate;
				}
			case HEADER_NAME:
				if (input == ':')
				{
					state_ = SPACE_BEFORE_HEADER_VALUE;
					return indeterminate;
				}
				else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
				{
					return bad;
				}
				else
				{
					current_header_key_.push_back(input);
					return indeterminate;
				}
			case SPACE_BEFORE_HEADER_VALUE:
				if (input == ' ')
					return indeterminate;
				else if(is_ctl(input))
					return bad;
				current_header_val_.push_back(input);
				state_ = HEADER_VALUE;
				return indeterminate;
			case HEADER_VALUE:
				if (input == '\r')
				{
					auto tmp = boost::trim_right_copy_if(current_header_val_, [](const char c)->bool{return c == ' ';});
					header_.add(current_header_key_, std::move(tmp));
					state_ = EXPECTING_NEWLINE_2;
					return indeterminate;
				}
				else if (is_ctl(input))
				{
					return bad;
				}
				else
				{
					current_header_val_.push_back(input);
					return indeterminate;
				}
			case EXPECTING_NEWLINE_2:
				if (input == '\n')
				{
					state_ = HEADER_LINE_START;
					return indeterminate;
				}
				else
				{
					return bad;
				}
			case EXPECTING_NEWLINE_3:
			{
				if (input != '\n')
				{
					return bad;
				}

				if (header_.get_count("content-length") !=0 )
				{
					content_length_ = boost::lexical_cast<unsigned int>(header_.get_val("content-length"));
					if (content_length_ > 0)
					{
						state_ = REQUEST_BODY;
						return indeterminate;
					}

					return good;
				}

				content_length_ = 0;
				return good;
			}
			case REQUEST_BODY:
			{
				body_.push_back(input);
				if (body_.size() < content_length_)
				{
					return indeterminate;
				}
				else
				{
					return good;
				}
			}
			default:
				return bad;
			}
		}
Exemplo n.º 5
0
boost::tribool request_parser::consume(request& req, char input)
{
  switch (state_) {
   case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      state_ = method;
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case method:
    if (input == ' ')
    {
      state_ = uri;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      state_ = http_version_h;
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.uri.push_back(input);
      return boost::indeterminate;
    }
  case http_version_h:
    if (input == 'H')
    {
      state_ = http_version_t_1;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      state_ = http_version_t_2;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      state_ = http_version_p;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_p:
    if (input == 'P')
    {
      state_ = http_version_slash;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      state_ = http_version_major;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major:
    if (input == '.')
    {
      state_ = http_version_minor_start;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      state_ = http_version_minor;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor:
    if (input == '\r')
    {
      state_ = expecting_newline_1;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_line_start:
    if (input == '\r')
    {
      state_ = expecting_newline_3;
      return boost::indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      state_ = header_lws;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.push_back(header());
      req.headers.back().name.push_back(input);
      state_ = header_name;
      return boost::indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      state_ = space_before_header_value;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return boost::indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      state_ = header_value;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_value:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      if (req.headers.back().name == content_length_name_)
	    content_length_ = boost::lexical_cast<std::size_t>(req.headers.back().value);
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_3:
    state_ = content;
    if (content_length_ > 0)
	return boost::indeterminate;
    return (input == '\n');
  case content:
   // Content.
	  /*std::cout << state_ << std::endl;
	  std::cout << input << std::endl;
	  std::cout << req.content.size() << std::endl;
	  std::cout << content_length_ << std::endl;*/

	req.content.push_back(input);
	if (req.content.size() == content_length_)
		return true;
	return boost::indeterminate;
  default:
   return false;
  }
}
Exemplo n.º 6
0
boost::tribool request_parser::consume(request& req, char input) {
  switch (state_) {
  case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
      return false;
    } else {
      state_ = method;
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case method:
    if (input == ' ') {
      if (req.method != "POST") return false; // only POST method is allowed
      state_ = uri;
      return boost::indeterminate;
    } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
      return false;
    } else {
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case uri:
    if (input == ' ') {
      state_ = http_version_h;
      return boost::indeterminate;
    } else if (is_ctl(input) || input == '?') {
      return false;
    } else {
      req.uri.push_back(input);
      return boost::indeterminate;
    }
  case http_version_h:
    if (input == 'H') {
      state_ = http_version_t_1;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_t_1:
    if (input == 'T') {
      state_ = http_version_t_2;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_t_2:
    if (input == 'T') {
      state_ = http_version_p;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_p:
    if (input == 'P') {
      state_ = http_version_slash;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_slash:
    if (input == '/') {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_major_start:
    if (is_digit(input)) {
      req.http_version_major = input - '0';
      state_ = http_version_major;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_major:
    if (input == '.') {
      state_ = http_version_minor_start;
      return boost::indeterminate;
    } else if (is_digit(input)) {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_minor_start:
    if (is_digit(input)) {
      req.http_version_minor = input - '0';
      state_ = http_version_minor;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_minor:
    if (input == '\r') {
      state_ = expecting_newline_before_first_header;
      return boost::indeterminate;
    } else if (is_digit(input)) {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return boost::indeterminate;
    } else {
      return false;
    }
  case expecting_newline_before_first_header:
    if (input == '\n') {
      state_ = header_line_start;
      return boost::indeterminate;
    } else {
      return false;
    }
  case header_line_start:
    if (input == '\r') {
      state_ = expecting_body_start;
      return boost::indeterminate;
    } else if (!req.headers.empty() && (input == ' ' || input == '\t')) {
      state_ = header_lws;
      return boost::indeterminate;
    } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
      return false;
    } else {
      req.headers.emplace_back();
      header& h = req.headers.back();
      h.name.reserve(64);
      h.value.reserve(64);
      h.name.push_back(input);
      state_ = header_name;
      return boost::indeterminate;
    }
  case header_lws:
    if (input == '\r') {
      state_ = expecting_newline;
      return boost::indeterminate;
    } else if (input == ' ' || input == '\t') {
      return boost::indeterminate;
    } else if (is_ctl(input)) {
      return false;
    } else {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case header_name:
    if (input == ':') {
      state_ = space_before_header_value;
      return boost::indeterminate;
    } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
      return false;
    } else {
      req.headers.back().name.push_back(input);
      return boost::indeterminate;
    }
  case space_before_header_value:
    if (input == ' ') {
      state_ = header_value;
      return boost::indeterminate;
    } else {
      return false;
    }
  case header_value:
    if (input == '\r') {
      state_ = expecting_newline;
      return boost::indeterminate;
    } else if (is_ctl(input)) {
      return false;
    } else {
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case expecting_newline:
    if (input == '\n') {
      state_ = header_line_start;
      return boost::indeterminate;
    } else {
      return false;
    }
  case expecting_body_start:
    if (input == '\n') {
      state_ = expecting_json_start;
      return boost::indeterminate;
    } else {
      return false;
    }
  case expecting_json_start:
    req.body.push_back(input);
    if (input == '{') {
      ++nesting_level_;
      state_ = expecting_json_end;
    }
    return boost::indeterminate;
  case expecting_json_end:
    req.body.push_back(input);
    if (input == '{') {
      ++nesting_level_;
    } else if (input == '}') {
      --nesting_level_;
      if (!nesting_level_) return true;
    }
    return boost::indeterminate;
  default:
    return false;
  }
}
Exemplo n.º 7
0
Response::Parser::state Response::Parser::consume(Response& resp, char input) {
    switch (state_) {
    case http_version_h:
        if (input == 'H') {
            state_ = http_version_t_1;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_t_1:
        if (input == 'T') {
            state_ = http_version_t_2;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_t_2:
        if (input == 'T') {
            state_ = http_version_p;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_p:
        if (input == 'P') {
            state_ = http_version_slash;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_slash:
        if (input == '/') {
            resp.major_ = resp.minor_ = 0;
            state_ = http_version_major_start;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_major_start:
        if (is_digit(input)) {
            resp.major_ = resp.major_ * 10 + (input - '0');
            state_ = http_version_major;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_major:
        if (input == '.') {
            state_ = http_version_minor_start;
            return indeterminate;
        } else if (is_digit(input)) {
            resp.major_ = resp.major_ * 10 + (input - '0');
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_minor_start:
        if (is_digit(input)) {
            resp.minor_ = resp.minor_ * 10 + (input - '0');
            state_ = http_version_minor;
            return indeterminate;
        } else {
            return bad;
        }

    case http_version_minor:
        if (input == ' ') {
            resp.status_code_ = 0;
            state_ = http_status_code;
            return indeterminate;
        } else if (is_digit(input)) {
            resp.minor_ = resp.minor_ * 10 + (input - '0');
            return indeterminate;
        } else {
            return bad;
        }

    case http_status_code:
        if (is_digit(input)) {
            resp.status_code_ = resp.status_code_ * 10 + (input - '0');
            return indeterminate;
        } else if (input == ' ') {
            state_ = http_status_msg;
            return indeterminate;
        } else {
            return bad;
        }

    case http_status_msg:
        if (input == '\r') {
            state_ = expecting_newline_1;
            return indeterminate;
        } else if (is_char(input)) {
            resp.desc.push_back(input);
            return indeterminate;
        } else {
            return bad;
        }

    case expecting_newline_1:
        if (input == '\n') {
            state_ = header_line_start;
            return indeterminate;
        } else {
            return bad;
        }

    case header_line_start:
        if (input == '\r') {
            state_ = expecting_newline_3;
            return indeterminate;
        } else if (!resp.headers.empty() && (input == ' ' || input == '\t')) {
            state_ = header_lws;
            return indeterminate;
        } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
            return bad;
        } else {
            resp.headers.emplace_back();
            resp.headers.back().first.push_back(input);
            state_ = header_name;
            return indeterminate;
        }

    case header_lws:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return indeterminate;
        } else if (input == ' ' || input == '\t') {
            return indeterminate;
        } else if (is_ctl(input)) {
            return bad;
        } else {
            state_ = header_value;
            resp.headers.back().second.push_back(input);
            return indeterminate;
        }

    case header_name:
        if (input == ':') {
            state_ = space_before_header_value;
            return indeterminate;
        } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
            return bad;
        } else {
            resp.headers.back().first.push_back(input);
            return indeterminate;
        }

    case space_before_header_value:
        if (input == ' ') {
            state_ = header_value;
            return indeterminate;
        } else {
            return bad;
        }

    case header_value:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return indeterminate;
        } else if (is_ctl(input)) {
            return bad;
        } else {
            resp.headers.back().second.push_back(input);
            return indeterminate;
        }

    case expecting_newline_2:
        if (input == '\n') {
            state_ = header_line_start;
            return indeterminate;
        } else {
            return bad;
        }

    case expecting_newline_3:
        return (input == '\n') ? good : bad;

    default:
        return bad;
    }
}
Exemplo n.º 8
0
        boost::tribool request_parser::consume(request& req, char input)
        {
            switch (state_)
            {
                case method_start:
                    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
                    {
                        return false;
                    }
                    else
                    {
                        state_ = method;
                        req.method.push_back(input);
                        return boost::indeterminate;
                    }
                case method:
                    if (input == ' ')
                    {
                        state_ = uri;
                        return boost::indeterminate;
                    }
                    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
                    {
                        return false;
                    }
                    else
                    {
                        req.method.push_back(input);
                        return boost::indeterminate;
                    }
                case uri_start:
                    if (is_ctl(input))
                    {
                        return false;
                    }
                    else
                    {
                        state_ = uri;
                        req.uri.push_back(input);
                        return boost::indeterminate;
                    }
                case uri:
                    if (input == ' ')
                    {
                        state_ = http_version_h;
                        return boost::indeterminate;
                    }
                    else if (is_ctl(input))
                    {
                        return false;
                    }
                    else
                    {
                        req.uri.push_back(input);
                        return boost::indeterminate;
                    }
                case http_version_h:
                    if (input == 'H')
                    {
                        state_ = http_version_t_1;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_t_1:
                    if (input == 'T')
                    {
                        state_ = http_version_t_2;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_t_2:
                    if (input == 'T')
                    {
                        state_ = http_version_p;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_p:
                    if (input == 'P')
                    {
                        state_ = http_version_slash;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_slash:
                    if (input == '/')
                    {
                        req.http_version_major = 0;
                        req.http_version_minor = 0;
                        state_ = http_version_major_start;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_major_start:
                    if (is_digit(input))
                    {
                        req.http_version_major = req.http_version_major * 10 + input - '0';
                        state_ = http_version_major;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_major:
                    if (input == '.')
                    {
                        state_ = http_version_minor_start;
                        return boost::indeterminate;
                    }
                    else if (is_digit(input))
                    {
                        req.http_version_major = req.http_version_major * 10 + input - '0';
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_minor_start:
                    if (is_digit(input))
                    {
                        req.http_version_minor = req.http_version_minor * 10 + input - '0';
                        state_ = http_version_minor;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case http_version_minor:
                    if (input == '\r')
                    {
                        state_ = expecting_newline_1;
                        return boost::indeterminate;
                    }
                    else if (is_digit(input))
                    {
                        req.http_version_minor = req.http_version_minor * 10 + input - '0';
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case expecting_newline_1:
                    if (input == '\n')
                    {
                        state_ = header_line_start;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case header_line_start:
                    if (input == '\r')
                    {
                        state_ = expecting_newline_3;
                        return boost::indeterminate;
                    }
                    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
                    {
                        state_ = header_lws;
                        return boost::indeterminate;
                    }
                    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
                    {
                        return false;
                    }
                    else
                    {
                        req.headers.push_back(header());
                        req.headers.back().name.push_back(input);
                        state_ = header_name;
                        return boost::indeterminate;
                    }
                case header_lws:
                    if (input == '\r')
                    {
                        state_ = expecting_newline_2;
                        return boost::indeterminate;
                    }
                    else if (input == ' ' || input == '\t')
                    {
                        return boost::indeterminate;
                    }
                    else if (is_ctl(input))
                    {
                        return false;
                    }
                    else
                    {
                        state_ = header_value;
                        req.headers.back().value.push_back(input);
                        return boost::indeterminate;
                    }
                case header_name:
                    if (input == ':')
                    {
                        state_ = space_before_header_value;
                        return boost::indeterminate;
                    }
                    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
                    {
                        return false;
                    }
                    else
                    {
                        req.headers.back().name.push_back(input);
                        return boost::indeterminate;
                    }
                case space_before_header_value:
                    if (input == ' ')
                    {
                        state_ = header_value;
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case header_value:
                    if (input == '\r')
                    {
                        state_ = expecting_newline_2;
                        return boost::indeterminate;
                    }
                    else if (is_ctl(input))
                    {
                        return false;
                    }
                    else
                    {
                        req.headers.back().value.push_back(input);
                        return boost::indeterminate;
                    }
                case expecting_newline_2:
                    if (input == '\n')
                    {
                        state_ = header_line_start;
                        std::vector<header>::const_iterator cit = req.headers.begin();
                        for (; cit != req.headers.end(); ++cit)
                        {
                            std::string n = (*cit).name;
                            std::transform(n.begin(), n.end(), n.begin(), ::toupper);

                            if (n == UPPER_CONTENT_LENGTH)
                            {
                                try
                                {
                                    cl_ = boost::lexical_cast<int>((*cit).value);
                                }
                                catch (const boost::bad_lexical_cast& e)
                                {
                                    return false;
                                }
                            }
                            else if (n == UPPER_CONTENT_TYPE)
                            {
                                std::string m = (*cit).value;
                                std::transform(m.begin(), m.end(), m.begin(), ::toupper);

                                if (m != UPPER_MIME_TYPE)
                                {
                                    return false;
                                }
                            }
                        }
                        return boost::indeterminate;
                    }
                    else
                    {
                        return false;
                    }
                case expecting_newline_3:
                {
                    if (0 == cl_)
                    {
                        return (input == '\n');
                    }
                    else
                    {
                        state_ = post_data;
                        return boost::indeterminate;
                    }
                }
                case post_data:
                {
                    req.post_data.push_back(input);
                    if (0 == --cl_)
                        return true;
                    else
                        return ((cl_ < 0) ? false : boost::indeterminate);
                }
                default:
                    return false;
            }
        }
Exemplo n.º 9
0
request_parser::result_type request_parser::consume(request& req, char input)
{
  switch (state_)
  {
  case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      state_ = method;
      req.method.push_back(input);
      return indeterminate;
    }
  case method:
    if (input == ' ')
    {
      state_ = uri;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.method.push_back(input);
      return indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      state_ = http_version_h;
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      req.uri.push_back(input);
      return indeterminate;
    }
  case http_version_h:
    if (input == 'H')
    {
      state_ = http_version_t_1;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      state_ = http_version_t_2;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      state_ = http_version_p;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_p:
    if (input == 'P')
    {
      state_ = http_version_slash;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      state_ = http_version_major;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_major:
    if (input == '.')
    {
      state_ = http_version_minor_start;
      return indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      state_ = http_version_minor;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_minor:
    if (input == '\r')
    {
      state_ = expecting_newline_1;
      return indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      state_ = header_line_start;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case header_line_start:
    if (input == '\r')
    {
      state_ = expecting_newline_3;
      return indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      state_ = header_lws;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.headers.push_back(header());
      req.headers.back().name.push_back(input);
      state_ = header_name;
      return indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      state_ = space_before_header_value;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      state_ = header_value;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case header_value:
    if (input == '\r')
    {
      if (req.headers.back().name == "Content-Length")
      {
        body_content_length_ = std::stoi(req.headers.back().value);
      }
      state_ = expecting_newline_2;
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      state_ = header_line_start;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case expecting_newline_3:
    if (body_content_length_ > 0)
    {
      state_ = body;
      return indeterminate;
    }
    return (input == '\n') ? good : bad;
  case body:
    req.body.push_back(input);
    if (req.body.length() < body_content_length_)
    {
      return indeterminate;
    }
    return good;
  default:
    return bad;
  }
}
Exemplo n.º 10
0
request_parser::result_type request_parser::consume(request& req, char input)
{
  switch (state_)
  {
  case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      state_ = method;
      req.method.push_back(input);
      return indeterminate;
    }
  case method:
    if (input == ' ')
    {
      state_ = uri;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.method.push_back(input);
      return indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      state_ = http_version_h;
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      req.uri.push_back(input);
      return indeterminate;
    }
  case http_version_h:
    if (input == 'H')
    {
      state_ = http_version_t_1;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      state_ = http_version_t_2;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      state_ = http_version_p;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_p:
    if (input == 'P')
    {
      state_ = http_version_slash;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      state_ = http_version_major;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_major:
    if (input == '.')
    {
      state_ = http_version_minor_start;
      return indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      state_ = http_version_minor;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case http_version_minor:
    if (input == '\r')
    {
      state_ = expecting_newline_1;
      return indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      state_ = header_line_start;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case header_line_start:
    if (input == '\r')
    {
      state_ = expecting_newline_3;
      return indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      state_ = header_lws;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.headers.push_back(header());
      req.headers.back().name.push_back(input);
      state_ = header_name;
      return indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      state_ = space_before_header_value;
      return indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return bad;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      state_ = header_value;
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case header_value:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return indeterminate;
    }
    else if (is_ctl(input))
    {
      return bad;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      state_ = header_line_start;
      // try parse content-length
      if(!req.headers.empty() &&
          0 == stricmp("Content-Length", req.headers.rbegin()->name.c_str() )) 
      {
          req.content_length = atoi(req.headers.rbegin()->value.c_str());
      }
      return indeterminate;
    }
    else
    {
      return bad;
    }
  case expecting_newline_3: // headers parse complete
      return (input == '\n') ? good : bad;
  default:
    return bad;
  }
}
Exemplo n.º 11
0
boost::tribool request_parser::consume(request& req, char input)
{
  switch (state_)
  {
  case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      state_ = method;
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case method:
    if (input == ' ')
    {
      state_ = uri;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case uri_start:
    if (is_ctl(input))
    {
      return false;
    }
    else
    {
      state_ = uri;
      req.uri.push_back(input);
      return boost::indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      state_ = http_version_h;
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.uri.push_back(input);
      return boost::indeterminate;
    }
  case http_version_h:
    if (input == 'H')
    {
      state_ = http_version_t_1;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      state_ = http_version_t_2;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      state_ = http_version_p;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_p:
    if (input == 'P')
    {
      state_ = http_version_slash;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      state_ = http_version_major;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major:
    if (input == '.')
    {
      state_ = http_version_minor_start;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      state_ = http_version_minor;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor:
    if (input == '\r')
    {
      state_ = expecting_newline_1;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_line_start:
    if (input == '\r')
    {
      state_ = expecting_newline_3;
      return boost::indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      state_ = header_lws;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.push_back(header());
      req.headers.back().name.push_back(input);
      state_ = header_name;
      return boost::indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      state_ = space_before_header_value;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return boost::indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      state_ = header_value;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_value:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_3:
	  if (input == '\n')
	  {
		  if( req.method != "POST" ) 
		  {
			  // finished
			  return true;
		  } else
		  {
			  // this is a post request, so we need to read the content
			  req.content_length = 0;
			  for( std::vector<header>::iterator ph = req.headers.begin();  ph != req.headers.end(); ++ph )
			  {
				  if( (*ph).name == "Content-Length" ) {
					  req.content_length = atoi( (*ph).value.c_str());
					  break;
				  }
			  }

			  state_ = reading_content;
			  return boost::indeterminate;
		  }
	  } else
	  {
		  return false;
	  }
  case reading_content:
	  req.content += input;
	  if( req.content.length() == req.content_length )
	  {
		  return true;
	  } 
	  else
	  {
		  return boost::indeterminate;
	  }

  default:
    return false;
  }
}
Exemplo n.º 12
0
boost::tribool& RequestParser::consume(Request& req, char input)
{
  static boost::tribool False(false);
  static boost::tribool True(true);
  static boost::tribool Indeterminate(boost::indeterminate);

  if (++requestSize_ > MAX_REQUEST_HEADER_SIZE)
    return False;

  switch (httpState_)
  {
  case method_start:
    if (input == '\r')
    {
      /*
       * allow a new line before a request -- this seems to be
       * accepted practice when dealing with multiple requests
       * in one connection, separated by a CRLF.
       */
      httpState_ = expecting_newline_0;
      return Indeterminate;
    } else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      httpState_ = method;
      consumeToString(req.method, MAX_METHOD_SIZE);
      consumeChar(input);
      return Indeterminate;
    }
  case expecting_newline_0:
    if (input == '\n')
    {
      httpState_ = method_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case method:
    if (input == ' ')
    {
      consumeComplete();
      httpState_ = uri_start;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(input))
	return Indeterminate;
      else
	return False;
    }
  case uri_start:
    if (is_ctl(input))
    {
      return False;
    }
    else
    {
      httpState_ = uri;
      consumeToString(req.uri, MAX_URI_SIZE);
      consumeChar(input);
      return Indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      consumeComplete();

      httpState_ = http_version_h;
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(input))
	return Indeterminate;
      else
	return False;
    }
  case http_version_h:
    if (input == 'H')
    {
      httpState_ = http_version_t_1;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      httpState_ = http_version_t_2;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      httpState_ = http_version_p;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_p:
    if (input == 'P')
    {
      httpState_ = http_version_slash;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      httpState_ = http_version_major_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      httpState_ = http_version_major;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_major:
    if (input == '.')
    {
      httpState_ = http_version_minor_start;
      return Indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      httpState_ = http_version_minor;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case http_version_minor:
    if (input == '\r')
    {
      httpState_ = expecting_newline_1;
      return Indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      httpState_ = header_line_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case header_line_start:
    if (input == '\r')
    {
      httpState_ = expecting_newline_3;
      return Indeterminate;
    }
    else if (!req.headerMap.empty() && (input == ' ' || input == '\t'))
    {
      // continuation of previous header
      httpState_ = header_lws;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      consumeToString(headerName_, MAX_FIELD_NAME_SIZE);
      consumeChar(input);
      httpState_ = header_name;
      return Indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      httpState_ = expecting_newline_2;
      return Indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      httpState_ = header_value;
      headerValue_.push_back(input);
      return Indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      consumeComplete();
      httpState_ = space_before_header_value;
      return Indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(input))
	return Indeterminate;
      else
	return False;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      consumeToString(headerValue_, MAX_FIELD_VALUE_SIZE);
      httpState_ = header_value;

      return Indeterminate;
    }
    else
    {
      consumeToString(headerValue_, MAX_FIELD_VALUE_SIZE);
      httpState_ = header_value;
    }
  case header_value:
    if (input == '\r')
    {
      consumeComplete();

      if (req.headerMap.find(headerName_) != req.headerMap.end()) {
	req.headerMap[headerName_] += ',' + headerValue_;
      } else {
	Request::HeaderMap::iterator i
	  = req.headerMap.insert(std::make_pair(headerName_, headerValue_))
	    .first;
	req.headerOrder.push_back(i);
      }

      httpState_ = expecting_newline_2;
      return Indeterminate;
    }
    else if (is_ctl(input))
    {
      return False;
    }
    else
    {
      if (consumeChar(input))
	return Indeterminate;
      else
	return False;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      httpState_ = header_line_start;
      return Indeterminate;
    }
    else
    {
      return False;
    }
  case expecting_newline_3:
    if (input == '\n')
      return True;
    else
      return False;
  default:
    return False;
  }
}
Exemplo n.º 13
0
boost::tribool request_parser::consume(request& req, const char input)
{
	switch(state_)
	{
	case command_start:
		if (!is_char(input) || is_ctl(input) || is_tspecial(input))
		{
			return false;
		}
		else
		{
			state_ = command;
			req.command.push_back(input);
			return boost::indeterminate;
		}
	case command:
		if (':' == input)
		{
			state_ = argument;
			return boost::indeterminate;
		}
		else if ('\r' == input)
		{
			state_ = newline_1;
			return boost::indeterminate;
		}
		else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
		{
			return false;
		}
		else
		{
			req.command.push_back(input);
			return boost::indeterminate;
		}
	case argument:
		if ('\r' == input)
		{
			state_ = newline_1;
			return boost::indeterminate;
		}
		else if (!is_char(input))
		{
			return false;
		}
		else
		{
			req.argument.push_back(input);
			return boost::indeterminate;
		}
	case newline_1:
		if ('\n' == input)
		{
			state_ = command_start;
			return true;
		}
		else
		{
			return false;
		}
	}
}
Exemplo n.º 14
0
		boost::tribool HTTPRequestParser::consume(HTTPRequest& req, char input)
		{
		  switch (state_)
		  {
		  case method_start:
			if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
			  return false;
			}
			else
			{
			  state_ = method;
			  req.method.push_back(input);
			  return boost::indeterminate;
			}
		  case method:
			if (input == ' ')
			{
			  state_ = uri;
			  return boost::indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
			  return false;
			}
			else
			{
			  req.method.push_back(input);
			  return boost::indeterminate;
			}
		  case uri_start:
			if (is_ctl(input))
			{
			  return false;
			}
			else
			{
			  state_ = uri;
			  req.uri.push_back(input);
			  return boost::indeterminate;
			}
		  case uri:
			if (input == ' ')
			{
			  state_ = http_version_h;
			  return boost::indeterminate;
			}
			else if (is_ctl(input))
			{
			  return false;
			}
			else
			{
			  req.uri.push_back(input);
			  return boost::indeterminate;
			}
		  case http_version_h:
			if (input == 'H')
			{
			  state_ = http_version_t_1;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_t_1:
			if (input == 'T')
			{
			  state_ = http_version_t_2;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_t_2:
			if (input == 'T')
			{
			  state_ = http_version_p;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_p:
			if (input == 'P')
			{
			  state_ = http_version_slash;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_slash:
			if (input == '/')
			{
			  req.http_version_major = 0;
			  req.http_version_minor = 0;
			  state_ = http_version_major_start;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_major_start:
			if (is_digit(input))
			{
			  req.http_version_major = req.http_version_major * 10 + input - '0';
			  state_ = http_version_major;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_major:
			if (input == '.')
			{
			  state_ = http_version_minor_start;
			  return boost::indeterminate;
			}
			else if (is_digit(input))
			{
			  req.http_version_major = req.http_version_major * 10 + input - '0';
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_minor_start:
			if (is_digit(input))
			{
			  req.http_version_minor = req.http_version_minor * 10 + input - '0';
			  state_ = http_version_minor;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case http_version_minor:
			if (input == '\r')
			{
			  state_ = expecting_newline_1;
			  return boost::indeterminate;
			}
			else if (is_digit(input))
			{
			  req.http_version_minor = req.http_version_minor * 10 + input - '0';
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case expecting_newline_1:
			if (input == '\n')
			{
			  state_ = header_line_start;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case header_line_start:
			if (input == '\r')
			{
			  state_ = expecting_newline_3;
			  return boost::indeterminate;
			}
			else if (!req.headers.empty() && (input == ' ' || input == '\t'))
			{
			  state_ = header_lws;
			  return boost::indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
			  return false;
			}
			else
			{
			  _currentHeaderKey.clear();
			  _currentHeaderValue.clear();
			  _currentHeaderKey.push_back(input);
			  state_ = header_name;
			  return boost::indeterminate;
			}
		  case header_lws:
			if (input == '\r')
			{
			  state_ = expecting_newline_2;
			  return boost::indeterminate;
			}
			else if (input == ' ' || input == '\t')
			{
			  return boost::indeterminate;
			}
			else if (is_ctl(input))
			{
			  return false;
			}
			else
			{
			  state_ = header_value;
			  _currentHeaderValue.push_back(input);
			  return boost::indeterminate;
			}
		  case header_name:
			if (input == ':')
			{
			  state_ = space_before_header_value;
			  return boost::indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
			  return false;
			}
			else
			{
				_currentHeaderKey.push_back(input);
			  return boost::indeterminate;
			}
		  case space_before_header_value:
			if (input == ' ')
			{
			  state_ = header_value;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case header_value:
			if (input == '\r')
			{
				req.headers.insert(make_pair(_currentHeaderKey, _currentHeaderValue));
			  state_ = expecting_newline_2;
			  return boost::indeterminate;
			}
			else if (is_ctl(input))
			{
				req.headers.insert(make_pair(_currentHeaderKey, _currentHeaderValue));
			  return false;
			}
			else
			{
			  _currentHeaderValue.push_back(input);
			  return boost::indeterminate;
			}
		  case expecting_newline_2:
			if (input == '\n')
			{
			  state_ = header_line_start;
			  return boost::indeterminate;
			}
			else
			{
			  return false;
			}
		  case expecting_newline_3:
			if (input == '\n')
			{
				if(req.method != "POST")
					return true;

				HTTPRequest::Headers::const_iterator it(req.headers.find("Content-Length"));
				if(it == req.headers.end())
					return false;

				_postToDownload = lexical_cast<size_t>(it->second);
				state_ = postData;
				return boost::indeterminate;
			}
			else
			{
				return false;
			}
		case postData:
			req.postData.push_back(input);
			--_postToDownload;
			if(_postToDownload)
				return boost::indeterminate;
			else
				return true;
		  default:
			return false;
		  }
		}
Exemplo n.º 15
0
/*
** parse http message:
**  http_eoh                          - end of headers
**  {http_header,   Key, Value}       - Key = atom() | string()
**  {http_request,  Method,Url,Version}
**  {http_response, Version, Status, Message}
**  {http_error,    Error-Line}
*/
int packet_parse_http(const char* buf, int len, int* statep,
                      PacketCallbacks* pcb, void* arg)
{
    const char* ptr = buf;
    const char* p0;
    int n = len;

    /* remove trailing CRNL (accept NL as well) */
    if ((n >= 2) && (buf[n-2] == '\r'))
        n -= 2;
    else if ((n >= 1) && (buf[n-1] == '\n'))
        n -= 1;

    if (*statep == 0) {
        /* start-line = Request-Line | Status-Line */

        if (n >= 5 && (strncmp(buf, "HTTP/", 5) == 0)) {
            int major  = 0;
            int minor  = 0;
            int status = 0;
            /* Status-Line = HTTP-Version SP
             *              Status-Code SP Reason-Phrase
             *              CRNL
             * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
             */
            ptr += 5;
            n -= 5;
            p0 = ptr;
            while (n && isdigit((int) *ptr)) {
                major = 10*major + (*ptr - '0');
                ptr++;
                n--;
            }
            if (ptr==p0 || !n || (*ptr != '.'))
                return -1;
            ptr++;
            n--;
            p0 = ptr;
            while (n && isdigit((int) *ptr)) {
                minor = 10*minor + (*ptr - '0');
                ptr++;
                n--;
            }
            if (ptr==p0) return -1;
            p0 = ptr;
            while (n && SP(ptr)) {
                ptr++; n--;
            }
            if (ptr==p0) return -1;
            
            while (n && isdigit((int) *ptr)) {
                status = 10*status + (*ptr - '0');
                ptr++;
                n--;
            }
            p0 = ptr;
            while (n && SP(ptr)) {
                ptr++; n--;
            }
            if (ptr==p0 && n>0) return -1;
            
            /* NOTE: the syntax allows empty reason phrases */
            (*statep) = !0;
            
            return pcb->http_response(arg, major, minor, status,
                                      ptr, n);
        }
        else {
            /* Request-Line = Method SP Request-URI SP HTTP-Version CRLF */
            http_atom_t* meth;
            const char* meth_ptr = buf;
            int         meth_len;
            PacketHttpURI uri;
            const char*   uri_ptr;
            int           uri_len;
            int major  = 0;
            int minor  = 0;
            unsigned long h = 0;

            while (n && !is_tspecial((unsigned char)*ptr)) {
                hash_update(h, (int)*ptr);
                ptr++;
                n--;
            }
            meth_len = ptr - meth_ptr;
            if (n == 0 || meth_len == 0 || !SP(ptr)) return -1;

            meth = http_hash_lookup(meth_ptr, meth_len, h,
                                    http_meth_hash, HTTP_METH_HASH_SIZE);

            while (n && SP(ptr)) {
                ptr++; n--;
            }
            uri_ptr = ptr;
            while (n && !SP(ptr)) {
                ptr++; n--;
            }
            if ((uri_len = (ptr - uri_ptr)) == 0)
                return -1;
            while (n && SP(ptr)) {
                ptr++; n--;
            }
            if (n == 0) {
                (*statep) = !0;
                http_parse_uri(&uri, uri_ptr, uri_len);
                return pcb->http_request(arg, meth, meth_ptr, meth_len,
                                         &uri, 0, 9);
            }
            if (n < 8)
                return -1;
            if (strncmp(ptr, "HTTP/", 5) != 0)
                return -1;
            ptr += 5;
            n   -= 5;

            p0 = ptr;
            while (n && isdigit((int) *ptr)) {
                major = 10*major + (*ptr - '0');
                ptr++;
                n--;
            }            
            if (ptr==p0 || !n || (*ptr != '.'))
                return -1;
            ptr++;
            n--;
            p0 = ptr;
            while (n && isdigit((int) *ptr)) {
                minor = 10*minor + (*ptr - '0');
                ptr++;
                n--;
            }
            if (ptr==p0) return -1;

            (*statep) = !0;
            http_parse_uri(&uri, uri_ptr, uri_len);
            return pcb->http_request(arg, meth, meth_ptr, meth_len,
                                     &uri, major, minor);
        }
    }
    else {
        int up = 1;      /* make next char uppercase */
        http_atom_t* name;
        char name_buf[HTTP_MAX_NAME_LEN];
        const char* name_ptr = name_buf;
        int  name_len;
        unsigned long h;

        if (n == 0) {
            /* end of headers */
            *statep = 0;  /* reset state (for next request) */
            return pcb->http_eoh(arg);
        }
        h = 0;
        name_len = 0;
        while (!is_tspecial((unsigned char)*ptr)) {
            if (name_len < HTTP_MAX_NAME_LEN) {
                int c = *ptr;
                if (up) {
                    if (islower(c)) {
                        c = toupper(c);
                    }
                    up = 0;
                }
                else {
                    if (isupper(c))
                        c = tolower(c);
                    else if (c == '-')
                        up = 1;
                }                            
                name_buf[name_len] = c;
                hash_update(h, c);
            }
            name_len++;
            ptr++;
            if (--n == 0) return -1;
        }
        while (n && SP(ptr)) { /* Skip white space before ':' */
            ptr++; n--;
        } 
        if (*ptr != ':') {
            return -1;
        }
        if (name_len <= HTTP_MAX_NAME_LEN) {
            name = http_hash_lookup(name_buf, name_len, h,
                                    http_hdr_hash, HTTP_HDR_HASH_SIZE);
        } 
        else {
            /* Is it ok to return original name without case adjustments? */
            name_ptr = buf;
            name = NULL;
        }
        ptr++;
        n--;
        /* Skip white space after ':' */
        while (n && SP(ptr)) {
            ptr++; n--;
        }
        return pcb->http_header(arg, name, name_ptr, name_len,
                                ptr, n);
    }
    return -1;
}   
Exemplo n.º 16
0
static bool is_token(int ch)
{
    /* Can by antying except a ctl character or a tspecial */
    return !is_ctl(ch) && !is_tspecial(ch);
}
Exemplo n.º 17
0
	NPLMsgIn_parser::Consume_Result NPLMsgIn_parser::consume(NPLMsgIn& req, char input)
	{
		switch (state_)
		{
		case method_start:
			if (input == ' ' || input == '\r' || input == '\n')
			{
				return c_res_indeterminate;
			}
			else
			{
				// allowing char [0-255] as method name characters, escaping only \r\n and ' '.  
				state_ = method;
				req.reset();
				req.method.push_back(input);
				return c_res_indeterminate;
			}
		case method:
			if (input == ' ')
			{
				// this fix a bug when http url contains the '(', it may be mis-interpreted. 
				state_ = req.IsNPLFileActivation() ? uri : uri_http;
				return c_res_indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
				return c_res_false;
			}
			else
			{
				req.method.push_back(input);
				return c_res_indeterminate;
			}
		case uri_http:
			if (input == ' ')
			{
				state_ = npl_version_n;
				return c_res_indeterminate;
			}
			else if (input == '\n' || input == '\r')
			{
				state_ = header_line_start; // version is omitted on first line. 
				return c_res_indeterminate;
			}
			else
			{
				req.m_n_filename = 0;
				req.m_filename.push_back(input);
				return c_res_indeterminate;
			}
		case uri:
			if (is_ctl(input))
			{
				req.npl_version_major = NPL_VERSION_MAJOR;
				req.npl_version_minor = NPL_VERSION_MINOR;
				state_ = header_line_start; // version is omitted on first line. 
				return c_res_indeterminate;
			}
			else if (input == '(')
			{
				state_ = uri_rts_name;
				return c_res_indeterminate;
			}
			else if (is_digit(input))
			{
				req.m_n_filename = req.m_n_filename * 10 + input - '0';
				req.m_filename.push_back(input);
				return c_res_indeterminate;
			}
			else if (input == ' ')
			{
				state_ = npl_version_n;
				return c_res_indeterminate;
			}
			else
			{
				req.m_n_filename = 0;
				req.m_filename.push_back(input);
				return c_res_indeterminate;
			}
		case uri_rts_name:
			if (input == ')')
			{
				state_ = uri;
				return c_res_indeterminate;
			}
			else if(is_ctl(input))
			{
				return c_res_false;
			}
			else
			{
				req.m_rts_name.push_back(input);
				return c_res_indeterminate;
			}
		case npl_version_n:
			if (input == '/')
			{
				req.npl_version_major = 0;
				req.npl_version_minor = 0;
				state_ = npl_version_major;
				return c_res_indeterminate;
			}
			else if (input == '\n')
			{
				state_ = header_line_start;
				return c_res_indeterminate;
			}
			else if (input == '\r')
				return c_res_indeterminate;
			else if (is_char(input))
			{
				// any character is accepted, such as "NPL", "HTTP"
				if(req.m_filename.empty() && req.m_n_filename > 0)
				{
					// for http response, this stores the third parameter "OK", "Error"
					req.m_filename.push_back(input);
				}
				return c_res_indeterminate;
			}
			else
			{
				return c_res_false;
			}
		case npl_version_major:
			if (is_digit(input))
			{
				req.npl_version_major = req.npl_version_major * 10 + input - '0';
				return c_res_indeterminate;
			}
			else if (input == '.')
			{
				state_ = npl_version_minor;
				return c_res_indeterminate;
			}
			else
			{
				return c_res_false;
			}
		case npl_version_minor:
			if (is_digit(input))
			{
				req.npl_version_minor = req.npl_version_minor * 10 + input - '0';
				return c_res_indeterminate;
			}
			else if (input == '\n')
			{
				state_ = header_line_start;
				return c_res_indeterminate;
			}
			else if (input == '\r')
				return c_res_indeterminate;
			else
			{
				return c_res_false;
			}
		case header_line_start:
			if (input == '\n')
			{
				// continue to read the code length
				state_ = code_length;

				if(req.method.size()>2 && req.method != "npl")
				{
					// only do check header if method has at least three characters. 
					int nCount = (int)req.headers.size();
					for (int i=0;i <nCount; ++i)
					{
						if(req.headers[i].name == "Content-Length")
						{
							int nLength = atoi(req.headers[i].value.c_str());
							if(nLength>0)
							{
								state_ = code_body;
								req.m_nLength = nLength;
								req.m_code.reserve(req.m_nLength+1);
								m_bCompressed = false;
								return c_res_code_body;
							}
							else
							{
								break;
							}
						}
					}
					m_bCompressed = false;
					reset();
					return c_res_true;
				}
				
				return c_res_indeterminate;
			}
			else if (input == '\r')
				return c_res_indeterminate;
			else if (!req.headers.empty() && (input == ' ' || input == '\t'))
			{
				state_ = header_lws;
				return c_res_indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
				return c_res_false;
			}
			else
			{
				req.headers.push_back(NPLMsgHeader());
				req.headers.back().name.push_back(input);
				state_ = header_name;
				return c_res_indeterminate;
			}
		case header_lws:
			if (input == '\n')
			{
				state_ = header_line_start;
				return c_res_indeterminate;
			}
			else if (input == '\r')
				return c_res_indeterminate;
			else if (input == ' ' || input == '\t')
			{
				return c_res_indeterminate;
			}
			else if (is_ctl(input))
			{
				return c_res_false;
			}
			else
			{
				state_ = header_value;
				req.headers.back().value.push_back(input);
				return c_res_indeterminate;
			}
		case header_name:
			if (input == ':')
			{
				state_ = header_value;
				return c_res_indeterminate;
			}
			else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
			{
				return c_res_false;
			}
			else
			{
				req.headers.back().name.push_back(input);
				return c_res_indeterminate;
			}
		case header_value:
			if (input == '\n')
			{
				state_ = header_line_start;
				return c_res_indeterminate;
			}
			else if (input == '\r')
				return c_res_indeterminate;
			else if (is_ctl(input))
			{
				return c_res_false;
			}
			else
			{
				string& value_ = req.headers.back().value;
				if( !(value_.empty() && (input == ' ' || input == '\t')) )
					value_.push_back(input);
				return c_res_indeterminate;
			}
		case code_length:
			if(is_digit(input))
			{
				req.m_nLength = req.m_nLength * 10 + input - '0';
				return c_res_indeterminate;
			}
			else if(input == ':' || input == '>')
			{
				state_ = code_body;
				m_bCompressed = (input == '>');
				if(req.m_nLength == 0)
				{
					reset();
					return c_res_true;
				}
				else
				{
					req.m_code.reserve(req.m_nLength+1);
					return c_res_code_body;
				}
			}
		case code_body:
			if(req.m_nLength>(int)req.m_code.size())
			{
				// I used  a special return value c_res_code_body to indicate that code body is met, 
				// so that we can read to end or length instead of doing the lexical work by char at a time. 
				req.m_code.push_back(input);
				if (req.m_nLength >(int)req.m_code.size()) 
					return c_res_code_body;
				else
				{
					reset();
					return c_res_true;
				}
			}
		default:
			return c_res_false;
		}
	}
Exemplo n.º 18
0
boost::tribool request_parser::consume(request& req, char input)
{
  switch (state_)
  {
  case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      state_ = method;
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case method:
    if (input == ' ')
    {
      state_ = uri;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.method.push_back(input);
      return boost::indeterminate;
    }
  case uri:
    if (input == ' ')
    {
      state_ = http_version_h;
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.uri.push_back(input);
      return boost::indeterminate;
    }
  case http_version_h:
    if (input == 'H')
    {
      state_ = http_version_t_1;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      state_ = http_version_t_2;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      state_ = http_version_p;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_p:
    if (input == 'P')
    {
      state_ = http_version_slash;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_slash:
    if (input == '/')
    {
      req.http_version_major = 0;
      req.http_version_minor = 0;
      state_ = http_version_major_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major_start:
    if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      state_ = http_version_major;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_major:
    if (input == '.')
    {
      state_ = http_version_minor_start;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_major = req.http_version_major * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor_start:
    if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      state_ = http_version_minor;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor:
    if (input == '\r')
    {
      state_ = expecting_newline_1;
      return boost::indeterminate;
    }
    else if (is_digit(input))
    {
      req.http_version_minor = req.http_version_minor * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_line_start:
    if (input == '\r')
    {
      state_ = expecting_newline_3;
      return boost::indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      state_ = header_lws;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.push_back(header());
      req.headers.back().name.push_back(input);
      state_ = header_name;
      return boost::indeterminate;
    }
  case header_lws:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (input == ' ' || input == '\t')
    {
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      state_ = header_value;
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      state_ = space_before_header_value;
      return boost::indeterminate;
    }
    else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return boost::indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      state_ = header_value;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_value:
    if (input == '\r')
    {
      state_ = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (is_ctl(input))
    {
      return false;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      state_ = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_3:
    return (input == '\n');
  default:
    return false;
  }
}
Exemplo n.º 19
0
boost::tribool form_parser::consume(json_var& variable, char input)
{//std::cout << input << "<" << state_ << "\n";
  switch (state_)
  {
  case var_start:
    if (!is_char(input))
    {
      return false;
    }
    else if(input == '\0')
    {
      return true;
    }
    else
    {
      value_ += input;
      state_ = var;
      return boost::indeterminate;
    }
  case var:
    if (input == '=')
    {
      (*var_)[value_] = json_var(json_var::string_var);
      var_ = &(*var_)[value_];
      value_.clear();
      state_ = value_start;
      return boost::indeterminate;
    }
    else if (input == '[')
    {
      state_ = property_start;
      return boost::indeterminate;
    }
    else if (input == '&')
    {
      (*var_)[value_] = json_var(true);
      value_.clear();
      state_ = var_start;
      return boost::indeterminate;
    }
    else if(input == '\0')
    {
      (*var_)[value_] = json_var(true);
      return true;
    }
    else if (!is_char(input) || is_tspecial(input))
    {
      return false;
    }
    else
    {
      value_ += input;
      return boost::indeterminate;
    }
  case property_start:
    if (is_char(input) && !is_tspecial(input))
    {
      if((*var_)[value_].get_type() != json_var::object_var)
       (*var_)[value_] = json_var(json_var::object_var);
      var_ = &(*var_)[value_];
      value_.clear();
      value_ += input;
      state_ = property;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case property:
    if (input == ']')
    {
      state_ = property_end;
      return boost::indeterminate;
    }
    else if (is_char(input) && !is_tspecial(input))
    {
      value_ += input;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case property_end:
    if (input == '=')
    {
      (*var_)[value_] = json_var(json_var::string_var);
      var_ = &(*var_)[value_];
      value_.clear();
      state_ = value_start;
      return boost::indeterminate;
    }
    else if (input == '[')
    {
      state_ = property_start;
      return boost::indeterminate;
    }
    else if (input == '&')
    {
      (*var_)[value_] = json_var("true");
      value_.clear();
      var_ = &variable;
      state_ = var_start;
      return boost::indeterminate;
    }
    else if(input == '\0')
    {
      (*var_)[value_] = json_var("true");
      return true;
    }
    else
    {
      return false;
    }
  case value_start:
    if (input == '&')
    {
      return false;
    }
    else
    {
      value_ += input;
      state_ = value;
      return boost::indeterminate;
    }
  case value:
    if (input == '&')
    {
      //std::cout << value_ << '\n';
      std::string value;
      utils::url_decode(value_, value);
      (*var_) = value;
      value_.clear();
      var_ = &variable;
      state_ = var_start;
      return boost::indeterminate;
    }
    else if (input == '\0')
    {
      //std::cout << value_ << '\n';
      std::string value;
      utils::url_decode(value_, value);
      (*var_) = value;
      return true;
    }
    else
    {
      value_ += input;
      return boost::indeterminate;
    }
  default:
    return false;
  }
}