📄 dirindex.cpp
字号:
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 = "<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 + -