WebServer.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:18k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "mplayerc.h"
  3. #include "resource.h"
  4. #include "MainFrm.h"
  5. #include <atlbase.h>
  6. #include <atlisapi.h>
  7. #include "WebServerSocket.h"
  8. #include "WebClientSocket.h"
  9. #include "WebServer.h"
  10. #include "....zlibzlib.h"
  11. CAtlMap<CString, CWebServer::RequestHandler, CStringElementTraits<CString> > CWebServer::m_internalpages;
  12. CAtlMap<CString, UINT, CStringElementTraits<CString> > CWebServer::m_downloads;
  13. CAtlMap<CStringA, CStringA, CStringElementTraits<CStringA> > CWebServer::m_mimes;
  14. CWebServer::CWebServer(CMainFrame* pMainFrame, int nPort)
  15. : m_pMainFrame(pMainFrame)
  16. , m_nPort(nPort)
  17. {
  18. if(m_internalpages.IsEmpty())
  19. {
  20. m_internalpages[_T("/")] = &CWebClientSocket::OnIndex;
  21. m_internalpages[_T("/index.html")] = &CWebClientSocket::OnIndex;
  22. m_internalpages[_T("/browser.html")] = &CWebClientSocket::OnBrowser;
  23. m_internalpages[_T("/controls.html")] = &CWebClientSocket::OnControls;
  24. m_internalpages[_T("/command.html")] = &CWebClientSocket::OnCommand;
  25. m_internalpages[_T("/status.html")] = &CWebClientSocket::OnStatus;
  26. m_internalpages[_T("/player.html")] = &CWebClientSocket::OnPlayer;
  27. m_internalpages[_T("/snapshot.jpg")] = &CWebClientSocket::OnSnapShotJpeg;
  28. m_internalpages[_T("/404.html")] = &CWebClientSocket::OnError404;
  29. m_internalpages[_T("/convres.html")] = &CWebClientSocket::OnConvRes;
  30. }
  31. if(m_downloads.IsEmpty())
  32. {
  33. m_downloads[_T("/default.css")] = IDF_DEFAULT_CSS;
  34. m_downloads[_T("/vbg.gif")] = IDF_VBR_GIF;
  35. m_downloads[_T("/vbs.gif")] = IDF_VBS_GIF;
  36. m_downloads[_T("/sliderbar.gif")] = IDF_SLIDERBAR_GIF;
  37. m_downloads[_T("/slidergrip.gif")] = IDF_SLIDERGRIP_GIF;
  38. m_downloads[_T("/sliderback.gif")] = IDF_SLIDERBACK_GIF;
  39. m_downloads[_T("/1pix.gif")] = IDF_1PIX_GIF;
  40. m_downloads[_T("/headericon.png")] = IDF_HEADERICON_PNG;
  41. m_downloads[_T("/headerback.png")] = IDF_HEADERBACK_PNG;
  42. m_downloads[_T("/headerclose.png")] = IDF_HEADERCLOSE_PNG;
  43. m_downloads[_T("/leftside.png")] = IDF_LEFTSIDE_PNG;
  44. m_downloads[_T("/rightside.png")] = IDF_RIGHTSIDE_PNG;
  45. m_downloads[_T("/bottomside.png")] = IDF_BOTTOMSIDE_PNG;
  46. m_downloads[_T("/leftbottomside.png")] = IDF_LEFTBOTTOMSIDE_PNG;
  47. m_downloads[_T("/rightbottomside.png")] = IDF_RIGHTBOTTOMSIDE_PNG;
  48. m_downloads[_T("/seekbarleft.png")] = IDF_SEEKBARLEFT_PNG;
  49. m_downloads[_T("/seekbarmid.png")] = IDF_SEEKBARMID_PNG;
  50. m_downloads[_T("/seekbarright.png")] = IDF_SEEKBARRIGHT_PNG;
  51. m_downloads[_T("/seekbargrip.png")] = IDF_SEEKBARGRIP_PNG;
  52. m_downloads[_T("/logo.png")] = IDF_LOGO_PNG;
  53. m_downloads[_T("/controlback.png")] = IDF_CONTROLBACK_PNG;
  54. m_downloads[_T("/controlbuttonplay.png")] = IDF_CONTROLBUTTONPLAY_PNG;
  55. m_downloads[_T("/controlbuttonpause.png")] = IDF_CONTROLBUTTONPAUSE_PNG;
  56. m_downloads[_T("/controlbuttonstop.png")] = IDF_CONTROLBUTTONSTOP_PNG;
  57. m_downloads[_T("/controlbuttonskipback.png")] = IDF_CONTROLBUTTONSKIPBACK_PNG;
  58. m_downloads[_T("/controlbuttondecrate.png")] = IDF_CONTROLBUTTONDECRATE_PNG;
  59. m_downloads[_T("/controlbuttonincrate.png")] = IDF_CONTROLBUTTONINCRATE_PNG;
  60. m_downloads[_T("/controlbuttonskipforward.png")] = IDF_CONTROLBUTTONSKIPFORWARD_PNG;
  61. m_downloads[_T("/controlbuttonstep.png")] = IDF_CONTROLBUTTONSTEP_PNG;
  62. m_downloads[_T("/controlvolumeon.png")] = IDF_CONTROLVOLUMEON_PNG;
  63. m_downloads[_T("/controlvolumeoff.png")] = IDF_CONTROLVOLUMEOFF_PNG;
  64. m_downloads[_T("/controlvolumebar.png")] = IDF_CONTROLVOLUMEBAR_PNG;
  65. m_downloads[_T("/controlvolumegrip.png")] = IDF_CONTROLVOLUMEGRIP_PNG;
  66. }
  67. CRegKey key;
  68. CString str(_T("MIME\Database\Content Type"));
  69. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
  70. {
  71. TCHAR buff[256];
  72. DWORD len = countof(buff);
  73. for(int i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len); i++, len = countof(buff))
  74. {
  75. CRegKey mime;
  76. TCHAR ext[64];
  77. ULONG len = countof(ext);
  78. if(ERROR_SUCCESS == mime.Open(HKEY_CLASSES_ROOT, str + _T("\") + buff, KEY_READ)
  79. && ERROR_SUCCESS == mime.QueryStringValue(_T("Extension"), ext, &len))
  80. m_mimes[CStringA(ext).MakeLower()] = CStringA(buff).MakeLower();
  81. }
  82. }
  83. m_mimes[".html"] = "text/html";
  84. m_mimes[".txt"] = "text/plain";
  85. m_mimes[".css"] = "text/css";
  86. m_mimes[".gif"] = "image/gif";
  87. m_mimes[".jpeg"] = "image/jpeg";
  88. m_mimes[".jpg"] = "image/jpeg";
  89. m_mimes[".png"] = "image/png";
  90. GetModuleFileName(AfxGetInstanceHandle(), str.GetBuffer(MAX_PATH), MAX_PATH);
  91. str.ReleaseBuffer();
  92. m_webroot = CPath(str);
  93. m_webroot.RemoveFileSpec();
  94. CString WebRoot = AfxGetAppSettings().WebRoot;
  95. WebRoot.Replace('/', '\');
  96. WebRoot.Trim();
  97. CPath p(WebRoot);
  98. if(WebRoot.Find(_T(":\")) < 0 && WebRoot.Find(_T("\\")) < 0) m_webroot.Append(WebRoot);
  99. else m_webroot = p;
  100. m_webroot.Canonicalize();
  101. m_webroot.MakePretty();
  102. if(!m_webroot.IsDirectory()) m_webroot = CPath();
  103. CList<CString> sl;
  104. Explode(AfxGetAppSettings().WebServerCGI, sl, ';');
  105. POSITION pos = sl.GetHeadPosition();
  106. while(pos)
  107. {
  108. CList<CString> sl2;
  109. CString ext = Explode(sl.GetNext(pos), sl2, '=', 2);
  110. if(sl2.GetCount() < 2) continue;
  111. m_cgi[ext] = sl2.GetTail();
  112. }
  113. m_ThreadId = 0;
  114.     m_hThread = ::CreateThread(NULL, 0, StaticThreadProc, (LPVOID)this, 0, &m_ThreadId);
  115. }
  116. CWebServer::~CWebServer()
  117. {
  118.     if(m_hThread != NULL)
  119. {
  120. PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0);
  121.         WaitForSingleObject(m_hThread, 10000);
  122.         EXECUTE_ASSERT(CloseHandle(m_hThread));
  123.     }
  124. }
  125. DWORD WINAPI CWebServer::StaticThreadProc(LPVOID lpParam)
  126. {
  127. return ((CWebServer*)lpParam)->ThreadProc();
  128. }
  129. DWORD CWebServer::ThreadProc()
  130. {
  131. if(!AfxSocketInit(NULL))
  132. return -1;
  133. CWebServerSocket s(this, m_nPort);
  134. MSG msg;
  135. while((int)GetMessage(&msg, NULL, 0, 0) > 0)
  136. {
  137. TranslateMessage(&msg);
  138. DispatchMessage(&msg);
  139. }
  140. return 0;
  141. }
  142. static void PutFileContents(LPCTSTR fn, const CStringA& data)
  143. {
  144. if(FILE* f = _tfopen(fn, _T("wb")))
  145. {
  146. fwrite((LPCSTR)data, 1, data.GetLength(), f);
  147. fclose(f);
  148. }
  149. }
  150. void CWebServer::Deploy(CString dir)
  151. {
  152. CStringA data;
  153. if(LoadResource(IDR_HTML_INDEX, data, RT_HTML)) PutFileContents(dir + _T("index.html"), data);
  154. if(LoadResource(IDR_HTML_BROWSER, data, RT_HTML)) PutFileContents(dir + _T("browser.html"), data);
  155. if(LoadResource(IDR_HTML_CONTROLS, data, RT_HTML)) PutFileContents(dir + _T("controls.html"), data);
  156. if(LoadResource(IDR_HTML_404, data, RT_HTML)) PutFileContents(dir + _T("404.html"), data);
  157. if(LoadResource(IDR_HTML_PLAYER, data, RT_HTML)) PutFileContents(dir + _T("player.html"), data);
  158. POSITION pos = m_downloads.GetStartPosition();
  159. while(pos)
  160. {
  161. CString fn;
  162. UINT id;
  163. m_downloads.GetNextAssoc(pos, fn, id);
  164. if(LoadResource(id, data, _T("FILE")))
  165. PutFileContents(dir + fn, data);
  166. }
  167. }
  168. bool CWebServer::ToLocalPath(CString& path, CString& redir)
  169. {
  170. if(!path.IsEmpty() && m_webroot.IsDirectory())
  171. {
  172. CString str = path;
  173. str.Replace('/', '\');
  174. str.TrimLeft('\');
  175. CPath p;
  176. p.Combine(m_webroot, str);
  177. p.Canonicalize();
  178. if(p.IsDirectory())
  179. {
  180. CList<CString> sl;
  181. Explode(AfxGetAppSettings().WebDefIndex, sl, ';');
  182. POSITION pos = sl.GetHeadPosition();
  183. while(pos)
  184. {
  185. str = sl.GetNext(pos);
  186. CPath p2 = p;
  187. p2.Append(str);
  188. if(p2.FileExists())
  189. {
  190. p = p2;
  191. redir = path;
  192. if(redir.GetAt(redir.GetLength()-1) != '/') redir += '/';
  193. redir += str;
  194. break;
  195. }
  196. }
  197. }
  198. if(_tcslen(p) > _tcslen(m_webroot) && p.FileExists())
  199. {
  200. path = (LPCTSTR)p;
  201. return true;
  202. }
  203. }
  204. return false;
  205. }
  206. bool CWebServer::LoadPage(UINT resid, CStringA& str, CString path)
  207. {
  208. CString redir;
  209. if(ToLocalPath(path, redir))
  210. {
  211. if(FILE* f = _tfopen(path, _T("rb")))
  212. {
  213. fseek(f, 0, 2);
  214. char* buff = str.GetBufferSetLength(ftell(f));
  215. fseek(f, 0, 0);
  216. int len = fread(buff, 1, str.GetLength(), f);
  217. fclose(f);
  218. return len == str.GetLength();
  219. }
  220. }
  221. return LoadResource(resid, str, RT_HTML);
  222. }
  223. void CWebServer::OnAccept(CWebServerSocket* pServer)
  224. {
  225. CAutoPtr<CWebClientSocket> p(new CWebClientSocket(this, m_pMainFrame));
  226. if(pServer->Accept(*p))
  227. {
  228. CString name;
  229. UINT port;
  230. if(AfxGetAppSettings().fWebServerLocalhostOnly && p->GetPeerName(name, port) && name != _T("127.0.0.1"))
  231. {
  232. p->Close();
  233. return;
  234. }
  235. m_clients.AddTail(p);
  236. }
  237. }
  238. void CWebServer::OnClose(CWebClientSocket* pClient)
  239. {
  240. POSITION pos = m_clients.GetHeadPosition();
  241. while(pos)
  242. {
  243. POSITION cur = pos;
  244. if(m_clients.GetNext(pos) == pClient)
  245. {
  246. m_clients.RemoveAt(cur);
  247. break;
  248. }
  249. }
  250. }
  251. void CWebServer::OnRequest(CWebClientSocket* pClient, CStringA& hdr, CStringA& body)
  252. {
  253. CPath p(pClient->m_path);
  254. CStringA ext = p.GetExtension().MakeLower();
  255. CStringA mime;
  256. if(ext.IsEmpty()) mime = "text/html";
  257. else m_mimes.Lookup(ext, mime);
  258. hdr = "HTTP/1.0 200 OKrn";
  259. bool fHandled = false, fCGI = false;
  260. if(!fHandled && m_webroot.IsDirectory())
  261. {
  262. CStringA tmphdr;
  263. fHandled = fCGI = CallCGI(pClient, tmphdr, body, mime);
  264. if(fHandled)
  265. {
  266. tmphdr.Replace("rn", "n");
  267. CList<CStringA> hdrlines;
  268. ExplodeMin(tmphdr, hdrlines, 'n');
  269. POSITION pos = hdrlines.GetHeadPosition();
  270. while(pos)
  271. {
  272. POSITION cur = pos;
  273. CList<CStringA> sl;
  274. CStringA key = Explode(hdrlines.GetNext(pos), sl, ':', 2);
  275. if(sl.GetCount() < 2) continue;
  276. key.Trim().MakeLower();
  277. if(key == "content-type") {mime = sl.GetTail().Trim(); hdrlines.RemoveAt(cur);}
  278. else if(key == "content-length") {hdrlines.RemoveAt(cur);}
  279. }
  280. tmphdr = Implode(hdrlines, 'n');
  281. tmphdr.Replace("n", "rn");
  282. hdr += tmphdr + "rn";
  283. }
  284. }
  285. RequestHandler rh = NULL;
  286. if(!fHandled && m_internalpages.Lookup(pClient->m_path, rh) && (pClient->*rh)(hdr, body, mime))
  287. {
  288. if(mime.IsEmpty()) mime = "text/html";
  289. CString redir;
  290. if(pClient->m_get.Lookup(_T("redir"), redir)
  291. || pClient->m_post.Lookup(_T("redir"), redir))
  292. {
  293. if(redir.IsEmpty()) redir = '/';
  294. hdr = 
  295. "HTTP/1.0 302 Foundrn"
  296. "Location: " + CStringA(redir) + "rn";
  297. return;
  298. }
  299. fHandled = true;
  300. }
  301. if(!fHandled && m_webroot.IsDirectory())
  302. {
  303. fHandled = LoadPage(0, body, pClient->m_path);
  304. }
  305. UINT resid;
  306. CStringA res;
  307. if(!fHandled && m_downloads.Lookup(pClient->m_path, resid) && LoadResource(resid, res, _T("FILE")))
  308. {
  309. if(mime.IsEmpty()) mime = "application/octet-stream";
  310. memcpy(body.GetBufferSetLength(res.GetLength()), res.GetBuffer(), res.GetLength());
  311. fHandled = true;
  312. }
  313. if(!fHandled)
  314. {
  315. hdr = mime == "text/html"
  316. ? "HTTP/1.0 301 Moved Permanentlyrn" "Location: /404.htmlrn"
  317. : "HTTP/1.0 404 Not Foundrn";
  318. return;
  319. }
  320. if(mime == "text/html" && !fCGI)
  321. {
  322. hdr += 
  323. "Expires: Thu, 19 Nov 1981 08:52:00 GMTrn"
  324. "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0rn"
  325. "Pragma: no-cachern";
  326. CStringA debug;
  327. if(AfxGetAppSettings().fWebServerPrintDebugInfo)
  328. {
  329. debug += "<hr>rn";
  330. CString key, value;
  331. POSITION pos;
  332. pos = pClient->m_hdrlines.GetStartPosition();
  333. while(pos) {pClient->m_hdrlines.GetNextAssoc(pos, key, value); debug += "HEADER[" + key + "] = " + value + "<br>rn";}
  334. debug += "cmd: " + pClient->m_cmd + "<br>rn";
  335. debug += "path: " + pClient->m_path + "<br>rn";
  336. debug += "ver: " + pClient->m_ver + "<br>rn";
  337. pos = pClient->m_get.GetStartPosition();
  338. while(pos) {pClient->m_get.GetNextAssoc(pos, key, value); debug += "GET[" + key + "] = " + value + "<br>rn";}
  339. pos = pClient->m_post.GetStartPosition();
  340. while(pos) {pClient->m_post.GetNextAssoc(pos, key, value); debug += "POST[" + key + "] = " + value + "<br>rn";}
  341. pos = pClient->m_cookie.GetStartPosition();
  342. while(pos) {pClient->m_cookie.GetNextAssoc(pos, key, value); debug += "COOKIE[" + key + "] = " + value + "<br>rn";}
  343. pos = pClient->m_request.GetStartPosition();
  344. while(pos) {pClient->m_request.GetNextAssoc(pos, key, value); debug += "REQUEST[" + key + "] = " + value + "<br>rn";}
  345. }
  346. body.Replace("[path]", CStringA(pClient->m_path));
  347. body.Replace("[indexpath]", "/index.html");
  348. body.Replace("[commandpath]", "/command.html");
  349. body.Replace("[browserpath]", "/browser.html");
  350. body.Replace("[controlspath]", "/controls.html");
  351. body.Replace("[wmcname]", "wm_command");
  352. body.Replace("[setposcommand]", CMD_SETPOS);
  353. body.Replace("[setvolumecommand]", CMD_SETVOLUME);
  354. body.Replace("[debug]", debug);
  355. // TODO: add more general tags to replace
  356. }
  357. // gzip
  358. if(AfxGetAppSettings().fWebServerUseCompression && hdr.Find("Content-Encoding:") < 0)
  359. do
  360. {
  361. CString accept_encoding;
  362. pClient->m_hdrlines.Lookup(_T("accept-encoding"), accept_encoding);
  363. accept_encoding.MakeLower();
  364. CList<CString> sl;
  365. ExplodeMin(accept_encoding, sl, ',');
  366. if(!sl.Find(_T("gzip"))) break;;
  367. CHAR path[MAX_PATH], fn[MAX_PATH];
  368. if(!GetTempPathA(MAX_PATH, path) || !GetTempFileNameA(path, "mpc_gz", 0, fn))
  369. break;
  370. gzFile gf = gzopen(fn, "wb9");
  371. if(!gf || gzwrite(gf, (LPVOID)(LPCSTR)body, body.GetLength()) != body.GetLength())
  372. {
  373. if(gf) gzclose(gf);
  374. DeleteFileA(fn);
  375. break;
  376. }
  377. gzclose(gf);
  378. FILE* f = fopen(fn, "rb");
  379. if(!f) {DeleteFileA(fn); break;}
  380. fseek(f, 0, 2);
  381. CHAR* s = body.GetBufferSetLength(ftell(f));
  382. fseek(f, 0, 0);
  383. int len = fread(s, 1, body.GetLength(), f);
  384. ASSERT(len == body.GetLength());
  385. fclose(f);
  386. DeleteFileA(fn);
  387. hdr += "Content-Encoding: gziprn";
  388. }
  389. while(0);
  390. CStringA content;
  391. content.Format(
  392. "Content-Type: %srn"
  393. "Content-Length: %drn", 
  394. mime, body.GetLength());
  395. hdr += content;
  396. }
  397. static DWORD WINAPI KillCGI(LPVOID lParam)
  398. {
  399. HANDLE hProcess = (HANDLE)lParam;
  400. if(WaitForSingleObject(hProcess, 30000) == WAIT_TIMEOUT)
  401. TerminateProcess(hProcess, 0);
  402. return 0;
  403. }
  404. bool CWebServer::CallCGI(CWebClientSocket* pClient, CStringA& hdr, CStringA& body, CStringA& mime)
  405. {
  406. CString path = pClient->m_path, redir = path;
  407. if(!ToLocalPath(path, redir)) return false;
  408. CString ext = CPath(path).GetExtension().MakeLower();
  409. CPath dir(path);
  410. dir.RemoveFileSpec();
  411. CString cgi;
  412. if(!m_cgi.Lookup(ext, cgi) || !CPath(cgi).FileExists())
  413. return false;
  414. HANDLE hProcess = GetCurrentProcess();
  415. HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup = NULL;
  416. HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup = NULL;
  417. SECURITY_ATTRIBUTES saAttr;
  418. ZeroMemory(&saAttr, sizeof(saAttr));
  419. saAttr.nLength = sizeof(saAttr);
  420. saAttr.bInheritHandle = TRUE;
  421. if(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
  422. {
  423. BOOL fSuccess = DuplicateHandle(hProcess, hChildStdoutRd, hProcess, &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
  424. CloseHandle(hChildStdoutRd);
  425. }
  426. if(CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
  427. {
  428. BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
  429. CloseHandle(hChildStdinWr);
  430. }
  431. STARTUPINFO siStartInfo;
  432. ZeroMemory(&siStartInfo, sizeof(siStartInfo));
  433. siStartInfo.cb = sizeof(siStartInfo);
  434. siStartInfo.hStdError = hChildStdoutWr;
  435. siStartInfo.hStdOutput = hChildStdoutWr;
  436. siStartInfo.hStdInput = hChildStdinRd;
  437. siStartInfo.dwFlags |= STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  438. siStartInfo.wShowWindow = SW_HIDE;
  439. PROCESS_INFORMATION piProcInfo;
  440. ZeroMemory(&piProcInfo, sizeof(piProcInfo));
  441. CStringA envstr;
  442. if(LPVOID lpvEnv = GetEnvironmentStrings())
  443. {
  444. CString str; 
  445. CList<CString> env;
  446. for(LPTSTR lpszVariable = (LPTSTR)lpvEnv; *lpszVariable; lpszVariable += _tcslen(lpszVariable)+1)
  447. if(lpszVariable != (LPTSTR)lpvEnv)
  448. env.AddTail(lpszVariable);
  449. env.AddTail(_T("GATEWAY_INTERFACE=CGI/1.1"));
  450. env.AddTail(_T("SERVER_SOFTWARE=Media Player Classic/6.4.x.y"));
  451. env.AddTail(_T("SERVER_PROTOCOL=") + pClient->m_ver);
  452. env.AddTail(_T("REQUEST_METHOD=") + pClient->m_cmd);
  453. env.AddTail(_T("PATH_INFO=") + redir);
  454. env.AddTail(_T("PATH_TRANSLATED=") + path);
  455. env.AddTail(_T("SCRIPT_NAME=") + redir);
  456. env.AddTail(_T("QUERY_STRING=") + pClient->m_query);
  457. if(pClient->m_hdrlines.Lookup(_T("content-type"), str))
  458. env.AddTail(_T("CONTENT_TYPE=") + str);
  459. if(pClient->m_hdrlines.Lookup(_T("content-length"), str))
  460. env.AddTail(_T("CONTENT_LENGTH=") + str);
  461. POSITION pos = pClient->m_hdrlines.GetStartPosition();
  462. while(pos)
  463. {
  464. CString key = pClient->m_hdrlines.GetKeyAt(pos);
  465. CString value = pClient->m_hdrlines.GetNextValue(pos);
  466. key.Replace(_T("-"), _T("_"));
  467. key.MakeUpper();
  468. env.AddTail(_T("HTTP_") + key + _T("=") + value);
  469. }
  470. CString name;
  471. UINT port;
  472. if(pClient->GetPeerName(name, port))
  473. {
  474. str.Format(_T("%d"), port);
  475. env.AddTail(_T("REMOTE_ADDR=")+name);
  476. env.AddTail(_T("REMOTE_HOST=")+name);
  477. env.AddTail(_T("REMOTE_PORT=")+str);
  478. }
  479. if(pClient->GetSockName(name, port))
  480. {
  481. str.Format(_T("%d"), port);
  482. env.AddTail(_T("SERVER_NAME=")+name);
  483. env.AddTail(_T("SERVER_PORT=")+str);
  484. }
  485. env.AddTail(_T(""));
  486. str = Implode(env, '');
  487. envstr = CStringA(str, str.GetLength());
  488. FreeEnvironmentStrings((LPTSTR)lpvEnv);
  489. }
  490. TCHAR* cmdln = new TCHAR[32768];
  491. _sntprintf(cmdln, 32768, _T(""%s" "%s""), cgi, path);
  492. if(hChildStdinRd && hChildStdoutWr)
  493. if(CreateProcess(
  494. NULL, cmdln, NULL, NULL, TRUE, 0, 
  495. envstr.GetLength() ? (LPVOID)(LPCSTR)envstr : NULL, 
  496. dir, &siStartInfo, &piProcInfo))
  497. {
  498. DWORD ThreadId;
  499. CreateThread(NULL, 0, KillCGI, (LPVOID)piProcInfo.hProcess, 0, &ThreadId);
  500. static const int BUFFSIZE = 1024;
  501. DWORD dwRead, dwWritten = 0;
  502. int i = 0, len = pClient->m_data.GetLength();
  503. for(; i < len; i += dwWritten)
  504. if(!WriteFile(hChildStdinWrDup, (LPCSTR)pClient->m_data + i, min(len - i, BUFFSIZE), &dwWritten, NULL)) 
  505. break;
  506. CloseHandle(hChildStdinWrDup);
  507. CloseHandle(hChildStdoutWr);
  508. body.Empty();
  509. CStringA buff;
  510. while(i == len && ReadFile(hChildStdoutRdDup, buff.GetBuffer(BUFFSIZE), BUFFSIZE, &dwRead, NULL) && dwRead)
  511. {
  512. buff.ReleaseBufferSetLength(dwRead);
  513. body += buff;
  514. }
  515. int hdrend = body.Find("rnrn");
  516. if(hdrend >= 0)
  517. {
  518. hdr = body.Left(hdrend+2);
  519. body = body.Mid(hdrend+4);
  520. }
  521. CloseHandle(hChildStdinRd);
  522. CloseHandle(hChildStdoutRdDup);
  523. CloseHandle(piProcInfo.hProcess);
  524. CloseHandle(piProcInfo.hThread);
  525. }
  526. else
  527. {
  528. body = _T("CGI Error");
  529. }
  530. delete [] cmdln;
  531. return true;
  532. }