📄 siteroot.cpp
字号:
int iTmp;
PIDB *pR = tPIHTTP.pResponseDB;
PIDB *pQ = tPIHTTP.pRequestDB;
/*
** Verify the content length and content type for
** sanity
*/
const char *pContentLength = (const char *)
PIDB_lookup( pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
const char *pContentType = (const char *)
PIDB_lookup( pQ, PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, 0 );
int iContentLength = pContentLength ? atoi( pContentLength ) : 0;
if ( iContentLength<=0 || !pContentType ||
PIUtil_stricmp( pContentType, ADMIN_CONTENTTYPE ) )
{
HTTPCore_logError( &tPIHTTP, "%s", "SiteRoot: \
Bad body content headers or bad length or configuration file." );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/*
** Attempt to open the file
*/
PIPLATFORM_FD tFd = PIFile_open( sConfigFileTmp, "wn" );
if ( tFd == PIPLATFORM_FD_INVALID )
{
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to open configuration temporary file '%s' for writing. Perhaps the \
configuration is being updated by two administrators at the same time. \
Configuration file upload failed.",
(const char *)sConfigFileTmp );
SwallowInput( tPIHTTP.pBuffer, iContentLength );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/*
** Now read from the input buffer and write to the file
*/
for(;;)
{
iTmp = (iContentLength<FILE_BUF_SIZE) ? iContentLength :
FILE_BUF_SIZE;
iTmp = PIIOBuffer_readToBuffer( tPIHTTP.pBuffer, szFileBuf, iTmp );
switch( iTmp )
{
case 0:
case -1:
/*
** We didn't read sufficient data
*/
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to read the specificied 'Content-Length' of data from remote \
administration client. Temporary configuration file '%s' will be removed. \
Configuration file upload failed.", (const char *)sConfigFileTmp );
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
goto close_file;
default:
/* good */
break;
};
assert( iTmp>0 );
iContentLength -= iTmp;
assert( iContentLength >= 0 );
/*
** Write to the file
*/
iTmp = PIFile_write( tFd, iTmp, szFileBuf );
if ( iTmp )
{
/*
** Error
*/
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to write to temporary configuration file '%s'. File upload failed.",
(const char *)sConfigFileTmp );
SwallowInput( tPIHTTP.pBuffer, iContentLength );
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
goto close_file;
};
if ( !iContentLength )
{
iRet = PIAPI_COMPLETED;
break;
};
};
close_file:
/*
** The temporary file has been read - close it and consider
** making it the main configuration file
*/
iTmp = PIFile_close( tFd );
if ( iTmp!=PIAPI_COMPLETED )
{
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to close temporary configuration file '%s'. Configuration file upload \
failed.", (const char *)sConfigFileTmp );
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/*
** Attempt to load the new configuration
*/
PIObject *pTmpObject = 0;
if ( iRet!=INT_REDIRECT )
{
pTmpObject = LoadConfigurationFile( sConfigFileTmp, 1 );
if ( !pTmpObject )
{
/*
** An error occurred, attempt to map the configuration
** file where the error will have been written
*/
PIFInfo *pFInfo = 0;
PIFMap *pMap = 0;
const char *pFileMap = 0;
int iLen = 0;
pFInfo = PIFInfo_new( sConfigFileTmp );
pMap = pFInfo ? PIFMap_new( pFInfo ) : 0 ;
pFileMap = pMap ? (const char *)PIFMap_lock( pMap, &iLen ) : 0;
if ( pFileMap )
{
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to load new site configuration file '%s'. Detailed error information \
follows:\n%s", (const char *)sConfigFileTmp, pFileMap );
}
else
{
HTTPCore_logError( &tPIHTTP, "SiteRoot: \
Failed to load new site configuration file '%s'.",
(const char *)sConfigFileTmp );
};
if ( pMap ) { PIFMap_delete( pMap ); };
if ( pFInfo ) { PIFInfo_delete( pFInfo ); };
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
};
/*
** Send response to client?
*/
if ( iRet!=INT_REDIRECT )
{
/*
** Send HTTP response to confirm that configuration has been
** accepted
*/
/* --- start response --- */
if ( HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
{
HTTPCore_logError( &tPIHTTP, "%s", "SiteRoot: Failed to send \
response headers for admin command." );
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
};
/*
** Do we want to make this the configuration file?
*/
if ( !tPIHTTP.iStatus || (tPIHTTP.iStatus>199 && tPIHTTP.iStatus<300))
{
/*
** Make this the new configuration.
*/
iRet = remove( sConfigFile );
assert( !iRet );
iRet = rename( sConfigFileTmp, sConfigFile );
assert( !iRet );
pNewLogicObject = pTmpObject;
if ( iInSiteCount )
{
/*
** There are threads currently executing the old logic
** object: let last thread out pick up the change.
*/
assert( iInSiteCount>0 );
pTmpObject = 0;
}
else
{
/*
** There are no threads executing the current logic
** object
*/
pTmpObject = pLogicObject;
pLogicObject = pNewLogicObject;
pNewLogicObject = 0;
};
iRet = PIAPI_COMPLETED;
}
else
{
/*
** Nuke the temporary file
*/
remove( sConfigFileTmp );
};
/*
** Delete any logic objects
*/
if ( pTmpObject )
{
PIObject_delete( pTmpObject, 0, 0 );
};
/*
** Done
*/
return iRet;
};
/*
** Handle admin requests
*/
int HandleAdminRequest( int iPhase, PIHTTP &tPIHTTP,
const char *pAdminCommand )
{
/*
** Only handle the request is the current status is a
** non-error status
*/
if (tPIHTTP.iStatus && (tPIHTTP.iStatus <200 || tPIHTTP.iStatus>299))
{
/* --- this is an error let something else handle it --- */
return PIAPI_CONTINUE;
};
switch( iPhase )
{
case PH_INIT:
case PH_HEADERS:
assert( 0 );
return PIAPI_COMPLETED;
case PH_MAPPING:
/*
** Set the physical path
*/
PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_STRING,
KEY_INT_PATH, (void *)(const char *)sConfigFile, 0 );
if (sRealm.Len())
{
PIDB_replace( tPIHTTP.pResponseDB, PIDBTYPE_STRING,
KEY_INT_AUTHENTICATIONREALM, (void *)(const char *)sRealm, 0 );
}
return PIAPI_COMPLETED;
case PH_CHECKPATH:
return PIAPI_COMPLETED;
case PH_CHECKAUTH:
/*
** Do site request for this phase
*/
{
PIHTTP *pPIHTTP = &tPIHTTP;
return PILogic_execute( pLogicObject, 1, (const char **)&pPIHTTP );
}
case PH_CHECKACCESS:
case PH_CHECKTYPE:
return PIAPI_COMPLETED;
case PH_HANDLE:
break;
case PH_HOSTMAP:
case PH_LOG:
case PH_DESTROY:
return PIAPI_CONTINUE;
default:
assert( 0 );
return PIAPI_CONTINUE;
};
int iRet;
if ( !PIUtil_stricmp( pAdminCommand, KEY_ADMIN_GETCONFIG ) )
{
PISync_lock( pMutex );
iRet = SendConfigFile( tPIHTTP );
PISync_unlock( pMutex );
}
else if ( !PIUtil_stricmp( pAdminCommand, KEY_ADMIN_SAVECONFIG ) )
{
PISync_lock( pMutex );
iRet = GetConfigFile( tPIHTTP );
PISync_unlock( pMutex );
}
else
{
HTTPCore_logError( &tPIHTTP, "SiteRoot: Unknown admin command \
'%s'.", pAdminCommand );
iRet = HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
return iRet;
};
/*
** Handle requests for this site
*/
int HandleSiteRequest( int iPhase, PIHTTP &tPIHTTP )
{
again:
PISync_lock( pMutex );
if ( iPhase==PH_INIT && pNewLogicObject )
{
/*
** A new configuration is ready to be used, waiting for
** threads to stop executing objects within this
** configuration.
*/
assert( iInSiteCount>0 );
PISync_unlock( pMutex );
PIPlatform_sleep( 2000 ); /* high tech. solution */
goto again;
};
assert( pLogicObject );
iInSiteCount++;
PISync_unlock( pMutex );
/*
** Do site request for this phase
*/
PIHTTP *pPIHTTP = &tPIHTTP;
int iRet = PILogic_execute( pLogicObject, 1, (const char **)&pPIHTTP );
PIObject *pTmpObject = 0;
PISync_lock( pMutex );
iInSiteCount--;
if ( iPhase==PH_DESTROY && !iInSiteCount && pNewLogicObject )
{
/*
** No other threads are using the objects for this site.
** the new site may be used and the old one destroyed
*/
pTmpObject = pLogicObject;
pLogicObject = pNewLogicObject;
pNewLogicObject = 0;
};
PISync_unlock( pMutex );
/*
** Now we are outside the mutex we can delete the old logic
** object if a new one was copied over
*/
if ( pTmpObject )
{
PIObject_delete( pTmpObject, 0, 0 );
};
return iRet;
};
/*
** The main function
*/
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
{
int iRet;
PIDB *pQ = tPIHTTP.pRequestDB;
const char *pAdminCommand = (const char *)PIDB_lookup( pQ,
PIDBTYPE_RFC822, pFKAdminCommand, PIDBFLAG_FASTKEY );
if ( pAdminCommand && strlen(pAdminCommand) )
{
/*
** This is an admin command
*/
iRet = HandleAdminRequest( iPhase, tPIHTTP, pAdminCommand );
if (iRet == INT_REDIRECT)
{
PIDB_replace( pQ, PIDBTYPE_RFC822, pFKAdminCommand,
NULL, PIDBFLAG_FASTKEY );
}
#if 0
cout << "Admin request: " << HTTPUtil_phaseNumberToName(iPhase)
<< ", " << HTTPUtil_rcNumberToName(iRet)<< ", " << tPIHTTP.iStatus << endl;
#endif
}
else
{
iRet = HandleSiteRequest( iPhase, tPIHTTP );
#if 0
cout << "Site request: " << HTTPUtil_phaseNumberToName(iPhase)
<< ", " << HTTPUtil_rcNumberToName(iRet) << ", " << tPIHTTP.iStatus << endl;
#endif
}
return iRet;
}
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int SiteRoot_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
return HandlerBaseSR_constructor( pObj, PI_NEW( SiteRoot( pObj,
iArgc, ppArgv ) ) );
}
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name SiteRootClass
Type LogicExtension
Library SiteRoot
OnClassLoad HandlerBaseSR_onClassLoad
Constructor SiteRoot_constructor
CopyConstructor HandlerBaseSR_copyConstructor
Destructor HandlerBaseSR_destructor
Execute HandlerBaseSR_execute
</Class>
<Object>
Name SiteRoot
Class SiteRootClass
</Object>
/*___+++CNF_END+++___*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -