⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpcgi.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  if (pSettings->m_sBindAddress.GetLength())
    sLine.Format(_T("SERVER_NAME=%s\n"), pSettings->m_sBindAddress);
  else
  {
    char pszHostName[256];
    if (gethostname(pszHostName, 256) == 0)
    {
      CString sName(pszHostName);
      sLine.Format(_T("SERVER_NAME=%s\n"), sName);
    }
    else
      sLine = (_T("SERVER_NAME=\n"));
  }
  sEnvironment += sLine;

  if (pClient->m_Request.m_nContentLength)
  {
    sLine.Format(_T("CONTENT_LENGTH=%d\n"), pClient->m_Request.m_nContentLength);
    sEnvironment += sLine;
  }

  if (pClient->m_Request.m_sContentType.GetLength())
  {
    sLine.Format(_T("CONTENT_TYPE=%s\n"), pClient->m_Request.m_sContentType);
    sEnvironment += sLine;
  }

  sLine.Format(_T("SERVER_PORT=%d\n"), pSettings->m_nPort);
  sEnvironment += sLine;

#ifdef W3MFC_SSL_SUPPORT
  if (pSettings->m_SSLProtocol == CHttpServerSettings::SSL_NONE)
    sEnvironment += _T("SERVER_PROTOCOL=HTTP/1.0\n");
  else
    sEnvironment += _T("SERVER_PROTOCOL=HTTPS/1.0\n");
#else
  sEnvironment += _T("SERVER_PROTOCOL=HTTP/1.0\n");
#endif

  sLine.Format(_T("SERVER_SOFTWARE=%s\n"), pSettings->m_sServerName);
  sEnvironment += sLine;

  CString sScriptName = pClient->m_Request.m_sLocalFile;
  sScriptName.Replace(_T('\\'), _T('/')); //Ensure we use unix directory separators
  if (sScriptName.GetLength() && sScriptName.GetAt(0) != _T('/'))
    sScriptName = _T("/") + sScriptName;
  sLine.Format(_T("SCRIPT_NAME=%s\n"), sScriptName);
  sEnvironment += sLine;

  //Form the absolute path for PATH_TRANSLATED
  LPTSTR pszFilePart;
  TCHAR pszAbsolutePath[_MAX_PATH];
  GetFullPathName(pClient->m_Request.m_sLocalFile, _MAX_PATH, pszAbsolutePath, &pszFilePart);
  sLine.Format(_T("PATH_TRANSLATED=%s\n"), pszAbsolutePath);
  sEnvironment += sLine;

  sLine.Format(_T("REQUEST_LINE=%s\n"), pClient->m_Request.m_sRequest);
  sEnvironment += sLine;

  sLine.Format(_T("QUERY_STRING=%s\n"), pClient->m_Request.m_sRawExtra);
  sEnvironment += sLine;
  
  if (!pClient->m_Request.m_sRemoteHost.IsEmpty())
  {
    sLine.Format(_T("REMOTE_HOST=%s\n"), pClient->m_Request.m_sRemoteHost);
    sEnvironment += sLine;
  }
  else
  {
    sLine.Format(_T("REMOTE_HOST=%d.%d.%d.%d\n"), pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b1,
                 pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b2, pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b3,
                 pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b4);
    sEnvironment += sLine;
  }

  sLine.Format(_T("REMOTE_ADDR=%d.%d.%d.%d\n"), pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b1,
               pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b2, pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b3,
               pClient->m_Request.m_ClientAddress.sin_addr.S_un.S_un_b.s_b4);
  sEnvironment += sLine;

  sLine.Format(_T("PATH_INFO=%s\n"), pClient->m_Request.m_sPathInfo);
  sEnvironment += sLine;

  sLine.Format(_T("REQUEST_METHOD=%s\n"), pClient->m_Request.m_sVerb);
  sEnvironment += sLine;

  int nKeySize = 0;
  if (pClient->GetKeySizeServerVariable(nKeySize))
  {
    sLine.Format(_T("HTTPS_KEYSIZE=%d\nCERT_KEYSIZE=%d\n"), nKeySize, nKeySize);
    sEnvironment += sLine;
  }

  if (pClient->GetServerKeySizeServerVariable(nKeySize))
  {
    sLine.Format(_T("HTTPS_SECRETKEYSIZE=%d\nCERT_SECRETKEYSIZE=%d\n"), nKeySize, nKeySize);
    sEnvironment += sLine;
  }

  sEnvironment += sLine;

#ifdef W3MFC_SSL_SUPPORT
  if (pSettings->m_SSLProtocol == CHttpServerSettings::SSL_NONE)
    sLine = _T("HTTPS=off\n");
  else
    sLine = _T("HTTPS=on\n");
#else
  sLine = _T("HTTPS=off\n");
#endif
  sEnvironment += sLine;

#ifdef W3MFC_SSL_SUPPORT
  if (pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
  {
    sLine.Format(_T("SERVER_PORT_SECURE=%d\n"), pSettings->m_nPort);
    sEnvironment += sLine;
  }
#endif

  long nSerialNumber = 0;
  if (pClient->GetCertSerialNumberServerVariable(nSerialNumber))
  {
    sLine.Format(_T("CERT_SERIALNUMBER=%d\n"), nSerialNumber);
    sEnvironment += sLine;
  }

  sLine.Format(_T("REQUEST_URI=%s\n"), pClient->m_Request.m_sURL);
  sEnvironment += sLine;

  sLine.Format(_T("URL=%s\n"), pClient->m_Request.m_sURL);
  sEnvironment += sLine;

  if (pClient->m_Request.m_bLoggedOn)
  {
    sLine.Format(_T("LOGON_USER=%s\n"), pClient->m_Request.m_sUsername);
    sEnvironment += sLine;
  }
  else if (pSettings->m_sUsername.GetLength())
  {
    sLine.Format(_T("LOGON_USER=%s\n"), pSettings->m_sUsername);
    sEnvironment += sLine;
  }

  char* szIssuer = NULL;
  if (pClient->GetCertIssuerServerVariable(szIssuer))
  { 
    CString sIssuer(szIssuer);
    sLine.Format(_T("CERT_SERVER_ISSUER=%s\nHTTPS_SERVER_ISSUER=%s\n"), sIssuer, sIssuer);
    sEnvironment += sLine;
  }

  char* szSubject = NULL;
  if (pClient->GetCertSubjectServerVariable(szSubject))
  { 
    CString sSubject(szSubject);
    sLine.Format(_T("CERT_SERVER_SUBJECT=%s\nHTTPS_SERVER_SUBJECT=%s\n"), sSubject, sSubject);
    sEnvironment += sLine;
  }

  sLine.Format(_T("HTTP_VERSION=%d.%d\n"), HIWORD(pClient->m_Request.m_dwHttpVersion), LOWORD(pClient->m_Request.m_dwHttpVersion));
  sEnvironment += sLine;

  POSITION posMap = pClient->m_Request.m_HeaderMap.GetStartPosition();
  while (posMap)
  {
    CString sKey;
    CString sValue;
    pClient->m_Request.m_HeaderMap.GetNextAssoc(posMap, sKey, sValue);

    sLine.Format(_T("HTTP_%s=%s\n"), sKey, sValue);
    sEnvironment += sLine;
  }

  return sEnvironment;
}

CString CHttpCGI::GetCGICommandLine(CHttpClient* pClient)
{
  //What will be the return value
  CString sCommandLine(pClient->m_Request.m_sLocalFile);

  //First get the extension of the file
  TCHAR sExt[_MAX_EXT];
  _tsplitpath(pClient->m_Request.m_sLocalFile, NULL, NULL, NULL, sExt);

  //Now get the command line for this extension from the registry
  TCHAR pszValue[1024/sizeof(TCHAR)];
  DWORD nData = 1024;
  HKEY hExtKey = NULL;
  if (RegOpenKeyEx(HKEY_CLASSES_ROOT, sExt, 0, KEY_READ, &hExtKey) == ERROR_SUCCESS)
  {
	  if (RegQueryValueEx(hExtKey, NULL, NULL, NULL, (LPBYTE)pszValue, &nData) == ERROR_SUCCESS)
	  {
      //Close the registry key now that we are finished with it
      RegCloseKey(hExtKey);

		  //pszValue is now the Extension File Subkey to use.
		  CString sValue;
		  sValue.Format(_T("%s\\Shell\\Open\\Command"), pszValue);
		  nData = 1024; //reset the size parameter

      HKEY hExtensionFileKey = NULL;
      if (RegOpenKeyEx(HKEY_CLASSES_ROOT, sValue, 0, KEY_READ, &hExtensionFileKey) == ERROR_SUCCESS)
		  {
 			  if (RegQueryValueEx(hExtensionFileKey, NULL, NULL, NULL, (LPBYTE)pszValue, &nData) == ERROR_SUCCESS)
			  {
          //Expand the string with any environment variables it may contain
          nData = 1024;
					LPTSTR szBuf = sCommandLine.GetBuffer(nData);
					DWORD  dwRet = ExpandEnvironmentStrings(pszValue, szBuf, nData); 
					sCommandLine.ReleaseBuffer();

          if (dwRet != 0)
          {
			      sCommandLine.Replace(_T("%L"), pClient->m_Request.m_sLocalFile);
			      sCommandLine.Replace(_T("%1"), pClient->m_Request.m_sLocalFile);
			      sCommandLine.Replace(_T("%*"), _T("")); 
          }
			  }

        //Close the registry key now that we are finished with it
			  RegCloseKey(hExtensionFileKey);
		  }
	  }
  }

  return sCommandLine;
}

void CHttpCGI::WriteToChildStdin(CHttpClient* pClient, HANDLE hChildStdin)
{
  //Write the entity body to STDIN of the CGI child process
  DWORD dwWritten;
  ASSERT(pClient->m_Request.m_pRawEntity);
  WriteFile(hChildStdin, pClient->m_Request.m_pRawEntity, pClient->m_Request.m_dwRawEntitySize, &dwWritten, NULL);
}

DWORD CHttpCGI::ReadFromClientStdout(CHttpClient* pClient, HANDLE hChildStdout, BOOL& bFoundKeepAlive) 
{ 
  //Validate our parameters
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);

  //Initialize the out parameters
  bFoundKeepAlive = FALSE;
  DWORD dwDataSent = 0;

  //Allocate the receive / re transmit buffer
  char* pszBuf = (char*) alloca(pSettings->m_dwCGIResponseBufferSize); 

  //Read output from the child process, and write to parent's STDOUT. 
  BOOL bMore = TRUE;
  BOOL bFirstBuffer = TRUE;
  while (bMore) 
  { 
    DWORD dwRead;
    if (!ReadFile(hChildStdout, pszBuf, pSettings->m_dwCGIResponseBufferSize-1, &dwRead, NULL) || dwRead == 0) 
      bMore = FALSE; 
    else
    {
      //Used as a return value to indicate how much was sent to the client
      dwDataSent += dwRead;
      BOOL bFoundHTTPReturnCodeLine = FALSE;

      if (bFirstBuffer)
      {
        //NULL terminate the data (so that we can use strstr)
        pszBuf[dwRead] = '\0';

        //See if the "Connection: Keep Alive" is being transmitted
        bFoundKeepAlive = (strstr(pszBuf, "Connection: Keep-Alive") != NULL);
        if (bFoundKeepAlive)
        {
          //Note it is important that "Content-Length" be also sent when using keep alives
          //as otherwise client browsers do not know when to stop reading to get the end
          //of the first response
          bFoundKeepAlive = (strstr(pszBuf, "Content-Length: ") != NULL);
        }
        
        //Do we have a HTTP return code line
        bFoundHTTPReturnCodeLine = (strstr(pszBuf,"HTTP/") != NULL);

        //We only do this parse on the first buffer
        bFirstBuffer = FALSE;
      }

      //Send the data back down the socket
      try
      {
 			  char* pszTTPReturnCodeLine = "HTTP/1.0 200 OK\n";
#ifdef W3MFC_SSL_SUPPORT
        if (!bFoundHTTPReturnCodeLine)
			    pClient->m_Socket.SendWithRetry(pszTTPReturnCodeLine, strlen(pszTTPReturnCodeLine), pSettings->m_dwWritableTimeout, pClient->m_SSL);
        pClient->m_Socket.SendWithRetry(pszBuf, dwRead, pSettings->m_dwWritableTimeout, pClient->m_SSL);
#else
        if (!bFoundHTTPReturnCodeLine)
			    pClient->m_Socket.SendWithRetry(pszTTPReturnCodeLine, strlen(pszTTPReturnCodeLine), pSettings->m_dwWritableTimeout);
        pClient->m_Socket.SendWithRetry(pszBuf, dwRead, pSettings->m_dwWritableTimeout);
#endif
      }
      catch(CWSocketException* pEx)
      {
        //Report the error
        CString sError;
        sError.Format(_T("CHttpCGI::ReadFromClientStdout, Failed to send to socket, Error:%d"), pEx->m_nError);
        pClient->m_pServer->OnError(sError);

        pEx->Delete();  

        bMore = FALSE;
      }
    }
  } 

  return dwDataSent;
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -