📄 dirindex.cpp
字号:
<TD>SortDate
<TD>The sort order is determined by the file date.
<TR>
<TD>SortDscr
<TD>The sort order is determined by the annotations in the DescriptionFile.
<TR>
<TD>TagNew
<TD>All all files newer than NewThreshold are marked with NewPattern.
</TABLE>
</CENTER>
Multiple options may be listed together by seperating them using the pipe
('|') character. Whitespace will be stripped from the option pattern. Options
are matched without regard to case sensitivity. Unknown options will raise
a configuration error. The option directive may be repeated multiple times.
Phase:
HANDLE
Returns:
PIAPI_COMPLETED if a directory index was succesfully sent to the client.
PIAPI_CONTINUE if this handler done nothing. PIAPI_ERROR and PIAPI_ABORT
on generic and severe error conditions.
Note:
A sorted HTML directory indes is made by using the above sort options and
hyperlinks with special URL parameters within the table headers
<XMP>
...
<TH><A HREF="%p?SortType=A">Type</A> \
<TH><A HREF="%p?SortName=A">Name</A> \
<TH><A HREF="%p?SortSize=A">Size</A> \
<TH><A HREF="%p?SortDate=A">Last Modified</A> \
<TH><A HREF="%p?SortDscr=A">Description</A> \
...
</XMP>
The URL parameters are of the general form "SortType(Name,Size,Date,Dscr)=A(D)"
for <B>A</B>scending or <B>D</B>escending sort order.
Example:
<PRE>
<Object>
Name DirectoryIndex
Class DirectoryIndexClass
Options "Name | Size | MIMEType"
</Object>
<Object>
...
Handle DirectoryIndex
...
</Object>
</PRE>
/*___+++HTMLDOC_END+++___*/
#endif
/*____________________________________________________________________________*\
*
Class:
Description:
Parse, store and add RFC822 headers to response DB's.
\*____________________________________________________________________________*/
class RFC822Header
{
private:
const char *pFKVariable;
PIString sValue;
int iOK;
public:
RFC822Header( const char *pLine )
: pFKVariable( 0 ),
iOK( 0 )
{
if ( !pLine )
{ return; };
int iLen = strlen( pLine );
int i;
for( i=0; i<iLen && pLine[i]!=':' && !(isspace(pLine[i])); i++);
if ( !i || pLine[i]!=':' )
{ return; };
PIString sVariable( pLine, i );
for( i++; i<iLen && (isspace(pLine[i])); i++); /* scan past ws */
pFKVariable = PIDB_getFastKey( sVariable, PIDBTYPE_RFC822 );
sValue = &( pLine[i] );
iOK = 1;
};
/* --- Replace this header in DB --- */
void ReplaceHeader( PIDB *pDB )
{
assert( pDB );
assert( pFKVariable );
assert( iOK );
PIDB_replace( pDB, PIDBTYPE_RFC822, pFKVariable,
(void *)(const char *)sValue, PIDBFLAG_FASTKEY );
};
inline int IsOK()
{ return iOK; };
};
/*____________________________________________________________________________*\
*
Class:
Description:
Maps a MIME type to an image path.
\*____________________________________________________________________________*/
class MIMEIcon
{
private:
PIString sMIMEPattern;
PIString sIconPath;
public:
MIMEIcon( const char *pMIMEPattern, const char *pIconPath )
: sMIMEPattern( pMIMEPattern ), sIconPath( pIconPath )
{};
/*___
____*/
bool Matches( const PIString &sMIMEType )
{
return HTTPUtil_regexMatch(
sMIMEPattern, sMIMEPattern.Len(),
sMIMEType, sMIMEType.Len() ) ?
true : false;
};
/*___
____*/
inline const PIString &GetPath() { return sIconPath; };
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class SwapFileName
{
public:
PIString sFrom;
PIString sTo;
SwapFileName( const PIString &sTheFrom, const PIString &sTheTo )
{
DeQuote tFrom( sTheFrom );
DeQuote tTo( sTheTo );
sFrom = (const char *)tFrom;
sTo = (const char *)tTo;
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class DescriptionMap
{
public:
PIString sFileName;
PIString sDescription;
DescriptionMap( const char *pLine )
{
assert( pLine );
int iLen = strlen( pLine );
int i=0;
for( i=0; i<iLen && pLine[i]!='|'; i++ );
PIString sTmp( pLine, i );
sFileName = sTmp;
if ( i<iLen ) { i++; };
pLine= &( pLine[i] );
sDescription = pLine;
};
};
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
WriteContext for parameters and
callback functions for writing the parameters
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
/* --- helper macro to facilitate writing --- */
inline int Internal_StrMinCpy( char *pS1, const char *pS2, int iL1, int iL2 )
{
if ( !iL2 )
{ return 0; };
if ( iL1 )
{
assert( iL1>0 );
assert( pS1 );
assert( pS2 );
strncpy( pS1, pS2, (iL1<iL2) ? iL1 : iL2 );
return iL2;
};
return iL2;
};
inline void _myassert( void *pVoid )
{ assert( pVoid ); };
#define FUNCTION(fn,record) \
static int (fn)( PIHTTP *, void *pData, char *pszBuffer, int iLength ) { \
_myassert( pData ); \
return Internal_StrMinCpy( \
pszBuffer, \
((WriteContext *)pData)->record.pField, \
iLength, \
((WriteContext *)pData)->record.iLength ); }
class WriteContext
{
public:
WriteContext()
{
memset( this, 0, sizeof( WriteContext ) );
};
class Record {
public:
int iLength;
const char *pField;
};
Record tAltName;
Record tIsDirectory;
Record tMedia;
Record tDescription;
Record tLastModifiedDate;
Record tName;
Record tIcon;
Record tDirectory;
Record tRelativePath;
Record tSize;
Record tTagNew;
Record tDirSize;
Record tDirCount;
};
FUNCTION( f_a, tAltName );
FUNCTION( f_b, tIsDirectory );
FUNCTION( f_c, tMedia );
FUNCTION( f_d, tDescription );
FUNCTION( f_i, tIcon );
FUNCTION( f_l, tLastModifiedDate );
FUNCTION( f_n, tName );
FUNCTION( f_p, tDirectory );
FUNCTION( f_r, tRelativePath );
FUNCTION( f_s, tSize );
FUNCTION( f_m, tTagNew );
FUNCTION( f_S, tDirSize );
FUNCTION( f_N, tDirCount );
/*____________________________________________________________________________*\
*
Description:
Create a map of FnPi3Write functions for parameters to expressions
\*____________________________________________________________________________*/
static FnPi3Write aFunctions[256] =
{
/*
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 .. 15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 .. 31 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 .. 47 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 48 .. 63 */
/* A B C D E F G H I J K L M N O */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, f_N,0,/* 64 .. 79 */
/* Q R S T U V W X Y Z */
0, 0, 0, f_S,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 .. 95 */
/* a b c d e f g h i j k l m n o */
0,f_a,f_b,f_c,f_d, 0, 0, 0, 0,f_i, 0, 0,f_l,f_m,f_n, 0, /* 96 .. 111 */
/* q r s t u v w x y z */
f_p,0,f_r,f_s, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112 .. 127 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* .. 255 */
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
#define KEY_CONF_HEADERPATTERN "HeaderPattern"
#define KEY_CONF_HEADERFILE "HeaderFile"
#define KEY_CONF_LISTTOP "ListTop"
#define KEY_CONF_FILEPATTERN "FilePattern"
#define KEY_CONF_LISTBOTTOM "ListBottom"
#define KEY_CONF_FOOTERFILE "FooterFile"
#define KEY_CONF_FOOTERPATTERN "FooterPattern"
#define KEY_CONF_LASTMODIFIEDFORMAT "LastModifiedFormat"
#define KEY_CONF_INCLUDE "Include"
#define KEY_CONF_EXCLUDE "Exclude"
#define KEY_CONF_DESCRIPTIONFILE "DescriptionFile"
#define KEY_CONF_MIMEICON "MIMEIcon"
#define KEY_CONF_HTTPEQUIV "HTTPEquiv"
#define KEY_CONF_SWAPFILENAME "SwapFileName"
#define KEY_CONF_OPTIONS "Options"
#define KEY_CONF_DESCRIPTIONFILE "DescriptionFile"
#define KEY_CONF_NEWPATTERN "NewPattern"
#define KEY_CONF_NEWTHRESHOLD "NewTreshold"
/*____________________________________________________________________________*\
*
Flags and Options
\*____________________________________________________________________________*/
#define FLG_NONE 0x00000000
#define FLG_NAME 0x00000001
#define FLG_ALTNAME 0x00000002
#define FLG_ICON 0x00000004
#define FLG_SIZE 0x00000008
#define FLG_MIMETYPE 0x00000010
#define FLG_RELPATH 0x00000020
#define FLG_MODDATE 0x00000040
#define FLG_ABBREVSIZE 0x00000080
#define FLG_FORMATSIZE 0x00000100
#define FLG_SORTCASE 0x00000200
#define FLG_SORTDESC 0x00000400
#define FLG_SORTTYPE 0x00000800
#define FLG_SORTNAME 0x00001000
#define FLG_SORTSIZE 0x00002000
#define FLG_SORTDATE 0x00004000
#define FLG_SORTDSCR 0x00008000
#define FLG_TAGNEW 0x00010000
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
Map these flags to names
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
struct {
const char *pName;
int iFlag;
} aFlagMap[] =
{
{ "Name", FLG_NAME },
{ "AltName", FLG_ALTNAME },
{ "Icon", FLG_ICON },
{ "Size", FLG_SIZE },
{ "MIMEType", FLG_MIMETYPE },
{ "RelPath", FLG_RELPATH },
{ "AbbrevSize", FLG_ABBREVSIZE },
{ "FormatSize", FLG_FORMATSIZE },
{ "SortCase", FLG_SORTCASE },
{ "SortDesc", FLG_SORTDESC },
{ "SortType", FLG_SORTTYPE },
{ "SortName", FLG_SORTNAME },
{ "SortSize", FLG_SORTSIZE },
{ "SortDate", FLG_SORTDATE },
{ "SortDscr", FLG_SORTDSCR },
{ "TagNew", FLG_TAGNEW },
/* ---
end of change
--- */
/* --- leave this last always --- */
{ 0, 0 }
};
#define KEY_SORT_TYPE "SortType"
#define KEY_SORT_NAME "SortName"
#define KEY_SORT_SIZE "SortSize"
#define KEY_SORT_DATE "SortDate"
#define KEY_SORT_DESC "SortDscr"
#define SORT_KEY_LEN 8
#define SORT_NONE 0
#define SORT_TYPE 1
#define SORT_NAME 2
#define SORT_SIZE 3
#define SORT_DATE 4
#define SORT_DESC 5
#define MAX_FILESORT_ARRAY 2048
/*____________________________________________________________________________*\
*
Class:
Description:
Helper function, compare two keys of type PIFInfo * by directory name.
Trick: Result is emphasized by 2 --> 0 no directory | >0 compare test
\*____________________________________________________________________________*/
int cmpDirs( PIFInfo *arg1, PIFInfo *arg2 ) {
if ( PIFInfo_isDirectory(arg1) ) {
// the parent dir has always the lowest weight
if ( !strcmp( PIFInfo_getName(arg1), "..\0" )) return 1;
if ( PIFInfo_isDirectory(arg2) ) {
// the parent dir has always the lowest weight
// but here it's the 2nd compare parameter
if ( !strcmp( PIFInfo_getName(arg2), "..\0" )) return 3;
// both directories --> equal weight
return 0;
};
// default case if only a1 is dir
return 1;
} else {
// default case if only a2 is dir
if ( PIFInfo_isDirectory(arg2) ) return 3;
// both are files --> equal weight
return 0;
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
Compare two keys of type PIFInfo * by name.
\*____________________________________________________________________________*/
int cmpName( PIFInfo *arg1, PIFInfo *arg2, PIDB *pDB, int bDescending, int bCaseSensitive ) {
if (arg1 == arg2) return 0;
// directories are always on top
int result = cmpDirs( arg1, arg2 );
if ( result ) {
result -= 2;
} else {
// case sensitivity
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 type.
\*____________________________________________________________________________*/
int cmpType( PIFInfo *arg1, PIFInfo *arg2, PIDB *pDB, int bDescending, int bCaseSensitive ) {
// directories are always top level
int result = cmpDirs( arg1, arg2 );
if ( result ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -