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

📄 isapiflt.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		/* --- callback functions --- */
		GetServerVariable = fnGetServerVariable;
		AddResponseHeaders = fnAddResponseHeaders;
		WriteClient = fnWriteClient;
		AllocMem = fnAllocMem;
		ServerSupportFunction = fnServerSupportFunction;

		/* --- proprietary data --- */
		const char *pContentLength = (const char *)PIDB_lookup(
			pPIHTTP->pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
		cbTotalBytes = pContentLength ? atol( pContentLength ) : 0;
		fIsSecurePort = (BOOL)PIDB_lookup( pPIHTTP->pConnectionDB,
			PIDBTYPE_STRING, KEY_HTTPS_KEYSIZE, 0 );
		};

	~ISAPIContext()
		{
		CloseHandle( hToken );
		}
};

/*____________________________________________________________________________*\
 *
 Class:
 Description:
\*____________________________________________________________________________*/
class ISAPIFLT : public HandlerBase
{
private:
	/* ---
	Configuration data
	--- */
	PIDB *pTypes;					/* DB for variable types */
	PIFInfo *pFInfo;				/* Store DLL file info */
	PIDLL *pDLL;					/* Store DLL handle */
	const char *pPath;              /* Store DLL path for error msgs */
	Pi3Expression *pCondition;		/* Store condition */
	HTTP_FILTER_VERSION tVer;		/* The server version of ISAPI filter */
	PFN_HTTPFILTERPROC fnHttpFilterProc; /* Pointer to the client filter function */
	const char *pfkIsapiContext;	/* Lookup key for the context pointer */
	const char *pFKPath;			/* Lookup key for the path */
	int iResult;					/* Result code for Handler

	/* ---
	Configuration data
	--- */
   	PIString sExtraHeadersPrefix;	/* Extra Header for environment values, */
									/* by default "HTTP_" */
	int iExtraHeaders;				/* whether or not to send extra headers */
	DblList lIgnoreHeaders;			/* extra headers to ignore */
	int iSystemLogon;
	FnPi3Write aFunctions[256];		/* callback functions */
	int iOptions;					/* The options of this handler */

	inline int checkIgnoreList(const char *pKey)
		{
		/* --- exclude the variables in lIgnoreHeaders --- */
		const char *pExclude;
		for( DblListIterator l( lIgnoreHeaders ); !l.BadIndex(); l++ )
			{
			pExclude = (const char *)l.Current();
			if (!PIUtil_stricmp(pKey, pExclude))
				{
				return 1;
				}
			};
		return 0;
		}
protected:
	int Parameter( const char *pVariable, const char *pValue,
		const char *pWhere )
		{
		assert( pVariable && pValue );
		PIOStrStream os;
		os.flags( os.flags() | ios::hex );
		os << pWhere << "ISAPIFLT: ";
		if ( !PIUtil_stricmp( KEY_CONF_CONDITION, pVariable ))
			{
			Pi3String *pError = Pi3String_new( 0 );
			pCondition = Pi3Expression_new( pValue, 0, pError );
			PIString sError( Pi3String_getPtr( pError ) );
			Pi3String_delete( pError );
			if ( !pCondition )
				{
				os << "Syntax error in condition: " << sError << ends;
				CONFIG_ERR( Object(), os.str() );
				Pi3Expression_delete( pCondition );
				return 0;
				};
			}
		else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHDRPREFIX, pVariable ) )
			{
				sExtraHeadersPrefix = (const char *)DeQuote( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHEADERSIGNORE, pVariable ) )
			{
			StringTokenizer tTokens( (const char *)DeQuote(pValue), " " );
			for( int i=0; i<tTokens.NumTokens(); i++)
				{
				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_SYSTEMLOGON, pVariable ) )
			{
			if ( !PIUtil_stricmp( VALUE_NO, pValue ) )
				{ iSystemLogon = 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 if ( !PIUtil_stricmp( KEY_CONF_TERMINATORS, pVariable ))
			{
			/* ---
			Split the options up by the bar ('|') character and then
			strip trailing and leading whitespace from option before
			attempting to match it.
			--- */
			StringTokenizer tTokens( pValue, "|" );
			for(int i=0; i<tTokens.NumTokens(); i++)
				{
				const char *pToken = tTokens.GetToken( i );

				/* --- skip leading whitespace --- */
				for( ; *pToken && (isspace(*pToken)); pToken++ );

				/* ---
				include only to first whitespace trailing whitespace
				--- */
				int j=0;
				for( ; pToken[j] && !(isspace(pToken[j])); j++ );
				/* ---
				j now contains the length of the first word in pToken
				--- */

				/* ---
				cycle through the list of available flags
				comparing them with this one
				--- */
				int i=0;
				for( ; aFlagMap[i].pName; i++ )
					{
					if ( !PIUtil_strncmpi( aFlagMap[i].pName, pToken, j ) )
						{ break; };
					};
				if ( !aFlagMap[i].pName )
					{
					/* --- flag not found --- */
					PIString sTmp( pToken, j );
					os << "Unknown option flag '" << sTmp << "'." << ends;
					CONFIG_ERR( Object(), os.str() );
					return 0;
					};
				iOptions |= aFlagMap[i].iFlag;
				};	/* --- loop over tokens separated by '|' --- */
			}
        else if ( !PIUtil_stricmp( KEY_CONF_FLTDLLPATH, pVariable ))
			{

			PIString sPath( pValue );
			HTTPCore_relativeToAbsolutePath(PIObject_getDB( Object() ),
				pValue,	(int *)&sPath );

			pFInfo = HTTPCore_getCachedFile( sPath ); 
			if ( !pFInfo )
				{ 
				os << "ISAPI Filter DLL '" << pValue << \
					"' does not exist or is not a regular file." << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				};

			/* ---	
			This file must exist and be a regular file 
			--- */
			if ( !PIFInfo_exists( pFInfo ) || !PIFInfo_isRegular( pFInfo ) )
				{
				os << "ISAPI Filter DLL '" << pValue << \
					"' does not exist or is not a regular file." << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				};

			/* ---	
			Try to load the ISAPI filter DLL 
			--- */
			strcpy((char *)pPath, sPath );
			pDLL = PIDLL_new( pPath );
			if ( !PIDLL_isLoaded( pDLL ) )
				{
				const char *pDesc = PIDLL_getErrorDescription( pDLL );
				os << "ISAPI Filter DLL '" << pValue << \
					"' could not be loaded, error description is " << pDesc << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				};

			/* ---
			Load the GetFilterVersion function from the DLL
			--- */
			PFN_GETFILTERVERSION fnGetVersion = (PFN_GETFILTERVERSION)
				PIDLL_getAddress( pDLL, "GetFilterVersion" );
			if ( !fnGetVersion )
				{
				os << "Could not load function 'GetFilterVersion'" << \
					  " from ISAPI DLL '" << pPath << "'" << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				};

			/* ---
			Do GetFilterVersion
			--- */
			tVer.dwServerFilterVersion = HTTP_FILTER_REVISION;
			if ( !( (fnGetVersion)( &tVer ) ) )
				{
				os << "Could not execute function 'GetFilterVersion'" << \
				" from ISAPI DLL '" << pPath << "'. Win32 Error code is " << \
				::GetLastError() << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				}
			/* ---
			Is the Version of the filter backward compatible to our server module?
			--- */
			else if ( tVer.dwServerFilterVersion < tVer.dwFilterVersion)
				{
				os << "Incompatible filter version in ISAPI DLL '" << pPath << \
					  "'. Server Filter version is " << tVer.dwServerFilterVersion << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
 				}
			/* ---
			This server module hasn't support for read/write filter notifications.
			If the filter needs this, you couldn't use the filter with Pi3Web
			--- */
			else if ( !( tVer.dwFlags & ( SF_NOTIFY_READ_RAW_DATA | SF_NOTIFY_SEND_RAW_DATA )))
				{
				/* ---
				Load the filter function
				--- */
				fnHttpFilterProc = ( PFN_HTTPFILTERPROC )PIDLL_getAddress( pDLL, "HttpFilterProc" );
				if ( !fnHttpFilterProc )
					{
					os << "Could not load 'HttpFilterProc' from ISAPI DLL '" << pPath << "'" << ends;
					CONFIG_ERR( Object(), os.str() );
					return 0;
					};
				}
			else
				{
				os << "Pi3Web doesn't support raw data read/write notification " << \
					  "requested by ISAPI DLL '" << pPath << "'" << ends;
				CONFIG_ERR( Object(), os.str() );
				return 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.pISAPIFLT->checkIgnoreList(pKey)) continue;

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

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

			// keep space for ': \r\n\0'
			if ( (i+iVarPos+iVarLen+iValSize+5) < iLength )							
				{																
				memcpy( &(pszBuffer[i]), tData.pISAPIFLT->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:
	ISAPIFLT( PIObject *pObject, int iArgc, const char *ppArgv[] )
	:	HandlerBase( pObject ),
		pTypes( PIDB_new( 0, "Types" ) ),
		pFInfo( NULL ),
		pDLL( NULL ),
		fnHttpFilterProc( NULL ),
		pPath( (const char *)PIUtil_malloc( 256 ) ),
		pCondition( NULL ),
		iOptions( 0 ),
		pfkIsapiContext( PIDB_getFastKey( KEY_INT_ISAPICONTEXT, PIDBTYPE_STRING )),
		pFKPath( PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING )),
		iResult( PIAPI_CONTINUE ),
		iExtraHeaders( 1 ),
		iSystemLogon( 1 )
		{
		/* --- clear out callback functions --- */
		memset( aFunctions, 0, sizeof( FnPi3Write ) * 256 );
		aFunctions['a'] = f_a;
		aFunctions['l'] = f_l;
		ReadParameters( iArgc, ppArgv );
		};

	virtual ~ISAPIFLT()
		{
		PIDB_delete( pTypes );
		for( DblListIterator i( lIgnoreHeaders ); !i.BadIndex(); i++ )
			{ PI_DELETE( (PIString *)i.Current() ); };
		Pi3Expression_delete( pCondition );
		if (pDLL) PIDLL_delete( pDLL );
		if (pFInfo) HTTPCore_releaseCachedFile( pFInfo );
		PIUtil_free( (void *)pPath );
		};

	/* ---
	The real filter stuff
	--- */
	int RunISAPI( PIHTTP *pPIHTTP, int iPhase, ISAPIContext *pContext )
		{
		assert( pPIHTTP && fnHttpFilterProc && pContext);
		int iFilterRet = 0;

		/* ---
		Look what we've to do
		--- */
		DWORD nType = 0;
		LPVOID pvNotification = NULL;

		/* ---
		Nothing to do: if (non)secure port notification is other
		than port characteristics of the connection
		--- */
		if (( pContext->fIsSecurePort && !( pContext->tVer.dwFlags & SF_NOTIFY_SECURE_PORT ))
		|| !( pContext->fIsSecurePort || ( pContext->tVer.dwFlags & SF_NOTIFY_NONSECURE_PORT )))
			{
			return FALSE;
			};

		/* ---
		Preprocessing headers phase mapped to SF_NOTIFY_PREPROC_HEADERS
		--- */
		if ( !nType && ( iPhase == PH_HEADERS ) && ( pContext->tVer.dwFlags & SF_NOTIFY_PREPROC_HEADERS ))
			{
			nType = SF_NOTIFY_PREPROC_HEADERS;
			HTTP_FILTER_PREPROC_HEADERS Hdrs;
			pvNotification = &Hdrs;
			Hdrs.GetHeader = fnGetHeader;
			Hdrs.SetHeader = fnSetHeader;
			Hdrs.AddHeader = fnAddHeader;

			/* ---
			Not implemented in filter version 2.1
			--- */
//			Hdrs.HttpStatus = pPIHTTP->iStatus;
			};

		/* ---
		Mapping phase mapped to SF_NOTIFY_URL_MAP
		--- */
		if ( !nType && ( iPhase == PH_MAPPING ) && ( pContext->tVer.dwFlags & SF_NOTIFY_URL_MAP ))
			{
			nType = SF_NOTIFY_URL_MAP;
			HTTP_FILTER_URL_MAP urlMap;
			pvNotification = &urlMap;

			urlMap.pszURL = (const char *)PIDB_lookup( pPIHTTP->pRequestDB,
				PIDBTYPE_STRING, KEY_HTTP_URI, 0 );

			urlMap.pszPhysicalPath = (char *)PIDB_lookup( pPIHTTP->pResponseDB,
				PIDBTYPE_STRING, pFKPath, PIDBFLAG_FASTKEY );

⌨️ 快捷键说明

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