WebServer.cpp

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                 // TODO: add more general tags to replace
00399         }
00400 
00401         // gzip
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 }

Generated on Tue Dec 13 14:47:05 2005 for guliverkli by  doxygen 1.4.5