Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasimir666 <casimir666@users.sourceforge.net>2006-06-25 01:37:43 +0400
committerCasimir666 <casimir666@users.sourceforge.net>2006-06-25 01:37:43 +0400
commit0868305e78da2b0742c2ce349efa041d5622ae21 (patch)
tree663fd93132c7927910ba7c13188d6332b2e3e5b2 /src/apps/mplayerc/WebServer.cpp
parent43c8656956a0460fc4551e3ea7a39b9f3094a3e3 (diff)
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@14 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/apps/mplayerc/WebServer.cpp')
-rw-r--r--src/apps/mplayerc/WebServer.cpp614
1 files changed, 614 insertions, 0 deletions
diff --git a/src/apps/mplayerc/WebServer.cpp b/src/apps/mplayerc/WebServer.cpp
new file mode 100644
index 000000000..a58b29f7d
--- /dev/null
+++ b/src/apps/mplayerc/WebServer.cpp
@@ -0,0 +1,614 @@
+#include "stdafx.h"
+#include "mplayerc.h"
+#include "resource.h"
+#include "MainFrm.h"
+#include <atlbase.h>
+#include <atlisapi.h>
+#include "WebServerSocket.h"
+#include "WebClientSocket.h"
+#include "WebServer.h"
+#include "..\..\zlib\zlib.h"
+
+CAtlStringMap<CWebServer::RequestHandler> CWebServer::m_internalpages;
+CAtlStringMap<UINT> CWebServer::m_downloads;
+CAtlStringMap<CStringA, CStringA> CWebServer::m_mimes;
+
+CWebServer::CWebServer(CMainFrame* pMainFrame, int nPort)
+ : m_pMainFrame(pMainFrame)
+ , m_nPort(nPort)
+{
+ if(m_internalpages.IsEmpty())
+ {
+ m_internalpages[_T("/")] = &CWebClientSocket::OnIndex;
+ m_internalpages[_T("/index.html")] = &CWebClientSocket::OnIndex;
+ m_internalpages[_T("/browser.html")] = &CWebClientSocket::OnBrowser;
+ m_internalpages[_T("/controls.html")] = &CWebClientSocket::OnControls;
+ m_internalpages[_T("/command.html")] = &CWebClientSocket::OnCommand;
+ m_internalpages[_T("/status.html")] = &CWebClientSocket::OnStatus;
+ m_internalpages[_T("/player.html")] = &CWebClientSocket::OnPlayer;
+ m_internalpages[_T("/snapshot.jpg")] = &CWebClientSocket::OnSnapShotJpeg;
+ m_internalpages[_T("/404.html")] = &CWebClientSocket::OnError404;
+ m_internalpages[_T("/convres.html")] = &CWebClientSocket::OnConvRes;
+ }
+
+ if(m_downloads.IsEmpty())
+ {
+ m_downloads[_T("/default.css")] = IDF_DEFAULT_CSS;
+ m_downloads[_T("/vbg.gif")] = IDF_VBR_GIF;
+ m_downloads[_T("/vbs.gif")] = IDF_VBS_GIF;
+ m_downloads[_T("/sliderbar.gif")] = IDF_SLIDERBAR_GIF;
+ m_downloads[_T("/slidergrip.gif")] = IDF_SLIDERGRIP_GIF;
+ m_downloads[_T("/sliderback.gif")] = IDF_SLIDERBACK_GIF;
+ m_downloads[_T("/1pix.gif")] = IDF_1PIX_GIF;
+ m_downloads[_T("/headericon.png")] = IDF_HEADERICON_PNG;
+ m_downloads[_T("/headerback.png")] = IDF_HEADERBACK_PNG;
+ m_downloads[_T("/headerclose.png")] = IDF_HEADERCLOSE_PNG;
+ m_downloads[_T("/leftside.png")] = IDF_LEFTSIDE_PNG;
+ m_downloads[_T("/rightside.png")] = IDF_RIGHTSIDE_PNG;
+ m_downloads[_T("/bottomside.png")] = IDF_BOTTOMSIDE_PNG;
+ m_downloads[_T("/leftbottomside.png")] = IDF_LEFTBOTTOMSIDE_PNG;
+ m_downloads[_T("/rightbottomside.png")] = IDF_RIGHTBOTTOMSIDE_PNG;
+ m_downloads[_T("/seekbarleft.png")] = IDF_SEEKBARLEFT_PNG;
+ m_downloads[_T("/seekbarmid.png")] = IDF_SEEKBARMID_PNG;
+ m_downloads[_T("/seekbarright.png")] = IDF_SEEKBARRIGHT_PNG;
+ m_downloads[_T("/seekbargrip.png")] = IDF_SEEKBARGRIP_PNG;
+ m_downloads[_T("/logo.png")] = IDF_LOGO_PNG;
+ m_downloads[_T("/controlback.png")] = IDF_CONTROLBACK_PNG;
+ m_downloads[_T("/controlbuttonplay.png")] = IDF_CONTROLBUTTONPLAY_PNG;
+ m_downloads[_T("/controlbuttonpause.png")] = IDF_CONTROLBUTTONPAUSE_PNG;
+ m_downloads[_T("/controlbuttonstop.png")] = IDF_CONTROLBUTTONSTOP_PNG;
+ m_downloads[_T("/controlbuttonskipback.png")] = IDF_CONTROLBUTTONSKIPBACK_PNG;
+ m_downloads[_T("/controlbuttondecrate.png")] = IDF_CONTROLBUTTONDECRATE_PNG;
+ m_downloads[_T("/controlbuttonincrate.png")] = IDF_CONTROLBUTTONINCRATE_PNG;
+ m_downloads[_T("/controlbuttonskipforward.png")] = IDF_CONTROLBUTTONSKIPFORWARD_PNG;
+ m_downloads[_T("/controlbuttonstep.png")] = IDF_CONTROLBUTTONSTEP_PNG;
+ m_downloads[_T("/controlvolumeon.png")] = IDF_CONTROLVOLUMEON_PNG;
+ m_downloads[_T("/controlvolumeoff.png")] = IDF_CONTROLVOLUMEOFF_PNG;
+ m_downloads[_T("/controlvolumebar.png")] = IDF_CONTROLVOLUMEBAR_PNG;
+ m_downloads[_T("/controlvolumegrip.png")] = IDF_CONTROLVOLUMEGRIP_PNG;
+ }
+
+ CRegKey key;
+ CString str(_T("MIME\\Database\\Content Type"));
+ if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
+ {
+ TCHAR buff[256];
+ DWORD len = countof(buff);
+ for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = countof(buff))
+ {
+ CRegKey mime;
+ TCHAR ext[64];
+ ULONG len = countof(ext);
+ if(ERROR_SUCCESS == mime.Open(HKEY_CLASSES_ROOT, str + _T("\\") + buff, KEY_READ)
+ && ERROR_SUCCESS == mime.QueryStringValue(_T("Extension"), ext, &len))
+ m_mimes[CStringA(ext).MakeLower()] = CStringA(buff).MakeLower();
+ }
+ }
+
+ m_mimes[".html"] = "text/html";
+ m_mimes[".txt"] = "text/plain";
+ m_mimes[".css"] = "text/css";
+ m_mimes[".gif"] = "image/gif";
+ m_mimes[".jpeg"] = "image/jpeg";
+ m_mimes[".jpg"] = "image/jpeg";
+ m_mimes[".png"] = "image/png";
+
+ GetModuleFileName(AfxGetInstanceHandle(), str.GetBuffer(MAX_PATH), MAX_PATH);
+ str.ReleaseBuffer();
+ m_webroot = CPath(str);
+ m_webroot.RemoveFileSpec();
+
+ CString WebRoot = AfxGetAppSettings().WebRoot;
+ WebRoot.Replace('/', '\\');
+ WebRoot.Trim();
+ CPath p(WebRoot);
+ if(WebRoot.Find(_T(":\\")) < 0 && WebRoot.Find(_T("\\\\")) < 0) m_webroot.Append(WebRoot);
+ else m_webroot = p;
+ m_webroot.Canonicalize();
+ m_webroot.MakePretty();
+ if(!m_webroot.IsDirectory()) m_webroot = CPath();
+
+ CAtlList<CString> sl;
+ Explode(AfxGetAppSettings().WebServerCGI, sl, ';');
+ POSITION pos = sl.GetHeadPosition();
+ while(pos)
+ {
+ CAtlList<CString> sl2;
+ CString ext = Explode(sl.GetNext(pos), sl2, '=', 2);
+ if(sl2.GetCount() < 2) continue;
+ m_cgi[ext] = sl2.GetTail();
+ }
+
+ m_ThreadId = 0;
+ m_hThread = ::CreateThread(NULL, 0, StaticThreadProc, (LPVOID)this, 0, &m_ThreadId);
+}
+
+CWebServer::~CWebServer()
+{
+ if(m_hThread != NULL)
+ {
+ PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0);
+ WaitForSingleObject(m_hThread, 10000);
+ EXECUTE_ASSERT(CloseHandle(m_hThread));
+ }
+}
+
+DWORD WINAPI CWebServer::StaticThreadProc(LPVOID lpParam)
+{
+ return ((CWebServer*)lpParam)->ThreadProc();
+}
+
+DWORD CWebServer::ThreadProc()
+{
+ if(!AfxSocketInit(NULL))
+ return -1;
+
+ CWebServerSocket s(this, m_nPort);
+
+ MSG msg;
+ while((int)GetMessage(&msg, NULL, 0, 0) > 0)
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return 0;
+}
+
+static void PutFileContents(LPCTSTR fn, const CStringA& data)
+{
+ if(FILE* f = _tfopen(fn, _T("wb")))
+ {
+ fwrite((LPCSTR)data, 1, data.GetLength(), f);
+ fclose(f);
+ }
+}
+
+void CWebServer::Deploy(CString dir)
+{
+ CStringA data;
+ if(LoadResource(IDR_HTML_INDEX, data, RT_HTML)) PutFileContents(dir + _T("index.html"), data);
+ if(LoadResource(IDR_HTML_BROWSER, data, RT_HTML)) PutFileContents(dir + _T("browser.html"), data);
+ if(LoadResource(IDR_HTML_CONTROLS, data, RT_HTML)) PutFileContents(dir + _T("controls.html"), data);
+ if(LoadResource(IDR_HTML_404, data, RT_HTML)) PutFileContents(dir + _T("404.html"), data);
+ if(LoadResource(IDR_HTML_PLAYER, data, RT_HTML)) PutFileContents(dir + _T("player.html"), data);
+
+ POSITION pos = m_downloads.GetStartPosition();
+ while(pos)
+ {
+ CString fn;
+ UINT id;
+ m_downloads.GetNextAssoc(pos, fn, id);
+ if(LoadResource(id, data, _T("FILE")))
+ PutFileContents(dir + fn, data);
+ }
+}
+
+bool CWebServer::ToLocalPath(CString& path, CString& redir)
+{
+ if(!path.IsEmpty() && m_webroot.IsDirectory())
+ {
+ CString str = path;
+ str.Replace('/', '\\');
+ str.TrimLeft('\\');
+
+ CPath p;
+ p.Combine(m_webroot, str);
+ p.Canonicalize();
+
+ if(p.IsDirectory())
+ {
+ CAtlList<CString> sl;
+ Explode(AfxGetAppSettings().WebDefIndex, sl, ';');
+ POSITION pos = sl.GetHeadPosition();
+ while(pos)
+ {
+ str = sl.GetNext(pos);
+ CPath p2 = p;
+ p2.Append(str);
+ if(p2.FileExists())
+ {
+ p = p2;
+ redir = path;
+ if(redir.GetAt(redir.GetLength()-1) != '/') redir += '/';
+ redir += str;
+ break;
+ }
+ }
+ }
+
+ if(_tcslen(p) > _tcslen(m_webroot) && p.FileExists())
+ {
+ path = (LPCTSTR)p;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CWebServer::LoadPage(UINT resid, CStringA& str, CString path)
+{
+ CString redir;
+ if(ToLocalPath(path, redir))
+ {
+ if(FILE* f = _tfopen(path, _T("rb")))
+ {
+ fseek(f, 0, 2);
+ char* buff = str.GetBufferSetLength(ftell(f));
+ fseek(f, 0, 0);
+ int len = fread(buff, 1, str.GetLength(), f);
+ fclose(f);
+ return len == str.GetLength();
+ }
+ }
+
+ return LoadResource(resid, str, RT_HTML);
+}
+
+void CWebServer::OnAccept(CWebServerSocket* pServer)
+{
+ CAutoPtr<CWebClientSocket> p(new CWebClientSocket(this, m_pMainFrame));
+ if(pServer->Accept(*p))
+ {
+ CString name;
+ UINT port;
+ if(AfxGetAppSettings().fWebServerLocalhostOnly && p->GetPeerName(name, port) && name != _T("127.0.0.1"))
+ {
+ p->Close();
+ return;
+ }
+
+ m_clients.AddTail(p);
+ }
+}
+
+void CWebServer::OnClose(CWebClientSocket* pClient)
+{
+ POSITION pos = m_clients.GetHeadPosition();
+ while(pos)
+ {
+ POSITION cur = pos;
+ if(m_clients.GetNext(pos) == pClient)
+ {
+ m_clients.RemoveAt(cur);
+ break;
+ }
+ }
+}
+
+void CWebServer::OnRequest(CWebClientSocket* pClient, CStringA& hdr, CStringA& body)
+{
+ CPath p(pClient->m_path);
+ CStringA ext = p.GetExtension().MakeLower();
+ CStringA mime;
+ if(ext.IsEmpty()) mime = "text/html";
+ else m_mimes.Lookup(ext, mime);
+
+ hdr = "HTTP/1.0 200 OK\r\n";
+
+ bool fHandled = false, fCGI = false;
+
+ if(!fHandled && m_webroot.IsDirectory())
+ {
+ CStringA tmphdr;
+ fHandled = fCGI = CallCGI(pClient, tmphdr, body, mime);
+
+ if(fHandled)
+ {
+ tmphdr.Replace("\r\n", "\n");
+ CAtlList<CStringA> hdrlines;
+ ExplodeMin(tmphdr, hdrlines, '\n');
+ POSITION pos = hdrlines.GetHeadPosition();
+ while(pos)
+ {
+ POSITION cur = pos;
+ CAtlList<CStringA> sl;
+ CStringA key = Explode(hdrlines.GetNext(pos), sl, ':', 2);
+ if(sl.GetCount() < 2) continue;
+ key.Trim().MakeLower();
+ if(key == "content-type") {mime = sl.GetTail().Trim(); hdrlines.RemoveAt(cur);}
+ else if(key == "content-length") {hdrlines.RemoveAt(cur);}
+ }
+ tmphdr = Implode(hdrlines, '\n');
+ tmphdr.Replace("\n", "\r\n");
+ hdr += tmphdr + "\r\n";
+ }
+ }
+
+ RequestHandler rh = NULL;
+ if(!fHandled && m_internalpages.Lookup(pClient->m_path, rh) && (pClient->*rh)(hdr, body, mime))
+ {
+ if(mime.IsEmpty()) mime = "text/html";
+
+ CString redir;
+ if(pClient->m_get.Lookup(_T("redir"), redir)
+ || pClient->m_post.Lookup(_T("redir"), redir))
+ {
+ if(redir.IsEmpty()) redir = '/';
+
+ hdr =
+ "HTTP/1.0 302 Found\r\n"
+ "Location: " + CStringA(redir) + "\r\n";
+ return;
+ }
+
+ fHandled = true;
+ }
+
+ if(!fHandled && m_webroot.IsDirectory())
+ {
+ fHandled = LoadPage(0, body, pClient->m_path);
+ }
+
+ UINT resid;
+ CStringA res;
+ if(!fHandled && m_downloads.Lookup(pClient->m_path, resid) && LoadResource(resid, res, _T("FILE")))
+ {
+ if(mime.IsEmpty()) mime = "application/octet-stream";
+ memcpy(body.GetBufferSetLength(res.GetLength()), res.GetBuffer(), res.GetLength());
+ fHandled = true;
+ }
+
+ if(!fHandled)
+ {
+ hdr = mime == "text/html"
+ ? "HTTP/1.0 301 Moved Permanently\r\n" "Location: /404.html\r\n"
+ : "HTTP/1.0 404 Not Found\r\n";
+ return;
+ }
+
+ if(mime == "text/html" && !fCGI)
+ {
+ hdr +=
+ "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n"
+ "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
+ "Pragma: no-cache\r\n";
+
+ CStringA debug;
+ if(AfxGetAppSettings().fWebServerPrintDebugInfo)
+ {
+ debug += "<hr>\r\n";
+ CString key, value;
+ POSITION pos;
+ pos = pClient->m_hdrlines.GetStartPosition();
+ while(pos) {pClient->m_hdrlines.GetNextAssoc(pos, key, value); debug += "HEADER[" + key + "] = " + value + "<br>\r\n";}
+ debug += "cmd: " + pClient->m_cmd + "<br>\r\n";
+ debug += "path: " + pClient->m_path + "<br>\r\n";
+ debug += "ver: " + pClient->m_ver + "<br>\r\n";
+ pos = pClient->m_get.GetStartPosition();
+ while(pos) {pClient->m_get.GetNextAssoc(pos, key, value); debug += "GET[" + key + "] = " + value + "<br>\r\n";}
+ pos = pClient->m_post.GetStartPosition();
+ while(pos) {pClient->m_post.GetNextAssoc(pos, key, value); debug += "POST[" + key + "] = " + value + "<br>\r\n";}
+ pos = pClient->m_cookie.GetStartPosition();
+ while(pos) {pClient->m_cookie.GetNextAssoc(pos, key, value); debug += "COOKIE[" + key + "] = " + value + "<br>\r\n";}
+ pos = pClient->m_request.GetStartPosition();
+ while(pos) {pClient->m_request.GetNextAssoc(pos, key, value); debug += "REQUEST[" + key + "] = " + value + "<br>\r\n";}
+ }
+
+ body.Replace("[path]", CStringA(pClient->m_path));
+ body.Replace("[indexpath]", "/index.html");
+ body.Replace("[commandpath]", "/command.html");
+ body.Replace("[browserpath]", "/browser.html");
+ body.Replace("[controlspath]", "/controls.html");
+ body.Replace("[wmcname]", "wm_command");
+ body.Replace("[setposcommand]", CMD_SETPOS);
+ body.Replace("[setvolumecommand]", CMD_SETVOLUME);
+ body.Replace("[debug]", debug);
+ // TODO: add more general tags to replace
+ }
+
+ // gzip
+ if(AfxGetAppSettings().fWebServerUseCompression && hdr.Find("Content-Encoding:") < 0)
+ do
+ {
+ CString accept_encoding;
+ pClient->m_hdrlines.Lookup(_T("accept-encoding"), accept_encoding);
+ accept_encoding.MakeLower();
+ CAtlList<CString> sl;
+ ExplodeMin(accept_encoding, sl, ',');
+ if(!sl.Find(_T("gzip"))) break;;
+
+ CHAR path[MAX_PATH], fn[MAX_PATH];
+ if(!GetTempPathA(MAX_PATH, path) || !GetTempFileNameA(path, "mpc_gz", 0, fn))
+ break;
+
+ gzFile gf = gzopen(fn, "wb9");
+ if(!gf || gzwrite(gf, (LPVOID)(LPCSTR)body, body.GetLength()) != body.GetLength())
+ {
+ if(gf) gzclose(gf);
+ DeleteFileA(fn);
+ break;
+ }
+ gzclose(gf);
+
+ FILE* f = fopen(fn, "rb");
+ if(!f) {DeleteFileA(fn); break;}
+ fseek(f, 0, 2);
+ CHAR* s = body.GetBufferSetLength(ftell(f));
+ fseek(f, 0, 0);
+ int len = fread(s, 1, body.GetLength(), f);
+ ASSERT(len == body.GetLength());
+ fclose(f);
+ DeleteFileA(fn);
+
+ hdr += "Content-Encoding: gzip\r\n";
+ }
+ while(0);
+
+ CStringA content;
+ content.Format(
+ "Content-Type: %s\r\n"
+ "Content-Length: %d\r\n",
+ mime, body.GetLength());
+ hdr += content;
+}
+
+static DWORD WINAPI KillCGI(LPVOID lParam)
+{
+ HANDLE hProcess = (HANDLE)lParam;
+ if(WaitForSingleObject(hProcess, 30000) == WAIT_TIMEOUT)
+ TerminateProcess(hProcess, 0);
+ return 0;
+}
+
+bool CWebServer::CallCGI(CWebClientSocket* pClient, CStringA& hdr, CStringA& body, CStringA& mime)
+{
+ CString path = pClient->m_path, redir = path;
+ if(!ToLocalPath(path, redir)) return false;
+ CString ext = CPath(path).GetExtension().MakeLower();
+ CPath dir(path);
+ dir.RemoveFileSpec();
+
+ CString cgi;
+ if(!m_cgi.Lookup(ext, cgi) || !CPath(cgi).FileExists())
+ return false;
+
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup = NULL;
+ HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup = NULL;
+
+ SECURITY_ATTRIBUTES saAttr;
+ ZeroMemory(&saAttr, sizeof(saAttr));
+ saAttr.nLength = sizeof(saAttr);
+ saAttr.bInheritHandle = TRUE;
+
+ if(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
+ {
+ BOOL fSuccess = DuplicateHandle(hProcess, hChildStdoutRd, hProcess, &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ CloseHandle(hChildStdoutRd);
+ }
+
+ if(CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
+ {
+ BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ CloseHandle(hChildStdinWr);
+ }
+
+ STARTUPINFO siStartInfo;
+ ZeroMemory(&siStartInfo, sizeof(siStartInfo));
+ siStartInfo.cb = sizeof(siStartInfo);
+ siStartInfo.hStdError = hChildStdoutWr;
+ siStartInfo.hStdOutput = hChildStdoutWr;
+ siStartInfo.hStdInput = hChildStdinRd;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+ siStartInfo.wShowWindow = SW_HIDE;
+
+ PROCESS_INFORMATION piProcInfo;
+ ZeroMemory(&piProcInfo, sizeof(piProcInfo));
+
+ CStringA envstr;
+
+ if(LPVOID lpvEnv = GetEnvironmentStrings())
+ {
+ CString str;
+
+ CAtlList<CString> env;
+ for(LPTSTR lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += _tcslen(lpszVariable)+1)
+ if(lpszVariable != (LPTSTR)lpvEnv)
+ env.AddTail(lpszVariable);
+
+ env.AddTail(_T("GATEWAY_INTERFACE=CGI/1.1"));
+ env.AddTail(_T("SERVER_SOFTWARE=Media Player Classic/6.4.x.y"));
+ env.AddTail(_T("SERVER_PROTOCOL=") + pClient->m_ver);
+ env.AddTail(_T("REQUEST_METHOD=") + pClient->m_cmd);
+ env.AddTail(_T("PATH_INFO=") + redir);
+ env.AddTail(_T("PATH_TRANSLATED=") + path);
+ env.AddTail(_T("SCRIPT_NAME=") + redir);
+ env.AddTail(_T("QUERY_STRING=") + pClient->m_query);
+
+ if(pClient->m_hdrlines.Lookup(_T("content-type"), str))
+ env.AddTail(_T("CONTENT_TYPE=") + str);
+ if(pClient->m_hdrlines.Lookup(_T("content-length"), str))
+ env.AddTail(_T("CONTENT_LENGTH=") + str);
+
+ POSITION pos = pClient->m_hdrlines.GetStartPosition();
+ while(pos)
+ {
+ CString key = pClient->m_hdrlines.GetKeyAt(pos);
+ CString value = pClient->m_hdrlines.GetNextValue(pos);
+ key.Replace(_T("-"), _T("_"));
+ key.MakeUpper();
+ env.AddTail(_T("HTTP_") + key + _T("=") + value);
+ }
+
+ CString name;
+ UINT port;
+
+ if(pClient->GetPeerName(name, port))
+ {
+ str.Format(_T("%d"), port);
+ env.AddTail(_T("REMOTE_ADDR=")+name);
+ env.AddTail(_T("REMOTE_HOST=")+name);
+ env.AddTail(_T("REMOTE_PORT=")+str);
+ }
+
+ if(pClient->GetSockName(name, port))
+ {
+ str.Format(_T("%d"), port);
+ env.AddTail(_T("SERVER_NAME=")+name);
+ env.AddTail(_T("SERVER_PORT=")+str);
+ }
+
+ env.AddTail(_T("\0"));
+
+ str = Implode(env, '\0');
+ envstr = CStringA(str, str.GetLength());
+
+ FreeEnvironmentStrings((LPTSTR)lpvEnv);
+ }
+
+ TCHAR* cmdln = new TCHAR[32768];
+ _sntprintf(cmdln, 32768, _T("\"%s\" \"%s\""), cgi, path);
+
+ if(hChildStdinRd && hChildStdoutWr)
+ if(CreateProcess(
+ NULL, cmdln, NULL, NULL, TRUE, 0,
+ envstr.GetLength() ? (LPVOID)(LPCSTR)envstr : NULL,
+ dir, &siStartInfo, &piProcInfo))
+ {
+ DWORD ThreadId;
+ CreateThread(NULL, 0, KillCGI, (LPVOID)piProcInfo.hProcess, 0, &ThreadId);
+
+ static const int BUFFSIZE = 1024;
+ DWORD dwRead, dwWritten = 0;
+
+ int i = 0, len = pClient->m_data.GetLength();
+ for(; i < len; i += dwWritten)
+ if(!WriteFile(hChildStdinWrDup, (LPCSTR)pClient->m_data + i, min(len - i, BUFFSIZE), &dwWritten, NULL))
+ break;
+
+ CloseHandle(hChildStdinWrDup);
+ CloseHandle(hChildStdoutWr);
+
+ body.Empty();
+
+ CStringA buff;
+ while(i == len && ReadFile(hChildStdoutRdDup, buff.GetBuffer(BUFFSIZE), BUFFSIZE, &dwRead, NULL) && dwRead)
+ {
+ buff.ReleaseBufferSetLength(dwRead);
+ body += buff;
+ }
+
+ int hdrend = body.Find("\r\n\r\n");
+ if(hdrend >= 0)
+ {
+ hdr = body.Left(hdrend+2);
+ body = body.Mid(hdrend+4);
+ }
+
+ CloseHandle(hChildStdinRd);
+ CloseHandle(hChildStdoutRdDup);
+
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ }
+ else
+ {
+ body = _T("CGI Error");
+ }
+
+ delete [] cmdln;
+
+ return true;
+}