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