NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryAuthDN(const nsACString & aValueUsedToFindDn) { if(!mInitialized) return NS_ERROR_NOT_INITIALIZED; nsresult rv = NS_OK; CharPtrArrayGuard attributes; *attributes.GetSizeAddr() = 2; *attributes.GetArrayAddr() = NS_STATIC_CAST(char **, nsMemory::Alloc((*attributes.GetSizeAddr()) * sizeof(char *))); attributes.GetArray()[0] = ToNewCString(nsDependentCString(DIR_GetFirstAttributeString(mDirServer, cn))); attributes.GetArray()[1] = nsnull; nsCAutoString filter(DIR_GetFirstAttributeString(mDirServer, auth)); filter += '='; filter += aValueUsedToFindDn; nsCAutoString dn; rv = mURL->GetDn(dn); if(NS_FAILED(rv)) return rv; rv = CreateNewLDAPOperation(); NS_ENSURE_SUCCESS(rv, rv); return mOperation->SearchExt(dn, nsILDAPURL::SCOPE_SUBTREE, filter, attributes.GetSize(), attributes.GetArray(), 0, 0); }
NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryChangedEntries(const nsACString & aChangedEntryDN) { if(!mInitialized) return NS_ERROR_NOT_INITIALIZED; if(aChangedEntryDN.IsEmpty()) return NS_ERROR_UNEXPECTED; nsCAutoString urlFilter; nsresult rv = mURL->GetFilter(urlFilter); if(NS_FAILED(rv)) return rv; PRInt32 scope; rv = mURL->GetScope(&scope); if(NS_FAILED(rv)) return rv; CharPtrArrayGuard attributes; rv = mURL->GetAttributes(attributes.GetSizeAddr(), attributes.GetArrayAddr()); if(NS_FAILED(rv)) return rv; rv = CreateNewLDAPOperation(); NS_ENSURE_SUCCESS(rv, rv); return mOperation->SearchExt(aChangedEntryDN, scope, urlFilter, attributes.GetSize(), attributes.GetArray(), 0, 0); }
nsresult nsAbQueryLDAPMessageListener::DoSearch() { nsresult rv; mCanceled = mFinished = PR_FALSE; mSearchOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIProxyObjectManager> proxyMgr = do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsILDAPMessageListener> proxyListener; rv = proxyMgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsILDAPMessageListener), this, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(proxyListener)); NS_ENSURE_SUCCESS(rv, rv); rv = mSearchOperation->Init (mConnection, proxyListener, nsnull); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString dn; rv = mUrl->GetDn (dn); NS_ENSURE_SUCCESS(rv, rv); PRInt32 scope; rv = mUrl->GetScope (&scope); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString filter; rv = mUrl->GetFilter (filter); NS_ENSURE_SUCCESS(rv, rv); CharPtrArrayGuard attributes; rv = mUrl->GetAttributes (attributes.GetSizeAddr (), attributes.GetArrayAddr ()); NS_ENSURE_SUCCESS(rv, rv); // I don't _think_ it's ever actually possible to get here without having // an nsAbLDAPDirectory object, but, just in case, I'll do a QI instead // of just static casts... nsCOMPtr<nsIAbLDAPDirectory> nsIAbDir = do_QueryInterface(mDirectoryQuery, &rv); NS_ENSURE_SUCCESS(rv, rv); nsAbLDAPDirectory *dir = NS_STATIC_CAST(nsAbLDAPDirectory *, NS_STATIC_CAST(nsIAbLDAPDirectory *, nsIAbDir.get())); rv = mSearchOperation->SetServerControls(dir->mSearchServerControls.get()); NS_ENSURE_SUCCESS(rv, rv); rv = mSearchOperation->SetClientControls(dir->mSearchClientControls.get()); NS_ENSURE_SUCCESS(rv, rv); rv = mSearchOperation->SearchExt (dn, scope, filter, attributes.GetSize (), attributes.GetArray (), mTimeOut, mResultLimit); return rv; }
nsresult nsAbLDAPProcessChangeLogData::ParseRootDSEEntry(nsILDAPMessage *aMessage) { NS_ENSURE_ARG_POINTER(aMessage); if (!mInitialized) return NS_ERROR_NOT_INITIALIZED; // Populate the RootDSEChangeLogEntry CharPtrArrayGuard attrs; nsresult rv = aMessage->GetAttributes(attrs.GetSizeAddr(), attrs.GetArrayAddr()); // No attributes if(NS_FAILED(rv)) return rv; for(PRInt32 i=attrs.GetSize()-1; i >= 0; i--) { PRUnicharPtrArrayGuard vals; rv = aMessage->GetValues(attrs.GetArray()[i], vals.GetSizeAddr(), vals.GetArrayAddr()); if(NS_FAILED(rv)) continue; if(vals.GetSize()) { if (!PL_strcasecmp(attrs[i], "changelog")) CopyUTF16toUTF8(vals[0], mRootDSEEntry.changeLogDN); if (!PL_strcasecmp(attrs[i], "firstChangeNumber")) mRootDSEEntry.firstChangeNumber = atol(NS_LossyConvertUTF16toASCII(vals[0]).get()); if (!PL_strcasecmp(attrs[i], "lastChangeNumber")) mRootDSEEntry.lastChangeNumber = atol(NS_LossyConvertUTF16toASCII(vals[0]).get()); if (!PL_strcasecmp(attrs[i], "dataVersion")) CopyUTF16toUTF8(vals[0], mRootDSEEntry.dataVersion); } } PRInt32 lastChangeNumber; mDirectory->GetLastChangeNumber(&lastChangeNumber); if ((mRootDSEEntry.lastChangeNumber > 0) && (lastChangeNumber < mRootDSEEntry.lastChangeNumber) && (lastChangeNumber > mRootDSEEntry.firstChangeNumber)) mUseChangeLog = PR_TRUE; if (mRootDSEEntry.lastChangeNumber && (lastChangeNumber == mRootDSEEntry.lastChangeNumber)) { Done(PR_TRUE); // We are up to date no need to replicate, db not open yet so call Done return NS_OK; } return rv; }
NS_IMETHODIMP nsAbLDAPDirectory::ModifyCard(nsIAbCard *aUpdatedCard) { NS_ENSURE_ARG_POINTER(aUpdatedCard); nsCOMPtr<nsIAbLDAPAttributeMap> attrMap; nsresult rv = GetAttributeMap(getter_AddRefs(attrMap)); NS_ENSURE_SUCCESS(rv, rv); // Get the LDAP card nsCOMPtr<nsIAbLDAPCard> card = do_QueryInterface(aUpdatedCard, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = Initiate(); NS_ENSURE_SUCCESS(rv, rv); // Retrieve preferences nsAutoCString prefString; rv = GetObjectClasses(prefString); NS_ENSURE_SUCCESS(rv, rv); CharPtrArrayGuard objClass; rv = SplitStringList(prefString, objClass.GetSizeAddr(), objClass.GetArrayAddr()); NS_ENSURE_SUCCESS(rv, rv); // Process updates nsCOMPtr<nsIArray> modArray; rv = card->GetLDAPMessageInfo(attrMap, objClass.GetSize(), objClass.GetArray(), nsILDAPModification::MOD_REPLACE, getter_AddRefs(modArray)); NS_ENSURE_SUCCESS(rv, rv); // Get current DN nsAutoCString oldDN; rv = card->GetDn(oldDN); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsILDAPService> ldapSvc = do_GetService( "@mozilla.org/network/ldap-service;1", &rv); NS_ENSURE_SUCCESS(rv, rv); // Retrieve base DN and RDN attributes nsAutoCString baseDN; nsAutoCString oldRDN; CharPtrArrayGuard rdnAttrs; rv = ldapSvc->ParseDn(oldDN.get(), oldRDN, baseDN, rdnAttrs.GetSizeAddr(), rdnAttrs.GetArrayAddr()); NS_ENSURE_SUCCESS(rv, rv); // Calculate new RDN and check whether it has changed nsAutoCString newRDN; rv = card->BuildRdn(attrMap, rdnAttrs.GetSize(), rdnAttrs.GetArray(), newRDN); NS_ENSURE_SUCCESS(rv, rv); if (newRDN.Equals(oldRDN)) { // Launch query rv = DoModify(this, nsILDAPModification::MOD_REPLACE, oldDN, modArray, EmptyCString(), EmptyCString()); } else { // Build and store the new DN nsAutoCString newDN(newRDN); newDN.AppendLiteral(","); newDN.Append(baseDN); rv = card->SetDn(newDN); NS_ENSURE_SUCCESS(rv, rv); // Launch query rv = DoModify(this, nsILDAPModification::MOD_REPLACE, oldDN, modArray, newRDN, baseDN); } return rv; }
NS_IMETHODIMP nsAbLDAPDirectory::AddCard(nsIAbCard *aUpdatedCard, nsIAbCard **aAddedCard) { NS_ENSURE_ARG_POINTER(aUpdatedCard); NS_ENSURE_ARG_POINTER(aAddedCard); nsCOMPtr<nsIAbLDAPAttributeMap> attrMap; nsresult rv = GetAttributeMap(getter_AddRefs(attrMap)); NS_ENSURE_SUCCESS(rv, rv); // Create a new LDAP card nsCOMPtr<nsIAbLDAPCard> card = do_CreateInstance(NS_ABLDAPCARD_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = Initiate(); NS_ENSURE_SUCCESS(rv, rv); // Copy over the card data nsCOMPtr<nsIAbCard> copyToCard = do_QueryInterface(card, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = copyToCard->Copy(aUpdatedCard); NS_ENSURE_SUCCESS(rv, rv); // Retrieve preferences nsAutoCString prefString; rv = GetRdnAttributes(prefString); NS_ENSURE_SUCCESS(rv, rv); CharPtrArrayGuard rdnAttrs; rv = SplitStringList(prefString, rdnAttrs.GetSizeAddr(), rdnAttrs.GetArrayAddr()); NS_ENSURE_SUCCESS(rv, rv); rv = GetObjectClasses(prefString); NS_ENSURE_SUCCESS(rv, rv); CharPtrArrayGuard objClass; rv = SplitStringList(prefString, objClass.GetSizeAddr(), objClass.GetArrayAddr()); NS_ENSURE_SUCCESS(rv, rv); // Process updates nsCOMPtr<nsIArray> modArray; rv = card->GetLDAPMessageInfo(attrMap, objClass.GetSize(), objClass.GetArray(), nsILDAPModification::MOD_ADD, getter_AddRefs(modArray)); NS_ENSURE_SUCCESS(rv, rv); // For new cards, the base DN is the search base DN nsCOMPtr<nsILDAPURL> currentUrl; rv = GetLDAPURL(getter_AddRefs(currentUrl)); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString baseDN; rv = currentUrl->GetDn(baseDN); NS_ENSURE_SUCCESS(rv, rv); // Calculate DN nsAutoCString cardDN; rv = card->BuildRdn(attrMap, rdnAttrs.GetSize(), rdnAttrs.GetArray(), cardDN); NS_ENSURE_SUCCESS(rv, rv); cardDN.AppendLiteral(","); cardDN.Append(baseDN); rv = card->SetDn(cardDN); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString ourUuid; GetUuid(ourUuid); copyToCard->SetDirectoryId(ourUuid); // Launch query rv = DoModify(this, nsILDAPModification::MOD_ADD, cardDN, modArray, EmptyCString(), EmptyCString()); NS_ENSURE_SUCCESS(rv, rv); NS_ADDREF(*aAddedCard = copyToCard); return NS_OK; }
nsresult nsAbLDAPProcessChangeLogData::ParseChangeLogEntries(nsILDAPMessage *aMessage) { NS_ENSURE_ARG_POINTER(aMessage); if(!mInitialized) return NS_ERROR_NOT_INITIALIZED; // Populate the RootDSEChangeLogEntry CharPtrArrayGuard attrs; nsresult rv = aMessage->GetAttributes(attrs.GetSizeAddr(), attrs.GetArrayAddr()); // No attributes if(NS_FAILED(rv)) return rv; nsAutoString targetDN; UpdateOp operation = NO_OP; for(PRInt32 i = attrs.GetSize()-1; i >= 0; i--) { PRUnicharPtrArrayGuard vals; rv = aMessage->GetValues(attrs.GetArray()[i], vals.GetSizeAddr(), vals.GetArrayAddr()); if(NS_FAILED(rv)) continue; if(vals.GetSize()) { if (!PL_strcasecmp(attrs[i], "targetdn")) targetDN = vals[0]; if (!PL_strcasecmp(attrs[i], "changetype")) { if (!Compare(nsDependentString(vals[0]), NS_LITERAL_STRING("add"), nsCaseInsensitiveStringComparator())) operation = ENTRY_ADD; if (!Compare(nsDependentString(vals[0]), NS_LITERAL_STRING("modify"), nsCaseInsensitiveStringComparator())) operation = ENTRY_MODIFY; if (!Compare(nsDependentString(vals[0]), NS_LITERAL_STRING("delete"), nsCaseInsensitiveStringComparator())) operation = ENTRY_DELETE; } } } mChangeLogEntriesCount++; if(!(mChangeLogEntriesCount % 10)) { // Inform the listener every 10 entries mListener->OnProgressChange(nsnull,nsnull,mChangeLogEntriesCount, -1, mChangeLogEntriesCount, -1); // In case if the LDAP Connection thread is starved and causes problem // uncomment this one and try. // PR_Sleep(PR_INTERVAL_NO_WAIT); // give others a chance } #ifdef DEBUG_rdayal printf ("ChangeLog Replication : Updated Entry : %s for OpType : %u\n", NS_ConvertUTF16toUTF8(targetDN).get(), operation); #endif switch(operation) { case ENTRY_ADD: // Add the DN to the add list if not already in the list if(!(mEntriesToAdd.IndexOf(targetDN) >= 0)) mEntriesToAdd.AppendString(targetDN); break; case ENTRY_DELETE: // Do not check the return here since delete may fail if // entry deleted in changelog does not exist in DB // for e.g if the user specifies a filter, so go next entry DeleteCard(targetDN); break; case ENTRY_MODIFY: // For modify, delete the entry from DB and add updated entry // we do this since we cannot access the changes attribs of changelog rv = DeleteCard(targetDN); if (NS_SUCCEEDED(rv)) if(!(mEntriesToAdd.IndexOf(targetDN) >= 0)) mEntriesToAdd.AppendString(targetDN); break; default: // Should not come here, would come here only // if the entry is not a changeLog entry NS_WARNING("nsAbLDAPProcessChangeLogData::ParseChangeLogEntries" "Not an changelog entry"); } // Go ahead processing the next entry, a modify or delete DB operation // can 'correctly' fail if the entry is not present in the DB, // e.g. in case a filter is specified. return NS_OK; }