00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef _MSC_VER
00029 #pragma warning(disable:4786)
00030 #endif
00031 #include "Utility.h"
00032 #include "HttpdCookies.h"
00033 #include "HttpdForm.h"
00034 #include "MemFile.h"
00035 #include "HttpdSocket.h"
00036 #include "Base64.h"
00037
00038
00039 #ifdef SOCKETS_NAMESPACE
00040 namespace SOCKETS_NAMESPACE {
00041 #endif
00042
00043 #define TMPSIZE 10000
00044
00045
00046
00047 int HttpdSocket::m_request_count = 0;
00048 std::string HttpdSocket::m_start = "";
00049
00050
00051 HttpdSocket::HttpdSocket(ISocketHandler& h)
00052 :HTTPSocket(h)
00053 ,m_content_length(0)
00054 ,m_file(NULL)
00055 ,m_received(0)
00056 ,m_request_id(++m_request_count)
00057 ,m_cookies(NULL)
00058 ,m_form(NULL)
00059 {
00060 m_http_date = datetime2httpdate(GetDate());
00061 if (!m_start.size())
00062 m_start = m_http_date;
00063 }
00064
00065
00066 HttpdSocket::~HttpdSocket()
00067 {
00068 if (m_file)
00069 {
00070 delete m_file;
00071 }
00072 if (m_cookies)
00073 delete m_cookies;
00074 if (m_form)
00075 delete m_form;
00076 }
00077
00078
00079 void HttpdSocket::OnFirst()
00080 {
00081 }
00082
00083
00084 void HttpdSocket::OnHeader(const std::string& key,const std::string& value)
00085 {
00086 if (!strcasecmp(key.c_str(),"content-length"))
00087 {
00088 m_content_length = atoi(value.c_str());
00089 m_content_length_str = value;
00090 }
00091 else
00092 if (!strcasecmp(key.c_str(),"cookie"))
00093 {
00094 m_http_cookie = value;
00095 }
00096 else
00097 if (!strcasecmp(key.c_str(),"content-type"))
00098 {
00099 m_content_type = value;
00100 }
00101 else
00102 if (!strcasecmp(key.c_str(),"if-modified-since"))
00103 {
00104 m_if_modified_since = value;
00105 }
00106 }
00107
00108
00109 void HttpdSocket::OnHeaderComplete()
00110 {
00111 m_cookies = new HttpdCookies(m_http_cookie);
00112
00113 if (GetMethod() == "GET")
00114 {
00115 Utility::SetEnv("QUERY_STRING", GetQueryString());
00116 }
00117 Utility::SetEnv("REQUEST_METHOD", GetMethod());
00118 Utility::SetEnv("HTTP_COOKIE", m_http_cookie);
00119 Utility::SetEnv("CONTENT_TYPE", m_content_type);
00120 Utility::SetEnv("CONTENT_LENGTH", m_content_length_str);
00121 if (GetMethod() == "POST")
00122 {
00123 m_file = new MemFile;
00124 }
00125 else
00126 if (GetMethod() == "GET")
00127 {
00128 m_form = new HttpdForm(GetQueryString(), GetQueryString().size() );
00129 AddResponseHeader("Date", datetime2httpdate(GetDate()) );
00130 if (GetUri() == "/image")
00131 {
00132 Send64(Utility::Logo, "image/png");
00133 }
00134 else
00135 {
00136 Exec();
00137 }
00138 Reset();
00139 }
00140 else
00141 {
00142 AddResponseHeader("Date", GetHttpDate());
00143 AddResponseHeader("Connection", "close");
00144 SetStatus("405");
00145 SetStatusText("Method not allowed");
00146 SendResponse();
00147 }
00148 }
00149
00150
00151 void HttpdSocket::OnData(const char *p,size_t l)
00152 {
00153 if (m_file)
00154 {
00155 m_file -> fwrite(p,1,l);
00156 }
00157 m_received += l;
00158 if (m_received >= m_content_length && m_content_length)
00159 {
00160
00161 if (m_file && !m_form)
00162 {
00163 m_form = new HttpdForm(m_file, m_content_type, m_content_length);
00164 AddResponseHeader("Date", datetime2httpdate(GetDate()) );
00165 if (GetUri() == "/image")
00166 {
00167 Send64(Utility::Logo, "image/png");
00168 }
00169 else
00170 {
00171 Exec();
00172 }
00173 Reset();
00174 }
00175 }
00176 }
00177
00178
00179 void HttpdSocket::Send64(const std::string& str64, const std::string& type)
00180 {
00181 Base64 bb;
00182
00183 if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str()))
00184 {
00185 SetStatus("304");
00186 SetStatusText("Not Modified");
00187 SendResponse();
00188 }
00189 else
00190 {
00191 size_t len = bb.decode_length(str64);
00192 unsigned char *buf = new unsigned char[len];
00193
00194 SetStatus("200");
00195 SetStatusText("OK");
00196
00197 AddResponseHeader("Content-length", Utility::l2string( (long)len) );
00198 AddResponseHeader("Content-type", type );
00199 AddResponseHeader("Last-modified", m_start);
00200 SendResponse();
00201
00202 bb.decode(str64, buf, len);
00203 SendBuf( (char *)buf, len);
00204 delete[] buf;
00205 }
00206 }
00207
00208
00209 std::string HttpdSocket::datetime2httpdate(const std::string& dt)
00210 {
00211 struct tm tp;
00212 time_t t;
00213 const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
00214 const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun",
00215 "Jul","Aug","Sep","Oct","Nov","Dec" };
00216 int i;
00217 char s[40];
00218
00219
00220
00221 if (dt.size() == 19)
00222 {
00223 tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900;
00224 i = atoi(dt.substr(5,2).c_str()) - 1;
00225 tp.tm_mon = i >= 0 ? i : 0;
00226 tp.tm_mday = atoi(dt.substr(8,2).c_str());
00227 tp.tm_hour = atoi(dt.substr(11,2).c_str());
00228 tp.tm_min = atoi(dt.substr(14,2).c_str());
00229 tp.tm_sec = atoi(dt.substr(17,2).c_str());
00230 tp.tm_wday = 0;
00231 tp.tm_yday = 0;
00232 tp.tm_isdst = 0;
00233 t = mktime(&tp);
00234 if (t == -1)
00235 {
00236 Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed");
00237 }
00238
00239 sprintf(s,"%s, %02d %s %d %02d:%02d:%02d GMT",
00240 days[tp.tm_wday],
00241 tp.tm_mday,
00242 months[tp.tm_mon],
00243 tp.tm_year + 1900,
00244 tp.tm_hour,tp.tm_min,tp.tm_sec);
00245 }
00246 else
00247 {
00248 *s = 0;
00249 }
00250 return s;
00251 }
00252
00253
00254 std::string HttpdSocket::GetDate()
00255 {
00256 time_t t = time(NULL);
00257 struct tm tp;
00258 #ifdef _WIN32
00259 memcpy(&tp, localtime(&t), sizeof(tp));
00260 #else
00261 localtime_r(&t, &tp);
00262 #endif
00263 char slask[40];
00264 sprintf(slask,"%d-%02d-%02d %02d:%02d:%02d",
00265 tp.tm_year + 1900,
00266 tp.tm_mon + 1,
00267 tp.tm_mday,
00268 tp.tm_hour,tp.tm_min,tp.tm_sec);
00269 return slask;
00270 }
00271
00272
00273 void HttpdSocket::Reset()
00274 {
00275 HTTPSocket::Reset();
00276 m_content_length = 0;
00277 if (m_file)
00278 {
00279 delete m_file;
00280 m_file = NULL;
00281 }
00282 m_received = 0;
00283 m_request_id = ++m_request_count;
00284 if (m_cookies)
00285 delete m_cookies;
00286 m_cookies = NULL;
00287 if (m_form)
00288 delete m_form;
00289 m_form = NULL;
00290 }
00291
00292
00293 const std::string& HttpdSocket::GetHttpDate() const
00294 {
00295 return m_http_date;
00296 }
00297
00298
00299 HttpdCookies *HttpdSocket::GetCookies()
00300 {
00301 return m_cookies;
00302 }
00303
00304
00305 const HttpdForm *HttpdSocket::GetForm() const
00306 {
00307 return m_form;
00308 }
00309
00310
00311
00312 #ifdef SOCKETS_NAMESPACE
00313 }
00314 #endif
00315
00316