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