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

📄 dirindex.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		pFKContentType( PIDB_getFastKey( KEY_HTTP_CONTENTTYPE,PIDBTYPE_RFC822)),
		pFKURI( PIDB_getFastKey( KEY_HTTP_URI, PIDBTYPE_STRING ) ),
		pFKPath( PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING ) ),
		sListTop( 0 ),
		bSortDescending( 0 ),
		iSortByColumn( SORT_NONE ),
		tNewTreshold( 0 )
		{
		ReadParameters( iArgc, ppArgv );
		if ( !IsOK() )
			{ return; };

		/* --- validate all necessary components were loaded --- */
		if ( !pFilePattern )
			{
			CONFIG_ERR( Object(),"DirectoryIndex: 'FilePattern' not defined");
			SetOK( 0 );
			return;
			};
		};

	virtual ~DirectoryIndex()
		{
		for( DblListIterator i( lInclude ); !i.BadIndex(); i++)
			{ PI_DELETE( (PIString *)i.Current() ); };
		for( DblListIterator j( lExclude ); !j.BadIndex(); j++)
			{ PI_DELETE( (PIString *)j.Current() ); };
		for( DblListIterator k( lMIMEIcons ); !k.BadIndex(); k++)
			{ PI_DELETE( (MIMEIcon *)k.Current() ); };
		for( DblListIterator m( lSwapFileNames ); !m.BadIndex(); m++)
			{ PI_DELETE( (SwapFileName *)m.Current() ); };
        for( DblListIterator n( lHTTPEquivalents ); !n.BadIndex(); n++)
            { PI_DELETE( (RFC822Header *)n.Current() ); };
		Pi3Expression_delete( pHeaderPattern );
		Pi3Expression_delete( pListTopPattern );
		Pi3Expression_delete( pFilePattern );
		Pi3Expression_delete( pListBottomPattern );
		Pi3Expression_delete( pFooterPattern );
		};

private:
	/* --- internal methods used to write directory index --- */

	/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *

			Miscellanious utilities

	 *___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
	/* ---
	Check if a filename should be changed to a different filename, returns
	new filename or PIString::Empty() to indicate no swap.
	--- */
	const PIString &CheckForSwap( const char *pFileName ) const
		{
		for( ConstDblListIterator i( lSwapFileNames ); !i.BadIndex(); i++ )
			{
			SwapFileName &tSwap = *((SwapFileName *)i.Current());
			if ( !PIUtil_stricmp( tSwap.sFrom, pFileName ) )
				{
				return tSwap.sTo;
				};
			};
		return PIString::Empty();
		};

	/* ---
	Returns the Icon image for a MIME type
	--- */
	const PIString &GetMIMEIcon( const PIString &sMIME ) const
		{
		for( ConstDblListIterator i( lMIMEIcons ); !i.BadIndex(); i++ )
			{
			MIMEIcon &tIcon = *( (MIMEIcon *)i.Current() );
			if (  tIcon.Matches( sMIME ) )
				{ return tIcon.GetPath(); };
			};
		return PIString::Empty();
		};

	/* --- --- */
	bool DoWriteThousands( PIString &sNum, unsigned long ulVal,
		const char *pSep ) const
		{
		if ( ulVal )
			{
			enum { BUF_SIZE=16 };
			char szBuf[BUF_SIZE];
			*szBuf='\0';
			if ( DoWriteThousands( sNum, ulVal/1000, pSep ) )
				{
				sNum.Concatenate( pSep );
				sprintf( szBuf, "%03d", (int)(ulVal%1000) );
				}
			else
				{
				sprintf( szBuf, "%d", (int)(ulVal%1000) );
				};
			sNum.Concatenate( szBuf );
			return true;
			}
		else
			{ return false; };
		};

	/*___
	____*/
	bool WriteThousands( PIString &sNum, unsigned long ulVal,
		const char *pSep ) const
		{
		if ( ulVal )
			{
			sNum = PIString::Empty();
			return DoWriteThousands( sNum, ulVal, pSep );
			}
		else
			{ sNum = "0"; };
		return true;
		};

	/* ---
	Load a description file, if one exists and contains descriptions return 1
	else 0
	--- */
	int LoadDescriptionFile( PIDB *pDescriptionDB, PIFInfo *pDir ) const
		{
		assert( pDir );
		int iRet = 0;
		if ( sDescriptionFile==PIString::Empty() )
			{ /* no file specified */ return iRet; };
		PIString sPath( PIFInfo_getPath( pDir ) );
		sPath.Concatenate( "/" );
		sPath.Concatenate( sDescriptionFile );

		/* --- get the file --- */
		PIFInfo *pFInfo = HTTPCore_getCachedFile( sPath );
		if ( !pFInfo )
			{ /* error should always be able to get file object */ return 0; };

		if ( PIFInfo_exists( pFInfo )  && PIFInfo_isRegular( pFInfo ) )
			{	
			enum { BUF_SIZE=1023 };
			char szBuf[BUF_SIZE+1];
			*szBuf = '\0';
			ifstream ifs( PIFInfo_getPath( pFInfo ) );
			while( ifs && !ifs.eof() ) 	
				{
				ifs.getline( szBuf, BUF_SIZE );
				DescriptionMap *pDesc = PI_NEW( DescriptionMap( szBuf ) );
				PIDB_add( pDescriptionDB, PIDBTYPE_OPAQUE, pDesc->sFileName,
					(void *)pDesc, 0 );
				iRet = 1;
				};
			};
		HTTPCore_releaseCachedFile( pFInfo );
		return iRet;
		};

	/* ---
	send a header or footer file, if appropriate.
	returns 1 on OK, 0 on error.
	--- */
	int SendFile( PIHTTP &tPIHTTP, const PIString &sFile, PIFInfo *pDir ) const
		{
		assert( pDir );
		if ( sFile==PIString::Empty() )
			{ /* no file specified */ return 1; };
		PIString sPath( PIFInfo_getPath( pDir ) );
		sPath.Concatenate( "/" );
		sPath.Concatenate( sFile );

		/* --- get the file --- */
		PIFInfo *pFInfo = HTTPCore_getCachedFile( sPath );
		if ( !pFInfo )
			{ /* error should always be able to get file object */ return 0; };

		if ( PIFInfo_exists( pFInfo )  && PIFInfo_isRegular( pFInfo ) )
			{	
			/* --- memory map the file and send it --- */
			PIFMap *pFileMap = PIFMap_new( pFInfo );

			/* --- send mapped file --- */
			const char *pMap = 0;
			int iLen = 0;
			if ( pFileMap )
				{ pMap = (const char *)PIFMap_lock( pFileMap, &iLen ); };
	
			if ( pMap && iLen )
				{
				PIIOBuffer_write( tPIHTTP.pBuffer, pMap, iLen, PIIOBUF_NONE );
				};

			PIFMap_delete( pFileMap );
			};
		HTTPCore_releaseCachedFile( pFInfo );
		return 1;
		};

	/* ---
	Grap the IOBuffer's internal buffer pointer and write the
	expression directly into it
	--- */
	int WriteExpression( Pi3Expression *pExpr, PIHTTP &tPIHTTP,
		WriteContext &tContext ) const
		{
		if ( !pExpr )
			{ return 1; };
		assert( pExpr );
		int iRecursed = 0;
		for(;;)
			{
			char *pBuffer = 0;
			int iSize = PIIOBuffer_getOutputBuffer( tPIHTTP.pBuffer, &pBuffer );
			int iLen = Pi3Expression_write( pExpr, &tPIHTTP, &tContext,
				pBuffer, iSize );
			if ( !iLen )
				{ return 1; };
			if ( iSize<iLen )
				{
				if ( iRecursed )
					{
					HTTPCore_logError( &tPIHTTP, "DirectoryIndex: IO \
buffer to small to generate expression for output." );
					return 0;
					};
				PIIOBuffer_flush( tPIHTTP.pBuffer );
				iRecursed = 1;
				}
			else
				{
				PIIOBuffer_advanceBufferPointer( tPIHTTP.pBuffer, iLen );
				return 1;
				};
			};

		/* --- should never get here --- */
		assert( 0 );
		return 0;
		};

	/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *

		Generate the header for the directory listing

	 *___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
	int Top( PIHTTP &tPIHTTP, PIFInfo *pDir, WriteContext &tContext ) const
		{
		if ( !WriteExpression( pHeaderPattern, tPIHTTP, tContext ) )
			{ return 0; };

		/* --- send any header file --- */
		if ( !SendFile( tPIHTTP, sHeaderFile, pDir ) )
			{
			HTTPCore_logError( &tPIHTTP, "DirectoryIndex: Error \
sending header file '%s'.", (const char *)sHeaderFile );
			return 0;
			};

		if ( !WriteExpression( pListTopPattern, tPIHTTP, tContext ) )
			{ return 0; };

		return 1;
		}

	/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *

		Generate a output for a single file in the listing

	 *___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
	int File( PIHTTP &tPIHTTP, WriteContext &tContext, PIFInfo *pInfo,
		const char *pRelativePath, PIDB *pDescriptionDB ) const
		{
		register int iFlags = iOptions;
		assert( pInfo );

		const char *pName = PIFInfo_getName( pInfo );
		assert( pName );
		if ( !pName ) { return 0; };

		/* --- name --- */
		if ( iFlags & FLG_NAME )
			{
			const PIString &sTmp = CheckForSwap( pName );
			if ( sTmp==PIString::Empty() )
				{
				tContext.tName.pField = PIFInfo_getName( pInfo );
				tContext.tName.iLength = strlen( PIFInfo_getName( pInfo ) );
				}
			else
				{
				tContext.tName.pField = sTmp;
				tContext.tName.iLength = sTmp.Len();
				};
			};

		/* --- alternate name --- */
		if ( iFlags & FLG_ALTNAME )
			{
			const char *pAlt = PIFInfo_getAlternateName( pInfo );
			tContext.tAltName.pField = pAlt;
			tContext.tAltName.iLength = strlen( pAlt );
			};

		/* --- modification date --- */
		enum { DATE_BUFFER=128 };
		char szDate[DATE_BUFFER];
		*szDate = '\0';
		if ( iFlags & FLG_MODDATE )
			{
			time_t tT = PIFInfo_getLastModified( pInfo );
			PIPlatform_beforeUnsafeBlock();
			struct tm *pTms = gmtime( &tT );
			assert( pTms );
			strftime( szDate, DATE_BUFFER, sLastModifiedFormat, pTms );
			PIPlatform_afterUnsafeBlock();
			tContext.tLastModifiedDate.pField = szDate;
			tContext.tLastModifiedDate.iLength = strlen( szDate );
			};

		/* --- tag file if new --- */
		if ( iFlags & FLG_TAGNEW )
			{
			time_t tT1 = PIFInfo_getLastModified( pInfo );
			time_t tT2;
			PIPlatform_beforeUnsafeBlock();
			time(&tT2);
			PIPlatform_afterUnsafeBlock();
			if ( tT1 + tNewTreshold >= tT2 )
				{
				tContext.tTagNew.pField = (const char *)sNewPattern;
				tContext.tTagNew.iLength = strlen( sNewPattern );
				}
			else
				{
				tContext.tTagNew.pField = 0;
				tContext.tTagNew.iLength = 0;
				}
			};

		/* ---
		Determine whether or not this is a directory
		--- */
		bool bIsDirectory = PIFInfo_isDirectory( pInfo );
		if ( bIsDirectory )
			{
			tContext.tIsDirectory.pField = "true";
			tContext.tIsDirectory.iLength = 4;
			}
		else
			{
			tContext.tIsDirectory.pField = 0;
			tContext.tIsDirectory.iLength = 0;
			};

		/* --- relative path --- */
		PIString sRelativePath( pRelativePath );
		if ( iFlags & FLG_RELPATH )
			{
			/* ---
			relative URI to file
			--- */
			/* --- don't do full URL encoding, just substitute '+' for ' '--- */
			PIString sName( pName );
			sRelativePath.Concatenate( sName);
			SwapSubStrings tEncoded( sRelativePath, " ", "+" );
			sRelativePath = tEncoded.GetString();
			if ( bIsDirectory )
				{
				sRelativePath.Concatenate( HTTP_DIRSEPERATOR );
				};
			tContext.tRelativePath.pField = sRelativePath;
			tContext.tRelativePath.iLength = sRelativePath.Len();
			};

		PIString sSize;
		if ( ( iFlags & FLG_SIZE ) ||
			( iFlags & FLG_FORMATSIZE ) ||
			( iFlags & FLG_ABBREVSIZE )
			)
			{
			if ( bIsDirectory )
				{
				tContext.tSize.pField = "-";
				tContext.tSize.iLength = 1;
				}
			else
				{
				unsigned long ulSize = PIFInfo_getSize( pInfo );
				if ( iFlags & FLG_SIZE )
 					{
					enum { BUF_SIZE=63 };
					char szBuf[BUF_SIZE+1];
					*szBuf = '\0';
					sprintf( szBuf, "%lu", ulSize );
					sSize = szBuf;
					}
				if ( iFlags & FLG_FORMATSIZE )
					{
					sSize = "0";
					WriteThousands( sSize, ulSize, "," /* thousands delimiter */ );
					}
				else if ( iFlags & FLG_ABBREVSIZE )
					{
					enum { BUF_SIZE=63 };
					char szBuf[BUF_SIZE+1];
					*szBuf = '\0';
					char s='K';
					if ( ulSize>=0x100000 )		/* 1 Meg. */
						{
						s = 'M';
						ulSize = 0xFFFFF & (ulSize >> 20); 
						sprintf( szBuf, "%d", (int)ulSize );
						sSize = szBuf;
						}
/*
**					else if ( ulSize>=0x400 )	/.* 1 K *./
** disable the <1K display because of alignment problems
*/
					else 
						{
						ulSize = 0x3FF & (ulSize >> 10); 
						if ( ulSize==0 ) { ulSize=1; };
						sprintf( szBuf, "%d", (int)ulSize );
						sSize = szBuf;
						}
/*					else
**						{ sSize = "&lt;1"; };
*/
					sSize.Concatenate( s );
					};
	
				/* --- set size --- */
				tContext.tSize.pField = sSize;
				tContext.tSize.iLength = sSize.Len();
				};
			};

		/* ---
		get the Media type only if it will be used.
		--- */
		PIString sMIME;
		if ( ( iFlags & FLG_MIMETYPE ) || ( iFlags & FLG_ICON ) )
			{
			if ( bIsDirectory )
				{ sMIME = TYPE_MAGIC_DIRECTORY; }
			else
				{
				 /* --- attempt to get mime type --- */
				sMIME = HTTPCore_getMIMETypeFromExtension(
					PIFInfo_getExtension( pInfo ) );
				}

⌨️ 快捷键说明

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