#include "CPlugInList.h"
#include "CServerPlugin.h"
#include "CLauncher.h"
#include "DSUtils.h"
#include "PrivateTypes.h"
#include "SharedConsts.h"
#include "CPluginConfig.h"
#include "CLog.h"
#include "CNodeList.h"
#include "CLDAPPlugInPrefs.h"
#include "DSLDAPUtils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
extern CFRunLoopRef gPluginRunLoop;
extern DSMutexSemaphore *gKerberosMutex;
extern CPluginConfig *gPluginConfig;
extern DSMutexSemaphore *gLazyPluginLoadingLock;
extern CPlugInList *gPlugins;
extern CNodeList *gNodeList;
UInt32 gMaxLazyLoaders = 20;
char* gLazyLoadAttemptedList[20] = {nil};
CPlugInList::CPlugInList ( void ) : fMutex("CPlugInList::fMutex")
{
fPICount = 0;
fTable = nil;
fTableTail = nil;
fCFRecordTypeRestrictions = NULL;
}
CPlugInList::~CPlugInList ( void )
{
}
SInt32 CPlugInList::AddPlugIn ( const char *inName,
const char *inVersion,
const char *inConfigAvail,
const char *inConfigFile,
eDSPluginLevel inLevel,
FourCharCode inKey,
CServerPlugin *inPluginPtr,
CFPlugInRef inPluginRef,
CFUUIDRef inCFuuidFactory,
UInt32 inULVers )
{
SInt32 siResult = eDSInvalidPlugInConfigData;
sTableData *aTableEntry = nil;
if ( inName == nil )
{
return( eDSNullParameter );
}
ePluginState pluginState = gPluginConfig->GetPluginState( inName );
fMutex.WaitLock();
try
{
aTableEntry = (sTableData *)calloc(1, sizeof(sTableData));
if (fTableTail != nil)
{
fTableTail->pNext = aTableEntry;
fTableTail = aTableEntry;
}
else
{
fTable = aTableEntry;
fTableTail = aTableEntry;
}
fTableTail->pNext = nil;
fTableTail->fName = inName;
fTableTail->fVersion = inVersion;
fTableTail->fConfigAvail = inConfigAvail;
fTableTail->fConfigFile = inConfigFile;
fTableTail->fPluginPtr = inPluginPtr;
fTableTail->fValidDataStamp = 0;
fTableTail->fLevel = inLevel;
if ( inPluginRef )
{
fTableTail->fPluginRef = inPluginRef;
CFRetain( fTableTail->fPluginRef );
}
if ( inCFuuidFactory )
{
fTableTail->fCFuuidFactory = inCFuuidFactory;
CFRetain( fTableTail->fCFuuidFactory );
}
if ( inULVers )
fTableTail->fULVers = inULVers;
fTableTail->fKey = inKey;
fTableTail->fState = pluginState | kUninitialized;
fPICount++;
siResult = eDSNoErr;
}
catch( SInt32 err )
{
siResult = err;
}
fMutex.SignalLock();
return( siResult );
}
void CPlugInList::LoadPlugin( sTableData *inTableEntry )
{
bool done = false;
SInt32 siResult = eDSNoErr;
UInt32 uiCntr = 0;
UInt32 uiAttempts = 100;
UInt32 uiWaitTime = 1;
sHeader aHeader;
CServerPlugin *ourPluginPtr= nil;
UInt32 listCount = 0;
gLazyPluginLoadingLock->WaitLock();
while( (gLazyLoadAttemptedList[listCount] != nil) && (listCount < gMaxLazyLoaders) )
{
if (strcmp(gLazyLoadAttemptedList[listCount],inTableEntry->fName) == 0)
{
gLazyPluginLoadingLock->SignalLock();
return;
}
listCount++;
}
if (listCount != gMaxLazyLoaders)
{
gLazyLoadAttemptedList[listCount] = strdup(inTableEntry->fName);
}
try
{
if ( inTableEntry->fPluginPtr == nil)
{
inTableEntry->fPluginPtr = new CServerPlugin( inTableEntry->fPluginRef, inTableEntry->fCFuuidFactory, inTableEntry->fKey, inTableEntry->fULVers, inTableEntry->fName );
ourPluginPtr = (CServerPlugin *)inTableEntry->fPluginPtr;
if ( ourPluginPtr == NULL ) throw( (SInt32)eMemoryError );
ourPluginPtr->Validate( inTableEntry->fVersion, inTableEntry->fKey );
while ( !done )
{
uiCntr++;
siResult = ourPluginPtr->Initialize();
if ( ( siResult != eDSNoErr ) && ( uiCntr == 1 ) )
{
ErrLog( kLogApplication, "Attempt #%l to initialize plug-in %s failed.\n Will retry initialization at most 100 times every %l second.", uiCntr, ourPluginPtr->GetPluginName(), uiWaitTime );
}
if ( siResult == eDSNoErr )
{
DbgLog( kLogApplication, "Initialization of plug-in %s succeeded with #%l attempt.", ourPluginPtr->GetPluginName(), uiCntr );
inTableEntry->fState = kInitialized | kInactive;
if (gPluginRunLoop != NULL)
{
aHeader.fType = kServerRunLoop;
aHeader.fResult = eDSNoErr;
aHeader.fContextData = (void *)gPluginRunLoop;
siResult = ourPluginPtr->ProcessRequest( (void*)&aHeader ); }
if (gKerberosMutex != NULL)
{
aHeader.fType = kKerberosMutex;
aHeader.fResult = eDSNoErr;
aHeader.fContextData = (void *)gKerberosMutex;
ourPluginPtr->ProcessRequest( (void*)&aHeader ); }
done = true;
}
if ( !done )
{
if ( uiCntr == uiAttempts )
{
ErrLog( kLogApplication, "%l attempts to initialize plug-in %s failed.\n Setting plug-in state to inactive.", uiCntr, ourPluginPtr->GetPluginName() );
inTableEntry->fState = kInactive | kFailedToInit;
done = true;
}
else
{
fWaitToInit.WaitForEvent( uiWaitTime * kMilliSecsPerSec );
}
}
}
SrvrLog( kLogApplication, "Plugin \"%s\", Version \"%s\", loaded on demand successfully.", inTableEntry->fName, inTableEntry->fVersion );
}
}
catch( SInt32 err )
{
SrvrLog( kLogApplication, "Plugin \"%s\", Version \"%s\", failed to load on demand (%d).", inTableEntry->fName, inTableEntry->fVersion, err );
}
gLazyPluginLoadingLock->SignalLock();
}
void CPlugInList::InitPlugIns ( eDSPluginLevel inLevel )
{
sTableData *aTableEntry = nil;
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( ( aTableEntry->fLevel == inLevel) && ( ( aTableEntry->fState & kUninitialized ) || ( aTableEntry->fState == 0 ) ) )
{
if ( (aTableEntry->fName != nil) && (aTableEntry->fPluginPtr != nil) )
{
try
{
CLauncher *cpLaunch = new CLauncher( (CServerPlugin *)aTableEntry->fPluginPtr );
if ( cpLaunch != nil )
{
cpLaunch->StartThread();
}
DbgLog( kLogApplication, "Plugin \"%s\", Version \"%s\", activated successfully.", aTableEntry->fName, aTableEntry->fVersion );
}
catch( SInt32 err )
{
DbgLog( kLogApplication, "Plugin \"%s\", Version \"%s\", failed to launch initialization thread.", aTableEntry->fName, aTableEntry->fVersion );
}
}
else if ( aTableEntry->fName != nil )
{
ePluginState pluginState = gPluginConfig->GetPluginState( aTableEntry->fName );
aTableEntry->fState = pluginState | kUninitialized;
DbgLog( kLogApplication, "Plugin \"%s\", Version \"%s\", referenced to be loaded on demand successfully.", aTableEntry->fName, aTableEntry->fVersion );
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
}
SInt32 CPlugInList::IsPresent ( const char *inName )
{
SInt32 siResult = ePluginNameNotFound;
sTableData *aTableEntry = nil;
if ( inName == nil )
{
return( eDSNullParameter );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
siResult = eDSNoErr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( siResult );
}
SInt32 CPlugInList::SetState ( const char *inName, const UInt32 inState )
{
SInt32 siResult = ePluginNameNotFound;
sTableData *aTableEntry = nil;
sTableData *tmpTableEntry = nil;
UInt32 curState = kUnknownState;
sTableData *pluginEntry = NULL;
if ( inName == nil )
{
return( eDSNullParameter );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
curState = aTableEntry->fState;
if ( (inState & kActive) && aTableEntry->fPluginPtr == NULL )
tmpTableEntry = MakeTableEntryCopy( aTableEntry );
pluginEntry = aTableEntry;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
if (tmpTableEntry != nil)
{
gNodeList->Lock();
LoadPlugin( tmpTableEntry );
gNodeList->Unlock();
if (tmpTableEntry->fPluginPtr != NULL)
{
fMutex.WaitLock();
if ( pluginEntry->fPluginPtr == NULL )
pluginEntry->fPluginPtr = tmpTableEntry->fPluginPtr;
fMutex.SignalLock();
}
DSFree(tmpTableEntry);
}
CServerPlugin* pluginPtr = NULL;
fMutex.WaitLock();
if ( (curState & inState) != inState && pluginEntry != NULL && pluginEntry->fPluginPtr != NULL )
{
pluginEntry->fState = inState;
pluginPtr = pluginEntry->fPluginPtr;
siResult = eDSNoErr;
}
fMutex.SignalLock();
if ( pluginPtr )
{
pluginPtr->SetPluginState( inState );
}
return( siResult );
}
SInt32 CPlugInList::GetState ( const char *inName, UInt32 *outState )
{
SInt32 siResult = ePluginNameNotFound;
sTableData *aTableEntry = nil;
if ( inName == nil )
{
return( eDSNullParameter );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
*outState = aTableEntry->fState;
siResult = eDSNoErr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( siResult );
}
SInt32 CPlugInList::UpdateValidDataStamp ( const char *inName )
{
SInt32 siResult = ePluginNameNotFound;
sTableData *aTableEntry = nil;
if ( inName == nil )
{
return( eDSNullParameter );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
aTableEntry->fValidDataStamp++;
siResult = eDSNoErr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( siResult );
}
UInt32 CPlugInList::GetValidDataStamp ( const char *inName )
{
UInt32 outStamp = 0;
sTableData *aTableEntry = nil;
if ( inName == nil )
{
return( eDSNullParameter );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
outStamp = aTableEntry->fValidDataStamp;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( outStamp );
}
UInt32 CPlugInList::GetPlugInCount ( void )
{
return( fPICount );
}
UInt32 CPlugInList::GetActiveCount ( void )
{
UInt32 activeCount = 0;
sTableData *aTableEntry = nil;
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName == nil )
{
if ( aTableEntry->fState & kActive )
{
activeCount++;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( activeCount );
}
void CPlugInList::SetPluginState( CServerPlugin *inPluginPtr, ePluginState inPluginState )
{
if ( inPluginPtr == NULL )
return;
SInt32 siResult = inPluginPtr->SetPluginState( inPluginState );
if ( siResult == eDSNoErr )
SrvrLog( kLogApplication, "Plug-in %s state is now %s.", inPluginPtr->GetPluginName(), (inPluginState == kActive ? "active" : "inactive") );
else
SrvrLog( kLogApplication, "Unable to set %s plug-in state to %s. Received error %l.", inPluginPtr->GetPluginName(), (inPluginState == kActive ? "active" : "inactive"),
siResult );
}
CServerPlugin* CPlugInList::GetPlugInPtr ( const char *inName, bool loadIfNeeded )
{
CServerPlugin *pResult = nil;
sTableData *aTableEntry = nil;
sTableData *tmpTableEntry = nil;
ePluginState newState = kUnknownState;
if ( inName == nil )
{
return( nil );
}
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( (aTableEntry->fName != nil) )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
if ( (aTableEntry->fPluginPtr == NULL) && loadIfNeeded )
{
tmpTableEntry = MakeTableEntryCopy( aTableEntry );
break;
}
pResult = aTableEntry->fPluginPtr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
if (tmpTableEntry != nil)
{
gNodeList->Lock();
LoadPlugin( tmpTableEntry );
gNodeList->Unlock();
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( ::strcmp( aTableEntry->fName, inName ) == 0 )
{
if ( loadIfNeeded && aTableEntry->fPluginPtr == NULL )
{
aTableEntry->fPluginPtr = tmpTableEntry->fPluginPtr;
aTableEntry->fState = tmpTableEntry->fState;
if ( aTableEntry->fPluginPtr != NULL )
{
newState = gPluginConfig->GetPluginState( aTableEntry->fPluginPtr->GetPluginName() );
aTableEntry->fState = newState;
}
}
pResult = aTableEntry->fPluginPtr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
DSFree(tmpTableEntry);
if ( loadIfNeeded && pResult != NULL )
{
SetPluginState( pResult, newState );
}
}
return( pResult );
}
CServerPlugin* CPlugInList::GetPlugInPtr ( const UInt32 inKey, bool loadIfNeeded )
{
CServerPlugin *pResult = nil;
sTableData *aTableEntry = nil;
sTableData *tmpTableEntry = nil;
ePluginState newState = kUnknownState;
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( (aTableEntry->fName != nil) )
{
if ( aTableEntry->fKey == inKey )
{
if ( aTableEntry->fPluginPtr == NULL
&& (gPluginConfig->GetPluginState(aTableEntry->fName) & kActive)
&& loadIfNeeded )
{
tmpTableEntry = MakeTableEntryCopy( aTableEntry );
break;
}
pResult = aTableEntry->fPluginPtr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
if (tmpTableEntry != nil)
{
gNodeList->Lock();
LoadPlugin( tmpTableEntry );
gNodeList->Unlock();
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if ( aTableEntry->fName != nil )
{
if ( aTableEntry->fKey == inKey )
{
if ( aTableEntry->fPluginPtr == NULL
&& (gPluginConfig->GetPluginState(aTableEntry->fName) & kActive)
&& loadIfNeeded )
{
aTableEntry->fPluginPtr = tmpTableEntry->fPluginPtr;
aTableEntry->fState = tmpTableEntry->fState;
if ( aTableEntry->fPluginPtr != NULL )
{
newState = gPluginConfig->GetPluginState( aTableEntry->fPluginPtr->GetPluginName() );
aTableEntry->fState = newState;
}
}
pResult = aTableEntry->fPluginPtr;
break;
}
}
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
DSFree(tmpTableEntry);
if ( loadIfNeeded && pResult != NULL )
{
SetPluginState( pResult, newState );
}
}
return( pResult );
}
CServerPlugin* CPlugInList::Next ( UInt32 *inIndex )
{
CServerPlugin *pResult = nil;
UInt32 tableIndex = 0;
sTableData *aTableEntry = nil;
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if (tableIndex == *inIndex)
{
if ( (aTableEntry->fName != nil) && (aTableEntry->fPluginPtr != nil) )
{
pResult = aTableEntry->fPluginPtr;
tableIndex++;
break;
}
else
{
*inIndex = tableIndex + 1; }
}
tableIndex++;
aTableEntry = aTableEntry->pNext;
}
*inIndex = tableIndex;
fMutex.SignalLock();
return( pResult );
}
CPlugInList::sTableData* CPlugInList::GetPlugInInfo ( UInt32 inIndex )
{
UInt32 tableIndex = 0;
sTableData *aTableEntry = nil;
fMutex.WaitLock();
aTableEntry = fTable;
while ( aTableEntry != nil )
{
if (tableIndex == inIndex)
{
break;
}
tableIndex++;
aTableEntry = aTableEntry->pNext;
}
fMutex.SignalLock();
return( aTableEntry );
}
CFMutableDictionaryRef CPlugInList::CopyRecordTypeRestrictionsDictionary( void )
{
CFMutableDictionaryRef restrictions = NULL;
fMutex.WaitLock();
if( fCFRecordTypeRestrictions )
restrictions = CFDictionaryCreateMutableCopy( kCFAllocatorDefault, NULL, fCFRecordTypeRestrictions );
else
restrictions = CFDictionaryCreateMutable( kCFAllocatorDefault, NULL, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
fMutex.SignalLock();
return(restrictions);
}
void CPlugInList::SetRecordTypeRestrictionsDictionary( CFMutableDictionaryRef inDictionary )
{
CFURLRef configFileURL = NULL;
CFDataRef xmlData = NULL;
CFStringRef sPath = NULL;
SInt32 errorCode = 0;
SInt32 siResult = 0;
if (inDictionary != NULL)
{
fMutex.WaitLock();
DSCFRelease(fCFRecordTypeRestrictions);
CFRetain( inDictionary );
fCFRecordTypeRestrictions = inDictionary;
sPath = CFStringCreateWithCString( kCFAllocatorDefault, kRecTypeRestrictionsFilePath, kCFStringEncodingUTF8 );
if (sPath != NULL)
{
configFileURL = ::CFURLCreateWithFileSystemPath( kCFAllocatorDefault, sPath, kCFURLPOSIXPathStyle, false );
DSCFRelease( sPath );
xmlData = CFPropertyListCreateXMLData(NULL, inDictionary);
if ( (configFileURL != NULL) && (xmlData != NULL) )
{
siResult = CFURLWriteDataAndPropertiesToResource( configFileURL, xmlData, NULL, &errorCode);
if (siResult == eDSNoErr)
{
chmod( kRecTypeRestrictionsFilePath, S_IRUSR | S_IWUSR );
}
}
DSCFRelease(configFileURL);
DSCFRelease(xmlData);
}
fMutex.SignalLock();
}
}
SInt32 CPlugInList::ReadRecordTypeRestrictions( void )
{
SInt32 siResult = eDSNoErr;
CFURLRef configFileURL = NULL;
CFURLRef configFileCorruptedURL = NULL;
CFDataRef xmlData = NULL;
struct stat statResult;
bool bReadFile = false;
bool bCorruptedFile = false;
bool bWroteFile = false;
SInt32 errorCode = 0;
CFStringRef sCorruptedPath = NULL;
CFStringRef sPath = NULL;
fMutex.WaitLock();
siResult = ::stat( kRecTypeRestrictionsFilePath, &statResult );
sPath = CFStringCreateWithCString( kCFAllocatorDefault, kRecTypeRestrictionsFilePath, kCFStringEncodingUTF8 );
if (sPath != NULL)
{
configFileURL = ::CFURLCreateWithFileSystemPath( kCFAllocatorDefault, sPath, kCFURLPOSIXPathStyle, false );
DSCFRelease( sPath );
if (siResult != eDSNoErr)
{
CreatePrefDirectory();
UInt32 uiDataSize = ::strlen( kDefaultRecTypeRestrictionsConfig );
xmlData = ::CFDataCreate( nil, (const UInt8 *)kDefaultRecTypeRestrictionsConfig, uiDataSize );
DbgLog( kLogPlugin, "CPlugInList: Created a new Record Type Restrictions config file since it did not exist" );
if ( (configFileURL != NULL) && (xmlData != NULL) )
{
siResult = CFURLWriteDataAndPropertiesToResource( configFileURL,
xmlData,
NULL,
&errorCode);
}
DSCFRelease(xmlData);
}
if ( (siResult == eDSNoErr) && (configFileURL != NULL) ) {
chmod( kRecTypeRestrictionsFilePath, S_IRUSR | S_IWUSR );
bReadFile = CFURLCreateDataAndPropertiesFromResource( kCFAllocatorDefault,
configFileURL,
&xmlData, NULL,
NULL,
&siResult);
}
}
if (bReadFile)
{
CFPropertyListRef configPropertyList = NULL;
if (xmlData != nil)
{
configPropertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
xmlData,
kCFPropertyListImmutable,
NULL);
if (configPropertyList != nil )
{
if ( CFDictionaryGetTypeID() == CFGetTypeID( configPropertyList ) )
{
DSCFRelease(fCFRecordTypeRestrictions);
fCFRecordTypeRestrictions = (CFDictionaryRef) configPropertyList;
}
}
}
if (fCFRecordTypeRestrictions == NULL)
{
DbgLog( kLogPlugin, "CPlugInList: Record Type Restrictions config file is corrupted" );
bCorruptedFile = true;
sCorruptedPath = ::CFStringCreateWithCString( kCFAllocatorDefault, kRecTypeRestrictionsCorruptedFilePath, kCFStringEncodingUTF8 );
if (sCorruptedPath != NULL)
{
configFileCorruptedURL = ::CFURLCreateWithFileSystemPath( kCFAllocatorDefault, sCorruptedPath, kCFURLPOSIXPathStyle, false );
DSCFRelease( sCorruptedPath ); if (configFileCorruptedURL != NULL)
{
bWroteFile = CFURLWriteDataAndPropertiesToResource( configFileCorruptedURL,
xmlData,
NULL,
&errorCode);
if (bWroteFile)
{
chmod( kRecTypeRestrictionsCorruptedFilePath, S_IRUSR | S_IWUSR );
}
}
}
}
DSCFRelease(xmlData);
}
else {
DbgLog( kLogPlugin, "CPlugInList: Record Type Restrictions config file is unreadable" );
bCorruptedFile = true;
}
if (bCorruptedFile)
{
UInt32 uiDataSize = ::strlen( kDefaultRecTypeRestrictionsConfig );
xmlData = ::CFDataCreate( nil, (const UInt8 *)kDefaultRecTypeRestrictionsConfig, uiDataSize );
DbgLog( kLogPlugin, "CPlugInList: Created a new Record Type Restrictions config file since existing one was corrupted" );
DSCFRelease(fCFRecordTypeRestrictions);
fCFRecordTypeRestrictions = (CFDictionaryRef)CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
xmlData,
kCFPropertyListImmutable,
NULL);
if ( (configFileURL != NULL) && (xmlData != NULL) )
{
siResult = CFURLWriteDataAndPropertiesToResource( configFileURL,
xmlData,
NULL,
&errorCode);
if (siResult == eDSNoErr)
{
chmod( kRecTypeRestrictionsFilePath, S_IRUSR | S_IWUSR );
}
}
DSCFRelease(xmlData);
}
DSCFRelease(configFileURL);
DSCFRelease(configFileCorruptedURL);
fMutex.SignalLock();
return( siResult );
}
bool CPlugInList::CreatePrefDirectory( void )
{
int siResult = eDSNoErr;
struct stat statResult;
DbgLog( kLogPlugin, "CPlugInList: Checking for Record Type Restrictions config file:" );
DbgLog( kLogPlugin, "CPlugInList: %s", kRecTypeRestrictionsFilePath );
siResult = ::stat( kRecTypeRestrictionsFilePath, &statResult );
if (siResult != eDSNoErr)
siResult = dsCreatePrefsDirectory();
return (siResult == 0);
}
bool CPlugInList::IsOKToServiceQuery( const char *inPluginName, const char *inNodeName, const char *inRecordTypeList, UInt32 inNumberRecordTypes )
{
bool isOK = true;
if (inRecordTypeList == NULL) return(isOK);
fMutex.WaitLock();
if (fCFRecordTypeRestrictions != NULL && inPluginName != NULL)
{
CFStringRef cfPluginName = NULL;
cfPluginName = CFStringCreateWithCString( kCFAllocatorDefault, inPluginName, kCFStringEncodingUTF8 );
if ( CFDictionaryContainsKey( fCFRecordTypeRestrictions, cfPluginName ) ) {
CFDictionaryRef cfPluginRestrictions = NULL;
cfPluginRestrictions = (CFDictionaryRef)CFDictionaryGetValue( fCFRecordTypeRestrictions, cfPluginName );
if (inNodeName != NULL) {
CFStringRef cfNodeName = NULL;
cfNodeName = CFStringCreateWithCString( kCFAllocatorDefault, inNodeName, kCFStringEncodingUTF8 );
bool useRestrictions = false;
if ( CFDictionaryContainsKey( cfPluginRestrictions, cfNodeName ) ) {
useRestrictions = true;
}
else if ( CFDictionaryContainsKey( cfPluginRestrictions, CFSTR("General") ) ) {
DSCFRelease(cfNodeName);
cfNodeName = CFStringCreateWithCString( kCFAllocatorDefault, "General", kCFStringEncodingUTF8 );
useRestrictions = true;
}
if (useRestrictions)
{
CFStringRef cfRecordTypeList = NULL;
cfRecordTypeList = CFStringCreateWithCString( kCFAllocatorDefault, inRecordTypeList, kCFStringEncodingUTF8 );
CFDictionaryRef cfRestrictions = NULL;
cfRestrictions = (CFDictionaryRef)CFDictionaryGetValue( cfPluginRestrictions, cfNodeName );
if ( CFDictionaryContainsKey( cfRestrictions, CFSTR(kRTRAllowKey) ) ) {
isOK = false;
CFArrayRef cfAllowRecordTypes = NULL;
cfAllowRecordTypes = (CFArrayRef)CFDictionaryGetValue( cfRestrictions, CFSTR(kRTRAllowKey) );
CFIndex cfNumberRecordTypesInArray = CFArrayGetCount( cfAllowRecordTypes );
UInt32 countMatchesFound = 0;
for( CFIndex i = 0; i<cfNumberRecordTypesInArray; i++ )
{
CFStringRef cfRecordType = (CFStringRef)CFArrayGetValueAtIndex( cfAllowRecordTypes, i );
if (CFStringFindWithOptions(cfRecordTypeList, cfRecordType, CFRangeMake( 0, CFStringGetLength( cfRecordTypeList )), kCFCompareCaseInsensitive, NULL))
{
countMatchesFound++;
if (inNumberRecordTypes == countMatchesFound)
{
isOK = true;
break;
}
}
}
}
else if ( CFDictionaryContainsKey( cfRestrictions, CFSTR(kRTRDenyKey) ) ) {
CFArrayRef cfDenyRecordTypes = NULL;
cfDenyRecordTypes = (CFArrayRef)CFDictionaryGetValue( cfRestrictions, CFSTR(kRTRDenyKey) );
CFIndex cfNumberRecordTypesInArray = CFArrayGetCount( cfDenyRecordTypes );
for( CFIndex i = 0; i<cfNumberRecordTypesInArray; i++ )
{
CFStringRef cfRecordType = (CFStringRef)CFArrayGetValueAtIndex( cfDenyRecordTypes, i );
if (CFStringFindWithOptions(cfRecordTypeList, cfRecordType, CFRangeMake( 0, CFStringGetLength( cfRecordTypeList )), kCFCompareCaseInsensitive, NULL))
{
isOK = false; break;
}
}
}
DSCFRelease(cfRecordTypeList);
}
DSCFRelease(cfNodeName);
}
}
DSCFRelease(cfPluginName);
}
fMutex.SignalLock();
return(isOK);
}
CPlugInList::sTableData* CPlugInList::MakeTableEntryCopy( sTableData *inEntry )
{
sTableData* outEntry = nil;
if (inEntry == nil )
return(nil);
outEntry = (sTableData*)calloc(1, sizeof(sTableData));
outEntry->fName = inEntry->fName;
outEntry->fVersion = inEntry->fVersion;
outEntry->fConfigAvail = inEntry->fConfigAvail;
outEntry->fConfigFile = inEntry->fConfigFile;
outEntry->fPluginPtr = inEntry->fPluginPtr;
outEntry->fPluginRef = inEntry->fPluginRef;
outEntry->fCFuuidFactory = inEntry->fCFuuidFactory;
outEntry->fULVers = inEntry->fULVers;
outEntry->fKey = inEntry->fKey;
outEntry->fState = inEntry->fState;
outEntry->fValidDataStamp = inEntry->fValidDataStamp;
outEntry->pNext = nil;
return(outEntry);
}