Exemplo n.º 1
0
boost::tribool RequestParser::consume(Request& req, char input) {
  switch (m_state) {

  case method_start:
    if (!isChar(input) || isCtl(input) || isTspecial(input)) {
      return false;
    } else {
      m_state = method;
      req.method.push_back(input);
      return boost::indeterminate;
    }

  case method:
    if (input == ' ') {
      m_state = uri;
      return boost::indeterminate;
    }
    else if (!isChar(input) || isCtl(input) || isTspecial(input)) {
      return false;
    }
    else
    {
      req.method.push_back(input);
      return boost::indeterminate;
    }
      
  case uri:
    if (input == ' ')
    {
      m_state = http_version_h;
      return boost::indeterminate;
    } else if (isCtl(input)) {
      return false;
    }
    else
    {
      req.uri.push_back(input);
      return boost::indeterminate;
    }

  case http_version_h:
    if (input == 'H')
    {
      m_state = http_version_t_1;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_1:
    if (input == 'T')
    {
      m_state = http_version_t_2;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_t_2:
    if (input == 'T')
    {
      m_state = http_version_p;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_p:
    if (input == 'P')
    {
      m_state = http_version_slash;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_slash:
    if (input == '/')  {
      req.httpVersionMajor = 0;
      req.httpVersionMinor = 0;
      m_state = http_version_major_start;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_major_start:
    if (isDigit(input)) {
      req.httpVersionMajor = req.httpVersionMajor * 10 + input - '0';
      m_state = http_version_major;
      return boost::indeterminate;
    } else {
      return false;
    }
  case http_version_major:
    if (input == '.')
    {
      m_state = http_version_minor_start;
      return boost::indeterminate;
    }
    else if (isDigit(input))
    {
      req.httpVersionMajor = req.httpVersionMajor * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor_start:
    if (isDigit(input))
    {
      req.httpVersionMinor = req.httpVersionMinor * 10 + input - '0';
      m_state = http_version_minor;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case http_version_minor:
    if (input == '\r')
    {
      m_state = expecting_newline_1;
      return boost::indeterminate;
    }
    else if (isDigit(input))
    {
      req.httpVersionMinor = req.httpVersionMinor * 10 + input - '0';
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_1:
    if (input == '\n')
    {
      m_state = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_line_start:
    if (input == '\r')
    {
      m_state = expecting_newline_3;
      return boost::indeterminate;
    }
    else if (!req.headers.empty() && (input == ' ' || input == '\t'))
    {
      m_state = header_lws;
      return boost::indeterminate;
    }
    else if (!isChar(input) || isCtl(input) || isTspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.push_back(Header());
      req.headers.back().name.push_back(input);
      m_state = header_name;
      return boost::indeterminate;
    }
  case header_lws:
    if (input == '\r') {
      m_state = expecting_newline_2;
      return boost::indeterminate;
    } else if (input == ' ' || input == '\t') {
      return boost::indeterminate;
    } else if (isCtl(input)) {
      return false;
    } else {
      m_state = header_value;
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case header_name:
    if (input == ':')
    {
      m_state = space_before_header_value;
      return boost::indeterminate;
    }
    else if (!isChar(input) || isCtl(input) || isTspecial(input))
    {
      return false;
    }
    else
    {
      req.headers.back().name.push_back(input);
      return boost::indeterminate;
    }
  case space_before_header_value:
    if (input == ' ')
    {
      m_state = header_value;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case header_value:
    if (input == '\r')
    {
      m_state = expecting_newline_2;
      return boost::indeterminate;
    }
    else if (isCtl(input))
    {
      return false;
    }
    else
    {
      req.headers.back().value.push_back(input);
      return boost::indeterminate;
    }
  case expecting_newline_2:
    if (input == '\n')
    {
      m_state = header_line_start;
      return boost::indeterminate;
    }
    else
    {
      return false;
    }
  case expecting_newline_3: {
    if(input == '\n') {
      req.headerIsReady = true; 
      if(req.method == "POST") {
        // gonna read by chunk the rest
        findBoundary(req);
        if(req.boundary == "") {
          return false;
        } else {
          m_state = postData_boundary;
          return boost::indeterminate;
        }
      } else {
        // GET, PUT, etc..
        return true;
      }
    } else {
      return false;
    }
  }
    
  case postData_boundary: {
    if(input == '\r') {
      m_state = postData_headerLine1;
    }
    return boost::indeterminate;
  }
  case postData_headerLine1: {
    if(input == '\r') {
      m_state = postData_headerLine2;
    }
    return boost::indeterminate;
  }
  case postData_headerLine2: {
    if(input == '\r') {
      m_state = postData_headerEmptyLineR;
    }
    return boost::indeterminate;
  }
  case postData_headerEmptyLineR: {
    if(input == '\r') {
      m_state = postData_headerEmptyLineN;
    }
    return boost::indeterminate;
  }
  case postData_headerEmptyLineN: {
    if(input == '\n') {
      m_state = postData_rawData;
    }
    return boost::indeterminate;
  }
  case postData_rawData: {
    if(m_postDataBuffer.size() == req.boundary.length()) {
      char topChar = m_postDataBuffer.front();
      m_postDataBuffer.pop_front();
      m_postDataBuffer.push_back(input);
      req.postChunk[req.postChunkSize] = topChar;
      req.postChunkSize++;
      if(isPostDataBufferIsEnd(req)) {
        return true;
      }
    } else {
      m_postDataBuffer.push_back(input);
    }
    return boost::indeterminate;
  }
  default:
    return false;
  }
}
		HttpRequestParser::ParseResult HttpRequestParser::consume(HttpRequest &request, char input) {
			switch (state_) {
				case method_start:
					if (!isChar(input) || isCtl(input) || isTspecial(input)) {
						return bad;
					} else {
						state_ = method;
						request.pushBackMethod(input);

						return indeterminate;
					}
				case method:
					if (input == ' ') {
						state_ = uri;

						return indeterminate;
					} else if (!isChar(input) || isCtl(input) || isTspecial(input)) {
						return bad;
					} else {
						request.pushBackMethod(input);
						return indeterminate;
					}
				case uri:
					if (input == '?') {
						state_ = query_param_start;

						return indeterminate;
					} else if (input == ' ') {
						state_ = http_version_h;

						return indeterminate;
					} else if (isCtl(input)) {
						return bad;
					} else {
						request.pushBackUri(input);

						return indeterminate;
					}
				case query_param_start:
					state_ = query_param_name;
					request.getQueryParameters().push_back(PairNameValue());
					request.getQueryParameters().back().name.push_back(input);

					return indeterminate;
				case query_param_name:
					if (input == '=') {
						state_ = query_param_value;

						return indeterminate;
					} else {
						request.getQueryParameters().back().name.push_back(input);
						return indeterminate;
					}
				case query_param_value:
					if (input == '&') {
						state_ = query_param_start;

						return indeterminate;
					} else if (input == ' ') {
						state_ = http_version_h;

						return indeterminate;
					} else {
						request.getQueryParameters().back().value.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 == '/') {
						state_ = http_version_major_start;
						request.setHttpVersionMajor(0);
						request.setHttpVersionMinor(0);

						return indeterminate;
					} else {
						return bad;
					}
				case http_version_major_start:
					if (isDigit(input)) {
						state_ = http_version_major;
						request.setHttpVersionMajor(request.getHttpVersionMajor() * 10 + input - '0');

						return indeterminate;
					} else {
						return bad;
					}
				case http_version_major:
					if (input == '.') {
						state_ = http_version_minor_start;

						return indeterminate;
					} else {
						return bad;
					}
				case http_version_minor_start:
					if (isDigit(input)) {
						state_ = http_version_minor;
						request.setHttpVersionMinor(request.getHttpVersionMinor() * 10 + input - '0');

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

						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 (!request.getHeaders().empty() && (input == ' ' || input == '\t')) {
						state_ = header_lws;

						return indeterminate;
					} else if (!isChar(input) || isCtl(input) || isTspecial(input)) {
						return bad;
					} else {
						request.getHeaders().push_back(PairNameValue());
						request.getHeaders().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 (isCtl(input)) {
						return bad;
					} else {
						state_ = header_value;

						return indeterminate;
					}
				case header_name:
					if (input == ':') {
						state_ = space_before_header_value;

						return indeterminate;
					} else if (!isChar(input) || isCtl(input) || isTspecial(input)) {
						return bad;
					} else {
						request.getHeaders().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 (isCtl(input)) {
						return bad;
					} else {
						request.getHeaders().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:
					return (input == '\n') ? good: bad;
				default:
					return bad;
			}
		}