📄 dirindex.cpp
字号:
result -= 2;
} else {
// case sensitivity
if ( bCaseSensitive ) {
result = strcmp(HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg1 )),
HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg2 )));
} else {
result = PIUtil_stricmp(HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg1 )),
HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg2 )));
};
// same type ? sort by name!
if (!result) {
result = bCaseSensitive ?
strcmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ))
: PIUtil_stricmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ));
};
};
// sort order
return bDescending ? -result : result;
};
/*____________________________________________________________________________*\
*
Class:
Description:
Compare two keys of type PIFInfo * by size.
\*____________________________________________________________________________*/
int cmpSize( PIFInfo *arg1, PIFInfo *arg2, PIDB *pDB, int bDescending, int bCaseSensitive ) {
// assume directories has 0 bytes (smaller than files)
// directories are always top level
int result = cmpDirs( arg1, arg2 );
if ( result ) {
result -= 2;
} else {
// no case sensitivity
result = PIFInfo_getSize(arg1) - PIFInfo_getSize(arg2);
// same size ? sort by name!
if (!result) {
result = bCaseSensitive ?
strcmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ))
: PIUtil_stricmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ));
};
}
// sort order
return bDescending ? -result : result;
};
/*____________________________________________________________________________*\
*
Class:
Description:
Compare two keys of type PIFInfo * by date.
\*____________________________________________________________________________*/
int cmpDate( PIFInfo *arg1, PIFInfo *arg2, PIDB *pDB, int bDescending, int bCaseSensitive ) {
// directories are always top level
int result = cmpDirs( arg1, arg2 );
if ( result ) {
result -= 2;
} else {
// no case sensitivity
result = PIFInfo_getLastModified(arg1) - PIFInfo_getLastModified(arg2);
// same date ? sort by name!
if (!result) {
result = bCaseSensitive ?
strcmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ))
: PIUtil_stricmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ));
};
}
// sort order
return bDescending ? -result : result;
};
/*____________________________________________________________________________*\
*
Class:
Description:
Compare two keys of type PIFInfo * by description.
\*____________________________________________________________________________*/
int cmpDesc( PIFInfo *arg1, PIFInfo *arg2, PIDB *pDB, int bDescending, int bCaseSensitive) {
// directories are always top level
int result = cmpDirs( arg1, arg2 );
if ( result ) {
result -= 2;
} else {
// load default description (Mime-Type) for 1st argument
const char *pVal1 = PIFInfo_isDirectory( arg1 ) ? TYPE_MAGIC_DIRECTORY
: HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg1 ));
// load default description (Mime-Type) for 2nd argument
const char *pVal2 = PIFInfo_isDirectory( arg2 ) ? TYPE_MAGIC_DIRECTORY
: HTTPCore_getMIMETypeFromExtension( PIFInfo_getExtension( arg2 ));
if ( pDB ) {
// load 1st description from Map-DB
DescriptionMap *pDesc1 = (DescriptionMap *)PIDB_lookup(
pDB, PIDBTYPE_OPAQUE, PIFInfo_getName( arg1 ), 0 );
if ( pDesc1 ) pVal1 = pDesc1->sDescription;
// load 2nd description from Map-DB
DescriptionMap *pDesc2 = (DescriptionMap *)PIDB_lookup(
pDB, PIDBTYPE_OPAQUE, PIFInfo_getName( arg2 ), 0 );
if ( pDesc2 ) pVal2 = pDesc2->sDescription;
};
// description can contain (invisibly) leading HTML-tags, skip them
if (strchr(pVal1, '<')==pVal1) { pVal1 = strchr(pVal1, '>'); pVal1++; }
if (strchr(pVal2, '<')==pVal2) { pVal2 = strchr(pVal2, '>'); pVal2++; }
// case sensitivity
result = bCaseSensitive ? strcmp( pVal1, pVal2 ) : PIUtil_stricmp( pVal1, pVal2 );
// same description ? sort by name!
if (!result) {
result = bCaseSensitive ?
strcmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ))
: PIUtil_stricmp( PIFInfo_getName( arg1 ), PIFInfo_getName( arg2 ));
};
}
// sort order
return bDescending ? -result : result;
};
/*____________________________________________________________________________*\
*
Class:
Description:
Quick sort of an array of PIFInfo pointers, by given column no.
Optional descending, case sensitive sort flags.
\*____________________________________________________________________________*/
void qSort(PIFInfo *A[], int Min, int Max, PIDB *pDB, int iSortByColumn, int bDescending, int bCaseSensitive) {
if ( iSortByColumn == SORT_NONE) { return; };
int Lo = Min;
int Hi = Max;
PIFInfo *T;
PIFInfo *Mid = A[(Lo + Hi) / 2];
do {
switch ( iSortByColumn )
{
case SORT_TYPE:
while ( cmpType( A[Lo], Mid, pDB, bDescending, bCaseSensitive) < 0 && A[Lo++] != Mid);
while ( cmpType( A[Hi], Mid, pDB, bDescending, bCaseSensitive) > 0 && A[Hi--] != Mid);
break;
case SORT_NAME:
while ( cmpName( A[Lo], Mid, pDB, bDescending, bCaseSensitive) < 0 && A[Lo++] != Mid);
while ( cmpName( A[Hi], Mid, pDB, bDescending, bCaseSensitive) > 0 && A[Hi--] != Mid);
break;
case SORT_SIZE:
while ( cmpSize( A[Lo], Mid, pDB, bDescending, bCaseSensitive) < 0 && A[Lo++] != Mid);
while ( cmpSize( A[Hi], Mid, pDB, bDescending, bCaseSensitive) > 0 && A[Hi--] != Mid);
break;
case SORT_DATE:
while ( cmpDate( A[Lo], Mid, pDB, bDescending, bCaseSensitive) < 0 && A[Lo++] != Mid);
while ( cmpDate( A[Hi], Mid, pDB, bDescending, bCaseSensitive) > 0 && A[Hi--] != Mid);
break;
case SORT_DESC:
while ( cmpDesc( A[Lo], Mid, pDB, bDescending, bCaseSensitive) < 0 && A[Lo++] != Mid);
while ( cmpDesc( A[Hi], Mid, pDB, bDescending, bCaseSensitive) > 0 && A[Hi--] != Mid);
break;
default: break;
};
if ( Lo <= Hi ) {
T = A[Lo];
A[Lo] = A[Hi];
A[Hi] = T;
Lo++;
Hi--;
};
} while ( Lo <= Hi );
if ( Hi > Min ) { qSort( A, Min, Hi, pDB, iSortByColumn, bDescending, bCaseSensitive ); };
if ( Lo < Max ) { qSort( A, Lo, Max, pDB, iSortByColumn, bDescending, bCaseSensitive ); };
};
/* ---
end of change
--- */
/*____________________________________________________________________________*\
*
Class:
Description:
Directory index handler
\*____________________________________________________________________________*/
class DirectoryIndex : public HandlerBaseHTTP
{
private:
/* --- forbid copy constructor --- */
DirectoryIndex( const DirectoryIndex &t )
: HandlerBaseHTTP( t )
{ assert( 0 ); };
/* ---
Configuration data
--- */
Pi3Expression *pHeaderPattern; /* pattern for top */
Pi3Expression *pListTopPattern; /* pattern sent before index */
Pi3Expression *pFilePattern; /* pattern for file */
Pi3Expression *pListBottomPattern;/* pattern sent after index */
Pi3Expression *pFooterPattern; /* pattern for footer */
PIString sHeaderFile; /* file to be sent as header */
PIString sFooterFile; /* file to be sent as footer */
PIString sLastModifiedFormat; /* last modified format */
PIString sNewPattern; /* pattern to tag new files */
DblList lInclude; /* patterns to include */
DblList lExclude; /* patterns to exclude */
DblList lMIMEIcons; /* mappings of MIME types to images */
DblList lSwapFileNames; /* files to swap */
DblList lHTTPEquivalents; /* response headers to send */
PIString sDescriptionFile; /* description file */
int iOptions; /* options/flags */
time_t tNewTreshold; /* threshold time for new files */
/* ---
FastKeys
--- */
const char *pFKContentType; /* RFC822: Content-Type */
const char *pFKURI; /* RFC822: URI from request header */
const char *pFKPath; /* STRING: Translated path */
PIString sListTop;
int bSortDescending;
int iSortByColumn;
/* ---
end of change
--- */
protected:
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
Load an expression or condition
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
int LoadExpression( const char *pName, Pi3Expression **ppExpression,
FnPi3Write *pFunctions, const char *pValue, PIOStrStream &os )
{
assert( ppExpression );
Pi3Expression *pExpression = *ppExpression;
if ( pExpression )
{
os << "'" << pName << "' may only be specified once." << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
Pi3String *pError = Pi3String_new( 0 );
pExpression = Pi3Expression_new( pValue, pFunctions, pError );
if ( !pExpression )
{
os << "Error parsing expression: " <<
Pi3String_getPtr( pError ) << ends;
CONFIG_ERR( Object(), os.str() );
Pi3String_delete( pError );
return 0;
};
Pi3String_delete( pError );
*ppExpression = pExpression;
return 1;
};
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
Configure handler object based on parameters
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
int Parameter( const char *pVariable, const char *pValue,
const char *pWhere )
{
assert( pVariable && pValue );
PIOStrStream os;
os << pWhere << "DirectoryIndex: ";
if ( !PIUtil_stricmp( KEY_CONF_HEADERFILE, pVariable ) )
{
sHeaderFile = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_FOOTERFILE, pVariable ) )
{
sFooterFile = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_LASTMODIFIEDFORMAT, pVariable ) )
{
iOptions |= FLG_MODDATE;
sLastModifiedFormat = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_HEADERPATTERN, pVariable ) )
{
if ( !LoadExpression( KEY_CONF_HEADERPATTERN, &pHeaderPattern,
aFunctions, pValue, os ) )
{ return 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_LISTTOP, pVariable ) )
{
if ( !LoadExpression( KEY_CONF_LISTTOP, &pListTopPattern,
aFunctions, pValue, os ) )
{ return 0; };
sListTop = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_FILEPATTERN, pVariable ) )
{
if ( !LoadExpression( KEY_CONF_FILEPATTERN, &pFilePattern,
aFunctions, pValue, os ) )
{ return 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_FOOTERPATTERN, pVariable ) )
{
if ( !LoadExpression( KEY_CONF_FOOTERPATTERN, &pFooterPattern,
aFunctions, pValue, os ) )
{ return 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_LISTBOTTOM, pVariable ) )
{
if ( !LoadExpression( KEY_CONF_LISTBOTTOM, &pListBottomPattern,
aFunctions, pValue, os ) )
{ return 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_OPTIONS, pVariable ) )
{
/* ---
Split the options up by the bar ('|') character and then
strip trailing and leading whitespace from option before
attempting to match it.
--- */
StringTokenizer tTokens( pValue, "|" );
for(int i=0; i<tTokens.NumTokens(); i++)
{
const char *pToken = tTokens.GetToken( i );
/* --- skip leading whitespace --- */
for( ; *pToken && (isspace(*pToken)); pToken++ );
/* ---
include only to first whitespace trailing whitespace
--- */
int j=0;
for( ; pToken[j] && !(isspace(pToken[j])); j++ );
/* ---
j now contains the length of the first word in pToken
--- */
/* ---
cycle through the list of available flags
comparing them with this one
--- */
int i=0;
for( ; aFlagMap[i].pName; i++ )
{
if ( !PIUtil_strncmpi( aFlagMap[i].pName, pToken, j ) )
{ break; };
};
if ( !aFlagMap[i].pName )
{
/* --- flag not found --- */
PIString sTmp( pToken, j );
os << "Unknown option flag '" << sTmp << "'." << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
iOptions |= aFlagMap[i].iFlag;
}; /* --- loop over tokens seperated by '|' --- */
}
else if ( !PIUtil_stricmp( KEY_CONF_INCLUDE, pVariable ) )
{
lInclude.Append( (DblList::type) PI_NEW( PIString( pValue ) ) );
}
else if ( !PIUtil_stricmp( KEY_CONF_EXCLUDE, pVariable ) )
{
lExclude.Append( (DblList::type) PI_NEW( PIString( pValue ) ) );
}
else if ( !PIUtil_stricmp( KEY_CONF_SWAPFILENAME, pVariable ) )
{
int i;
for( i=0; pValue[i] && !(isspace(pValue[i])); i++);
PIString sOld( pValue, i );
pValue = &( pValue[i] );
for( ; *pValue && (isspace(*pValue)); pValue++ );
lSwapFileNames.Append( (DblList::type)
PI_NEW( SwapFileName( sOld, pValue ) ) );
}
else if ( !PIUtil_stricmp( KEY_CONF_DESCRIPTIONFILE, pVariable ) )
{
sDescriptionFile = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_MIMEICON, pVariable ) )
{
StringTokenizer tTokens( pValue, " ", 0 );
if ( tTokens.NumTokens()!=2 )
{
os << "Syntax error in definiton of 'MIMEIcon', line is '" <<
pValue << "'" << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
lMIMEIcons.Append( (DblList::type) PI_NEW(
MIMEIcon( tTokens.GetToken(0), tTokens.GetToken(1) ) ) );
}
else if ( !PIUtil_stricmp( KEY_CONF_HTTPEQUIV, pVariable ) )
{
RFC822Header *pHeader = PI_NEW( RFC822Header( pValue ) );
if ( !pHeader || !pHeader->IsOK() )
{
os << "Bad HTTPEquiv expression, '" << pValue << "'" << ends;
CONFIG_ERR( Object(), os.str() );
PI_DELETE( pHeader );
return 0;
}
else
{
lHTTPEquivalents.Append( (DblList::type)pHeader );
};
}
else if ( !PIUtil_stricmp( KEY_CONF_NEWPATTERN, pVariable ) )
{
sNewPattern = pValue;
}
else if ( !PIUtil_stricmp( KEY_CONF_NEWTHRESHOLD, pVariable ) )
{
tNewTreshold = 86400 * atoi(pValue);
}
else
{
os << "Unknown directive '" << pVariable <<
"'" << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
return 1;
};
public:
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
Object lifetime stuff
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
DirectoryIndex( PIObject *pTheObject, int iArgc, const char *ppArgv[] )
:
HandlerBaseHTTP( pTheObject ),
pHeaderPattern( 0 ),
pListTopPattern( 0 ),
pFilePattern( 0 ),
pListBottomPattern( 0 ),
pFooterPattern( 0 ),
iOptions( FLG_NONE ),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -