#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> //used for mkdir and stat
#include <syslog.h>
#include <mach/mach_time.h> // for dsTimeStamp
#include <libkern/OSAtomic.h>
#include <Security/Authorization.h>
#include "DirServices.h"
#include "DirServicesUtils.h"
#include "DirServicesConst.h"
#include "DirServicesPriv.h"
#include "SharedConsts.h"
#include "CSharedData.h"
#include "PrivateTypes.h"
#include "DSUtils.h"
#include "CAttributeList.h"
#include "CPlugInRef.h"
#include "CDataBuff.h"
#include "CRecTypeList.h"
#include "ServerControl.h"
#include "CLog.h"
#include "CAttributeList.h"
#include "CSearchPlugin.h"
#include "ServerModuleLib.h"
#include "DSUtils.h"
#include "COSUtils.h"
#include "PluginData.h"
#include "DSCThread.h"
#include "DSEventSemaphore.h"
#include "CContinue.h"
#include "GetMACAddress.h"
extern bool gServerOS;
extern CCachePlugin *gCacheNode;
uint32_t gSystemGoingToSleep = 0;
int32_t CSearchPlugin::fAuthCheckNodeThreadActive = false;
int32_t CSearchPlugin::fContactCheckNodeThreadActive = false;
DSEventSemaphore CSearchPlugin::fAuthPolicyChangeEvent;
DSEventSemaphore CSearchPlugin::fContactPolicyChangeEvent;
bool gDHCPLDAPEnabled = false;
int32_t gInitializeActive = false;
#define kDS1AttrDHCPLDAPDefault "dsAttrTypeStandard:DHCPLDAPDefault"
static CPlugInRef *gSNNodeRef = nil;
static CContinue *gSNContinue = nil;
DSEventSemaphore gKickSearchRequests;
static DSEventSemaphore gNetworkTransition;
static CSearchPlugin *gSearchNode = nil;
static void DHCPChangeNotification( SCDynamicStoreRef aSCDStore, CFArrayRef changedKeys, void *inInfo )
{
if ( inInfo != NULL && !gSystemGoingToSleep && OSAtomicCompareAndSwap32Barrier(false, true, &gInitializeActive) == true ) {
CSearchPluginHandlerThread* aSearchPluginHandlerThread = new CSearchPluginHandlerThread( DSCThread::kTSSearchPlugInHndlrThread, 2, inInfo );
if (aSearchPluginHandlerThread != NULL)
aSearchPluginHandlerThread->StartThread();
}
}
int ShouldRegisterWorkstation(void)
{
int result = 0;
if ( ( gSearchNode != nil ) && !gSystemGoingToSleep ) result = gSearchNode->fRegisterWorkstation ? 1 : -1;
return result;
}
#pragma mark -
#pragma mark Specific Search Plugin Handler Routines for Run Loop spawned jobs
#pragma mark -
CSearchPluginHandlerThread::CSearchPluginHandlerThread ( void ) : CInternalDispatchThread(kTSSearchPlugInHndlrThread)
{
fThreadSignature = kTSSearchPlugInHndlrThread;
fWhichFunction = 0;
fNeededClass = nil;
}
CSearchPluginHandlerThread::CSearchPluginHandlerThread ( const FourCharCode inThreadSignature, int inWhichFunction, void *inNeededClass ) : CInternalDispatchThread(inThreadSignature)
{
fThreadSignature = inThreadSignature;
fWhichFunction = inWhichFunction;
fNeededClass = inNeededClass;
}
CSearchPluginHandlerThread::~CSearchPluginHandlerThread()
{
}
void CSearchPluginHandlerThread::StartThread ( void )
{
if ( this == nil ) throw((SInt32)eMemoryError);
this->Resume();
}
void CSearchPluginHandlerThread:: LastChance ( void )
{
}
void CSearchPluginHandlerThread::StopThread ( void )
{
SetThreadRunState( kThreadStop );
}
SInt32 CSearchPluginHandlerThread::ThreadMain ( void )
{
CSearchPlugin *aSearchPlugin = (CSearchPlugin *) fNeededClass;
if ( aSearchPlugin != nil )
{
switch ( fWhichFunction )
{
case 1:
aSearchPlugin->CheckNodes( eDSAuthenticationSearchNodeName, &CSearchPlugin::fAuthCheckNodeThreadActive, &CSearchPlugin::fAuthPolicyChangeEvent );
break;
case 2:
aSearchPlugin->Initialize();
break;
case 3:
aSearchPlugin->CheckNodes( eDSContactsSearchNodeName, &CSearchPlugin::fContactCheckNodeThreadActive, &CSearchPlugin::fContactPolicyChangeEvent );
break;
default:
break;
}
}
StopThread();
return( 0 );
}
#pragma mark -
#pragma mark Search Plugin
#pragma mark -
CSearchPlugin::CSearchPlugin ( FourCharCode inSig, const char *inName ) : CServerPlugin(inSig, inName),
fMutex("CSearchPlugin::fMutex")
{
fDirRef = 0;
fState = kUnknownState;
pSearchConfigList = nil;
fAuthSearchPathCheck = nil;
fSomeNodeFailedToOpen = false;
if ( gSNNodeRef == nil )
{
if (gServerOS)
gSNNodeRef = new CPlugInRef( CSearchPlugin::ContextDeallocProc, 1024 );
else
gSNNodeRef = new CPlugInRef( CSearchPlugin::ContextDeallocProc, 256 );
}
if ( gSNContinue == nil )
{
if (gServerOS)
gSNContinue = new CContinue( CSearchPlugin::ContinueDeallocProc, 256 );
else
gSNContinue = new CContinue( CSearchPlugin::ContinueDeallocProc, 64 );
}
CFMutableArrayRef notifyKeys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
SCDynamicStoreContext scContext = { 0, this, NULL, NULL, NULL };
CFStringRef locationKey = SCDynamicStoreKeyCreateLocation( kCFAllocatorDefault );
if ( locationKey != NULL )
CFArrayAppendValue( notifyKeys, locationKey );
CFArrayAppendValue( notifyKeys, CFSTR(kDSStdNotifyDHCPOptionsAvailable) );
SCDynamicStoreRef store = SCDynamicStoreCreate( kCFAllocatorDefault, CFSTR("CSearchPlugin::Initialize"), DHCPChangeNotification,
&scContext );
if ( store != NULL )
{
SCDynamicStoreSetNotificationKeys( store, notifyKeys, NULL );
CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource( kCFAllocatorDefault, store, 0 );
if (rls != NULL)
{
CFRunLoopAddSource( CFRunLoopGetMain(), rls, kCFRunLoopDefaultMode );
CFRelease( rls );
}
}
DSCFRelease( locationKey );
DSCFRelease( notifyKeys );
DSCFRelease( store );
gSearchNode = this;
::dsOpenDirService( &fDirRef );
fRegisterWorkstation = false;
#if AUGMENT_RECORDS
fAugmentNodeRef = 0;
#endif
}
CSearchPlugin::~CSearchPlugin ( void )
{
sSearchConfig *pConfig = nil;
sSearchConfig *pDeleteConfig = nil;
pConfig = pSearchConfigList;
while (pConfig != nil)
{
pDeleteConfig = pConfig;
pConfig = pConfig->fNext; CleanSearchConfigData( pDeleteConfig );
free( pDeleteConfig );
pDeleteConfig = nil;
}
pSearchConfigList = nil;
if (fDirRef != 0)
{
::dsCloseDirService( fDirRef );
}
}
SInt32 CSearchPlugin::Validate ( const char *inVersionStr, const UInt32 inSignature )
{
fPlugInSignature = inSignature;
return( eDSNoErr );
}
SInt32 CSearchPlugin::PeriodicTask ( void )
{
return( eDSNoErr );
}
SInt32 CSearchPlugin::Initialize ( void )
{
SInt32 siResult = eDSNoErr;
SInt32 result = eDSNoErr;
SInt32 addLDAPResult = eSearchPathNotDefined;
tDataList *aNodeName = nil;
sSearchConfig *aSearchConfig = nil;
sSearchConfig *lastSearchConfig = nil;
UInt32 index = 0;
UInt32 aSearchConfigType = 0;
char *aSearchNodeName = nil;
char *aSearchConfigFilePrefix = nil;
sSearchList *aSearchNodeList = nil;
sSearchList *autoSearchNodeList = nil;
CConfigs *aConfigFromXML = nil;
UInt32 aSearchPolicy = 0;
eDirNodeType aDirNodeType = kUnknownNodeType;
char *authSearchPathCheck = nil;
bool bShouldNotify = fSomeNodeFailedToOpen;
bool bRegisterWorkstation = false;
try
{
siResult = ::dsVerifyDirRefNum(fDirRef);
if (siResult != eDSNoErr)
{
siResult = ::dsOpenDirService( &fDirRef );
if ( siResult != eDSNoErr ) throw( siResult );
}
for (index = 0; index < 2; index++)
{
switch( index )
{
case 0:
DbgLog( kLogPlugin, "Setting Authentication Search Node Configuraton" );
aSearchConfigType = eDSAuthenticationSearchNodeName;
aDirNodeType = kSearchNodeType;
break;
case 1:
DbgLog( kLogPlugin, "Setting Contacts Search Node Configuraton" );
aSearchConfigType = eDSContactsSearchNodeName;
aDirNodeType = kContactsSearchNodeType;
break;
}
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey(aSearchConfigType);
if (aSearchConfig != nil) {
aConfigFromXML = aSearchConfig->pConfigFromXML;
aSearchNodeName = aSearchConfig->fSearchNodeName;
aSearchConfigFilePrefix = aSearchConfig->fSearchConfigFilePrefix;
}
else
{
if (index == 0)
{
aSearchNodeName = (char *) calloc(sizeof(kstrAuthenticationNodeName) + 1, sizeof(char));
if ( aSearchNodeName != NULL )
strcpy(aSearchNodeName, kstrAuthenticationNodeName);
else
siResult = eMemoryError;
aSearchConfigFilePrefix = (char *) calloc(sizeof(kstrAuthenticationConfigFilePrefix) + 1, sizeof(char));
if ( aSearchConfigFilePrefix != NULL )
strcpy(aSearchConfigFilePrefix, kstrAuthenticationConfigFilePrefix);
else
siResult = eMemoryError;
}
else
{
aSearchNodeName = (char *) calloc(sizeof(kstrContactsNodeName) + 1, sizeof(char));
if ( aSearchNodeName != NULL )
strcpy(aSearchNodeName, kstrContactsNodeName);
else
siResult = eMemoryError;
aSearchConfigFilePrefix = (char *) calloc(sizeof(kstrContactsConfigFilePrefix) + 1, sizeof(char));
if ( aSearchConfigFilePrefix != NULL )
strcpy(aSearchConfigFilePrefix, kstrContactsConfigFilePrefix);
else
siResult = eMemoryError;
}
}
fMutex.SignalLock();
if ( aConfigFromXML == nil )
{
aConfigFromXML = new CConfigs();
if ( aConfigFromXML != nil )
{
result = aConfigFromXML->Init( aSearchConfigFilePrefix, aSearchPolicy );
if ( result != eDSNoErr ) {
aSearchPolicy = kAutomaticSearchPolicy; }
}
else
{
aSearchPolicy = kAutomaticSearchPolicy; }
}
else if (aSearchConfig != nil) {
aSearchPolicy = aSearchConfig->fSearchNodePolicy;
}
switch ( aSearchPolicy )
{
case kCustomSearchPolicy:
DbgLog( kLogPlugin, "Setting search policy to Custom search" );
aSearchNodeList = aConfigFromXML->GetCustom();
if ( aSearchNodeList != NULL )
bRegisterWorkstation = true;
siResult = AddLocalNodesAsFirstPaths(&aSearchNodeList);
break;
case kLocalSearchPolicy:
DbgLog( kLogPlugin, "Setting search policy to Local search" );
siResult = AddLocalNodesAsFirstPaths(&aSearchNodeList);
break;
case kAutomaticSearchPolicy:
default:
DbgLog( kLogPlugin, "Setting search policy to Automatic search" );
siResult = AddLocalNodesAsFirstPaths(&aSearchNodeList);
autoSearchNodeList = DupSearchListWithNewRefs(aSearchNodeList);
break;
}
if (siResult == eDSNoErr)
{
if (aSearchPolicy == kAutomaticSearchPolicy)
{
bool bStateChanged = false;
if ( aConfigFromXML->IsDHCPLDAPEnabled() )
{
bStateChanged = (gDHCPLDAPEnabled == false);
gDHCPLDAPEnabled = true;
bRegisterWorkstation = true;
}
else
{
bStateChanged = (gDHCPLDAPEnabled == true);
gDHCPLDAPEnabled = false;
}
addLDAPResult = AddDefaultLDAPNodesLast( &aSearchNodeList );
if (bStateChanged)
{
DbgLog( kLogPlugin, "CSearchPlugin::Initialize DHCP LDAP setting changed to <%s>", (gDHCPLDAPEnabled ? "on" : "off") );
SCDynamicStoreRef store = SCDynamicStoreCreate( kCFAllocatorDefault, CFSTR("DirectoryService"), NULL, NULL );
if (store != NULL)
{
SCDynamicStoreNotifyValue( store, CFSTR(kDSStdNotifyDHCPConfigStateChanged) );
DbgLog( kLogPlugin, "CSearchPlugin::Initialize DHCP LDAP sent notification" );
CFRelease( store );
}
}
}
if (aSearchConfig != nil) {
sSearchList *toCleanSearchNodeList = nil;
fMutex.WaitLock();
toCleanSearchNodeList = aSearchConfig->fSearchNodeList;
aSearchConfig->fSearchNodeList = aSearchNodeList;
aSearchConfig->fSearchNodePolicy = aSearchPolicy;
if (aSearchConfigType == eDSAuthenticationSearchNodeName)
{
sSearchList *aNewListPtr = nil;
sSearchList *anOldListPtr = nil;
aNewListPtr = aSearchNodeList->fNext; aNewListPtr = aNewListPtr->fNext; while (aNewListPtr != nil)
{
anOldListPtr = toCleanSearchNodeList->fNext; anOldListPtr = anOldListPtr->fNext; while (anOldListPtr != nil)
{
if ( (anOldListPtr->fNodeName != nil) && (aNewListPtr->fNodeName != nil) &&
strcmp(anOldListPtr->fNodeName, aNewListPtr->fNodeName) == 0) {
DBGLOG2( kLogPlugin, "CSearchPlugin::Initialize: reinit - reachability of node <%s> retained as <%s>",
aNewListPtr->fNodeName, anOldListPtr->fNodeReachable ? "true" : "false");
aNewListPtr->fNodeReachable = anOldListPtr->fNodeReachable;
aNewListPtr->fHasNeverOpened = anOldListPtr->fHasNeverOpened;
break;
}
anOldListPtr = anOldListPtr->fNext;
}
aNewListPtr = aNewListPtr->fNext;
}
}
else
{
sSearchList *aListPtr = nil;
aListPtr = aSearchNodeList->fNext; aListPtr = aListPtr->fNext; while (aListPtr != nil)
{
aListPtr->fNodeReachable = false;
aListPtr->fHasNeverOpened = true;
aListPtr = aListPtr->fNext;
}
}
fMutex.SignalLock();
CleanSearchListData( toCleanSearchNodeList );
}
else
{
aSearchConfig = MakeSearchConfigData( aSearchNodeList,
aSearchPolicy,
aConfigFromXML,
aSearchNodeName,
aSearchConfigFilePrefix,
aDirNodeType,
aSearchConfigType);
AddSearchConfigToList(aSearchConfig);
}
if (addLDAPResult == eSearchPathNotDefined)
{
SetSearchPolicyIndicatorFile(aSearchConfigType, aSearchPolicy);
}
else {
SetSearchPolicyIndicatorFile(aSearchConfigType, kCustomSearchPolicy);
}
addLDAPResult = eSearchPathNotDefined;
EnsureCheckNodesThreadIsRunning( (tDirPatternMatch) aSearchConfigType );
aSearchNodeList = nil;
aSearchPolicy = 0;
aConfigFromXML = nil;
aSearchNodeName = nil;
aSearchConfigFilePrefix = nil;
lastSearchConfig = aSearchConfig;
aSearchConfig = nil;
fState = kUnknownState;
fState += kInitialized;
fState += kActive;
gSNNodeRef->DoOnAllItems(CSearchPlugin::ContextSetListChangedProc);
}
}
if ( (autoSearchNodeList != nil) && (lastSearchConfig != nil) )
{
CleanSearchListData( autoSearchNodeList );
}
{ DbgLog( kLogPlugin, "Setting Default Network Search Node Configuraton" );
aSearchConfigType = eDSNetworkSearchNodeName;
aDirNodeType = kNetworkSearchNodeType;
aSearchPolicy = kCustomSearchPolicy;
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey(aSearchConfigType);
if (aSearchConfig != nil) {
aConfigFromXML = aSearchConfig->pConfigFromXML;
aSearchNodeName = aSearchConfig->fSearchNodeName;
aSearchConfigFilePrefix = aSearchConfig->fSearchConfigFilePrefix; }
else
{
aSearchNodeName = (char *) calloc( 1, sizeof(kstrNetworkNodeName) + 1 );
if ( aSearchNodeName != NULL )
strcpy(aSearchNodeName, kstrNetworkNodeName);
aSearchConfigFilePrefix = NULL;
if ( aConfigFromXML == nil )
{
aConfigFromXML = new CConfigs();
}
}
fMutex.SignalLock();
if (aSearchConfig != nil) {
sSearchList *toCleanSearchNodeList = nil;
fMutex.WaitLock();
toCleanSearchNodeList = aSearchConfig->fSearchNodeList;
aSearchConfig->fSearchNodeList = aSearchNodeList;
aSearchConfig->fSearchNodePolicy = aSearchPolicy;
fMutex.SignalLock();
CleanSearchListData( toCleanSearchNodeList );
}
else
{
aSearchConfig = MakeSearchConfigData( aSearchNodeList,
aSearchPolicy,
aConfigFromXML,
aSearchNodeName,
aSearchConfigFilePrefix,
aDirNodeType,
aSearchConfigType);
AddSearchConfigToList(aSearchConfig);
}
}
}
catch( SInt32 err )
{
siResult = err;
fState = kUnknownState;
fState += kFailedToInit;
}
fMutex.WaitLock();
aSearchConfig = pSearchConfigList;
while (aSearchConfig != nil) {
aNodeName = ::dsBuildFromPathPriv( aSearchConfig->fSearchNodeName, "/" );
if ( aNodeName != nil )
{
CServerPlugin::_RegisterNode( fPlugInSignature, aNodeName, aSearchConfig->fDirNodeType );
::dsDataListDeallocatePriv( aNodeName );
free( aNodeName );
aNodeName = nil;
if ( strcmp(kstrAuthenticationNodeName, aSearchConfig->fSearchNodeName) == 0 )
{
CDataBuff *aTmpData = nil;
sSearchList *pListPtr = nil;
char *p = nil;
aTmpData = new CDataBuff();
if ( aTmpData != nil )
{
pListPtr = aSearchConfig->fSearchNodeList;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
if (p != nil)
{
aTmpData->AppendString( p );
}
pListPtr = pListPtr->fNext;
}
authSearchPathCheck = (char *) calloc(1, (aTmpData->GetLength()) + 1);
memcpy(authSearchPathCheck, aTmpData->GetData(), aTmpData->GetLength());
delete(aTmpData);
aTmpData = nil;
}
}
}
aSearchConfig = aSearchConfig->fNext;
}
fRegisterWorkstation = bRegisterWorkstation;
if (fAuthSearchPathCheck == nil)
{
bShouldNotify = false;
}
else if (authSearchPathCheck != nil)
{
if (strcmp(fAuthSearchPathCheck, authSearchPathCheck) != 0)
{
bShouldNotify = true;
}
}
DSFreeString(fAuthSearchPathCheck);
fAuthSearchPathCheck = authSearchPathCheck;
if (bShouldNotify)
{
gSrvrCntl->NodeSearchPolicyChanged();
}
fSomeNodeFailedToOpen = false;
fMutex.SignalLock();
OSAtomicCompareAndSwap32Barrier( true, false, &gInitializeActive );
return( siResult );
}
bool CSearchPlugin:: SwitchSearchPolicy ( UInt32 inSearchPolicy, sSearchConfig *inSearchConfig )
{
SInt32 siResult = eDSNoErr;
bool bAuthSwitched = false; SInt32 addLDAPResult = eSearchPathNotDefined;
char *authSearchPathCheck = nil;
bool bRegisterWorkstation = false;
fMutex.WaitLock();
try
{
if ( inSearchConfig->pConfigFromXML == nil )
{
inSearchConfig->pConfigFromXML = new CConfigs();
if ( inSearchConfig->pConfigFromXML == nil ) throw( (SInt32)eDSPlugInConfigFileError );
siResult = inSearchConfig->pConfigFromXML->Init( inSearchConfig->fSearchConfigFilePrefix, inSearchConfig->fSearchNodePolicy );
if ( siResult != eDSNoErr ) throw( siResult );
}
inSearchConfig->fSearchNodePolicy = inSearchPolicy;
sSearchList *toCleanSearchNodeList = nil;
toCleanSearchNodeList = inSearchConfig->fSearchNodeList;
inSearchConfig->fSearchNodeList = nil;
switch ( inSearchConfig->fSearchNodePolicy )
{
case kCustomSearchPolicy:
DbgLog( kLogPlugin, "Setting search policy to Custom search" );
inSearchConfig->fSearchNodeList = inSearchConfig->pConfigFromXML->GetCustom();
if ( inSearchConfig->fSearchNodeList != NULL )
bRegisterWorkstation = true;
siResult = AddLocalNodesAsFirstPaths(&(inSearchConfig->fSearchNodeList));
break;
case kLocalSearchPolicy:
DbgLog( kLogPlugin, "Setting search policy to Local search" );
siResult = AddLocalNodesAsFirstPaths(&(inSearchConfig->fSearchNodeList));
break;
case kAutomaticSearchPolicy:
default:
DbgLog( kLogPlugin, "Setting search policy to Automatic default" );
siResult = AddLocalNodesAsFirstPaths(&(inSearchConfig->fSearchNodeList));
break;
}
if (siResult == eDSNoErr)
{
if (inSearchConfig->fSearchNodePolicy == kAutomaticSearchPolicy)
{
if ( inSearchConfig->pConfigFromXML != nil )
{
bool bStateChanged = false;
if (inSearchConfig->pConfigFromXML->IsDHCPLDAPEnabled())
{
bStateChanged = (gDHCPLDAPEnabled == false);
gDHCPLDAPEnabled = true;
bRegisterWorkstation = true;
}
else
{
bStateChanged = (gDHCPLDAPEnabled == true);
gDHCPLDAPEnabled = false;
}
if (bStateChanged)
{
DbgLog( kLogPlugin, "CSearchPlugin::SwitchSearchPolicy DHCP LDAP setting changed to <%s>",
(gDHCPLDAPEnabled ? "on" : "off") );
SCDynamicStoreRef store = SCDynamicStoreCreate( NULL, CFSTR("DirectoryService"), NULL, NULL );
if (store != NULL)
{ SCDynamicStoreNotifyValue( store, CFSTR(kDSStdNotifyDHCPConfigStateChanged) );
DSCFRelease( store );
}
}
addLDAPResult = AddDefaultLDAPNodesLast( &(inSearchConfig->fSearchNodeList) );
}
}
if (inSearchConfig->fSearchConfigKey == eDSAuthenticationSearchNodeName)
{
sSearchList *aNewListPtr = nil;
sSearchList *anOldListPtr = nil;
aNewListPtr = inSearchConfig->fSearchNodeList->fNext; aNewListPtr = aNewListPtr->fNext; while (aNewListPtr != nil)
{
anOldListPtr = toCleanSearchNodeList->fNext; anOldListPtr = anOldListPtr->fNext; while (anOldListPtr != nil)
{
if ( (anOldListPtr->fNodeName != nil) && (aNewListPtr->fNodeName != nil) &&
strcmp(anOldListPtr->fNodeName, aNewListPtr->fNodeName) == 0) {
DBGLOG2( kLogPlugin, "CSearchPlugin::SwitchSearchPolicy: switch - reachability of node <%s> retained as <%s>",
aNewListPtr->fNodeName, anOldListPtr->fNodeReachable ? "true" : "false");
aNewListPtr->fNodeReachable = anOldListPtr->fNodeReachable;
aNewListPtr->fHasNeverOpened = anOldListPtr->fHasNeverOpened;
break;
}
anOldListPtr = anOldListPtr->fNext;
}
aNewListPtr = aNewListPtr->fNext;
}
}
else
{
sSearchList *aListPtr = nil;
aListPtr = inSearchConfig->fSearchNodeList->fNext; aListPtr = aListPtr->fNext;
while (aListPtr != nil)
{
aListPtr->fNodeReachable = false;
aListPtr->fHasNeverOpened = true;
aListPtr = aListPtr->fNext;
}
}
EnsureCheckNodesThreadIsRunning( (tDirPatternMatch) inSearchConfig->fSearchConfigKey );
fState = kUnknownState;
fState += kInitialized;
fState += kActive;
if (addLDAPResult == eSearchPathNotDefined)
{
SetSearchPolicyIndicatorFile( inSearchConfig->fSearchConfigKey, inSearchConfig->fSearchNodePolicy );
}
else {
SetSearchPolicyIndicatorFile( inSearchConfig->fSearchConfigKey, kCustomSearchPolicy );
}
gSNNodeRef->DoOnAllItems(CSearchPlugin::ContextSetListChangedProc);
}
CleanSearchListData( toCleanSearchNodeList );
}
catch( SInt32 err )
{
siResult = err;
fState = kUnknownState;
fState += kInactive;
}
fRegisterWorkstation = bRegisterWorkstation;
if ( strcmp(kstrAuthenticationNodeName, inSearchConfig->fSearchNodeName) == 0 )
{
CDataBuff *aTmpData = nil;
sSearchList *pListPtr = nil;
char *p = nil;
aTmpData = new CDataBuff();
if ( aTmpData != nil )
{
pListPtr = inSearchConfig->fSearchNodeList;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
if (p != nil)
{
aTmpData->AppendString( p );
}
pListPtr = pListPtr->fNext;
}
authSearchPathCheck = (char *) calloc(1, (aTmpData->GetLength()) + 1);
memcpy(authSearchPathCheck, aTmpData->GetData(), aTmpData->GetLength());
delete(aTmpData);
aTmpData = nil;
}
}
if (authSearchPathCheck != nil)
{
if (fAuthSearchPathCheck != nil)
{
free(fAuthSearchPathCheck);
}
fAuthSearchPathCheck = authSearchPathCheck;
gSrvrCntl->NodeSearchPolicyChanged();
if ( gCacheNode != NULL )
{
gCacheNode->EmptyCacheEntryType( CACHE_ENTRY_TYPE_ALL );
}
bAuthSwitched = true;
}
fMutex.SignalLock();
return( bAuthSwitched );
}
sSearchList *CSearchPlugin:: GetDefaultLocalPath( void )
{
UInt32 uiCntr = 1;
sSearchList *outSrchList = nil;
outSrchList = (sSearchList *)calloc( sizeof( sSearchList ), sizeof(char) );
outSrchList->fNodeName = strdup(kstrDefaultLocalNodeName);
outSrchList->fDataList = ::dsBuildFromPathPriv( kstrDefaultLocalNodeName, "/" );
DbgLog( kLogPlugin, "CSearchPlugin::GetDefaultLocalPath<setlocalfirst>:Search policy node %l = %s", uiCntr++, outSrchList->fNodeName );
return( outSrchList );
}
sSearchList *CSearchPlugin:: GetBSDLocalPath( void )
{
UInt32 uiCntr = 2;
sSearchList *outSrchList = nil;
outSrchList = (sSearchList *)calloc( sizeof( sSearchList ), sizeof(char) );
outSrchList->fNodeName = strdup( kstrBSDLocalNodeName );
outSrchList->fDataList = dsBuildFromPathPriv( kstrBSDLocalNodeName, "/" );
DbgLog( kLogPlugin, "CSearchPlugin::GetBSDLocalPath<setbsdsecond>:Search policy node %l = %s", uiCntr++, outSrchList->fNodeName );
return( outSrchList );
}
SInt32 CSearchPlugin::AddDefaultLDAPNodesLast( sSearchList **inSearchNodeList )
{
SInt32 siResult = eSearchPathNotDefined;
sSearchList *ldapSrchList = nil;
sSearchList *pSrchList = nil;
if ( gDHCPLDAPEnabled )
{
ldapSrchList = GetDefaultLDAPPaths();
if ( ldapSrchList != nil )
{
if ( *inSearchNodeList == nil )
{
*inSearchNodeList = ldapSrchList;
}
else
{
pSrchList = *inSearchNodeList;
while(pSrchList->fNext != nil)
{
pSrchList = pSrchList->fNext;
}
pSrchList->fNext = ldapSrchList;
}
siResult = eDSNoErr;
}
}
return( siResult );
}
SInt32 CSearchPlugin::AddLocalNodesAsFirstPaths( sSearchList **inSearchNodeList )
{
SInt32 siResult = eDSNoErr;
sSearchList *aSrchList = nil;
sSearchList *pSrchList = nil;
char *localNodeName = nil;
localNodeName = strdup( kstrBSDLocalNodeName );
aSrchList = GetBSDLocalPath();
free(localNodeName);
if ( aSrchList == nil )
{
siResult = eSearchPathNotDefined;
}
else
{
if ( *inSearchNodeList == nil )
{
*inSearchNodeList = aSrchList;
}
else
{
pSrchList = aSrchList;
while (pSrchList->fNext != nil)
{
pSrchList = pSrchList->fNext;
}
pSrchList->fNext = *inSearchNodeList;
*inSearchNodeList = aSrchList;
}
}
localNodeName = strdup( kstrDefaultLocalNodeName );
aSrchList = GetDefaultLocalPath();
free(localNodeName);
if ( aSrchList == nil )
{
siResult = eSearchPathNotDefined;
}
else
{
if ( *inSearchNodeList == nil )
{
*inSearchNodeList = aSrchList;
}
else
{
pSrchList = aSrchList;
while (pSrchList->fNext != nil)
{
pSrchList = pSrchList->fNext;
}
pSrchList->fNext = *inSearchNodeList;
*inSearchNodeList = aSrchList;
}
}
return( siResult );
}
sSearchList *CSearchPlugin:: GetDefaultLDAPPaths ( void )
{
SInt32 siResult = eDSNoErr;
tDataBuffer *pNodeBuff = nil;
tDataList *pNodeNameDL = nil;
tDataList *pNodeList = nil;
UInt32 uiCount = 0;
sSearchList *pCurList = nil;
sSearchList *pSrchList = nil;
UInt32 uiCntr = 1;
sSearchList *outSrchList = nil;
tDirNodeReference aNodeRef = 0;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef attrValueListRef = 0;
tAttributeValueEntry *pAttrValueEntry = nil;
tAttributeEntry *pAttrEntry = nil;
UInt32 aIndex = 0;
try
{
pNodeBuff = ::dsDataBufferAllocate( fDirRef, 2048 );
if ( pNodeBuff == nil ) throw( (SInt32)eMemoryError );
pNodeNameDL = ::dsBuildListFromStringsPriv( "LDAPv3", nil );
if ( pNodeNameDL == nil ) throw( (SInt32)eMemoryAllocError );
siResult = ::dsOpenDirNode( fDirRef, pNodeNameDL, &aNodeRef );
if ( siResult != eDSNoErr ) throw( siResult );
::dsDataListDeallocate( fDirRef, pNodeNameDL );
free(pNodeNameDL);
pNodeNameDL = nil;
pNodeList = ::dsBuildListFromStringsPriv( kDSNAttrDefaultLDAPPaths, nil );
if ( pNodeList == nil ) throw( (SInt32)eMemoryAllocError );
siResult = ::dsGetDirNodeInfo( aNodeRef, pNodeList, pNodeBuff, false, &uiCount, &attrListRef, nil );
if ( siResult != eDSNoErr ) throw( siResult );
if ( uiCount == 0 ) throw ( (SInt32)eNoSearchNodesFound );
::dsDataListDeallocate( fDirRef, pNodeList );
free(pNodeList);
pNodeList = nil;
siResult = dsGetAttributeEntry( aNodeRef, pNodeBuff, attrListRef, 1, &attrValueListRef, &pAttrEntry );
if ( siResult != eDSNoErr ) throw( siResult );
for (aIndex=1; aIndex < (pAttrEntry->fAttributeValueCount+1); aIndex++)
{
siResult = dsGetAttributeValue( aNodeRef, pNodeBuff, aIndex, attrValueListRef, &pAttrValueEntry );
if ( siResult != eDSNoErr ) throw( siResult );
if ( pAttrValueEntry->fAttributeValueData.fBufferData == nil ) throw( (SInt32)eMemoryAllocError );
pSrchList = (sSearchList *)calloc( sizeof( sSearchList ), sizeof(char) );
pSrchList->fNodeName = (char *)calloc( pAttrValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) );
if ( pSrchList->fNodeName != NULL )
strcpy( pSrchList->fNodeName, pAttrValueEntry->fAttributeValueData.fBufferData );
pSrchList->fDataList = ::dsBuildFromPathPriv( pSrchList->fNodeName, "/" );
DbgLog( kLogPlugin, "CSearchPlugin::GetDefaultLDAPPaths:Search policy node %l = %s", uiCntr++, pSrchList->fNodeName );
if ( outSrchList == nil )
{
outSrchList = pSrchList;
outSrchList->fNext = nil;
pCurList = outSrchList;
}
else
{
pCurList->fNext = pSrchList;
pCurList = pSrchList;
pCurList->fNext = nil;
}
dsDeallocAttributeValueEntry(fDirRef, pAttrValueEntry);
pAttrValueEntry = nil;
}
dsCloseAttributeList(attrListRef);
dsCloseAttributeValueList(attrValueListRef);
dsDeallocAttributeEntry(fDirRef, pAttrEntry);
pAttrEntry = nil;
siResult = ::dsCloseDirNode(aNodeRef);
if ( siResult != eDSNoErr ) throw( siResult );
if ( pNodeBuff != nil )
{
::dsDataBufferDeAllocate( fDirRef, pNodeBuff );
pNodeBuff = nil;
}
}
catch( SInt32 err )
{
siResult = err;
}
if ( pNodeBuff != nil )
{
::dsDataBufferDeAllocate( fDirRef, pNodeBuff );
pNodeBuff = nil;
}
if ( pNodeList != nil )
{
::dsDataListDeallocate( fDirRef, pNodeList );
free(pNodeList);
pNodeList = nil;
}
if ( pNodeNameDL != nil )
{
::dsDataListDeallocate( fDirRef, pNodeNameDL );
free(pNodeNameDL);
pNodeNameDL = nil;
}
return( outSrchList );
}
void CSearchPlugin::WakeUpRequests ( void )
{
gKickSearchRequests.PostEvent();
}
void CSearchPlugin::WaitForInit ( void )
{
gKickSearchRequests.WaitForEvent( (UInt32)(2 * 60 * kMilliSecsPerSec) );
}
SInt32 CSearchPlugin::ProcessRequest ( void *inData )
{
SInt32 siResult = eDSNoErr;
char *pathStr = nil;
try
{
if ( inData == nil )
{
throw( (SInt32)ePlugInDataError );
}
if (((sHeader *)inData)->fType == kOpenDirNode)
{
if (((sOpenDirNode *)inData)->fInDirNodeName != nil)
{
pathStr = ::dsGetPathFromListPriv( ((sOpenDirNode *)inData)->fInDirNodeName, "/" );
if ( (pathStr != nil) && (strncmp(pathStr,"/Search",7) != 0) )
{
throw( (SInt32)eDSOpenNodeFailed);
}
}
}
if ( ((sHeader *)inData)->fType == kServerRunLoop || ((sHeader *)inData)->fType == kKerberosMutex )
{
return eDSNoErr;
}
WaitForInit();
if (fState == kUnknownState)
{
throw( (SInt32)ePlugInCallTimedOut );
}
if ( (fState & kFailedToInit) || !(fState & kInitialized) )
{
throw( (SInt32)ePlugInFailedToInitialize );
}
if ( (fState & kInactive) || !(fState & kActive) )
{
throw( (SInt32)ePlugInNotActive );
}
if ( ((sHeader *)inData)->fType == kHandleNetworkTransition )
{
EnsureCheckNodesThreadIsRunning( eDSAuthenticationSearchNodeName ); EnsureCheckNodesThreadIsRunning( eDSContactsSearchNodeName ); }
else
{
siResult = HandleRequest( inData );
}
}
catch( SInt32 err )
{
siResult = err;
}
if (pathStr != nil)
{
free(pathStr);
pathStr = nil;
}
return( siResult );
}
SInt32 CSearchPlugin::HandleRequest ( void *inData )
{
SInt32 siResult = eDSNoErr;
sHeader *pMsgHdr = nil;
try
{
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kReleaseContinueData:
siResult = ReleaseContinueData( (sReleaseContinueData *)inData );
break;
case kOpenDirNode:
siResult = OpenDirNode( (sOpenDirNode *)inData );
break;
case kCloseDirNode:
siResult = CloseDirNode( (sCloseDirNode *)inData );
break;
case kGetDirNodeInfo:
siResult = GetDirNodeInfo( (sGetDirNodeInfo *)inData );
break;
case kGetRecordList:
siResult = GetRecordList( (sGetRecordList *)inData );
break;
case kGetRecordEntry:
siResult = GetRecordEntry( (sGetRecordEntry *)inData );
break;
case kGetAttributeEntry:
siResult = GetAttributeEntry( (sGetAttributeEntry *)inData );
break;
case kGetAttributeValue:
siResult = GetAttributeValue( (sGetAttributeValue *)inData );
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
siResult = AttributeValueSearch( (sDoAttrValueSearchWithData *)inData );
break;
case kDoMultipleAttributeValueSearch:
case kDoMultipleAttributeValueSearchWithData:
siResult = MultipleAttributeValueSearch( (sDoMultiAttrValueSearchWithData *)inData );
break;
case kCloseAttributeList:
siResult = CloseAttributeList( (sCloseAttributeList *)inData );
break;
case kCloseAttributeValueList:
siResult = CloseAttributeValueList( (sCloseAttributeValueList *)inData );
break;
case kDoPlugInCustomCall:
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kServerRunLoop:
siResult = eDSNoErr;
break;
case kHandleSystemWillSleep:
siResult = eDSNoErr;
SystemGoingToSleep();
break;
case kHandleSystemWillPowerOn:
siResult = eDSNoErr;
SystemWillPowerOn();
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
}
catch( SInt32 err )
{
siResult = err;
}
catch ( ... )
{
siResult = ePlugInError;
}
return( siResult );
}
SInt32 CSearchPlugin::ReleaseContinueData ( sReleaseContinueData *inData )
{
SInt32 siResult = eDSNoErr;
if ( gSNContinue->RemoveItem( inData->fInContinueData ) != eDSNoErr )
{
siResult = eDSInvalidContext;
}
return( siResult );
}
#pragma mark -
#pragma mark DS API Service Routines
#pragma mark -
SInt32 CSearchPlugin::OpenDirNode ( sOpenDirNode *inData )
{
SInt32 siResult = eDSOpenNodeFailed;
char *pathStr = nil;
sSearchContextData *pContext = nil;
sSearchConfig *aSearchConfigList = nil;
if ( inData != nil )
{
pathStr = ::dsGetPathFromListPriv( inData->fInDirNodeName, "/" );
if ( pathStr != nil )
{
fMutex.WaitLock();
aSearchConfigList = pSearchConfigList;
while (aSearchConfigList != nil)
{
if ( ::strcmp( pathStr, aSearchConfigList->fSearchNodeName ) == 0 )
{
pContext = MakeContextData();
if (pContext != nil)
{
pContext->pSearchListMutex = new DSMutexSemaphore("sSearchContextData::pSearchListMutex");
pContext->fSearchConfigKey = aSearchConfigList->fSearchConfigKey;
if (strcmp(pathStr, kstrNetworkNodeName) == 0)
{
pContext->fSearchNodeList = BuildNetworkNodeList();
}
else {
pContext->fSearchNodeList = DupSearchListWithNewRefs(aSearchConfigList->fSearchNodeList);
}
if (aSearchConfigList->fSearchNodePolicy == kAutomaticSearchPolicy)
{
pContext->bAutoSearchList = true;
}
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
#if AUGMENT_RECORDS
pContext->pConfigFromXML = aSearchConfigList->pConfigFromXML;
#endif
gSNNodeRef->AddItem( inData->fOutNodeRef, pContext );
siResult = eDSNoErr;
}
break;
}
aSearchConfigList = aSearchConfigList->fNext;
}
fMutex.SignalLock();
free( pathStr );
pathStr = nil;
}
}
return( siResult );
}
SInt32 CSearchPlugin::CloseDirNode ( sCloseDirNode *inData )
{
SInt32 siResult = eDSNoErr;
sSearchContextData *pContext = nil;
try
{
pContext = (sSearchContextData *) gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
gSNNodeRef->RemoveItem( inData->fInNodeRef );
gSNContinue->RemoveItems( inData->fInNodeRef );
}
catch( SInt32 err )
{
siResult = err;
}
return( siResult );
}
SInt32 CSearchPlugin::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
SInt32 siResult = eDSNoErr;
UInt32 uiOffset = 0;
UInt32 uiNodeCnt = 0;
char *p = nil;
char *localNodeName = nil;
UInt32 uiCntr = 1;
UInt32 uiAttrCnt = 0;
CAttributeList *inAttrList = nil;
char *pAttrName = nil;
char *pData = nil;
sSearchContextData *pAttrContext = nil;
sSearchList *pListPtr = nil;
sSearchList *pListPtrToo = nil;
sSearchList *pListCustom = nil;
CBuff outBuff;
char *policyValue = nil;
sSearchContextData *pContext = nil;
sSearchConfig *aSearchConfig = nil;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
CDataBuff *aTmpData = nil;
UInt32 searchNodeNameBufLen = 0;
bool bHaveLock = false;
try
{
aRecData = new CDataBuff();
aAttrData = new CDataBuff();
aTmpData = new CDataBuff();
if ( inData == nil ) throw( (SInt32)eMemoryError );
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
siResult = CheckSearchPolicyChange(pContext, inData->fInNodeRef, inData->fOutContinueData);
if( siResult != eDSNoErr )
{
throw( siResult );
}
fMutex.WaitLock();
bHaveLock = true;
aSearchConfig = FindSearchConfigWithKey(pContext->fSearchConfigKey);
if ( aSearchConfig == nil ) throw( (SInt32)eDSInvalidNodeRef );
inAttrList = new CAttributeList( inData->fInDirNodeInfoTypeList );
if ( inAttrList == nil ) throw( (SInt32)eDSNullNodeInfoTypeList );
if (inAttrList->GetCount() == 0) throw( (SInt32)eDSEmptyNodeInfoTypeList );
siResult = outBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff.SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
aRecData->Clear();
aAttrData->Clear();
aRecData->AppendShort( ::strlen( kDSStdRecordTypeSearchNodeInfo ) );
aRecData->AppendString( kDSStdRecordTypeSearchNodeInfo );
if (aSearchConfig->fSearchNodeName != nil)
{
searchNodeNameBufLen = strlen( aSearchConfig->fSearchNodeName );
aRecData->AppendShort( searchNodeNameBufLen );
searchNodeNameBufLen += 2;
aRecData->AppendString( aSearchConfig->fSearchNodeName );
}
else
{
aRecData->AppendShort( ::strlen( "SearchNodeInfo" ) );
aRecData->AppendString( "SearchNodeInfo" );
searchNodeNameBufLen = 16; }
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrSearchPath ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrSearchPath ) );
aTmpData->AppendString( kDS1AttrSearchPath );
if ( inData->fInAttrInfoOnly == false )
{
uiNodeCnt = 0;
pListPtr = pContext->fSearchNodeList;
while ( pListPtr != nil )
{
uiNodeCnt++;
pListPtr = pListPtr->fNext;
}
aTmpData->AppendShort( uiNodeCnt );
pListPtr = pContext->fSearchNodeList;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
aTmpData->AppendLong( ::strlen( p ) );
aTmpData->AppendString( p );
pListPtr = pListPtr->fNext;
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrNSPSearchPath ) == 0) ) &&
(pContext->fSearchConfigKey != eDSNetworkSearchNodeName) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrNSPSearchPath ) );
aTmpData->AppendString( kDS1AttrNSPSearchPath );
if ( inData->fInAttrInfoOnly == false )
{
uiNodeCnt = 0;
AddLocalNodesAsFirstPaths(&pListPtr);
if ( pListPtr == nil ) throw( (SInt32)eSearchPathNotDefined );
AddDefaultLDAPNodesLast(&pListPtr);
pListPtrToo = pListPtr;
while ( pListPtr != nil )
{
uiNodeCnt++;
pListPtr = pListPtr->fNext;
}
aTmpData->AppendShort( uiNodeCnt );
pListPtr = pListPtrToo;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
aTmpData->AppendLong( ::strlen( p ) );
aTmpData->AppendString( p );
pListPtr = pListPtr->fNext;
}
CleanSearchListData( pListPtrToo );
pListPtrToo = nil;
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrLSPSearchPath ) == 0) ) &&
(pContext->fSearchConfigKey != eDSNetworkSearchNodeName) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrLSPSearchPath ) );
aTmpData->AppendString( kDS1AttrLSPSearchPath );
if ( inData->fInAttrInfoOnly == false )
{
uiNodeCnt = 0;
AddLocalNodesAsFirstPaths(&pListPtr);
if ( pListPtr == nil ) throw( (SInt32)eSearchPathNotDefined );
pListPtrToo = pListPtr;
while ( pListPtr != nil )
{
uiNodeCnt++;
pListPtr = pListPtr->fNext;
}
aTmpData->AppendShort( uiNodeCnt );
pListPtr = pListPtrToo;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
aTmpData->AppendLong( ::strlen( p ) );
aTmpData->AppendString( p );
pListPtr = pListPtr->fNext;
}
CleanSearchListData( pListPtrToo );
pListPtrToo = nil;
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrCSPSearchPath ) == 0) ) &&
(pContext->fSearchConfigKey != eDSNetworkSearchNodeName) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrCSPSearchPath ) );
aTmpData->AppendString( kDS1AttrCSPSearchPath );
if ( inData->fInAttrInfoOnly == false )
{
if ( aSearchConfig->pConfigFromXML != nil )
{
pListCustom = aSearchConfig->pConfigFromXML->GetCustom();
}
AddLocalNodesAsFirstPaths(&pListPtr);
if ( pListPtr == nil ) throw( (SInt32)eSearchPathNotDefined );
pListPtrToo = pListPtr;
while ( pListPtrToo->fNext != nil )
{
pListPtrToo = pListPtrToo->fNext;
}
pListPtrToo->fNext = pListCustom;
uiNodeCnt = 0;
pListPtrToo = pListPtr;
while ( pListPtr != nil )
{
uiNodeCnt++;
pListPtr = pListPtr->fNext;
}
aTmpData->AppendShort( uiNodeCnt );
pListPtr = pListPtrToo;
while ( pListPtr != nil )
{
p = pListPtr->fNodeName;
aTmpData->AppendLong( ::strlen( p ) );
aTmpData->AppendString( p );
pListPtr = pListPtr->fNext;
}
CleanSearchListData( pListPtrToo );
pListPtrToo = nil;
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrSearchPolicy ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrSearchPolicy ) );
aTmpData->AppendString( kDS1AttrSearchPolicy );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
if (aSearchConfig->fSearchNodePolicy == kAutomaticSearchPolicy)
{
policyValue = new char[1+strlen(kDS1AttrNSPSearchPath)];
strcpy(policyValue, kDS1AttrNSPSearchPath);
}
else if (aSearchConfig->fSearchNodePolicy == kLocalSearchPolicy)
{
policyValue = new char[1+strlen(kDS1AttrLSPSearchPath)];
strcpy(policyValue, kDS1AttrLSPSearchPath);
}
else if (aSearchConfig->fSearchNodePolicy == kCustomSearchPolicy)
{
policyValue = new char[1+strlen(kDS1AttrCSPSearchPath)];
strcpy(policyValue, kDS1AttrCSPSearchPath);
}
else
{
policyValue = new char[1+strlen("Unknown")];
strcpy(policyValue,"Unknown");
}
aTmpData->AppendLong( ::strlen( policyValue ) );
aTmpData->AppendString( policyValue );
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrReadOnlyNode ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrReadOnlyNode ) );
aTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( ::strlen( "ReadOnly" ) );
aTmpData->AppendString( "ReadOnly" );
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrDHCPLDAPDefault ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrDHCPLDAPDefault ) );
aTmpData->AppendString( kDS1AttrDHCPLDAPDefault );
if ( inData->fInAttrInfoOnly == false )
{
if ( aSearchConfig->pConfigFromXML != nil )
{
aTmpData->AppendShort( 1 );
if ( gDHCPLDAPEnabled )
{
aTmpData->AppendLong( sizeof("on")-1 );
aTmpData->AppendString( "on" );
}
else
{
aTmpData->AppendLong( sizeof("off")-1 );
aTmpData->AppendString( "off" );
}
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
}
fMutex.SignalLock();
bHaveLock = false;
aRecData->AppendShort( uiAttrCnt );
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
outBuff.AddData( aRecData->GetData(), aRecData->GetLength() );
inData->fOutAttrInfoCount = uiAttrCnt;
pData = outBuff.GetDataBlock( 1, &uiOffset );
if ( pData != nil )
{
pAttrContext = MakeContextData();
pAttrContext->offset = uiOffset + 38 + searchNodeNameBufLen;
gSNNodeRef->AddItem( inData->fOutAttrListRef, pAttrContext );
}
else
{
siResult = eDSBufferTooSmall;
}
inData->fOutDataBuff->fBufferLength = inData->fOutDataBuff->fBufferSize;
}
catch( SInt32 err )
{
siResult = err;
if ( bHaveLock )
{
fMutex.SignalLock();
}
}
if ( localNodeName != nil )
{
free( localNodeName );
localNodeName = nil;
}
if ( inAttrList != nil )
{
delete( inAttrList );
inAttrList = nil;
}
if (policyValue != nil)
{
delete( policyValue );
}
if ( aRecData != nil )
{
delete(aRecData);
aRecData = nil;
}
if ( aAttrData != nil )
{
delete(aAttrData);
aAttrData = nil;
}
if ( aTmpData != nil )
{
delete(aTmpData);
aTmpData = nil;
}
return( siResult );
}
SInt32 CSearchPlugin::GetRecordList ( sGetRecordList *inData )
{
SInt32 siResult = eDSNoErr;
UInt32 recCount = 0;
bool done = false;
sSearchContinueData *pContinue = nil;
sSearchContinueData *pInContinue = nil;
eSearchState runState = keGetRecordList;
eSearchState lastState = keUnknownState;
CBuff inOutBuff;
sSearchContextData *pContext = nil;
bool bKeepOldBuffer = false;
try
{
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
if (pContext->pSearchListMutex == nil ) throw( (SInt32)eDSBadContextData);
siResult = CheckSearchPolicyChange(pContext, inData->fInNodeRef, inData->fIOContinueData);
pContext->pSearchListMutex->WaitLock();
if( siResult != eDSNoErr ) throw( siResult );
if ( pContext->fSearchNodeList == nil ) throw( (SInt32)eSearchPathNotDefined );
if ( inData->fIOContinueData != nil )
{
if ( gSNContinue->VerifyItem( inData->fIOContinueData ) == true )
{
pInContinue = (sSearchContinueData *)inData->fIOContinueData;
if (pInContinue->bNodeBuffTooSmall)
{
pInContinue->bNodeBuffTooSmall = false;
throw( (SInt32)eDSBufferTooSmall );
}
pContinue = (sSearchContinueData *)calloc( sizeof( sSearchContinueData ), sizeof( char ) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDirRef = pInContinue->fDirRef;
pContinue->fNodeRef = pInContinue->fNodeRef;
pContinue->fAttrOnly = pInContinue->fAttrOnly;
pContinue->fRecCount = pInContinue->fRecCount;
pContinue->fRecIndex = pInContinue->fRecIndex;
pContinue->fState = pInContinue->fState;
pContinue->bIsAugmented = pInContinue->bIsAugmented;
pContinue->fAugmentReqAttribs = dsDataListCopyList( 0, pInContinue->fAugmentReqAttribs );
if (inData->fInDataBuff->fBufferSize != pInContinue->fDataBuff->fBufferSize)
{
if (pContinue->fState == keAddDataToBuff)
{
bKeepOldBuffer = true;
pContinue->fDataBuff = pInContinue->fDataBuff; pInContinue->fDataBuff = nil; }
else
{
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fInDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
}
}
else
{
pContinue->fDataBuff = pInContinue->fDataBuff;
pInContinue->fDataBuff = nil;
}
pContinue->fContextData = pInContinue->fContextData;
pContinue->fLimitRecSearch = pInContinue->fLimitRecSearch;
pContinue->fTotalRecCount = pInContinue->fTotalRecCount;
pContinue->bNodeBuffTooSmall= pInContinue->bNodeBuffTooSmall;
pInContinue->fContextData = nil;
gSNContinue->RemoveItem( inData->fIOContinueData );
pInContinue = nil;
inData->fIOContinueData = nil;
runState = pContinue->fState;
}
else
{
throw( (SInt32)eDSInvalidContinueData );
}
}
else
{
pContinue = (sSearchContinueData *)calloc( 1, sizeof( sSearchContinueData ) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fInDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
siResult = GetNextNodeRef( 0, &pContinue->fNodeRef, pContext );
if ( siResult != eDSNoErr ) throw( siResult );
pContinue->fDirRef = fDirRef;
pContinue->fRecIndex = 1;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
pContinue->bNodeBuffTooSmall= false;
if (inData->fOutRecEntryCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutRecEntryCount;
}
}
siResult = inOutBuff.Initialize( inData->fInDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inOutBuff.SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
inData->fIOContinueData = nil;
inData->fOutRecEntryCount = 0;
while ( !done )
{
switch ( runState )
{
case keGetRecordList:
{
if (pContinue->fLimitRecSearch > pContinue->fTotalRecCount)
{
recCount = pContinue->fLimitRecSearch - pContinue->fTotalRecCount;
}
else
{
recCount = 0;
}
siResult = ::dsGetRecordList( pContinue->fNodeRef,
pContinue->fDataBuff,
inData->fInRecNameList,
inData->fInPatternMatch,
inData->fInRecTypeList,
(pContinue->bIsAugmented && pContinue->fAugmentReqAttribs ? pContinue->fAugmentReqAttribs : inData->fInAttribTypeList),
inData->fInAttribInfoOnly,
&recCount,
&pContinue->fContextData );
pContinue->fRecCount = recCount;
pContinue->fRecIndex = 1;
lastState = keGetRecordList;
}
break;
case keAddDataToBuff:
{
siResult = AddDataToOutBuff( pContinue, &inOutBuff, pContext, inData->fInAttribTypeList );
if (bKeepOldBuffer)
{
if (siResult == eDSNoErr)
{
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fInDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
bKeepOldBuffer = false;
}
}
lastState = keAddDataToBuff;
}
break;
case keGetNextNodeRef:
{
siResult = GetNextNodeRef( pContinue->fNodeRef, &pContinue->fNodeRef, pContext );
lastState = keGetNextNodeRef;
if ( siResult == eDSNoErr )
UpdateContinueForAugmented( pContext, pContinue, inData->fInAttribTypeList );
}
break;
case keSetContinueData:
{
switch ( lastState )
{
case keAddDataToBuff:
inOutBuff.GetDataBlockCount( &inData->fOutRecEntryCount );
pContinue->fTotalRecCount += inData->fOutRecEntryCount;
pContinue->fState = lastState;
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
siResult = eDSNoErr;
break;
case keGetRecordList:
case keGetNextNodeRef:
inOutBuff.GetDataBlockCount( &inData->fOutRecEntryCount );
pContinue->fTotalRecCount += inData->fOutRecEntryCount;
pContinue->fState = keGetRecordList;
if ( siResult == keSearchNodeListEnd )
{
siResult = eDSNoErr;
inData->fIOContinueData = nil;
}
else
{
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
}
break;
case keBufferTooSmall:
if (pContinue->fContextData == nil) {
pContinue->fState = keAddDataToBuff;
siResult = eDSBufferTooSmall;
}
else {
inOutBuff.GetDataBlockCount( &inData->fOutRecEntryCount );
pContinue->fTotalRecCount += inData->fOutRecEntryCount;
if (inData->fOutRecEntryCount == 0)
{
siResult = eDSBufferTooSmall;
}
else
{
pContinue->bNodeBuffTooSmall= true;
siResult = eDSNoErr;
}
if( pContinue->fRecIndex <= pContinue->fRecCount )
pContinue->fState = keAddDataToBuff;
else
pContinue->fState = keGetRecordList;
}
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
break;
default:
DbgLog( kLogPlugin, "*** Invalid continue state = %l", lastState );
break;
}
}
break;
case keDone:
{
if ( pContinue != nil )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown run state = %l", runState );
done = true;
}
break;
}
switch ( runState )
{
case keGetRecordList:
{
if ( siResult == eDSNoErr )
{
if ( pContinue->fRecCount != 0 )
{
runState = keAddDataToBuff;
}
else if (pContinue->fContextData == nil)
{
runState = keGetNextNodeRef;
}
}
else if ( (siResult == eDSRecordNotFound ) ||
(siResult == eDSInvalidRecordName) ||
(siResult == eDSInvalidRecordType) )
{
runState = keGetNextNodeRef;
if (siResult == eDSInvalidRecordType)
{
if (pContinue->fContextData != nil)
{
dsReleaseContinueData(pContinue->fNodeRef, pContinue->fContextData);
pContinue->fContextData = nil;
}
}
}
else if (siResult == eDSBufferTooSmall)
{
lastState = keBufferTooSmall;
runState = keSetContinueData;
}
else {
runState = keGetNextNodeRef;
}
}
break;
case keAddDataToBuff:
{
UInt32 aRecCnt = 0;
inOutBuff.GetDataBlockCount(&aRecCnt);
if ( ( siResult == eDSNoErr ) || ( ( siResult == CBuff::kBuffFull ) && (aRecCnt > 0) ) )
{
inData->fOutRecEntryCount = aRecCnt;
if ((pContinue->fLimitRecSearch <= (pContinue->fTotalRecCount + inData->fOutRecEntryCount)) &&
(pContinue->fLimitRecSearch != 0))
{
pContinue->fTotalRecCount += inData->fOutRecEntryCount;
pContinue->fState = runState;
runState = keDone;
inData->fIOContinueData = nil;
siResult = eDSNoErr;
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
}
else if ( pContinue->fContextData )
{
lastState = keGetRecordList;
runState = keGetRecordList;
}
else
{
runState = keGetNextNodeRef;
}
}
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
lastState = keBufferTooSmall;
}
else
{
runState = keDone;
}
}
}
break;
case keGetNextNodeRef:
{
inOutBuff.GetDataBlockCount( &recCount );
if ( siResult == eDSNoErr )
{
if ( recCount == 0 )
{
runState = keGetRecordList;
}
else
{
runState = keSetContinueData;
}
}
else
{
if ( siResult == keSearchNodeListEnd )
{
runState = keSetContinueData;
}
else
{
runState = keDone;
}
}
}
break;
case keSetContinueData:
case keDone:
case keError:
{
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown transition state = %l", runState );
done = true;
}
break;
} }
pContext->pSearchListMutex->SignalLock();
}
catch( SInt32 err )
{
if ( (pContext != nil) && (pContext->pSearchListMutex != nil) )
{
pContext->pSearchListMutex->SignalLock();
}
siResult = err;
}
if ( (inData->fIOContinueData == nil) && (pContinue != nil ) )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
return( siResult );
}
SInt32 CSearchPlugin::GetRecordEntry ( sGetRecordEntry *inData )
{
SInt32 siResult = eDSNoErr;
UInt32 uiIndex = 0;
UInt32 uiCount = 0;
UInt32 uiOffset = 0;
UInt32 uberOffset = 0;
char *pData = nil;
tRecordEntryPtr pRecEntry = nil;
sSearchContextData *pContext = nil;
CBuff inBuff;
UInt32 offset = 0;
UInt16 usTypeLen = 0;
char *pRecType = nil;
UInt16 usNameLen = 0;
char *pRecName = nil;
UInt16 usAttrCnt = 0;
UInt32 buffLen = 0;
try
{
if ( inData == nil ) throw( (SInt32)eMemoryError );
if ( inData->fInOutDataBuff == nil ) throw( (SInt32)eDSEmptyBuffer );
if (inData->fInOutDataBuff->fBufferSize == 0) throw( (SInt32)eDSEmptyBuffer );
siResult = inBuff.Initialize( inData->fInOutDataBuff );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inBuff.GetDataBlockCount( &uiCount );
if ( siResult != eDSNoErr ) throw( siResult );
uiIndex = inData->fInRecEntryIndex;
if ( uiIndex == 0 ) throw( (SInt32)eDSInvalidIndex );
if ( uiIndex > uiCount ) throw( (SInt32)eDSIndexOutOfRange );
pData = inBuff.GetDataBlock( uiIndex, &uberOffset );
if ( pData == nil ) throw( (SInt32)eDSCorruptBuffer );
buffLen = inBuff.GetDataBlockLength( uiIndex );
pData += 4;
offset = 0;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, pData, 2 );
pRecEntry = (tRecordEntry *)calloc( 1, sizeof( tRecordEntry ) + usNameLen + usTypeLen + 4 + kBuffPad );
pRecEntry->fRecordNameAndType.fBufferSize = usNameLen + usTypeLen + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = usNameLen + usTypeLen + 4;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData, &usNameLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecName, usNameLen );
uiOffset += usNameLen;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &usTypeLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecType, usTypeLen );
pRecEntry->fRecordAttributeCount = usAttrCnt;
pContext = MakeContextData();
if ( pContext == nil ) throw( (SInt32)eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
gSNNodeRef->AddItem( inData->fOutAttrListRef, pContext );
inData->fOutRecEntryPtr = pRecEntry;
}
catch( SInt32 err )
{
siResult = err;
}
return( siResult );
}
SInt32 CSearchPlugin::GetAttributeEntry ( sGetAttributeEntry *inData )
{
SInt32 siResult = eDSNoErr;
UInt16 usAttrTypeLen = 0;
UInt16 usAttrCnt = 0;
UInt32 usAttrLen = 0;
UInt16 usValueCnt = 0;
UInt32 usValueLen = 0;
UInt32 i = 0;
UInt32 uiIndex = 0;
UInt32 uiAttrEntrySize = 0;
UInt32 uiOffset = 0;
UInt32 uiTotalValueSize = 0;
UInt32 offset = 0;
UInt32 buffSize = 0;
UInt32 buffLen = 0;
char *p = nil;
char *pAttrType = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueListRef attrValueListRef = 0;
tAttributeEntryPtr pAttribInfo = nil;
sSearchContextData *pAttrContext = nil;
sSearchContextData *pValueContext = nil;
try
{
if ( inData == nil ) throw( (SInt32)eMemoryError );
pAttrContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInAttrListRef );
if ( pAttrContext == nil ) throw( (SInt32)eDSBadContextData );
uiIndex = inData->fInAttrInfoIndex;
if (uiIndex == 0) throw( (SInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (SInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pAttrContext->offset;
offset = pAttrContext->offset;
if (2 + offset > buffSize) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, p, 2 );
if (uiIndex > usAttrCnt) throw( (SInt32)eDSIndexOutOfRange );
p += 2;
offset += 2;
for ( i = 1; i < uiIndex; i++ )
{
if (4 + offset > buffSize) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (4 + offset > buffSize) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (4 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
uiTotalValueSize += usValueLen;
}
uiAttrEntrySize = sizeof( tAttributeEntry ) + usAttrTypeLen + kBuffPad;
pAttribInfo = (tAttributeEntry *)calloc( 1, uiAttrEntrySize );
pAttribInfo->fAttributeValueCount = usValueCnt;
pAttribInfo->fAttributeDataSize = uiTotalValueSize;
pAttribInfo->fAttributeValueMaxSize = 512; pAttribInfo->fAttributeSignature.fBufferSize = usAttrTypeLen + kBuffPad;
pAttribInfo->fAttributeSignature.fBufferLength = usAttrTypeLen;
::memcpy( pAttribInfo->fAttributeSignature.fBufferData, pAttrType, usAttrTypeLen );
attrValueListRef = inData->fOutAttrValueListRef;
pValueContext = MakeContextData();
if ( pValueContext == nil ) throw( (SInt32)eMemoryAllocError );
pValueContext->offset = uiOffset;
gSNNodeRef->AddItem( inData->fOutAttrValueListRef, pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
}
catch( SInt32 err )
{
siResult = err;
}
return( siResult );
}
SInt32 CSearchPlugin::GetAttributeValue ( sGetAttributeValue *inData )
{
SInt32 siResult = eDSNoErr;
UInt16 usValueCnt = 0;
UInt32 usValueLen = 0;
UInt16 usAttrNameLen = 0;
UInt32 i = 0;
UInt32 uiIndex = 0;
UInt32 offset = 0;
char *p = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueEntry *pAttrValue = nil;
sSearchContextData *pValueContext = nil;
UInt32 buffSize = 0;
UInt32 buffLen = 0;
UInt32 attrLen = 0;
try
{
pValueContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInAttrValueListRef );
if ( pValueContext == nil ) throw( (SInt32)eDSBadContextData );
uiIndex = inData->fInAttrValueIndex;
if (uiIndex == 0) throw( (SInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (SInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pValueContext->offset;
offset = pValueContext->offset;
if (4 + offset > buffSize) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( (SInt32)eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (2 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
if (uiIndex > usValueCnt) throw( (SInt32)eDSIndexOutOfRange );
for ( i = 1; i < uiIndex; i++ )
{
if (4 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (4 + offset > buffLen) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4;
offset += 4;
pAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + usValueLen + kBuffPad );
pAttrValue->fAttributeValueData.fBufferSize = usValueLen + kBuffPad;
pAttrValue->fAttributeValueData.fBufferLength = usValueLen;
if ( usValueLen + offset > buffLen ) throw( (SInt32)eDSInvalidBuffFormat );
::memcpy( pAttrValue->fAttributeValueData.fBufferData, p, usValueLen );
pAttrValue->fAttributeValueID = 0x00;
inData->fOutAttrValue = pAttrValue;
}
catch( SInt32 err )
{
siResult = err;
}
return( siResult );
}
SInt32 CSearchPlugin::AttributeValueSearch ( sDoAttrValueSearchWithData *inData )
{
SInt32 siResult = eDSNoErr;
UInt32 recCount = 0;
bool done = false;
sSearchContinueData *pContinue = nil;
sSearchContinueData *pInContinue = nil;
eSearchState runState = keGetRecordList; eSearchState lastState = keUnknownState;
CBuff inOutBuff;
sSearchContextData *pContext = nil;
bool bKeepOldBuffer = false;
try
{
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
if (pContext->pSearchListMutex == nil ) throw( (SInt32)eDSBadContextData);
siResult = CheckSearchPolicyChange(pContext, inData->fInNodeRef, inData->fIOContinueData);
pContext->pSearchListMutex->WaitLock();
if( siResult != eDSNoErr ) throw( siResult );
if ( pContext->fSearchNodeList == nil ) throw( (SInt32)eSearchPathNotDefined );
if ( inData->fIOContinueData != nil )
{
if ( gSNContinue->VerifyItem( inData->fIOContinueData ) == true )
{
pInContinue = (sSearchContinueData *)inData->fIOContinueData;
if (pInContinue->bNodeBuffTooSmall)
{
pInContinue->bNodeBuffTooSmall = false;
throw( (SInt32)eDSBufferTooSmall );
}
pContinue = (sSearchContinueData *)calloc( sizeof( sSearchContinueData ), sizeof(char) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDirRef = pInContinue->fDirRef;
pContinue->fNodeRef = pInContinue->fNodeRef;
pContinue->fAttrOnly = pInContinue->fAttrOnly;
pContinue->fRecCount = pInContinue->fRecCount;
pContinue->fRecIndex = pInContinue->fRecIndex;
pContinue->fState = pInContinue->fState;
pContinue->bIsAugmented = pInContinue->bIsAugmented;
pContinue->fAugmentReqAttribs = dsDataListCopyList( 0, pInContinue->fAugmentReqAttribs );
if (inData->fOutDataBuff->fBufferSize != pInContinue->fDataBuff->fBufferSize)
{
if (pContinue->fState == keAddDataToBuff)
{
bKeepOldBuffer = true;
pContinue->fDataBuff = pInContinue->fDataBuff; pInContinue->fDataBuff = nil; }
else
{
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
}
}
else
{
pContinue->fDataBuff = pInContinue->fDataBuff;
pInContinue->fDataBuff = nil;
}
pContinue->fContextData = pInContinue->fContextData;
pContinue->fLimitRecSearch = pInContinue->fLimitRecSearch;
pContinue->fTotalRecCount = pInContinue->fTotalRecCount;
pContinue->bNodeBuffTooSmall= pInContinue->bNodeBuffTooSmall;
pInContinue->fContextData = nil;
gSNContinue->RemoveItem( inData->fIOContinueData );
pInContinue = nil;
inData->fIOContinueData = nil;
runState = pContinue->fState;
}
else
{
throw( (SInt32)eDSInvalidContinueData );
}
}
else
{
pContinue = (sSearchContinueData *)calloc( 1, sizeof( sSearchContinueData ) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
siResult = GetNextNodeRef( 0, &pContinue->fNodeRef, pContext );
if ( siResult != eDSNoErr ) throw( siResult );
pContinue->fDirRef = fDirRef;
pContinue->fRecIndex = 1;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
pContinue->bNodeBuffTooSmall= false;
if (inData->fOutMatchRecordCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
siResult = inOutBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inOutBuff.SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
while ( !done )
{
switch ( runState )
{
case keGetRecordList:
{
if (pContinue->fLimitRecSearch > pContinue->fTotalRecCount)
{
recCount = pContinue->fLimitRecSearch - pContinue->fTotalRecCount;
}
else
{
recCount = 0;
}
if ( inData->fType == kDoAttributeValueSearchWithData )
{
siResult = ::dsDoAttributeValueSearchWithData(
pContinue->fNodeRef,
pContinue->fDataBuff,
inData->fInRecTypeList,
inData->fInAttrType,
inData->fInPattMatchType,
inData->fInPatt2Match,
(pContinue->bIsAugmented && pContinue->fAugmentReqAttribs ? pContinue->fAugmentReqAttribs : inData->fInAttrTypeRequestList),
inData->fInAttrInfoOnly,
&recCount,
&pContinue->fContextData );
}
else
{
siResult = ::dsDoAttributeValueSearch( pContinue->fNodeRef,
pContinue->fDataBuff,
inData->fInRecTypeList,
inData->fInAttrType,
inData->fInPattMatchType,
inData->fInPatt2Match,
&recCount,
&pContinue->fContextData );
}
pContinue->fRecCount = recCount;
pContinue->fRecIndex = 1;
lastState = keGetRecordList;
}
break;
case keAddDataToBuff:
{
if ( inData->fType == kDoAttributeValueSearchWithData )
{
siResult = AddDataToOutBuff( pContinue, &inOutBuff, pContext, inData->fInAttrTypeRequestList );
}
else
{
siResult = AddDataToOutBuff( pContinue, &inOutBuff, pContext, NULL );
}
if (bKeepOldBuffer)
{
if (siResult == eDSNoErr)
{
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
bKeepOldBuffer = false;
}
}
lastState = keAddDataToBuff;
}
break;
case keGetNextNodeRef:
{
siResult = GetNextNodeRef( pContinue->fNodeRef, &pContinue->fNodeRef, pContext );
lastState = keGetNextNodeRef;
if ( inData->fType == kDoAttributeValueSearchWithData && siResult == eDSNoErr )
UpdateContinueForAugmented( pContext, pContinue, inData->fInAttrTypeRequestList );
}
break;
case keSetContinueData:
{
switch ( lastState )
{
case keAddDataToBuff:
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = lastState;
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
siResult = eDSNoErr;
break;
case keGetRecordList:
case keGetNextNodeRef:
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = keGetRecordList;
if ( siResult == keSearchNodeListEnd )
{
siResult = eDSNoErr;
inData->fIOContinueData = nil;
}
else
{
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
}
break;
case keBufferTooSmall:
if (pContinue->fContextData == nil) {
pContinue->fState = keAddDataToBuff;
siResult = eDSBufferTooSmall;
}
else {
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
if (inData->fOutMatchRecordCount == 0)
{
siResult = eDSBufferTooSmall;
}
else
{
pContinue->bNodeBuffTooSmall= true;
siResult = eDSNoErr;
}
if( pContinue->fRecIndex <= pContinue->fRecCount )
pContinue->fState = keAddDataToBuff;
else
pContinue->fState = keGetRecordList;
}
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
break;
default:
DbgLog( kLogPlugin, "*** Invalid continue state = %l", lastState );
break;
}
}
break;
case keDone:
{
if ( pContinue != nil )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown run state = %l", runState );
done = true;
}
break;
}
switch ( runState )
{
case keGetRecordList:
{
if ( siResult == eDSNoErr )
{
if ( pContinue->fRecCount != 0 )
{
runState = keAddDataToBuff;
}
else if (pContinue->fContextData == nil)
{
runState = keGetNextNodeRef;
}
}
else if ( (siResult == eDSRecordNotFound ) ||
(siResult == eDSInvalidRecordName) ||
(siResult == eDSInvalidRecordType) )
{
runState = keGetNextNodeRef;
if (siResult == eDSInvalidRecordType)
{
if (pContinue->fContextData != nil)
{
dsReleaseContinueData(pContinue->fNodeRef, pContinue->fContextData);
pContinue->fContextData = nil;
}
}
}
else if (siResult == eDSBufferTooSmall)
{
lastState = keBufferTooSmall;
runState = keSetContinueData;
}
else {
runState = keGetNextNodeRef;
}
}
break;
case keAddDataToBuff:
{
UInt32 aRecCnt = 0;
inOutBuff.GetDataBlockCount(&aRecCnt);
if ( ( siResult == eDSNoErr ) || ( ( siResult == CBuff::kBuffFull ) && (aRecCnt > 0) ) )
{
inData->fOutMatchRecordCount = aRecCnt;
if ((pContinue->fLimitRecSearch <= (pContinue->fTotalRecCount + inData->fOutMatchRecordCount)) &&
(pContinue->fLimitRecSearch != 0))
{
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = runState;
runState = keDone;
inData->fIOContinueData = nil;
siResult = eDSNoErr;
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
}
else if ( pContinue->fContextData )
{
lastState = keGetRecordList;
runState = keGetRecordList;
}
else
{
runState = keGetNextNodeRef;
}
}
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
lastState = keBufferTooSmall;
}
else
{
runState = keDone;
}
}
}
break;
case keGetNextNodeRef:
{
inOutBuff.GetDataBlockCount( &recCount );
if ( siResult == eDSNoErr )
{
if ( recCount == 0 )
{
runState = keGetRecordList;
}
else
{
runState = keSetContinueData;
}
}
else
{
if ( siResult == keSearchNodeListEnd )
{
runState = keSetContinueData;
}
else
{
runState = keDone;
}
}
}
break;
case keSetContinueData:
case keDone:
case keError:
{
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown transition state = %l", runState );
done = true;
}
break;
} }
pContext->pSearchListMutex->SignalLock();
}
catch( SInt32 err )
{
if ( (pContext != nil) && (pContext->pSearchListMutex != nil) )
{
pContext->pSearchListMutex->SignalLock();
}
siResult = err;
}
if ( (inData->fIOContinueData == nil) && (pContinue != nil ) )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
return( siResult );
}
SInt32 CSearchPlugin::MultipleAttributeValueSearch ( sDoMultiAttrValueSearchWithData *inData )
{
SInt32 siResult = eDSNoErr;
UInt32 recCount = 0;
bool done = false;
sSearchContinueData *pContinue = nil;
sSearchContinueData *pInContinue = nil;
eSearchState runState = keGetRecordList; eSearchState lastState = keUnknownState;
CBuff inOutBuff;
sSearchContextData *pContext = nil;
bool bKeepOldBuffer = false;
try
{
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
if (pContext->pSearchListMutex == nil ) throw( (SInt32)eDSBadContextData);
siResult = CheckSearchPolicyChange(pContext, inData->fInNodeRef, inData->fIOContinueData);
pContext->pSearchListMutex->WaitLock();
if( siResult != eDSNoErr ) throw( siResult );
if ( pContext->fSearchNodeList == nil ) throw( (SInt32)eSearchPathNotDefined );
if ( inData->fIOContinueData != nil )
{
if ( gSNContinue->VerifyItem( inData->fIOContinueData ) == true )
{
pInContinue = (sSearchContinueData *)inData->fIOContinueData;
if (pInContinue->bNodeBuffTooSmall)
{
pInContinue->bNodeBuffTooSmall = false;
throw( (SInt32)eDSBufferTooSmall );
}
pContinue = (sSearchContinueData *)calloc( sizeof( sSearchContinueData ), sizeof(char) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDirRef = pInContinue->fDirRef;
pContinue->fNodeRef = pInContinue->fNodeRef;
pContinue->fAttrOnly = pInContinue->fAttrOnly;
pContinue->fRecCount = pInContinue->fRecCount;
pContinue->fRecIndex = pInContinue->fRecIndex;
pContinue->fState = pInContinue->fState;
pContinue->bIsAugmented = pInContinue->bIsAugmented;
pContinue->fAugmentReqAttribs = dsDataListCopyList( 0, pInContinue->fAugmentReqAttribs );
if (inData->fOutDataBuff->fBufferSize != pInContinue->fDataBuff->fBufferSize)
{
if (pContinue->fState == keAddDataToBuff)
{
bKeepOldBuffer = true;
pContinue->fDataBuff = pInContinue->fDataBuff; pInContinue->fDataBuff = nil; }
else
{
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
}
}
else
{
pContinue->fDataBuff = pInContinue->fDataBuff;
pInContinue->fDataBuff = nil;
}
pContinue->fContextData = pInContinue->fContextData;
pContinue->fLimitRecSearch = pInContinue->fLimitRecSearch;
pContinue->fTotalRecCount = pInContinue->fTotalRecCount;
pContinue->bNodeBuffTooSmall= pInContinue->bNodeBuffTooSmall;
pInContinue->fContextData = nil;
gSNContinue->RemoveItem( inData->fIOContinueData );
pInContinue = nil;
inData->fIOContinueData = nil;
runState = pContinue->fState;
}
else
{
throw( (SInt32)eDSInvalidContinueData );
}
}
else
{
pContinue = (sSearchContinueData *)calloc( 1, sizeof( sSearchContinueData ) );
if ( pContinue == nil ) throw( (SInt32)eMemoryAllocError );
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
siResult = GetNextNodeRef( 0, &pContinue->fNodeRef, pContext );
if ( siResult != eDSNoErr ) throw( siResult );
pContinue->fDirRef = fDirRef;
pContinue->fRecIndex = 1;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
pContinue->bNodeBuffTooSmall= false;
if (inData->fOutMatchRecordCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
siResult = inOutBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inOutBuff.SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
while ( !done )
{
switch ( runState )
{
case keGetRecordList:
{
if (pContinue->fLimitRecSearch > pContinue->fTotalRecCount)
{
recCount = pContinue->fLimitRecSearch - pContinue->fTotalRecCount;
}
else
{
recCount = 0;
}
if ( inData->fType == kDoMultipleAttributeValueSearchWithData )
{
siResult = ::dsDoMultipleAttributeValueSearchWithData(
pContinue->fNodeRef,
pContinue->fDataBuff,
inData->fInRecTypeList,
inData->fInAttrType,
inData->fInPattMatchType,
inData->fInPatterns2MatchList,
(pContinue->bIsAugmented && pContinue->fAugmentReqAttribs ? pContinue->fAugmentReqAttribs : inData->fInAttrTypeRequestList),
inData->fInAttrInfoOnly,
&recCount,
&pContinue->fContextData );
}
else
{
siResult = ::dsDoMultipleAttributeValueSearch(
pContinue->fNodeRef,
pContinue->fDataBuff,
inData->fInRecTypeList,
inData->fInAttrType,
inData->fInPattMatchType,
inData->fInPatterns2MatchList,
&recCount,
&pContinue->fContextData );
}
pContinue->fRecCount = recCount;
pContinue->fRecIndex = 1;
lastState = keGetRecordList;
}
break;
case keAddDataToBuff:
{
if ( inData->fType == kDoMultipleAttributeValueSearchWithData )
{
siResult = AddDataToOutBuff( pContinue, &inOutBuff, pContext, inData->fInAttrTypeRequestList );
}
else
{
siResult = AddDataToOutBuff( pContinue, &inOutBuff, pContext, NULL );
}
if (bKeepOldBuffer)
{
if (siResult == eDSNoErr)
{
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
pContinue->fDataBuff = ::dsDataBufferAllocatePriv( inData->fOutDataBuff->fBufferSize );
if ( pContinue->fDataBuff == nil ) throw( (SInt32)eMemoryAllocError );
bKeepOldBuffer = false;
}
}
lastState = keAddDataToBuff;
}
break;
case keGetNextNodeRef:
{
siResult = GetNextNodeRef( pContinue->fNodeRef, &pContinue->fNodeRef, pContext );
lastState = keGetNextNodeRef;
if ( inData->fType == kDoMultipleAttributeValueSearchWithData && siResult == eDSNoErr )
UpdateContinueForAugmented( pContext, pContinue, inData->fInAttrTypeRequestList );
}
break;
case keSetContinueData:
{
switch ( lastState )
{
case keAddDataToBuff:
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = lastState;
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
siResult = eDSNoErr;
break;
case keGetRecordList:
case keGetNextNodeRef:
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = keGetRecordList;
if ( siResult == keSearchNodeListEnd )
{
siResult = eDSNoErr;
inData->fIOContinueData = nil;
}
else
{
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
}
break;
case keBufferTooSmall:
if (pContinue->fContextData == nil) {
pContinue->fState = keAddDataToBuff;
siResult = eDSBufferTooSmall;
}
else {
inOutBuff.GetDataBlockCount( &inData->fOutMatchRecordCount );
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
if (inData->fOutMatchRecordCount == 0)
{
siResult = eDSBufferTooSmall;
}
else
{
pContinue->bNodeBuffTooSmall= true;
siResult = eDSNoErr;
}
if( pContinue->fRecIndex <= pContinue->fRecCount )
pContinue->fState = keAddDataToBuff;
else
pContinue->fState = keGetRecordList;
}
inData->fIOContinueData = pContinue;
gSNContinue->AddItem( pContinue, inData->fInNodeRef );
break;
default:
DbgLog( kLogPlugin, "*** Invalid continue state = %l", lastState );
break;
}
}
break;
case keDone:
{
if ( pContinue != nil )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown run state = %l", runState );
done = true;
}
break;
}
switch ( runState )
{
case keGetRecordList:
{
if ( siResult == eDSNoErr )
{
if ( pContinue->fRecCount != 0 )
{
runState = keAddDataToBuff;
}
else if (pContinue->fContextData == nil)
{
runState = keGetNextNodeRef;
}
}
else if ( (siResult == eDSRecordNotFound ) ||
(siResult == eDSInvalidRecordName) ||
(siResult == eDSInvalidRecordType) )
{
runState = keGetNextNodeRef;
if (siResult == eDSInvalidRecordType)
{
if (pContinue->fContextData != nil)
{
dsReleaseContinueData(pContinue->fNodeRef, pContinue->fContextData);
pContinue->fContextData = nil;
}
}
}
else if (siResult == eDSBufferTooSmall)
{
lastState = keBufferTooSmall;
runState = keSetContinueData;
}
else {
runState = keGetNextNodeRef;
}
}
break;
case keAddDataToBuff:
{
UInt32 aRecCnt = 0;
inOutBuff.GetDataBlockCount(&aRecCnt);
if ( ( siResult == eDSNoErr ) || ( ( siResult == CBuff::kBuffFull ) && (aRecCnt > 0) ) )
{
inData->fOutMatchRecordCount = aRecCnt;
if ((pContinue->fLimitRecSearch <= (pContinue->fTotalRecCount + inData->fOutMatchRecordCount)) &&
(pContinue->fLimitRecSearch != 0))
{
pContinue->fTotalRecCount += inData->fOutMatchRecordCount;
pContinue->fState = runState;
runState = keDone;
inData->fIOContinueData = nil;
siResult = eDSNoErr;
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
}
else if ( pContinue->fContextData )
{
lastState = keGetRecordList;
runState = keGetRecordList;
}
else
{
runState = keGetNextNodeRef;
}
}
}
else
{
if ( siResult == CBuff::kBuffFull )
{
runState = keSetContinueData;
lastState = keBufferTooSmall;
}
else
{
runState = keDone;
}
}
}
break;
case keGetNextNodeRef:
{
inOutBuff.GetDataBlockCount( &recCount );
if ( siResult == eDSNoErr )
{
if ( recCount == 0 )
{
runState = keGetRecordList;
}
else
{
runState = keSetContinueData;
}
}
else
{
if ( siResult == keSearchNodeListEnd )
{
runState = keSetContinueData;
}
else
{
runState = keDone;
}
}
}
break;
case keSetContinueData:
case keDone:
case keError:
{
done = true;
}
break;
default:
{
DbgLog( kLogPlugin, "*** Unknown transition state = %l", runState );
done = true;
}
break;
} }
pContext->pSearchListMutex->SignalLock();
}
catch( SInt32 err )
{
if ( (pContext != nil) && (pContext->pSearchListMutex != nil) )
{
pContext->pSearchListMutex->SignalLock();
}
siResult = err;
}
if ( (inData->fIOContinueData == nil) && (pContinue != nil ) )
{
CSearchPlugin::ContinueDeallocProc( pContinue );
pContinue = nil;
}
return( siResult );
}
void CSearchPlugin::SystemGoingToSleep( void )
{
OSAtomicTestAndSet( 0, &gSystemGoingToSleep );
sSearchConfig *aSearchConfig = NULL;
sSearchList *aSearchNodeList = NULL;
sSearchList *aNodeListPtr = NULL;
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey(eDSAuthenticationSearchNodeName);
if ( aSearchConfig != nil )
{
aSearchNodeList = aSearchConfig->fSearchNodeList;
if (aSearchNodeList != nil)
{
aNodeListPtr = aSearchNodeList->fNext; aNodeListPtr = aNodeListPtr->fNext; while (aNodeListPtr != nil)
{
if (aNodeListPtr->fNodeName != nil)
{
aNodeListPtr->fNodeReachable = false;
if ( gCacheNode != NULL )
{
DBGLOG1( kLogPlugin, "CSearchPlugin::SystemGoingToSleep updating node reachability <%s> to <Unavailable>",
aNodeListPtr->fNodeName );
gCacheNode->UpdateNodeReachability( aNodeListPtr->fNodeName, false );
}
}
aNodeListPtr = aNodeListPtr->fNext;
}
}
}
fMutex.SignalLock();
}
void CSearchPlugin::SystemWillPowerOn( void )
{
DBGLOG( kLogPlugin, "CSearchPlugin::SystemWillPowerOn request" );
OSAtomicTestAndClear( 0, &gSystemGoingToSleep );
EnsureCheckNodesThreadIsRunning( eDSAuthenticationSearchNodeName ); EnsureCheckNodesThreadIsRunning( eDSContactsSearchNodeName ); }
#pragma mark -
#pragma mark Support Routines
#pragma mark -
void CSearchPlugin::UpdateContinueForAugmented( sSearchContextData *inContext, sSearchContinueData *inContinue, tDataListPtr inAttrTypeRequestList )
{
if ( IsAugmented(inContext, inContinue->fNodeRef) == true && inAttrTypeRequestList != NULL )
{
bool bAddRecordName = true;
inContinue->bIsAugmented = true;
tDataBufferPriv *pPrivData = (tDataBufferPriv *) (inAttrTypeRequestList != NULL ? inAttrTypeRequestList->fDataListHead : NULL);
while ( pPrivData != NULL )
{
if ( strcmp(pPrivData->fBufferData, kDSAttributesStandardAll) == 0 ||
strcmp(pPrivData->fBufferData, kDSAttributesAll) == 0 ||
strcmp(pPrivData->fBufferData, kDSNAttrRecordName) == 0 )
{
bAddRecordName = false;
break;
}
pPrivData = (tDataBufferPriv *) pPrivData->fNextPtr;
}
if ( bAddRecordName == true )
{
inContinue->fAugmentReqAttribs = dsDataListCopyList( 0, inAttrTypeRequestList );
dsAppendStringToListAllocPriv( inContinue->fAugmentReqAttribs, kDSNAttrRecordName );
}
}
else
{
inContinue->bIsAugmented = false;
}
}
bool CSearchPlugin::IsAugmented( sSearchContextData *inContext, tDirNodeReference inNodeRef )
{
if ( inContext != NULL && inNodeRef != 0 && inContext->pConfigFromXML != NULL && inContext->pConfigFromXML->AugmentSearch() )
{
char *augmentingNodeName = inContext->pConfigFromXML->AugmentDirNodeName();
bool bAugmentOK = false;
char *thisNodeName = NULL;
sSearchList *aList = inContext->fSearchNodeList;
while ( aList != NULL )
{
if ( aList->fNodeRef == inNodeRef )
thisNodeName = aList->fNodeName;
if ( aList->fNodeName != NULL && strcmp(aList->fNodeName, augmentingNodeName) == 0 )
bAugmentOK = true;
aList = aList->fNext;
}
if ( bAugmentOK && thisNodeName != NULL && strcmp(thisNodeName, inContext->pConfigFromXML->ToBeAugmentedDirNodeName()) == 0 )
return true;
}
return false;
}
SInt32 CSearchPlugin::GetNextNodeRef ( tDirNodeReference inNodeRef, tDirNodeReference *outNodeRef, sSearchContextData *inContext )
{
SInt32 siResult = keSearchNodeListEnd;
sSearchList *pNodeList = nil;
tDirNodeReference aNodeRef = inNodeRef;
UInt32 nodeIndex = 0;
bool bFailedToOpen = false;
pNodeList = (sSearchList *)inContext->fSearchNodeList;
if (aNodeRef != 0) {
while ( pNodeList != nil )
{
nodeIndex++;
if ( aNodeRef == pNodeList->fNodeRef )
{
pNodeList = pNodeList->fNext;
break;
}
pNodeList = pNodeList->fNext;
}
}
if ( (nodeIndex == 0) || (nodeIndex == 1) ) {
pNodeList->fNodeReachable = true;
pNodeList->fHasNeverOpened = false;
}
while ( pNodeList != nil )
{
if (pNodeList->fNodeReachable)
{
if ( pNodeList->fOpened == false )
{
siResult = ::dsOpenDirNode( fDirRef, pNodeList->fDataList, &pNodeList->fNodeRef );
if ( siResult == eDSNoErr )
{
*outNodeRef = pNodeList->fNodeRef;
pNodeList->fOpened = true;
break;
}
else
{
siResult = keSearchNodeListEnd;
fSomeNodeFailedToOpen = true;
bFailedToOpen = true;
}
}
else
{
*outNodeRef = pNodeList->fNodeRef;
siResult = eDSNoErr;
break;
}
}
pNodeList = pNodeList->fNext;
}
if ( bFailedToOpen == true )
EnsureCheckNodesThreadIsRunning( (tDirPatternMatch) inContext->fSearchConfigKey );
return( siResult );
}
tDataList* CSearchPlugin::GetNodePath ( tDirNodeReference inNodeRef, sSearchContextData *inContext )
{
tDataList *pResult = nil;
sSearchList *pNodeList = nil;
pNodeList = (sSearchList *)inContext->fSearchNodeList;
while ( pNodeList != nil )
{
if ( inNodeRef == pNodeList->fNodeRef )
{
pResult = pNodeList->fDataList;
break;
}
pNodeList = pNodeList->fNext;
}
return( pResult );
}
sSearchContextData* CSearchPlugin::MakeContextData ( void )
{
sSearchContextData *pOut = nil;
pOut = (sSearchContextData *) calloc( 1, sizeof(sSearchContextData) );
if ( pOut != nil )
{
pOut->fSearchNodeList = nil;
pOut->bListChanged = false;
pOut->pSearchListMutex = nil;
pOut->fSearchNode = this;
pOut->bAutoSearchList = false;
pOut->bCheckForNIParentNow = false;
#if AUGMENT_RECORDS
pOut->pConfigFromXML = nil;
#endif
}
return( pOut );
}
SInt32 CSearchPlugin::CleanContextData ( sSearchContextData *inContext )
{
SInt32 siResult = eDSNoErr;
DSMutexSemaphore *ourMutex = nil;
if (( inContext == nil ) || ( gSearchNode == nil ))
{
siResult = eDSBadContextData;
}
else
{
ourMutex = inContext->pSearchListMutex;
if (ourMutex != nil)
{
ourMutex->WaitLock();
if (inContext->fSearchNodeList != nil && inContext->fSearchNode != nil)
{
gSearchNode->CleanSearchListData( inContext->fSearchNodeList );
inContext->fSearchNodeList = nil;
}
OSAtomicCompareAndSwap32Barrier(true, false, &inContext->bListChanged);
inContext->offset = 0;
inContext->fSearchConfigKey = 0;
inContext->pSearchListMutex = nil;
inContext->bAutoSearchList = false;
inContext->bCheckForNIParentNow = false;
#if AUGMENT_RECORDS
inContext->pConfigFromXML = nil; #endif
delete(ourMutex);
ourMutex = nil;
}
free( inContext );
inContext = nil;
}
return( siResult );
}
SInt32 CSearchPlugin::AddDataToOutBuff ( sSearchContinueData *inContinue, CBuff *inOutBuff, sSearchContextData *inContext, tDataListPtr inRequestedAttrList )
{
UInt32 i = 1;
UInt32 j = 1;
SInt32 attrCnt = 0;
SInt32 siResult = eDSNoErr;
char *cpRecType = nil;
char *cpRecName = nil;
tRecordEntry *pRecEntry = nil;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef valueRef = 0;
tAttributeEntry *pAttrEntry = nil;
tAttributeValueEntry *pValueEntry = nil;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
CDataBuff *aTmpData = nil;
#if AUGMENT_RECORDS
bool bAugmentThisNode= false;
bool bAskedForGUIDinAugment = false;
char* augGUIDValue = nil;
CFMutableArrayRef realNodeAttrList= NULL;
CFArrayRef anArray = NULL;
CFMutableArrayRef augNodeAttrList = NULL;
char* realNodeGUID = nil;
char* recTypeSuffix = nil;
#endif
try
{
aRecData = new CDataBuff();
aAttrData = new CDataBuff();
aTmpData = new CDataBuff();
while ( (inContinue->fRecIndex <= inContinue->fRecCount) && (siResult == eDSNoErr) )
{
attrCnt = 0;
siResult = ::dsGetRecordEntry( inContinue->fNodeRef, inContinue->fDataBuff, inContinue->fRecIndex, &attrListRef, &pRecEntry );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = ::dsGetRecordTypeFromEntry( pRecEntry, &cpRecType );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = ::dsGetRecordNameFromEntry( pRecEntry, &cpRecName );
if ( siResult != eDSNoErr ) throw( siResult );
aRecData->Clear();
aAttrData->Clear();
aTmpData->Clear();
aRecData->AppendShort( ::strlen( cpRecType ) );
aRecData->AppendString( cpRecType );
aRecData->AppendShort( ::strlen( cpRecName ) );
aRecData->AppendString( cpRecName );
#if AUGMENT_RECORDS
if ( IsAugmented(inContext, inContinue->fNodeRef) == true )
{
CFDictionaryRef aDict = inContext->pConfigFromXML->AugmentAttrListDict();
if (aDict != NULL)
{
if (strncmp(cpRecType, kDSStdRecordTypePrefix, sizeof(kDSStdRecordTypePrefix)-1) == 0)
{
recTypeSuffix = &cpRecType[sizeof(kDSStdRecordTypePrefix)-1];
}
if (recTypeSuffix != NULL)
{
CFStringRef cfRecType = CFStringCreateWithCString( NULL, cpRecType, kCFStringEncodingUTF8 );
anArray = (CFArrayRef)CFDictionaryGetValue( aDict, cfRecType );
DSCFRelease(cfRecType);
if (anArray != NULL ) {
bAugmentThisNode = true;
CFIndex arrayCnt = CFArrayGetCount(anArray);
if (arrayCnt > 0)
{
if (fAugmentNodeRef == 0)
{
char* nodeName = inContext->pConfigFromXML->AugmentDirNodeName();
if (nodeName != nil)
{
tDataListPtr aNodeName = dsBuildFromPathPriv( nodeName, "/" );
siResult = dsOpenDirNode( fDirRef, aNodeName, &fAugmentNodeRef );
dsDataListDeallocatePriv( aNodeName );
free( aNodeName );
}
}
} } } } }
#endif
if ( pRecEntry->fRecordAttributeCount != 0 )
{
attrCnt += pRecEntry->fRecordAttributeCount;
for ( i = 1; i <= pRecEntry->fRecordAttributeCount; i++ )
{
siResult = ::dsGetAttributeEntry( inContinue->fNodeRef, inContinue->fDataBuff, attrListRef, i, &valueRef, &pAttrEntry );
if ( siResult != eDSNoErr ) throw( siResult );
#if AUGMENT_RECORDS
if (bAugmentThisNode)
{
if ( inContinue->bIsAugmented && inContinue->fAugmentReqAttribs != NULL )
{
if ( strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName) == 0 )
{
attrCnt--; goto skipRecord;
}
}
if (realNodeAttrList == NULL)
realNodeAttrList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
CFStringRef cfTempString = CFStringCreateWithCString( kCFAllocatorDefault, pAttrEntry->fAttributeSignature.fBufferData,
kCFStringEncodingUTF8 );
CFArrayAppendValue( realNodeAttrList, cfTempString );
DSCFRelease( cfTempString );
}
#endif
aTmpData->AppendShort( ::strlen( pAttrEntry->fAttributeSignature.fBufferData ) );
aTmpData->AppendString( pAttrEntry->fAttributeSignature.fBufferData );
if ( inContinue->fAttrOnly == false )
{
aTmpData->AppendShort( pAttrEntry->fAttributeValueCount );
for ( j = 1; j <= pAttrEntry->fAttributeValueCount; j++ )
{
siResult = dsGetAttributeValue( inContinue->fNodeRef, inContinue->fDataBuff, j, valueRef, &pValueEntry );
if ( siResult != eDSNoErr ) throw( siResult );
#if AUGMENT_RECORDS
if (bAugmentThisNode)
{
if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDS1AttrGeneratedUID) == 0)
{
realNodeGUID = strdup(pValueEntry->fAttributeValueData.fBufferData);
}
}
#endif
aTmpData->AppendLong( pValueEntry->fAttributeValueData.fBufferLength );
aTmpData->AppendBlock( pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength );
dsDeallocAttributeValueEntry(fDirRef, pValueEntry);
pValueEntry = nil;
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
#if AUGMENT_RECORDS
skipRecord:
#endif
aTmpData->Clear();
dsCloseAttributeValueList(valueRef);
dsDeallocAttributeEntry(fDirRef, pAttrEntry);
pAttrEntry = nil;
}
}
#if AUGMENT_RECORDS
if ( (fAugmentNodeRef != 0) && bAugmentThisNode )
{
tDataListPtr augmentRecName = nil;
tDataListPtr augmentRecType = nil;
tDataListPtr augmentAttrTypes = nil;
UInt32 augmentRecCount = 1; tDataBufferPtr dataBuff = nil;
tContextData augmentContext = nil;
dataBuff = dsDataBufferAllocate( fDirRef, 1024 );
if ( dataBuff == nil ) throw( (SInt32)eMemoryAllocError );
char * cpAugmentRecName = (char *)calloc(1, strlen(cpRecName) + 1 + strlen(recTypeSuffix) + 1);
strcpy(cpAugmentRecName, recTypeSuffix);
strcat(cpAugmentRecName, ":");
strcat(cpAugmentRecName, cpRecName);
augmentRecName = dsBuildListFromStrings( fDirRef, cpAugmentRecName, NULL );
augmentRecType = dsBuildListFromStrings( fDirRef, kDSStdRecordTypeAugments, NULL );
CFMutableArrayRef reqAttrList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
bool bReqAll = false;
if (inRequestedAttrList == NULL)
{
bReqAll = true;
}
else
{
CAttributeList* cpAttrTypeList = new CAttributeList( inRequestedAttrList );
if ( cpAttrTypeList == nil ) throw( (SInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0)
{
DSCFRelease( reqAttrList );
DSDelete( cpAttrTypeList );
throw( (SInt32)eDSEmptyAttributeTypeList );
}
if (cpAttrTypeList->GetCount() == 1)
{
char* pAttrType = nil;
cpAttrTypeList->GetAttribute( 1, &pAttrType );
if (pAttrType != nil)
{
if (strcmp(pAttrType, kDSAttributesAll) == 0 )
{
bReqAll = true;
}
}
}
if (!bReqAll)
{
for (UInt32 anIndex = 1; anIndex <= cpAttrTypeList->GetCount(); anIndex++)
{
char* aString = nil;
cpAttrTypeList->GetAttribute( anIndex, &aString );
if (aString != NULL)
{
CFStringRef aCFString = CFStringCreateWithCString( kCFAllocatorDefault, aString, kCFStringEncodingUTF8 );
CFArrayAppendValue(reqAttrList, aCFString);
DSCFRelease(aCFString);
}
}
}
DSDelete( cpAttrTypeList );
}
augNodeAttrList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if ( anArray != NULL && realNodeAttrList != NULL )
{
for (CFIndex arrayIndex = 0; arrayIndex < CFArrayGetCount(anArray); arrayIndex++)
{
CFStringRef anItem = (CFStringRef)CFArrayGetValueAtIndex(anArray, arrayIndex);
if (anItem != NULL)
{
if ( CFArrayContainsValue(realNodeAttrList, CFRangeMake(0, CFArrayGetCount(realNodeAttrList)), anItem) == FALSE )
{
if (bReqAll)
{
CFArrayAppendValue(augNodeAttrList, anItem);
}
else if (augNodeAttrList != NULL)
{
if ( CFArrayContainsValue(reqAttrList, CFRangeMake( 0, ::CFArrayGetCount( reqAttrList ) ), anItem) )
{
CFArrayAppendValue(augNodeAttrList, anItem);
}
}
}
} }
} bool firstAddedToList = false;
if (realNodeGUID != nil)
{
augmentAttrTypes = dsBuildListFromStrings( fDirRef, kDS1AttrGeneratedUID, NULL );
firstAddedToList = true;
}
CFIndex arrayCnt = CFArrayGetCount(augNodeAttrList);
for (CFIndex arrayIndex = 0; arrayIndex < arrayCnt; arrayIndex++)
{
const char * aString = CFStringGetCStringPtr( (CFStringRef)CFArrayGetValueAtIndex(augNodeAttrList, arrayIndex), kCFStringEncodingUTF8 );
char* ioCStr = nil;
if (aString == NULL)
{
CFStringRef aCFStr = (CFStringRef)CFArrayGetValueAtIndex(augNodeAttrList, arrayIndex);
CFIndex maxCStrLen = CFStringGetMaximumSizeForEncoding( CFStringGetLength( aCFStr ), kCFStringEncodingUTF8 ) + 1;
size_t ioCStrSize = 0;
ioCStr = (char*)calloc( 1, maxCStrLen );
ioCStrSize = maxCStrLen;
if( CFStringGetCString( aCFStr, ioCStr, ioCStrSize, kCFStringEncodingUTF8 ) )
{
aString = ioCStr;
}
}
if (aString != NULL)
{
if (strcmp(aString, kDS1AttrGeneratedUID) != 0)
{
if (firstAddedToList)
{
dsAppendStringToListAlloc(0, augmentAttrTypes, aString );
}
else
{
augmentAttrTypes = dsBuildListFromStrings( fDirRef, aString, NULL );
firstAddedToList = true;
}
}
else
{
bAskedForGUIDinAugment = true;
}
}
DSFreeString(ioCStr);
}
DSCFRelease( reqAttrList );
DSCFRelease( augNodeAttrList );
do
{
siResult = dsGetRecordList( fAugmentNodeRef,
dataBuff,
augmentRecName,
eDSExact, augmentRecType,
augmentAttrTypes,
inContinue->fAttrOnly,
&augmentRecCount,
&augmentContext);
if (siResult == eDSBufferTooSmall)
{
UInt32 bufSize = dataBuff->fBufferSize;
dsDataBufferDeallocatePriv( dataBuff );
dataBuff = nil;
dataBuff = ::dsDataBufferAllocate( fDirRef, bufSize * 2 );
}
} while ( (siResult == eDSBufferTooSmall) || ( (siResult == eDSNoErr) && (augmentRecCount == 0) && (augmentContext != nil) ) );
DSFreeString( cpAugmentRecName );
if ( augmentRecName != NULL ) {
dsDataListDeallocatePriv( augmentRecName );
DSFree( augmentRecName );
}
if ( augmentRecType != NULL ) {
dsDataListDeallocatePriv( augmentRecType );
DSFree( augmentRecType );
}
if ( augmentAttrTypes != NULL ) {
dsDataListDeallocatePriv( augmentAttrTypes );
DSFree( augmentAttrTypes );
}
tRecordEntry *pAugRecEntry = nil;
tAttributeListRef attrAugListRef = 0;
tAttributeValueListRef valueAugRef = 0;
tAttributeEntry *pAugAttrEntry = nil;
tAttributeValueEntry *pAugValueEntry = nil;
if ( (siResult == eDSNoErr) && (augmentRecCount > 0) )
{
siResult = ::dsGetRecordEntry( fAugmentNodeRef, dataBuff, 1, &attrAugListRef, &pAugRecEntry );
if ( (siResult == eDSNoErr) && (pAugRecEntry != nil) )
{
for ( i = 1; i <= pAugRecEntry->fRecordAttributeCount; i++ )
{
attrCnt++;
siResult = ::dsGetAttributeEntry( fAugmentNodeRef, dataBuff, attrAugListRef, i, &valueAugRef, &pAugAttrEntry );
if ( siResult != eDSNoErr ) break;
aTmpData->AppendShort( ::strlen( pAugAttrEntry->fAttributeSignature.fBufferData ) );
aTmpData->AppendString( pAugAttrEntry->fAttributeSignature.fBufferData );
bool bAddAttr = true;
bool bGetGUID = false;
if ( inContinue->fAttrOnly == false )
{
if ( ::strcmp( pAugAttrEntry->fAttributeSignature.fBufferData, kDS1AttrGeneratedUID ) == 0 )
{
if (!bAskedForGUIDinAugment)
{
bAddAttr = false;
attrCnt--; }
bGetGUID = true;
}
if (bAddAttr)
{
aTmpData->AppendShort( pAugAttrEntry->fAttributeValueCount );
}
for ( j = 1; j <= pAugAttrEntry->fAttributeValueCount; j++ )
{
siResult = dsGetAttributeValue( fAugmentNodeRef, dataBuff, j, valueAugRef, &pAugValueEntry );
if ( siResult != eDSNoErr ) break;
if (bAddAttr)
{
aTmpData->AppendLong( pAugValueEntry->fAttributeValueData.fBufferLength );
aTmpData->AppendBlock( pAugValueEntry->fAttributeValueData.fBufferData, pAugValueEntry->fAttributeValueData.fBufferLength );
}
if (bGetGUID)
{
augGUIDValue = strdup(pAugValueEntry->fAttributeValueData.fBufferData);
}
if ( pAugValueEntry != NULL )
{
dsDeallocAttributeValueEntry( fDirRef, pAugValueEntry );
pAugValueEntry = NULL;
}
}
if ( siResult != eDSNoErr )
break;
}
else
{
aTmpData->AppendShort( 0 );
}
if (bAddAttr)
{
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
}
aTmpData->Clear();
dsCloseAttributeValueList(valueAugRef);
if (pAugAttrEntry != nil)
{
dsDeallocAttributeEntry(fDirRef, pAugAttrEntry);
pAugAttrEntry = nil;
}
}
}
dsCloseAttributeList(attrAugListRef);
if (pAugRecEntry != nil)
{
dsDeallocRecordEntry(fDirRef, pAugRecEntry);
pAugRecEntry = nil;
}
}
if ( dataBuff != NULL ) {
dsDataBufferDeallocatePriv( dataBuff );
dataBuff = NULL;
}
}
#endif
DSFreeString( cpRecName );
DSFreeString( cpRecType );
aRecData->AppendShort( attrCnt );
if ( attrCnt != 0 )
{
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
siResult = inOutBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
if ( siResult == eDSNoErr )
{
inContinue->fRecIndex++;
}
dsCloseAttributeList(attrListRef);
dsDeallocRecordEntry(fDirRef, pRecEntry);
pRecEntry = nil;
#if AUGMENT_RECORDS
DSCFRelease( realNodeAttrList ); #endif
} }
catch( SInt32 err )
{
siResult = err;
}
if ( cpRecType != nil )
{
free( cpRecType );
cpRecType = nil;
}
if ( cpRecName != nil )
{
free( cpRecName );
cpRecName = nil;
}
if ( aRecData != nil )
{
delete(aRecData);
aRecData = nil;
}
if ( aAttrData != nil )
{
delete(aAttrData);
aAttrData = nil;
}
if ( aTmpData != nil )
{
delete(aTmpData);
aTmpData = nil;
}
#if AUGMENT_RECORDS
DSFreeString(realNodeGUID);
DSFreeString(augGUIDValue);
#endif
return( siResult );
}
SInt32 CSearchPlugin::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
SInt32 siResult = eDSNoErr;
bool bAuthSwitched = false;
UInt32 aRequest = 0;
SInt32 xmlDataLength = 0;
CFDataRef xmlData = nil;
CFDictionaryRef dhcpLDAPdict = nil;
CFMutableArrayRef cspArray = nil;
UInt32 bufLen = 0;
sSearchContextData *pContext = nil;
sSearchConfig *aSearchConfig = nil;
sSearchList *nodeListPtr = nil;
AuthorizationRef authRef = 0;
AuthorizationItemSet *resultRightSet = NULL;
AuthorizationExternalForm blankExtForm;
bool verifyAuthRef = true;
CFRange aRange;
try
{
if ( inData == nil ) throw( (SInt32)eDSNullParameter );
if ( inData->fInRequestData == nil ) throw( (SInt32)eDSNullDataBuff );
if ( inData->fInRequestData->fBufferData == nil ) throw( (SInt32)eDSEmptyBuffer );
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (SInt32)eDSInvalidNodeRef );
if (pContext->fSearchConfigKey == eDSNetworkSearchNodeName) throw( (SInt32)eDSInvalidNodeRef );
aRequest = inData->fInRequestCode;
bufLen = inData->fInRequestData->fBufferLength;
if (aRequest != eDSCustomCallSearchSubNodesUnreachable && aRequest != eDSCustomCallSearchCheckForAugmentRecord)
{
if ( pContext->fEffectiveUID == 0 )
{
if ( bufLen >= sizeof(AuthorizationExternalForm) )
{
bzero(&blankExtForm, sizeof(AuthorizationExternalForm));
if (memcmp(inData->fInRequestData->fBufferData, &blankExtForm, sizeof(AuthorizationExternalForm)) == 0)
verifyAuthRef = false;
}
else
{
verifyAuthRef = false;
}
}
else
{
if ( bufLen < sizeof(AuthorizationExternalForm) )
throw( (SInt32)eDSInvalidBuffFormat );
}
if (verifyAuthRef) {
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInRequestData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
DbgLog( kLogPlugin, "CSearchPlugin: AuthorizationCreateFromExternalForm returned error %d", siResult );
syslog( LOG_ALERT, "Search Custom Call <%d> AuthorizationCreateFromExternalForm returned error %d", aRequest, siResult );
throw( (SInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.services.directory.configure", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, &resultRightSet);
if (resultRightSet != NULL)
{
AuthorizationFreeItemSet(resultRightSet);
resultRightSet = NULL;
}
if (siResult != errAuthorizationSuccess)
{
DbgLog( kLogPlugin, "CSearchPlugin: AuthorizationCopyRights returned error %d", siResult );
syslog( LOG_ALERT, "AuthorizationCopyRights returned error %d", siResult );
throw( (SInt32)eDSPermissionError );
}
}
}
fMutex.WaitLock();
try
{
DSEventSemaphore *eventSemaphore = NULL;
aSearchConfig = FindSearchConfigWithKey(pContext->fSearchConfigKey);
if ( aSearchConfig == nil ) throw( (SInt32)eDSInvalidNodeRef );
if ( aSearchConfig->fSearchNodeList == nil ) throw( (SInt32)eSearchPathNotDefined );
switch( aRequest )
{
case eDSCustomCallSearchSetPolicyAutomatic:
bAuthSwitched = SwitchSearchPolicy( kAutomaticSearchPolicy, aSearchConfig );
if (aSearchConfig->pConfigFromXML)
{
siResult = aSearchConfig->pConfigFromXML->SetSearchPolicy(kAutomaticSearchPolicy);
siResult = aSearchConfig->pConfigFromXML->WriteConfig();
}
break;
case eDSCustomCallSearchSetPolicyLocalOnly:
bAuthSwitched = SwitchSearchPolicy( kLocalSearchPolicy, aSearchConfig );
if (aSearchConfig->pConfigFromXML)
{
siResult = aSearchConfig->pConfigFromXML->SetSearchPolicy(kLocalSearchPolicy);
siResult = aSearchConfig->pConfigFromXML->WriteConfig();
}
break;
case eDSCustomCallSearchSetPolicyCustom:
eventSemaphore = &fAuthPolicyChangeEvent;
if ( aSearchConfig->fSearchConfigKey == eDSContactsSearchNodeName )
eventSemaphore = &fContactPolicyChangeEvent;
eventSemaphore->ResetEvent();
bAuthSwitched = SwitchSearchPolicy( kCustomSearchPolicy, aSearchConfig );
if (aSearchConfig->pConfigFromXML)
{
siResult = aSearchConfig->pConfigFromXML->SetSearchPolicy(kCustomSearchPolicy);
siResult = aSearchConfig->pConfigFromXML->WriteConfig();
}
if ( (bAuthSwitched && aSearchConfig->fSearchConfigKey == eDSAuthenticationSearchNodeName) ||
aSearchConfig->fSearchConfigKey == eDSContactsSearchNodeName )
{
fMutex.SignalLock();
if ( eventSemaphore->WaitForEvent(15 * kMilliSecsPerSec) == false )
{
DbgLog( kLogPlugin, "CSearchPlugin::DoPluginCustomCall - eDSCustomCallSearchSetPolicyCustom - timed out waiting for node check" );
}
fMutex.WaitLock();
#if AUGMENT_RECORDS
CheckForAugmentConfig( (tDirPatternMatch) aSearchConfig->fSearchConfigKey );
#endif
}
break;
#if AUGMENT_RECORDS
case eDSCustomCallSearchCheckForAugmentRecord:
CheckForAugmentConfig( (tDirPatternMatch) aSearchConfig->fSearchConfigKey );
break;
#endif
case eDSCustomCallSearchSetCustomNodeList:
xmlDataLength = (SInt32) bufLen - sizeof( AuthorizationExternalForm );
if ( xmlDataLength <= 0 ) throw( (SInt32)eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL,(UInt8 *)(inData->fInRequestData->fBufferData + sizeof( AuthorizationExternalForm )),xmlDataLength);
cspArray = (CFMutableArrayRef)CFPropertyListCreateFromXMLData(NULL,xmlData,0,NULL);
if (aSearchConfig->pConfigFromXML)
{
siResult = aSearchConfig->pConfigFromXML->SetListArray(cspArray);
siResult = aSearchConfig->pConfigFromXML->WriteConfig();
}
CFRelease(cspArray);
CFRelease(xmlData);
if ( aSearchConfig->fSearchNodePolicy == kCustomSearchPolicy )
{
eventSemaphore = &fAuthPolicyChangeEvent;
if ( aSearchConfig->fSearchConfigKey == eDSContactsSearchNodeName )
eventSemaphore = &fContactPolicyChangeEvent;
eventSemaphore->ResetEvent();
bAuthSwitched = SwitchSearchPolicy( kCustomSearchPolicy, aSearchConfig );
if ( (bAuthSwitched && aSearchConfig->fSearchConfigKey == eDSAuthenticationSearchNodeName) ||
aSearchConfig->fSearchConfigKey == eDSContactsSearchNodeName )
{
fMutex.SignalLock();
if ( eventSemaphore->WaitForEvent(15 * kMilliSecsPerSec) == false )
{
DbgLog( kLogPlugin, "CSearchPlugin::DoPluginCustomCall - eDSCustomCallSearchSetCustomNodeList timed out waiting for node check" );
}
fMutex.WaitLock();
#if AUGMENT_RECORDS
CheckForAugmentConfig( (tDirPatternMatch) aSearchConfig->fSearchConfigKey );
#endif
}
}
break;
case eDSCustomCallSearchReadDHCPLDAPSize:
if ( inData->fOutRequestResponse == nil ) throw( (SInt32)eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( (SInt32)eDSEmptyBuffer );
if ( inData->fOutRequestResponse->fBufferSize < sizeof( CFIndex ) ) throw( (SInt32)eDSInvalidBuffFormat );
if ( aSearchConfig->pConfigFromXML != nil)
{
dhcpLDAPdict = aSearchConfig->pConfigFromXML->GetDHCPLDAPDictionary();
if (dhcpLDAPdict != 0)
{
xmlData = CFPropertyListCreateXMLData(NULL,dhcpLDAPdict);
}
if (xmlData != 0)
{
*(CFIndex*)(inData->fOutRequestResponse->fBufferData) = CFDataGetLength(xmlData);
inData->fOutRequestResponse->fBufferLength = sizeof( CFIndex );
CFRelease(xmlData);
xmlData = 0;
}
else
{
*(CFIndex*)(inData->fOutRequestResponse->fBufferData) = 0;
inData->fOutRequestResponse->fBufferLength = sizeof( CFIndex );
}
}
break;
case eDSCustomCallSearchReadDHCPLDAPData:
if ( inData->fOutRequestResponse == nil ) throw( (SInt32)eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( (SInt32)eDSEmptyBuffer );
if ( aSearchConfig->pConfigFromXML != nil )
{
dhcpLDAPdict = aSearchConfig->pConfigFromXML->GetDHCPLDAPDictionary();
if (dhcpLDAPdict != 0)
{
xmlData = CFPropertyListCreateXMLData(NULL,dhcpLDAPdict);
if (xmlData != 0)
{
aRange.location = 0;
aRange.length = CFDataGetLength( xmlData );
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length )
throw( (SInt32)eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
CFRelease( xmlData );
xmlData = 0;
}
}
}
break;
case eDSCustomCallSearchWriteDHCPLDAPData:
xmlDataLength = (SInt32) bufLen - sizeof( AuthorizationExternalForm );
if ( xmlDataLength <= 0 ) throw( (SInt32)eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL,(UInt8 *)(inData->fInRequestData->fBufferData + sizeof( AuthorizationExternalForm )),xmlDataLength);
dhcpLDAPdict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(NULL,xmlData,0,NULL);
if (aSearchConfig->pConfigFromXML)
{
aSearchConfig->pConfigFromXML->SetDHCPLDAPDictionary(dhcpLDAPdict);
siResult = aSearchConfig->pConfigFromXML->WriteConfig();
}
CFRelease(dhcpLDAPdict);
CFRelease(xmlData);
DbgLog( kLogPlugin, "CSearchPlugin::DoPluginCustomCall updating DHCP LDAP configuration for policy %X", aSearchConfig->fSearchConfigKey );
bAuthSwitched = SwitchSearchPolicy( aSearchConfig->fSearchNodePolicy, aSearchConfig );
#if AUGMENT_RECORDS
if ( (bAuthSwitched && aSearchConfig->fSearchConfigKey == eDSAuthenticationSearchNodeName) ||
aSearchConfig->fSearchConfigKey == eDSContactsSearchNodeName)
{
CheckForAugmentConfig( (tDirPatternMatch) aSearchConfig->fSearchConfigKey );
}
#endif
break;
case eDSCustomCallSearchSubNodesUnreachable:
{
if ( inData->fOutRequestResponse == nil ) throw( (SInt32)eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( (SInt32)eDSEmptyBuffer );
CFMutableArrayRef nodeList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
const int NUM_POLICIES = 2;
int policies[NUM_POLICIES] = { eDSAuthenticationSearchNodeName, eDSContactsSearchNodeName };
for (int i = 0; i < NUM_POLICIES; i++)
{
aSearchConfig = FindSearchConfigWithKey( policies[i] );
if (aSearchConfig != nil)
{
nodeListPtr = aSearchConfig->fSearchNodeList->fNext; nodeListPtr = nodeListPtr->fNext; while (nodeListPtr != nil)
{
if (!nodeListPtr->fNodeReachable && nodeListPtr->fNodeName != nil)
{
CFStringRef nodeStr = CFStringCreateWithCString( kCFAllocatorDefault, nodeListPtr->fNodeName, kCFStringEncodingUTF8 );
CFArrayAppendValue( nodeList, nodeStr );
DSCFRelease( nodeStr );
}
nodeListPtr = nodeListPtr->fNext;
}
}
}
DbgLog( kLogPlugin, "CSearchPlugin::DoPluginCustomCall eDSCustomCallSearchSubNodesUnavailable - %d nodes unreachable", CFArrayGetCount(nodeList) );
xmlData = CFPropertyListCreateXMLData( NULL, nodeList );
if (xmlData != nil)
{
aRange.location = 0;
aRange.length = CFDataGetLength( xmlData );
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length )
throw( (SInt32)eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
DSCFRelease( nodeList );
DSCFRelease( xmlData );
}
break;
}
default:
break;
}
}
catch( SInt32 err )
{
siResult = err;
}
catch( ... )
{
siResult = eUndefinedError;
}
fMutex.SignalLock();
}
catch( SInt32 err )
{
siResult = err;
}
if (authRef != 0)
{
AuthorizationFree(authRef, 0);
authRef = 0;
}
return( siResult );
}
SInt32 CSearchPlugin:: CleanSearchConfigData ( sSearchConfig *inList )
{
SInt32 siResult = eDSNoErr;
if ( inList != nil )
{
inList->fSearchNodePolicy = 0;
inList->fSearchConfigKey = 0;
inList->fDirNodeType = kUnknownNodeType;
inList->fNext = nil;
if (inList->fSearchNodeName != nil)
{
free(inList->fSearchNodeName);
inList->fSearchNodeName = nil;
}
if (inList->fSearchConfigFilePrefix != nil)
{
free(inList->fSearchConfigFilePrefix);
inList->fSearchConfigFilePrefix = nil;
}
CleanSearchListData( inList->fSearchNodeList );
inList->fSearchNodeList = nil;
if (inList->pConfigFromXML != nil)
{
delete(inList->pConfigFromXML);
inList->pConfigFromXML = nil;
}
}
return( siResult );
}
SInt32 CSearchPlugin:: CleanSearchListData ( sSearchList *inList )
{
SInt32 siResult = eDSNoErr;
sSearchList *pList = nil;
sSearchList *pDeleteList = nil;
if (inList != nil)
{
pList = inList;
while (pList != nil)
{
pDeleteList = pList;
pList = pList->fNext; if (pDeleteList->fNodeName != nil)
{
delete ( pDeleteList->fNodeName );
}
pDeleteList->fOpened = false;
pDeleteList->fNodeReachable = false;
if (pDeleteList->fNodeRef != 0)
{
::dsCloseDirNode(pDeleteList->fNodeRef); pDeleteList->fNodeRef = 0;
}
pDeleteList->fNext = nil;
if (pDeleteList->fDataList != nil)
{
dsDataListDeallocatePriv ( pDeleteList->fDataList );
free( pDeleteList->fDataList );
pDeleteList->fDataList = nil;
}
delete( pDeleteList );
pDeleteList = nil;
}
}
return( siResult );
}
sSearchConfig *CSearchPlugin::MakeSearchConfigData ( sSearchList *inSearchNodeList,
UInt32 inSearchPolicy,
CConfigs *inConfigFromXML,
char *inSearchNodeName,
char *inSearchConfigFilePrefix,
eDirNodeType inDirNodeType,
UInt32 inSearchConfigType )
{
SInt32 siResult = eDSNoErr;
sSearchConfig *configOut = nil;
configOut = (sSearchConfig *) calloc(sizeof(sSearchConfig), sizeof(char));
if (configOut != nil)
{
siResult = CleanSearchConfigData(configOut);
configOut->fSearchNodeList = inSearchNodeList;
configOut->fSearchNodePolicy = inSearchPolicy;
configOut->pConfigFromXML = inConfigFromXML;
configOut->fSearchNodeName = inSearchNodeName;
configOut->fSearchConfigFilePrefix = inSearchConfigFilePrefix;
configOut->fDirNodeType = inDirNodeType;
configOut->fSearchConfigKey = inSearchConfigType;
configOut->fNext = nil;
}
return( configOut );
}
sSearchConfig *CSearchPlugin:: FindSearchConfigWithKey ( UInt32 inSearchConfigKey )
{
sSearchConfig *configOut = nil;
fMutex.WaitLock();
configOut = pSearchConfigList;
while ( configOut != nil )
{
if (configOut->fSearchConfigKey == inSearchConfigKey)
{
break;
}
configOut = configOut->fNext;
}
fMutex.SignalLock();
return( configOut );
}
SInt32 CSearchPlugin:: AddSearchConfigToList ( sSearchConfig *inSearchConfig )
{
sSearchConfig *aConfigList = nil;
SInt32 siResult = eDSInvalidIndex;
bool uiDup = false;
fMutex.WaitLock();
aConfigList = pSearchConfigList;
while ( aConfigList != nil ) {
if (aConfigList->fSearchConfigKey == inSearchConfig->fSearchConfigKey)
{
uiDup = true;
break;
}
aConfigList = aConfigList->fNext;
}
if (!uiDup) {
aConfigList = pSearchConfigList;
if (aConfigList == nil)
{
pSearchConfigList = inSearchConfig;
}
else
{
while ( aConfigList->fNext != nil )
{
aConfigList = aConfigList->fNext;
}
aConfigList->fNext = inSearchConfig;
}
siResult = eDSNoErr;
}
fMutex.SignalLock();
return( siResult );
}
SInt32 CSearchPlugin::CloseAttributeList ( sCloseAttributeList *inData )
{
SInt32 siResult = eDSNoErr;
sSearchContextData *pContext = nil;
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInAttributeListRef );
if ( pContext != nil )
{
gSNNodeRef->RemoveItem( inData->fInAttributeListRef );
}
else
{
siResult = eDSInvalidAttrListRef;
}
return( siResult );
}
SInt32 CSearchPlugin::CloseAttributeValueList ( sCloseAttributeValueList *inData )
{
SInt32 siResult = eDSNoErr;
sSearchContextData *pContext = nil;
pContext = (sSearchContextData *)gSNNodeRef->GetItemData( inData->fInAttributeValueListRef );
if ( pContext != nil )
{
gSNNodeRef->RemoveItem( inData->fInAttributeValueListRef );
}
else
{
siResult = eDSInvalidAttrValueRef;
}
return( siResult );
}
sSearchList *CSearchPlugin::DupSearchListWithNewRefs ( sSearchList *inSearchList )
{
sSearchList *outSearchList = nil;
sSearchList *pSearchList = inSearchList;
sSearchList *aSearchList = nil;
sSearchList *tailSearchList = nil;
bool isFirst = true;
bool getLocalFirst = true;
while (pSearchList != nil)
{
aSearchList = (sSearchList *)calloc( 1, sizeof( sSearchList ) );
aSearchList->fOpened = false;
aSearchList->fHasNeverOpened = pSearchList->fHasNeverOpened;
aSearchList->fNodeReachable = pSearchList->fNodeReachable;
aSearchList->fNodeRef = 0;
aSearchList->fNodeName = nil;
aSearchList->fDataList = nil;
aSearchList->fNext = nil;
if (isFirst)
{
outSearchList = aSearchList;
tailSearchList = aSearchList;
isFirst = false;
}
else
{
tailSearchList->fNext = aSearchList;
tailSearchList = aSearchList;
}
if (pSearchList->fNodeName != nil)
{
aSearchList->fNodeName = (char *)calloc(1, ::strlen(pSearchList->fNodeName) + 1);
strcpy(aSearchList->fNodeName,pSearchList->fNodeName);
if (getLocalFirst)
{
aSearchList->fDataList = ::dsBuildFromPathPriv( kstrDefaultLocalNodeName, "/" );
getLocalFirst = false;
}
else
{
aSearchList->fDataList = ::dsBuildFromPathPriv( aSearchList->fNodeName, "/" );
}
}
pSearchList = pSearchList->fNext;
}
return( outSearchList );
}
void CSearchPlugin::ContinueDeallocProc ( void* inContinueData )
{
sSearchContinueData *pContinue = (sSearchContinueData *)inContinueData;
if ( pContinue != nil )
{
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
if ( pContinue->fContextData != nil )
{
::dsReleaseContinueData( pContinue->fNodeRef, pContinue->fContextData );
pContinue->fContextData = nil;
}
if ( pContinue->fAugmentReqAttribs != NULL )
{
dsDataListDeallocate( 0, pContinue->fAugmentReqAttribs );
DSFree( pContinue->fAugmentReqAttribs );
}
free( pContinue );
pContinue = nil;
}
}
void CSearchPlugin::ContextDeallocProc ( void* inContextData )
{
sSearchContextData *pContext = (sSearchContextData *) inContextData;
if ( pContext != nil )
{
CleanContextData( pContext );
}
}
void CSearchPlugin:: ContextSetListChangedProc ( void* inContextData )
{
sSearchContextData *pContext = (sSearchContextData *) inContextData;
if ( pContext != nil )
{
OSAtomicCompareAndSwap32Barrier(false, true, &pContext->bListChanged);
}
}
void CSearchPlugin:: ContextSetCheckForNIParentNowProc ( void* inContextData )
{
sSearchContextData *pContext = (sSearchContextData *) inContextData;
if ( pContext != nil )
{
pContext->bCheckForNIParentNow = true;
}
}
SInt32 CSearchPlugin::CheckSearchPolicyChange( sSearchContextData *pContext, tDirNodeReference inNodeRef, tContextData inContinueData )
{
SInt32 siResult = eDSNoErr;
sSearchConfig *aSearchConfig = nil;
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey(pContext->fSearchConfigKey);
if ( aSearchConfig == nil )
{
siResult = eDSInvalidNodeRef;
}
else if ( ( pContext->bListChanged ) && ( pContext->fSearchConfigKey != eDSNetworkSearchNodeName ) )
{
if ( inContinueData != nil )
{
siResult = eDSInvalidContinueData; }
else
{
if ( pContext->pSearchListMutex )
{
if ( !pContext->pSearchListMutex->WaitTry() )
{
fMutex.SignalLock();
return eDSBadContextData;
}
}
CleanSearchListData( pContext->fSearchNodeList );
gSNContinue->RemoveItems( inNodeRef );
pContext->fSearchNodeList = DupSearchListWithNewRefs(aSearchConfig->fSearchNodeList);
if (aSearchConfig->fSearchNodePolicy == kAutomaticSearchPolicy)
{
pContext->bAutoSearchList = true;
}
else
{
pContext->bAutoSearchList = false;
}
OSAtomicCompareAndSwap32Barrier(true, false, &pContext->bListChanged);
if( pContext->pSearchListMutex )
{
pContext->pSearchListMutex->SignalLock();
}
}
}
fMutex.SignalLock();
return siResult;
}
void CSearchPlugin:: SetSearchPolicyIndicatorFile ( UInt32 inSearchNodeKey, UInt32 inSearchPolicyIndex )
{
if (inSearchNodeKey == eDSAuthenticationSearchNodeName)
{
dsCreatePrefsDirectory();
RemoveSearchPolicyIndicatorFile();
if (inSearchPolicyIndex == 3)
{
dsTouch( "/var/run/.DSRunningSP3" );
}
else if (inSearchPolicyIndex == 2)
{
dsTouch( "/var/run/.DSRunningSP2" );
}
else {
dsTouch( "/var/run/.DSRunningSP1" );
}
}
}
void CSearchPlugin:: RemoveSearchPolicyIndicatorFile ( void )
{
dsRemove( "/var/run/.DSRunningSP1" );
dsRemove( "/var/run/.DSRunningSP2" );
dsRemove( "/var/run/.DSRunningSP3" );
}
sSearchList *CSearchPlugin::BuildNetworkNodeList ( void )
{
sSearchList *outSearchList = nil;
sSearchList *aSearchList = nil;
sSearchList *tailSearchList = nil;
bool isFirst = true;
tDataBuffer *pNodeBuff = nil;
bool done = false;
UInt32 uiCount = 0;
UInt32 uiIndex = 0;
tContextData context = NULL;
tDataList *pDataList = nil;
SInt32 siResult = eDSNoErr;
try
{
pNodeBuff = ::dsDataBufferAllocatePriv( 2048 );
if ( pNodeBuff == nil ) throw( (SInt32)eMemoryAllocError );
while ( done == false )
{
do
{
siResult = dsFindDirNodes( fDirRef, pNodeBuff, NULL, eDSDefaultNetworkNodes, &uiCount, &context );
if (siResult == eDSBufferTooSmall)
{
UInt32 bufSize = pNodeBuff->fBufferSize;
dsDataBufferDeallocatePriv( pNodeBuff );
pNodeBuff = nil;
pNodeBuff = ::dsDataBufferAllocatePriv( bufSize * 2 );
}
} while (siResult == eDSBufferTooSmall);
if ( siResult != eDSNoErr ) throw( siResult );
for ( uiIndex = 1; uiIndex <= uiCount; uiIndex++ )
{
siResult = dsGetDirNodeName( fDirRef, pNodeBuff, uiIndex, &pDataList );
if ( siResult != eDSNoErr ) throw( siResult );
aSearchList = (sSearchList *)calloc( 1, sizeof( sSearchList ) );
if ( aSearchList == nil ) throw( (SInt32)eMemoryAllocError );
aSearchList->fOpened = false;
aSearchList->fHasNeverOpened = true;
aSearchList->fNodeReachable = false;
aSearchList->fNodeRef = 0;
aSearchList->fDataList = pDataList;
aSearchList->fNodeName = dsGetPathFromListPriv( pDataList, "/" );
aSearchList->fNext = nil;
if (isFirst)
{
outSearchList = aSearchList;
tailSearchList = aSearchList;
isFirst = false;
}
else
{
tailSearchList->fNext = aSearchList;
tailSearchList = aSearchList;
}
pDataList = nil;
}
done = (context == nil);
}
dsDataBufferDeallocatePriv( pNodeBuff );
pNodeBuff = nil;
}
catch( SInt32 err )
{
outSearchList = nil;
DbgLog( kLogPlugin, "Memory error finding the Default Network Nodes with error: %l", err );
}
return( outSearchList );
}
SInt32 CSearchPlugin::SetPluginState ( const UInt32 inState )
{
if ( inState & kActive )
{
WakeUpRequests();
}
return( eDSNoErr );
}
#if AUGMENT_RECORDS
SInt32 CSearchPlugin::CheckForAugmentConfig ( tDirPatternMatch policyToCheck )
{
SInt32 siResult = eDSNoErr;
CFDictionaryRef aDict = NULL;
sSearchConfig *aSearchConfig = nil;
aDict = FindAugmentConfigRecord( policyToCheck );
if ( aDict != NULL )
{
if ( CFDictionaryContainsKey( aDict, CFSTR( kXMLAugmentSearchKey ) ) &&
CFDictionaryContainsKey( aDict, CFSTR( kXMLAugmentDirNodeNameKey ) ) &&
CFDictionaryContainsKey( aDict, CFSTR( kXMLToBeAugmentedDirNodeNameKey ) ) &&
CFDictionaryContainsKey( aDict, CFSTR( kXMLAugmentAttrListDictKey ) ) )
{
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey( policyToCheck );
if ( (aSearchConfig != nil) && (aSearchConfig->pConfigFromXML != nil) )
{
aSearchConfig->pConfigFromXML->UpdateAugmentDict(aDict);
}
fMutex.SignalLock();
}
DSCFRelease( aDict );
}
return( siResult );
}
CFDictionaryRef CSearchPlugin::FindAugmentConfigRecord( tDirPatternMatch nodeType )
{
sSearchConfig *aSearchConfig = nil;
sSearchList *aSearchList = nil;
bool bLookForConfig = false;
tDataBufferPtr dataBuff = nil;
SInt32 siResult = eDSNoErr;
UInt32 nodeCount = 0;
tContextData context = nil;
tDataListPtr nodeName = nil;
tDirNodeReference aSearchNodeRef = 0;
tDataListPtr recName = nil;
tDataListPtr recType = nil;
tDataListPtr attrTypes = nil;
UInt32 recCount = 1; tRecordEntry *pRecEntry = nil;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef valueRef = 0;
tAttributeEntry *pAttrEntry = nil;
tAttributeValueEntry *pValueEntry = nil;
CFMutableDictionaryRef outDictionary = NULL;
char *pMetaNodeLocation = NULL;
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey( nodeType );
if ( (aSearchConfig != nil) && (aSearchConfig->fSearchNodePolicy == kCustomSearchPolicy) )
{
if ((aSearchConfig->fSearchNodeList != nil) && (aSearchConfig->fSearchNodeList->fNext != nil))
{
aSearchList = aSearchConfig->fSearchNodeList->fNext;
aSearchList = aSearchList->fNext;
if (aSearchList != nil)
{
bLookForConfig = true;
}
}
}
fMutex.SignalLock();
try
{
if ( (bLookForConfig) && (fDirRef != 0) )
{
dataBuff = dsDataBufferAllocate( fDirRef, 256 );
if ( dataBuff == nil ) throw( (SInt32)eMemoryAllocError );
siResult = dsFindDirNodes( fDirRef, dataBuff, nil, nodeType, &nodeCount, &context );
if ( siResult != eDSNoErr ) throw( siResult );
if ( nodeCount < 1 ) throw( eDSNodeNotFound );
siResult = dsGetDirNodeName( fDirRef, dataBuff, 1, &nodeName );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = dsOpenDirNode( fDirRef, nodeName, &aSearchNodeRef );
if ( siResult != eDSNoErr ) throw( siResult );
if ( nodeName != NULL )
{
dsDataListDeallocate( fDirRef, nodeName );
free( nodeName );
nodeName = NULL;
}
recName = dsBuildListFromStrings( fDirRef, "augmentconfiguration", NULL );
recType = dsBuildListFromStrings( fDirRef, kDSStdRecordTypeConfig, NULL );
attrTypes = dsBuildListFromStrings( fDirRef, kDS1AttrXMLPlist, kDSNAttrMetaNodeLocation, NULL );
context = nil;
do
{
siResult = dsGetRecordList( aSearchNodeRef, dataBuff, recName, eDSExact, recType, attrTypes, false, &recCount, &context);
if (siResult == eDSBufferTooSmall)
{
UInt32 bufSize = dataBuff->fBufferSize;
dsDataBufferDeallocatePriv( dataBuff );
dataBuff = nil;
dataBuff = ::dsDataBufferAllocate( fDirRef, bufSize * 2 );
}
} while ( (siResult == eDSBufferTooSmall) || ( (siResult == eDSNoErr) && (recCount == 0) && (context != nil) ) );
if ( (siResult == eDSNoErr) && (recCount > 0) )
{
siResult = ::dsGetRecordEntry( aSearchNodeRef, dataBuff, 1, &attrListRef, &pRecEntry );
if ( (siResult == eDSNoErr) && (pRecEntry != nil) )
{
for ( UInt32 ii = 1; ii <= pRecEntry->fRecordAttributeCount; ii++ )
{
siResult = ::dsGetAttributeEntry( aSearchNodeRef, dataBuff, attrListRef, ii, &valueRef, &pAttrEntry );
if ( ( siResult == eDSNoErr ) && ( pAttrEntry->fAttributeValueCount > 0 ) )
{
siResult = ::dsGetAttributeValue( aSearchNodeRef, dataBuff, 1, valueRef, &pValueEntry );
if ( ( ::strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDS1AttrXMLPlist ) == 0 ) &&
( pValueEntry->fAttributeValueData.fBufferData != nil ) )
{
CFDataRef xmlData = NULL;
CFPropertyListRef configPropertyList = NULL;
xmlData = CFDataCreate( NULL, (UInt8*)pValueEntry->fAttributeValueData.fBufferData,
strlen(pValueEntry->fAttributeValueData.fBufferData) );
if (xmlData != nil)
{
configPropertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
xmlData,
kCFPropertyListMutableContainers,
NULL );
if (configPropertyList != nil )
{
if ( CFDictionaryGetTypeID() == CFGetTypeID( configPropertyList ) )
{
outDictionary = (CFMutableDictionaryRef) configPropertyList;
}
else
{
DSCFRelease(configPropertyList);
}
}
CFRelease(xmlData);
}
}
else if ( strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation) == 0 &&
pValueEntry->fAttributeValueData.fBufferData != nil )
{
pMetaNodeLocation = strdup( pValueEntry->fAttributeValueData.fBufferData );
}
if ( pValueEntry != NULL )
{
dsDeallocAttributeValueEntry( fDirRef, pValueEntry );
pValueEntry = NULL;
}
}
dsCloseAttributeValueList(valueRef);
if (pAttrEntry != nil)
{
dsDeallocAttributeEntry(fDirRef, pAttrEntry);
pAttrEntry = nil;
}
}
}
dsCloseAttributeList(attrListRef);
if (pRecEntry != nil)
{
dsDeallocRecordEntry(fDirRef, pRecEntry);
pRecEntry = nil;
}
} } }
catch( SInt32 err )
{
DbgLog( kLogPlugin, "CSearchPlugin::FindAugmentConfigRecord failed with error %d", err );
}
if ( outDictionary != NULL && pMetaNodeLocation != NULL )
{
CFStringRef cfTempString = CFStringCreateWithCString( kCFAllocatorDefault, pMetaNodeLocation, kCFStringEncodingUTF8 );
if ( cfTempString != NULL )
{
CFDictionarySetValue( outDictionary, CFSTR(kXMLAugmentDirNodeNameKey), cfTempString );
DSCFRelease( cfTempString );
}
}
DSFree( pMetaNodeLocation );
if ( recName != NULL )
{
dsDataListDeallocate( fDirRef, recName );
free( recName );
recName = NULL;
}
if ( recType != NULL )
{
dsDataListDeallocate( fDirRef, recType );
free( recType );
recType = NULL;
}
if ( attrTypes != NULL )
{
dsDataListDeallocate( fDirRef, attrTypes );
free( attrTypes );
attrTypes = NULL;
}
if ( dataBuff != NULL )
{
dsDataBufferDeAllocate( fDirRef, dataBuff );
dataBuff = NULL;
}
if ( nodeName != NULL )
{
dsDataListDeallocate( fDirRef, nodeName );
free( nodeName );
nodeName = NULL;
}
if (aSearchNodeRef != 0)
{
dsCloseDirNode(aSearchNodeRef);
aSearchNodeRef = 0;
}
return outDictionary;
} #endif
void CSearchPlugin::EnsureCheckNodesThreadIsRunning( tDirPatternMatch policyToCheck )
{
if ( policyToCheck == eDSAuthenticationSearchNodeName && OSAtomicCompareAndSwap32Barrier(false, true, &fAuthCheckNodeThreadActive) == true )
{
CSearchPluginHandlerThread* aSearchPluginHandlerThread = new CSearchPluginHandlerThread(DSCThread::kTSSearchPlugInHndlrThread, 1, (void *)this);
if (aSearchPluginHandlerThread != NULL)
aSearchPluginHandlerThread->StartThread();
}
else if ( policyToCheck == eDSContactsSearchNodeName && OSAtomicCompareAndSwap32Barrier(false, true, &fContactCheckNodeThreadActive) == true )
{
CSearchPluginHandlerThread* aSearchPluginHandlerThread = new CSearchPluginHandlerThread(DSCThread::kTSSearchPlugInHndlrThread, 3, (void *)this);
if (aSearchPluginHandlerThread != NULL)
aSearchPluginHandlerThread->StartThread();
}
else
{
gNetworkTransition.PostEvent();
}
}
void CSearchPlugin::CheckNodes( tDirPatternMatch policyToCheck, int32_t *threadFlag, DSEventSemaphore *eventSemaphore )
{
sSearchConfig *aSearchConfig = nil;
sSearchList *aSearchNodeList = nil;
sSearchList *aNodeListPtr = nil;
CFMutableArrayRef aNodeList = 0;
CFStringRef aNodeStr = 0;
bool bTryAgain = true;
int cntBeforeWaitLonger = 0; int waitSeconds = 5;
DBGLOG1( kLogPlugin, "CSearchPlugin::CheckNodes: checking network node reachability on search policy %X", policyToCheck );
while (bTryAgain)
{
bTryAgain = false;
aNodeList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey( policyToCheck );
if ( aSearchConfig != nil )
{
aSearchNodeList = aSearchConfig->fSearchNodeList;
if (aSearchNodeList != nil)
{
aNodeListPtr = aSearchNodeList->fNext; aNodeListPtr = aNodeListPtr->fNext; while (aNodeListPtr != nil)
{
if (aNodeListPtr->fNodeName != nil)
{
aNodeStr = CFStringCreateWithCString( kCFAllocatorDefault, aNodeListPtr->fNodeName, kCFStringEncodingUTF8 );
CFArrayAppendValue(aNodeList, aNodeStr);
CFRelease(aNodeStr);
}
aNodeListPtr = aNodeListPtr->fNext;
}
}
}
fMutex.SignalLock();
CFIndex nodeCount = CFArrayGetCount(aNodeList);
for (CFIndex indexCount = 0; indexCount < nodeCount; indexCount++)
{
aNodeStr = (CFStringRef)CFArrayGetValueAtIndex(aNodeList, indexCount);
int maxLength = 1 + CFStringGetMaximumSizeForEncoding( CFStringGetLength(aNodeStr), kCFStringEncodingUTF8 );
char *tmpStr = (char *)calloc(1, maxLength);
CFStringGetCString(aNodeStr, tmpStr, maxLength, kCFStringEncodingUTF8);
tDataListPtr aNodeName = dsBuildFromPathPriv( tmpStr, "/" );
tDirNodeReference aNodeRef = 0;
SInt32 result = dsOpenDirNode( fDirRef, aNodeName, &aNodeRef );
if (result == eDSNoErr)
{
DBGLOG1( kLogPlugin, "CSearchPlugin::CheckNodes: calling dsOpenDirNode succeeded on node <%s>", tmpStr);
dsCloseDirNode(aNodeRef);
}
else
{
DBGLOG1( kLogPlugin, "CSearchPlugin::CheckNodes: calling dsOpenDirNode failed on node <%s>", tmpStr);
bTryAgain = true;
gNetworkTransition.ResetEvent();
}
fMutex.WaitLock();
aSearchConfig = FindSearchConfigWithKey( policyToCheck );
if ( aSearchConfig != nil )
{
aSearchNodeList = aSearchConfig->fSearchNodeList;
if (aSearchNodeList != nil)
{
aNodeListPtr = aSearchNodeList->fNext; aNodeListPtr = aNodeListPtr->fNext; while (aNodeListPtr != nil)
{
if (strcmp(aNodeListPtr->fNodeName, tmpStr) == 0) {
bool newState = (result==eDSNoErr);
if (aNodeListPtr->fNodeReachable != newState)
{
aNodeListPtr->fNodeReachable = newState;
if (newState && aNodeListPtr->fHasNeverOpened)
{
aNodeListPtr->fHasNeverOpened = false;
if ( gCacheNode != NULL && policyToCheck == eDSAuthenticationSearchNodeName )
{
gCacheNode->EmptyCacheEntryType( CACHE_ENTRY_TYPE_ALL );
DBGLOG1( kLogPlugin, "CSearchPlugin::CheckNodes first time reachability of <%s> flushing cache", tmpStr );
}
}
else
{
if ( gCacheNode != NULL && policyToCheck == eDSAuthenticationSearchNodeName )
gCacheNode->EmptyCacheEntryType( CACHE_ENTRY_TYPE_NEGATIVE );
DBGLOG2( kLogPlugin, "CSearchPlugin::CheckNodes updating search policy for reachability of <%s> to <%s>", tmpStr,
(newState ? "Available" : "Unavailable") );
}
gSNNodeRef->DoOnAllItems(CSearchPlugin::ContextSetListChangedProc);
if (newState)
{
if ( policyToCheck == eDSAuthenticationSearchNodeName ) {
gSrvrCntl->NodeSearchPolicyChanged();
}
else if ( policyToCheck == eDSContactsSearchNodeName ) {
SCDynamicStoreRef store = SCDynamicStoreCreate( NULL, CFSTR("DirectoryService"), NULL, NULL );
if ( store != NULL )
{
if ( SCDynamicStoreNotifyValue( store, CFSTR(kDSStdNotifyContactSearchPolicyChanged) ) )
DbgLog( kLogNotice, "CSearchPlugin::CheckNodes - notify sent for contact search policy change" );
DSCFRelease(store);
}
}
}
if ( gCacheNode != NULL && policyToCheck == eDSAuthenticationSearchNodeName )
{
gCacheNode->UpdateNodeReachability( aNodeListPtr->fNodeName, aNodeListPtr->fNodeReachable );
}
}
break;
}
aNodeListPtr = aNodeListPtr->fNext;
}
}
}
fMutex.SignalLock();
dsDataListDeallocatePriv( aNodeName );
free( aNodeName );
aNodeName = nil;
DSFreeString(tmpStr);
}
CFRelease(aNodeList);
aNodeList = 0;
eventSemaphore->PostEvent();
if (bTryAgain)
{
if( gNetworkTransition.WaitForEvent( waitSeconds * kMilliSecsPerSec ) == true )
{
cntBeforeWaitLonger = 0;
waitSeconds = 5;
}
else
{
cntBeforeWaitLonger++;
if (cntBeforeWaitLonger == 4)
{
cntBeforeWaitLonger = 0;
waitSeconds = waitSeconds * 2;
if (waitSeconds > 900)
{
waitSeconds = 900;
}
DBGLOG1( kLogPlugin, "CSearchPlugin::CheckNodes: adjusting check delay time to <%d> seconds for checking network node reachability", waitSeconds);
}
}
}
}
CheckForAugmentConfig( policyToCheck );
OSAtomicCompareAndSwap32Barrier( true, false, threadFlag );
}