示例#1
0
static char *parse_field_content(http_parser_t *parser)
{
    char *start, *str, ch;

    start = parser->parse_ptr;
    do {
        if (parser->parse_ptr - parser->data >= parser->len)
            break;

        ch = *parser->parse_ptr;
        if (is_ctl(ch))
            break;
        if (!parse_crlf(parser))
            break;
        parser->parse_ptr++;
    } while (1);

    if (parser->parse_ptr - start == 0)
        return NULL;

    str = malloc(parser->parse_ptr - start + 1);
    ASSERT(str != NULL);

    strncpy(str, start, parser->parse_ptr - start);
    str[parser->parse_ptr - start] = '\0';

    return str;
}
示例#2
0
// token = 1*<any CHAR except CTLs or separators>
const char* parse_token(unsigned char **p)
{
	int len = 0;
	while (1) {
		if (is_char(**p) && !(is_ctl(**p) || is_separator(**p))) {
			(*p)++;
			len++;
			continue;
		} else {
			if (len > 0) {
				return NULL;
			}
			return ERR;
		}
	}
}
示例#3
0
// qdtext = <any TEXT except <">>
const char* parse_qdtext(unsigned char **p)
{
	int len = 0;
	while (0 != (char)**p) {
		if (!parse_lws(p)) {
			len++;
			continue;
		} else if (is_ctl(**p) || DQUOTE == **p) {
			break;
		}
		len++;
		(*p)++;
	}

	return len ? NULL : ERR;
}
示例#4
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;
		}
示例#5
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;
			}
		}
示例#6
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;
		  }
		}
示例#7
0
static gboolean
accelerator_parse (const gchar         *accelerator,
                   MetaKeyCombo        *combo)
{
    guint keyval, keycode;
    MetaVirtualModifier mods;
    gint len;

    combo->keysym = 0;
    combo->keycode = 0;
    combo->modifiers = 0;

    if (accelerator == NULL)
        return FALSE;

    keyval = 0;
    keycode = 0;
    mods = 0;
    len = strlen (accelerator);
    while (len)
    {
        if (*accelerator == '<')
        {
            if (len >= 9 && is_primary (accelerator))
            {
                /* Primary is treated the same as Control */
                accelerator += 9;
                len -= 9;
                mods |= META_VIRTUAL_CONTROL_MASK;
            }
            else if (len >= 9 && is_control (accelerator))
            {
                accelerator += 9;
                len -= 9;
                mods |= META_VIRTUAL_CONTROL_MASK;
            }
            else if (len >= 7 && is_shift (accelerator))
            {
                accelerator += 7;
                len -= 7;
                mods |= META_VIRTUAL_SHIFT_MASK;
            }
            else if (len >= 6 && is_shft (accelerator))
            {
                accelerator += 6;
                len -= 6;
                mods |= META_VIRTUAL_SHIFT_MASK;
            }
            else if (len >= 6 && is_ctrl (accelerator))
            {
                accelerator += 6;
                len -= 6;
                mods |= META_VIRTUAL_CONTROL_MASK;
            }
            else if (len >= 6 && is_modx (accelerator))
            {
                static const guint mod_vals[] = {
                    META_VIRTUAL_ALT_MASK,
                    META_VIRTUAL_MOD2_MASK,
                    META_VIRTUAL_MOD3_MASK,
                    META_VIRTUAL_MOD4_MASK,
                    META_VIRTUAL_MOD5_MASK,
                };

                len -= 6;
                accelerator += 4;
                mods |= mod_vals[*accelerator - '1'];
                accelerator += 2;
            }
            else if (len >= 5 && is_ctl (accelerator))
            {
                accelerator += 5;
                len -= 5;
                mods |= META_VIRTUAL_CONTROL_MASK;
            }
            else if (len >= 5 && is_alt (accelerator))
            {
                accelerator += 5;
                len -= 5;
                mods |= META_VIRTUAL_ALT_MASK;
            }
            else if (len >= 6 && is_meta (accelerator))
            {
                accelerator += 6;
                len -= 6;
                mods |= META_VIRTUAL_META_MASK;
            }
            else if (len >= 7 && is_hyper (accelerator))
            {
                accelerator += 7;
                len -= 7;
                mods |= META_VIRTUAL_HYPER_MASK;
            }
            else if (len >= 7 && is_super (accelerator))
            {
                accelerator += 7;
                len -= 7;
                mods |= META_VIRTUAL_SUPER_MASK;
            }
            else
            {
                gchar last_ch;

                last_ch = *accelerator;
                while (last_ch && last_ch != '>')
                {
                    last_ch = *accelerator;
                    accelerator += 1;
                    len -= 1;
                }
            }
        }
        else
        {
            if (len >= 4 && is_keycode (accelerator))
            {
                keycode = strtoul (accelerator, NULL, 16);
                goto out;
            }
            else if (strcmp (accelerator, "Above_Tab") == 0)
            {
                keyval = META_KEY_ABOVE_TAB;
                goto out;
            }
            else
            {
                keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
                if (keyval == XKB_KEY_NoSymbol)
                {
                    char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
                    keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
                    g_free (with_xf86);

                    if (keyval == XKB_KEY_NoSymbol)
                        return FALSE;
                }
            }

            accelerator += len;
            len -= len;
        }
    }

out:
    combo->keysym = keyval;
    combo->keycode = keycode;
    combo->modifiers = mods;
    return TRUE;
}
示例#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;
            }
        }
示例#9
0
Result ws::http_request_parser::consume(char c)
{
	switch(state_)
	{
		case METHOD_GET_1:
			return require_char(c, 'G', METHOD_GET_2);
			break;
		
		case METHOD_GET_2:
			return require_char(c, 'E', METHOD_GET_3);
			break;
		
		case METHOD_GET_3:
			return require_char(c, 'T', METHOD_GET_SP);
			break;
		
		case METHOD_GET_SP:
			return require_char(c, ' ', URI);
			break;
		
		case URI:
			if (c == ' ')
				state_ = HTTP_1;
			else if (!is_ctl(c))
				request.uri.push_back(c);
			else
				return BAD_REQUEST;
			return INDETERMINATE;
			break;
		
		case HTTP_1:
			return require_char(c, 'H', HTTP_2);
			break;
		
		case HTTP_2:
			return require_char(c, 'T', HTTP_3);
			break;
		
		case HTTP_3:
			return require_char(c, 'T', HTTP_4);
			break;
		
		case HTTP_4:
			return require_char(c, 'P', HTTP_SLASH);
			break;
		
		case HTTP_SLASH:
			return require_char(c, '/', HTTP_VERSION_MAJOR);
			break;
		
		case HTTP_VERSION_MAJOR:
			return require_char(c, '1', HTTP_VERSION_POINT);
			break;
		
		case HTTP_VERSION_POINT:
			return require_char(c, '.', HTTP_VERSION_MINOR);
			break;
		
		case HTTP_VERSION_MINOR:
			return require_char(c, '1', REQUEST_LINE_CR);
			break;
		
		case REQUEST_LINE_CR:
			return require_char(c, CR, REQUEST_LINE_LF);
			break;
		
		case REQUEST_LINE_LF:
			return require_char(c, LF, HEADER_START);
			break;
		
		case HEADER_START:
			if (c == CR)
			{
				state_ = FINAL_LF;
				return INDETERMINATE;
			}
			state_ = HEADER_NAME;
			return process_header_name_char(c);
			break;
		
		case HEADER_NAME:
			if (c == ':')
			{
				state_ = HEADER_VALUE_START;
				return INDETERMINATE;
			}
			return process_header_name_char(c);
			break;
		
		case HEADER_VALUE_START:
			if (is_lws(c))
				return INDETERMINATE;
			state_ = HEADER_VALUE;
			return process_header_value_char(c);
			break;
		
		case HEADER_VALUE:
			if (c == CR)
			{
				header_value_complete();
				state_ = HEADER_LF;
				return INDETERMINATE;
			}
			return process_header_value_char(c);
			break;
		
		case HEADER_LF:
			return require_char(c, LF, HEADER_START);
			break;
		
		case FINAL_LF:
			if (c == LF)
			{
				state_ = AFTER_FINAL_LF;
				return GOOD;
			}
			else
				return BAD_REQUEST;
			break;
		
		case AFTER_FINAL_LF:
			return BAD_REQUEST;
			break;
	}
	return BAD_REQUEST;
}
示例#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')
    {
      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;
  }
}
示例#11
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;
  }
}
示例#12
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;
  }
}
示例#13
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;
  }
}
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;
		}
	}
}
示例#15
0
		bool parse_http_status_line(Iterator begin, Iterator end, int& version_major, int& version_minor, int& status)
		{
			enum
			{
				http_version_h,
				http_version_t_1,
				http_version_t_2,
				http_version_p,
				http_version_slash,
				http_version_major_start,
				http_version_major,
				http_version_minor_start,
				http_version_minor,
				status_code_start,
				status_code,
				reason_phrase,
				linefeed,
				fail
			} state = http_version_h;

			Iterator iter = begin;
			std::string reason;
			while (iter != end && state != fail)
			{
				char c = *iter++;
				switch (state)
				{
				case http_version_h:
					state = (c == 'H') ? http_version_t_1 : fail;
					break;
				case http_version_t_1:
					state = (c == 'T') ? http_version_t_2 : fail;
					break;
				case http_version_t_2:
					state = (c == 'T') ? http_version_p : fail;
					break;
				case http_version_p:
					state = (c == 'P') ? http_version_slash : fail;
					break;
				case http_version_slash:
					state = (c == '/') ? http_version_major_start : fail;
					break;
				case http_version_major_start:
					if (is_digit(c))
					{
						version_major = version_major * 10 + c - '0';
						state = http_version_major;
					}
					else
						state = fail;
					break;
				case http_version_major:
					if (c == '.')
						state = http_version_minor_start;
					else if (is_digit(c))
						version_major = version_major * 10 + c - '0';
					else
						state = fail;
					break;
				case http_version_minor_start:
					if (is_digit(c))
					{
						version_minor = version_minor * 10 + c - '0';
						state = http_version_minor;
					}
					else
						state = fail;
					break;
				case http_version_minor:
					if (c == ' ')
						state = status_code_start;
					else if (is_digit(c))
						version_minor = version_minor * 10 + c - '0';
					else
						state = fail;
					break;
				case status_code_start:
					if (is_digit(c))
					{
						status = status * 10 + c - '0';
						state = status_code;
					}
					else
						state = fail;
					break;
				case status_code:
					if (c == ' ')
						state = reason_phrase;
					else if (is_digit(c))
						status = status * 10 + c - '0';
					else
						state = fail;
					break;
				case reason_phrase:
					if (c == '\r')
						state = linefeed;
					else if (is_ctl(c))
						state = fail;
					else
						reason.push_back(c);
					break;
				case linefeed:
					return (c == '\n');
				default:
					return false;
				}
			}
			return false;
		}
示例#16
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;
  }
}
示例#17
0
bool ws::http_request_parser::is_valid_header_value_char(char c)
{
	return (!is_ctl(c));
}
示例#18
0
static bool is_token(int ch)
{
    /* Can by antying except a ctl character or a tspecial */
    return !is_ctl(ch) && !is_tspecial(ch);
}
示例#19
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;
		}
	}
示例#20
0
/**
 * egg_accelerator_parse_virtual:
 * @accelerator:      string representing an accelerator
 * @accelerator_key:  return location for accelerator keyval
 * @accelerator_mods: return location for accelerator modifier mask
 *
 * Parses a string representing a virtual accelerator. The format
 * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
 * "&lt;Release&gt;z" (the last one is for key release).  The parser
 * is fairly liberal and allows lower or upper case, and also
 * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
 *
 * If the parse fails, @accelerator_key and @accelerator_mods will
 * be set to 0 (zero) and %FALSE will be returned. If the string contains
 * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
 * returned.
 *
 * The virtual vs. concrete accelerator distinction is a relic of
 * how the X Window System works; there are modifiers Mod2-Mod5 that
 * can represent various keyboard keys (numlock, meta, hyper, etc.),
 * the virtual modifier represents the keyboard key, the concrete
 * modifier the actual Mod2-Mod5 bits in the key press event.
 *
 * Returns: %TRUE on success.
 */
gboolean
egg_accelerator_parse_virtual (const gchar            *accelerator,
                               guint                  *accelerator_key,
			       guint                  *keycode,
                               EggVirtualModifierType *accelerator_mods)
{
  guint keyval;
  GdkModifierType mods;
  gint len;
  gboolean bad_keyval;

  if (accelerator_key)
    *accelerator_key = 0;
  if (accelerator_mods)
    *accelerator_mods = 0;
  if (keycode)
    *keycode = 0;

  g_return_val_if_fail (accelerator != NULL, FALSE);

  bad_keyval = FALSE;

  keyval = 0;
  mods = 0;
  len = strlen (accelerator);
  while (len)
    {
      if (*accelerator == '<')
	{
	  if (len >= 9 && is_release (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_RELEASE_MASK;
	    }
	  else if (len >= 9 && is_control (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 7 && is_shift (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_shft (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_ctrl (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 6 && is_modx (accelerator))
	    {
	      static const guint mod_vals[] = {
		EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
		EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
	      };

	      len -= 6;
	      accelerator += 4;
	      mods |= mod_vals[*accelerator - '1'];
	      accelerator += 2;
	    }
	  else if (len >= 5 && is_ctl (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 5 && is_alt (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_ALT_MASK;
	    }
          else if (len >= 6 && is_meta (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_META_MASK;
	    }
          else if (len >= 7 && is_hyper (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_HYPER_MASK;
	    }
          else if (len >= 7 && is_super (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SUPER_MASK;
	    }
	  else
	    {
	      gchar last_ch;

	      last_ch = *accelerator;
	      while (last_ch && last_ch != '>')
		{
		  last_ch = *accelerator;
		  accelerator += 1;
		  len -= 1;
		}
	    }
	}
      else
	{
          keyval = gdk_keyval_from_name (accelerator);

          if (keyval == 0)
	    {
	      /* If keyval is 0, than maybe it's a keycode.  Check for 0x## */
	      if (len >= 4 && is_keycode (accelerator))
		{
		  char keystring[5];
		  gchar *endptr;
		  gint tmp_keycode;

		  memcpy (keystring, accelerator, 4);
		  keystring [4] = '\000';

		  tmp_keycode = strtol (keystring, &endptr, 16);

		  if (endptr == NULL || *endptr != '\000')
		    {
		      bad_keyval = TRUE;
		    }
		  else if (keycode != NULL)
		    {
		      *keycode = tmp_keycode;
		      /* 0x00 is an invalid keycode too. */
		      if (*keycode == 0)
			bad_keyval = TRUE;
		    }
		}
	    } else if (keycode != NULL)
		*keycode = XKeysymToKeycode (GDK_DISPLAY(), keyval);

          accelerator += len;
          len -= len;
	}
    }

  if (accelerator_key)
    *accelerator_key = gdk_keyval_to_lower (keyval);
  if (accelerator_mods)
    *accelerator_mods = mods;

  return !bad_keyval;
}
示例#21
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;
  }
}
示例#22
0
/**
 * egg_accelerator_parse_virtual:
 * @accelerator:      string representing an accelerator
 * @accelerator_key:  return location for accelerator keyval
 * @accelerator_mods: return location for accelerator modifier mask
 *
 * Parses a string representing a virtual accelerator. The format
 * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
 * "&lt;Release&gt;z" (the last one is for key release).  The parser
 * is fairly liberal and allows lower or upper case, and also
 * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
 *
 * If the parse fails, @accelerator_key and @accelerator_mods will
 * be set to 0 (zero) and %FALSE will be returned. If the string contains
 * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
 * returned.
 *
 * The virtual vs. concrete accelerator distinction is a relic of
 * how the X Window System works; there are modifiers Mod2-Mod5 that
 * can represent various keyboard keys (numlock, meta, hyper, etc.),
 * the virtual modifier represents the keyboard key, the concrete
 * modifier the actual Mod2-Mod5 bits in the key press event.
 * 
 * Returns: %TRUE on success.
 */
gboolean
egg_accelerator_parse_virtual (const gchar            *accelerator,
                               guint                  *accelerator_key,
                               EggVirtualModifierType *accelerator_mods)
{
  guint keyval;
  GdkModifierType mods;
  gint len;
  gboolean bad_keyval;
  
  if (accelerator_key)
    *accelerator_key = 0;
  if (accelerator_mods)
    *accelerator_mods = 0;

  g_return_val_if_fail (accelerator != NULL, FALSE);

  bad_keyval = FALSE;
  
  keyval = 0;
  mods = 0;
  len = strlen (accelerator);
  while (len)
    {
      if (*accelerator == '<')
	{
	  if (len >= 9 && is_release (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_RELEASE_MASK;
	    }
	  else if (len >= 9 && is_control (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 7 && is_shift (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_shft (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_ctrl (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 6 && is_modx (accelerator))
	    {
	      static const guint mod_vals[] = {
		EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
		EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
	      };

	      len -= 6;
	      accelerator += 4;
	      mods |= mod_vals[*accelerator - '1'];
	      accelerator += 2;
	    }
	  else if (len >= 5 && is_ctl (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 5 && is_alt (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_ALT_MASK;
	    }
          else if (len >= 6 && is_meta (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_META_MASK;
	    }
          else if (len >= 7 && is_hyper (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_HYPER_MASK;
	    }
          else if (len >= 7 && is_super (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SUPER_MASK;
	    }
          else if (len >= 9 && is_primary (accelerator))
        {
          accelerator += 9;
          len -= 9;
          mods |= EGG_VIRTUAL_CONTROL_MASK;
        }
	      else
	    {
	      gchar last_ch;
	      
	      last_ch = *accelerator;
	      while (last_ch && last_ch != '>')
            {
		      last_ch = *accelerator;
		      accelerator += 1;
		      len -= 1;
		    }
	    }
	}
      else
	{
          keyval = gdk_keyval_from_name (accelerator);
          
          if (keyval == 0)
            bad_keyval = TRUE;
          
          accelerator += len;
          len -= len;              
	}
    }
  
  if (accelerator_key)
    *accelerator_key = gdk_keyval_to_lower (keyval);
  if (accelerator_mods)
    *accelerator_mods = mods;

  return !bad_keyval;
}
示例#23
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;
  }
}
示例#24
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;
  }
}
示例#25
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;
    }
}