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

📄 isapi20.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				lIgnoreHeaders.Append( (DblList::type)
					PI_NEW( PIString( tTokens.GetToken( i ) ) ) );
				};
			}
		else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHEADERS, pVariable ) )
			{
			if ( !PIUtil_stricmp( VALUE_NO, pValue ) )
				{ iExtraHeaders = 0; };
			}
		else if ( !PIUtil_stricmp( KEY_CONF_VARIABLE, pVariable ) )
			{
			const char *pK;
			const char *pV;
			StringTokenizer tTokens( (const char *)DeQuote(pValue), "=" );
			if (tTokens.NumTokens() < 2)
				{
				os << "Invalid Variable '" << pValue <<
					"'" << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				}

			pK = tTokens.GetToken( 0 );
			pV = tTokens.GetToken( 1 );

			Pi3String *pError = Pi3String_new( 0 );
			Pi3Expression *pExpr = Pi3Expression_new( pV, aFunctions,
				pError );
			if ( !pExpr )
				{
				os << Pi3String_getPtr( pError ) << ends;
				Pi3String_delete( pError );
				CONFIG_ERR( Object(), os.str() ); 
				return 0;
				};
			Pi3String_delete( pError );
			PIDB_add( pTypes, PIDBTYPE_OPAQUE, pK, (void *)pExpr, 0 );
			}
		else
			{
			os << "Unknown directive '" << pVariable <<
				"'" << ends;
			CONFIG_ERR( Object(), os.str() );
			return 0;
			};

		return 1;
		};

	/* ---
	Callback function for Pi3Expression parameter %a
	--- */
	static int f_a( PIHTTP *pPIHTTP, void *pData, char *pszBuffer, int iLength )
	{
		(void)pPIHTTP;
		ISAPIContext &tData = *( (ISAPIContext *)pData );
	    assert( pszBuffer );

		PIDB *pQ = pPIHTTP->pRequestDB;											
		int i = 0;																
	
		/* --- loop over all RFC822 headers in request block --- */				
		PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );	
		if ( !pIter ) { return 0; }

		const char *pKey;													
		const char *pValue;
		for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
			{																
			pValue = (const char *)PIDBIterator_current( pIter,	&pKey );
			assert( pKey && pValue );											

			if ( !pKey || !pValue ) { /* sanity */ continue; };										

			if (tData.pISAPI20->checkIgnoreList(pKey)) continue;

			void *fnEnv = PIDB_lookup( tData.pISAPI20->pTypes, PIDBTYPE_OPAQUE, pKey, 0 );
			if ( fnEnv ) { continue; };

			int iVarLen = strlen( pKey );										
			int iVarPos = tData.pISAPI20->sExtraHeadersPrefix.Len();								
			int iValSize = strlen( pValue );									

			// keep space for ': \r\n\0'
			if ( (i+iVarPos+iVarLen+iValSize+5) < iLength )							
				{																
				memcpy( &(pszBuffer[i]), tData.pISAPI20->sExtraHeadersPrefix, iVarPos );
				i += iVarPos;
				for( int j=0; j<iVarLen; j++, i++ )							
					{																
					if ( isalnum( pKey[j] ) )										
						{ pszBuffer[i]=toupper(pKey[j]); }						
					else															
						{ pszBuffer[i]='_'; };									
					};
				pszBuffer[i++] = ':';
				pszBuffer[i++] = ' ';
				memcpy( &(pszBuffer[i]), pValue, iValSize ); i+=iValSize;		
				pszBuffer[i++] = '\r';
				pszBuffer[i++] = '\n';											
				}																
			else																
				{																
				PIDBIterator_delete( pIter );
				::SetLastError( ERROR_INSUFFICIENT_BUFFER );				
				return 1024;													
				};																
			};
		PIDBIterator_delete( pIter );
		pszBuffer[i] = 0;											
		return i;															
	};

	/* ---
	Callback function for Pi3Expression parameter %l
	--- */
	static int f_l( PIHTTP *pPIHTTP, void *pData, char *pszBuffer, int iLength )
	{
	(void)pPIHTTP;
	ISAPIContext &tData = *( (ISAPIContext *)pData );
    assert( pszBuffer );

	*((DWORD *)pszBuffer) = tData.cbTotalBytes;
	pszBuffer[sizeof(DWORD)] = 0;
	return sizeof(DWORD);
	}


public:
	ISAPI20( PIObject *pObject, int iArgc, const char *ppArgv[] )
	:	HandlerBaseISAPI( pObject ),
		pTypes( PIDB_new( 0, "Types" ) ),
		iExtraHeaders( 1 ),
		dwPlatform( initVersion() )
		{
		/* --- clear out callback functions --- */
		memset( aFunctions, 0, sizeof( FnPi3Write ) * 256 );
		aFunctions['a'] = f_a;
		aFunctions['l'] = f_l;
		ReadParameters( iArgc, ppArgv );
		};

	virtual ~ISAPI20()
		{
		PIDB_delete( pTypes );
		for( DblListIterator i( lIgnoreHeaders ); !i.BadIndex(); i++ )
			{ PI_DELETE( (PIString *)i.Current() ); };
		};

	/* ---
	The real stuff
	--- */
	int RunISAPI( PIHTTP *pPIHTTP, PFN_HTTPEXTENSIONPROC fnHttpExtensionProc,
		const char *pPath )
		{
		assert( pPIHTTP );

		/* ---
		Create new ISAPI context
		--- */
		ISAPIContext tContext( this, pPIHTTP );

		/* ---
		Read in stdin (if any)
		--- */
		if ( tContext.cbTotalBytes )
			{
			/* ---
			See how much we can read on the first pass and leave the	
			extension for call ReadClient() for the rest		
			--- */
			int iRead = 0;
			const char *pBuffer = PIIOBuffer_read( pPIHTTP->pBuffer,
				&iRead );
			if ( !pBuffer || !iRead )
				{
				/* ---
				This is an error
				--- */
				HTTPCore_logError( pPIHTTP, "ISAPI20: Could not read client \
data (%ld bytes) for ISAPI DLL '%s'.", (long)tContext.cbTotalBytes, pPath );
				return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
				};
			
			/* --- 
			Allocate a buffer and put data in it, buffer size will be
			no more that internal buffer in PIIOBuffer object.
			(usually between 4 and 16 K).
			--- */
			tContext.lpbData = (LPBYTE)PIHTTP_allocMem( pPIHTTP, iRead );
			memcpy( tContext.lpbData, pBuffer, iRead );
			tContext.cbAvailable = iRead;
			};

		/* ---
		Change impersonation level (for ASP on WinNT)
		--- */
		if (dwPlatform == VER_PLATFORM_WIN32_NT) ImpersonateSelf(SecurityImpersonation);

		/* ---
		Fire off extension
		--- */
		int iRet = (fnHttpExtensionProc)( &tContext );

		/* ---
		Check for error message
		--- */
		if ( tContext.lpszLogData && *(tContext.lpszLogData) )
			{
			HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI dll with path '%s' \
logged an error message: ________________________________________________________________________________\n%s\n________________________________________________________________________________", pPath, tContext.lpszLogData );
			};
		
		pPIHTTP->iStatus = tContext.dwHttpStatusCode;

		switch( iRet )
			{
			case HSE_STATUS_SUCCESS:
				/*
				** Assume Content-Length could not be set, disable
				** keep open
				*/
				PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE,
					KEY_INT_KEEPOPEN, 0, 0 );
				break;

			case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
				/*
				** OK
				*/
				break;

			case HSE_STATUS_PENDING:
				/*
				** We must wait until this asynchronous extension
				** has finished
				*/
				if ((tContext.isFinished() == PIAPI_ERROR) && HTTPCore_debugEnabled())
					{
					/*
					** The asynchronous extension was timed out
					*/
					HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' will be unloaded, wait for semaphore failed with error code %d",
						pPath, PIPlatform_getLastError());
					tContext.iRc = PIAPI_ERROR;
					break;
					}
				else
					{
					switch( tContext.iRc )
						{
						case 0:
						case HSE_STATUS_SUCCESS:
							/*
							** Assume Content-Length could not be set, disable
							** keep open
							*/
							PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE,
								KEY_INT_KEEPOPEN, 0, 0 );
							tContext.iRc = PIAPI_COMPLETED;
							break;
	
						case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
							/*
							** OK
							*/
							tContext.iRc = PIAPI_COMPLETED;
							break;

						case HSE_STATUS_PENDING:
							/*
							** This is a heavy error, because even an asynchronous
							** extension must be finished here
							*/
							if ( HTTPCore_debugEnabled() )
								{
								HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' returned illegal status code HSE_STATUS_PENDING.", pPath );
								};

							tContext.iRc = PIAPI_ERROR;						
							break;

						case HSE_STATUS_ERROR:
							if ( HTTPCore_debugEnabled() )
								{
								HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned HSE_STATUS_ERROR.", pPath );
								};
							tContext.iRc = PIAPI_COMPLETED;	
							break;

						default:
							if ( HTTPCore_debugEnabled() )
								{
								HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' returned HSE_STATUS_ERROR or an unknown return code of %d.",
									pPath, tContext.iRc );
								};
							tContext.iRc = PIAPI_COMPLETED;
						};
					};
				break;

			case HSE_STATUS_ERROR:
				if ( HTTPCore_debugEnabled() )
					{
					HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned HSE_STATUS_ERROR.", pPath );
					};
				break;

			default:
				if ( HTTPCore_debugEnabled() )
					{
					HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned an unknown return code of %d.", pPath, iRet );
					};
			};

		return tContext.iRc;
		};

	/* ---
	The real stuff
	--- */
	int DoISAPI( PIDLL *pDLL, const char *pPath, PIHTTP *pPIHTTP )
		{
		assert( pDLL );

		PFN_GETEXTENSIONVERSION fnGetVersion = (PFN_GETEXTENSIONVERSION)
			PIDLL_getAddress( pDLL, "GetExtensionVersion" );
		if ( !fnGetVersion )
			{
			HTTPCore_logError( pPIHTTP, "ISAPI20: Could not load function \
'GetExtensionVersion' from ISAPI DLL '%s'.", pPath );
			return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
			};

		PFN_HTTPEXTENSIONPROC fnHttpExtensionProc = (PFN_HTTPEXTENSIONPROC)
			PIDLL_getAddress( pDLL, "HttpExtensionProc" );
		if ( !fnHttpExtensionProc )
			{
			HTTPCore_logError( pPIHTTP, "ISAPI20: Could not load function \
'HttpExtensionProc' from ISAPI DLL '%s'.", pPath );
			return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
			};

		PFN_TERMINATEEXTENSION fnTerminateExtension = (PFN_TERMINATEEXTENSION)
			PIDLL_getAddress( pDLL, "TerminateExtension" );

		/* ---
		No check, fnTerminateExtension is optional
		--- */

		/* ---
		Do GetExtensionVersion
		--- */
		HSE_VERSION_INFO tInfo;
		if ( !( (fnGetVersion)( &tInfo ) ) )
			{
			HTTPCore_logError( pPIHTTP, "ISAPI20: Call to \
'GetExtensionVersion' failed for ISAPI DLL '%s'. Win32 Error code is %d.",
				pPath , ::GetLastError() );
			return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
			};

		/* ---
		OK do the DLL processing
		--- */
		int iRet = RunISAPI( pPIHTTP, fnHttpExtensionProc, pPath );
	
		/* ---
		Unload DLL
		--- */
		if ( fnTerminateExtension )
			{
			(fnTerminateExtension)(HSE_TERM_MUST_UNLOAD);
			};
		
		return iRet;
		};

	int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
		{
		if ( iPhase!=PH_HANDLE )
			{ return PIAPI_ERROR; };

		PIDB *pR = tPIHTTP.pResponseDB;
		PIDB *pQ = tPIHTTP.pRequestDB;

⌨️ 快捷键说明

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