#include <sys/stat.h> // for file and dir stat calls
#include <syslog.h> // for syslog()
#include <CoreFoundation/CFDictionary.h>
#include "CPluginConfig.h"
#include "CServerPlugin.h"
#include "CPluginList.h"
#include "ServerControl.h"
#include "CFile.h"
#include "CLog.h"
extern bool gServerOS;
extern uInt32 gRefCountWarningLimit;
extern uInt32 gDelayFailedLocalAuthReturnsDeltaInSeconds;
extern uInt32 gMaxHandlerThreadCount;
CPluginConfig::CPluginConfig ( void )
{
fPlistRef = nil;
fDictRef = nil;
}
CPluginConfig::~CPluginConfig()
{
if ( fPlistRef != nil )
{
::CFRelease( fPlistRef );
fPlistRef = nil;
}
}
sInt32 CPluginConfig::Initialize ( void )
{
bool bSuccess = false;
int iResult = 0;
uInt32 uiDataSize = 0;
char *pData = nil;
CFile *pFile = nil;
struct stat statbuf;
CFDataRef dataRef = nil;
CFStringRef keyStrRef = nil;
unsigned char cfNumBool = false;
CFNumberRef cfNumber = 0;
try
{
iResult = ::stat( kConfigFilePath, &statbuf );
if ( iResult == 0 )
{
pFile = new CFile( kConfigFilePath );
if ( pFile != nil )
{
if ( (pFile->is_open()) && (pFile->FileSize() > 0) )
{
pData = (char *)::malloc( pFile->FileSize() + 1 );
if ( pData != nil )
{
uiDataSize = pFile->ReadBlock( pData, pFile->FileSize() );
dataRef = ::CFDataCreate( nil, (const uInt8 *)pData, uiDataSize );
if ( dataRef != nil )
{
fPlistRef = ::CFPropertyListCreateFromXMLData( kCFAllocatorDefault, dataRef, kCFPropertyListMutableContainersAndLeaves, nil );
if ( fPlistRef != nil )
{
if ( ::CFDictionaryGetTypeID() == ::CFGetTypeID( fPlistRef ) )
{
fDictRef = (CFMutableDictionaryRef)fPlistRef;
bSuccess = true;
}
}
CFRelease( dataRef );
dataRef = nil;
}
free( pData );
pData = nil;
}
}
delete( pFile );
pFile = nil;
}
}
if ( bSuccess == true && fDictRef != NULL )
{
CFStringRef configVersion = (CFStringRef)CFDictionaryGetValue( fDictRef, CFSTR(kVersionKey) );
if ( configVersion == NULL )
{
CFRelease( fDictRef );
fDictRef = NULL;
bSuccess = false;
SRVRLOG( kLogApplication, "Plugin configuration file has no version, resetting to current defaults." );
}
else
{
Boolean bUpgradedConfigVersion = false;
CFRetain( configVersion );
if ( CFStringCompare( configVersion, CFSTR("1.1"), kCFCompareNumerically ) == kCFCompareLessThan )
{
CFDictionarySetValue( fDictRef, CFSTR(kVersionKey), CFSTR("1.1") );
CFDictionarySetValue( fDictRef, CFSTR(kAppleTalkPluginKey), CFSTR(kActiveValue) );
bUpgradedConfigVersion = true;
SRVRLOG( kLogApplication, "Plugin configuration file upgraded to 1.1, AppleTalk plugin now Active." );
}
if ( bUpgradedConfigVersion == true )
{
SaveConfigData();
}
CFRelease( configVersion ); }
}
if ( bSuccess == false )
{
iResult = ::stat( kJaguarUpdateFilePath, &statbuf );
if (gServerOS)
{
if (iResult == 0)
{
uiDataSize = ::strlen( kServerDefaultUpgradeConfig );
dataRef = ::CFDataCreate( nil, (const uInt8 *)kServerDefaultUpgradeConfig, uiDataSize );
}
else
{
uiDataSize = ::strlen( kServerDefaultConfig );
dataRef = ::CFDataCreate( nil, (const uInt8 *)kServerDefaultConfig, uiDataSize );
}
}
else
{
if (iResult == 0)
{
uiDataSize = ::strlen( kDefaultUpgradeConfig );
dataRef = ::CFDataCreate( nil, (const uInt8 *)kDefaultUpgradeConfig, uiDataSize );
}
else
{
uiDataSize = ::strlen( kDefaultConfig );
dataRef = ::CFDataCreate( nil, (const uInt8 *)kDefaultConfig, uiDataSize );
}
}
if ( dataRef != nil )
{
fPlistRef = (CFMutableDictionaryRef)::CFPropertyListCreateFromXMLData( kCFAllocatorDefault, dataRef, kCFPropertyListMutableContainersAndLeaves, nil );
if ( fPlistRef != nil )
{
if ( ::CFDictionaryGetTypeID() == ::CFGetTypeID( fPlistRef ) )
{
fDictRef = (CFMutableDictionaryRef)fPlistRef;
CFStringRef keyStrRef = nil;
keyStrRef = ::CFStringCreateWithCString( kCFAllocatorDefault, "Active Directory", kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
bool bFound = false;
bFound =::CFDictionaryContainsKey( fDictRef, keyStrRef );
if ( bFound == false )
{
::CFDictionarySetValue( fDictRef, keyStrRef, CFSTR( kInactiveValue ) );
SaveConfigData();
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
bSuccess = true;
SaveConfigData();
}
}
CFRelease( dataRef );
dataRef = nil;
}
}
if (fDictRef != nil)
{
keyStrRef = ::CFStringCreateWithCString( NULL, kTooManyReferencesWarningCount, kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
if ( CFDictionaryContainsKey( fDictRef, keyStrRef ) )
{
cfNumber = (CFNumberRef)CFDictionaryGetValue( fDictRef, keyStrRef );
if ( cfNumber != nil )
{
cfNumBool = CFNumberGetValue(cfNumber, kCFNumberIntType, &gRefCountWarningLimit);
}
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
keyStrRef = ::CFStringCreateWithCString( NULL, kDelayFailedLocalAuthReturnsDeltaInSeconds, kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
if ( CFDictionaryContainsKey( fDictRef, keyStrRef ) )
{
cfNumber = (CFNumberRef)CFDictionaryGetValue( fDictRef, keyStrRef );
if ( cfNumber != nil )
{
cfNumBool = CFNumberGetValue(cfNumber, kCFNumberIntType, &gDelayFailedLocalAuthReturnsDeltaInSeconds);
}
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
keyStrRef = ::CFStringCreateWithCString( NULL, kMaxHandlerThreadCount, kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
if ( CFDictionaryContainsKey( fDictRef, keyStrRef ) )
{
cfNumber = (CFNumberRef)CFDictionaryGetValue( fDictRef, keyStrRef );
if ( cfNumber != nil )
{
cfNumBool = CFNumberGetValue(cfNumber, kCFNumberIntType, &gMaxHandlerThreadCount);
if (gMaxHandlerThreadCount < kMaxHandlerThreads)
{
gMaxHandlerThreadCount = kMaxHandlerThreads;
syslog(LOG_ALERT,"Maximum handler thread count cannot be set less than %u", kMaxHandlerThreads);
}
else if (gMaxHandlerThreadCount > 256)
{
gMaxHandlerThreadCount = kMaxHandlerThreads;
syslog(LOG_ALERT,"Maximum handler thread count cannot be set greater than 256 so resetting to default of %u", kMaxHandlerThreads);
}
}
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
}
}
catch ( ... )
{
}
return( noErr );
}
ePluginState CPluginConfig::GetPluginState ( const char *inPluginName )
{
ePluginState epsResult = kActive; bool bFound = false;
CFStringRef cfStringRef = nil;
char *pValue = nil;
CFStringRef keyStrRef = nil;
if ( (fDictRef != nil) && (inPluginName != nil) )
{
keyStrRef = ::CFStringCreateWithCString( NULL, inPluginName, kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
bFound = ::CFDictionaryContainsKey( fDictRef, keyStrRef );
if ( bFound == true )
{
cfStringRef = (CFStringRef)::CFDictionaryGetValue( fDictRef, keyStrRef );
if ( cfStringRef != nil )
{
if ( ::CFGetTypeID( cfStringRef ) == ::CFStringGetTypeID() )
{
pValue = (char *)::CFStringGetCStringPtr( cfStringRef, kCFStringEncodingMacRoman );
if ( pValue != nil )
{
if ( ::strcmp( pValue, kInactiveValue ) == 0 )
{
epsResult = kInactive;
}
}
}
}
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
}
return( epsResult );
}
sInt32 CPluginConfig::SetPluginState ( const char *inPluginName, const ePluginState inPluginState )
{
CFStringRef keyStrRef = nil;
if ( (fDictRef != nil) && (inPluginName != nil) )
{
CServerPlugin* plugin = gPlugins->GetPlugInPtr( inPluginName, false );
if ( plugin )
plugin->SetPluginState( inPluginState );
keyStrRef = ::CFStringCreateWithCString( NULL, inPluginName, kCFStringEncodingMacRoman );
if ( keyStrRef != nil )
{
if ( inPluginState == kActive )
{
::CFDictionarySetValue( fDictRef, keyStrRef, CFSTR( kActiveValue ) );
}
else if ( inPluginState == kInactive )
{
::CFDictionarySetValue( fDictRef, keyStrRef, CFSTR( kInactiveValue ) );
}
::CFRelease( keyStrRef );
keyStrRef = nil;
}
}
return( noErr );
}
sInt32 CPluginConfig::SaveConfigData ( void )
{
CFDataRef dataRef = nil;
int result = 0;;
struct stat statResult;
if ( fDictRef != nil )
{
dataRef = ::CFPropertyListCreateXMLData( NULL, fDictRef );
if ( dataRef != nil )
{
result = ::stat( kConfigFilePath, &statResult );
if (result != eDSNoErr)
{
result = ::stat( "/Library/Preferences", &statResult );
if (result != eDSNoErr)
{
::mkdir( "/Library/Preferences", 0775 );
::chmod( "/Library/Preferences", 0775 ); }
result = ::stat( "/Library/Preferences/DirectoryService", &statResult );
if (result != eDSNoErr)
{
::mkdir( "/Library/Preferences/DirectoryService", 0775 );
::chmod( "/Library/Preferences/DirectoryService", 0775 ); }
}
UInt8 *pData = (UInt8*)::calloc( CFDataGetLength(dataRef), 1 );
CFDataGetBytes( dataRef, CFRangeMake(0,CFDataGetLength(dataRef)), pData );
if ( (pData != nil) && (pData[0] != 0) )
{
try
{
CFile *pFile = new CFile( kConfigFilePath, true );
if ( pFile != nil )
{
if ( pFile->is_open() )
{
pFile->seteof( 0 );
pFile->write( pData, CFDataGetLength(dataRef) );
}
delete( pFile );
pFile = nil;
::chmod( kConfigFilePath, 0600 );
}
}
catch ( ... )
{
}
free(pData);
}
CFRelease( dataRef );
dataRef = nil;
}
}
return( noErr );
}