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

📄 sendssi.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "AUTH_TYPE", 
			Pi3Expression_new( "$x", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "CONTENT_LENGTH", 
			Pi3Expression_new( "$Y", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "CONTENT_TYPE", 
			Pi3Expression_new( "$C", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DOCUMENT_NAME", 
			Pi3Expression_new( "$f", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DOCUMENT_URI", 
			Pi3Expression_new( "$U", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS", 
			Pi3Expression_new( "$g", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_KEYSIZE", 
			Pi3Expression_new( "$K", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_SECRETKEYSIZE", 
			Pi3Expression_new( "$G", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_CIPHERNAME", 
			Pi3Expression_new( "$e", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "QUERY_STRING", 
			Pi3Expression_new( "$q", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_ADMIN", 
			Pi3Expression_new( "$a", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_SOFTWARE", 
			Pi3Expression_new( "$S", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_NAME", 
			Pi3Expression_new( "$v", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_PORT", 
			Pi3Expression_new( "$p", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_PROTOCOL", 
			Pi3Expression_new( "&dblookup(request,string,Protocol)",
			0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REQUEST_METHOD", 
			Pi3Expression_new( "$m", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_ADDR", 
			Pi3Expression_new( "$A", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_HOST", 
			Pi3Expression_new( "$h", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_IDENT", 
			Pi3Expression_new( "$i", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_USER", 
			Pi3Expression_new( "$u", 0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTP_ACCEPT", 
			Pi3Expression_new( "&dblookup(request,rfc822,Accept)",
			0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTP_USER_AGENT", 
			Pi3Expression_new( "&dblookup(request,rfc822,User-Agent)",
			0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REFERER", 
			Pi3Expression_new( "&dblookup(request,rfc822,Referer)",
			0, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DATE_GMT", 
			Pi3Expression_new( "%a", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DATE_LOCAL", 
			Pi3Expression_new( "%b", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "LAST_MODIFIED", 
			Pi3Expression_new( "%c", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "PATH_INFO", 
			Pi3Expression_new( "$I", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "PATH_TRANSLATED", 
			Pi3Expression_new( "$Z", aFunctions, pDummy ), 0 );
		PIDB_add( pVariables, PIDBTYPE_OPAQUE, "ERROR_MESSAGES", 
			Pi3Expression_new( "&dblookup(request,string,ErrorMessage,,,&_())",
			0, pDummy ), 0 );
		Pi3String_delete( pDummy );
		};

	~SendSSI()
		{
		/* --- delete functions DB --- */
		PIDB_delete( pFunctions );

		/* --- delete variables from variables DB --- */
		PIDBIterator *pIter = PIDB_getIterator( pVariables, PIDBTYPE_OPAQUE,
			0, 0 );
		if ( pIter )
			{
			for( ; PIDBIterator_atValidElement( pIter );
				PIDBIterator_next( pIter ) )
				{
				Pi3Expression_delete(
					(Pi3Expression *)PIDBIterator_current( pIter, 0 ) );
				};
			PIDBIterator_delete( pIter );
			};

		/* --- delete variables DB --- */
		PIDB_delete( pVariables );

		Pi3Expression_delete( pHeaderPattern );
		Pi3Expression_delete( pFooterPattern );
		Pi3Expression_delete( pExecFileFixup );
		};

	/* ---
	Process a single SSI directive
	Return 0 on error, 1 on success.
	--- */
	int ProcessSSIDirective( PIHTTP &tPIHTTP, const char *pDirective, 
		int iDirectiveLen, SSIParam &tParam )
		{
		/* --- get first word (command) in directive --- */
		int i;
		for( i=0; i<iDirectiveLen && !(isspace(pDirective[i])); i++);

		/* --- portions of directive --- */
		const char *pCommand = pDirective;
		int iCommandLen = i;
		const char *pVariable = 0;
		int iVariableLen = 0;
		const char *pValue = 0;
		int iValueLen = 0;
	
		if ( i<iDirectiveLen )
			{
			/* --- get variable --- */
			for( ; i<iDirectiveLen && (isspace(pDirective[i])); i++);
			pDirective = &( pDirective[i] ); iDirectiveLen -= i; i = 0;
			pVariable = pDirective;
			for( ; i<iDirectiveLen && !(isspace(pDirective[i])) &&
				pDirective[i]!='='; i++);
			iVariableLen = i;

			/* --- get value --- */
			for( ; i<iDirectiveLen && ( (isspace(pDirective[i])) ||
				( pDirective[i]=='=' ) ); i++);
			int iQuoted = 0;
			if ( pDirective[i]=='"' ) { iQuoted = 1; i++; };
			pDirective = &( pDirective[i] ); iDirectiveLen -= i; i = 0;
			for( ; i<iDirectiveLen && ( !(isspace(pDirective[i])) || iQuoted )
				; i++)
				{
				if ( pDirective[i]=='"' && iQuoted )
					{ break; };
				};
			pValue = pDirective;
			iValueLen = i;
			};

		/* --- get directive function and execute it --- */
		PIString sCommand( pCommand, iCommandLen );
		sCommand.ConvertToUpperCase();
		SSIFunc tFn = (SSIFunc)PIDB_lookup( pFunctions, PIDBTYPE_OPAQUE,
			sCommand, 0 );

		if ( !tFn )
			{
			/* --- unrecognised directive --- */
			PIIOBuffer_write(
				tPIHTTP.pBuffer, 
				tParam.tConfig.sErrMsg,
				tParam.tConfig.sErrMsg.Len(),
				PIIOBUF_NONE );
			return 0;
			}
		return (tFn)( *this, tPIHTTP, pVariable, iVariableLen, pValue,
			iValueLen, tParam );
		};

	/* ---
	SSI Parse the memory block pMap and send the result to the remote
	client
	Returns 0 on error.
	--- */
	int SSIParse( PIHTTP &tPIHTTP, PIFInfo *pFInfo, const char *pMap,
		int iLen, int iFlags )
		{
#define MIN(a,b) ((a)<(b)?(a):(b))
		SSIConfig tLocalConfig( tConfig );
		SSIParam tParam( pFInfo, tLocalConfig, pExecFileFixup );
		for(;;)
			{
			/* --- find next ssi directive --- */
			int i;
			for( i=0; i<iLen &&
				strncmp( &(pMap[i]), "<!--#", MIN(5,iLen-i) ); i++ );

			/* --- send what has been parsed so far --- */
			if ( i )
				{
				PIIOBuffer_write(
					tPIHTTP.pBuffer, 
					pMap,
					i,
					iFlags );
				};
			if ( i==iLen ) { break; };	/* done! */
			i += 5; pMap = &(pMap[i]); iLen -= i; i=0;

			/* ---
			this is an SSI directive
			--- */
			/* --- scan forward to next '-->', skipping quoted text --- */
			int iQuoted = 0;
			for( ; i<iLen &&
				( strncmp( &(pMap[i]), "-->", MIN(3,iLen-i)) || iQuoted ); i++)
				{
				if ( pMap[i]=='"' ) { iQuoted = ( iQuoted ? 0 : 1 ); };
				};

			/* --- if EOF before '-->' write out an error --- */
			if ( i==iLen )
				{
				PIIOBuffer_write(
					tPIHTTP.pBuffer, 
					tParam.tConfig.sErrMsg,
					tParam.tConfig.sErrMsg.Len(),
					iFlags );
				break;
				};

			/* --- process the directive, ignore errors --- */
			ProcessSSIDirective( tPIHTTP, pMap, i, tParam );

			/* --- skip the directive and continue --- */
			i += 3; pMap = &(pMap[i]); iLen -= i;
			};
		return 1;	
		};

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

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

		/* ---
		Get file object
		--- */
		const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
			KEY_INT_PATH, 0 );
		PIFInfo *pFInfo = HTTPCore_getCachedFile( pPath ); 
		if ( !pFInfo )
			{ return PIAPI_ERROR; };

		/* ---	
		This file must exist and be a regular file 
		--- */
		if ( !PIFInfo_exists( pFInfo ) ||
			!PIFInfo_isRegular( pFInfo ) )
			{
			HTTPCore_logError( &tPIHTTP, "SendSSI: File with path '%s' \
does not exist or is not a regular file.", pPath );
			HTTPCore_releaseCachedFile( pFInfo );	
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* ---
		memory map the file
		--- */

		/* --- get the file map --- */
		const char *pMap = 0;
		int iLen = 0;

		/* --- get filemap object --- */
		PIFMap *pFileMap = 0;
		if ( PIFInfo_getSize( pFInfo )>0 )
			{
			pFileMap = PIFMap_new( pFInfo );
			if ( pFileMap )
				{
				pMap = (const char *)PIFMap_lock( pFileMap, &iLen );
				};
			if ( !pFileMap || !pMap )
				{	
				HTTPCore_logError( &tPIHTTP, "SendSSI: \
Could not memory map file with path '%s'.", pPath );
				PIFMap_delete( pFileMap );
				HTTPCore_releaseCachedFile( pFInfo );	
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
				};
			}
		else
			{
			/* --- zero length file --- */
			pMap = "";
			iLen = 0;
			};

		/* --- set content type to 'text/html --- */
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
			(void *)"text/html", 0 );

		/* --- dynamically generated content should not be cached --- */
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_PRAGMA, (void *)"no-cache", 0 );
		PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_EXPIRES,	
			(void *)"Mon, 23 Feb 1970 15:30:00 GMT", 0 );

		/* --- we don't send a content-length so disable keep open --- */
		PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, KEY_INT_KEEPOPEN,
			(void *)0, 0 );

		/* --- last modified --- */
		Pi3String *pTmp = Pi3String_new( 0 );
		time_t tT;
		time( &tT );
		PIPlatform_beforeUnsafeBlock();
		struct tm *pTms = gmtime( &tT );
		HTTPUtil_rFC822Time( pTms, pTmp );
		PIPlatform_afterUnsafeBlock();
		PIDB_add( pR, PIDBTYPE_RFC822, KEY_HTTP_LASTMODIFIED,
			(void *)Pi3String_getPtr( pTmp ), 0 );
		Pi3String_delete( pTmp );

		/* --- If current status is 0 then change to 200 OK --- */
		if ( !tPIHTTP.iStatus ) { tPIHTTP.iStatus = ST_OK; };

		/* ---
		Lookup method 
		--- */
		int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD, 0 );

		/* --- 	
		Get the header
		--- */
		enum { PATTERN_BUF_SIZE=1024 };
		char szHeader[PATTERN_BUF_SIZE];
		char *pHeader = 0;
		int iHeaderLen = 0;
		if ( pHeaderPattern )
			{
			pHeader = ( iMethod==MD_GET ) ? szHeader : 0;
			iHeaderLen = Pi3Expression_write( pHeaderPattern, &tPIHTTP, 0,
					pHeader, PATTERN_BUF_SIZE );
			if ( iHeaderLen>PATTERN_BUF_SIZE && pHeader )
				{
				pHeader = (char *)PIHTTP_allocMem( &tPIHTTP, iHeaderLen );
				Pi3Expression_write( pHeaderPattern, &tPIHTTP, 0, pHeader,
					iHeaderLen );
				};
			};

		/* --- 	
		Get the footer
		--- */
		char szFooter[PATTERN_BUF_SIZE];
		char *pFooter = 0;
		int iFooterLen = 0;
		if ( pFooterPattern )
			{
			pFooter = ( iMethod==MD_GET ) ? szFooter : 0;
			iFooterLen = Pi3Expression_write( pFooterPattern, &tPIHTTP, 0,
					pFooter, PATTERN_BUF_SIZE );
			if ( iFooterLen>PATTERN_BUF_SIZE && pFooter )
				{
				pFooter = (char *)PIHTTP_allocMem( &tPIHTTP, iFooterLen );
				Pi3Expression_write( pFooterPattern, &tPIHTTP, 0, pFooter,
					iFooterLen );
				};
			};

		/* --- transfer-encoding --- */
		int iFlags = (!PIHTTP_isChild( &tPIHTTP) && (int)PIDB_lookup( tPIHTTP.pRequestDB,
			PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, 0 ) == 3 ) ? PIIOBUF_CHUNKED : PIIOBUF_NONE;
		if ( iFlags & PIIOBUF_CHUNKED )
			{
			PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_TRANSFERENCODING,
				(void *)KEY_HTTP_CHUNKED, 0 );
			}

		/* --- start response --- */
		int iRet =
			HTTPCore_sendGeneralHeaders( &tPIHTTP ) == PIAPI_COMPLETED
		 && HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) == PIAPI_COMPLETED;

		if ( iRet && (iFlags & PIIOBUF_CHUNKED) ) iRet = PIIOBuffer_flush( tPIHTTP.pBuffer );

		/* --- 
		If the Method is 'GET' return PIAPI_CONTINUE to let the 
		handling continue by sending the file.
		Otherwise assume Method is 'HEAD' and return PIAPI_COMPLETED as
		end of transaction
		--- */
		if (iRet)
			{
			switch( iMethod )
				{
				case MD_GET:
					if ( pHeader && iHeaderLen )
						{
						iRet = ( PIIOBuffer_write( tPIHTTP.pBuffer, pHeader,
							iHeaderLen, iFlags)>0 );
						};
					if ( iRet )
						{
						/* --- process the file, ignore errors --- */
						iRet = SSIParse( tPIHTTP, pFInfo, pMap, iLen, iFlags );
						};
					if ( iRet && pFooter && iFooterLen )
						{
						iRet = ( PIIOBuffer_write( tPIHTTP.pBuffer, pFooter,
							iFooterLen, iFlags)>0 );
						};
					break;
		
				case MD_HEAD:
					break;

				default:
					assert( 0 );
					iRet = 0;
				};
			};

		if ( pFileMap )	{ PIFMap_delete( pFileMap ); };
		HTTPCore_releaseCachedFile( pFInfo );	

		/* ---
		If iRet is 0 an error occurred
		** NOTE:
		--- */

		return iRet ? PIAPI_COMPLETED : PIAPI_ERROR;
		};
};

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

#if 0
/*___+++CNF_BEGIN+++___*/
	<Class>
		Name SendSSIClass
		Type LogicExtension
		Library HTTP
		OnClassLoad HandlerBaseHTTP_onClassLoad
		Constructor SendSSI_constructor
		CopyConstructor HandlerBaseHTTP_copyConstructor
		Destructor HandlerBaseHTTP_destructor
		Execute HandlerBaseHTTP_execute
	</Class>

	<Object>
		Name SendSSI
		Class SendSSIClass
	</Object>
/*___+++CNF_END+++___*/
#endif


⌨️ 快捷键说明

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