예제 #1
0
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);
}
예제 #2
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);
        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;
}