1 // src/HttpResponse.cc
2 // This file is part of libpbe; see http://anyterm.org/
3 // (C) 2005-2008 Philip Endecott
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19
20 #include "HttpResponse.hh"
21
22 #include "FileDescriptor.hh"
23 #include "mustfind.hh"
24
25 #include <boost/lexical_cast.hpp>
26
27 #include <sstream>
28 #include <functional>
29
30 using namespace std;
31
32
33 namespace pbe {
34
35
send_chunked(ostream & strm,string data)36 static void send_chunked(ostream& strm, string data)
37 {
38 strm << hex << data.length() << "\r\n"
39 << data << "\r\n"
40 << "0\r\n"
41 << "\r\n";
42 }
43
44
send(FileDescriptor & fd)45 void HttpResponse::send(FileDescriptor& fd)
46 {
47 ostringstream s;
48 s << http_version << ' ' << status_code << ' ' << reason_phrase << "\r\n";
49 for (map<string,string>::const_iterator i = headers.begin();
50 i != headers.end(); ++i) {
51 s << i->first << ": " << i->second << "\r\n";
52 }
53 s << "Transfer-Encoding: chunked\r\n"
54 << "\r\n";
55 if (body.length()==0) {
56 s << "0\r\n\r\n";
57 } else {
58 send_chunked(s,body);
59 }
60
61 fd.writeall(s.str());
62 }
63
64
get_line(string & s)65 static string get_line(string& s)
66 {
67 string crlf = "\r\n";
68 string::iterator i = mustsearch(s.begin(),s.end(),crlf.begin(),crlf.end());
69 string l(s.begin(),i);
70 s = string(i+2,s.end());
71 return l;
72 }
73
74
HttpResponse(string s)75 HttpResponse::HttpResponse(string s)
76 {
77 const string response_line = get_line(s);
78 string::const_iterator sp1 = mustfind(response_line.begin(),response_line.end(),' ');
79 http_version = string(response_line.begin(),sp1);
80 string::const_iterator sp2 = mustfind(sp1+1,response_line.end(),' ');
81 status_code = boost::lexical_cast<int>(string(sp1+1,sp2));
82 reason_phrase = string(sp2+2,response_line.end());
83
84 while (1) {
85 const string hdr = get_line(s);
86 if (hdr.empty()) {
87 break;
88 }
89 string::const_iterator colon_pos = mustfind(hdr.begin(),hdr.end(),':');
90 const string hdr_name(hdr.begin(),colon_pos);
91 const string hdr_val(colon_pos+1,hdr.end());
92 const string trimmed_hdr_val(mustfind_if(hdr_val.begin(),hdr_val.end(),
93 bind2nd(not_equal_to<char>(),' ')),
94 hdr_val.end());
95 headers[hdr_name] = trimmed_hdr_val;
96 }
97
98 body = s;
99 }
100
101
102 };
103
104