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

📄 httpdirectory.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
Module : HttpDirectory.cpp
Purpose: Implementation for the CHttpDirectory class
Created: PJN / 21-02-2003
History: None

Copyright (c) 2003 - 2005 by PJ Naughter.  (Web: www.naughter.com, Email: pjna@naughter.com)

All rights reserved.

Copyright / Usage Details:

You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
when your product is released in binary form. You are allowed to modify the source code in any way you want 
except you cannot modify the copyright details at the top of each module. If you want to distribute source 
code with your application, then you are only allowed to distribute versions released by the author. This is 
to maintain a single distribution point for the source code. 

*/



//////////////// Includes ////////////////////////////////////////////

#include "stdafx.h"
#include "..\resource.h"
#include "HttpDirectory.h"
#include "HttpClient.h"



//////////////// Macros //////////////////////////////////////////////

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



//////////////// Implementation //////////////////////////////////////

CHttpDirectory::CHttpDirectory()
{
  m_bDirectoryListing = FALSE;
  m_bScript = FALSE;
  m_bWritable = FALSE;
}

CHttpDirectory::~CHttpDirectory()
{
}

void CHttpDirectory::SetAlias(const CString& sAlias)
{
  //Must be some alias
  ASSERT(sAlias.GetLength());

  //Ensure the virtual directory begins with a "\"
  if (sAlias.Find(_T('\\')) == -1)
  {
    if (sAlias.Find(_T('/')) == 0)
      m_sAlias = _T('\\') + sAlias.Mid(1);
    else
      m_sAlias = _T('\\') + sAlias;
  }  
  else
    m_sAlias = sAlias;

  //Ensure there is a \ on the end of the directory if 
  //length is greater than 1
  int nLen = m_sAlias.GetLength();
  if (nLen > 1 && (m_sAlias.GetAt(nLen - 1) != _T('\\')))
    m_sAlias += _T('\\');
}

void CHttpDirectory::SetDirectory(const CString& sDirectory)
{
  m_sDirectory = sDirectory;  
}

void CHttpDirectory::SetDefaultFile(const CString& sDefaultFile)
{
  m_sDefaultFile = sDefaultFile;
}

BOOL CHttpDirectory::HandleDirectoryAuthorization(CHttpClient* pClient)
{
  //Validate our parameters
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);

  //Do we need to do virtual directory authentication
  if (m_sUsername.GetLength())
  {
    //If the username and password matches up
    if (m_sUsername == pClient->m_Request.m_sUsername && m_sPassword == pClient->m_Request.m_sPassword)
      return TRUE;
    else
    {
      if (pSettings->m_bAllowBasicAuthentication || pSettings->m_bAllowNTLMAuthentication)
      {
        //Fail the request with the challenge sent back to the client
        pClient->ReturnUnauthorizedMessage(m_sRealm.GetLength() ? m_sRealm : m_sAlias);
      }
      else
      {
        //Report the error
        CString sError;
        sError.Format(_T("CHttpDirectory::HandleDirectoryAuthorization, Directory is protected but all authentication mechanisms are disabled, All requests for this directory will fail!!, %s"), m_sAlias);
        pClient->m_pServer->OnError(sError);

        pClient->ReturnErrorMessage(500); //Internal server error
      }    

      return FALSE;
    }
  }
  else
    return TRUE;
}

void CHttpDirectory::TransmitDirectory(CHttpClient* pClient)
{
  //Validate our parameters
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);

	//For correct operation of the T2A macro, see MFC Tech Note 59
  USES_CONVERSION;

  //Look for all files in the specified directory
  CFileFind finder;
  CString strWildcard(pClient->m_Request.m_sLocalFile);
  strWildcard += _T("\\*.*");
  BOOL bWorking = finder.FindFile(strWildcard);
  if (bWorking)
  {
    //Load up the template of the body
    CString sTemp;
    sTemp.LoadString(IDS_DIRECTORY_LISTING_HEADER);
    CString sBody(sTemp);

    FILETIME ftLastModified;
    ZeroMemory(&ftLastModified, sizeof(FILETIME));
    BOOL bHaveLastModified = FALSE;

    TCHAR cLastChar = pClient->m_Request.m_sURL.GetAt(pClient->m_Request.m_sURL.GetLength()-1);
    CString sDirectoryURL;
    if (cLastChar != _T('\\') && (cLastChar != _T('/')))
      sDirectoryURL = pClient->m_Request.m_sURL + _T("/");
    else
      sDirectoryURL = pClient->m_Request.m_sURL;

    //Iterate through all the files in this directory
    sBody += _T("<table>\r\n");
    while (bWorking)
    {
      bWorking = finder.FindNextFile();
      if (!finder.IsDots())
      {
        //Get the last modified time for the file
        CString sLine;
        FILETIME ft;
        finder.GetLastWriteTime(&ft);
        if (CompareFileTime(&ft, &ftLastModified) > 0)
        {
          CopyMemory(&ftLastModified, &ft, sizeof(FILETIME));
          bHaveLastModified = TRUE;
        }

        //Form the URL of the file
        CString sFilename = finder.GetFileName();
        CString sEncodedFilename = CHttpClient::URLEncode(sFilename);
        CString sURL = sDirectoryURL + sEncodedFilename;

        //Get the last modified date as a string
        TCHAR sDate[20];
        SYSTEMTIME st;
        FileTimeToSystemTime(&ft, &st);
        GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, sDate, 20);

        //Get the last modified time as a string
        TCHAR sTod[20];
        GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, sTod, 20);

        //Form all the info into a row of the table
        sLine.Format(_T("<tr>\r\n<td><a href=%s>%s</a></td><td>%dKB</td><td>%s</td><td>%s</td>\r\n</tr>"), 
                     sURL, sFilename, (finder.GetLength()+1023)/1024, sDate, sTod);
        sBody += sLine;
      }
    }
    finder.Close();
    sBody += _T("</table>\r\n");
    sTemp.LoadString(IDS_DIRECTORY_LISTING_FOOTER);
    sBody += sTemp;

    //replace any "%1"'s with m_Request.m_sURL
    sBody.Replace(_T("%1"), pClient->m_Request.m_sURL);

    //Make a local copy of the field we are going to parse
    char* pszBody = T2A((LPTSTR) (LPCTSTR) sBody);

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

    //Form the header of the response
    CHttpResponseHeader responseHdr;
    responseHdr.AddStatusCode(200);
    responseHdr.AddDate(stCurTime);
    responseHdr.AddServer(pSettings->m_sServerName);
    responseHdr.AddW3MfcAllowFields(pSettings->m_bAllowDeleteRequest);
    SYSTEMTIME stLastModified;
    if (bHaveLastModified && ::FileTimeToSystemTime(&ftLastModified, &stLastModified))
      responseHdr.AddLastModified(stLastModified);
    if (pClient->m_bResponseKeepAlive)
      responseHdr.AddKeepAlive();
    int nBodyLength = strlen(pszBody);
    responseHdr.AddContentLength(nBodyLength);
    responseHdr.AddContentType(_T("text/html"));

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

    //Log the information
    pClient->PostLog(200, nBodyLength);
  }
  else
  {
    DWORD dwSize = pClient->ReturnErrorMessage(500); //Internal server error

    //Log the information
    pClient->PostLog(500, dwSize);
  }
}

void CHttpDirectory::TransmitFile(CHttpClient* pClient)
{
  //Validate our settings
  ASSERT(pClient);
  ASSERT(pClient->m_pServer);
  CHttpServerSettings* pSettings = pClient->m_pServer->GetSettings();
  ASSERT(pSettings);
  ASSERT(pSettings->m_pMimeManager);

⌨️ 快捷键说明

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