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); }
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); UNREFERENCED_PARAMETER(fSuccess); CloseHandle(hChildStdoutRd); } if (CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { BOOL fSuccess = DuplicateHandle(hProcess, hChildStdinWr, hProcess, &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS); UNREFERENCED_PARAMETER(fSuccess); 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; LPVOID lpvEnv = GetEnvironmentStrings(); if (lpvEnv) { 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 - Home Cinema/") MPC_VERSION_STR); 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 = DNew TCHAR[32768]; _sntprintf_s(cmdln, 32768, 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; }