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

📄 uploaderbase.cpp

📁 Browser-based (HTTP) file uploading is a great way to transfer arbitrary files from a client machine
💻 CPP
字号:
// UploaderBase.cpp: implementation of the CUploaderBase class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "UploaderBase.h"
#include <afxtempl.h>

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

#define UPLOAD_OK						0x0000
#define FILESIZE_INVALID				0x0001
#define EXTENSION_NOT_ALLOWED			0x0002
#define DESTINATION_PATH_INVALID		0x0003
#define UNKNOWN_ERROR					0x0004
#define UNABLE_TO_CREATE_FILE			0x0005
#define FILE_DOESNT_EXIST				0x0006



char* MyStrStr(char* string, const char* strCharSet, long lSizeString)
{
	if (!strCharSet || !strCharSet[0])
		return 0;


	int  iIndex        = 0;
	int  iBkIndex      = -1;
	long lBkSizeString = -1L;
	int  iCharSetIndex = 0;

	while (lSizeString >= 0)
	{
		if (iBkIndex == -1 && iCharSetIndex && string[iIndex] == strCharSet[0])
		{
			iBkIndex      = iIndex;
			lBkSizeString = lSizeString;
		}

		if (string[iIndex] == strCharSet[iCharSetIndex])
		{
			iCharSetIndex++;
			iIndex++;

			if (strCharSet[iCharSetIndex] == 0)
				return &(string[iIndex-iCharSetIndex]);
		}
		else
		{
			iCharSetIndex = 0;

			if (iBkIndex != -1)
			{
				iIndex        = iBkIndex;
				lSizeString   = lBkSizeString + 1;
				iBkIndex      = -1;
				lBkSizeString = -1L;
			}
			else
			{
				iIndex++;
			}
		}

		lSizeString--;
	}

	return 0;

}





BOOL StrEqual(LPCTSTR lpszString, LPCTSTR lpszSrc)
{
	if (!lpszString || !lpszString[0])
		return FALSE;

	if (!lpszSrc || !lpszSrc[0])
		return FALSE;

	int i=0;
	
	while (TRUE)
	{
		if (!lpszSrc[i])
			return TRUE;

		if (!lpszString[i])
			return FALSE;

		if (lpszSrc[i] != lpszString[i])
			return FALSE;

		i++;
	}
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CUploaderBase::CUploaderBase()
{
	m_lMaxSize       = -1L;
	m_lpBytesData    = NULL;
	m_lDataSize      = 0L;
}

CUploaderBase::~CUploaderBase()
{
	if (m_lpBytesData)
		delete [] m_lpBytesData;
}




HRESULT CUploaderBase::SetMaxFileSize(long lMaxSize)
{
	m_lMaxSize = lMaxSize;

	return S_OK;
}



HRESULT CUploaderBase::SetDestinationPath(BSTR bsDestinationPath)
{
	m_sDestPath = bsDestinationPath;

	if (!m_sDestPath.IsEmpty())
		if (m_sDestPath.Right(1) != "\\")
			m_sDestPath += "\\";

	return S_OK;
}


HRESULT CUploaderBase::StartUpload(IRequest* pIRequest)
{
	HRESULT hr = pIRequest->get_TotalBytes(&m_lDataSize);

	if (FAILED(hr))
		return hr;

	if (m_lDataSize == 0L)
	{
		return S_OK;
	}

	COleVariant  varBytesToRead;
	COleSafeArray sarrayBytes; 
	
	varBytesToRead = m_lDataSize;
	
	sarrayBytes.CreateOneDim(VT_UI1, m_lDataSize);
	
	hr = pIRequest->BinaryRead(&varBytesToRead, &sarrayBytes);

	if (FAILED(hr))
	{
		sarrayBytes.Clear();
		return hr;
	}


	LPVOID lpData;
	sarrayBytes.AccessData(&lpData);

	m_lpBytesData = new BYTE[m_lDataSize];
	memcpy(m_lpBytesData, lpData, m_lDataSize);

	
	sarrayBytes.UnaccessData();
	sarrayBytes.Clear();

	// gets the header
	TCHAR szHeaderEnd[] = { 13, 10, 13, 10, 0 };
	int iCount = 0;

	CArray<char, char> charArray;
	charArray.SetSize(0, 64);

	while (!StrEqual((LPTSTR)&m_lpBytesData[iCount], szHeaderEnd))
	{
		charArray.Add(m_lpBytesData[iCount++]);		

		// we reached the end
		if (iCount == m_lDataSize)
		{
			m_sHeader.Empty();
			break;
		}

	}

	charArray.Add(0);
	m_sHeader = charArray.GetData();

	if (!m_sHeader.IsEmpty())
	{
		TCHAR szCrLf[] = { 13, 10, 0 }; 

		// gets the delimiter from the header	
		m_sDelimiter = m_sHeader.Left(m_sHeader.Find(szCrLf));

	}

	// make this a buffer a null string
	// it ends with an 13 10
	// so replace the 13 with a 0 :)
	m_lpBytesData[m_lDataSize-2] = 0;

	TRACE("DELIMITER: %s\n", m_sDelimiter);

/*
#ifdef _DEBUG


	CStdioFile file;
	if (file.Open("output.txt", CFile::modeWrite | CFile::modeCreate))
	{
		file.Write(m_lpBytesData, m_lDataSize);
		file.Close();

		WinExec("Notepad output.txt", SW_SHOW);
	}

#endif
*/
	return S_OK;

}




HRESULT CUploaderBase::GetError(long lError, BSTR* pbsReturn)
{
	CString sError;

	switch (lError)
	{
	case UPLOAD_OK:
		sError = _T("No Error");
		break;

	case FILESIZE_INVALID:
		sError = _T("Filesize invalid");
		break;

	case EXTENSION_NOT_ALLOWED:
		sError = _T("Extension not allowed");
		break;

	case DESTINATION_PATH_INVALID:
		sError = _T("Invalid destination path");
		break;

	case UNKNOWN_ERROR:
		sError = _T("Unkown Error");
		break;

	case UNABLE_TO_CREATE_FILE:
		sError = _T("Error creating file");
		break;

	case FILE_DOESNT_EXIST:
		sError = _T("The file doesn't exists");
		break;
	}

	*pbsReturn = sError.AllocSysString();

	return S_OK;
}


HRESULT CUploaderBase::GetFormValue(CString sFieldName, BSTR* pbsReturn)
{
	BOOL bOK = FALSE;

	if (m_lpBytesData)
	{
		// looks for name="fieldName"
		CString sField("name=\"");
		sField += sFieldName;
		sField += "\"";

		LPCTSTR lpszField = MyStrStr((LPTSTR)m_lpBytesData, sField, m_lDataSize);

		if (lpszField)
		{
			// we found the start now looks for the end
			LPCTSTR lpszEndField = strstr(lpszField + sField.GetLength() + 4, m_sDelimiter);
			lpszField += (sField.GetLength() + 4);

			// figures out the size and gets the value
			int nSize = (lpszEndField - lpszField) - 2;
			LPBYTE lpFieldValue = new BYTE[nSize + 1];
			memcpy(lpFieldValue, lpszField, nSize);
			lpFieldValue[nSize] = 0;

			// pass to the returning variable
			CString sFieldValue(lpFieldValue);
			*pbsReturn = sFieldValue.AllocSysString();

			delete [] lpFieldValue;

			bOK = TRUE;

		}

	}
	
	if (!bOK)
	{
		// oh god, we didn't find it 
		*pbsReturn = SysAllocString(OLESTR(""));
	}


	return S_OK;
}



HRESULT CUploaderBase::UploadFile(CString sFieldName, long* plResult)
{
	// we don't have the destination path
	if (m_sDestPath.IsEmpty())
	{
		*plResult = DESTINATION_PATH_INVALID;
		return S_OK;
	}

	if (m_lpBytesData)
	{
		// looks for name="fieldName"
		CString sField("name=\"");
		sField += sFieldName;
		sField += "\"";

		LPTSTR lpszField = MyStrStr((LPTSTR)m_lpBytesData, sField, m_lDataSize);

		if (lpszField)
		{
			// we found it now looks for the filename
			lpszField += sField.GetLength();

			LPTSTR lpszFilenameStart = strstr(lpszField, "filename=""");
			LPTSTR lpszContentType   = strstr(lpszField, "Content-Type: ");
			
			if (!lpszFilenameStart || !lpszContentType)
			{
				*plResult = UNKNOWN_ERROR;
				return S_OK;
			}

			// this is COOL!!!
			lpszContentType[-3] = 0;
			LPTSTR lpszFilename = strrchr(lpszFilenameStart, '\\');

			if (!lpszFilename)
			{
				// restore the buffer
				lpszContentType[-3] = '"';

				*plResult = FILE_DOESNT_EXIST;
				return S_OK;

			}

			// that's the filename
			CString sFilename = lpszFilename + 1;
			lpszContentType[-3] = '"';

			// check if the file extension is ok
			CString sExtension;
			int iPosDoth = sFilename.ReverseFind('.');
			if (iPosDoth != -1)
			{
				sExtension = sFilename.Mid(iPosDoth + 1);
			}

			if (!FileExtensionAllowed(sExtension))
			{
				*plResult = EXTENSION_NOT_ALLOWED;
				return S_OK;
			}

			// try to find the beginning of the file
			TCHAR szEndContentType[] = { 13, 10, 13, 10, 0 };
			LPTSTR lpszFileStart = MyStrStr(lpszContentType, szEndContentType, m_lDataSize - (lpszContentType - (LPTSTR)m_lpBytesData));

			if (!lpszFileStart)
			{
				*plResult = UNKNOWN_ERROR;
				return S_OK;

			}

			lpszFileStart += 4; // strlen(szEndContentType)

			// checks the end of the file
			LPTSTR lpszFileEnd = MyStrStr(lpszFileStart, m_sDelimiter, m_lDataSize - (lpszFileStart - (LPTSTR)m_lpBytesData));

			if (!lpszFileEnd)
			{
				*plResult = UNKNOWN_ERROR;
				return S_OK;
			}

			lpszFileEnd -= 2;

			// now figures out the size
			int nSize = lpszFileEnd - lpszFileStart;

			if (m_lMaxSize != -1L)
			{
				if (nSize > m_lMaxSize)
				{
					*plResult = FILESIZE_INVALID;
					return S_OK;
				}
			}

			// creates the file
			CreateDirectory(m_sDestPath, NULL);

			// copies the file
			CString sPath(m_sDestPath);
			sPath += sFilename;
			CFile fileUpload;

			if (fileUpload.Open(sPath, CFile::modeWrite | CFile::modeCreate))
			{
				fileUpload.Write(lpszFileStart, nSize);
				fileUpload.Close();
				
				*plResult = UPLOAD_OK;
			}
			else
			{
				*plResult = UNABLE_TO_CREATE_FILE;		
			}
		}
		else
		{
			*plResult = FILE_DOESNT_EXIST;

		}
	}
	else
	{
		*plResult = UNKNOWN_ERROR;
	}


	return S_OK;
}


HRESULT CUploaderBase::SetAllowedExtensions(const SAFEARRAY* psarray)
{
	COleSafeArray sarray(*psarray, VT_BSTR);

	long lLowerBound;
	long lUpBound;

	sarray.GetLBound(1, &lLowerBound);
	sarray.GetUBound(1, &lUpBound);

	long lIndex[2];
	VARIANT val;

	lIndex[1] = 1;

	for (; lLowerBound <= lUpBound; lLowerBound++)
	{
		lIndex[0] = lLowerBound;

		sarray.GetElement(lIndex, &val);

		m_ExtensionList.AddTail(CString(val.bstrVal));
	}

	return S_OK;
}



HRESULT CUploaderBase::SetForbiddenExtensions(const SAFEARRAY* psarray)
{
	COleSafeArray sarray(*psarray, VT_BSTR);

	long lLowerBound;
	long lUpBound;

	sarray.GetLBound(1, &lLowerBound);
	sarray.GetUBound(1, &lUpBound);

	long lIndex[2];
	VARIANT val;

	lIndex[1] = 1;

	for (; lLowerBound <= lUpBound; lLowerBound++)
	{
		lIndex[0] = lLowerBound;

		sarray.GetElement(lIndex, &val);

		m_ForbiddenList.AddTail(CString(val.bstrVal));
	}

	return S_OK;
}

BOOL CUploaderBase::FileExtensionAllowed(LPCTSTR lpszExtension)
{
	// try to search in the forbidden extensions
	CString sElement;
	POSITION pos = m_ForbiddenList.GetHeadPosition();
		
	while (pos)
	{
		sElement = m_ExtensionList.GetNext(pos);

		if (sElement.CompareNoCase(lpszExtension) == 0)
			return FALSE;
	}
		

	// now watch the allowed extensions
	pos = m_ExtensionList.GetHeadPosition();

	if (!pos)
		return TRUE;

	while (pos)
	{
		sElement = m_ExtensionList.GetNext(pos);

		if (sElement.CompareNoCase(lpszExtension) == 0)
			return TRUE;

		if (sElement == _T("*") || sElement == _T("*.*"))
			return TRUE;
	}

	return FALSE;
}

HRESULT CUploaderBase::GetUploadFilename(CString sFieldName, BSTR *pbsReturn)
{
	if (m_lpBytesData)
	{
		// looks for name="fieldName"
		CString sField("name=\"");
		sField += sFieldName;
		sField += "\"";

		LPTSTR lpszField = MyStrStr((LPTSTR)m_lpBytesData, sField, m_lDataSize);

		if (lpszField)
		{
			// we found it now looks for the filename
			lpszField += sField.GetLength();

			LPTSTR lpszFilenameStart = strstr(lpszField, "filename=""");
			LPTSTR lpszContentType   = strstr(lpszField, "Content-Type: ");
			
			if (!lpszFilenameStart || !lpszContentType)
			{
				*pbsReturn = SysAllocString(OLESTR(""));
				return S_OK;
			}

			// this is COOL!!!
			lpszContentType[-3] = 0;
			LPTSTR lpszFilename = strrchr(lpszFilenameStart, '\\');

			if (!lpszFilename)
			{
				// restore the buffer
				lpszContentType[-3] = '"';

				*pbsReturn = SysAllocString(OLESTR(""));
				return S_OK;

			}

			// that's the filename
			CString sFilename = lpszFilename + 1;
			lpszContentType[-3] = '"';

			*pbsReturn = sFilename.AllocSysString();
			return S_OK;
		}
	}

	*pbsReturn = SysAllocString(OLESTR(""));

	return S_OK;

}

⌨️ 快捷键说明

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