Support unrar64.dll
[xy_vsfilter.git] / src / apps / mplayerc / WebServer.cpp
blob0832798e3cc8986f1c8c1dc0616f190d4d69d6e3
1 #include "..\..\zlib\zlib.h"
2 #include "stdafx.h"
3 #include "mplayerc.h"
4 #include "resource.h"
5 #include "MainFrm.h"
6 #include <atlbase.h>
7 #include <atlisapi.h>
8 #include "WebServerSocket.h"
9 #include "WebClientSocket.h"
10 #include "WebServer.h"
13 CAtlStringMap<CWebServer::RequestHandler> CWebServer::m_internalpages;
14 CAtlStringMap<UINT> CWebServer::m_downloads;
15 CAtlStringMap<CStringA, CStringA> CWebServer::m_mimes;
17 CWebServer::CWebServer(CMainFrame* pMainFrame, int nPort)
18 : m_pMainFrame(pMainFrame)
19 , m_nPort(nPort)
21 if(m_internalpages.IsEmpty())
23 m_internalpages[_T("/")] = &CWebClientSocket::OnIndex;
24 m_internalpages[_T("/index.html")] = &CWebClientSocket::OnIndex;
25 m_internalpages[_T("/browser.html")] = &CWebClientSocket::OnBrowser;
26 m_internalpages[_T("/controls.html")] = &CWebClientSocket::OnControls;
27 m_internalpages[_T("/command.html")] = &CWebClientSocket::OnCommand;
28 m_internalpages[_T("/status.html")] = &CWebClientSocket::OnStatus;
29 m_internalpages[_T("/player.html")] = &CWebClientSocket::OnPlayer;
30 m_internalpages[_T("/snapshot.jpg")] = &CWebClientSocket::OnSnapShotJpeg;
31 m_internalpages[_T("/404.html")] = &CWebClientSocket::OnError404;
32 m_internalpages[_T("/convres.html")] = &CWebClientSocket::OnConvRes;
35 if(m_downloads.IsEmpty())
37 m_downloads[_T("/default.css")] = IDF_DEFAULT_CSS;
38 m_downloads[_T("/vbg.gif")] = IDF_VBR_GIF;
39 m_downloads[_T("/vbs.gif")] = IDF_VBS_GIF;
40 m_downloads[_T("/sliderbar.gif")] = IDF_SLIDERBAR_GIF;
41 m_downloads[_T("/slidergrip.gif")] = IDF_SLIDERGRIP_GIF;
42 m_downloads[_T("/sliderback.gif")] = IDF_SLIDERBACK_GIF;
43 m_downloads[_T("/1pix.gif")] = IDF_1PIX_GIF;
44 m_downloads[_T("/headericon.png")] = IDF_HEADERICON_PNG;
45 m_downloads[_T("/headerback.png")] = IDF_HEADERBACK_PNG;
46 m_downloads[_T("/headerclose.png")] = IDF_HEADERCLOSE_PNG;
47 m_downloads[_T("/leftside.png")] = IDF_LEFTSIDE_PNG;
48 m_downloads[_T("/rightside.png")] = IDF_RIGHTSIDE_PNG;
49 m_downloads[_T("/bottomside.png")] = IDF_BOTTOMSIDE_PNG;
50 m_downloads[_T("/leftbottomside.png")] = IDF_LEFTBOTTOMSIDE_PNG;
51 m_downloads[_T("/rightbottomside.png")] = IDF_RIGHTBOTTOMSIDE_PNG;
52 m_downloads[_T("/seekbarleft.png")] = IDF_SEEKBARLEFT_PNG;
53 m_downloads[_T("/seekbarmid.png")] = IDF_SEEKBARMID_PNG;
54 m_downloads[_T("/seekbarright.png")] = IDF_SEEKBARRIGHT_PNG;
55 m_downloads[_T("/seekbargrip.png")] = IDF_SEEKBARGRIP_PNG;
56 m_downloads[_T("/logo.png")] = IDF_LOGO7;
57 m_downloads[_T("/controlback.png")] = IDF_CONTROLBACK_PNG;
58 m_downloads[_T("/controlbuttonplay.png")] = IDF_CONTROLBUTTONPLAY_PNG;
59 m_downloads[_T("/controlbuttonpause.png")] = IDF_CONTROLBUTTONPAUSE_PNG;
60 m_downloads[_T("/controlbuttonstop.png")] = IDF_CONTROLBUTTONSTOP_PNG;
61 m_downloads[_T("/controlbuttonskipback.png")] = IDF_CONTROLBUTTONSKIPBACK_PNG;
62 m_downloads[_T("/controlbuttondecrate.png")] = IDF_CONTROLBUTTONDECRATE_PNG;
63 m_downloads[_T("/controlbuttonincrate.png")] = IDF_CONTROLBUTTONINCRATE_PNG;
64 m_downloads[_T("/controlbuttonskipforward.png")] = IDF_CONTROLBUTTONSKIPFORWARD_PNG;
65 m_downloads[_T("/controlbuttonstep.png")] = IDF_CONTROLBUTTONSTEP_PNG;
66 m_downloads[_T("/controlvolumeon.png")] = IDF_CONTROLVOLUMEON_PNG;
67 m_downloads[_T("/controlvolumeoff.png")] = IDF_CONTROLVOLUMEOFF_PNG;
68 m_downloads[_T("/controlvolumebar.png")] = IDF_CONTROLVOLUMEBAR_PNG;
69 m_downloads[_T("/controlvolumegrip.png")] = IDF_CONTROLVOLUMEGRIP_PNG;
72 CRegKey key;
73 CString str(_T("MIME\\Database\\Content Type"));
74 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
76 TCHAR buff[256];
77 DWORD len = countof(buff);
78 for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = countof(buff))
80 CRegKey mime;
81 TCHAR ext[64];
82 ULONG len = countof(ext);
83 if(ERROR_SUCCESS == mime.Open(HKEY_CLASSES_ROOT, str + _T("\\") + buff, KEY_READ)
84 && ERROR_SUCCESS == mime.QueryStringValue(_T("Extension"), ext, &len))
85 m_mimes[CStringA(ext).MakeLower()] = CStringA(buff).MakeLower();
89 m_mimes[".html"] = "text/html";
90 m_mimes[".txt"] = "text/plain";
91 m_mimes[".css"] = "text/css";
92 m_mimes[".gif"] = "image/gif";
93 m_mimes[".jpeg"] = "image/jpeg";
94 m_mimes[".jpg"] = "image/jpeg";
95 m_mimes[".png"] = "image/png";
97 GetModuleFileName(AfxGetInstanceHandle(), str.GetBuffer(MAX_PATH), MAX_PATH);
98 str.ReleaseBuffer();
99 m_webroot = CPath(str);
100 m_webroot.RemoveFileSpec();
102 CString WebRoot = AfxGetAppSettings().WebRoot;
103 WebRoot.Replace('/', '\\');
104 WebRoot.Trim();
105 CPath p(WebRoot);
106 if(WebRoot.Find(_T(":\\")) < 0 && WebRoot.Find(_T("\\\\")) < 0) m_webroot.Append(WebRoot);
107 else m_webroot = p;
108 m_webroot.Canonicalize();
109 m_webroot.MakePretty();
110 if(!m_webroot.IsDirectory()) m_webroot = CPath();
112 CAtlList<CString> sl;
113 Explode(AfxGetAppSettings().WebServerCGI, sl, ';');
114 POSITION pos = sl.GetHeadPosition();
115 while(pos)
117 CAtlList<CString> sl2;
118 CString ext = Explode(sl.GetNext(pos), sl2, '=', 2);
119 if(sl2.GetCount() < 2) continue;
120 m_cgi[ext] = sl2.GetTail();
123 m_ThreadId = 0;
124 m_hThread = ::CreateThread(NULL, 0, StaticThreadProc, (LPVOID)this, 0, &m_ThreadId);
127 CWebServer::~CWebServer()
129 if(m_hThread != NULL)
131 PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0);
132 WaitForSingleObject(m_hThread, 10000);
133 EXECUTE_ASSERT(CloseHandle(m_hThread));
137 DWORD WINAPI CWebServer::StaticThreadProc(LPVOID lpParam)
139 return ((CWebServer*)lpParam)->ThreadProc();
142 DWORD CWebServer::ThreadProc()
144 if(!AfxSocketInit(NULL))
145 return -1;
147 CWebServerSocket s(this, m_nPort);
149 MSG msg;
150 while((int)GetMessage(&msg, NULL, 0, 0) > 0)
152 TranslateMessage(&msg);
153 DispatchMessage(&msg);
156 return 0;
159 static void PutFileContents(LPCTSTR fn, const CStringA& data)
161 if(FILE* f = _tfopen(fn, _T("wb")))
163 fwrite((LPCSTR)data, 1, data.GetLength(), f);
164 fclose(f);
168 void CWebServer::Deploy(CString dir)
170 CStringA data;
171 if(LoadResource(IDR_HTML_INDEX, data, RT_HTML)) PutFileContents(dir + _T("index.html"), data);
172 if(LoadResource(IDR_HTML_BROWSER, data, RT_HTML)) PutFileContents(dir + _T("browser.html"), data);
173 if(LoadResource(IDR_HTML_CONTROLS, data, RT_HTML)) PutFileContents(dir + _T("controls.html"), data);
174 if(LoadResource(IDR_HTML_404, data, RT_HTML)) PutFileContents(dir + _T("404.html"), data);
175 if(LoadResource(IDR_HTML_PLAYER, data, RT_HTML)) PutFileContents(dir + _T("player.html"), data);
177 POSITION pos = m_downloads.GetStartPosition();
178 while(pos)
180 CString fn;
181 UINT id;
182 m_downloads.GetNextAssoc(pos, fn, id);
183 if(LoadResource(id, data, _T("FILE")))
184 PutFileContents(dir + fn, data);
188 bool CWebServer::ToLocalPath(CString& path, CString& redir)
190 if(!path.IsEmpty() && m_webroot.IsDirectory())
192 CString str = path;
193 str.Replace('/', '\\');
194 str.TrimLeft('\\');
196 CPath p;
197 p.Combine(m_webroot, str);
198 p.Canonicalize();
200 if(p.IsDirectory())
202 CAtlList<CString> sl;
203 Explode(AfxGetAppSettings().WebDefIndex, sl, ';');
204 POSITION pos = sl.GetHeadPosition();
205 while(pos)
207 str = sl.GetNext(pos);
208 CPath p2 = p;
209 p2.Append(str);
210 if(p2.FileExists())
212 p = p2;
213 redir = path;
214 if(redir.GetAt(redir.GetLength()-1) != '/') redir += '/';
215 redir += str;
216 break;
221 if(_tcslen(p) > _tcslen(m_webroot) && p.FileExists())
223 path = (LPCTSTR)p;
224 return true;
228 return false;
231 bool CWebServer::LoadPage(UINT resid, CStringA& str, CString path)
233 CString redir;
234 if(ToLocalPath(path, redir))
236 if(FILE* f = _tfopen(path, _T("rb")))
238 fseek(f, 0, 2);
239 char* buff = str.GetBufferSetLength(ftell(f));
240 fseek(f, 0, 0);
241 int len = fread(buff, 1, str.GetLength(), f);
242 fclose(f);
243 return len == str.GetLength();
247 return LoadResource(resid, str, RT_HTML);
250 void CWebServer::OnAccept(CWebServerSocket* pServer)
252 CAutoPtr<CWebClientSocket> p(new CWebClientSocket(this, m_pMainFrame));
253 if(pServer->Accept(*p))
255 CString name;
256 UINT port;
257 if(AfxGetAppSettings().fWebServerLocalhostOnly && p->GetPeerName(name, port) && name != _T("127.0.0.1"))
259 p->Close();
260 return;
263 m_clients.AddTail(p);
267 void CWebServer::OnClose(CWebClientSocket* pClient)
269 POSITION pos = m_clients.GetHeadPosition();
270 while(pos)
272 POSITION cur = pos;
273 if(m_clients.GetNext(pos) == pClient)
275 m_clients.RemoveAt(cur);
276 break;
281 void CWebServer::OnRequest(CWebClientSocket* pClient, CStringA& hdr, CStringA& body)
283 CPath p(pClient->m_path);
284 CStringA ext = p.GetExtension().MakeLower();
285 CStringA mime;
286 if(ext.IsEmpty()) mime = "text/html";
287 else m_mimes.Lookup(ext, mime);
289 hdr = "HTTP/1.0 200 OK\r\n";
291 bool fHandled = false, fCGI = false;
293 if(!fHandled && m_webroot.IsDirectory())
295 CStringA tmphdr;
296 fHandled = fCGI = CallCGI(pClient, tmphdr, body, mime);
298 if(fHandled)
300 tmphdr.Replace("\r\n", "\n");
301 CAtlList<CStringA> hdrlines;
302 ExplodeMin(tmphdr, hdrlines, '\n');
303 POSITION pos = hdrlines.GetHeadPosition();
304 while(pos)
306 POSITION cur = pos;
307 CAtlList<CStringA> sl;
308 CStringA key = Explode(hdrlines.GetNext(pos), sl, ':', 2);
309 if(sl.GetCount() < 2) continue;
310 key.Trim().MakeLower();
311 if(key == "content-type") {mime = sl.GetTail().Trim(); hdrlines.RemoveAt(cur);}
312 else if(key == "content-length") {hdrlines.RemoveAt(cur);}
314 tmphdr = Implode(hdrlines, '\n');
315 tmphdr.Replace("\n", "\r\n");
316 hdr += tmphdr + "\r\n";
320 RequestHandler rh = NULL;
321 if(!fHandled && m_internalpages.Lookup(pClient->m_path, rh) && (pClient->*rh)(hdr, body, mime))
323 if(mime.IsEmpty()) mime = "text/html";
325 CString redir;
326 if(pClient->m_get.Lookup(_T("redir"), redir)
327 || pClient->m_post.Lookup(_T("redir"), redir))
329 if(redir.IsEmpty()) redir = '/';
331 hdr =
332 "HTTP/1.0 302 Found\r\n"
333 "Location: " + CStringA(redir) + "\r\n";
334 return;
337 fHandled = true;
340 if(!fHandled && m_webroot.IsDirectory())
342 fHandled = LoadPage(0, body, pClient->m_path);
345 UINT resid;
346 CStringA res;
347 if(!fHandled && m_downloads.Lookup(pClient->m_path, resid) && LoadResource(resid, res, _T("FILE")))
349 if(mime.IsEmpty()) mime = "application/octet-stream";
350 memcpy(body.GetBufferSetLength(res.GetLength()), res.GetBuffer(), res.GetLength());
351 fHandled = true;
354 if(!fHandled)
356 hdr = mime == "text/html"
357 ? "HTTP/1.0 301 Moved Permanently\r\n" "Location: /404.html\r\n"
358 : "HTTP/1.0 404 Not Found\r\n";
359 return;
362 if(mime == "text/html" && !fCGI)
364 hdr +=
365 "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n"
366 "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
367 "Pragma: no-cache\r\n";
369 CStringA debug;
370 if(AfxGetAppSettings().fWebServerPrintDebugInfo)
372 debug += "<hr>\r\n";
373 CString key, value;
374 POSITION pos;
375 pos = pClient->m_hdrlines.GetStartPosition();
376 while(pos) {pClient->m_hdrlines.GetNextAssoc(pos, key, value); debug += "HEADER[" + key + "] = " + value + "<br>\r\n";}
377 debug += "cmd: " + pClient->m_cmd + "<br>\r\n";
378 debug += "path: " + pClient->m_path + "<br>\r\n";
379 debug += "ver: " + pClient->m_ver + "<br>\r\n";
380 pos = pClient->m_get.GetStartPosition();
381 while(pos) {pClient->m_get.GetNextAssoc(pos, key, value); debug += "GET[" + key + "] = " + value + "<br>\r\n";}
382 pos = pClient->m_post.GetStartPosition();
383 while(pos) {pClient->m_post.GetNextAssoc(pos, key, value); debug += "POST[" + key + "] = " + value + "<br>\r\n";}
384 pos = pClient->m_cookie.GetStartPosition();
385 while(pos) {pClient->m_cookie.GetNextAssoc(pos, key, value); debug += "COOKIE[" + key + "] = " + value + "<br>\r\n";}
386 pos = pClient->m_request.GetStartPosition();
387 while(pos) {pClient->m_request.GetNextAssoc(pos, key, value); debug += "REQUEST[" + key + "] = " + value + "<br>\r\n";}
390 body.Replace("[path]", CStringA(pClient->m_path));
391 body.Replace("[indexpath]", "/index.html");
392 body.Replace("[commandpath]", "/command.html");
393 body.Replace("[browserpath]", "/browser.html");
394 body.Replace("[controlspath]", "/controls.html");
395 body.Replace("[wmcname]", "wm_command");
396 body.Replace("[setposcommand]", CMD_SETPOS);
397 body.Replace("[setvolumecommand]", CMD_SETVOLUME);
398 body.Replace("[debug]", debug);
399 // TODO: add more general tags to replace
402 // gzip
403 if(AfxGetAppSettings().fWebServerUseCompression && hdr.Find("Content-Encoding:") < 0)
406 CString accept_encoding;
407 pClient->m_hdrlines.Lookup(_T("accept-encoding"), accept_encoding);
408 accept_encoding.MakeLower();
409 CAtlList<CString> sl;
410 ExplodeMin(accept_encoding, sl, ',');
411 if(!sl.Find(_T("gzip"))) break;;
413 CHAR path[MAX_PATH], fn[MAX_PATH];
414 if(!GetTempPathA(MAX_PATH, path) || !GetTempFileNameA(path, "mpc_gz", 0, fn))
415 break;
417 gzFile gf = gzopen(fn, "wb9");
418 if(!gf || gzwrite(gf, (LPVOID)(LPCSTR)body, body.GetLength()) != body.GetLength())
420 if(gf) gzclose(gf);
421 DeleteFileA(fn);
422 break;
424 gzclose(gf);
426 FILE* f = fopen(fn, "rb");
427 if(!f) {DeleteFileA(fn); break;}
428 fseek(f, 0, 2);
429 CHAR* s = body.GetBufferSetLength(ftell(f));
430 fseek(f, 0, 0);
431 int len = fread(s, 1, body.GetLength(), f);
432 ASSERT(len == body.GetLength());
433 fclose(f);
434 DeleteFileA(fn);
436 hdr += "Content-Encoding: gzip\r\n";
438 while(0);
440 CStringA content;
441 content.Format(
442 "Content-Type: %s\r\n"
443 "Content-Length: %d\r\n",
444 mime, body.GetLength());
445 hdr += content;
448 static DWORD WINAPI KillCGI(LPVOID lParam)
450 HANDLE hProcess = (HANDLE)lParam;
451 if(WaitForSingleObject(hProcess, 30000) == WAIT_TIMEOUT)
452 TerminateProcess(hProcess, 0);
453 return 0;
456 bool CWebServer::CallCGI(CWebClientSocket* pClient, CStringA& hdr, CStringA& body, CStringA& mime)
458 CString path = pClient->m_path, redir = path;
459 if(!ToLocalPath(path, redir)) return false;
460 CString ext = CPath(path).GetExtension().MakeLower();
461 CPath dir(path);
462 dir.RemoveFileSpec();
464 CString cgi;
465 if(!m_cgi.Lookup(ext, cgi) || !CPath(cgi).FileExists())
466 return false;
468 HANDLE hProcess = GetCurrentProcess();
469 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup = NULL;
470 HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup = NULL;
472 SECURITY_ATTRIBUTES saAttr;
473 ZeroMemory(&saAttr, sizeof(saAttr));
474 saAttr.nLength = sizeof(saAttr);
475 saAttr.bInheritHandle = TRUE;
477 if(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
479 BOOL fSuccess = DuplicateHandle(hProcess, hChildStdoutRd, hProcess, &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
480 CloseHandle(hChildStdoutRd);
483 if(CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
485 BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
486 CloseHandle(hChildStdinWr);
489 STARTUPINFO siStartInfo;
490 ZeroMemory(&siStartInfo, sizeof(siStartInfo));
491 siStartInfo.cb = sizeof(siStartInfo);
492 siStartInfo.hStdError = hChildStdoutWr;
493 siStartInfo.hStdOutput = hChildStdoutWr;
494 siStartInfo.hStdInput = hChildStdinRd;
495 siStartInfo.dwFlags |= STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
496 siStartInfo.wShowWindow = SW_HIDE;
498 PROCESS_INFORMATION piProcInfo;
499 ZeroMemory(&piProcInfo, sizeof(piProcInfo));
501 CStringA envstr;
503 if(LPVOID lpvEnv = GetEnvironmentStrings())
505 CString str;
507 CAtlList<CString> env;
508 for(LPTSTR lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += _tcslen(lpszVariable)+1)
509 if(lpszVariable != (LPTSTR)lpvEnv)
510 env.AddTail(lpszVariable);
512 env.AddTail(_T("GATEWAY_INTERFACE=CGI/1.1"));
513 env.AddTail(_T("SERVER_SOFTWARE=Media Player Classic/6.4.x.y"));
514 env.AddTail(_T("SERVER_PROTOCOL=") + pClient->m_ver);
515 env.AddTail(_T("REQUEST_METHOD=") + pClient->m_cmd);
516 env.AddTail(_T("PATH_INFO=") + redir);
517 env.AddTail(_T("PATH_TRANSLATED=") + path);
518 env.AddTail(_T("SCRIPT_NAME=") + redir);
519 env.AddTail(_T("QUERY_STRING=") + pClient->m_query);
521 if(pClient->m_hdrlines.Lookup(_T("content-type"), str))
522 env.AddTail(_T("CONTENT_TYPE=") + str);
523 if(pClient->m_hdrlines.Lookup(_T("content-length"), str))
524 env.AddTail(_T("CONTENT_LENGTH=") + str);
526 POSITION pos = pClient->m_hdrlines.GetStartPosition();
527 while(pos)
529 CString key = pClient->m_hdrlines.GetKeyAt(pos);
530 CString value = pClient->m_hdrlines.GetNextValue(pos);
531 key.Replace(_T("-"), _T("_"));
532 key.MakeUpper();
533 env.AddTail(_T("HTTP_") + key + _T("=") + value);
536 CString name;
537 UINT port;
539 if(pClient->GetPeerName(name, port))
541 str.Format(_T("%d"), port);
542 env.AddTail(_T("REMOTE_ADDR=")+name);
543 env.AddTail(_T("REMOTE_HOST=")+name);
544 env.AddTail(_T("REMOTE_PORT=")+str);
547 if(pClient->GetSockName(name, port))
549 str.Format(_T("%d"), port);
550 env.AddTail(_T("SERVER_NAME=")+name);
551 env.AddTail(_T("SERVER_PORT=")+str);
554 env.AddTail(_T("\0"));
556 str = Implode(env, '\0');
557 envstr = CStringA(str, str.GetLength());
559 FreeEnvironmentStrings((LPTSTR)lpvEnv);
562 TCHAR* cmdln = new TCHAR[32768];
563 _sntprintf(cmdln, 32768, _T("\"%s\" \"%s\""), cgi, path);
565 if(hChildStdinRd && hChildStdoutWr)
566 if(CreateProcess(
567 NULL, cmdln, NULL, NULL, TRUE, 0,
568 envstr.GetLength() ? (LPVOID)(LPCSTR)envstr : NULL,
569 dir, &siStartInfo, &piProcInfo))
571 DWORD ThreadId;
572 CreateThread(NULL, 0, KillCGI, (LPVOID)piProcInfo.hProcess, 0, &ThreadId);
574 static const int BUFFSIZE = 1024;
575 DWORD dwRead, dwWritten = 0;
577 int i = 0, len = pClient->m_data.GetLength();
578 for(; i < len; i += dwWritten)
579 if(!WriteFile(hChildStdinWrDup, (LPCSTR)pClient->m_data + i, min(len - i, BUFFSIZE), &dwWritten, NULL))
580 break;
582 CloseHandle(hChildStdinWrDup);
583 CloseHandle(hChildStdoutWr);
585 body.Empty();
587 CStringA buff;
588 while(i == len && ReadFile(hChildStdoutRdDup, buff.GetBuffer(BUFFSIZE), BUFFSIZE, &dwRead, NULL) && dwRead)
590 buff.ReleaseBufferSetLength(dwRead);
591 body += buff;
594 int hdrend = body.Find("\r\n\r\n");
595 if(hdrend >= 0)
597 hdr = body.Left(hdrend+2);
598 body = body.Mid(hdrend+4);
601 CloseHandle(hChildStdinRd);
602 CloseHandle(hChildStdoutRdDup);
604 CloseHandle(piProcInfo.hProcess);
605 CloseHandle(piProcInfo.hThread);
607 else
609 body = _T("CGI Error");
612 delete [] cmdln;
614 return true;