📄 isapi20.cpp
字号:
lIgnoreHeaders.Append( (DblList::type)
PI_NEW( PIString( tTokens.GetToken( i ) ) ) );
};
}
else if ( !PIUtil_stricmp( KEY_CONF_EXTRAHEADERS, pVariable ) )
{
if ( !PIUtil_stricmp( VALUE_NO, pValue ) )
{ iExtraHeaders = 0; };
}
else if ( !PIUtil_stricmp( KEY_CONF_VARIABLE, pVariable ) )
{
const char *pK;
const char *pV;
StringTokenizer tTokens( (const char *)DeQuote(pValue), "=" );
if (tTokens.NumTokens() < 2)
{
os << "Invalid Variable '" << pValue <<
"'" << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
}
pK = tTokens.GetToken( 0 );
pV = tTokens.GetToken( 1 );
Pi3String *pError = Pi3String_new( 0 );
Pi3Expression *pExpr = Pi3Expression_new( pV, aFunctions,
pError );
if ( !pExpr )
{
os << Pi3String_getPtr( pError ) << ends;
Pi3String_delete( pError );
CONFIG_ERR( Object(), os.str() );
return 0;
};
Pi3String_delete( pError );
PIDB_add( pTypes, PIDBTYPE_OPAQUE, pK, (void *)pExpr, 0 );
}
else
{
os << "Unknown directive '" << pVariable <<
"'" << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
return 1;
};
/* ---
Callback function for Pi3Expression parameter %a
--- */
static int f_a( PIHTTP *pPIHTTP, void *pData, char *pszBuffer, int iLength )
{
(void)pPIHTTP;
ISAPIContext &tData = *( (ISAPIContext *)pData );
assert( pszBuffer );
PIDB *pQ = pPIHTTP->pRequestDB;
int i = 0;
/* --- loop over all RFC822 headers in request block --- */
PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
if ( !pIter ) { return 0; }
const char *pKey;
const char *pValue;
for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
{
pValue = (const char *)PIDBIterator_current( pIter, &pKey );
assert( pKey && pValue );
if ( !pKey || !pValue ) { /* sanity */ continue; };
if (tData.pISAPI20->checkIgnoreList(pKey)) continue;
void *fnEnv = PIDB_lookup( tData.pISAPI20->pTypes, PIDBTYPE_OPAQUE, pKey, 0 );
if ( fnEnv ) { continue; };
int iVarLen = strlen( pKey );
int iVarPos = tData.pISAPI20->sExtraHeadersPrefix.Len();
int iValSize = strlen( pValue );
// keep space for ': \r\n\0'
if ( (i+iVarPos+iVarLen+iValSize+5) < iLength )
{
memcpy( &(pszBuffer[i]), tData.pISAPI20->sExtraHeadersPrefix, iVarPos );
i += iVarPos;
for( int j=0; j<iVarLen; j++, i++ )
{
if ( isalnum( pKey[j] ) )
{ pszBuffer[i]=toupper(pKey[j]); }
else
{ pszBuffer[i]='_'; };
};
pszBuffer[i++] = ':';
pszBuffer[i++] = ' ';
memcpy( &(pszBuffer[i]), pValue, iValSize ); i+=iValSize;
pszBuffer[i++] = '\r';
pszBuffer[i++] = '\n';
}
else
{
PIDBIterator_delete( pIter );
::SetLastError( ERROR_INSUFFICIENT_BUFFER );
return 1024;
};
};
PIDBIterator_delete( pIter );
pszBuffer[i] = 0;
return i;
};
/* ---
Callback function for Pi3Expression parameter %l
--- */
static int f_l( PIHTTP *pPIHTTP, void *pData, char *pszBuffer, int iLength )
{
(void)pPIHTTP;
ISAPIContext &tData = *( (ISAPIContext *)pData );
assert( pszBuffer );
*((DWORD *)pszBuffer) = tData.cbTotalBytes;
pszBuffer[sizeof(DWORD)] = 0;
return sizeof(DWORD);
}
public:
ISAPI20( PIObject *pObject, int iArgc, const char *ppArgv[] )
: HandlerBaseISAPI( pObject ),
pTypes( PIDB_new( 0, "Types" ) ),
iExtraHeaders( 1 ),
dwPlatform( initVersion() )
{
/* --- clear out callback functions --- */
memset( aFunctions, 0, sizeof( FnPi3Write ) * 256 );
aFunctions['a'] = f_a;
aFunctions['l'] = f_l;
ReadParameters( iArgc, ppArgv );
};
virtual ~ISAPI20()
{
PIDB_delete( pTypes );
for( DblListIterator i( lIgnoreHeaders ); !i.BadIndex(); i++ )
{ PI_DELETE( (PIString *)i.Current() ); };
};
/* ---
The real stuff
--- */
int RunISAPI( PIHTTP *pPIHTTP, PFN_HTTPEXTENSIONPROC fnHttpExtensionProc,
const char *pPath )
{
assert( pPIHTTP );
/* ---
Create new ISAPI context
--- */
ISAPIContext tContext( this, pPIHTTP );
/* ---
Read in stdin (if any)
--- */
if ( tContext.cbTotalBytes )
{
/* ---
See how much we can read on the first pass and leave the
extension for call ReadClient() for the rest
--- */
int iRead = 0;
const char *pBuffer = PIIOBuffer_read( pPIHTTP->pBuffer,
&iRead );
if ( !pBuffer || !iRead )
{
/* ---
This is an error
--- */
HTTPCore_logError( pPIHTTP, "ISAPI20: Could not read client \
data (%ld bytes) for ISAPI DLL '%s'.", (long)tContext.cbTotalBytes, pPath );
return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
};
/* ---
Allocate a buffer and put data in it, buffer size will be
no more that internal buffer in PIIOBuffer object.
(usually between 4 and 16 K).
--- */
tContext.lpbData = (LPBYTE)PIHTTP_allocMem( pPIHTTP, iRead );
memcpy( tContext.lpbData, pBuffer, iRead );
tContext.cbAvailable = iRead;
};
/* ---
Change impersonation level (for ASP on WinNT)
--- */
if (dwPlatform == VER_PLATFORM_WIN32_NT) ImpersonateSelf(SecurityImpersonation);
/* ---
Fire off extension
--- */
int iRet = (fnHttpExtensionProc)( &tContext );
/* ---
Check for error message
--- */
if ( tContext.lpszLogData && *(tContext.lpszLogData) )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI dll with path '%s' \
logged an error message: ________________________________________________________________________________\n%s\n________________________________________________________________________________", pPath, tContext.lpszLogData );
};
pPIHTTP->iStatus = tContext.dwHttpStatusCode;
switch( iRet )
{
case HSE_STATUS_SUCCESS:
/*
** Assume Content-Length could not be set, disable
** keep open
*/
PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE,
KEY_INT_KEEPOPEN, 0, 0 );
break;
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
/*
** OK
*/
break;
case HSE_STATUS_PENDING:
/*
** We must wait until this asynchronous extension
** has finished
*/
if ((tContext.isFinished() == PIAPI_ERROR) && HTTPCore_debugEnabled())
{
/*
** The asynchronous extension was timed out
*/
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' will be unloaded, wait for semaphore failed with error code %d",
pPath, PIPlatform_getLastError());
tContext.iRc = PIAPI_ERROR;
break;
}
else
{
switch( tContext.iRc )
{
case 0:
case HSE_STATUS_SUCCESS:
/*
** Assume Content-Length could not be set, disable
** keep open
*/
PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE,
KEY_INT_KEEPOPEN, 0, 0 );
tContext.iRc = PIAPI_COMPLETED;
break;
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
/*
** OK
*/
tContext.iRc = PIAPI_COMPLETED;
break;
case HSE_STATUS_PENDING:
/*
** This is a heavy error, because even an asynchronous
** extension must be finished here
*/
if ( HTTPCore_debugEnabled() )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' returned illegal status code HSE_STATUS_PENDING.", pPath );
};
tContext.iRc = PIAPI_ERROR;
break;
case HSE_STATUS_ERROR:
if ( HTTPCore_debugEnabled() )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned HSE_STATUS_ERROR.", pPath );
};
tContext.iRc = PIAPI_COMPLETED;
break;
default:
if ( HTTPCore_debugEnabled() )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension \
with path '%s' returned HSE_STATUS_ERROR or an unknown return code of %d.",
pPath, tContext.iRc );
};
tContext.iRc = PIAPI_COMPLETED;
};
};
break;
case HSE_STATUS_ERROR:
if ( HTTPCore_debugEnabled() )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned HSE_STATUS_ERROR.", pPath );
};
break;
default:
if ( HTTPCore_debugEnabled() )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: ISAPI extension with path \
'%s' returned an unknown return code of %d.", pPath, iRet );
};
};
return tContext.iRc;
};
/* ---
The real stuff
--- */
int DoISAPI( PIDLL *pDLL, const char *pPath, PIHTTP *pPIHTTP )
{
assert( pDLL );
PFN_GETEXTENSIONVERSION fnGetVersion = (PFN_GETEXTENSIONVERSION)
PIDLL_getAddress( pDLL, "GetExtensionVersion" );
if ( !fnGetVersion )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: Could not load function \
'GetExtensionVersion' from ISAPI DLL '%s'.", pPath );
return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
};
PFN_HTTPEXTENSIONPROC fnHttpExtensionProc = (PFN_HTTPEXTENSIONPROC)
PIDLL_getAddress( pDLL, "HttpExtensionProc" );
if ( !fnHttpExtensionProc )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: Could not load function \
'HttpExtensionProc' from ISAPI DLL '%s'.", pPath );
return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
};
PFN_TERMINATEEXTENSION fnTerminateExtension = (PFN_TERMINATEEXTENSION)
PIDLL_getAddress( pDLL, "TerminateExtension" );
/* ---
No check, fnTerminateExtension is optional
--- */
/* ---
Do GetExtensionVersion
--- */
HSE_VERSION_INFO tInfo;
if ( !( (fnGetVersion)( &tInfo ) ) )
{
HTTPCore_logError( pPIHTTP, "ISAPI20: Call to \
'GetExtensionVersion' failed for ISAPI DLL '%s'. Win32 Error code is %d.",
pPath , ::GetLastError() );
return HTTPUtil_doHTTPError( pPIHTTP, ST_INTERNALERROR );
};
/* ---
OK do the DLL processing
--- */
int iRet = RunISAPI( pPIHTTP, fnHttpExtensionProc, pPath );
/* ---
Unload DLL
--- */
if ( fnTerminateExtension )
{
(fnTerminateExtension)(HSE_TERM_MUST_UNLOAD);
};
return iRet;
};
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
{
if ( iPhase!=PH_HANDLE )
{ return PIAPI_ERROR; };
PIDB *pR = tPIHTTP.pResponseDB;
PIDB *pQ = tPIHTTP.pRequestDB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -