OSDN Git Service

2d6b39d38fc412a23ffbd43f41d0a4ea037c6953
[ultramonkey-l7/sslproxy.git] / include / http_message.cpp
1 /*
2  * @file  http_message.cpp
3  * @brief module of HTTP Message
4  * @brief HTTP Message parser
5  *
6  * Copyright (C) 2009  NTT COMWARE Corporation.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24
25 #include "http_message.h"
26
27 /*!
28  * HTTP Message constructor.
29  */
30 http_message::http_message()
31     :
32     modified(false)
33 {
34     /*-------- DEBUG LOG --------*/
35     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
36         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 1, // XXX log
37         "in/out_function : Constructor http_message::http_message(void)");
38     }
39     /*------ DEBUG LOG END ------*/
40 }
41
42 /*!
43  * HTTP Message constructor.
44  * Parse HTTP message header.
45  *
46  * @param[in]   header  full http message header string
47  */
48 http_message::http_message(std::string header)
49     :
50     modified(false)
51 {
52     /*-------- DEBUG LOG --------*/
53     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
54         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 1, // XXX log
55         "in/out_function : Constructor http_message::http_message(std::string header) : "
56         "header(%s)", header.c_str());
57     }
58     /*------ DEBUG LOG END ------*/
59     this->parse(header);
60 }
61
62 /*!
63  * HTTP Message destructor.
64  */
65 http_message::~http_message()
66 {
67     /*-------- DEBUG LOG --------*/
68     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
69         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 2, // XXX log
70         "in/out_function : Destructor http_message::~http_message(void)");
71     }
72     /*------ DEBUG LOG END ------*/
73 }
74
75 /*!
76  * Get HTTP header field function.
77  *
78  * @param[in]   field_name  lookup field name
79  * @return      header field value
80  */
81 field_range http_message::header(std::string field_name)
82 {
83     /*-------- DEBUG LOG --------*/
84     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
85         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
86         "in_function : field_range http_message::header(std::string field_name) : "
87         "field_name(%s)", field_name.c_str());
88     }
89     /*------ DEBUG LOG END ------*/
90
91     field_range ret = this->_header.get<field_map>().equal_range(field_name);
92
93     /*-------- DEBUG LOG --------*/
94     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
95         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
96         "out_function : field_range http_message::header(std::string field_name)");
97     }
98     /*------ DEBUG LOG END ------*/
99
100     return ret;
101 }
102
103 /*!
104  * Set HTTP header field function.
105  * Set new HTTP header field and return old HTTP header field.
106  *
107  * @param[in]   field_name  lookup field name
108  * @param[in]   field_value field value
109  */
110 void http_message::header(std::string field_name, std::string field_value)
111 {
112     /*-------- DEBUG LOG --------*/
113     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
114         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
115         "in_function : field_range http_message::header(std::string field_name, std::string field_value) : "
116         "field_name(%s), field_value(%s)", field_name.c_str(), field_value.c_str());
117     }
118     /*------ DEBUG LOG END ------*/
119
120     bool replaced = false;
121     field_range ret = this->_header.get<field_map>().equal_range(field_name);
122     field_map_iterator it = ret.first;
123     field_map_iterator it_end = ret.second;
124     for (;it != it_end; ++it) {
125         if ( _header.get<field_map>().replace(it, field(field_name, field_value)) ) {
126             replaced = true;
127             this->modified = true;
128         }
129     }
130     if (!replaced) {
131         _header.get<field_map>().insert( field(field_name, field_value) );
132         this->modified = true;
133     }
134
135     /*-------- DEBUG LOG --------*/
136     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
137         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
138         "out_function : field_range http_message::header(std::string field_name, std::string field_value)");
139     }
140     /*------ DEBUG LOG END ------*/
141 }
142
143 /*!
144  * Get message body function.
145  *
146  * @return    message body
147  */
148 std::string http_message::body()
149 {
150     /*-------- DEBUG LOG --------*/
151     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
152         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
153         "in_function : std::string http_message::body(void)");
154         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
155         "out_function : std::string http_message::body(void) : "
156         "return(%s)", this->_body.c_str());
157     }
158     /*------ DEBUG LOG END ------*/
159
160     return this->_body;
161 }
162
163 /*!
164  * Set message body function.
165  * Set new message body and return old message body.
166  *
167  * @param[in]   _body   new message body
168  * @return  old message body
169  */
170 std::string http_message::body(std::string _body)
171 {
172     /*-------- DEBUG LOG --------*/
173     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
174         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
175         "in_function : std::string http_message::http_version(std::string _message) : "
176         "_body(%s)", _body.c_str());
177     }
178     /*------ DEBUG LOG END ------*/
179
180     std::string ret = this->_body;
181     this->_body = _body;
182     this->modified = true;
183
184     /*-------- DEBUG LOG --------*/
185     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
186         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
187         "out_function : std::string http_message::body(std::string _body) : "
188         "return(%s)", ret.c_str());
189     }
190     /*------ DEBUG LOG END ------*/
191
192     return ret;
193 }
194
195 /*!
196  * Get full HTTP message function.
197  *
198  * @return    HTTP message
199  */
200 std::string http_message::as_string()
201 {
202     /*-------- DEBUG LOG --------*/
203     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
204         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
205         "in_function : std::string http_message::as_string(void)");
206     }
207     /*------ DEBUG LOG END ------*/
208
209     if (this->modified)
210         this->rebuild();
211
212     /*-------- DEBUG LOG --------*/
213     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
214         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
215         "out_function : std::string http_message::as_string(void) : "
216         "return(%s)", this->raw_message.c_str());
217     }
218     /*------ DEBUG LOG END ------*/
219
220     return this->raw_message;
221 }
222
223 /*!
224  * Parse HTTP header function.
225  *
226  * @param[in]   message     full HTTP message header
227  */
228 void http_message::parse(std::string message)
229 {
230     /*-------- DEBUG LOG --------*/
231     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
232         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
233         "in_function : void http_message::parse(std::string message) : "
234         "message(%s)", message.c_str());
235     }
236     /*------ DEBUG LOG END ------*/
237
238     // save raw message
239     this->raw_message = message;
240
241     // parse message
242     HTTP_MESSAGE_POSITION pos = MESSAGE_TOP;
243
244     /*
245      * RFC2616
246      *  OCTET       : 8bit data
247      *  CHAR        : US-ASCII(0-127)
248      *  UPALPHA     : A-Z
249      *  LOALPHA     : a-z
250      *  ALPHA       : UPALPHA | LOALPHA
251      *  DIGIT       : 0-9
252      *  HEXDIG      : A-F | a-f | DIGIT
253      *  SP          : SPace(32)
254      *  HT          : Horizontal Tab(9)
255      *  CR          : Carriage Return(13)
256      *  LF          : Line Feed(10)
257      *  CTL         : ConTLol char(0-31,127)
258      *  LWS         : [CRLF] 1*(SP|HT)
259      *  separators  : ()<>@,;:\"/[]?={} and SP, HT
260      *  token       : 1*(CHAR not CTL, separators)
261      */
262     std::string::iterator ptr = message.begin();
263     std::string::iterator end = message.end();
264     std::string::iterator start = ptr;
265     std::pair<std::string, std::string> field_pair;
266     while (ptr != end) {
267         switch(pos) {
268         /*
269          * MESSAGE-HEADER   : field-name ":" [ field-value ]
270          * field-name       : token
271          * field-value      : *( field-content | LWS )
272          * field-content    : <the OCTETs making up the field-value and
273          *                    consisting of either *TEXT or combinations
274          *                    of token, separators, and quoted-string>
275          * TEXT             : <any OCTET except CTLs, but including LWS>
276          * quoted-string    : ( <"> *(qdtext | quoted-pair ) <"> )
277          * qdtext           : <any TEXT except <">>
278          * quoted-pair      : "\" CHAR
279          */
280         case MESSAGE_TOP:
281             if (isalpha(*ptr) || *ptr == '-' || isdigit(*ptr) || 
282                 *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == '!' ||
283                 *ptr == '$' || *ptr == '&' || *ptr == '*' || *ptr == '+' ||
284                 *ptr == '%') {
285                 start = ptr;
286                 pos = MESSAGE_FIELD_NAME;
287             } else if (*ptr == '\r') { // CRLF + CRLF
288                 pos = MESSAGE_LAST_CR;
289             } else {
290                 /*-------- DEBUG LOG --------*/
291                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
292                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
293                     "out_function : void http_message::parse(std::string message) : not CRLF");
294                 }
295                 /*------ DEBUG LOG END ------*/
296                 throw -1;
297             }
298             break;
299
300         case MESSAGE_CR:
301             // LF only
302             if (*ptr == '\n') {
303                 pos = MESSAGE_LF;
304             } else {
305                 /*-------- DEBUG LOG --------*/
306                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
307                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
308                     "out_function : void http_request::parse(std::string request) : not CRLF");
309                 }
310                 /*------ DEBUG LOG END ------*/
311                 throw -1;
312             }
313             break;
314
315         case MESSAGE_LF:
316             if (isalpha(*ptr) || *ptr == '-' || isdigit(*ptr) || 
317                 *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == '!' ||
318                 *ptr == '$' || *ptr == '&' || *ptr == '*' || *ptr == '+' ||
319                 *ptr == '%') {
320                 if (field_pair.first.length()) {
321                     _header.get<field_map>().insert(field_pair);
322                     field_pair.first.clear();
323                 }
324                 start = ptr;
325                 pos = MESSAGE_FIELD_NAME;
326             } else if (*ptr == ' ' || *ptr == '\t') {
327                 pos = MESSAGE_FIELD_VALUE;
328             } else if (*ptr == '\r') { // CRLF + CRLF
329                 if (field_pair.first.length()) {
330                     _header.get<field_map>().insert(field_pair);
331                     field_pair.first.clear();
332                 }
333                 pos = MESSAGE_LAST_CR;
334             } else {
335                 /*-------- DEBUG LOG --------*/
336                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
337                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
338                     "out_function : void http_message::parse(std::string message) : not CRLF");
339                 }
340                 /*------ DEBUG LOG END ------*/
341                 throw -1;
342             }
343             break;
344
345         case MESSAGE_FIELD_NAME:
346             // field-name end with ':'
347             if (*ptr == ':') {
348                 pos = MESSAGE_FIELD_NAME_COLON;
349                 field_pair.first.assign(start, ptr);
350             } else if (!isalpha(*ptr) && *ptr != '-' && !isdigit(*ptr) && 
351                 *ptr != '.' && *ptr != '_' && *ptr != '~' && *ptr != '!' &&
352                 *ptr != '$' && *ptr != '&' && *ptr != '*' && *ptr != '+' &&
353                 *ptr != '%') {
354                 /*-------- DEBUG LOG --------*/
355                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
356                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
357                     "out_function : void http_message::parse(std::string message) : Invalid header field name.");
358                 }
359                 /*------ DEBUG LOG END ------*/
360                 throw -1;
361             }
362             break;
363
364         case MESSAGE_FIELD_NAME_COLON:
365             if (*ptr == ' ' || isalpha(*ptr) || isdigit(*ptr) || *ptr == '-' ||
366                 *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == ':' || 
367                 *ptr == '@' || *ptr == '!' || *ptr == '$' || *ptr == '&' ||
368                 *ptr == '(' || *ptr == ')' || *ptr == '*' || *ptr == '+' ||
369                 *ptr == ',' || *ptr == ';' || *ptr == '=' || *ptr == '%' ||
370                 *ptr == '<' || *ptr == '>' || *ptr == '[' || *ptr == ']' ||
371                 *ptr == '{' || *ptr == '}' || *ptr == '?' || *ptr == '"' ||
372                 *ptr == '|' || *ptr == '/' || *ptr == '\\' || *ptr == '\t') {
373                 start = ptr;
374                 pos = MESSAGE_FIELD_VALUE;
375             } else if (*ptr == '\r') { // omit field value
376                 field_pair.second.clear();
377             } else {
378                 /*-------- DEBUG LOG --------*/
379                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
380                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
381                     "out_function : void http_message::parse(std::string message) : Invalid header field value.('%c')", *ptr);
382                 }
383                 /*------ DEBUG LOG END ------*/
384             }
385             break;
386
387         case MESSAGE_FIELD_VALUE:
388             // field-value end with CR
389             if (*ptr == '\r') {
390                 pos = MESSAGE_CR;
391                 field_pair.second.assign(start, ptr);
392             } else if (*ptr != ' ' && !isalpha(*ptr) && !isdigit(*ptr) && *ptr != '-' &&
393                 *ptr != '.' && *ptr != '_' && *ptr != '~' && *ptr != ':' && 
394                 *ptr != '@' && *ptr != '!' && *ptr != '$' && *ptr != '&' &&
395                 *ptr != '(' && *ptr != ')' && *ptr != '*' && *ptr != '+' &&
396                 *ptr != ',' && *ptr != ';' && *ptr != '=' && *ptr != '%' &&
397                 *ptr != '<' && *ptr != '>' && *ptr != '[' && *ptr != ']' &&
398                 *ptr != '{' && *ptr != '}' && *ptr != '?' && *ptr != '"' &&
399                 *ptr != '|' && *ptr != '/' && *ptr != '\\'&& *ptr != '\t' ) {
400                 /*-------- DEBUG LOG --------*/
401                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
402                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
403                     "out_function : void http_message::parse(std::string message) : Invalid header field value.('%c')", *ptr);
404                 }
405                 /*------ DEBUG LOG END ------*/
406                 throw -1;
407             }
408             break;
409
410         case MESSAGE_LAST_CR:
411             // LF only
412             if (*ptr == '\n') {
413                 pos = MESSAGE_LAST_LF;
414             } else {
415                 /*-------- DEBUG LOG --------*/
416                 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
417                     LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
418                     "out_function : void http_message::parse(std::string message) : not CRLF");
419                 }
420                 /*------ DEBUG LOG END ------*/
421                 throw -1;
422             }
423             break;
424
425         /*
426          * MESSAGE-BODY     : *OCTET
427          */
428         case MESSAGE_LAST_LF:
429             pos = MESSAGE_BODY;
430             start = ptr;
431             break;
432
433         case MESSAGE_BODY:
434             break;
435         }
436         ptr++;
437     }
438
439     switch (pos) {
440     case MESSAGE_BODY:
441         this->_body.assign(start, ptr);
442     }
443
444     /*-------- DEBUG LOG --------*/
445     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
446         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
447         "out_function : void http_message::parse(std::string message)");
448     }
449     /*------ DEBUG LOG END ------*/
450 }
451
452 /*!
453  * Rebuild HTTP header function.
454  */
455 void http_message::rebuild()
456 {
457     /*-------- DEBUG LOG --------*/
458     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
459         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
460         "in_function : void http_message::rebuild()");
461     }
462     /*------ DEBUG LOG END ------*/
463
464     // insertion order
465     header_container::iterator it = this->_header.begin();
466     header_container::iterator it_end = this->_header.end();
467
468     while (it != it_end) {
469         this->raw_message += it->first + ": " + it->second + "\r\n";
470         it++;
471     }
472
473     this->raw_message += "\r\n" + this->body();
474
475     /*-------- DEBUG LOG --------*/
476     if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
477         LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
478         "out_function : void http_message::rebuild()");
479     }
480     /*------ DEBUG LOG END ------*/
481 }
482
483
484
485 //============================
486
487 void printheader(http_message& message, std::string name) {
488         field_range r;
489         r = message.header(name);
490         while (r.first != r.second) {
491             std::cout << "=======> HEADER(" << r.first->first << "): " << r.first->second<< std::endl;
492             r.first++;
493         }
494 }
495
496 void changeheader(http_message& message, std::string name, std::string value) {
497         message.header(name, value);
498         printheader(message, name);
499 }
500
501 int main() {
502
503     try {
504         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");
505         std::cout << message.as_string() << std::endl;
506         printheader(message, "Host");
507         printheader(message, "X-Forwarded-For");
508         printheader(message, "Accept");
509         printheader(message, "Test");
510         changeheader(message, "Test", "new test");
511         changeheader(message, "Host", "new host");
512         std::cout << message.as_string() << std::endl;
513         std::cout << message.body("type=project&id=303") << std::endl;
514         std::cout << message.body() << std::endl;
515         std::cout << message.as_string() << std::endl;
516     }
517     catch(...) {}
518
519     try {
520         http_message r;
521         r.header("Host", "img.unitcom.co.jp");
522         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)");
523         r.header("Accept", "image/png,image/*;q=0.8,*/*;q=0.5");
524         r.header("Accept-Language", "ja,en-us;q=0.7,en;q=0.3");
525         r.header("Accept-Encoding", "gzip,deflate");
526         r.header("Accept-Charset", "Shift_JIS,utf-8;q=0.7,*;q=0.7");
527         r.header("Keep-Alive", "300");
528         r.header("Connection", "keep-alive");
529         r.header("Referer", "http://www.faith-go.co.jp/special/");
530         r.header("Cookie", "ASPSESSIONIDQCCQBQBR=HHKHICIACCKKHPIIECCOBOJG");
531         r.body("TEST__TEST");
532         std::cout << r.as_string() << std::endl;
533     }
534     catch(...) {}
535
536     try {
537 std::string text = 
538 "Host: 192.168.0.4:7780\r\n"
539 "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"
540 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
541 "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n"
542 "Accept-Encoding: gzip,deflate\r\n"
543 "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
544 "Keep-Alive: 300\r\n"
545 "Connection: keep-alive\r\n"
546 "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"
547 "Cache-Control: max-age=0\r\n"
548 "\r\n";
549         http_message re(text);
550         std::cout << re.as_string() << std::endl;
551     }
552     catch(...){}
553     return 0;
554 }