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

📄 dirindex.cpp

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

		/* --- Set the Media type --- */
		if ( iFlags & FLG_MIMETYPE )
			{
			tContext.tMedia.pField = sMIME;
			tContext.tMedia.iLength = sMIME.Len();
			};
	
		/* --- Get the icon path for this MIME type --- */
		if ( iFlags & FLG_ICON )
			{
			const PIString &sIcon = GetMIMEIcon( sMIME );
			tContext.tIcon.pField = sIcon;
			tContext.tIcon.iLength = sIcon.Len();
			};

		/* --- get the files description --- */
		if ( pDescriptionDB )
			{
			DescriptionMap *pDesc = (DescriptionMap *)PIDB_lookup(
				pDescriptionDB, PIDBTYPE_OPAQUE, pName, 0 );
			if ( pDesc )
				{
				tContext.tDescription.pField = pDesc->sDescription;
				tContext.tDescription.iLength = pDesc->sDescription.Len();
				}
			else
				{	
				tContext.tDescription.pField = 0;
				tContext.tDescription.iLength = 0;
				};
			};

		/* --- generate the output and send it to the remote client --- */
		assert( pFilePattern );
		if ( !WriteExpression( pFilePattern, tPIHTTP, tContext ) )
			{ return 0; };

		/* --- null out some fields --- */
		tContext.tName.iLength = 0;
		tContext.tAltName.iLength = 0;
		tContext.tLastModifiedDate.iLength = 0;
		tContext.tIsDirectory.iLength = 0;
		tContext.tRelativePath.iLength = 0;
		tContext.tIcon.iLength = 0;
		tContext.tMedia.iLength = 0;
		tContext.tSize.iLength = 0;

		return 1;
		};

	/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
		
				Generate the directory trailer

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

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

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

		return 1;
		};

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

		Generate the directory and write in to output stream

	 *___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
	bool GenerateDirectoryListing(
			PIHTTP &tPIHTTP,
			WriteContext &tContext,
			PIFInfo *pDir,
			const char *pRelativePath ) const
		{
		assert( pDir );
		assert( PIFInfo_isDirectory( pDir ) );

		tContext.tDirectory.pField = pRelativePath;
		tContext.tDirectory.iLength = strlen( pRelativePath );

		/* ---	
		Attempt to load a description file
		--- */
		PIDB *pDescriptionDB = 0;
		if ( sDescriptionFile!=PIString::Empty() )
			{
			pDescriptionDB = PIDB_new( 0, "File Descriptions" );
			if ( !LoadDescriptionFile( pDescriptionDB, pDir ) )
				{
				PIDB_delete( pDescriptionDB );
				pDescriptionDB = 0;
				};
			};

		PIFInfo *pFile = PIFInfo_getFirstFileInDirectory( pDir );
		int iError = 0;		/* error flag */
		PIFInfo *Files[MAX_FILESORT_ARRAY];
		int fCount = 0;
		unsigned long ulSize = 0;
			
		while( pFile && !iError && ( fCount < MAX_FILESORT_ARRAY ))
			{
			/* ---
			Check file is allowed, this is an OR function, if any allow		
			pattern matches then include this file
			--- */
			int iAllow = 0;
			if ( PIFInfo_isReadable( pFile ) )
				{
				/* ---
				Get filename
				--- */
				PIString sFileName( PIFInfo_getName( pFile ) );

				for( ConstDblListIterator i( lInclude ); !i.BadIndex(); i++ )
					{
					PIString &sPattern = *( (PIString *)i.Current() );	
					if ( HTTPUtil_regexMatch(
						sPattern, sPattern.Len(),
						sFileName, sFileName.Len() )
						)
						{
						iAllow = 1;
						break;
						};
					};
	
				if ( iAllow )
					{
					/* ---
					Check if the file has been excluded, this is an OR function,
					exclude if any exlusion matches
					--- */
					for( ConstDblListIterator e( lExclude ); !e.BadIndex(); e++ )
						{
						PIString &sPattern = *( (PIString *)e.Current() );	
						if ( HTTPUtil_regexMatch(
							sPattern, sPattern.Len(),
							sFileName, sFileName.Len() )
							)
							{
							iAllow = 0;	
							break;
							};
						};
					};
				};
	
			if ( iAllow )
				{
				if (!PIFInfo_isDirectory( pFile ))
					ulSize += PIFInfo_getSize( pFile );
				Files[fCount++] = PIFInfo_new( PIFInfo_getPath( pFile ));
				};

			if ( iError || !PIFInfo_getNextFileInDirectory( pFile ) )
				{ PIFInfo_delete( pFile ); pFile = 0; };
			}; //while

		if ( !iError )
			{
			Files[fCount] = 0;
			qSort(Files, 0, fCount - 1, pDescriptionDB, iSortByColumn, bSortDescending, iOptions & FLG_SORTCASE);
			}

		enum { BUF_SIZE=63 };
		char szBuf[BUF_SIZE+1];
		sprintf(szBuf, "%lu", fCount);
		PIString sDirCount = szBuf;

		/* --- set directory count --- */
		tContext.tDirCount.pField = sDirCount;
		tContext.tDirCount.iLength = sDirCount.Len();

		PIString sDirSize;
		if ( iOptions & FLG_SIZE )
			{
			enum { BUF_SIZE=63 };
			char szBuf[BUF_SIZE+1];
			*szBuf = '\0';
			sprintf( szBuf, "%lu", ulSize );
			sDirSize = szBuf;
			}
		if ( iOptions & FLG_FORMATSIZE )
			{
			sDirSize = "0";
			WriteThousands( sDirSize, ulSize, "," /* thousands delimiter */ );
			}
		else if ( iOptions & 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 );
				sDirSize = szBuf;
				}
			else 
				{
				ulSize = 0x3FF & (ulSize >> 10); 
				sprintf( szBuf, "%d ", (int)ulSize );
				sDirSize = szBuf;
				}
			sDirSize.Concatenate( s );
			};
	
		/* --- set directory size --- */
		tContext.tDirSize.pField = sDirSize;
		tContext.tDirSize.iLength = sDirSize.Len();

		/* --- write the header --- */
		Top( tPIHTTP, pDir, tContext );

		/* --- write the body --- */
		for (int j = 0; j < fCount; j++ ) {
			// call 'File' only if no error but delete array members in any case
			iError = iError || !File( tPIHTTP, tContext, Files[j],
				pRelativePath, pDescriptionDB );
			PIFInfo_delete( Files[j] );
		};

		/* --- write the footer --- */
		Bottom( tPIHTTP, pDir, tContext );

		/* ---
		Delete descriptions 
		--- */
		PIDBIterator *pIter = PIDB_getIterator( pDescriptionDB,
			PIDBTYPE_OPAQUE, 0, 0 );
		if ( pIter )
			{
			for( ; pIter && PIDBIterator_atValidElement( pIter );
				PIDBIterator_next( pIter ) )
				{
				DescriptionMap *pDesc = (DescriptionMap *)
					PIDBIterator_current( pIter, 0 );
				assert( pDesc );
				PI_DELETE( pDesc );
				};
			};
		if ( pDescriptionDB )
			{ PIDB_delete( pDescriptionDB ); };
		PIDBIterator_delete( pIter );
		return true;
		};

public:

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

					Handle the request

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

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

		/* --- 
		The following is the kernel of the sort property
		together with the qSort function.
		--- */

		// set the default sort order by options value
		bSortDescending = ( iOptions & FLG_SORTDESC );			

		// parse the query string and change the table header row
		char *pQueryString = (char *)
			PIDB_lookup( pQ, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING, 0 );
		char *pos = NULL;
		int bListTopModified = 0;

		// set the default sort column by options value
		// and find default field in table header row
		if ( iOptions & FLG_SORTTYPE )
			{ 
				iSortByColumn = SORT_TYPE;
				pos = strstr( sListTop, KEY_SORT_TYPE );
			}
		else if ( iOptions & FLG_SORTNAME )
			{
				iSortByColumn = SORT_NAME;
				pos = strstr( sListTop, KEY_SORT_NAME );
			}
		else if ( iOptions & FLG_SORTSIZE )
			{ 
				iSortByColumn = SORT_SIZE;
				pos = strstr( sListTop, KEY_SORT_SIZE );
			}
		else if ( iOptions & FLG_SORTDATE )
			{
				iSortByColumn = SORT_DATE;
				pos = strstr( sListTop, KEY_SORT_DATE );
			}
		else if ( iOptions & FLG_SORTDSCR )
			{
				iSortByColumn = SORT_DESC;
				pos = strstr( sListTop, KEY_SORT_DESC );
			};

		// the last sort order
//		int iOldColumn = iSortByColumn;
		
		// expected Tokens in QueryString
		const char *pColumn = 0;
		const char *pSort = 0;
		
		if ( !pQueryString || !strcmp( pQueryString, "" )) {
		    if (pos) {
			// set the sort order for the default column to the inverse default
			if ( bSortDescending )
				{ strncpy( pos + SORT_KEY_LEN + 1, "A", 1 ); }
			else
				{ strncpy( pos + SORT_KEY_LEN + 1, "D", 1 ); };
			bListTopModified = 1;
		    };
		} else {
			StringTokenizer tTokens( pQueryString, "=" );
			if (tTokens.NumTokens() < 2) {
				HTTPCore_logError( &tPIHTTP, "DirectoryIndex: Invalid QueryString '%s'.", pQueryString );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			} else {
				pColumn = (const char *)tTokens.GetToken( 0 );
				pSort = (const char *)tTokens.GetToken( 1 );
			};

			// switch sort order			
			if ( pSort ) { bSortDescending = !strcmp( pSort, "D" ); };

	    		// find the current sort column (query string must be part of header row)
			pos = pColumn ? strstr( sListTop, pColumn ) : 0;
			if ( pos ) {
			    // set the sort column by query string field
				if ( !strcmp( pColumn, KEY_SORT_TYPE )) { iSortByColumn = SORT_TYPE; };
				if ( !strcmp( pColumn, KEY_SORT_NAME )) { iSortByColumn = SORT_NAME; };				
				if ( !strcmp( pColumn, KEY_SORT_SIZE )) { iSortByColumn = SORT_SIZE; };
				if ( !strcmp( pColumn, KEY_SORT_DATE )) { iSortByColumn = SORT_DATE; };
				if ( !strcmp( pColumn, KEY_SORT_DESC )) { iSortByColumn = SORT_DESC; };
    
				// the header has to be patched
				if ( bSortDescending ) {
				    strncpy( pos + strlen( pColumn ) + 1, "A", 1 );
				} else {
				    strncpy( pos + strlen( pColumn ) + 1, "D", 1 );
		    		};
    				bListTopModified = 1;
			};
		};
		
		// write the changed table header into Pi3-Expression
		if ( bListTopModified ) {
			// delete old expression
			if ( pListTopPattern ) { Pi3Expression_delete( pListTopPattern ); };
			Pi3String *pError = Pi3String_new( 0 );

			// create new expression from changed table header
			pListTopPattern = Pi3Expression_new( sListTop, aFunctions, pError );
			Pi3String_delete( pError );

			// Error!
			if ( !pListTopPattern )	{
				HTTPCore_logError( &tPIHTTP, "DirectoryIndex: Error when trying to change header row." );
				return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );;
			};
		};

		/* --- request must be GET or HEAD --- */
		int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD,
			0 );
		if ( iMethod!=MD_GET && iMethod!=MD_HEAD )
			{ return PIAPI_CONTINUE; };

		/* ---
		Get URL Path
		--- */
		const char *pURI = (const char *)
			PIDB_lookup( pQ, PIDBTYPE_STRING, pFKURI, PIDBFLAG_FASTKEY ); 
		if ( !pURI )
			{
			HTTPCore_logError( &tPIHTTP, "DirectoryIndex: pURI is NULL." );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );;
			};

		/* --- get directory --- */
		const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
			pFKPath, PIDBFLAG_FASTKEY );	
		PIFInfo *pDir = HTTPCore_getCachedFile( pPath );

		if ( !pDir )
			{
			HTTPCore_logError( &tPIHTTP, "DirectoryIndex: \
HTTPCore_getCachedFile() failed.");
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		if ( !PIFInfo_exists( pDir ) )
			{
			HTTPCore_logError( &tPIHTTP, "DirectoryIndex: Resource \
with path '%s' does not exist.", PIFInfo_getPath( pDir ) );
			HTTPCore_releaseCachedFile( pDir );
			return HTTPUtil_doHTTPError( &tPIHTTP, 404 );
			};

		if ( !PIFInfo_isDirectory( pDir ) )
			{
			HTTPCore_logError( &tPIHTTP, "DirectoryIndex: Resource \
with path '%s' is not a directory.", PIFInfo_getPath( pDir ) );
			HTTPCore_releaseCachedFile( pDir );
			return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
			};

		/* --- set the status --- */
		tPIHTTP.iStatus = ST_OK;

		/* --- replace content-type --- */
		PIDB_replace( pR, PIDBTYPE_RFC822, pFKContentType,
			(void *)"text/html", PIDBFLAG_FASTKEY );

		/* --- send last modified --- */
		Pi3String *pTmp = Pi3String_new( 0 );
		time_t tT = PIFInfo_getLastModified( pDir );
		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 ),

⌨️ 快捷键说明

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