4 |
|
// |
5 |
|
// $Id$ |
6 |
|
|
7 |
+ |
#include <arpa/inet.h> |
8 |
+ |
|
9 |
|
#include "Daemon.hpp" |
10 |
|
|
11 |
|
string Daemon::crlf("\r\n"); |
81 |
|
|
82 |
|
void Daemon::response(ostream& sout, Status status) |
83 |
|
{ |
84 |
< |
sout << "HTTP/1.1 " << status << ' '; |
85 |
< |
|
84 |
< |
switch (status) |
85 |
< |
{ |
86 |
< |
case ok: |
87 |
< |
sout << "OK"; |
88 |
< |
break; |
89 |
< |
case found: |
90 |
< |
sout << "Found"; |
91 |
< |
break; |
92 |
< |
case seeOther: |
93 |
< |
sout << "See Other"; |
94 |
< |
break; |
95 |
< |
case bad: |
96 |
< |
sout << "Bad Request"; |
97 |
< |
break; |
98 |
< |
case notFound: |
99 |
< |
sout << "Not Found"; |
100 |
< |
break; |
101 |
< |
case lengthRequired: |
102 |
< |
sout << "Length Required"; |
103 |
< |
break; |
104 |
< |
case mediaType: |
105 |
< |
sout << "Unsupported Media Type"; |
106 |
< |
break; |
107 |
< |
case serverError: |
108 |
< |
sout << "Internal Server Error"; |
109 |
< |
break; |
110 |
< |
case notImplemented: |
111 |
< |
sout << "Not Implemented"; |
112 |
< |
break; |
113 |
< |
case version: |
114 |
< |
sout << "HTTP Version not supported"; |
115 |
< |
} |
116 |
< |
|
117 |
< |
sout << crlf << "Date: " << date() << crlf << "Server: Smersh/0.9" << crlf |
84 |
> |
sout << "HTTP/1.1 " << status << ' ' << reason(status) << crlf << "Date: " |
85 |
> |
<< date() << crlf << "Server: Smersh/0.9" << crlf |
86 |
|
<< "Connection: close" << crlf; |
87 |
|
} |
88 |
|
|
89 |
< |
void Daemon::error(ostream& sout, Status status) |
89 |
> |
streamsize Daemon::error(ostream& sout, Status status) |
90 |
|
{ |
91 |
< |
sout << crlf; |
91 |
> |
string reason(this->reason(status)); |
92 |
> |
ostringstream error; |
93 |
> |
|
94 |
> |
error << "<html><head><title>" << status << ' ' << reason << "</title></hea" |
95 |
> |
<< "d><body><h1>" << reason << "</h1><p>Mistakes were made, deal with t" |
96 |
> |
<< "hem.</p><hr /><address>Smersh/0.9</address></body></html>\n"; |
97 |
> |
sout << "Content-Length: " << error.str().length() << crlf |
98 |
> |
<< "Content-Type: text/html; charset=UTF-8\r\n\r\n" << error.str(); |
99 |
> |
|
100 |
> |
return error.str().size(); |
101 |
|
} |
102 |
|
|
103 |
|
string Daemon::date(bool log) |
115 |
|
return when; |
116 |
|
} |
117 |
|
|
118 |
+ |
string Daemon::ip(const api::TcpSocket& socket) |
119 |
+ |
{ |
120 |
+ |
api::InternetAddress address(socket.GetAddress()); |
121 |
+ |
|
122 |
+ |
return inet_ntoa(address->sin_addr); |
123 |
+ |
} |
124 |
+ |
|
125 |
|
int Daemon::handle(api::TcpSocket* client) |
126 |
|
{ |
127 |
|
ios::InputOutputStreamBufAdapter adapter(*client); |
133 |
|
|
134 |
|
response(sio, code); |
135 |
|
|
136 |
< |
if (code == ok) |
136 |
> |
bool head(env.get("REQUEST_METHOD") == "HEAD"); |
137 |
> |
streamsize sent(0); |
138 |
> |
|
139 |
> |
if (code == ok && !head) |
140 |
|
{ |
141 |
|
ostringstream output; |
142 |
|
Smersh smersh(post, output, env); |
143 |
|
string content(output.str().substr(40)); |
144 |
|
|
145 |
|
sio << "Content-Length: " << content.length() << crlf |
146 |
< |
<< "Content-Type: text/html; charset=UTF-8" << crlf << crlf; |
146 |
> |
<< "Content-Type: text/html; charset=UTF-8\r\n\r\n"; |
147 |
|
|
148 |
|
sio.write(content.data(), content.size()); |
149 |
+ |
|
150 |
+ |
sent = content.size(); |
151 |
|
} |
152 |
< |
else if (env.get("REQUEST_METHOD") != "HEAD") error(sio, code); |
153 |
< |
else sio << "Content-Type: text/html; charset=UTF-8" << crlf << crlf; |
152 |
> |
else if (head) sio << "Content-Type: text/html; charset=UTF-8\r\n\r\n"; |
153 |
> |
else sent = error(sio, code); |
154 |
|
|
155 |
< |
log << code << ' ' << 0 << " \"" << env.get("HTTP_REFERER") << "\" \"" |
155 |
> |
log << code << ' ' << (sent > 0 ? lexical_cast<string>(sent) : string("0")) |
156 |
> |
<< " \"" << env.get("HTTP_REFERER") << "\" \"" |
157 |
|
<< env.get("HTTP_USER_AGENT") << '"'; |
158 |
|
|
159 |
< |
if (debug) cerr << date(true) << ' ' << log.str() << '\n'; |
159 |
> |
ofstream fout(this->log.c_str(), ios_base::app); |
160 |
> |
|
161 |
> |
fout << ip(*client) << " - - " << date(true) << ' ' << log.str() << '\n'; |
162 |
|
|
163 |
|
delete client; |
164 |
|
} |
212 |
|
Daemon::Status Daemon::message(istream& sin, Environment& env, ostream& post) |
213 |
|
{ |
214 |
|
string contentLength(env.get("CONTENT_LENGTH")); |
215 |
< |
|
215 |
> |
|
216 |
|
if (env.get("CONTENT_TYPE") != "application/x-www-form-urlencoded") return |
217 |
|
mediaType; |
218 |
|
if (contentLength.empty()) return lengthRequired; |
227 |
|
|
228 |
|
return ok; |
229 |
|
} |
230 |
+ |
|
231 |
+ |
string Daemon::reason(Status status) |
232 |
+ |
{ |
233 |
+ |
ostringstream sout; |
234 |
+ |
|
235 |
+ |
switch (status) |
236 |
+ |
{ |
237 |
+ |
case ok: |
238 |
+ |
sout << "OK"; |
239 |
+ |
break; |
240 |
+ |
case found: |
241 |
+ |
sout << "Found"; |
242 |
+ |
break; |
243 |
+ |
case seeOther: |
244 |
+ |
sout << "See Other"; |
245 |
+ |
break; |
246 |
+ |
case bad: |
247 |
+ |
sout << "Bad Request"; |
248 |
+ |
break; |
249 |
+ |
case notFound: |
250 |
+ |
sout << "Not Found"; |
251 |
+ |
break; |
252 |
+ |
case lengthRequired: |
253 |
+ |
sout << "Length Required"; |
254 |
+ |
break; |
255 |
+ |
case mediaType: |
256 |
+ |
sout << "Unsupported Media Type"; |
257 |
+ |
break; |
258 |
+ |
case serverError: |
259 |
+ |
sout << "Internal Server Error"; |
260 |
+ |
break; |
261 |
+ |
case notImplemented: |
262 |
+ |
sout << "Not Implemented"; |
263 |
+ |
break; |
264 |
+ |
case version: |
265 |
+ |
sout << "HTTP Version not supported"; |
266 |
+ |
} |
267 |
+ |
|
268 |
+ |
return sout.str(); |
269 |
+ |
} |