php4handler.cpp

来自「mini http server,可以集成嵌入到程序中,实现简单的web功能」· C++ 代码 · 共 908 行 · 第 1/2 页

CPP
908
字号
		*lpdwSize = iToCopy;											\
		strncpy( (char *)lpvBuffer, pValue, iToCopy );					\
		return PIAPI_TRUE;												\
		};			

# define FN_STRING( name, value ) \
	static BOOL (name)( PHP4 *, PIHTTP *pPIHTTP, LPVOID lpvBuffer,		\
			LPDWORD lpdwSize )											\
		{																\
		const char *pValue = (value);									\
		if ( !pValue )													\
			{															\
			pValue = ""; 												\
			};															\
		int iToCopy = strlen( pValue ) + 1;								\
		if ( (DWORD)iToCopy>*lpdwSize || !lpvBuffer )					\
			{															\
			*lpdwSize = iToCopy;										\
			PIPlatform_setLastError( PIAPI_EINVAL );					\
			return PIAPI_FALSE;											\
			};															\
		*lpdwSize = iToCopy;											\
		strncpy( (char *)lpvBuffer, pValue, iToCopy );					\
		return PIAPI_TRUE;												\
		};			

	FN_DB_STR( fnAuthType, pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHTYPE );
	FN_DB_STR( fnContentLength, pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH );
	FN_DB_STR( fnContentType, pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE );
	FN_STRING( fnGatewayInterface, "CGI/1.1" );
	FN_DB_STR( fnPathInfo, pResponseDB, PIDBTYPE_STRING, KEY_INT_PATHINFO );
	FN_DB_STR( fnPathTranslated, pResponseDB, PIDBTYPE_STRING, KEY_INT_PATHTRANSLATED );
	FN_DB_STR( fnQueryString, pRequestDB, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING );
	FN_DB_STR( fnRemoteAddr, pConnectionDB, PIDBTYPE_STRING, KEY_INT_REMOTEADDR );
	FN_DB_STR( fnRemoteHost, pConnectionDB, PIDBTYPE_STRING, KEY_INT_REMOTEHOST );
	FN_DB_STR( fnRemoteUser, pResponseDB, PIDBTYPE_STRING, KEY_INT_REMOTEUSER );
	FN_DB_STR( fnRequestMethod, pRequestDB, PIDBTYPE_STRING, KEY_HTTP_METHOD );
	FN_DB_STR( fnScriptName, pResponseDB, PIDBTYPE_STRING, KEY_INT_SCRIPTNAME );
	FN_DB_STR( fnServerProtocol, pRequestDB, PIDBTYPE_STRING, KEY_HTTP_PROTOCOL );
	FN_DB_STR( fnCookie, pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_COOKIE );
	FN_STRING( fnServerName, HTTPUtil_getHostName(pPIHTTP) );
	FN_STRING( fnServerPort, HTTPUtil_getHostPort(pPIHTTP) );
	FN_STRING( fnServerSoftware, HTTPCore_getServerStamp() );
#undef FN_DB_STR
#undef FN_STRING

	int Parameter( const char *pVariable, const char *pValue,
		const char *pWhere )
		{
		assert( pVariable && pValue );
		PIOStrStream os;
		os << pWhere << "PHP4: ";
		if ( !PIUtil_stricmp( KEY_CONF_EXTRAHDRPREFIX, pVariable ) )
			{
				sExtraHeadersPrefix = (const char *)DeQuote( pValue );
			}
		else if ( !PIUtil_stricmp( KEY_CONF_BEHAVIOR, pVariable ) )
			{
			/* ---
			cycle through the list of available flags
			comparing them with this one
			--- */
			int i=0;
			for( ; aFlagMap[i].pName; i++ )
				{
				if ( !PIUtil_stricmp( aFlagMap[i].pName,
					DeQuote( pValue )))	{ break; };
				};
			if ( !aFlagMap[i].pName )
				{
				/* --- flag not found --- */
				os << "Unknown PHP4 mode '" << pValue << "'." << ends;
				CONFIG_ERR( Object(), os.str() );
				return 0;
				};
			iBehavior = aFlagMap[i].iFlag;
			}
		else
			{
			os << "Unknown directive '" << pVariable <<
				"'" << ends;
			CONFIG_ERR( Object(), os.str() );
			return 0;
			};
		return 1;
		};

public:
	PHP4( PIObject *pObject, int iArgc, const char *ppArgv[] )
	:	HandlerBasePHP4( pObject ),
		pTypes( PIDB_new( 0, "Types" )),
		iBehavior( PHP_MODE_STANDARD )
		{
		ReadParameters( iArgc, ppArgv );
		/* ---
		Insert DB types for 'GetServerVariable'
		--- */
#define AT( name, function ) \
		PIDB_add( pTypes, PIDBTYPE_OPAQUE, (name), (void *)function, 0 );

		AT( "ALL_HTTP", fnAllHttp );
		AT( "AUTH_TYPE", fnAuthType );
		AT( "CONTENT_LENGTH", fnContentLength );
		AT( "CONTENT_TYPE", fnContentType );
		AT( "GATEWAY_INTERFACE", fnGatewayInterface );
		AT( "PATH_INFO", fnPathInfo );
		AT( "PATH_TRANSLATED", fnPathTranslated );
		AT( "QUERY_STRING", fnQueryString );
		AT( "REMOTE_ADDR", fnRemoteAddr );
		AT( "REMOTE_HOST", fnRemoteHost );
		AT( "REMOTE_USER", fnRemoteUser );
		AT( "REQUEST_METHOD", fnRequestMethod );
		AT( "SCRIPT_NAME", fnScriptName );
		AT( "SERVER_NAME", fnServerName );
		AT( "SERVER_PORT", fnServerPort );
		AT( "SERVER_PROTOCOL", fnServerProtocol );
		AT( "SERVER_SOFTWARE", fnServerSoftware );
		AT( "HTTP_COOKIE", fnCookie );
#undef AT
		};

	virtual ~PHP4()
		{
		PIDB_delete( pTypes );
		};

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

		/* ---
		Create new PHP4 context
		--- */
		PHP4Context tContext( this, &tPIHTTP, iBehavior );
		const char *pPath = (const char *)PIDB_lookup( tPIHTTP.pResponseDB,
			PIDBTYPE_STRING, KEY_INT_PATH, 0 );

		/* ---
		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( tPIHTTP.pBuffer, &iRead );
			if ( !pBuffer || !iRead )
				{
				/* ---
				This is an error
				--- */
				HTTPCore_logError( &tPIHTTP, "PHP4: Could not read stdin \
(%ld bytes) for PHP3 script '%s'.", (long)tContext.cbTotalBytes, pPath );
				return HTTPUtil_doHTTPError( &tPIHTTP, 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( &tPIHTTP, iRead );
			memcpy( tContext.lpbData, pBuffer, iRead );
			tContext.cbAvailable = iRead;
			};

		/* ---
		Fire off PHP4 Wrapper
		--- */
		int iRet = PHP4_wrapper( &tContext );

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

		switch( iRet )
			{
			case PIAPI_COMPLETED:
				if (iBehavior == PHP_MODE_LINT )
					{
#define MSG "\
<BODY BGCOLOR=\"#FFFFFF\" BACKGROUND=\"/icons/Pi3Tile.gif\">\
<H2>PHP4 Syntax correct</H2>\
The syntax check for the called PHP4 resource succeeded.</BODY>"
						unsigned long ulLen;
						ulLen = sizeof(MSG)-1;
						char szBuf[16];
						sprintf( szBuf, "%lu", ulLen );					
						PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_RFC822,
							KEY_HTTP_CONTENTLENGTH, szBuf, 0 );
						PIIOBuffer_write( tPIHTTP.pBuffer, MSG, ulLen, PIIOBUF_NONE );
						PIIOBuffer_flush( tPIHTTP.pBuffer );
#undef MSG
					}
				break;
			case PIAPI_ERROR:
				if (iBehavior == PHP_MODE_LINT)
					{
#define MSG "\
<BODY BGCOLOR=\"#FFFFFF\" BACKGROUND=\"/icons/Pi3Tile.gif\">\
<H2>PHP4 Syntax error</H2>\
The syntax check for the called PHP4 resource failed.</BODY>"
					unsigned long ulLen = sizeof(MSG)-1;
					char szBuf[16];
					sprintf( szBuf, "%lu", ulLen );					
					PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_RFC822,
						KEY_HTTP_CONTENTLENGTH, szBuf, 0 );
					PIIOBuffer_write( tPIHTTP.pBuffer, MSG, ulLen, PIIOBUF_NONE );
					PIIOBuffer_flush( tPIHTTP.pBuffer );
#undef MSG
					}
				else
					{
					HTTPCore_logError( &tPIHTTP, "PHP4: Script wrapper with path %s \
returned with a general error.", pPath );
					};
				break;
			default:
				HTTPCore_logError( &tPIHTTP, "PHP4: Script wrapper with path %s \
returned an unknown code.", pPath );
			};

		return tContext.iRc;
		};

	BOOL GetServerVariable( PIHTTP *pPIHTTP, LPSTR lpszVariableName,
		LPVOID lpvBuffer, LPDWORD lpdwSize )
		{
		if ( !lpszVariableName || !lpdwSize )
			{
			PIPlatform_setLastError( PIAPI_EINVAL );
			return PIAPI_FALSE;
			};

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

		/* ---
		Lookup function corresponding to this environment variable
		--- */
		PMFN fnEnv = (PMFN)PIDB_lookup( pTypes, PIDBTYPE_OPAQUE, sTmp, 0 );

		/* ---
		No lookup function?
		--- */
		if ( !fnEnv )
			{
			PIPlatform_setLastError( PIAPI_EINVAL );
			return PIAPI_FALSE;
			};

		return (fnEnv)( this, pPIHTTP, lpvBuffer, lpdwSize );
		};
};

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
BOOL fnGetServerVariable( HCONN hConn, LPSTR lpszVariableName,
	LPVOID lpvBuffer, LPDWORD lpdwSize )
{
	PHP4Context *pContext = (PHP4Context *)hConn;
	int iRet = pContext->pPHP4->GetServerVariable( pContext->pPIHTTP,
		lpszVariableName, lpvBuffer, lpdwSize );
	if ( HTTPCore_debugEnabled() )
		{
		HTTPCore_logDebug( DBG_MED, "PHP4: Return code<%d>, variable<%s>, \
value<%x>, size<%d>.",
			iRet, lpszVariableName ? lpszVariableName : "",
			(void *)lpvBuffer, lpdwSize ? *lpdwSize : 0 );
		};
	return iRet;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
BOOL fnWriteClient( HCONN ConnID, LPVOID Buffer, LPDWORD	lpdwBytes,
	DWORD dwReserved )
{
	if ( !ConnID || !lpdwBytes || !Buffer )
		{
		PIPlatform_setLastError( PIAPI_EINVAL );
		return PIAPI_FALSE;
		};

	PHP4Context *pContext = (PHP4Context *)ConnID;
	int iWritten = PIIOBuffer_write( pContext->pPIHTTP->pBuffer,
		(char *)Buffer, *lpdwBytes, PIIOBUF_NONE );
	if ( iWritten==-1 )
		{
		/*
		** Socket must have been closed
		*/
		PIPlatform_setLastError( PIAPI_EINVAL );
		return PIAPI_FALSE;
		};
	*lpdwBytes = iWritten;
	return PIAPI_TRUE;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
BOOL fnReadClient( HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize )
{
	if ( !ConnID || !lpdwSize )
		{
		PIPlatform_setLastError( PIAPI_EINVAL );
		return PIAPI_FALSE;
		};

	PHP4Context *pContext = (PHP4Context *)ConnID;
	int iRet = PIIOBuffer_readToBuffer( pContext->pPIHTTP->pBuffer,
		(char *)lpvBuffer, *lpdwSize );
	if ( iRet>0 )
		{
		*lpdwSize = iRet;
		return PIAPI_TRUE;
		}
	else
		{
		return PIAPI_FALSE;
		};
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
BOOL fnSendHeaderFunction( HCONN ConnID, LPDWORD lpdwSize, LPDWORD lpdwDataType )
{
	if ( !ConnID )
		{
		PIPlatform_setLastError( PIAPI_EINVAL );
		return PIAPI_FALSE;
		};

	PHP4Context *pContext = (PHP4Context *)ConnID;
	PIHTTP *pPIHTTP = pContext->pPIHTTP;

//	switch( pContext->dwHttpStatusCode )
//		{
//		case ST_PERMANENTREDIRECT:
//		case 302:
//			PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_RFC822,
//				KEY_HTTP_LOCATION, (void *)"302", 0 );
//			pContext->dwHttpStatusCode = ST_PERMANENTREDIRECT;
//			pContext->iRc = PIAPI_COMPLETED;
//			return PIAPI_TRUE;
//		default:
			/*
			** Assume Content-Length could not be set, disable keep open
			*/
			PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE,
				KEY_INT_KEEPOPEN, 0, 0 );
			pPIHTTP->iStatus = pContext->dwHttpStatusCode;
			pContext->iRc = PIAPI_COMPLETED;

			/*
			** Send server specific headers
			*/
			if ( HTTPCore_sendGeneralHeaders( pPIHTTP ) != PIAPI_COMPLETED )
				{
				return PIAPI_FALSE;
				}

			if ( lpdwSize && *lpdwSize && lpdwDataType )
				{
				if ( PIIOBuffer_write( pPIHTTP->pBuffer, (const char *)lpdwDataType,
					*lpdwSize, PIIOBUF_NONE ) != *lpdwSize ) return PIAPI_FALSE;
				};

			return PIAPI_TRUE;
//		};
//	return PIAPI_FALSE;
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int PHP4_constructor( PIObject *pObj,
	int iArgc, const char *ppArgv[] )
{
	return HandlerBasePHP4_constructor( pObj, PI_NEW( PHP4( pObj,
		iArgc, ppArgv ) ) );
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int PHP4_destructor( PIObject *pObj, int,
	const char *[] )
{
	delete (PHP4 *)PIObject_getUserData( pObj );
	return PIAPI_COMPLETED;
}


#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name PHP4Class
		Type LogicExtension
		Library PHP4Wrapper
		OnClassLoad HandlerBasePHP4_onClassLoad
		Constructor PHP4_constructor
		CopyConstructor HandlerBasePHP4_copyConstructor
		Destructor PHP4_destructor
		Execute HandlerBasePHP4_execute
	</Class>

	<Object>
		Name PHP4
		Class PHP4Class
		ExtraHeadersPrefix "HTTP_"
#		PHPMode "Highlight"
	</Object>

/*___+++CNF_END+++___*/
#endif

⌨️ 快捷键说明

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