コード例 #1
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
int CHttpServer::CallMemberFunc(CHttpServerContext* pCtxt,
	const AFX_PARSEMAP_ENTRY* pEntry,
	AFX_PARSEMAP_ENTRY* pParams, LPTSTR pszParams)
{
	ISAPIASSERT(NULL != pEntry);
	AFX_PISAPICMD pFunc = pEntry->pfn;
	ISAPIASSERT(NULL != pFunc);
	int nRet = callOK;

	// get default function and parameters
	BYTE bNoParams = 0;
	const BYTE* pbParams = (const BYTE*)pEntry->pszArgs;
	if (NULL == pbParams)
		pbParams = &bNoParams;
	UINT nParams = lstrlenA((LPCSTR)pbParams);

	AFX_PARSEMAP_ENTRY_PARAMS *pDefaultParams = NULL;
	if (pParams != NULL)
	{
		::EnterCriticalSection(m_pCritSec);
		if (pParams->pszFnName == NULL)
			nRet = ParseDefaultParams(pParams, nParams, pDefaultParams, pbParams);
		else
			pDefaultParams = (AFX_PARSEMAP_ENTRY_PARAMS*) pParams->pszFnName;
		::LeaveCriticalSection(m_pCritSec);
	}

	if (nRet == callOK)
	{
		// get default function and return value information
		AFX_PISAPICMD pfn = pEntry->pfn;

		// determine size of arguments and allocate stack space
		// include space for our context pointer
		UINT nSizeArgs = GetStackSize(pbParams) + sizeof(_STACK_PTR);
		ISAPIASSERT(nSizeArgs != 0);

		if (nSizeArgs < _STACK_MIN)
			nSizeArgs = _STACK_MIN;
		BYTE* pStack = (BYTE*)_alloca(nSizeArgs + _SCRATCH_SIZE);
		if (pStack == NULL)
		{
			ISAPITRACE0("Error: stack overflow in CHttpServer::CallMemberFunc()!\n");
			return callNoStackSpace;
		}

		if (pDefaultParams != NULL)
#ifndef _SHADOW_DOUBLES
			nRet = PushDefaultStackArgs(pStack, pCtxt, pbParams, pszParams,
				pDefaultParams);
#else
			nRet = PushDefaultStackArgs(pStack, pCtxt, pbParams, pszParams,
				pDefaultParams, nSizeArgs);
#endif
		else
コード例 #2
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
UINT PASCAL CHttpServer::GetStackSize(const BYTE* pbParams)
{
	// size of arguments on stack when pushed by value
	static const UINT rgnByValue[] =
	{
		sizeof(_STACK_INT),         // ITS_I2
		sizeof(_STACK_LONG),        // ITS_I4
		sizeof(_STACK_FLOAT),       // ITS_R4
		sizeof(_STACK_DOUBLE),      // ITS_R8
		sizeof(LPCTSTR),            // ITS_PSTR
		0,                          // ITS_EMPTY
	};
	// sizeof 'this' pointer
	UINT nCount = sizeof(CHttpServer*);
#ifdef _ALIGN_STACK
	nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
#endif

	// count arguments
	ISAPIASSERT(pbParams != NULL);
	while (*pbParams != 0 && *pbParams != IT_EMPTY)
	{
		// align if necessary
		// get and add appropriate byte count

#ifdef _ALIGN_DOUBLES
		// align doubles on 8 byte for some platforms
		if (*pbParams == IT_R8)
			nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
#endif

		// *pbParams must fit in the rgnByValue array
		ISAPIASSERT(*pbParams >= 1 && *pbParams <= sizeof(rgnByValue)/sizeof(UINT));
		nCount += rgnByValue[*pbParams-1];

#ifdef _ALIGN_STACK
		nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
#endif
		++pbParams;
	}
#if defined(_ALIGN_DOUBLES) && defined(_SHADOW_DOUBLES)
	// align doubles on 8 byte for some platforms
	nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
#endif
	return nCount;
}
コード例 #3
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
CHttpServer::CHttpServer(TCHAR cDelimiter /* = '&' */)
	: m_cTokenDelimiter(cDelimiter)
{
	ISAPIASSERT(pServer == NULL);   // only one server instance
	pServer = this;

	// allocate our critical section directly to avoid bogus traces
	m_pCritSec = (LPCRITICAL_SECTION)
		LocalAlloc(LPTR, sizeof(CRITICAL_SECTION));
	::InitializeCriticalSection(m_pCritSec);
}
コード例 #4
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
void CHttpServer::BuildStatusCode(LPTSTR pszResponse, DWORD dwCode)
{
	ISAPIASSERT(pszResponse != NULL);
	HTTPStatusInfo* pInfo = statusStrings;

	while (pInfo->pstrString != NULL)
	{
		if (dwCode == pInfo->dwCode)
			break;
		pInfo++;
	}

	if (pInfo->pstrString != NULL)
		wsprintf(pszResponse, _T("%d %s"), dwCode, pInfo->pstrString);
	else
	{
		ISAPIASSERT(dwCode != HTTP_STATUS_OK);
		ISAPITRACE1("Warning: Nonstandard status code %d\n", dwCode);
		BuildStatusCode(pszResponse, HTTP_STATUS_OK);
	}
}
コード例 #5
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
void CHttpServer::AddHeader(CHttpServerContext* pCtxt,
	LPCTSTR pszString) const
{
#ifdef _DEBUG
	// Can't call AddHeader() after writing directly to the stream.
	ISAPIASSERT(pCtxt->m_dwOldEndOfHeaders == pCtxt->m_pStream->GetStreamSize());
#endif

	*pCtxt << pszString;
	pCtxt->m_dwEndOfHeaders = pCtxt->m_pStream->GetStreamSize();

#ifdef _DEBUG
	pCtxt->m_dwOldEndOfHeaders = pCtxt->m_dwEndOfHeaders;
#endif
}
コード例 #6
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
#ifdef _AFXDLL
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
#endif
	BOOL bRet;

	ISAPIASSERT(pServer != NULL);
	if (pServer == NULL)
		bRet = FALSE;
	else
		bRet = pServer->GetExtensionVersion(pVer);

	return bRet;
}
コード例 #7
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
extern "C" DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
{
#ifdef _AFXDLL
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
#endif
	DWORD dwRet;

	ISAPIASSERT(pServer != NULL);
	if (pServer == NULL)
	{
		dwRet = HSE_STATUS_ERROR;
		pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
	}
	else
		dwRet = pServer->HttpExtensionProc(pECB);

	return dwRet;
}
コード例 #8
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
const AFX_PARSEMAP_ENTRY* CHttpServer::LookUp(LPCTSTR pszMethod,
	const AFX_PARSEMAP*& pMap, AFX_PARSEMAP_ENTRY*& pParams,
	AFX_PISAPICMD pCmdDefault /* = NULL */)
{
	UINT iEntry;
	LPCTSTR pszFnName;
	const AFX_PARSEMAP* pParseMap = GetParseMap();
	const AFX_PARSEMAP* pBaseMap;
	const AFX_PARSEMAP_ENTRY* pRet = NULL;

	while (pParseMap != NULL && pRet == NULL)
	{
		UINT cEntries = (*pParseMap->pfnGetNumMapEntries)();
		const AFX_PARSEMAP_ENTRY* pCurrent = pParseMap->lpEntries;

		for (iEntry = 0; iEntry < cEntries && pRet == NULL; iEntry++, pCurrent++)
		{
#ifdef _DEBUG
			// make sure not 2 parameter maps in a row

			if (pCurrent->pfn == NULL && (iEntry+1 < cEntries))
				ISAPIASSERT(pCurrent[1].pfn != NULL);
#endif

			// skip parameter maps

			if (pCurrent->pfn == NULL)
				continue;

			pszFnName = pCurrent->pszFnName;

			// if the caller wants the default command, find that--
			// if the caller wants something specific, perform a compare
			// otherwise, see if we recursed to look up the default command

			if (pCmdDefault == NULL)
			{
				if (pszMethod == NULL && pCurrent->pszArgs == NULL)
					pRet = pCurrent;
				else if (pszMethod != NULL && pCurrent->pszArgs != NULL
					&& _tcsicmp(pszFnName, pszMethod) == 0)
					pRet = pCurrent;
			}
			else if (pCurrent->pfn == pCmdDefault && pCurrent->pszArgs != NULL)
				pRet = pCurrent;

			if (pRet != NULL)
			{
				// if we need the default, recurse to find it by name
				if (pszMethod == NULL && pCmdDefault == NULL)
					return LookUp(NULL, pMap, pParams, pCurrent->pfn);

				// found it!  see if there are parameters

				if (iEntry+1 >= cEntries || pCurrent[1].pfn != NULL)
				{
					pParams = NULL;
					pMap = NULL;
				}
				else
				{
					pParams = (AFX_PARSEMAP_ENTRY*) &(pCurrent[1]);
					pMap = pParseMap;
				}
			}
		}

#ifdef _AFXDLL
		pBaseMap = (*pParseMap->pfnGetBaseMap)();
#else
		pBaseMap = pParseMap->pBaseMap;
#endif

		// catch simple mistake of BEGIN_PARSE_MAP(CMyClass, CMyClass)
		ISAPIASSERT(pBaseMap != pParseMap);
		pParseMap = pBaseMap;
	}

	// no matching entry ?
	if (pRet == NULL)
		ISAPITRACE1("Warning: no handler for command '%s'\n", pszMethod);
	return pRet;
}
コード例 #9
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
int CHttpServer::CallFunction(CHttpServerContext* pCtxt,
	LPTSTR pszQuery, LPTSTR pszCommand)
{
	int nRet;

	AFX_PARSEMAP_ENTRY* pParams;
	const AFX_PARSEMAP* pMap;
	const AFX_PARSEMAP_ENTRY* pFn;

	ISAPIASSERT(pCtxt->m_pStream == NULL);
	pCtxt->m_pStream = ConstructStream();
	if (pCtxt->m_pStream == NULL)
		nRet = callNoStream;
	else
	{
		ISAPIASSERT(pszQuery != NULL);
		if (pszQuery == NULL)
			nRet = callBadCommand;
		else
		{
			LPTSTR pszMethod;
			LPTSTR pszParams;

			// did the user specify a command via "MfcISAPICommand"?

			LPTSTR pszHiddenCommand = _tcschr(pszQuery, '=');
			if (pszHiddenCommand != NULL)
			{
				*pszHiddenCommand = '\0';

				// is it there?

				if (_tcsicmp(pszQuery, _T("MfcISAPICommand")) == 0)
				{
					// did they have a method, too?

					pszMethod = pszHiddenCommand+1;
					if (*pszMethod == '\0')
						pszParams = pszMethod;
					else
					{
						pszParams = _tcschr(pszMethod, m_cTokenDelimiter);
						if (pszParams != NULL && *pszParams != '\0')
							*pszParams++ = '\0';
					}

					// if we find it, we can call it

					pFn = LookUp(pszMethod, pMap, pParams);
					if (pFn != NULL)
						goto MakeTheCall;
				}

				// we didn't find the command, or we didn't have
				// "MfcISAPICommand", so we'll try and process things
				// normally...

				*pszHiddenCommand = '=';
			}

			if (pszCommand == NULL)
			{
				// got something via a GET method
				// is the first thing a parameter or a command?

				LPTSTR pszEquals;
				LPTSTR pszQMark;

				pszParams = _tcschr(pszQuery, m_cTokenDelimiter);
				pszQMark = _tcschr(pszQuery, '?');

				// Parameters start at the first delimiter

				if (pszParams == NULL || (pszQMark != NULL && (pszQMark < pszParams)))
				{
					pszParams = pszQMark;

					// if the command ends in question mark
					// and nothing else, ignore it
					if (pszQMark != NULL && pszQMark[1] == '\0')
					{
						*pszQMark = '\0';
						pszParams = NULL;
					}
				}

				// Does an equals sign show up before the first delimiter?

				pszEquals = _tcschr(pszQuery, '=');
				if (pszEquals == NULL || pszEquals > pszParams)
				{
					// It might be a command. If it isn't blank,
					// try and find it in the parameter map--if
					// we can't, then assume it is a parameter.

					pszMethod = pszQuery;
					if (*pszMethod != '\0')
					{
						TCHAR cTemp;
						if (pszParams != NULL)
						{
							cTemp = *pszParams;
							*pszParams++ = '\0';
						}

						pFn = LookUp(pszMethod, pMap, pParams);
						if (pFn != NULL)
							goto MakeTheCall;

						if (pszParams != NULL)
							*--pszParams = cTemp;
					}
				}

				// we can be sure it's a parameter
				if (pszQMark == NULL || pszQMark >= pszParams)
				{
					// default command, params as supplied
					pszMethod = NULL;
					pszParams = pszQuery;
				}
				else
				{
					pszMethod = pszQuery;
					*pszQMark++ = '\0';
					pszParams = pszQMark;
				}
			}
			else
			{
				// with a POST, the verb arrives seperately
				pszMethod = pszCommand;
				pszParams = pszQuery;
			}

			// is it a default verb?
			if (pszMethod != NULL && _tcslen(pszMethod) == 0)
				pszMethod = NULL;

			// is it a useless parameter?
			if (pszParams != NULL && _tcslen(pszParams) == 0)
				pszParams = NULL;

			pFn = LookUp(pszMethod, pMap, pParams);

MakeTheCall:
			if (pFn == NULL)
				nRet = callBadCommand;
			else
			{
				pCtxt->m_pStream->InitStream();
				nRet = CallMemberFunc(pCtxt, pFn, pParams, pszParams);
			}
		}
	}

	return nRet;
}
コード例 #10
0
ファイル: isapi.cpp プロジェクト: rickerliang/OpenNT
DWORD CHttpServer::HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
{
	DWORD dwRet = HSE_STATUS_SUCCESS;
	BOOL bDefault = FALSE;
	LPTSTR pszPostBuffer = NULL;
	LPTSTR pszQuery;
	LPTSTR pszCommand = NULL;
	int nMethodRet;
	LPTSTR pstrLastChar;
	DWORD cbStream = 0;
	BYTE* pbStream = NULL;
	CHttpServerContext ctxtCall(pECB);

	pECB->dwHttpStatusCode = 0;

	ISAPIASSERT(NULL != pServer);
	if (pServer == NULL)
	{
		dwRet = HSE_STATUS_ERROR;
		goto CleanUp;
	}

	// get the query

	if (_tcsicmp(pECB->lpszMethod, szGet) == 0)
	{
		pszQuery = pECB->lpszQueryString;
	}
	else if (_tcsicmp(pECB->lpszMethod, szPost) == 0)
	{
		pszCommand = pECB->lpszQueryString;
		pszPostBuffer = new TCHAR[pECB->cbAvailable + 1];
		pszQuery = GetQuery(&ctxtCall, pszPostBuffer, pECB->cbAvailable);
	}
	else
	{
		ISAPITRACE1("Error: Unrecognized method: %s\n", pECB->lpszMethod);
		dwRet = HSE_STATUS_ERROR;
		goto CleanUp;
	}

	// trim junk that some browsers put at the very end

	pstrLastChar = pszQuery + _tcslen(pszQuery) -1;
	while ((*pstrLastChar == ' ' || *pstrLastChar == '\n' ||
		   *pstrLastChar == '\r') && pstrLastChar > pszQuery)
	{
		*pstrLastChar-- = '\0';
	}

	// do something about it

	if (!pServer->InitInstance(&ctxtCall))
		dwRet = HSE_STATUS_ERROR;
	else
	{
		pECB->dwHttpStatusCode = HTTP_STATUS_OK;
		try {
			nMethodRet = pServer->CallFunction(&ctxtCall, pszQuery, pszCommand);
		}
		catch (...)
		{
			ISAPITRACE1("Error: command %s caused an unhandled exception!\n",
				pszQuery);
			nMethodRet = callNoStackSpace;
		}

		// was an error caused by trying to dispatch?

		if (nMethodRet != callOK && pECB->dwHttpStatusCode == HTTP_STATUS_OK)
		{
			dwRet = HSE_STATUS_ERROR;
			switch (nMethodRet)
			{
			case callNoStream:
				pECB->dwHttpStatusCode = HTTP_STATUS_NO_CONTENT;
				break;

			case callParamRequired:
			case callBadParamCount:
			case callBadParam:
				pECB->dwHttpStatusCode = HTTP_STATUS_BAD_REQUEST;
				break;

			case callBadCommand:
				pECB->dwHttpStatusCode = HTTP_STATUS_NOT_IMPLEMENTED;
				break;

			case callNoStackSpace:
			default:
				pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
				break;
			}
		}

		// if there was no error or the user said they handled
		// the error, prepare to spit out the generated HTML

		if (nMethodRet == callOK ||
			OnParseError(&ctxtCall, nMethodRet) == TRUE)
		{
			cbStream = ctxtCall.m_pStream->GetStreamSize();
			pbStream = ctxtCall.m_pStream->Detach();
		}
	}

CleanUp:
	// if there was an error, return an appropriate status
	TCHAR szResponse[64];
	BuildStatusCode(szResponse, pECB->dwHttpStatusCode);

	DWORD dwSize = cbStream - ctxtCall.m_dwEndOfHeaders;
	BYTE* pbContent = NULL;
	BYTE cSaved;

	if (pbStream != NULL)
	{
		cSaved = pbStream[ctxtCall.m_dwEndOfHeaders];
		pbStream[ctxtCall.m_dwEndOfHeaders] = '\0';
		pbContent = &pbStream[ctxtCall.m_dwEndOfHeaders];
	}

	if (!ctxtCall.ServerSupportFunction(
		HSE_REQ_SEND_RESPONSE_HEADER, szResponse, 0, (LPDWORD) pbStream))
	{
		pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
		dwRet = HSE_STATUS_ERROR;
#ifdef _DEBUG
		DWORD dwCause = ::GetLastError();
		ISAPITRACE1("Error: Unable to write headers: %8.8X!\n", dwCause);
#endif
	}
	else
	{
		if (pbContent != NULL)
		{
			// write a newline to separate content from headers

			*pbContent = cSaved;
			DWORD dwNewLineSize = 2;
			if (!ctxtCall.WriteClient(_T("\r\n"), &dwNewLineSize, 0) ||
				!ctxtCall.WriteClient(pbContent, &dwSize, 0))
			{
				dwRet = HSE_STATUS_ERROR;
				pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
				ISAPITRACE("Error: Unable to write content body!\n");
			}
		}
		else
			ISAPITRACE("Error: No body content!\n");
	}

	if (pbStream != NULL)
		ctxtCall.m_pStream->Free(pbStream);

	if (dwRet == HSE_STATUS_SUCCESS)
		pECB->dwHttpStatusCode = HTTP_STATUS_OK;

	if (pszPostBuffer != NULL)
		delete [] pszPostBuffer;

	return dwRet;
}
コード例 #11
0
ファイル: isapimix.cpp プロジェクト: anyue100/winscp
CHttpServerContext& CHttpServerContext::operator<<(const CByteArray& array)
{
	ISAPIASSERT(m_pStream != NULL);
	if (m_pStream != NULL) *m_pStream << array;
		return *this;
}
コード例 #12
0
ファイル: isapimix.cpp プロジェクト: anyue100/winscp
CHttpServerContext& CHttpServerContext::operator<<(const CLongBinary& blob)
{
	ISAPIASSERT(m_pStream != NULL);
	if (m_pStream != NULL) *m_pStream << blob;
		return *this;
}