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

📄 httpclient.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  ASSERT(m_pServer);
  CHttpServerSettings* pSettings = m_pServer->GetSettings();
  ASSERT(pSettings);

  //Form the body of the response
  DWORD dwBodyLength = 0;
  char* pszBody = m_pServer->LoadHTML(302, dwBodyLength);

  //Form the header of the response
  CHttpResponseHeader responseHdr;
  responseHdr.AddStatusCode(302);
  SYSTEMTIME st;
  GetSystemTime(&st);
  responseHdr.AddDate(st);
  responseHdr.AddServer(pSettings->m_sServerName);
  responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
  responseHdr.AddLocation(sURL);
  if (m_bResponseKeepAlive)
    responseHdr.AddKeepAlive();
  responseHdr.AddContentLength(dwBodyLength);
  responseHdr.AddContentType(_T("text/html"));

  //Send the header and body all in one
  TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);

  //Log the information
  PostLog(302, dwBodyLength);

  return dwBodyLength;
}

DWORD CHttpClient::ReturnUnauthorizedMessage(const CString& sRealm)
{
  //Validate our parameters
  ASSERT(m_pServer);
  CHttpServerSettings* pSettings = m_pServer->GetSettings();
  ASSERT(pSettings);
  ASSERT(pSettings->m_bAllowBasicAuthentication || pSettings->m_bAllowNTLMAuthentication);

  //Form the body of the response
  DWORD dwBodyLength = 0;
  char* pszBody = m_pServer->LoadHTML(401, dwBodyLength);

  //Form the header of the response
  CHttpResponseHeader responseHdr;
  responseHdr.AddStatusCode(401);
  SYSTEMTIME st;
  GetSystemTime(&st);
  responseHdr.AddDate(st);
  responseHdr.AddServer(pSettings->m_sServerName);
  responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);

  if (pSettings->m_bAllowNTLMAuthentication)
    responseHdr.AddWWWAuthenticateNTLM(m_Request.m_sAuthenticationResponse);
  if (pSettings->m_bAllowBasicAuthentication)
    responseHdr.AddWWWAuthenticateBasic(sRealm);
  if (m_bResponseKeepAlive)
    responseHdr.AddKeepAlive();
  responseHdr.AddContentLength(dwBodyLength);
  responseHdr.AddContentType(_T("text/html"));

  //Send the header and body all in one
  TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);

  //Log the information
  PostLog(401, dwBodyLength);

  return dwBodyLength;
}

DWORD CHttpClient::ReturnFileDeletedOkMessage(const CString& /*sFile*/)
{
  //Validate our parameters
  ASSERT(m_pServer);
  CHttpServerSettings* pSettings = m_pServer->GetSettings();
  ASSERT(pSettings);

  //Form the body of the response
  DWORD dwBodyLength = 0;
  char* pszBody = m_pServer->GetFileDeletedHTML(dwBodyLength);

  //Form the header of the response
  CHttpResponseHeader responseHdr;
  responseHdr.AddStatusCode(200);
  SYSTEMTIME st;
  GetSystemTime(&st);
  responseHdr.AddDate(st);
  responseHdr.AddServer(pSettings->m_sServerName);
  responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
  if (m_bResponseKeepAlive)
    responseHdr.AddKeepAlive();
  responseHdr.AddContentLength(dwBodyLength);
  responseHdr.AddContentType(_T("text/html"));

  //Send the header and body all in one
  TransmitBuffer(m_Socket, responseHdr, (BYTE*)pszBody, dwBodyLength, pSettings->m_dwWritableTimeout);

  //Log the information
  PostLog(200, dwBodyLength);

  //Don't forget to free up the memory
  delete [] pszBody;

  return dwBodyLength;
}

void CHttpClient::TransmitBuffer(BYTE* byData, DWORD dwSize, CHttpDirectory* /*pDirectory*/, BOOL bForceExpire)
{
  //validate our settings
  ASSERT(m_pServer);
  CHttpServerSettings* pSettings = m_pServer->GetSettings();
  ASSERT(pSettings);
  ASSERT(pSettings->m_pMimeManager);

  CHttpResponseHeader responseHdr;

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

  if (m_Request.m_dwHttpVersion > MAKELONG(9, 0)) //No header sent for Http 0.9
  {
    //Get the mime type for extension we are about to return
    CString sMime = pSettings->m_pMimeManager->GetMimeType(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 (bForceExpire)
		  responseHdr.AddExpires(stCurTime);		
    if (m_bResponseKeepAlive)
      responseHdr.AddKeepAlive();
    responseHdr.AddContentLength(dwSize);
    responseHdr.AddContentType(sMime);

    //Send the header and body all in one
    TransmitBuffer(m_Socket, responseHdr, byData, dwSize, pSettings->m_dwWritableTimeout);
  }
  else
  {
    //Send back the file contents (if not a HEAD request)
    if (m_Request.m_Verb != CHttpRequest::HTTP_VERB_HEAD)
    {
      try
      {
        m_Socket.SendWithRetry(byData, dwSize, pSettings->m_dwWritableTimeout);
      }
      catch(CWSocketException* pEx)
      {
        //Report the error
        CString sError;
        sError.Format(_T("CHttpClient::TransmitBuffer, Failed to send to socket, Error:%d"), pEx->m_nError);
        m_pServer->OnError(sError);

        pEx->Delete();  
      }
    }
  }

  //Log the information
  PostLog(200, dwSize);
}
 
CHttpDirectory* CHttpClient::GetVirtualDirectory(const CString& sDirectory)
{
  //Validate our parameters
  ASSERT(m_pServer);
  CHttpServerSettings* pSettings = m_pServer->GetSettings();
  ASSERT(pSettings);

  CHttpDirectory* pDirectory = NULL;
  for (int i=0; i<pSettings->m_Directories.GetSize() && pDirectory == NULL; i++)  
  {
    CHttpDirectory* pDir = pSettings->m_Directories.GetAt(i);
    if (sDirectory.CompareNoCase(pDir->GetAlias()) == 0)
      pDirectory = pDir;
  }

  return pDirectory;  
}

int CHttpClient::HexToInt(TCHAR ch)
{
  //character is in range of 0-9 subtract ascii value of '0' to get integer
  if ((ch >= _T('0')) && (ch <= _T('9')))
    return ch - _T('0');

  //character is in range of a-z or A-Z subtract ascii value of 'a' and add 10 to get it converted into int
  if ((ch >= _T('a')) && (ch <= _T('f')))
    return ch - _T('a') + 10;
  else if ((ch >= _T('A')) && (ch <= _T('F')))
    return ch - _T('A') + 10;

  //Character is not a Hex Digit
  return -1;
}

TCHAR CHttpClient::IntToHex(int Character)
{
  //This function only expects nibbles
  ASSERT(Character >= 0 && Character <= 15);
  
  if (Character <= 9)
    return (TCHAR)(Character + _T('0'));
  else
    return (TCHAR)(Character - 10 + _T('A'));
}

CString CHttpClient::UTF8ToCString(const CString& sURL)
{
  //Get the length of the string to convert from UTF
  int nInputLen = sURL.GetLength();

  //Allocate memory to hold the Unicode string
  LPWSTR lpwszURL = new WCHAR[nInputLen * 4];

  //Convert the UTF input string to Unicode
  int nInputIndex = 0;
  int nOutputIndex = 0;
  while (nInputIndex < nInputLen)
  {
    BYTE cInputChar1 = (BYTE) sURL.GetAt(nInputIndex);
    if (cInputChar1 <= 0x7f)
    {
      //Form the current output character
      lpwszURL[nOutputIndex] = cInputChar1;

      //Move onto the next input character
      nInputIndex++;
    }
    else if (nInputIndex < nInputLen-1 && cInputChar1 <= 0xdf)
    {
      //Form the current output character
      lpwszURL[nOutputIndex] = (wchar_t) (((cInputChar1 & 0x1f) << 6) + 
                                          (sURL.GetAt(nInputIndex+1) & 0x3f));

      //Move onto the next input character
      nInputIndex += 2;
    }
    else if (nInputIndex < nInputLen-2)
    {

      //Form the current output character
      lpwszURL[nOutputIndex] = (wchar_t) (((cInputChar1 & 0x0f) << 12) + 
                                          ((sURL.GetAt(nInputIndex+1) & 0x3f) << 6) +
                                          (sURL.GetAt(nInputIndex+2) & 0x3f));

      //Move onto the next input character
      nInputIndex += 3;
    }
    else
    {
      //skip illegal sequence
      nInputIndex++;
    }

    //Move onto the next output character
    nOutputIndex++;
  }

  //Don't forget to NULL terminate
  lpwszURL[nOutputIndex] = _T('\0');

  //Form a CString version of the Unicode string
  CString sDecodedURL(lpwszURL);

  //Tidy up the heap memory we have been using
  delete [] lpwszURL;

  //Return the string
  return sDecodedURL;
}

CString CHttpClient::URLEncode(const CString& sURL)
{
  CString sEncodedURL;
  int nLength = sURL.GetLength();
  LPTSTR pszEncodedURL = sEncodedURL.GetBufferSetLength((nLength*3) + 1);
  int nOutputIndex = 0;
  for (int i=0; i<nLength; i++)
  {
    //Pull out the current character to evaluate
    BYTE CurrentChar = (BYTE) sURL.GetAt(i);

    //Should we encode the character or not? See RFC 1738 for the details.
    if ((CurrentChar >= '0' && CurrentChar <= '9') ||
        (CurrentChar >= 'a' && CurrentChar <= 'z') ||
        (CurrentChar >= 'A' && CurrentChar <= 'Z') ||
        (CurrentChar == '$') ||
        (CurrentChar == '-') ||
        (CurrentChar == '_') ||
        (CurrentChar == '.') ||
        (CurrentChar == '+') ||
        (CurrentChar == '!') ||
        (CurrentChar == '*') ||
        (CurrentChar == '\'') ||
        (CurrentChar == '(') ||
        (CurrentChar == ')') ||
        (CurrentChar == ','))
    {
      pszEncodedURL[nOutputIndex] = CurrentChar;
      ++nOutputIndex;
    }
    else 
    {
      pszEncodedURL[nOutputIndex] = _T('%');
      ++nOutputIndex;

      TCHAR nNibble = IntToHex((CurrentChar & 0xF0) >> 4);
      pszEncodedURL[nOutputIndex] = nNibble;
      ++nOutputIndex;

      nNibble = IntToHex(CurrentChar & 0x0F);  
      pszEncodedURL[nOutputIndex] = nNibble;
      ++nOutputIndex;
    }
  }
  //Don't forget to NULL terminate
  pszEncodedURL[nOutputIndex] = _T('\0');
  sEncodedURL.ReleaseBuffer();

  return sEncodedURL;
}

CString CHttpClient::URLDecode(const CString& sURL)
{
  CString sDecodedURL;
  int nLength = sURL.GetLength();
  LPTSTR pszDecodedURL = sDecodedURL.GetBufferSetLength(nLength + 1);
  int nOutputIndex = 0;
  for (int i=0; i<nLength; i++)
  {
    TCHAR c1 = sURL[i];
    if (c1 != _T('%'))
    {
      if (c1 == '+')
        pszDecodedURL[nOutputIndex] = ' ';  
      else
        pszDecodedURL[nOutputIndex] = c1;
      nOutputIndex++;
    }
    else
    {
      if (i < nLength-2)
      {
        int msb = HexToInt(sURL[i+1]);
        int lsb = HexToInt(sURL[i+2]);
        if (msb != -1 && lsb != -1)
        {
          int nChar = (msb << 4) + lsb;
          pszDecodedURL[nOutputIndex] = TCHAR(nChar);
          nOutputIndex++;
          i += 2;
        }
        else
        {
          pszDecodedURL[nOutputIndex] = c1;
          nOutputIndex++;
        }
      }
      else
      {
        pszDecodedURL[nOutputIndex] = c1;
        nOutputIndex++;
      }
    }
  }
  //Don't forget to NULL terminate
  pszDecodedURL[nOutputIndex] = _T('\0');
  sDecodedURL.ReleaseBuffer();

  return sDecodedURL;
}

BOOL CHttpClient::MapURLToLocalFilename(CString& sURL, CString& sLocalFile, CString& sPathInfo, BOOL& bDirectory, CHttpDirectory*& pDirectory, DWORD& dwMatchingURL, DWORD& dwMatchingPath)
{
  //Setup the default return value from this function
  BOOL bSuccess = FALSE;
  sLocalFile.Empty();
  sPathInfo.Empty();
  bDirectory = FALSE;
  pDirectory = NULL;
  dwMatchingURL = 0;
  dwMatchingPath = 0;

  //Convert from Unix to Windows format
  CString sClientURL(sURL);
  sClientURL.Replace(_T("/"), _T("\\"));

  //As a security precaution do not allow any URL's which contains any relative parts in it 
  //(as an example trying to request a file outside of the directories we are serving)
  //We also exclude URL's with a ":" in them as this is how NTFS streams are accessed
  if (sClientURL.Find(_T("..")) == -1 && sClientURL.Find(_T(":")) == -1)
  {
    pDirectory = NULL;
    TCHAR sDrive[_MAX_DRIVE];
    TCHAR sDir[_MAX_DIR];
    TCHAR sFname[_MAX_FNAME];
    TCHAR sExt[_MAX_EXT];
    CString sVirtualDir(sClientURL);
    sVirtualDir += _T("\\"); //Initially try a default directory
    do
    {
      _tsplitpath(sVirtualDir, sDrive, sDir, sFname, sExt);
      if (_tcslen(sDir))
      {
        pDirectory = GetVirtualDirectory(sDir);
        if (pDirectory == NULL)
        {
          sVirtualDir = sDir;
          sVirtualDir = sVirtualDir.Left(sVirtualDir.GetLength()-1);
        }
      }
    }
    while (pDirectory == NULL && _tcslen(sDir));

    if (pDirectory)
    {
	  CString strPath = pDirectory->GetDirectory();
      ASSERT(pDirectory->GetDirectory().GetLength());
      ASSERT(pDirectory->GetAlias().GetLength());

      //Ignore the alias part of the URL now that we have got the virtual directory
      CString sAlias = pDirectory->GetAlias();
      CString sRelativeFile(sClientURL);

⌨️ 快捷键说明

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