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

📄 httpdirectory.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 2 页
字号:

  //Variable used to generate the header response
  CHttpResponseHeader responseHdr;

  //Open the file (use the FILE_FLAG_SEQUENTIAL_SCAN to improve performance)
  HANDLE hFile = ::CreateFile(pClient->m_Request.m_sLocalFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  if (hFile != INVALID_HANDLE_VALUE)
  {
    //Get the last modified time for the file / directory
    FILETIME ftFile;
    FILETIME ftRequest;
    SYSTEMTIME stFile;
    BOOL bHaveFileTime = ::GetFileTime(hFile, NULL, NULL, &ftFile);
    if (bHaveFileTime)
    {
      ::FileTimeToSystemTime(&ftFile, &stFile);

      //deliberately remove the milliseconds as they do not appear in HTTP responses.
      stFile.wMilliseconds = 0;
      SystemTimeToFileTime(&stFile, &ftFile);
    }

    //Get the current system time in UTC
    SYSTEMTIME stCurTime;
    FILETIME ftCurTime;
    ::GetSystemTime(&stCurTime);
    ::SystemTimeToFileTime(&stCurTime, &ftCurTime);

    //Ensure that the file time is not past the server time
    if (CompareFileTime(&ftFile, &ftCurTime) == 1)
    {
      CopyMemory(&ftFile, &ftCurTime, sizeof(FILETIME));
      CopyMemory(&stFile, &stCurTime, sizeof(SYSTEMTIME));
    }

    //Handle conditional GET of the file
    if (pClient->m_Request.m_Verb == CHttpRequest::HTTP_VERB_GET && 
        bHaveFileTime && pClient->m_Request.m_bIfModifiedSincePresent &&
        ::SystemTimeToFileTime(&pClient->m_Request.m_IfModifiedSince, &ftRequest) &&
        ::CompareFileTime(&ftFile, &ftRequest) != 1)
    {
      //Form the header
      responseHdr.AddStatusCode(304); //File Not modified
      responseHdr.AddDate(stCurTime);
      responseHdr.AddServer(pSettings->m_sServerName);
      responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
	    if (pSettings->m_bAutoExpire)
		    responseHdr.AddExpires(stFile);		
      if (pClient->m_bResponseKeepAlive)
        responseHdr.AddKeepAlive();
      responseHdr.AddLastModified(stFile);
      responseHdr.AddContentLength(0);
      responseHdr.AddContentType(_T("text/html"));

      //Send the header
#ifdef W3MFC_SSL_SUPPORT
      responseHdr.Send(pClient->m_Socket, pSettings->m_dwWritableTimeout, pClient->m_SSL);
#else
      responseHdr.Send(pClient->m_Socket, pSettings->m_dwWritableTimeout);
#endif

      //No body is sent for a 304 status

      //Log the information
      pClient->PostLog(304, 0);
    }
    else
    {
      //Get the length of the file
      DWORD dwFileLength = GetFileSize(hFile, NULL);

      if (pClient->m_Request.m_dwHttpVersion > MAKELONG(9, 0))
      {
        CString sMime = pSettings->m_pMimeManager->GetMimeType(pClient->m_Request);

        //Form the header of the response
        responseHdr.AddStatusCode(200);
        responseHdr.AddDate(stCurTime);
        responseHdr.AddServer(pSettings->m_sServerName);
        responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
	      if (pSettings->m_bAutoExpire)
		      responseHdr.AddExpires(stFile);		
        if (pClient->m_bResponseKeepAlive)
          responseHdr.AddKeepAlive();
        if (bHaveFileTime)
          responseHdr.AddLastModified(stFile);
        responseHdr.AddContentLength(dwFileLength);
        responseHdr.AddContentType(sMime);

        //Send back the file contents (if not a HEAD request)
        if (pClient->m_Request.m_Verb == CHttpRequest::HTTP_VERB_HEAD)
        {
          //Just send the header
#ifdef W3MFC_SSL_SUPPORT
          responseHdr.Send(pClient->m_Socket, pSettings->m_dwWritableTimeout, pClient->m_SSL);
#else
          responseHdr.Send(pClient->m_Socket, pSettings->m_dwWritableTimeout);
#endif
        }
        else
        {
          //Send the header and body all in one
          pClient->TransmitFile(pClient->m_Socket, responseHdr, hFile, dwFileLength, pSettings->m_dwWritableTimeout);
        }
      }
      else
      {
        //No header sent for Http 0.9

        //Send back the file contents (if not a HEAD request)
        if (pClient->m_Request.m_Verb != CHttpRequest::HTTP_VERB_HEAD)
        {
          try
          {
            char sBuf[4096];
            DWORD dwBytesRead = 0;
            do 
            {
              if (::ReadFile(hFile, sBuf, 4096, &dwBytesRead, NULL) && dwBytesRead)
#ifdef W3MFC_SSL_SUPPORT
                pClient->m_Socket.SendWithRetry(sBuf, dwBytesRead, pSettings->m_dwWritableTimeout, pClient->m_SSL);
#else
                pClient->m_Socket.SendWithRetry(sBuf, dwBytesRead, pSettings->m_dwWritableTimeout);
#endif
            } 
            while (dwBytesRead);
          }
          catch(CWSocketException* pEx)
          {
            //Report the error
            CString sError;
            sError.Format(_T("CHttpDirectory::TransmitFile, Failed to send to socket, Error:%d"), pEx->m_nError);
            pClient->m_pServer->OnError(sError);

            pEx->Delete();  
          }
        }
      }

      //Log the information
      pClient->PostLog(200, dwFileLength);
    }

    //Don't forget to close the file
    CloseHandle(hFile);
  }
  else
  {
    DWORD dwLastError = ::GetLastError();
    if (dwLastError == ERROR_ACCESS_DENIED && ((GetFileAttributes(pClient->m_Request.m_sLocalFile) & FILE_ATTRIBUTE_DIRECTORY) == 0) && 
        (pSettings->m_bAllowBasicAuthentication || 
         pSettings->m_bAllowNTLMAuthentication))
      pClient->ReturnUnauthorizedMessage(pClient->m_Request.m_sURL);
    else
      pClient->ReturnErrorMessage(404); //File not found
  }
}

void CHttpDirectory::HandleDirectory(CHttpClient* pClient, BOOL bDirectory)
{
  //Validate the parameters
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);

  //Do the directory level authentication
  if (!HandleDirectoryAuthorization(pClient))
    return;

  if (m_bScript)
  {
    BOOL bSentSomething = FALSE;

  #ifndef W3MFC_NO_ISAPI_SUPPORT
    CString sDLL = pSettings->m_pISAPIManager->GetISAPIExtension(pClient->m_Request);
    if (sDLL.GetLength())
    {
      bSentSomething = TRUE;
      TransmitISAPIRequest(pClient, sDLL); //Do our ISAPI implementation
    }
  #endif  
  #ifndef W3MFC_NO_CGI_SUPPORT
    if (!bSentSomething)
    {
      bSentSomething = TRUE;
      pSettings->m_pCGI->TransmitCGIResponse(pClient); //Do our CGI implementation
    }
  #endif

    if (!bSentSomething)
    {
      //Report the error
      CString sError;
      sError.Format(_T("CHttpDirectory::HandleDirectoryAuthorization, Directory is a script directory but ISAPI and / or CGI is not supported in this configuration, All requests for this directory will fail!!, %s"), m_sAlias);
      pClient->m_pServer->OnError(sError);

      pClient->ReturnErrorMessage(500); //Internal server error
    }
  }
  else if (bDirectory)
    TransmitDirectory(pClient); //Return a directory listing back to the client
  else
    TransmitFile(pClient); //Return the file back to the client
}

#ifndef W3MFC_NO_ISAPI_SUPPORT
void CHttpDirectory::TransmitISAPIRequest(CHttpClient* pClient, const CString& sDLL)
{
  //Validate the parameters
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);
  ASSERT(pSettings->m_pISAPI);

  //Reset the data counter
  pClient->m_dwDataSentViaWriteClient = 0;
  pClient->m_nHttpStatusCodeSent = 0;
  pClient->m_bResponseKeepAlive = FALSE;

  //Assume the worst
  BOOL bSuccess = FALSE;

  if (pSettings->m_bCacheISAPI)
  {
    CHttpISAPIExtension* pISAPI = pSettings->m_pISAPI->CachedLoad(sDLL);
    if (pISAPI)
      bSuccess = pSettings->m_pISAPI->CallHttpExtensionProc(pClient, *pISAPI);
  }
  else
  {
    CHttpISAPIExtension isapi;
    if (pSettings->m_pISAPI->UncachedLoad(sDLL, isapi))
      bSuccess = pSettings->m_pISAPI->CallHttpExtensionProc(pClient, isapi);
  }

  if (!bSuccess)
  {
    //Report the error
    CString sError;
    sError.Format(_T("CHttpDirectory::TransmitISAPIRequest, Failed calling the function HttpExtensionProc in the ISAPI extension %s"), sDLL);
    pClient->m_pServer->OnError(sError);

    pClient->ReturnErrorMessage(500); //Internal server error
  }
  else
    pClient->PostLog(pClient->m_nHttpStatusCodeSent, pClient->m_dwDataSentViaWriteClient);
}
#endif

⌨️ 快捷键说明

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