00001 #include "stdafx.h"
00002 #include "mplayerc.h"
00003 #include "resource.h"
00004 #include "MainFrm.h"
00005 #include <atlbase.h>
00006 #include <atlisapi.h>
00007 #include "WebServerSocket.h"
00008 #include "WebClientSocket.h"
00009 #include "WebServer.h"
00010 #include "..\..\zlib\zlib.h"
00011
00012 CAtlMap<CString, CWebServer::RequestHandler, CStringElementTraits<CString> > CWebServer::m_internalpages;
00013 CAtlMap<CString, UINT, CStringElementTraits<CString> > CWebServer::m_downloads;
00014 CAtlMap<CStringA, CStringA, CStringElementTraits<CStringA> > CWebServer::m_mimes;
00015
00016 CWebServer::CWebServer(CMainFrame* pMainFrame, int nPort)
00017 : m_pMainFrame(pMainFrame)
00018 , m_nPort(nPort)
00019 {
00020 if(m_internalpages.IsEmpty())
00021 {
00022 m_internalpages[_T("/")] = &CWebClientSocket::OnIndex;
00023 m_internalpages[_T("/index.html")] = &CWebClientSocket::OnIndex;
00024 m_internalpages[_T("/browser.html")] = &CWebClientSocket::OnBrowser;
00025 m_internalpages[_T("/controls.html")] = &CWebClientSocket::OnControls;
00026 m_internalpages[_T("/command.html")] = &CWebClientSocket::OnCommand;
00027 m_internalpages[_T("/status.html")] = &CWebClientSocket::OnStatus;
00028 m_internalpages[_T("/player.html")] = &CWebClientSocket::OnPlayer;
00029 m_internalpages[_T("/snapshot.jpg")] = &CWebClientSocket::OnSnapShotJpeg;
00030 m_internalpages[_T("/404.html")] = &CWebClientSocket::OnError404;
00031 m_internalpages[_T("/convres.html")] = &CWebClientSocket::OnConvRes;
00032 }
00033
00034 if(m_downloads.IsEmpty())
00035 {
00036 m_downloads[_T("/default.css")] = IDF_DEFAULT_CSS;
00037 m_downloads[_T("/vbg.gif")] = IDF_VBR_GIF;
00038 m_downloads[_T("/vbs.gif")] = IDF_VBS_GIF;
00039 m_downloads[_T("/sliderbar.gif")] = IDF_SLIDERBAR_GIF;
00040 m_downloads[_T("/slidergrip.gif")] = IDF_SLIDERGRIP_GIF;
00041 m_downloads[_T("/sliderback.gif")] = IDF_SLIDERBACK_GIF;
00042 m_downloads[_T("/1pix.gif")] = IDF_1PIX_GIF;
00043 m_downloads[_T("/headericon.png")] = IDF_HEADERICON_PNG;
00044 m_downloads[_T("/headerback.png")] = IDF_HEADERBACK_PNG;
00045 m_downloads[_T("/headerclose.png")] = IDF_HEADERCLOSE_PNG;
00046 m_downloads[_T("/leftside.png")] = IDF_LEFTSIDE_PNG;
00047 m_downloads[_T("/rightside.png")] = IDF_RIGHTSIDE_PNG;
00048 m_downloads[_T("/bottomside.png")] = IDF_BOTTOMSIDE_PNG;
00049 m_downloads[_T("/leftbottomside.png")] = IDF_LEFTBOTTOMSIDE_PNG;
00050 m_downloads[_T("/rightbottomside.png")] = IDF_RIGHTBOTTOMSIDE_PNG;
00051 m_downloads[_T("/seekbarleft.png")] = IDF_SEEKBARLEFT_PNG;
00052 m_downloads[_T("/seekbarmid.png")] = IDF_SEEKBARMID_PNG;
00053 m_downloads[_T("/seekbarright.png")] = IDF_SEEKBARRIGHT_PNG;
00054 m_downloads[_T("/seekbargrip.png")] = IDF_SEEKBARGRIP_PNG;
00055 m_downloads[_T("/logo.png")] = IDF_LOGO_PNG;
00056 m_downloads[_T("/controlback.png")] = IDF_CONTROLBACK_PNG;
00057 m_downloads[_T("/controlbuttonplay.png")] = IDF_CONTROLBUTTONPLAY_PNG;
00058 m_downloads[_T("/controlbuttonpause.png")] = IDF_CONTROLBUTTONPAUSE_PNG;
00059 m_downloads[_T("/controlbuttonstop.png")] = IDF_CONTROLBUTTONSTOP_PNG;
00060 m_downloads[_T("/controlbuttonskipback.png")] = IDF_CONTROLBUTTONSKIPBACK_PNG;
00061 m_downloads[_T("/controlbuttondecrate.png")] = IDF_CONTROLBUTTONDECRATE_PNG;
00062 m_downloads[_T("/controlbuttonincrate.png")] = IDF_CONTROLBUTTONINCRATE_PNG;
00063 m_downloads[_T("/controlbuttonskipforward.png")] = IDF_CONTROLBUTTONSKIPFORWARD_PNG;
00064 m_downloads[_T("/controlbuttonstep.png")] = IDF_CONTROLBUTTONSTEP_PNG;
00065 m_downloads[_T("/controlvolumeon.png")] = IDF_CONTROLVOLUMEON_PNG;
00066 m_downloads[_T("/controlvolumeoff.png")] = IDF_CONTROLVOLUMEOFF_PNG;
00067 m_downloads[_T("/controlvolumebar.png")] = IDF_CONTROLVOLUMEBAR_PNG;
00068 m_downloads[_T("/controlvolumegrip.png")] = IDF_CONTROLVOLUMEGRIP_PNG;
00069 }
00070
00071 CRegKey key;
00072 CString str(_T("MIME\\Database\\Content Type"));
00073 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
00074 {
00075 TCHAR buff[256];
00076 DWORD len = countof(buff);
00077 for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = countof(buff))
00078 {
00079 CRegKey mime;
00080 TCHAR ext[64];
00081 ULONG len = countof(ext);
00082 if(ERROR_SUCCESS == mime.Open(HKEY_CLASSES_ROOT, str + _T("\\") + buff, KEY_READ)
00083 && ERROR_SUCCESS == mime.QueryStringValue(_T("Extension"), ext, &len))
00084 m_mimes[CStringA(ext).MakeLower()] = CStringA(buff).MakeLower();
00085 }
00086 }
00087
00088 m_mimes[".html"] = "text/html";
00089 m_mimes[".txt"] = "text/plain";
00090 m_mimes[".css"] = "text/css";
00091 m_mimes[".gif"] = "image/gif";
00092 m_mimes[".jpeg"] = "image/jpeg";
00093 m_mimes[".jpg"] = "image/jpeg";
00094 m_mimes[".png"] = "image/png";
00095
00096 GetModuleFileName(AfxGetInstanceHandle(), str.GetBuffer(MAX_PATH), MAX_PATH);
00097 str.ReleaseBuffer();
00098 m_webroot = CPath(str);
00099 m_webroot.RemoveFileSpec();
00100
00101 CString WebRoot = AfxGetAppSettings().WebRoot;
00102 WebRoot.Replace('/', '\\');
00103 WebRoot.Trim();
00104 CPath p(WebRoot);
00105 if(WebRoot.Find(_T(":\\")) < 0 && WebRoot.Find(_T("\\\\")) < 0) m_webroot.Append(WebRoot);
00106 else m_webroot = p;
00107 m_webroot.Canonicalize();
00108 m_webroot.MakePretty();
00109 if(!m_webroot.IsDirectory()) m_webroot = CPath();
00110
00111 CList<CString> sl;
00112 Explode(AfxGetAppSettings().WebServerCGI, sl, ';');
00113 POSITION pos = sl.GetHeadPosition();
00114 while(pos)
00115 {
00116 CList<CString> sl2;
00117 CString ext = Explode(sl.GetNext(pos), sl2, '=', 2);
00118 if(sl2.GetCount() < 2) continue;
00119 m_cgi[ext] = sl2.GetTail();
00120 }
00121
00122 m_ThreadId = 0;
00123 m_hThread = ::CreateThread(NULL, 0, StaticThreadProc, (LPVOID)this, 0, &m_ThreadId);
00124 }
00125
00126 CWebServer::~CWebServer()
00127 {
00128 if(m_hThread != NULL)
00129 {
00130 PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0);
00131 WaitForSingleObject(m_hThread, 10000);
00132 EXECUTE_ASSERT(CloseHandle(m_hThread));
00133 }
00134 }
00135
00136 DWORD WINAPI CWebServer::StaticThreadProc(LPVOID lpParam)
00137 {
00138 return ((CWebServer*)lpParam)->ThreadProc();
00139 }
00140
00141 DWORD CWebServer::ThreadProc()
00142 {
00143 if(!AfxSocketInit(NULL))
00144 return -1;
00145
00146 CWebServerSocket s(this, m_nPort);
00147
00148 MSG msg;
00149 while((int)GetMessage(&msg, NULL, 0, 0) > 0)
00150 {
00151 TranslateMessage(&msg);
00152 DispatchMessage(&msg);
00153 }
00154
00155 return 0;
00156 }
00157
00158 static void PutFileContents(LPCTSTR fn, const CStringA& data)
00159 {
00160 if(FILE* f = _tfopen(fn, _T("wb")))
00161 {
00162 fwrite((LPCSTR)data, 1, data.GetLength(), f);
00163 fclose(f);
00164 }
00165 }
00166
00167 void CWebServer::Deploy(CString dir)
00168 {
00169 CStringA data;
00170 if(LoadResource(IDR_HTML_INDEX, data, RT_HTML)) PutFileContents(dir + _T("index.html"), data);
00171 if(LoadResource(IDR_HTML_BROWSER, data, RT_HTML)) PutFileContents(dir + _T("browser.html"), data);
00172 if(LoadResource(IDR_HTML_CONTROLS, data, RT_HTML)) PutFileContents(dir + _T("controls.html"), data);
00173 if(LoadResource(IDR_HTML_404, data, RT_HTML)) PutFileContents(dir + _T("404.html"), data);
00174 if(LoadResource(IDR_HTML_PLAYER, data, RT_HTML)) PutFileContents(dir + _T("player.html"), data);
00175
00176 POSITION pos = m_downloads.GetStartPosition();
00177 while(pos)
00178 {
00179 CString fn;
00180 UINT id;
00181 m_downloads.GetNextAssoc(pos, fn, id);
00182 if(LoadResource(id, data, _T("FILE")))
00183 PutFileContents(dir + fn, data);
00184 }
00185 }
00186
00187 bool CWebServer::ToLocalPath(CString& path, CString& redir)
00188 {
00189 if(!path.IsEmpty() && m_webroot.IsDirectory())
00190 {
00191 CString str = path;
00192 str.Replace('/', '\\');
00193 str.TrimLeft('\\');
00194
00195 CPath p;
00196 p.Combine(m_webroot, str);
00197 p.Canonicalize();
00198
00199 if(p.IsDirectory())
00200 {
00201 CList<CString> sl;
00202 Explode(AfxGetAppSettings().WebDefIndex, sl, ';');
00203 POSITION pos = sl.GetHeadPosition();
00204 while(pos)
00205 {
00206 str = sl.GetNext(pos);
00207 CPath p2 = p;
00208 p2.Append(str);
00209 if(p2.FileExists())
00210 {
00211 p = p2;
00212 redir = path;
00213 if(redir.GetAt(redir.GetLength()-1) != '/') redir += '/';
00214 redir += str;
00215 break;
00216 }
00217 }
00218 }
00219
00220 if(_tcslen(p) > _tcslen(m_webroot) && p.FileExists())
00221 {
00222 path = (LPCTSTR)p;
00223 return true;
00224 }
00225 }
00226
00227 return false;
00228 }
00229
00230 bool CWebServer::LoadPage(UINT resid, CStringA& str, CString path)
00231 {
00232 CString redir;
00233 if(ToLocalPath(path, redir))
00234 {
00235 if(FILE* f = _tfopen(path, _T("rb")))
00236 {
00237 fseek(f, 0, 2);
00238 char* buff = str.GetBufferSetLength(ftell(f));
00239 fseek(f, 0, 0);
00240 int len = fread(buff, 1, str.GetLength(), f);
00241 fclose(f);
00242 return len == str.GetLength();
00243 }
00244 }
00245
00246 return LoadResource(resid, str, RT_HTML);
00247 }
00248
00249 void CWebServer::OnAccept(CWebServerSocket* pServer)
00250 {
00251 CAutoPtr<CWebClientSocket> p(new CWebClientSocket(this, m_pMainFrame));
00252 if(pServer->Accept(*p))
00253 {
00254 CString name;
00255 UINT port;
00256 if(AfxGetAppSettings().fWebServerLocalhostOnly && p->GetPeerName(name, port) && name != _T("127.0.0.1"))
00257 {
00258 p->Close();
00259 return;
00260 }
00261
00262 m_clients.AddTail(p);
00263 }
00264 }
00265
00266 void CWebServer::OnClose(CWebClientSocket* pClient)
00267 {
00268 POSITION pos = m_clients.GetHeadPosition();
00269 while(pos)
00270 {
00271 POSITION cur = pos;
00272 if(m_clients.GetNext(pos) == pClient)
00273 {
00274 m_clients.RemoveAt(cur);
00275 break;
00276 }
00277 }
00278 }
00279
00280 void CWebServer::OnRequest(CWebClientSocket* pClient, CStringA& hdr, CStringA& body)
00281 {
00282 CPath p(pClient->m_path);
00283 CStringA ext = p.GetExtension().MakeLower();
00284 CStringA mime;
00285 if(ext.IsEmpty()) mime = "text/html";
00286 else m_mimes.Lookup(ext, mime);
00287
00288 hdr = "HTTP/1.0 200 OK\r\n";
00289
00290 bool fHandled = false, fCGI = false;
00291
00292 if(!fHandled && m_webroot.IsDirectory())
00293 {
00294 CStringA tmphdr;
00295 fHandled = fCGI = CallCGI(pClient, tmphdr, body, mime);
00296
00297 if(fHandled)
00298 {
00299 tmphdr.Replace("\r\n", "\n");
00300 CList<CStringA> hdrlines;
00301 ExplodeMin(tmphdr, hdrlines, '\n');
00302 POSITION pos = hdrlines.GetHeadPosition();
00303 while(pos)
00304 {
00305 POSITION cur = pos;
00306 CList<CStringA> sl;
00307 CStringA key = Explode(hdrlines.GetNext(pos), sl, ':', 2);
00308 if(sl.GetCount() < 2) continue;
00309 key.Trim().MakeLower();
00310 if(key == "content-type") {mime = sl.GetTail().Trim(); hdrlines.RemoveAt(cur);}
00311 else if(key == "content-length") {hdrlines.RemoveAt(cur);}
00312 }
00313 tmphdr = Implode(hdrlines, '\n');
00314 tmphdr.Replace("\n", "\r\n");
00315 hdr += tmphdr + "\r\n";
00316 }
00317 }
00318
00319 RequestHandler rh = NULL;
00320 if(!fHandled && m_internalpages.Lookup(pClient->m_path, rh) && (pClient->*rh)(hdr, body, mime))
00321 {
00322 if(mime.IsEmpty()) mime = "text/html";
00323
00324 CString redir;
00325 if(pClient->m_get.Lookup(_T("redir"), redir)
00326 || pClient->m_post.Lookup(_T("redir"), redir))
00327 {
00328 if(redir.IsEmpty()) redir = '/';
00329
00330 hdr =
00331 "HTTP/1.0 302 Found\r\n"
00332 "Location: " + CStringA(redir) + "\r\n";
00333 return;
00334 }
00335
00336 fHandled = true;
00337 }
00338
00339 if(!fHandled && m_webroot.IsDirectory())
00340 {
00341 fHandled = LoadPage(0, body, pClient->m_path);
00342 }
00343
00344 UINT resid;
00345 CStringA res;
00346 if(!fHandled && m_downloads.Lookup(pClient->m_path, resid) && LoadResource(resid, res, _T("FILE")))
00347 {
00348 if(mime.IsEmpty()) mime = "application/octet-stream";
00349 memcpy(body.GetBufferSetLength(res.GetLength()), res.GetBuffer(), res.GetLength());
00350 fHandled = true;
00351 }
00352
00353 if(!fHandled)
00354 {
00355 hdr = mime == "text/html"
00356 ? "HTTP/1.0 301 Moved Permanently\r\n" "Location: /404.html\r\n"
00357 : "HTTP/1.0 404 Not Found\r\n";
00358 return;
00359 }
00360
00361 if(mime == "text/html" && !fCGI)
00362 {
00363 hdr +=
00364 "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n"
00365 "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
00366 "Pragma: no-cache\r\n";
00367
00368 CStringA debug;
00369 if(AfxGetAppSettings().fWebServerPrintDebugInfo)
00370 {
00371 debug += "<hr>\r\n";
00372 CString key, value;
00373 POSITION pos;
00374 pos = pClient->m_hdrlines.GetStartPosition();
00375 while(pos) {pClient->m_hdrlines.GetNextAssoc(pos, key, value); debug += "HEADER[" + key + "] = " + value + "<br>\r\n";}
00376 debug += "cmd: " + pClient->m_cmd + "<br>\r\n";
00377 debug += "path: " + pClient->m_path + "<br>\r\n";
00378 debug += "ver: " + pClient->m_ver + "<br>\r\n";
00379 pos = pClient->m_get.GetStartPosition();
00380 while(pos) {pClient->m_get.GetNextAssoc(pos, key, value); debug += "GET[" + key + "] = " + value + "<br>\r\n";}
00381 pos = pClient->m_post.GetStartPosition();
00382 while(pos) {pClient->m_post.GetNextAssoc(pos, key, value); debug += "POST[" + key + "] = " + value + "<br>\r\n";}
00383 pos = pClient->m_cookie.GetStartPosition();
00384 while(pos) {pClient->m_cookie.GetNextAssoc(pos, key, value); debug += "COOKIE[" + key + "] = " + value + "<br>\r\n";}
00385 pos = pClient->m_request.GetStartPosition();
00386 while(pos) {pClient->m_request.GetNextAssoc(pos, key, value); debug += "REQUEST[" + key + "] = " + value + "<br>\r\n";}
00387 }
00388
00389 body.Replace("[path]", CStringA(pClient->m_path));
00390 body.Replace("[indexpath]", "/index.html");
00391 body.Replace("[commandpath]", "/command.html");
00392 body.Replace("[browserpath]", "/browser.html");
00393 body.Replace("[controlspath]", "/controls.html");
00394 body.Replace("[wmcname]", "wm_command");
00395 body.Replace("[setposcommand]", CMD_SETPOS);
00396 body.Replace("[setvolumecommand]", CMD_SETVOLUME);
00397 body.Replace("[debug]", debug);
00398
00399 }
00400
00401
00402 if(AfxGetAppSettings().fWebServerUseCompression && hdr.Find("Content-Encoding:") < 0)
00403 do
00404 {
00405 CString accept_encoding;
00406 pClient->m_hdrlines.Lookup(_T("accept-encoding"), accept_encoding);
00407 accept_encoding.MakeLower();
00408 CList<CString> sl;
00409 ExplodeMin(accept_encoding, sl, ',');
00410 if(!sl.Find(_T("gzip"))) break;;
00411
00412 CHAR path[MAX_PATH], fn[MAX_PATH];
00413 if(!GetTempPathA(MAX_PATH, path) || !GetTempFileNameA(path, "mpc_gz", 0, fn))
00414 break;
00415
00416 gzFile gf = gzopen(fn, "wb9");
00417 if(!gf || gzwrite(gf, (LPVOID)(LPCSTR)body, body.GetLength()) != body.GetLength())
00418 {
00419 if(gf) gzclose(gf);
00420 DeleteFileA(fn);
00421 break;
00422 }
00423 gzclose(gf);
00424
00425 FILE* f = fopen(fn, "rb");
00426 if(!f) {DeleteFileA(fn); break;}
00427 fseek(f, 0, 2);
00428 CHAR* s = body.GetBufferSetLength(ftell(f));
00429 fseek(f, 0, 0);
00430 int len = fread(s, 1, body.GetLength(), f);
00431 ASSERT(len == body.GetLength());
00432 fclose(f);
00433 DeleteFileA(fn);
00434
00435 hdr += "Content-Encoding: gzip\r\n";
00436 }
00437 while(0);
00438
00439 CStringA content;
00440 content.Format(
00441 "Content-Type: %s\r\n"
00442 "Content-Length: %d\r\n",
00443 mime, body.GetLength());
00444 hdr += content;
00445 }
00446
00447 static DWORD WINAPI KillCGI(LPVOID lParam)
00448 {
00449 HANDLE hProcess = (HANDLE)lParam;
00450 if(WaitForSingleObject(hProcess, 30000) == WAIT_TIMEOUT)
00451 TerminateProcess(hProcess, 0);
00452 return 0;
00453 }
00454
00455 bool CWebServer::CallCGI(CWebClientSocket* pClient, CStringA& hdr, CStringA& body, CStringA& mime)
00456 {
00457 CString path = pClient->m_path, redir = path;
00458 if(!ToLocalPath(path, redir)) return false;
00459 CString ext = CPath(path).GetExtension().MakeLower();
00460 CPath dir(path);
00461 dir.RemoveFileSpec();
00462
00463 CString cgi;
00464 if(!m_cgi.Lookup(ext, cgi) || !CPath(cgi).FileExists())
00465 return false;
00466
00467 HANDLE hProcess = GetCurrentProcess();
00468 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup = NULL;
00469 HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup = NULL;
00470
00471 SECURITY_ATTRIBUTES saAttr;
00472 ZeroMemory(&saAttr, sizeof(saAttr));
00473 saAttr.nLength = sizeof(saAttr);
00474 saAttr.bInheritHandle = TRUE;
00475
00476 if(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
00477 {
00478 BOOL fSuccess = DuplicateHandle(hProcess, hChildStdoutRd, hProcess, &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
00479 CloseHandle(hChildStdoutRd);
00480 }
00481
00482 if(CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
00483 {
00484 BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
00485 CloseHandle(hChildStdinWr);
00486 }
00487
00488 STARTUPINFO siStartInfo;
00489 ZeroMemory(&siStartInfo, sizeof(siStartInfo));
00490 siStartInfo.cb = sizeof(siStartInfo);
00491 siStartInfo.hStdError = hChildStdoutWr;
00492 siStartInfo.hStdOutput = hChildStdoutWr;
00493 siStartInfo.hStdInput = hChildStdinRd;
00494 siStartInfo.dwFlags |= STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
00495 siStartInfo.wShowWindow = SW_HIDE;
00496
00497 PROCESS_INFORMATION piProcInfo;
00498 ZeroMemory(&piProcInfo, sizeof(piProcInfo));
00499
00500 CStringA envstr;
00501
00502 if(LPVOID lpvEnv = GetEnvironmentStrings())
00503 {
00504 CString str;
00505
00506 CList<CString> env;
00507 for(LPTSTR lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += _tcslen(lpszVariable)+1)
00508 if(lpszVariable != (LPTSTR)lpvEnv)
00509 env.AddTail(lpszVariable);
00510
00511 env.AddTail(_T("GATEWAY_INTERFACE=CGI/1.1"));
00512 env.AddTail(_T("SERVER_SOFTWARE=Media Player Classic/6.4.x.y"));
00513 env.AddTail(_T("SERVER_PROTOCOL=") + pClient->m_ver);
00514 env.AddTail(_T("REQUEST_METHOD=") + pClient->m_cmd);
00515 env.AddTail(_T("PATH_INFO=") + redir);
00516 env.AddTail(_T("PATH_TRANSLATED=") + path);
00517 env.AddTail(_T("SCRIPT_NAME=") + redir);
00518 env.AddTail(_T("QUERY_STRING=") + pClient->m_query);
00519
00520 if(pClient->m_hdrlines.Lookup(_T("content-type"), str))
00521 env.AddTail(_T("CONTENT_TYPE=") + str);
00522 if(pClient->m_hdrlines.Lookup(_T("content-length"), str))
00523 env.AddTail(_T("CONTENT_LENGTH=") + str);
00524
00525 POSITION pos = pClient->m_hdrlines.GetStartPosition();
00526 while(pos)
00527 {
00528 CString key = pClient->m_hdrlines.GetKeyAt(pos);
00529 CString value = pClient->m_hdrlines.GetNextValue(pos);
00530 key.Replace(_T("-"), _T("_"));
00531 key.MakeUpper();
00532 env.AddTail(_T("HTTP_") + key + _T("=") + value);
00533 }
00534
00535 CString name;
00536 UINT port;
00537
00538 if(pClient->GetPeerName(name, port))
00539 {
00540 str.Format(_T("%d"), port);
00541 env.AddTail(_T("REMOTE_ADDR=")+name);
00542 env.AddTail(_T("REMOTE_HOST=")+name);
00543 env.AddTail(_T("REMOTE_PORT=")+str);
00544 }
00545
00546 if(pClient->GetSockName(name, port))
00547 {
00548 str.Format(_T("%d"), port);
00549 env.AddTail(_T("SERVER_NAME=")+name);
00550 env.AddTail(_T("SERVER_PORT=")+str);
00551 }
00552
00553 env.AddTail(_T("\0"));
00554
00555 str = Implode(env, '\0');
00556 envstr = CStringA(str, str.GetLength());
00557
00558 FreeEnvironmentStrings((LPTSTR)lpvEnv);
00559 }
00560
00561 TCHAR* cmdln = new TCHAR[32768];
00562 _sntprintf(cmdln, 32768, _T("\"%s\" \"%s\""), cgi, path);
00563
00564 if(hChildStdinRd && hChildStdoutWr)
00565 if(CreateProcess(
00566 NULL, cmdln, NULL, NULL, TRUE, 0,
00567 envstr.GetLength() ? (LPVOID)(LPCSTR)envstr : NULL,
00568 dir, &siStartInfo, &piProcInfo))
00569 {
00570 DWORD ThreadId;
00571 CreateThread(NULL, 0, KillCGI, (LPVOID)piProcInfo.hProcess, 0, &ThreadId);
00572
00573 static const int BUFFSIZE = 1024;
00574 DWORD dwRead, dwWritten = 0;
00575
00576 int i = 0, len = pClient->m_data.GetLength();
00577 for(; i < len; i += dwWritten)
00578 if(!WriteFile(hChildStdinWrDup, (LPCSTR)pClient->m_data + i, min(len - i, BUFFSIZE), &dwWritten, NULL))
00579 break;
00580
00581 CloseHandle(hChildStdinWrDup);
00582 CloseHandle(hChildStdoutWr);
00583
00584 body.Empty();
00585
00586 CStringA buff;
00587 while(i == len && ReadFile(hChildStdoutRdDup, buff.GetBuffer(BUFFSIZE), BUFFSIZE, &dwRead, NULL) && dwRead)
00588 {
00589 buff.ReleaseBufferSetLength(dwRead);
00590 body += buff;
00591 }
00592
00593 int hdrend = body.Find("\r\n\r\n");
00594 if(hdrend >= 0)
00595 {
00596 hdr = body.Left(hdrend+2);
00597 body = body.Mid(hdrend+4);
00598 }
00599
00600 CloseHandle(hChildStdinRd);
00601 CloseHandle(hChildStdoutRdDup);
00602
00603 CloseHandle(piProcInfo.hProcess);
00604 CloseHandle(piProcInfo.hThread);
00605 }
00606 else
00607 {
00608 body = _T("CGI Error");
00609 }
00610
00611 delete [] cmdln;
00612
00613 return true;
00614 }