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

📄 isapiflt.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			CHAR lpvBuffer[256];
			urlMap.cbPathBuff = sizeof(lpvBuffer);
			strncpy( lpvBuffer, urlMap.pszPhysicalPath, strlen(urlMap.pszPhysicalPath) + 1);
			urlMap.pszPhysicalPath = lpvBuffer;
		};

		/* ---
		Authentication phase mapped to SF_NOTIFY_AUTHENTICATION
		--- */
		if ( !nType && ( iPhase == PH_CHECKAUTH ) && ( pContext->tVer.dwFlags & SF_NOTIFY_AUTHENTICATION )
			// don't notify internal redirects again!
			&& ( pPIHTTP->iStatus != ST_UNAUTHORIZED ))
			{
			CHAR lpvUserBuff[SF_MAX_USERNAME] = "";
			CHAR lpvPasswBuff[SF_MAX_PASSWORD] = "";

			/*
			** Get browser authentication string
			*/
			const char *pAuthenticate = (const char *)PIDB_lookup(
				pPIHTTP->pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_AUTHORIZATION, 0 );
			if ( pAuthenticate )
				{

				/*
				** Check authentication string
				*/
				if ( !strncmp( pAuthenticate, "Basic ", 6 ) )
					{
					/*
					** Check to see if this is an acceptable base64 encoding
					*/
					const char *pBase64 = &( pAuthenticate[6] );
					CHAR auth[256];

					Base64Decode( pBase64, auth, sizeof( auth ));
					char *tok = strtok( auth, ":" );
					if ( tok != NULL )
						{
						strncpy( lpvUserBuff, tok, strlen(tok) + 1);
						PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING,
							KEY_INT_REMOTEUSER, tok, 0 );
						tok = strtok( NULL, ":" );
						if ( tok != NULL )
							{
							strncpy( lpvPasswBuff, tok, strlen(tok) + 1);
							PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING,
								KEY_INT_AUTHPASS, tok, 0 );
							};
						};
					};
				};

			nType = SF_NOTIFY_AUTHENTICATION;
			HTTP_FILTER_AUTHENT Auth;
			pvNotification = &Auth;
			Auth.cbUserBuff = sizeof(lpvUserBuff);
			Auth.pszUser = lpvUserBuff;
			Auth.cbPasswordBuff = sizeof(lpvPasswBuff);
			Auth.pszPassword = lpvPasswBuff;
		};

		/* ---
		CheckPath phase mapped to SF_NOTIFY_ACCESS_DENIED if HTTP state is 401 || 403
		--- */
		if ( !nType && ( iPhase == PH_CHECKPATH ) && (( pPIHTTP->iStatus == ST_UNAUTHORIZED ) || ( pPIHTTP->iStatus == ST_FORBIDDEN ))
			&& ( pContext->tVer.dwFlags & SF_NOTIFY_ACCESS_DENIED ))
			{
			nType = SF_NOTIFY_ACCESS_DENIED;
			HTTP_FILTER_ACCESS_DENIED Accs;
			pvNotification = &Accs;
			Accs.pszURL = (const char *)PIDB_lookup( pPIHTTP->pRequestDB,
				PIDBTYPE_STRING, KEY_HTTP_URI, 0 );

			/*
			** if Status is 403, the original path is stored in KEY_INT_OLDPATH
			*/
			if ( pPIHTTP->iStatus == ST_FORBIDDEN )
				{
				PIDB_getFastKey( KEY_INT_OLDPATH, PIDBTYPE_STRING );
				}
			else
				{
				PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING );
				};

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

			Accs.dwReason = ( pPIHTTP->iStatus == ST_UNAUTHORIZED ) ? SF_DENIED_LOGON : SF_DENIED_RESOURCE;
			};

		/* ---
		Handle phase mapped to SF_NOTIFY_SEND_RESPONSE
		--- */

		/* Not implemented in filter version 2.1
		if ( !nType && ( iPhase == PH_HANDLE ) && ( pContext->tVer.dwFlags & SF_NOTIFY_SEND_RESPONSE ))
			{
			nType = SF_NOTIFY_SEND_RESPONSE;
			HTTP_FILTER_SEND_RESPONSE Resp;
			pvNotification = &Resp;
			Resp.GetHeader = fnGetHeader;
			Resp.SetHeader = fnSetHeader;
			Resp.AddHeader = fnAddHeader;

			Resp.HttpStatus = pPIHTTP->iStatus;
			};
		*/

		/* ---
		Log phase mapped to	SF_NOTIFY_LOG
		--- */
		if ( !nType && ( iPhase == PH_LOG ) && ( pContext->tVer.dwFlags & SF_NOTIFY_LOG ))
			{
			nType = SF_NOTIFY_LOG;
			HTTP_FILTER_LOG Log;
			pvNotification = &Log;
			Log.pszClientHostName = (const char *)PIDB_lookup( pPIHTTP->pConnectionDB, PIDBTYPE_STRING, KEY_INT_REMOTEHOST, 0 );
			Log.pszClientUserName = (const char *)PIDB_lookup( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_REMOTEUSER, 0 );
			Log.pszServerName = (const char *)PIDB_lookup( pPIHTTP->pHostDB, PIDBTYPE_RFC822, KEY_INT_HOSTNAME, 0 );
			Log.pszOperation = (const char *)PIDB_lookup( pPIHTTP->pRequestDB, PIDBTYPE_STRING, KEY_HTTP_METHOD, 0 );
			Log.pszTarget = (const char *)PIDB_lookup( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_SCRIPTNAME, 0 );
			Log.pszParameters = (const char *)PIDB_lookup( pPIHTTP->pRequestDB, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING, 0 );
			Log.dwHttpStatus = pPIHTTP->iStatus;
			Log.dwWin32Status = ::GetLastError();
			/* ---
			Not implemented in filter version 2.1
			--- */
//			Log.dwBytesSent = pPIHTTP->GetIOBuffer().GetBytesSent();
//			Log.dwBytesRecvd = 0;
//			long lSeconds;	
//			long lMicroSeconds;	
//			PITimer_elapsed( pPIHTTP->pTimer, &lSeconds, &lMicroSeconds );
//			Log.msTimeForProcessing = ( 1000 * lSeconds ) + (lMicroSeconds % 1000 ));
			};

		/* ---
		Nothing to do!
		--- */
		if ( !nType ) return FALSE;

		/* ---
		Fire off filter function
		--- */
		iFilterRet = (fnHttpFilterProc)( pContext, nType, pvNotification );

		/* ---
		Post processing for handled notifications
		--- */

		/*
		** Change the physical path for phase PH_MAPPING
		*/
		if (( iPhase == PH_MAPPING ) && ( pContext->tVer.dwFlags & SF_NOTIFY_URL_MAP )
			&& ( iFilterRet != SF_STATUS_REQ_ERROR ))
			{
			const char *pFKPath = PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING );
			PIDB_replace( pPIHTTP->pResponseDB,	PIDBTYPE_STRING, pFKPath,
				((HTTP_FILTER_URL_MAP *)pvNotification)->pszPhysicalPath,
				PIDBFLAG_FASTKEY );
			};

		/*
		** Change the authentication uid/pwd in the DB
		*/
		if (( iPhase == PH_CHECKAUTH ) && ( pContext->tVer.dwFlags & SF_NOTIFY_AUTHENTICATION ))
			{
			if (( iFilterRet != SF_STATUS_REQ_ERROR ) && ( (DWORD)::GetLastError() != ERROR_ACCESS_DENIED ))
				{
				PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_REMOTEUSER,
					((HTTP_FILTER_AUTHENT *)pvNotification)->pszUser, 0 );
				PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHPASS,
					((HTTP_FILTER_AUTHENT *)pvNotification)->pszPassword, 0 );

				/*
				** If we have finished, try to logon (WindowsNT only)
				*/
				if ( iFilterRet == SF_STATUS_REQ_HANDLED_NOTIFICATION )
					{
					/*
					** parameter not set or already authenticated
					*/
					if (!iSystemLogon || pContext->hToken)
						{
						iResult = PIAPI_COMPLETED;
						return pContext->iRc;
						};

					OSVERSIONINFO VerInfo;
					VerInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
					// If this fails, something has gone wrong
					if ( !GetVersionEx( &VerInfo )) { return PIAPI_ERROR; }

					if ( VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
						{
						if (LogonUser(((HTTP_FILTER_AUTHENT *)pvNotification)->pszUser,
							NULL, // lpszDomain
							((HTTP_FILTER_AUTHENT *)pvNotification)->pszPassword,
							LOGON32_LOGON_INTERACTIVE,
							LOGON32_PROVIDER_DEFAULT, 
							&pContext->hToken ))
							{
							// If this fails, something has gone wrong
							if (!ImpersonateLoggedOnUser( pContext->hToken ))
								{
								return PIAPI_ERROR;
								}
							/*
							** authenticated and impersonated
							*/
							iResult = PIAPI_COMPLETED;
							return pContext->iRc;
  							}
						}
					}
				}
			else
				{
				if ((DWORD)::GetLastError() != ERROR_ACCESS_DENIED ) { return PIAPI_ERROR; }
				}

			/*
			** authentication challenge (Basic)
			*/
			PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHTYPE, "Basic", 0 );
			const char *pRealm = (const char *)PIDB_lookup( pPIHTTP->pResponseDB,
				PIDBTYPE_STRING, KEY_INT_AUTHENTICATIONREALM, 0 );
			if (!pRealm) pRealm="default";
			char *pAuth = (char *)PIHTTP_allocMem( pPIHTTP, sizeof( "Basic realm=\"\"" )
				+ strlen( pRealm ) + 1 );
			sprintf( pAuth, "Basic realm=\"%s\"", pRealm );
			PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_RFC822,
				KEY_HTTP_WWW_AUTHENTICATE, pAuth, 0 );

			/*
			** Redirect because of authentication failure
			*/
			iResult = HTTPUtil_doHTTPError( pPIHTTP, ST_UNAUTHORIZED );
			return pContext->iRc;
			};

		/*
		** if ServerSupportFunction added any extra header
		** requested with SF_REQ_ADD_HEADERS_ON_DENIAL
		*/
		if (( iPhase == PH_CHECKPATH ) && (( pPIHTTP->iStatus == ST_UNAUTHORIZED )
			|| ( pPIHTTP->iStatus == ST_FORBIDDEN )) && pContext->pszHeaders )
			{
			char *pszValue;
			char *pszName = strtok( (char *)pContext->pszHeaders, ":" );
			while ( pszName )
				{
				// search for space but also remove CRLF
				pszValue = strtok( NULL, "\r\n ");
				if ( !(pszName && pszValue) )
					{
					break;
					};
				PIDB_add( pPIHTTP->pResponseDB, PIDBTYPE_RFC822, pszName, pszValue, 0 );
				// search for double quota but also remove CRLF
				pszName = strtok( NULL, "\r\n:" );
				};
			};

		/* ---
		Status/Error handling
		--- */
		switch( iFilterRet )
			{
			case SF_STATUS_REQ_FINISHED:
				/*
				** Assume Content-Length could not be set, disable keep open
				*/
				PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE, KEY_INT_KEEPOPEN, 0, 0 );
				pPIHTTP->iStatus = ST_OK;
				break;

			case SF_STATUS_REQ_FINISHED_KEEP_CONN:
				/*
				** OK
				*/
				pPIHTTP->iStatus = ST_OK;
				break;

			case SF_STATUS_REQ_NEXT_NOTIFICATION:
				/*
				** OK
				*/
				break;

			case SF_STATUS_REQ_HANDLED_NOTIFICATION:
				/*
				** OK
				*/
				iResult = PIAPI_COMPLETED;
				break;

			case SF_STATUS_REQ_READ_NEXT:
				/*
				** OK
				*/
				break;

			case SF_STATUS_REQ_ERROR:
			default:
				pPIHTTP->iStatus = ST_INTERNALERROR;
				HTTPCore_logError( pPIHTTP, "ISAPIFLT: ISAPI filter \
'%s' returned SF_STATUS_REQ_ERROR or an unknown return code.", pPath );
			};

		return pContext->iRc;
		};


	/* ---
	The entry point ...
	--- */
	int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &tB/* tBuffer */ )
		{
        /*
        ** The result for this phase depends on preconfigured values
        */
		iResult = ( aPhaseMap[iPhase] & iOptions ) ? PIAPI_COMPLETED : PIAPI_CONTINUE;

        /*
        ** Only handle the request if the condition is TRUE
        */
		if ( pCondition && !Pi3Expression_write( pCondition, &tPIHTTP, 0, 0, 0 )) return iResult;

		int iFilterErr = FALSE;
		/*
		** Retrieve ISAPI context ...
		*/
		ISAPIContext *pContext = (ISAPIContext *)PIDB_lookup( tPIHTTP.pConnectionDB,
			PIDBTYPE_OPAQUE, pfkIsapiContext, PIDBFLAG_FASTKEY );
		/*
		** ... or create a new one
		*/
		if ( !pContext )
			{
			pContext = new ISAPIContext( this, &tPIHTTP, tVer );
			PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, pfkIsapiContext,
				(void *)pContext, PIDBFLAG_FASTKEY );
			};

        /*
        ** Only handle the request if the current status is a non-error status
        */
        if (( !tPIHTTP.iStatus ) || ( tPIHTTP.iStatus == ST_OK )
		/* --- Exception: 401, 403 are notified by ISAPI filters! --- */
		|| ( tPIHTTP.iStatus == ST_UNAUTHORIZED ) || ( tPIHTTP.iStatus == ST_FORBIDDEN ))
            {
			/* --- OK, do the filter DLL processing --- */
			iFilterErr = RunISAPI( &tPIHTTP, iPhase, pContext );
			};

		/*
		** pContext - explicite destruction
		*/
		if (( iPhase == PH_DESTROY ) && pContext )
			{
			delete pContext;
			pContext = NULL;
			PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, pfkIsapiContext,
				(void *)pContext, PIDBFLAG_FASTKEY);
			};

		/*
		** an error is occured
		*/
		if ( iFilterErr )
			{
			HTTPCore_logError( &tPIHTTP, "ISAPIFLT: Call to 'HttpFilterProc' \
failed for ISAPI DLL '%s'. Win32 Error code is %d.", pPath , ::GetLastError() );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			}
		else return iResult;
		};


	/* ---
	Used by the callback function with the same name
	--- */
	BOOL GetServerVariable( PIHTTP *pPIHTTP, LPSTR lpszVariableName,
		LPVOID lpvBuffer, LPDWORD lpdwSize, ISAPIContext *pContext )
		{
		if ( !lpszVariableName || !lpdwSize )
			{
			::SetLastError( ERROR_INVALID_PARAMETER );
			return FALSE;
			};

		/* ---
		Convert variable to upper case
		--- */
		PIString sTmp( lpszVariableName );
		sTmp.ConvertToUpperCase();

		Pi3Expression *pExpr = (Pi3Expression *)PIDB_lookup(pTypes, PIDBTYPE_OPAQUE,
			(const char *)sTmp, 0);

		if (pExpr)
			{
			UINT iWritten = Pi3Expression_write( pExpr, pPIHTTP, pContext, (char *)lpvBuffer,
				*lpdwSize );
			if ( iWritten==-1 )
				{
				*lpdwSize = 0;
				::SetLastError( ERROR_INVALID_INDEX );
				return 0;
				}

			/*
			** Skip empty variable fields, this allows an environment
			** variable to be added conditionally
			*/
			if ( iWritten>=0 )
				{
				if ( iWritten>=*lpdwSize )
					{
					*lpdwSize = iWritten;
					::SetLastError( ERROR_INSUFFICIENT_BUFFER );
					return 0;
					};
				((char *)lpvBuffer)[iWritten] = '\0';	
				*lpdwSize = iWritten;
				return 1;
				};
			}

		/* --- no variable found, try to find an extra header --- */
		if ( iExtraHeaders ) 
			{
			PIDB *pQ = pPIHTTP->pRequestDB;											
	
			/* --- 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 (checkIgnoreList(pKey)) continue;

				PIString sTest(sExtraHeadersPrefix);
				sTest.Concatenate(pKey);
				char *pBuf = (char *)(const char *)sTest;
				for( int i=0; i<sTest.Len(); i++ )							
					{																
					if ( isalnum( pBuf[i] ) )										
						{ pBuf[i]=toupper(pBuf[i]); }						
					else															
						{ pBuf[i]='_'; };		
					}

				if (!PIUtil_stricmp((const char *)sTest, (const char *)sTmp))
					{
					strncpy((char *)lpvBuffer, pValue, strlen(pValue));
					*lpdwSize = strlen(pValue);

⌨️ 快捷键说明

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