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

📄 httpcore.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	/* --- assume time(), gmtime() and strftime() are not thread safe --- */
	PIPlatform_beforeUnsafeBlock();
	time( &tT ); 

	/* ---
	Don't know of a standard for error logfile time, so the following
	time format will be used

		"Thu Mar 27 19:28:21 1997 GMT"

	--- */
	strftime( szBuf, BUF_SIZE, "[%a %b %d %H:%M:%S %Y GMT] ", gmtime( &tT ) );
	PIPlatform_afterUnsafeBlock();

#if TEMP
	/* ---
	Generating an error message is comparatively infrequent, so can do
	things a little less efficientlty
	--- */
    enum { INCREMENT = 8192 };
    int iMaxLen = INCREMENT;
	int iLen = strlen( szBuf );
again:
	char *pBuffer = PI_NEW( char[iMaxLen+1] );	/* unfortunately we don't 
									        	have snprintf, well we
                                                do under MSVC ... */
    if ( iMaxLen < iLen )
        {
        iMaxLen += ( iLen - iMaxLen ) + INCREMENT;
        delete [] pBuffer;
        goto again;
        };
	strcpy( pBuffer, szBuf );
    iMaxLen -= iLen;

	/* --- print message --- */
	va_start( tvList, pFormat );
    if ( iMaxLen > 0 )
        {
#if WIN32
        if ( _vsnprintf( &(pBuffer[iLen]), iMaxLen, pFormat, tvList )==-1 )
#else
        if ( vsprintf( &(pBuffer[iLen]), pFormat, tvList )==-1 )
#endif
            {
            /*
            ** Not enough space for data 
            */
            iMaxLen += INCREMENT;
            iMaxLen *= 2;           /* make memory increments go up
                                    binary exponentially
                                    */
            delete [] pBuffer;
            goto again;
            };
        };
	va_end( tvList );

	iLen += strlen( &(pBuffer[iLen]) );
#if WIN32	
	pBuffer[iLen++] = '\r';
#endif
	pBuffer[iLen++] = '\n';
	pBuffer[iLen] = '\0';
	PIFile_writeAtomic( tError, iLen, pBuffer );

	/* ---
	Add the message to the response DB
	--- */
	if ( pPIHTTP && pPIHTTP->pResponseDB )
		{
		PIDB_add( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_ERRORMESSAGE,
			(void *)pBuffer, 0 );
		};

	PI_DELETE( [] pBuffer );

#else
	/* --- print time stamp --- */
	fputs( szBuf, pError );

	/* --- print message --- */
	va_start( tvList, pFormat );
	vfprintf( pError, pFormat, tvList );
	va_end( tvList );

	/* --- print carriage return and flush message --- */
	fputc( '\n', pError );
	fflush( pError );
#endif

	return 0;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Returns 0 on success.
\*____________________________________________________________________________*/
int HTTPCore_logDebug( int /* iLevel */, const char *pFormat, ... )
{
	assert( pSG );
	FILE *pDebug = pSG->pDebugLog;
	if ( !pDebug )
		{ return 0; /* --- debugging not switched on --- */ };

	va_list tvList;
	
	/* --- print message --- */
	va_start( tvList, pFormat );
	vfprintf( pDebug, pFormat, tvList );
	va_end( tvList );

	/* --- print carriage return and flush message --- */
	fputc( '\n', pDebug );
	fflush( pDebug );

	return 0;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_executePhase(
	PIHTTP *pPIHTTP,
	PIObject *(* nextFn)(void *),
	void *pArg )
{
	PIObject *pHandler = 0;
	pHandler = (nextFn)( pArg );
	int iResult = PIAPI_CONTINUE;
	while( pHandler )
		{
		/* --- buffer for debug logging --- */
		enum { BUF_SIZE=1023 };
		char szBuf[BUF_SIZE+1];

		/* --- set debug information --- */
		pPIHTTP->pHandlerName = PIObject_getName( pHandler );
		pPIHTTP->iLastResultCode = PIAPI_EINVAL;

		/* --- delta information for profiling --- */
		long lSeconds = 0;
		long lMicroSeconds = 0;

		/* --- log before handler debug --- */
		if ( pSG->pDebugLog )
			{
			if ( pSG->pBeforeHandler )
				{
				int iLen = Pi3Expression_write( pSG->pBeforeHandler, pPIHTTP, 0,
					szBuf, BUF_SIZE );
				if ( iLen!=-1 )
					{
					if ( iLen>BUF_SIZE ) { iLen=BUF_SIZE; };
					szBuf[iLen] = '\0';	
					HTTPCore_logDebug( DBG_LOW, "%s", szBuf );
					};
				};
			pPIHTTP->iDepth++;
			PITimer_elapsed( pPIHTTP->pTimer, &lSeconds, &lMicroSeconds );
			};

		iResult = PILogic_execute( pHandler, 1, (const char **)&pPIHTTP );

		/* --- log after handler debug --- */
		if ( pSG->pDebugLog )
			{
 			if ( pSG->pAfterHandler )
				{
				/* --- get handler time delta for profiling --- */
				long lSeconds2 = 0;
				long lMicroSeconds2 = 0;
				PITimer_elapsed( pPIHTTP->pTimer, &lSeconds2, &lMicroSeconds2 );
				pPIHTTP->iDelta = (int)( ( lMicroSeconds2 - lMicroSeconds ) +
					( ( lSeconds2 - lSeconds ) * 1000000L ) );
				};

			pPIHTTP->iDepth--;
			if ( pSG->pAfterHandler )
				{
				/* --- set debug information name --- */
				pPIHTTP->pHandlerName = PIObject_getName( pHandler );
				pPIHTTP->iLastResultCode = iResult;

				int iLen = Pi3Expression_write( pSG->pAfterHandler, pPIHTTP, 0,
					szBuf, BUF_SIZE );
				if ( iLen!=-1 )
					{
					if ( iLen>BUF_SIZE ) { iLen=BUF_SIZE; };
					szBuf[iLen] = '\0';	
					HTTPCore_logDebug( DBG_LOW, "%s", szBuf );
					};
				};
			};

		switch( iResult )
			{
			case PIAPI_CONTINUE:
				goto done_handler;

			case PIAPI_COMPLETED:
			case PIAPI_ERROR:
			case PIAPI_ABORT:
			case INT_REDIRECT:
				goto done_phase;

			default:
				assert( 0 );
				goto done_phase;
			};	/* end switch */
done_handler:;
		pHandler = (nextFn)( pArg );
		};	/* end while */
done_phase:

	return iResult;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Determine the error code if any for PIAPI_CONTINUE returned
	from a handler phase (no action taken). HTTP error status code
	is returned. A return code of 0 indicates no error.
\*____________________________________________________________________________*/
int Internal_ContinueStatus( int iPhase )
{
	switch( iPhase )
		{
		case PH_INVALID:		return ST_INTERNALERROR;
		case PH_INIT:			return ST_INTERNALERROR;
		case PH_HEADERS:		return ST_INTERNALERROR;
		case PH_HOSTMAP:		return 0;
		case PH_MAPPING:		return ST_INTERNALERROR;
		case PH_CHECKPATH:		return ST_NOTFOUND;
		case PH_CHECKAUTH:		return ST_UNAUTHORIZED;
		case PH_CHECKACCESS:	return ST_FORBIDDEN;
		case PH_CHECKTYPE:		return ST_INTERNALERROR;
		case PH_HANDLE:			return ST_INTERNALERROR;
		case PH_LOG:			return 0;
		case PH_DESTROY:		return 0;
		default:
			return ST_INTERNALERROR;
		};
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int Internal_SetPath( PIHTTP &tPIHTTP )
{
	int iRet = PIAPI_COMPLETED;

	/* --- 
	Get the URI path
	Use HTTPCore_contractPath() to remove '..' and other evil elements
	Set the 'Path' response variable to the contracted path or
	Set the status to 403 if the path attempted to read up into
	the directory root.
	--- */
	const char *pURI = (const char *)PIDB_lookup( tPIHTTP.GetRequestDB(), 
				PIDBTYPE_STRING, pFKURI, PIDBFLAG_FASTKEY );
	if ( pURI ) 
		{
		char *pTmp = new char[strlen(pURI)+1];
		strcpy( pTmp, pURI ); 

		/* ---
		Then contract it to avoid side effects of '.' and '..' in
		the URL
		--- */
		if ( HTTPUtil_contractPath( pTmp )>0 )
			{
			/* --- force a 403 (forbidden) error --- */
			tPIHTTP.iStatus = ST_FORBIDDEN;
			iRet = INT_REDIRECT;
			}
		else
			{
			PIDB_add( tPIHTTP.GetResponseDB(), PIDBTYPE_STRING,
				pFKPath, pTmp, PIDBFLAG_FASTKEY );
			};

		delete [] pTmp;
		}
	else
		{
		HTTPCore_logError( &tPIHTTP, "Could not set request path\n" );
		iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
		};

	return iRet;
}

/*____________________________________________________________________________*\
*
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
static PIObject *Internal_ExecutePhaseCallback( void *pArg )
{
	DblListIterator *pIter = (DblListIterator *)pArg;
	assert( pIter );
	if ( pIter->BadIndex() )
		{ return 0; };
	PIObject *pObject = (PIObject *)pIter->Current();
	assert( pObject );
	(*pIter)++;
	return pObject;
}

/*____________________________________________________________________________*\
*
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
static int Internal_ExecutePhase( PIHTTP *pPIHTTP, DblList &lHandlers )
{
	DblListIterator i( lHandlers );
	return HTTPCore_executePhase( pPIHTTP, Internal_ExecutePhaseCallback, &i);
}

/*____________________________________________________________________________*\
*
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_dispatch(
	PIHTTP *pPIHTTP,
	int iStartPhase,
	int iEndPhase )
{
	assert( pPIHTTP );
	PIDB *pC = pPIHTTP->GetConnectionDB();
/*	PIDB *pR = pPIHTTP->GetResponseDB(); */
	PIIOBuffer &tB = pPIHTTP->GetIOBuffer();
	int iRet = PIAPI_COMPLETED;

	int iNumRedirects = 0;
again:
	for( int iPhase = iStartPhase; iPhase<=iEndPhase; iPhase++ )
		{
		/* --- cast away const --- */
		*( (int *)&(pPIHTTP->ciPhase) ) = iPhase;

		/* ---
		If this is the log phase, then flush all output and set bytes sent
		--- */
		if ( iPhase == PH_LOG )
			{
			tB.Flush();
			PIDB_replace( pC, PIDBTYPE_OPAQUE, pFKBytesSent,
				(void *)tB.GetBytesSent(), PIDBFLAG_FASTKEY );
			};

		/* --- execute phase --- */
		iRet = Internal_ExecutePhase( pPIHTTP, pSG->lHandlers );

		/* ---
		Determine action based on return code, iRet, and status, iStatus.
		--- */
		switch( iRet )
			{
			case PIAPI_CONTINUE:
				{
				int iStatus = Internal_ContinueStatus( iPhase );
				if ( !iStatus ) { break; };
				pPIHTTP->iStatus = iStatus;

				/* --- set an error message --- */
				HTTPCore_logError( pPIHTTP, "HTTPCore_dispatch: No processing \
occurred for phase '%s', response status set to '%d'.", \
					HTTPUtil_phaseNumberToName( iPhase ), iStatus );
				};
				/* --- fall through to redirect --- */

			case INT_REDIRECT:
				if ( iPhase<=PH_HANDLE && iNumRedirects<=MAX_REDIRECTS )
					{
					iStartPhase = PH_MAPPING;
					iNumRedirects++;
					goto again;
					};
				return PIAPI_ERROR;

			case PIAPI_COMPLETED:
				if ( iPhase==PH_HEADERS && !pPIHTTP->iStatus &&
					Internal_SetPath( *pPIHTTP )==INT_REDIRECT )
					{
					if ( iNumRedirects<=MAX_REDIRECTS )
						{	
						iStartPhase = PH_MAPPING;
						iNumRedirects++;
						goto again;
						}
					else
						{
						return PIAPI_ERROR;
						};
					};
				break;

			/* --- error conditions --- */
			case PIAPI_ERROR:
			case PIAPI_ABORT:
				return iRet;

			default:
				assert( 0 );
				return PIAPI_ABORT;

			};	/* --- end of switch on phase return code --- */
		};	/* --- end of this phase --- */

	/* --- if the last handler left 'CONTINUE', change to 'COMPLETED' --- */
	if ( iRet==PIAPI_CONTINUE )
		{ iRet = PIAPI_COMPLETED; };

	return iRet;
}

/*____________________________________________________________________________*\
*
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_debugEnabled()
{
	return ( pSG->pDebugLog ) ? 1 : 0 ;
}

⌨️ 快捷键说明

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