+++ /dev/null
-/*
- * @file http_message.cpp
- * @brief module of HTTP Message
- * @brief HTTP Message parser
- *
- * Copyright (C) 2009 NTT COMWARE Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- **********************************************************************/
-
-#include "http_message.h"
-
-/*!
- * HTTP Message constructor.
- */
-http_message::http_message()
- :
- modified(false)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 1, // XXX log
- "in/out_function : Constructor http_message::http_message(void)");
- }
- /*------ DEBUG LOG END ------*/
-}
-
-/*!
- * HTTP Message constructor.
- * Parse HTTP message header.
- *
- * @param[in] header full http message header string
- */
-http_message::http_message(std::string header)
- :
- modified(false)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 1, // XXX log
- "in/out_function : Constructor http_message::http_message(std::string header) : "
- "header(%s)", header.c_str());
- }
- /*------ DEBUG LOG END ------*/
- this->parse(header);
-}
-
-/*!
- * HTTP Message destructor.
- */
-http_message::~http_message()
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 2, // XXX log
- "in/out_function : Destructor http_message::~http_message(void)");
- }
- /*------ DEBUG LOG END ------*/
-}
-
-/*!
- * Get HTTP header field function.
- *
- * @param[in] field_name lookup field name
- * @return header field value
- */
-field_range http_message::header(std::string field_name)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : field_range http_message::header(std::string field_name) : "
- "field_name(%s)", field_name.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- field_range ret = this->_header.get<field_map>().equal_range(field_name);
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : field_range http_message::header(std::string field_name)");
- }
- /*------ DEBUG LOG END ------*/
-
- return ret;
-}
-
-/*!
- * Set HTTP header field function.
- * Set new HTTP header field and return old HTTP header field.
- *
- * @param[in] field_name lookup field name
- * @param[in] field_value field value
- */
-void http_message::header(std::string field_name, std::string field_value)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : field_range http_message::header(std::string field_name, std::string field_value) : "
- "field_name(%s), field_value(%s)", field_name.c_str(), field_value.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- bool replaced = false;
- field_range ret = this->_header.get<field_map>().equal_range(field_name);
- field_map_iterator it = ret.first;
- field_map_iterator it_end = ret.second;
- for (;it != it_end; ++it) {
- if ( _header.get<field_map>().replace(it, field(field_name, field_value)) ) {
- replaced = true;
- this->modified = true;
- }
- }
- if (!replaced) {
- _header.get<field_map>().insert( field(field_name, field_value) );
- this->modified = true;
- }
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : field_range http_message::header(std::string field_name, std::string field_value)");
- }
- /*------ DEBUG LOG END ------*/
-}
-
-/*!
- * Get message body function.
- *
- * @return message body
- */
-std::string http_message::body()
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : std::string http_message::body(void)");
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : std::string http_message::body(void) : "
- "return(%s)", this->_body.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- return this->_body;
-}
-
-/*!
- * Set message body function.
- * Set new message body and return old message body.
- *
- * @param[in] _body new message body
- * @return old message body
- */
-std::string http_message::body(std::string _body)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : std::string http_message::http_version(std::string _message) : "
- "_body(%s)", _body.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- std::string ret = this->_body;
- this->_body = _body;
- this->modified = true;
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : std::string http_message::body(std::string _body) : "
- "return(%s)", ret.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- return ret;
-}
-
-/*!
- * Get full HTTP message function.
- *
- * @return HTTP message
- */
-std::string http_message::as_string()
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : std::string http_message::as_string(void)");
- }
- /*------ DEBUG LOG END ------*/
-
- if (this->modified)
- this->rebuild();
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : std::string http_message::as_string(void) : "
- "return(%s)", this->raw_message.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- return this->raw_message;
-}
-
-/*!
- * Parse HTTP header function.
- *
- * @param[in] message full HTTP message header
- */
-void http_message::parse(std::string message)
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : void http_message::parse(std::string message) : "
- "message(%s)", message.c_str());
- }
- /*------ DEBUG LOG END ------*/
-
- // save raw message
- this->raw_message = message;
-
- // parse message
- HTTP_MESSAGE_POSITION pos = MESSAGE_TOP;
-
- /*
- * RFC2616
- * OCTET : 8bit data
- * CHAR : US-ASCII(0-127)
- * UPALPHA : A-Z
- * LOALPHA : a-z
- * ALPHA : UPALPHA | LOALPHA
- * DIGIT : 0-9
- * HEXDIG : A-F | a-f | DIGIT
- * SP : SPace(32)
- * HT : Horizontal Tab(9)
- * CR : Carriage Return(13)
- * LF : Line Feed(10)
- * CTL : ConTLol char(0-31,127)
- * LWS : [CRLF] 1*(SP|HT)
- * separators : ()<>@,;:\"/[]?={} and SP, HT
- * token : 1*(CHAR not CTL, separators)
- */
- std::string::iterator ptr = message.begin();
- std::string::iterator end = message.end();
- std::string::iterator start = ptr;
- std::pair<std::string, std::string> field_pair;
- while (ptr != end) {
- switch(pos) {
- /*
- * MESSAGE-HEADER : field-name ":" [ field-value ]
- * field-name : token
- * field-value : *( field-content | LWS )
- * field-content : <the OCTETs making up the field-value and
- * consisting of either *TEXT or combinations
- * of token, separators, and quoted-string>
- * TEXT : <any OCTET except CTLs, but including LWS>
- * quoted-string : ( <"> *(qdtext | quoted-pair ) <"> )
- * qdtext : <any TEXT except <">>
- * quoted-pair : "\" CHAR
- */
- case MESSAGE_TOP:
- if (isalpha(*ptr) || *ptr == '-' || isdigit(*ptr) ||
- *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == '!' ||
- *ptr == '$' || *ptr == '&' || *ptr == '*' || *ptr == '+' ||
- *ptr == '%') {
- start = ptr;
- pos = MESSAGE_FIELD_NAME;
- } else if (*ptr == '\r') { // CRLF + CRLF
- pos = MESSAGE_LAST_CR;
- } else {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : not CRLF");
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- case MESSAGE_CR:
- // LF only
- if (*ptr == '\n') {
- pos = MESSAGE_LF;
- } else {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_request::parse(std::string request) : not CRLF");
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- case MESSAGE_LF:
- if (isalpha(*ptr) || *ptr == '-' || isdigit(*ptr) ||
- *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == '!' ||
- *ptr == '$' || *ptr == '&' || *ptr == '*' || *ptr == '+' ||
- *ptr == '%') {
- if (field_pair.first.length()) {
- _header.get<field_map>().insert(field_pair);
- field_pair.first.clear();
- }
- start = ptr;
- pos = MESSAGE_FIELD_NAME;
- } else if (*ptr == ' ' || *ptr == '\t') {
- pos = MESSAGE_FIELD_VALUE;
- } else if (*ptr == '\r') { // CRLF + CRLF
- if (field_pair.first.length()) {
- _header.get<field_map>().insert(field_pair);
- field_pair.first.clear();
- }
- pos = MESSAGE_LAST_CR;
- } else {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : not CRLF");
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- case MESSAGE_FIELD_NAME:
- // field-name end with ':'
- if (*ptr == ':') {
- pos = MESSAGE_FIELD_NAME_COLON;
- field_pair.first.assign(start, ptr);
- } else if (!isalpha(*ptr) && *ptr != '-' && !isdigit(*ptr) &&
- *ptr != '.' && *ptr != '_' && *ptr != '~' && *ptr != '!' &&
- *ptr != '$' && *ptr != '&' && *ptr != '*' && *ptr != '+' &&
- *ptr != '%') {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : Invalid header field name.");
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- case MESSAGE_FIELD_NAME_COLON:
- if (*ptr == ' ' || isalpha(*ptr) || isdigit(*ptr) || *ptr == '-' ||
- *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == ':' ||
- *ptr == '@' || *ptr == '!' || *ptr == '$' || *ptr == '&' ||
- *ptr == '(' || *ptr == ')' || *ptr == '*' || *ptr == '+' ||
- *ptr == ',' || *ptr == ';' || *ptr == '=' || *ptr == '%' ||
- *ptr == '<' || *ptr == '>' || *ptr == '[' || *ptr == ']' ||
- *ptr == '{' || *ptr == '}' || *ptr == '?' || *ptr == '"' ||
- *ptr == '|' || *ptr == '/' || *ptr == '\\' || *ptr == '\t') {
- start = ptr;
- pos = MESSAGE_FIELD_VALUE;
- } else if (*ptr == '\r') { // omit field value
- field_pair.second.clear();
- } else {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : Invalid header field value.('%c')", *ptr);
- }
- /*------ DEBUG LOG END ------*/
- }
- break;
-
- case MESSAGE_FIELD_VALUE:
- // field-value end with CR
- if (*ptr == '\r') {
- pos = MESSAGE_CR;
- field_pair.second.assign(start, ptr);
- } else if (*ptr != ' ' && !isalpha(*ptr) && !isdigit(*ptr) && *ptr != '-' &&
- *ptr != '.' && *ptr != '_' && *ptr != '~' && *ptr != ':' &&
- *ptr != '@' && *ptr != '!' && *ptr != '$' && *ptr != '&' &&
- *ptr != '(' && *ptr != ')' && *ptr != '*' && *ptr != '+' &&
- *ptr != ',' && *ptr != ';' && *ptr != '=' && *ptr != '%' &&
- *ptr != '<' && *ptr != '>' && *ptr != '[' && *ptr != ']' &&
- *ptr != '{' && *ptr != '}' && *ptr != '?' && *ptr != '"' &&
- *ptr != '|' && *ptr != '/' && *ptr != '\\'&& *ptr != '\t' ) {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : Invalid header field value.('%c')", *ptr);
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- case MESSAGE_LAST_CR:
- // LF only
- if (*ptr == '\n') {
- pos = MESSAGE_LAST_LF;
- } else {
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message) : not CRLF");
- }
- /*------ DEBUG LOG END ------*/
- throw -1;
- }
- break;
-
- /*
- * MESSAGE-BODY : *OCTET
- */
- case MESSAGE_LAST_LF:
- pos = MESSAGE_BODY;
- start = ptr;
- break;
-
- case MESSAGE_BODY:
- break;
- }
- ptr++;
- }
-
- switch (pos) {
- case MESSAGE_BODY:
- this->_body.assign(start, ptr);
- }
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::parse(std::string message)");
- }
- /*------ DEBUG LOG END ------*/
-}
-
-/*!
- * Rebuild HTTP header function.
- */
-void http_message::rebuild()
-{
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "in_function : void http_message::rebuild()");
- }
- /*------ DEBUG LOG END ------*/
-
- // insertion order
- header_container::iterator it = this->_header.begin();
- header_container::iterator it_end = this->_header.end();
-
- while (it != it_end) {
- this->raw_message += it->first + ": " + it->second + "\r\n";
- it++;
- }
-
- this->raw_message += "\r\n" + this->body();
-
- /*-------- DEBUG LOG --------*/
- if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
- LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
- "out_function : void http_message::rebuild()");
- }
- /*------ DEBUG LOG END ------*/
-}
-
-
-
-//============================
-
-void printheader(http_message& message, std::string name) {
- field_range r;
- r = message.header(name);
- while (r.first != r.second) {
- std::cout << "=======> HEADER(" << r.first->first << "): " << r.first->second<< std::endl;
- r.first++;
- }
-}
-
-void changeheader(http_message& message, std::string name, std::string value) {
- message.header(name, value);
- printheader(message, name);
-}
-
-int main() {
-
- try {
- http_message message("POST /index HTTP/1.1\r\nHost: localhost\r\nX-Forwarded-For: localhost\r\n foobar\r\nAccept: */*\r\n\r\nMessageBODY");
- std::cout << message.as_string() << std::endl;
- printheader(message, "Host");
- printheader(message, "X-Forwarded-For");
- printheader(message, "Accept");
- printheader(message, "Test");
- changeheader(message, "Test", "new test");
- changeheader(message, "Host", "new host");
- std::cout << message.as_string() << std::endl;
- std::cout << message.body("type=project&id=303") << std::endl;
- std::cout << message.body() << std::endl;
- std::cout << message.as_string() << std::endl;
- }
- catch(...) {}
-
- try {
- http_message r;
- r.header("Host", "img.unitcom.co.jp");
- r.header("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)");
- r.header("Accept", "image/png,image/*;q=0.8,*/*;q=0.5");
- r.header("Accept-Language", "ja,en-us;q=0.7,en;q=0.3");
- r.header("Accept-Encoding", "gzip,deflate");
- r.header("Accept-Charset", "Shift_JIS,utf-8;q=0.7,*;q=0.7");
- r.header("Keep-Alive", "300");
- r.header("Connection", "keep-alive");
- r.header("Referer", "http://www.faith-go.co.jp/special/");
- r.header("Cookie", "ASPSESSIONIDQCCQBQBR=HHKHICIACCKKHPIIECCOBOJG");
- r.body("TEST__TEST");
- std::cout << r.as_string() << std::endl;
- }
- catch(...) {}
-
- try {
-std::string text =
-"Host: 192.168.0.4:7780\r\n"
-"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)\r\n"
-"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
-"Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n"
-"Accept-Encoding: gzip,deflate\r\n"
-"Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
-"Keep-Alive: 300\r\n"
-"Connection: keep-alive\r\n"
-"Cookie: rh_omni_tc=70160000000H4AoAAK; __utma=225840474.262789985507525570.1236909895.1236909895.1236909895.1; __utmz=225840474.1236909895.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); sch_target=mygroup; sch_d=3; sch_m=5; sch_y=2009; sch_move=weekly; PHPSESSID=pfn9gu39gkfq3cn16cr70q12b5; circular_kwd=; room_target=all; room_move=weekly; room_y=2009; room_m=4; room_d=27\r\n"
-"Cache-Control: max-age=0\r\n"
-"\r\n";
- http_message re(text);
- std::cout << re.as_string() << std::endl;
- }
- catch(...){}
- return 0;
-}