📄 sendssi.cpp
字号:
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "AUTH_TYPE",
Pi3Expression_new( "$x", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "CONTENT_LENGTH",
Pi3Expression_new( "$Y", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "CONTENT_TYPE",
Pi3Expression_new( "$C", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DOCUMENT_NAME",
Pi3Expression_new( "$f", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DOCUMENT_URI",
Pi3Expression_new( "$U", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS",
Pi3Expression_new( "$g", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_KEYSIZE",
Pi3Expression_new( "$K", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_SECRETKEYSIZE",
Pi3Expression_new( "$G", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTPS_CIPHERNAME",
Pi3Expression_new( "$e", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "QUERY_STRING",
Pi3Expression_new( "$q", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_ADMIN",
Pi3Expression_new( "$a", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_SOFTWARE",
Pi3Expression_new( "$S", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_NAME",
Pi3Expression_new( "$v", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_PORT",
Pi3Expression_new( "$p", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "SERVER_PROTOCOL",
Pi3Expression_new( "&dblookup(request,string,Protocol)",
0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REQUEST_METHOD",
Pi3Expression_new( "$m", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_ADDR",
Pi3Expression_new( "$A", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_HOST",
Pi3Expression_new( "$h", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_IDENT",
Pi3Expression_new( "$i", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REMOTE_USER",
Pi3Expression_new( "$u", 0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTP_ACCEPT",
Pi3Expression_new( "&dblookup(request,rfc822,Accept)",
0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "HTTP_USER_AGENT",
Pi3Expression_new( "&dblookup(request,rfc822,User-Agent)",
0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "REFERER",
Pi3Expression_new( "&dblookup(request,rfc822,Referer)",
0, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DATE_GMT",
Pi3Expression_new( "%a", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "DATE_LOCAL",
Pi3Expression_new( "%b", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "LAST_MODIFIED",
Pi3Expression_new( "%c", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "PATH_INFO",
Pi3Expression_new( "$I", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "PATH_TRANSLATED",
Pi3Expression_new( "$Z", aFunctions, pDummy ), 0 );
PIDB_add( pVariables, PIDBTYPE_OPAQUE, "ERROR_MESSAGES",
Pi3Expression_new( "&dblookup(request,string,ErrorMessage,,,&_())",
0, pDummy ), 0 );
Pi3String_delete( pDummy );
};
~SendSSI()
{
/* --- delete functions DB --- */
PIDB_delete( pFunctions );
/* --- delete variables from variables DB --- */
PIDBIterator *pIter = PIDB_getIterator( pVariables, PIDBTYPE_OPAQUE,
0, 0 );
if ( pIter )
{
for( ; PIDBIterator_atValidElement( pIter );
PIDBIterator_next( pIter ) )
{
Pi3Expression_delete(
(Pi3Expression *)PIDBIterator_current( pIter, 0 ) );
};
PIDBIterator_delete( pIter );
};
/* --- delete variables DB --- */
PIDB_delete( pVariables );
Pi3Expression_delete( pHeaderPattern );
Pi3Expression_delete( pFooterPattern );
Pi3Expression_delete( pExecFileFixup );
};
/* ---
Process a single SSI directive
Return 0 on error, 1 on success.
--- */
int ProcessSSIDirective( PIHTTP &tPIHTTP, const char *pDirective,
int iDirectiveLen, SSIParam &tParam )
{
/* --- get first word (command) in directive --- */
int i;
for( i=0; i<iDirectiveLen && !(isspace(pDirective[i])); i++);
/* --- portions of directive --- */
const char *pCommand = pDirective;
int iCommandLen = i;
const char *pVariable = 0;
int iVariableLen = 0;
const char *pValue = 0;
int iValueLen = 0;
if ( i<iDirectiveLen )
{
/* --- get variable --- */
for( ; i<iDirectiveLen && (isspace(pDirective[i])); i++);
pDirective = &( pDirective[i] ); iDirectiveLen -= i; i = 0;
pVariable = pDirective;
for( ; i<iDirectiveLen && !(isspace(pDirective[i])) &&
pDirective[i]!='='; i++);
iVariableLen = i;
/* --- get value --- */
for( ; i<iDirectiveLen && ( (isspace(pDirective[i])) ||
( pDirective[i]=='=' ) ); i++);
int iQuoted = 0;
if ( pDirective[i]=='"' ) { iQuoted = 1; i++; };
pDirective = &( pDirective[i] ); iDirectiveLen -= i; i = 0;
for( ; i<iDirectiveLen && ( !(isspace(pDirective[i])) || iQuoted )
; i++)
{
if ( pDirective[i]=='"' && iQuoted )
{ break; };
};
pValue = pDirective;
iValueLen = i;
};
/* --- get directive function and execute it --- */
PIString sCommand( pCommand, iCommandLen );
sCommand.ConvertToUpperCase();
SSIFunc tFn = (SSIFunc)PIDB_lookup( pFunctions, PIDBTYPE_OPAQUE,
sCommand, 0 );
if ( !tFn )
{
/* --- unrecognised directive --- */
PIIOBuffer_write(
tPIHTTP.pBuffer,
tParam.tConfig.sErrMsg,
tParam.tConfig.sErrMsg.Len(),
PIIOBUF_NONE );
return 0;
}
return (tFn)( *this, tPIHTTP, pVariable, iVariableLen, pValue,
iValueLen, tParam );
};
/* ---
SSI Parse the memory block pMap and send the result to the remote
client
Returns 0 on error.
--- */
int SSIParse( PIHTTP &tPIHTTP, PIFInfo *pFInfo, const char *pMap,
int iLen, int iFlags )
{
#define MIN(a,b) ((a)<(b)?(a):(b))
SSIConfig tLocalConfig( tConfig );
SSIParam tParam( pFInfo, tLocalConfig, pExecFileFixup );
for(;;)
{
/* --- find next ssi directive --- */
int i;
for( i=0; i<iLen &&
strncmp( &(pMap[i]), "<!--#", MIN(5,iLen-i) ); i++ );
/* --- send what has been parsed so far --- */
if ( i )
{
PIIOBuffer_write(
tPIHTTP.pBuffer,
pMap,
i,
iFlags );
};
if ( i==iLen ) { break; }; /* done! */
i += 5; pMap = &(pMap[i]); iLen -= i; i=0;
/* ---
this is an SSI directive
--- */
/* --- scan forward to next '-->', skipping quoted text --- */
int iQuoted = 0;
for( ; i<iLen &&
( strncmp( &(pMap[i]), "-->", MIN(3,iLen-i)) || iQuoted ); i++)
{
if ( pMap[i]=='"' ) { iQuoted = ( iQuoted ? 0 : 1 ); };
};
/* --- if EOF before '-->' write out an error --- */
if ( i==iLen )
{
PIIOBuffer_write(
tPIHTTP.pBuffer,
tParam.tConfig.sErrMsg,
tParam.tConfig.sErrMsg.Len(),
iFlags );
break;
};
/* --- process the directive, ignore errors --- */
ProcessSSIDirective( tPIHTTP, pMap, i, tParam );
/* --- skip the directive and continue --- */
i += 3; pMap = &(pMap[i]); iLen -= i;
};
return 1;
};
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
{
if ( iPhase!=PH_HANDLE )
{ return PIAPI_ERROR; };
PIDB *pR = tPIHTTP.pResponseDB;
PIDB *pQ = tPIHTTP.pRequestDB;
/* ---
Get file object
--- */
const char *pPath = (const char *)PIDB_lookup( pR, PIDBTYPE_STRING,
KEY_INT_PATH, 0 );
PIFInfo *pFInfo = HTTPCore_getCachedFile( pPath );
if ( !pFInfo )
{ return PIAPI_ERROR; };
/* ---
This file must exist and be a regular file
--- */
if ( !PIFInfo_exists( pFInfo ) ||
!PIFInfo_isRegular( pFInfo ) )
{
HTTPCore_logError( &tPIHTTP, "SendSSI: File with path '%s' \
does not exist or is not a regular file.", pPath );
HTTPCore_releaseCachedFile( pFInfo );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/* ---
memory map the file
--- */
/* --- get the file map --- */
const char *pMap = 0;
int iLen = 0;
/* --- get filemap object --- */
PIFMap *pFileMap = 0;
if ( PIFInfo_getSize( pFInfo )>0 )
{
pFileMap = PIFMap_new( pFInfo );
if ( pFileMap )
{
pMap = (const char *)PIFMap_lock( pFileMap, &iLen );
};
if ( !pFileMap || !pMap )
{
HTTPCore_logError( &tPIHTTP, "SendSSI: \
Could not memory map file with path '%s'.", pPath );
PIFMap_delete( pFileMap );
HTTPCore_releaseCachedFile( pFInfo );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
}
else
{
/* --- zero length file --- */
pMap = "";
iLen = 0;
};
/* --- set content type to 'text/html --- */
PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE,
(void *)"text/html", 0 );
/* --- dynamically generated content should not be cached --- */
PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_PRAGMA, (void *)"no-cache", 0 );
PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_EXPIRES,
(void *)"Mon, 23 Feb 1970 15:30:00 GMT", 0 );
/* --- we don't send a content-length so disable keep open --- */
PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, KEY_INT_KEEPOPEN,
(void *)0, 0 );
/* --- last modified --- */
Pi3String *pTmp = Pi3String_new( 0 );
time_t tT;
time( &tT );
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 ), 0 );
Pi3String_delete( pTmp );
/* --- If current status is 0 then change to 200 OK --- */
if ( !tPIHTTP.iStatus ) { tPIHTTP.iStatus = ST_OK; };
/* ---
Lookup method
--- */
int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD, 0 );
/* ---
Get the header
--- */
enum { PATTERN_BUF_SIZE=1024 };
char szHeader[PATTERN_BUF_SIZE];
char *pHeader = 0;
int iHeaderLen = 0;
if ( pHeaderPattern )
{
pHeader = ( iMethod==MD_GET ) ? szHeader : 0;
iHeaderLen = Pi3Expression_write( pHeaderPattern, &tPIHTTP, 0,
pHeader, PATTERN_BUF_SIZE );
if ( iHeaderLen>PATTERN_BUF_SIZE && pHeader )
{
pHeader = (char *)PIHTTP_allocMem( &tPIHTTP, iHeaderLen );
Pi3Expression_write( pHeaderPattern, &tPIHTTP, 0, pHeader,
iHeaderLen );
};
};
/* ---
Get the footer
--- */
char szFooter[PATTERN_BUF_SIZE];
char *pFooter = 0;
int iFooterLen = 0;
if ( pFooterPattern )
{
pFooter = ( iMethod==MD_GET ) ? szFooter : 0;
iFooterLen = Pi3Expression_write( pFooterPattern, &tPIHTTP, 0,
pFooter, PATTERN_BUF_SIZE );
if ( iFooterLen>PATTERN_BUF_SIZE && pFooter )
{
pFooter = (char *)PIHTTP_allocMem( &tPIHTTP, iFooterLen );
Pi3Expression_write( pFooterPattern, &tPIHTTP, 0, pFooter,
iFooterLen );
};
};
/* --- transfer-encoding --- */
int iFlags = (!PIHTTP_isChild( &tPIHTTP) && (int)PIDB_lookup( tPIHTTP.pRequestDB,
PIDBTYPE_OPAQUE, KEY_HTTP_PROTOCOL, 0 ) == 3 ) ? PIIOBUF_CHUNKED : PIIOBUF_NONE;
if ( iFlags & PIIOBUF_CHUNKED )
{
PIDB_replace( pR, PIDBTYPE_RFC822, KEY_HTTP_TRANSFERENCODING,
(void *)KEY_HTTP_CHUNKED, 0 );
}
/* --- start response --- */
int iRet =
HTTPCore_sendGeneralHeaders( &tPIHTTP ) == PIAPI_COMPLETED
&& HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) == PIAPI_COMPLETED;
if ( iRet && (iFlags & PIIOBUF_CHUNKED) ) iRet = PIIOBuffer_flush( tPIHTTP.pBuffer );
/* ---
If the Method is 'GET' return PIAPI_CONTINUE to let the
handling continue by sending the file.
Otherwise assume Method is 'HEAD' and return PIAPI_COMPLETED as
end of transaction
--- */
if (iRet)
{
switch( iMethod )
{
case MD_GET:
if ( pHeader && iHeaderLen )
{
iRet = ( PIIOBuffer_write( tPIHTTP.pBuffer, pHeader,
iHeaderLen, iFlags)>0 );
};
if ( iRet )
{
/* --- process the file, ignore errors --- */
iRet = SSIParse( tPIHTTP, pFInfo, pMap, iLen, iFlags );
};
if ( iRet && pFooter && iFooterLen )
{
iRet = ( PIIOBuffer_write( tPIHTTP.pBuffer, pFooter,
iFooterLen, iFlags)>0 );
};
break;
case MD_HEAD:
break;
default:
assert( 0 );
iRet = 0;
};
};
if ( pFileMap ) { PIFMap_delete( pFileMap ); };
HTTPCore_releaseCachedFile( pFInfo );
/* ---
If iRet is 0 an error occurred
** NOTE:
--- */
return iRet ? PIAPI_COMPLETED : PIAPI_ERROR;
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int SendSSI_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
return HandlerBaseHTTP_constructor( pObj, PI_NEW( SendSSI( pObj,
iArgc, ppArgv ) ) );
}
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name SendSSIClass
Type LogicExtension
Library HTTP
OnClassLoad HandlerBaseHTTP_onClassLoad
Constructor SendSSI_constructor
CopyConstructor HandlerBaseHTTP_copyConstructor
Destructor HandlerBaseHTTP_destructor
Execute HandlerBaseHTTP_execute
</Class>
<Object>
Name SendSSI
Class SendSSIClass
</Object>
/*___+++CNF_END+++___*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -