mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 09:57:32 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
93
mailnews/addrbook/src/moz.build
Normal file
93
mailnews/addrbook/src/moz.build
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'nsAbDirProperty.h',
|
||||
'nsDirPrefs.h',
|
||||
'nsVCardObj.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsAbAddressCollector.cpp',
|
||||
'nsAbBooleanExpression.cpp',
|
||||
'nsAbBSDirectory.cpp',
|
||||
'nsAbCardProperty.cpp',
|
||||
'nsAbContentHandler.cpp',
|
||||
'nsAbDirectoryQuery.cpp',
|
||||
'nsAbDirectoryQueryProxy.cpp',
|
||||
'nsAbDirFactoryService.cpp',
|
||||
'nsAbDirProperty.cpp',
|
||||
'nsAbLDIFService.cpp',
|
||||
'nsAbManager.cpp',
|
||||
'nsAbMDBCard.cpp',
|
||||
'nsAbMDBDirectory.cpp',
|
||||
'nsAbMDBDirFactory.cpp',
|
||||
'nsAbMDBDirProperty.cpp',
|
||||
'nsAbQueryStringToExpression.cpp',
|
||||
'nsAbView.cpp',
|
||||
'nsAddbookProtocolHandler.cpp',
|
||||
'nsAddbookUrl.cpp',
|
||||
'nsAddrDatabase.cpp',
|
||||
'nsDirPrefs.cpp',
|
||||
'nsMsgVCardService.cpp',
|
||||
'nsVCard.cpp',
|
||||
'nsVCardObj.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_MAPI_SUPPORT']:
|
||||
SOURCES += [
|
||||
'nsAbOutlookDirectory.cpp',
|
||||
'nsAbOutlookDirFactory.cpp',
|
||||
'nsAbWinHelper.cpp',
|
||||
'nsMapiAddressBook.cpp',
|
||||
'nsWabAddressBook.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
SOURCES += [
|
||||
'nsAbOSXDirFactory.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsAbOSXCard.mm',
|
||||
'nsAbOSXDirectory.mm',
|
||||
'nsAbOSXUtils.mm',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_LDAP_XPCOM']:
|
||||
SOURCES += [
|
||||
'nsAbBoolExprToLDAPFilter.cpp',
|
||||
'nsAbLDAPCard.cpp',
|
||||
'nsAbLDAPDirectory.cpp',
|
||||
'nsAbLDAPDirectoryModify.cpp',
|
||||
'nsAbLDAPDirectoryQuery.cpp',
|
||||
'nsAbLDAPDirFactory.cpp',
|
||||
'nsAbLDAPListenerBase.cpp',
|
||||
'nsAbLDAPReplicationData.cpp',
|
||||
'nsAbLDAPReplicationQuery.cpp',
|
||||
'nsAbLDAPReplicationService.cpp',
|
||||
]
|
||||
# XXX These files are not being built as they don't work. Bug 311632 should
|
||||
# fix them.
|
||||
# nsAbLDAPChangeLogQuery.cpp
|
||||
# nsAbLDAPChangeLogData.cpp
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsAbLDAPAutoCompleteSearch.js',
|
||||
]
|
||||
|
||||
DEFINES['MOZ_LDAP_XPCOM'] = True
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsAbAutoCompleteMyDomain.js',
|
||||
'nsAbAutoCompleteSearch.js',
|
||||
'nsAbLDAPAttributeMap.js',
|
||||
]
|
||||
|
||||
EXTRA_PP_COMPONENTS += [
|
||||
'nsAddrbook.manifest',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'mail'
|
||||
331
mailnews/addrbook/src/nsAbAddressCollector.cpp
Normal file
331
mailnews/addrbook/src/nsAbAddressCollector.cpp
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbAddressCollector.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "prmem.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "mozilla/mailnews/MimeHeaderParser.h"
|
||||
|
||||
using namespace mozilla::mailnews;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbAddressCollector, nsIAbAddressCollector, nsIObserver)
|
||||
|
||||
#define PREF_MAIL_COLLECT_ADDRESSBOOK "mail.collect_addressbook"
|
||||
|
||||
nsAbAddressCollector::nsAbAddressCollector()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbAddressCollector::~nsAbAddressCollector()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> pPrefBranchInt(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
pPrefBranchInt->RemoveObserver(PREF_MAIL_COLLECT_ADDRESSBOOK, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first card found with the specified email address. This
|
||||
* returns an already addrefed pointer to the card if the card is found.
|
||||
*/
|
||||
already_AddRefed<nsIAbCard>
|
||||
nsAbAddressCollector::GetCardForAddress(const nsACString &aEmailAddress,
|
||||
nsIAbDirectory **aDirectory)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
rv = abManager->GetDirectories(getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
bool hasMore;
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
nsCOMPtr<nsIAbCard> result;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
rv = enumerator->GetNext(getter_AddRefs(supports));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
directory = do_QueryInterface(supports, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
// Some implementations may return NS_ERROR_NOT_IMPLEMENTED here,
|
||||
// so just catch the value and continue.
|
||||
if (NS_FAILED(directory->CardForEmailAddress(aEmailAddress,
|
||||
getter_AddRefs(result))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (aDirectory)
|
||||
directory.forget(aDirectory);
|
||||
return result.forget();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbAddressCollector::CollectAddress(const nsACString &aAddresses,
|
||||
bool aCreateCard,
|
||||
uint32_t aSendFormat)
|
||||
{
|
||||
// If we've not got a valid directory, no point in going any further
|
||||
if (!mDirectory)
|
||||
return NS_OK;
|
||||
|
||||
// note that we're now setting the whole recipient list,
|
||||
// not just the pretty name of the first recipient.
|
||||
nsTArray<nsCString> names;
|
||||
nsTArray<nsCString> addresses;
|
||||
ExtractAllAddresses(EncodedHeader(aAddresses),
|
||||
UTF16ArrayAdapter<>(names), UTF16ArrayAdapter<>(addresses));
|
||||
uint32_t numAddresses = names.Length();
|
||||
|
||||
for (uint32_t i = 0; i < numAddresses; i++)
|
||||
{
|
||||
// Don't allow collection of addresses with no email address, it makes
|
||||
// no sense. Whilst we should never get here in most normal cases, we
|
||||
// should still be careful.
|
||||
if (addresses[i].IsEmpty())
|
||||
continue;
|
||||
|
||||
CollectSingleAddress(addresses[i], names[i], aCreateCard, aSendFormat,
|
||||
false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbAddressCollector::CollectSingleAddress(const nsACString &aEmail,
|
||||
const nsACString &aDisplayName,
|
||||
bool aCreateCard,
|
||||
uint32_t aSendFormat,
|
||||
bool aSkipCheckExisting)
|
||||
{
|
||||
if (!mDirectory)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> originDirectory;
|
||||
nsCOMPtr<nsIAbCard> card = (!aSkipCheckExisting) ?
|
||||
GetCardForAddress(aEmail, getter_AddRefs(originDirectory)) : nullptr;
|
||||
|
||||
if (!card && (aCreateCard || aSkipCheckExisting))
|
||||
{
|
||||
card = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && card)
|
||||
{
|
||||
// Set up the fields for the new card.
|
||||
SetNamesForCard(card, aDisplayName);
|
||||
AutoCollectScreenName(card, aEmail);
|
||||
|
||||
if (NS_SUCCEEDED(card->SetPrimaryEmail(NS_ConvertUTF8toUTF16(aEmail))))
|
||||
{
|
||||
card->SetPropertyAsUint32(kPreferMailFormatProperty, aSendFormat);
|
||||
|
||||
nsCOMPtr<nsIAbCard> addedCard;
|
||||
rv = mDirectory->AddCard(card, getter_AddRefs(addedCard));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add card");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (card && originDirectory)
|
||||
{
|
||||
// It could be that the origin directory is read-only, so don't try and
|
||||
// write to it if it is.
|
||||
bool readOnly;
|
||||
rv = originDirectory->GetReadOnly(&readOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (readOnly)
|
||||
return NS_OK;
|
||||
|
||||
// address is already in the AB, so update the names
|
||||
bool modifiedCard = false;
|
||||
|
||||
nsString displayName;
|
||||
card->GetDisplayName(displayName);
|
||||
// If we already have a display name, don't set the names on the card.
|
||||
if (displayName.IsEmpty() && !aDisplayName.IsEmpty())
|
||||
modifiedCard = SetNamesForCard(card, aDisplayName);
|
||||
|
||||
if (aSendFormat != nsIAbPreferMailFormat::unknown)
|
||||
{
|
||||
uint32_t currentFormat;
|
||||
rv = card->GetPropertyAsUint32(kPreferMailFormatProperty,
|
||||
¤tFormat);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get preferred mail format");
|
||||
|
||||
// we only want to update the AB if the current format is unknown
|
||||
if (currentFormat == nsIAbPreferMailFormat::unknown &&
|
||||
NS_SUCCEEDED(card->SetPropertyAsUint32(kPreferMailFormatProperty,
|
||||
aSendFormat)))
|
||||
modifiedCard = true;
|
||||
}
|
||||
|
||||
if (modifiedCard)
|
||||
originDirectory->ModifyCard(card);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Works out the screen name to put on the card for some well-known addresses
|
||||
void
|
||||
nsAbAddressCollector::AutoCollectScreenName(nsIAbCard *aCard,
|
||||
const nsACString &aEmail)
|
||||
{
|
||||
if (!aCard)
|
||||
return;
|
||||
|
||||
int32_t atPos = aEmail.FindChar('@');
|
||||
if (atPos == -1)
|
||||
return;
|
||||
|
||||
const nsACString& domain = Substring(aEmail, atPos + 1);
|
||||
|
||||
if (domain.IsEmpty())
|
||||
return;
|
||||
// username in
|
||||
// username@aol.com (America Online)
|
||||
// username@cs.com (Compuserve)
|
||||
// username@netscape.net (Netscape webmail)
|
||||
// are all AIM screennames. autocollect that info.
|
||||
if (domain.Equals("aol.com") || domain.Equals("cs.com") ||
|
||||
domain.Equals("netscape.net"))
|
||||
aCard->SetPropertyAsAUTF8String(kScreenNameProperty, Substring(aEmail, 0, atPos));
|
||||
else if (domain.Equals("gmail.com") || domain.Equals("googlemail.com"))
|
||||
aCard->SetPropertyAsAUTF8String(kGtalkProperty, Substring(aEmail, 0, atPos));
|
||||
}
|
||||
|
||||
// Returns true if the card was modified successfully.
|
||||
bool
|
||||
nsAbAddressCollector::SetNamesForCard(nsIAbCard *aSenderCard,
|
||||
const nsACString &aFullName)
|
||||
{
|
||||
nsCString firstName;
|
||||
nsCString lastName;
|
||||
bool modifiedCard = false;
|
||||
|
||||
if (NS_SUCCEEDED(aSenderCard->SetDisplayName(NS_ConvertUTF8toUTF16(aFullName))))
|
||||
modifiedCard = true;
|
||||
|
||||
// Now split up the full name.
|
||||
SplitFullName(nsCString(aFullName), firstName, lastName);
|
||||
|
||||
if (!firstName.IsEmpty() &&
|
||||
NS_SUCCEEDED(aSenderCard->SetFirstName(NS_ConvertUTF8toUTF16(firstName))))
|
||||
modifiedCard = true;
|
||||
|
||||
if (!lastName.IsEmpty() &&
|
||||
NS_SUCCEEDED(aSenderCard->SetLastName(NS_ConvertUTF8toUTF16(lastName))))
|
||||
modifiedCard = true;
|
||||
|
||||
if (modifiedCard)
|
||||
aSenderCard->SetPropertyAsBool("PreferDisplayName", false);
|
||||
|
||||
return modifiedCard;
|
||||
}
|
||||
|
||||
// Splits the first and last name based on the space between them.
|
||||
void
|
||||
nsAbAddressCollector::SplitFullName(const nsCString &aFullName, nsCString &aFirstName,
|
||||
nsCString &aLastName)
|
||||
{
|
||||
int index = aFullName.RFindChar(' ');
|
||||
if (index != -1)
|
||||
{
|
||||
aLastName = Substring(aFullName, index + 1);
|
||||
aFirstName = Substring(aFullName, 0, index);
|
||||
}
|
||||
}
|
||||
|
||||
// Observes the collected address book pref in case it changes.
|
||||
NS_IMETHODIMP
|
||||
nsAbAddressCollector::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
|
||||
if (!prefBranch) {
|
||||
NS_ASSERTION(prefBranch, "failed to get prefs");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SetUpAbFromPrefs(prefBranch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Initialises the collector with the required items.
|
||||
nsresult
|
||||
nsAbAddressCollector::Init(void)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = prefBranch->AddObserver(PREF_MAIL_COLLECT_ADDRESSBOOK, this, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
SetUpAbFromPrefs(prefBranch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Performs the necessary changes to set up the collector for the specified
|
||||
// collected address book.
|
||||
void
|
||||
nsAbAddressCollector::SetUpAbFromPrefs(nsIPrefBranch *aPrefBranch)
|
||||
{
|
||||
nsCString abURI;
|
||||
aPrefBranch->GetCharPref(PREF_MAIL_COLLECT_ADDRESSBOOK,
|
||||
getter_Copies(abURI));
|
||||
|
||||
if (abURI.IsEmpty())
|
||||
abURI.AssignLiteral(kPersonalAddressbookUri);
|
||||
|
||||
if (abURI == mABURI)
|
||||
return;
|
||||
|
||||
mDirectory = nullptr;
|
||||
mABURI = abURI;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
rv = abManager->GetDirectory(mABURI, getter_AddRefs(mDirectory));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
bool readOnly;
|
||||
rv = mDirectory->GetReadOnly(&readOnly);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// If the directory is read-only, we can't write to it, so just blank it out
|
||||
// here, and warn because we shouldn't hit this (UI is wrong).
|
||||
if (readOnly)
|
||||
{
|
||||
NS_ERROR("Address Collection book preferences is set to a read-only book. "
|
||||
"Address collection will not take place.");
|
||||
mDirectory = nullptr;
|
||||
}
|
||||
}
|
||||
44
mailnews/addrbook/src/nsAbAddressCollector.h
Normal file
44
mailnews/addrbook/src/nsAbAddressCollector.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsAbAddressCollector_H_
|
||||
#define _nsAbAddressCollector_H_
|
||||
|
||||
#include "nsIAbAddressCollector.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIPrefBranch;
|
||||
|
||||
class nsAbAddressCollector : public nsIAbAddressCollector,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
nsAbAddressCollector();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABADDRESSCOLLECTOR
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsresult Init();
|
||||
|
||||
private:
|
||||
virtual ~nsAbAddressCollector();
|
||||
already_AddRefed<nsIAbCard> GetCardForAddress(const nsACString &aEmailAddress,
|
||||
nsIAbDirectory **aDirectory);
|
||||
void AutoCollectScreenName(nsIAbCard *aCard, const nsACString &aEmail);
|
||||
bool SetNamesForCard(nsIAbCard *aSenderCard, const nsACString &aFullName);
|
||||
void SplitFullName(const nsCString &aFullName, nsCString &aFirstName,
|
||||
nsCString &aLastName);
|
||||
void SetUpAbFromPrefs(nsIPrefBranch *aPrefBranch);
|
||||
nsCOMPtr <nsIAbDirectory> mDirectory;
|
||||
nsCString mABURI;
|
||||
};
|
||||
|
||||
#endif // _nsAbAddressCollector_H_
|
||||
|
||||
58
mailnews/addrbook/src/nsAbAutoCompleteMyDomain.js
Normal file
58
mailnews/addrbook/src/nsAbAutoCompleteMyDomain.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function nsAbAutoCompleteMyDomain() {}
|
||||
|
||||
nsAbAutoCompleteMyDomain.prototype = {
|
||||
classID: Components.ID("{5b259db2-e451-4de9-8a6f-cfba91402973}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Components.interfaces.nsIAutoCompleteSearch]),
|
||||
|
||||
cachedIdKey: "",
|
||||
cachedIdentity: null,
|
||||
|
||||
applicableHeaders: new Set(["addr_to", "addr_cc", "addr_bcc", "addr_reply"]),
|
||||
|
||||
startSearch: function(aString, aSearchParam, aResult, aListener) {
|
||||
let params = aSearchParam ? JSON.parse(aSearchParam) : {};
|
||||
let applicable = ("type" in params) && this.applicableHeaders.has(params.type);
|
||||
const ACR = Components.interfaces.nsIAutoCompleteResult;
|
||||
var address = null;
|
||||
if (applicable && aString && !aString.includes(",")) {
|
||||
if (("idKey" in params) && (params.idKey != this.cachedIdKey)) {
|
||||
this.cachedIdentity = MailServices.accounts.getIdentity(params.idKey);
|
||||
this.cachedIdKey = params.idKey;
|
||||
}
|
||||
if (this.cachedIdentity.autocompleteToMyDomain)
|
||||
address = aString.includes("@") ? aString :
|
||||
this.cachedIdentity.email.replace(/[^@]*/, aString);
|
||||
}
|
||||
|
||||
var result = {
|
||||
searchString: aString,
|
||||
searchResult: address ? ACR.RESULT_SUCCESS : ACR.RESULT_FAILURE,
|
||||
defaultIndex: -1,
|
||||
errorDescription: null,
|
||||
matchCount: address ? 1 : 0,
|
||||
getValueAt: function() { return address; },
|
||||
getLabelAt: function() { return this.getValueAt(); },
|
||||
getCommentAt: function() { return null; },
|
||||
getStyleAt: function() { return "default-match"; },
|
||||
getImageAt: function() { return null; },
|
||||
getFinalCompleteValueAt: function(aIndex) {
|
||||
return this.getValueAt(aIndex);
|
||||
},
|
||||
removeValueAt: function() {}
|
||||
};
|
||||
aListener.onSearchResult(this, result);
|
||||
},
|
||||
|
||||
stopSearch: function() {}
|
||||
};
|
||||
|
||||
var components = [nsAbAutoCompleteMyDomain];
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
466
mailnews/addrbook/src/nsAbAutoCompleteSearch.js
Normal file
466
mailnews/addrbook/src/nsAbAutoCompleteSearch.js
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/ABQueryUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var ACR = Components.interfaces.nsIAutoCompleteResult;
|
||||
var nsIAbAutoCompleteResult = Components.interfaces.nsIAbAutoCompleteResult;
|
||||
|
||||
function nsAbAutoCompleteResult(aSearchString) {
|
||||
// Can't create this in the prototype as we'd get the same array for
|
||||
// all instances
|
||||
this._searchResults = []; // final results
|
||||
this.searchString = aSearchString;
|
||||
this._collectedValues = new Map(); // temporary unsorted results
|
||||
// Get model query from pref; this will return mail.addr_book.autocompletequery.format.phonetic
|
||||
// if mail.addr_book.show_phonetic_fields == true
|
||||
this.modelQuery = getModelQuery("mail.addr_book.autocompletequery.format");
|
||||
// check if the currently active model query has been modified by user
|
||||
this._modelQueryHasUserValue = modelQueryHasUserValue("mail.addr_book.autocompletequery.format");
|
||||
}
|
||||
|
||||
nsAbAutoCompleteResult.prototype = {
|
||||
_searchResults: null,
|
||||
|
||||
// nsIAutoCompleteResult
|
||||
|
||||
modelQuery: null,
|
||||
searchString: null,
|
||||
searchResult: ACR.RESULT_NOMATCH,
|
||||
defaultIndex: -1,
|
||||
errorDescription: null,
|
||||
|
||||
get matchCount() {
|
||||
return this._searchResults.length;
|
||||
},
|
||||
|
||||
getValueAt: function getValueAt(aIndex) {
|
||||
return this._searchResults[aIndex].value;
|
||||
},
|
||||
|
||||
getLabelAt: function getLabelAt(aIndex) {
|
||||
return this.getValueAt(aIndex);
|
||||
},
|
||||
|
||||
getCommentAt: function getCommentAt(aIndex) {
|
||||
return this._searchResults[aIndex].comment;
|
||||
},
|
||||
|
||||
getStyleAt: function getStyleAt(aIndex) {
|
||||
return "local-abook";
|
||||
},
|
||||
|
||||
getImageAt: function getImageAt(aIndex) {
|
||||
return "";
|
||||
},
|
||||
|
||||
getFinalCompleteValueAt: function(aIndex) {
|
||||
return this.getValueAt(aIndex);
|
||||
},
|
||||
|
||||
removeValueAt: function removeValueAt(aRowIndex, aRemoveFromDB) {
|
||||
},
|
||||
|
||||
// nsIAbAutoCompleteResult
|
||||
|
||||
getCardAt: function getCardAt(aIndex) {
|
||||
return this._searchResults[aIndex].card;
|
||||
},
|
||||
|
||||
getEmailToUse: function getEmailToUse(aIndex) {
|
||||
return this._searchResults[aIndex].emailToUse;
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([ACR, nsIAbAutoCompleteResult])
|
||||
}
|
||||
|
||||
function nsAbAutoCompleteSearch() {}
|
||||
|
||||
nsAbAutoCompleteSearch.prototype = {
|
||||
// For component registration
|
||||
classID: Components.ID("2f946df9-114c-41fe-8899-81f10daf4f0c"),
|
||||
|
||||
// This is set from a preference,
|
||||
// 0 = no comment column, 1 = name of address book this card came from
|
||||
// Other numbers currently unused (hence default to zero)
|
||||
_commentColumn: 0,
|
||||
_parser: MailServices.headerParser,
|
||||
_abManager: MailServices.ab,
|
||||
applicableHeaders: new Set(["addr_to", "addr_cc", "addr_bcc", "addr_reply"]),
|
||||
|
||||
// Private methods
|
||||
|
||||
/**
|
||||
* Returns the popularity index for a given card. This takes account of a
|
||||
* translation bug whereby Thunderbird 2 stores its values in mork as
|
||||
* hexadecimal, and Thunderbird 3 stores as decimal.
|
||||
*
|
||||
* @param aDirectory The directory that the card is in.
|
||||
* @param aCard The card to return the popularity index for.
|
||||
*/
|
||||
_getPopularityIndex: function _getPopularityIndex(aDirectory, aCard) {
|
||||
let popularityValue = aCard.getProperty("PopularityIndex", "0");
|
||||
let popularityIndex = parseInt(popularityValue);
|
||||
|
||||
// If we haven't parsed it the first time round, parse it as hexadecimal
|
||||
// and repair so that we don't have to keep repairing.
|
||||
if (isNaN(popularityIndex)) {
|
||||
popularityIndex = parseInt(popularityValue, 16);
|
||||
|
||||
// If its still NaN, just give up, we shouldn't ever get here.
|
||||
if (isNaN(popularityIndex))
|
||||
popularityIndex = 0;
|
||||
|
||||
// Now store this change so that we're not changing it each time around.
|
||||
if (!aDirectory.readOnly) {
|
||||
aCard.setProperty("PopularityIndex", popularityIndex);
|
||||
try {
|
||||
aDirectory.modifyCard(aCard);
|
||||
}
|
||||
catch (ex) {
|
||||
Components.utils.reportError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return popularityIndex;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the score of the (full) address, given the search input. We want
|
||||
* results that match the beginning of a "word" in the result to score better
|
||||
* than a result that matches only in the middle of the word.
|
||||
*
|
||||
* @param aCard - the card whose score is being decided
|
||||
* @param aAddress - full lower-cased address, including display name and address
|
||||
* @param aSearchString - search string provided by user
|
||||
* @return a score; a higher score is better than a lower one
|
||||
*/
|
||||
_getScore: function(aCard, aAddress, aSearchString) {
|
||||
const BEST = 100;
|
||||
|
||||
// We will firstly check if the search term provided by the user
|
||||
// is the nick name for the card or at least in the beginning of it.
|
||||
let nick = aCard.getProperty("NickName", "").toLocaleLowerCase();
|
||||
aSearchString = aSearchString.toLocaleLowerCase();
|
||||
if (nick == aSearchString)
|
||||
return BEST + 1;
|
||||
if (nick.indexOf(aSearchString) == 0)
|
||||
return BEST;
|
||||
|
||||
// We'll do this case-insensitively and ignore the domain.
|
||||
let atIdx = aAddress.lastIndexOf("@");
|
||||
if (atIdx != -1) // mail lists don't have an @
|
||||
aAddress = aAddress.substr(0, atIdx);
|
||||
let idx = aAddress.indexOf(aSearchString);
|
||||
if (idx == 0)
|
||||
return BEST;
|
||||
if (idx == -1)
|
||||
return 0;
|
||||
|
||||
// We want to treat firstname, lastname and word boundary(ish) parts of
|
||||
// the email address the same. E.g. for "John Doe (:xx) <jd.who@example.com>"
|
||||
// all of these should score the same: "John", "Doe", "xx",
|
||||
// ":xx", "jd", "who".
|
||||
let prevCh = aAddress.charAt(idx - 1);
|
||||
if (/[ :."'(\-_<&]/.test(prevCh))
|
||||
return BEST;
|
||||
|
||||
// The match was inside a word -> we don't care about the position.
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Searches cards in the given directory. If a card is matched (and isn't
|
||||
* a mailing list) then the function will add a result for each email address
|
||||
* that exists.
|
||||
*
|
||||
* @param searchQuery The boolean search query to use.
|
||||
* @param directory An nsIAbDirectory to search.
|
||||
* @param result The result element to append results to.
|
||||
*/
|
||||
_searchCards: function(searchQuery, directory, result) {
|
||||
let childCards;
|
||||
try {
|
||||
childCards = this._abManager.getDirectory(directory.URI + searchQuery).childCards;
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Error running addressbook query '" + searchQuery + "': " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache this values to save going through xpconnect each time
|
||||
var commentColumn = this._commentColumn == 1 ? directory.dirName : "";
|
||||
|
||||
// Now iterate through all the cards.
|
||||
while (childCards.hasMoreElements()) {
|
||||
var card = childCards.getNext();
|
||||
|
||||
if (card instanceof Components.interfaces.nsIAbCard) {
|
||||
if (card.isMailList)
|
||||
this._addToResult(commentColumn, directory, card, "", true, result);
|
||||
else {
|
||||
let email = card.primaryEmail;
|
||||
if (email)
|
||||
this._addToResult(commentColumn, directory, card, email, true, result);
|
||||
|
||||
email = card.getProperty("SecondEmail", "");
|
||||
if (email)
|
||||
this._addToResult(commentColumn, directory, card, email, false, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks the parent card and email address of an autocomplete results entry
|
||||
* from a previous result against the search parameters to see if that entry
|
||||
* should still be included in the narrowed-down result.
|
||||
*
|
||||
* @param aCard The card to check.
|
||||
* @param aEmailToUse The email address to check against.
|
||||
* @param aSearchWords Array of words in the multi word search string.
|
||||
* @return True if the card matches the search parameters, false
|
||||
* otherwise.
|
||||
*/
|
||||
_checkEntry: function _checkEntry(aCard, aEmailToUse, aSearchWords) {
|
||||
// Joining values of many fields in a single string so that a single
|
||||
// search query can be fired on all of them at once. Separating them
|
||||
// using spaces so that field1=> "abc" and field2=> "def" on joining
|
||||
// shouldn't return true on search for "bcd".
|
||||
// Note: This should be constructed from model query pref using
|
||||
// getModelQuery("mail.addr_book.autocompletequery.format")
|
||||
// but for now we hard-code the default value equivalent of the pref here
|
||||
// or else bail out before and reconstruct the full c++ query if the pref
|
||||
// has been customized (modelQueryHasUserValue), so that we won't get here.
|
||||
let cumulativeFieldText = aCard.displayName + " " +
|
||||
aCard.firstName + " " +
|
||||
aCard.lastName + " " +
|
||||
aEmailToUse + " " +
|
||||
aCard.getProperty("NickName", "");
|
||||
if (aCard.isMailList)
|
||||
cumulativeFieldText += " " + aCard.getProperty("Notes", "");
|
||||
cumulativeFieldText = cumulativeFieldText.toLocaleLowerCase();
|
||||
|
||||
return aSearchWords.every(String.prototype.includes,
|
||||
cumulativeFieldText);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks to see if an emailAddress (name/address) is a duplicate of an
|
||||
* existing entry already in the results. If the emailAddress is found, it
|
||||
* will remove the existing element if the popularity of the new card is
|
||||
* higher than the previous card.
|
||||
*
|
||||
* @param directory The directory that the card is in.
|
||||
* @param card The card that could be a duplicate.
|
||||
* @param lcEmailAddress The emailAddress (name/address combination) to check
|
||||
* for duplicates against. Lowercased.
|
||||
* @param currentResults The current results list.
|
||||
*/
|
||||
_checkDuplicate: function (directory, card, lcEmailAddress, currentResults) {
|
||||
let existingResult = currentResults._collectedValues.get(lcEmailAddress);
|
||||
if (!existingResult)
|
||||
return false;
|
||||
|
||||
let popIndex = this._getPopularityIndex(directory, card);
|
||||
// It's a duplicate, is the new one more popular?
|
||||
if (popIndex > existingResult.popularity) {
|
||||
// Yes it is, so delete this element, return false and allow
|
||||
// _addToResult to sort the new element into the correct place.
|
||||
currentResults._collectedValues.delete(lcEmailAddress);
|
||||
return false;
|
||||
}
|
||||
// Not more popular, but still a duplicate. Return true and _addToResult
|
||||
// will just forget about it.
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a card to the results list if it isn't a duplicate. The function will
|
||||
* order the results by popularity.
|
||||
*
|
||||
* @param commentColumn The text to be displayed in the comment column
|
||||
* (if any).
|
||||
* @param directory The directory that the card is in.
|
||||
* @param card The card being added to the results.
|
||||
* @param emailToUse The email address from the card that should be used
|
||||
* for this result.
|
||||
* @param isPrimaryEmail Is the emailToUse the primary email? Set to true if
|
||||
* it is the case. For mailing lists set it to true.
|
||||
* @param result The result to add the new entry to.
|
||||
*/
|
||||
_addToResult: function(commentColumn, directory, card,
|
||||
emailToUse, isPrimaryEmail, result) {
|
||||
let mbox = this._parser.makeMailboxObject(card.displayName,
|
||||
card.isMailList ? card.getProperty("Notes", "") || card.displayName :
|
||||
emailToUse);
|
||||
if (!mbox.email)
|
||||
return;
|
||||
|
||||
let emailAddress = mbox.toString();
|
||||
let lcEmailAddress = emailAddress.toLocaleLowerCase();
|
||||
|
||||
// If it is a duplicate, then just return and don't add it. The
|
||||
// _checkDuplicate function deals with it all for us.
|
||||
if (this._checkDuplicate(directory, card, lcEmailAddress, result))
|
||||
return;
|
||||
|
||||
result._collectedValues.set(lcEmailAddress, {
|
||||
value: emailAddress,
|
||||
comment: commentColumn,
|
||||
card: card,
|
||||
isPrimaryEmail: isPrimaryEmail,
|
||||
emailToUse: emailToUse,
|
||||
popularity: this._getPopularityIndex(directory, card),
|
||||
score: this._getScore(card, lcEmailAddress, result.searchString)
|
||||
});
|
||||
},
|
||||
|
||||
// nsIAutoCompleteSearch
|
||||
|
||||
/**
|
||||
* Starts a search based on the given parameters.
|
||||
*
|
||||
* @see nsIAutoCompleteSearch for parameter details.
|
||||
*
|
||||
* It is expected that aSearchParam contains the identity (if any) to use
|
||||
* for determining if an address book should be autocompleted against.
|
||||
*/
|
||||
startSearch: function startSearch(aSearchString, aSearchParam,
|
||||
aPreviousResult, aListener) {
|
||||
let params = aSearchParam ? JSON.parse(aSearchParam) : {};
|
||||
var result = new nsAbAutoCompleteResult(aSearchString);
|
||||
if (("type" in params) && !this.applicableHeaders.has(params.type)) {
|
||||
result.searchResult = ACR.RESULT_IGNORED;
|
||||
aListener.onSearchResult(this, result);
|
||||
return;
|
||||
}
|
||||
|
||||
let fullString = aSearchString && aSearchString.trim().toLocaleLowerCase();
|
||||
|
||||
// If the search string is empty, or contains a comma, or the user
|
||||
// hasn't enabled autocomplete, then just return no matches or the
|
||||
// result ignored.
|
||||
// The comma check is so that we don't autocomplete against the user
|
||||
// entering multiple addresses.
|
||||
if (!fullString || aSearchString.includes(",")) {
|
||||
result.searchResult = ACR.RESULT_IGNORED;
|
||||
aListener.onSearchResult(this, result);
|
||||
return;
|
||||
}
|
||||
|
||||
// Array of all the terms from the fullString search query
|
||||
// (separated on the basis of spaces or exact terms on the
|
||||
// basis of quotes).
|
||||
let searchWords = getSearchTokens(fullString);
|
||||
|
||||
// Find out about the comment column
|
||||
try {
|
||||
this._commentColumn = Services.prefs.getIntPref("mail.autoComplete.commentColumn");
|
||||
} catch(e) { }
|
||||
|
||||
if (aPreviousResult instanceof nsIAbAutoCompleteResult &&
|
||||
aSearchString.startsWith(aPreviousResult.searchString) &&
|
||||
aPreviousResult.searchResult == ACR.RESULT_SUCCESS &&
|
||||
!result._modelQueryHasUserValue &&
|
||||
result.modelQuery == aPreviousResult.modelQuery) {
|
||||
// We have successful previous matches, and model query has not changed since
|
||||
// previous search, therefore just iterate through the list of previous result
|
||||
// entries and reduce as appropriate (via _checkEntry function).
|
||||
// Test for model query change is required: when reverting back from custom to
|
||||
// default query, result._modelQueryHasUserValue==false, but we must bail out.
|
||||
// Todo: However, if autocomplete model query has been customized, we fall
|
||||
// back to using the full query again instead of reducing result list in js;
|
||||
// The full query might be less performant as it's fired against entire AB,
|
||||
// so we should try morphing the query for js. We can't use the _checkEntry
|
||||
// js query yet because it is hardcoded (mimic default model query).
|
||||
// At least we now allow users to customize their autocomplete model query...
|
||||
for (let i = 0; i < aPreviousResult.matchCount; ++i) {
|
||||
let card = aPreviousResult.getCardAt(i);
|
||||
let email = aPreviousResult.getEmailToUse(i);
|
||||
if (this._checkEntry(card, email, searchWords)) {
|
||||
// Add matches into the results array. We re-sort as needed later.
|
||||
result._searchResults.push({
|
||||
value: aPreviousResult.getValueAt(i),
|
||||
comment: aPreviousResult.getCommentAt(i),
|
||||
card: card,
|
||||
isPrimaryEmail: (card.primaryEmail == email),
|
||||
emailToUse: email,
|
||||
popularity: parseInt(card.getProperty("PopularityIndex", "0")),
|
||||
score: this._getScore(card,
|
||||
aPreviousResult.getValueAt(i).toLocaleLowerCase(),
|
||||
fullString)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Construct the search query from pref; using a query means we can
|
||||
// optimise on running the search through c++ which is better for string
|
||||
// comparisons (_checkEntry is relatively slow).
|
||||
// When user's fullstring search expression is a multiword query, search
|
||||
// for each word separately so that each result contains all the words
|
||||
// from the fullstring in the fields of the addressbook card
|
||||
// (see bug 558931 for explanations).
|
||||
// Use helper method to split up search query to multi-word search
|
||||
// query against multiple fields.
|
||||
let searchWords = getSearchTokens(fullString);
|
||||
let searchQuery = generateQueryURI(result.modelQuery, searchWords);
|
||||
|
||||
// Now do the searching
|
||||
let allABs = this._abManager.directories;
|
||||
|
||||
// We're not going to bother searching sub-directories, currently the
|
||||
// architecture forces all cards that are in mailing lists to be in ABs as
|
||||
// well, therefore by searching sub-directories (aka mailing lists) we're
|
||||
// just going to find duplicates.
|
||||
while (allABs.hasMoreElements()) {
|
||||
let dir = allABs.getNext();
|
||||
if (dir instanceof Components.interfaces.nsIAbDirectory &&
|
||||
dir.useForAutocomplete(("idKey" in params) ? params.idKey : null)) {
|
||||
this._searchCards(searchQuery, dir, result);
|
||||
}
|
||||
}
|
||||
|
||||
result._searchResults = [...result._collectedValues.values()];
|
||||
}
|
||||
|
||||
// Sort the results. Scoring may have changed so do it even if this is
|
||||
// just filtered previous results.
|
||||
result._searchResults.sort(function(a, b) {
|
||||
// Order by 1) descending score, then 2) descending popularity,
|
||||
// then 3) primary email before secondary for the same card, then
|
||||
// 4) by emails sorted alphabetically.
|
||||
return (b.score - a.score) ||
|
||||
(b.popularity - a.popularity) ||
|
||||
((a.card == b.card && a.isPrimaryEmail) ? -1 : 0) ||
|
||||
a.value.localeCompare(b.value);
|
||||
});
|
||||
|
||||
if (result.matchCount) {
|
||||
result.searchResult = ACR.RESULT_SUCCESS;
|
||||
result.defaultIndex = 0;
|
||||
}
|
||||
|
||||
aListener.onSearchResult(this, result);
|
||||
},
|
||||
|
||||
stopSearch: function stopSearch() {
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces
|
||||
.nsIAutoCompleteSearch])
|
||||
};
|
||||
|
||||
// Module
|
||||
|
||||
var components = [nsAbAutoCompleteSearch];
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
323
mailnews/addrbook/src/nsAbBSDirectory.cpp
Normal file
323
mailnews/addrbook/src/nsAbBSDirectory.cpp
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsAbBSDirectory.h"
|
||||
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAddrDatabase.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsIAbMDBDirectory.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsAbDirFactoryService.h"
|
||||
#include "nsAbMDBDirFactory.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
|
||||
#include "nsCRTGlue.h"
|
||||
|
||||
nsAbBSDirectory::nsAbBSDirectory()
|
||||
: mInitialized(false)
|
||||
, mServers(13)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbBSDirectory::~nsAbBSDirectory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::Init(const char *aURI)
|
||||
{
|
||||
mURI = aURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsAbBSDirectory, nsAbDirProperty)
|
||||
|
||||
nsresult nsAbBSDirectory::CreateDirectoriesFromFactory(const nsACString &aURI,
|
||||
DIR_Server *aServer,
|
||||
bool aNotify)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Get the directory factory service
|
||||
nsCOMPtr<nsIAbDirFactoryService> dirFactoryService =
|
||||
do_GetService(NS_ABDIRFACTORYSERVICE_CONTRACTID,&rv);
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
// Get the directory factory from the URI
|
||||
nsCOMPtr<nsIAbDirFactory> dirFactory;
|
||||
rv = dirFactoryService->GetDirFactory(aURI, getter_AddRefs(dirFactory));
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
// Create the directories
|
||||
nsCOMPtr<nsISimpleEnumerator> newDirEnumerator;
|
||||
rv = dirFactory->GetDirectories(NS_ConvertUTF8toUTF16(aServer->description),
|
||||
aURI,
|
||||
nsDependentCString(aServer->prefName),
|
||||
getter_AddRefs(newDirEnumerator));
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
// Enumerate through the directories adding them
|
||||
// to the sub directories array
|
||||
bool hasMore;
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
|
||||
while (NS_SUCCEEDED(newDirEnumerator->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
nsCOMPtr<nsISupports> newDirSupports;
|
||||
rv = newDirEnumerator->GetNext(getter_AddRefs(newDirSupports));
|
||||
if(NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> childDir = do_QueryInterface(newDirSupports, &rv);
|
||||
if(NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
// Define a relationship between the preference
|
||||
// entry and the directory
|
||||
mServers.Put(childDir, aServer);
|
||||
|
||||
mSubDirectories.AppendObject(childDir);
|
||||
|
||||
if (aNotify && abManager)
|
||||
abManager->NotifyDirectoryItemAdded(this, childDir);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::GetChildNodes(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
nsresult rv = EnsureInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_NewArrayEnumerator(aResult, mSubDirectories);
|
||||
}
|
||||
|
||||
nsresult nsAbBSDirectory::EnsureInitialized()
|
||||
{
|
||||
if (mInitialized)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbDirFactoryService> dirFactoryService =
|
||||
do_GetService(NS_ABDIRFACTORYSERVICE_CONTRACTID,&rv);
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
nsTArray<DIR_Server*> *directories = DIR_GetDirectories();
|
||||
if (!directories)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
int32_t count = directories->Length();
|
||||
for (int32_t i = 0; i < count; i++)
|
||||
{
|
||||
DIR_Server *server = directories->ElementAt(i);
|
||||
|
||||
// if this is a 4.x, local .na2 addressbook (PABDirectory)
|
||||
// we must skip it.
|
||||
// mozilla can't handle 4.x .na2 addressbooks
|
||||
// note, the filename might be na2 for 4.x LDAP directories
|
||||
// (we used the .na2 file for replication), and we don't want to skip
|
||||
// those. see bug #127007
|
||||
uint32_t fileNameLen = strlen(server->fileName);
|
||||
if (((fileNameLen > kABFileName_PreviousSuffixLen) &&
|
||||
strcmp(server->fileName + fileNameLen - kABFileName_PreviousSuffixLen,
|
||||
kABFileName_PreviousSuffix) == 0) &&
|
||||
(server->dirType == PABDirectory))
|
||||
continue;
|
||||
|
||||
// Set the uri property
|
||||
nsAutoCString URI (server->uri);
|
||||
// This is in case the uri is never set
|
||||
// in the nsDirPref.cpp code.
|
||||
if (!server->uri)
|
||||
{
|
||||
URI = NS_LITERAL_CSTRING(kMDBDirectoryRoot);
|
||||
URI += nsDependentCString(server->fileName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that we are not converting from a
|
||||
* a 4.x address book file e.g. pab.na2
|
||||
* check if the URI ends with ".na2"
|
||||
*/
|
||||
if (StringEndsWith(URI, NS_LITERAL_CSTRING(kABFileName_PreviousSuffix)))
|
||||
URI.Replace(kMDBDirectoryRootLen, URI.Length() - kMDBDirectoryRootLen, server->fileName);
|
||||
|
||||
// Create the directories
|
||||
rv = CreateDirectoriesFromFactory(URI, server, false /* notify */);
|
||||
|
||||
// If we failed, this could be because something has set a pref for us
|
||||
// which is now broke (e.g. no factory present). So just ignore this one
|
||||
// and move on.
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("CreateDirectoriesFromFactory failed - Invalid factory?");
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
// sort directories by position...
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::CreateNewDirectory(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
uint32_t aType,
|
||||
const nsACString &aPrefName,
|
||||
nsACString &aResult)
|
||||
{
|
||||
nsresult rv = EnsureInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* This procedure is still MDB specific
|
||||
* due to the dependence on the current
|
||||
* nsDirPref.cpp code
|
||||
*/
|
||||
|
||||
nsCString URI(aURI);
|
||||
|
||||
/*
|
||||
* The creation of the address book in the preferences
|
||||
* is very MDB implementation specific.
|
||||
* If the fileName attribute is null then it will
|
||||
* create an appropriate file name.
|
||||
* Somehow have to resolve this issue so that it
|
||||
* is more general.
|
||||
*
|
||||
*/
|
||||
DIR_Server* server = nullptr;
|
||||
rv = DIR_AddNewAddressBook(aDirName, EmptyCString(), URI,
|
||||
(DirectoryType)aType, aPrefName, &server);
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
if (aType == PABDirectory) {
|
||||
// Add the URI property
|
||||
URI.AssignLiteral(kMDBDirectoryRoot);
|
||||
URI.Append(nsDependentCString(server->fileName));
|
||||
}
|
||||
|
||||
aResult.Assign(server->prefName);
|
||||
|
||||
rv = CreateDirectoriesFromFactory(URI, server, true /* notify */);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::CreateDirectoryByURI(const nsAString &aDisplayName,
|
||||
const nsACString &aURI)
|
||||
{
|
||||
nsresult rv = EnsureInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString fileName;
|
||||
if (StringBeginsWith(aURI, NS_LITERAL_CSTRING(kMDBDirectoryRoot)))
|
||||
fileName = Substring(aURI, kMDBDirectoryRootLen);
|
||||
|
||||
DIR_Server * server = nullptr;
|
||||
rv = DIR_AddNewAddressBook(aDisplayName, fileName, aURI,
|
||||
PABDirectory, EmptyCString(), &server);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = CreateDirectoriesFromFactory(aURI, server, true /* notify */);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::DeleteDirectory(nsIAbDirectory *directory)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(directory);
|
||||
|
||||
nsresult rv = EnsureInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DIR_Server *server = nullptr;
|
||||
mServers.Get(directory, &server);
|
||||
|
||||
if (!server)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
struct GetDirectories
|
||||
{
|
||||
GetDirectories(DIR_Server* aServer) : mServer(aServer) { }
|
||||
|
||||
nsCOMArray<nsIAbDirectory> directories;
|
||||
DIR_Server* mServer;
|
||||
};
|
||||
GetDirectories getDirectories(server);
|
||||
for (auto iter = mServers.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData() == getDirectories.mServer) {
|
||||
nsCOMPtr<nsIAbDirectory> abDir = do_QueryInterface(iter.Key());
|
||||
getDirectories.directories.AppendObject(abDir);
|
||||
}
|
||||
}
|
||||
|
||||
DIR_DeleteServerFromList(server);
|
||||
|
||||
nsCOMPtr<nsIAbDirFactoryService> dirFactoryService =
|
||||
do_GetService(NS_ABDIRFACTORYSERVICE_CONTRACTID,&rv);
|
||||
NS_ENSURE_SUCCESS (rv, rv);
|
||||
|
||||
uint32_t count = getDirectories.directories.Count();
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsIAbDirectory> d = getDirectories.directories[i];
|
||||
|
||||
mServers.Remove(d);
|
||||
mSubDirectories.RemoveObject(d);
|
||||
|
||||
if (abManager)
|
||||
abManager->NotifyDirectoryDeleted(this, d);
|
||||
|
||||
nsCString uri;
|
||||
rv = d->GetURI(uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirFactory> dirFactory;
|
||||
rv = dirFactoryService->GetDirFactory(uri, getter_AddRefs(dirFactory));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
rv = dirFactory->DeleteDirectory(d);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::HasDirectory(nsIAbDirectory *dir, bool *hasDir)
|
||||
{
|
||||
if (!hasDir)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = EnsureInitialized();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DIR_Server *dirServer = nullptr;
|
||||
mServers.Get(dir, &dirServer);
|
||||
return DIR_ContainsServer(dirServer, hasDir);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::UseForAutocomplete(const nsACString &aIdentityKey,
|
||||
bool *aResult)
|
||||
{
|
||||
// For the "root" directory (kAllDirectoryRoot) always return true so that
|
||||
// we can search sub directories that may or may not be local.
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBSDirectory::GetURI(nsACString &aURI)
|
||||
{
|
||||
if (mURI.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
aURI = mURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
50
mailnews/addrbook/src/nsAbBSDirectory.h
Normal file
50
mailnews/addrbook/src/nsAbBSDirectory.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef nsAbBSDirectory_h__
|
||||
#define nsAbBSDirectory_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbDirProperty.h"
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsAbBSDirectory : public nsAbDirProperty
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsAbBSDirectory();
|
||||
|
||||
// nsIAbDirectory methods
|
||||
NS_IMETHOD Init(const char *aURI) override;
|
||||
NS_IMETHOD GetChildNodes(nsISimpleEnumerator* *result) override;
|
||||
NS_IMETHOD CreateNewDirectory(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
uint32_t aType,
|
||||
const nsACString &aPrefName,
|
||||
nsACString &aResult) override;
|
||||
NS_IMETHOD CreateDirectoryByURI(const nsAString &aDisplayName,
|
||||
const nsACString &aURI) override;
|
||||
NS_IMETHOD DeleteDirectory(nsIAbDirectory *directory) override;
|
||||
NS_IMETHOD HasDirectory(nsIAbDirectory *dir, bool *hasDir) override;
|
||||
NS_IMETHOD UseForAutocomplete(const nsACString &aIdentityKey, bool *aResult) override;
|
||||
NS_IMETHOD GetURI(nsACString &aURI) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsAbBSDirectory();
|
||||
nsresult EnsureInitialized();
|
||||
nsresult CreateDirectoriesFromFactory(const nsACString &aURI,
|
||||
DIR_Server* aServer, bool aNotify);
|
||||
|
||||
protected:
|
||||
bool mInitialized;
|
||||
nsCOMArray<nsIAbDirectory> mSubDirectories;
|
||||
nsDataHashtable<nsISupportsHashKey, DIR_Server*> mServers;
|
||||
};
|
||||
|
||||
#endif
|
||||
246
mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp
Normal file
246
mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIAbLDAPAttributeMap.h"
|
||||
#include "nsAbBoolExprToLDAPFilter.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
const int nsAbBoolExprToLDAPFilter::TRANSLATE_CARD_PROPERTY = 1 << 0 ;
|
||||
const int nsAbBoolExprToLDAPFilter::ALLOW_NON_CONVERTABLE_CARD_PROPERTY = 1 << 1 ;
|
||||
|
||||
nsresult nsAbBoolExprToLDAPFilter::Convert (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsCString& filter,
|
||||
int flags)
|
||||
{
|
||||
nsCString f;
|
||||
nsresult rv = FilterExpression (map, expression, f, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
filter = f;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbBoolExprToLDAPFilter::FilterExpression (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsCString& filter,
|
||||
int flags)
|
||||
{
|
||||
nsCOMPtr<nsIArray> childExpressions;
|
||||
nsresult rv = expression->GetExpressions(getter_AddRefs(childExpressions));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t count;
|
||||
rv = childExpressions->GetLength(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
|
||||
nsAbBooleanOperationType operation;
|
||||
rv = expression->GetOperation(&operation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/*
|
||||
* 3rd party query integration with Mozilla is achieved
|
||||
* by calling nsAbLDAPDirectoryQuery::DoQuery(). Thus
|
||||
* we can arrive here with a query asking for all the
|
||||
* ldap attributes using the card:nsIAbCard interface.
|
||||
*
|
||||
* So we need to check that we are not creating a condition
|
||||
* filter against this expression otherwise we will end up with an invalid
|
||||
* filter equal to "(|)".
|
||||
*/
|
||||
|
||||
if (count == 1 )
|
||||
{
|
||||
nsCOMPtr<nsIAbBooleanConditionString>
|
||||
childCondition(do_QueryElementAt(childExpressions, 1, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCString name;
|
||||
rv = childCondition->GetName (getter_Copies (name));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if(name.Equals("card:nsIAbCard"))
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
filter.AppendLiteral("(");
|
||||
switch (operation)
|
||||
{
|
||||
case nsIAbBooleanOperationTypes::AND:
|
||||
filter.AppendLiteral("&");
|
||||
rv = FilterExpressions (map, childExpressions, filter, flags);
|
||||
break;
|
||||
case nsIAbBooleanOperationTypes::OR:
|
||||
filter.AppendLiteral("|");
|
||||
rv = FilterExpressions (map, childExpressions, filter, flags);
|
||||
break;
|
||||
case nsIAbBooleanOperationTypes::NOT:
|
||||
if (count > 1)
|
||||
return NS_ERROR_FAILURE;
|
||||
filter.AppendLiteral("!");
|
||||
rv = FilterExpressions (map, childExpressions, filter, flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
filter.AppendLiteral(")");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbBoolExprToLDAPFilter::FilterExpressions (
|
||||
nsIAbLDAPAttributeMap *map,
|
||||
nsIArray* expressions,
|
||||
nsCString& filter,
|
||||
int flags)
|
||||
{
|
||||
uint32_t count;
|
||||
nsresult rv = expressions->GetLength(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanConditionString> childCondition;
|
||||
nsCOMPtr<nsIAbBooleanExpression> childExpression;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
childCondition = do_QueryElementAt(expressions, i, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = FilterCondition (map, childCondition, filter, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
continue;
|
||||
}
|
||||
|
||||
childExpression = do_QueryElementAt(expressions, i, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = FilterExpression (map, childExpression, filter, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbBoolExprToLDAPFilter::FilterCondition (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanConditionString* condition,
|
||||
nsCString& filter,
|
||||
int flags)
|
||||
{
|
||||
nsCString name;
|
||||
nsresult rv = condition->GetName(getter_Copies (name));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString ldapAttr(name);
|
||||
if (flags & TRANSLATE_CARD_PROPERTY)
|
||||
{
|
||||
rv = map->GetFirstAttribute (name, ldapAttr);
|
||||
if (!(flags & ALLOW_NON_CONVERTABLE_CARD_PROPERTY) &&
|
||||
!ATTRMAP_FOUND_ATTR(rv, ldapAttr))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAbBooleanConditionType conditionType;
|
||||
rv = condition->GetCondition(&conditionType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString value;
|
||||
rv = condition->GetValue (getter_Copies (value));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ConvertUTF16toUTF8 vUTF8 (value);
|
||||
|
||||
switch (conditionType)
|
||||
{
|
||||
case nsIAbBooleanConditionTypes::DoesNotExist:
|
||||
filter.AppendLiteral("(!(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=*))");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::Exists:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=*)");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::Contains:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.Append("=*");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral("*)");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::DoesNotContain:
|
||||
filter.AppendLiteral("(!(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=*");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral("*))");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::Is:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral(")");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::IsNot:
|
||||
filter.AppendLiteral("(!(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral("))");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::BeginsWith:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral("*)");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::EndsWith:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("=*");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral(")");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::LessThan:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("<=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral(")");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::GreaterThan:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral(">=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral(")");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::SoundsLike:
|
||||
filter.AppendLiteral("(");
|
||||
filter.Append(ldapAttr);
|
||||
filter.AppendLiteral("~=");
|
||||
filter.Append(vUTF8);
|
||||
filter.AppendLiteral(")");
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::RegExp:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
45
mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h
Normal file
45
mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsBooleanExpressionToLDAPFilter_h__
|
||||
#define nsBooleanExpressionToLDAPFilter_h__
|
||||
|
||||
#include "nsIAbBooleanExpression.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIAbLDAPAttributeMap;
|
||||
|
||||
class nsAbBoolExprToLDAPFilter
|
||||
{
|
||||
public:
|
||||
static const int TRANSLATE_CARD_PROPERTY ;
|
||||
static const int ALLOW_NON_CONVERTABLE_CARD_PROPERTY ;
|
||||
|
||||
static nsresult Convert (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsCString& filter,
|
||||
int flags = TRANSLATE_CARD_PROPERTY);
|
||||
|
||||
protected:
|
||||
static nsresult FilterExpression (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsCString& filter,
|
||||
int flags);
|
||||
static nsresult FilterExpressions (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIArray* expressions,
|
||||
nsCString& filter,
|
||||
int flags);
|
||||
static nsresult FilterCondition (
|
||||
nsIAbLDAPAttributeMap* map,
|
||||
nsIAbBooleanConditionString* condition,
|
||||
nsCString& filter,
|
||||
int flags);
|
||||
};
|
||||
|
||||
#endif
|
||||
132
mailnews/addrbook/src/nsAbBooleanExpression.cpp
Normal file
132
mailnews/addrbook/src/nsAbBooleanExpression.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbBooleanExpression.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbBooleanConditionString, nsIAbBooleanConditionString)
|
||||
|
||||
nsAbBooleanConditionString::nsAbBooleanConditionString() :
|
||||
mCondition (nsIAbBooleanConditionTypes::Exists)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbBooleanConditionString::~nsAbBooleanConditionString()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute nsAbBooleanConditionType condition; */
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::GetCondition(nsAbBooleanConditionType *aCondition)
|
||||
{
|
||||
if (!aCondition)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aCondition = mCondition;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::SetCondition(nsAbBooleanConditionType aCondition)
|
||||
{
|
||||
mCondition = aCondition;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute string name; */
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::GetName(char** aName)
|
||||
{
|
||||
if (!aName)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aName = mName.IsEmpty() ? 0 : ToNewCString(mName);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::SetName(const char* aName)
|
||||
{
|
||||
if (!aName)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mName = aName;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute wstring value; */
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::GetValue(char16_t** aValue)
|
||||
{
|
||||
if (!aValue)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aValue = ToNewUnicode(mValue);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsAbBooleanConditionString::SetValue(const char16_t * aValue)
|
||||
{
|
||||
if (!aValue)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mValue = aValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbBooleanExpression, nsIAbBooleanExpression)
|
||||
|
||||
nsAbBooleanExpression::nsAbBooleanExpression() :
|
||||
mOperation (nsIAbBooleanOperationTypes::AND)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbBooleanExpression::~nsAbBooleanExpression()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute nsAbBooleanOperationType operation; */
|
||||
NS_IMETHODIMP nsAbBooleanExpression::GetOperation(nsAbBooleanOperationType *aOperation)
|
||||
{
|
||||
if (!aOperation)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aOperation = mOperation;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsAbBooleanExpression::SetOperation(nsAbBooleanOperationType aOperation)
|
||||
{
|
||||
mOperation = aOperation;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIArray expressions; */
|
||||
NS_IMETHODIMP nsAbBooleanExpression::GetExpressions(nsIArray **aExpressions)
|
||||
{
|
||||
if (!aExpressions)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (!mExpressions)
|
||||
{
|
||||
mExpressions = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
|
||||
if (!mExpressions)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aExpressions = mExpressions);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbBooleanExpression::SetExpressions(nsIArray *aExpressions)
|
||||
{
|
||||
if (!aExpressions)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mExpressions = aExpressions;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
43
mailnews/addrbook/src/nsAbBooleanExpression.h
Normal file
43
mailnews/addrbook/src/nsAbBooleanExpression.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbBooleanExpression_h__
|
||||
#define nsAbBooleanExpression_h__
|
||||
|
||||
#include "nsIAbBooleanExpression.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIArray.h"
|
||||
|
||||
class nsAbBooleanConditionString : public nsIAbBooleanConditionString
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABBOOLEANCONDITIONSTRING
|
||||
|
||||
nsAbBooleanConditionString();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbBooleanConditionString();
|
||||
nsAbBooleanConditionType mCondition;
|
||||
nsCString mName;
|
||||
nsString mValue;
|
||||
};
|
||||
|
||||
class nsAbBooleanExpression: public nsIAbBooleanExpression
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABBOOLEANEXPRESSION
|
||||
|
||||
nsAbBooleanExpression();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbBooleanExpression();
|
||||
nsAbBooleanOperationType mOperation;
|
||||
nsCOMPtr<nsIArray> mExpressions;
|
||||
};
|
||||
|
||||
#endif
|
||||
1193
mailnews/addrbook/src/nsAbCardProperty.cpp
Normal file
1193
mailnews/addrbook/src/nsAbCardProperty.cpp
Normal file
File diff suppressed because it is too large
Load diff
59
mailnews/addrbook/src/nsAbCardProperty.h
Normal file
59
mailnews/addrbook/src/nsAbCardProperty.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Address Book Person Card Property
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsAbCardProperty_h__
|
||||
#define nsAbCardProperty_h__
|
||||
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
class nsIStringBundle;
|
||||
class mozITXTToHTMLConv;
|
||||
struct AppendItem;
|
||||
|
||||
/*
|
||||
* Address Book Card Property
|
||||
*/
|
||||
|
||||
class nsAbCardProperty: public nsIAbCard
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABCARD
|
||||
NS_DECL_NSIABITEM
|
||||
|
||||
nsAbCardProperty();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbCardProperty();
|
||||
bool m_IsMailList;
|
||||
nsCString m_MailListURI;
|
||||
|
||||
// Store most of the properties here
|
||||
nsInterfaceHashtable<nsCStringHashKey, nsIVariant> m_properties;
|
||||
|
||||
nsCString m_directoryId, m_localId;
|
||||
private:
|
||||
nsresult AppendSection(const AppendItem *aArray, int16_t aCount, const nsString& aHeading, nsIStringBundle *aBundle, mozITXTToHTMLConv *aConv, nsString &aResult);
|
||||
nsresult AppendLine(const AppendItem &aItem, mozITXTToHTMLConv *aConv, nsString &aResult);
|
||||
nsresult AppendLabel(const AppendItem &aItem, nsIStringBundle *aBundle, mozITXTToHTMLConv *aConv, nsString &aResult);
|
||||
nsresult AppendCityStateZip(const AppendItem &aItem, nsIStringBundle *aBundle, mozITXTToHTMLConv *aConv, nsString &aResult);
|
||||
|
||||
nsresult ConvertToBase64EncodedXML(nsACString &result);
|
||||
nsresult ConvertToXMLPrintData(nsAString &result);
|
||||
nsresult ConvertToEscapedVCard(nsACString &result);
|
||||
};
|
||||
|
||||
#endif
|
||||
184
mailnews/addrbook/src/nsAbContentHandler.cpp
Normal file
184
mailnews/addrbook/src/nsAbContentHandler.cpp
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbContentHandler.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "plstr.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsIMsgVCardService.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsVCard.h"
|
||||
#include "nsIChannel.h"
|
||||
//
|
||||
// nsAbContentHandler
|
||||
//
|
||||
nsAbContentHandler::nsAbContentHandler()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbContentHandler::~nsAbContentHandler()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbContentHandler, nsIContentHandler,
|
||||
nsIStreamLoaderObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbContentHandler::HandleContent(const char *aContentType,
|
||||
nsIInterfaceRequestor *aWindowContext,
|
||||
nsIRequest *request)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(request);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// First of all, get the content type and make sure it is a content type we know how to handle!
|
||||
if (PL_strcasecmp(aContentType, "application/x-addvcard") == 0) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||
if (!aChannel) return NS_ERROR_FAILURE;
|
||||
|
||||
rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
if (uri)
|
||||
{
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPath(path);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
const char *startOfVCard = strstr(path.get(), "add?vcard=");
|
||||
if (startOfVCard)
|
||||
{
|
||||
nsCString unescapedData;
|
||||
|
||||
// XXX todo, explain why we is escaped twice
|
||||
MsgUnescapeString(nsDependentCString(startOfVCard + strlen("add?vcard=")),
|
||||
0, unescapedData);
|
||||
|
||||
if (!aWindowContext)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> domWindow = do_GetInterface(aWindowContext);
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = nsPIDOMWindowOuter::From(domWindow);
|
||||
parentWindow = parentWindow->GetOuterWindow();
|
||||
NS_ENSURE_ARG_POINTER(parentWindow);
|
||||
|
||||
nsCOMPtr<nsIAbManager> ab =
|
||||
do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIAbCard> cardFromVCard;
|
||||
rv = ab->EscapedVCardToAbCard(unescapedData.get(),
|
||||
getter_AddRefs(cardFromVCard));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
|
||||
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ifptr->SetData(cardFromVCard);
|
||||
ifptr->SetDataIID(&NS_GET_IID(nsIAbCard));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> dialogWindow;
|
||||
|
||||
rv = parentWindow->OpenDialog(
|
||||
NS_LITERAL_STRING("chrome://messenger/content/addressbook/abNewCardDialog.xul"),
|
||||
EmptyString(),
|
||||
NS_LITERAL_STRING("chrome,resizable=no,titlebar,modal,centerscreen"),
|
||||
ifptr, getter_AddRefs(dialogWindow));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
else if (PL_strcasecmp(aContentType, "text/x-vcard") == 0) {
|
||||
// create a vcard stream listener that can parse the data stream
|
||||
// and bring up the appropriate UI
|
||||
|
||||
// (1) cancel the current load operation. We'll restart it
|
||||
request->Cancel(NS_ERROR_ABORT);
|
||||
// get the url we were trying to open
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
|
||||
|
||||
rv = channel->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// create a stream loader to handle the v-card data
|
||||
nsCOMPtr<nsIStreamLoader> streamLoader;
|
||||
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader),
|
||||
uri,
|
||||
this,
|
||||
nullPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
}
|
||||
else // The content-type was not application/x-addvcard...
|
||||
return NS_ERROR_WONT_HANDLE_CONTENT;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbContentHandler::OnStreamComplete(nsIStreamLoader *aLoader,
|
||||
nsISupports *aContext, nsresult aStatus,
|
||||
uint32_t datalen, const uint8_t *data)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aContext);
|
||||
NS_ENSURE_SUCCESS(aStatus, aStatus); // don't process the vcard if we got a status error
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// take our vCard string and open up an address book window based on it
|
||||
nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(NS_MSGVCARDSERVICE_CONTRACTID);
|
||||
if (vCardService)
|
||||
{
|
||||
nsAutoPtr<VObject> vObj(vCardService->Parse_MIME((const char *)data, datalen));
|
||||
if (vObj)
|
||||
{
|
||||
int32_t len = 0;
|
||||
nsCString vCard;
|
||||
vCard.Adopt(vCardService->WriteMemoryVObjects(0, &len, vObj, false));
|
||||
|
||||
nsCOMPtr<nsIAbManager> ab =
|
||||
do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIAbCard> cardFromVCard;
|
||||
rv = ab->EscapedVCardToAbCard(vCard.get(),
|
||||
getter_AddRefs(cardFromVCard));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> domWindow = do_GetInterface(aContext);
|
||||
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = nsPIDOMWindowOuter::From(domWindow);
|
||||
parentWindow = parentWindow->GetOuterWindow();
|
||||
NS_ENSURE_ARG_POINTER(parentWindow);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> dialogWindow;
|
||||
rv = parentWindow->OpenDialog(
|
||||
NS_LITERAL_STRING("chrome://messenger/content/addressbook/abNewCardDialog.xul"),
|
||||
EmptyString(),
|
||||
NS_LITERAL_STRING("chrome,resizable=no,titlebar,modal,centerscreen"),
|
||||
cardFromVCard, getter_AddRefs(dialogWindow));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
26
mailnews/addrbook/src/nsAbContentHandler.h
Normal file
26
mailnews/addrbook/src/nsAbContentHandler.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __nsAbContentHandler_h
|
||||
#define __nsAbContentHandler_h
|
||||
|
||||
#include "nsIStreamLoader.h"
|
||||
#include "nsIContentHandler.h"
|
||||
|
||||
class nsAbContentHandler : public nsIContentHandler,
|
||||
public nsIStreamLoaderObserver
|
||||
{
|
||||
public:
|
||||
nsAbContentHandler();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICONTENTHANDLER
|
||||
NS_DECL_NSISTREAMLOADEROBSERVER
|
||||
|
||||
private:
|
||||
virtual ~nsAbContentHandler();
|
||||
};
|
||||
|
||||
#endif
|
||||
54
mailnews/addrbook/src/nsAbDirFactoryService.cpp
Normal file
54
mailnews/addrbook/src/nsAbDirFactoryService.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "plstr.h"
|
||||
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbDirFactoryService.h"
|
||||
#include "nsIAbDirFactory.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirFactoryService, nsIAbDirFactoryService)
|
||||
|
||||
nsAbDirFactoryService::nsAbDirFactoryService()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirFactoryService::~nsAbDirFactoryService()
|
||||
{
|
||||
}
|
||||
|
||||
/* nsIAbDirFactory getDirFactory (in string uri); */
|
||||
NS_IMETHODIMP
|
||||
nsAbDirFactoryService::GetDirFactory(const nsACString &aURI,
|
||||
nsIAbDirFactory** aDirFactory)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirFactory);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Obtain the network IO service
|
||||
nsCOMPtr<nsIIOService> nsService =
|
||||
mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(nsService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Extract the scheme
|
||||
nsAutoCString scheme;
|
||||
rv = nsService->ExtractScheme(aURI, scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Try to find a factory using the component manager.
|
||||
nsAutoCString contractID;
|
||||
contractID.AssignLiteral(NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX);
|
||||
contractID.Append(scheme);
|
||||
|
||||
return CallCreateInstance(contractID.get(), aDirFactory);
|
||||
}
|
||||
23
mailnews/addrbook/src/nsAbDirFactoryService.h
Normal file
23
mailnews/addrbook/src/nsAbDirFactoryService.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbDirFactoryService_h__
|
||||
#define nsAbDirFactoryService_h__
|
||||
|
||||
#include "nsIAbDirFactoryService.h"
|
||||
|
||||
class nsAbDirFactoryService : public nsIAbDirFactoryService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRFACTORYSERVICE
|
||||
|
||||
nsAbDirFactoryService();
|
||||
|
||||
private:
|
||||
virtual ~nsAbDirFactoryService();
|
||||
};
|
||||
|
||||
#endif
|
||||
593
mailnews/addrbook/src/nsAbDirProperty.cpp
Normal file
593
mailnews/addrbook/src/nsAbDirProperty.cpp
Normal file
|
|
@ -0,0 +1,593 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbDirProperty.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
// From nsDirPrefs
|
||||
#define kDefaultPosition 1
|
||||
|
||||
nsAbDirProperty::nsAbDirProperty(void)
|
||||
: m_LastModifiedDate(0),
|
||||
mIsValidURI(false),
|
||||
mIsQueryURI(false)
|
||||
{
|
||||
m_IsMailList = false;
|
||||
}
|
||||
|
||||
nsAbDirProperty::~nsAbDirProperty(void)
|
||||
{
|
||||
#if 0
|
||||
// this code causes a regression #138647
|
||||
// don't turn it on until you figure it out
|
||||
if (m_AddressList) {
|
||||
uint32_t count;
|
||||
nsresult rv;
|
||||
rv = m_AddressList->GetLength(&count);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
int32_t i;
|
||||
for (i = count - 1; i >= 0; i--)
|
||||
m_AddressList->RemoveElementAt(i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirProperty, nsIAbDirectory, nsISupportsWeakReference,
|
||||
nsIAbCollection, nsIAbItem)
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetUuid(nsACString &uuid)
|
||||
{
|
||||
// XXX: not all directories have a dirPrefId...
|
||||
nsresult rv = GetDirPrefId(uuid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
uuid.Append('&');
|
||||
nsString dirName;
|
||||
GetDirName(dirName);
|
||||
uuid.Append(NS_ConvertUTF16toUTF8(dirName));
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GenerateName(int32_t aGenerateFormat,
|
||||
nsIStringBundle *aBundle,
|
||||
nsAString &name)
|
||||
{
|
||||
return GetDirName(name);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetPropertiesChromeURI(nsACString &aResult)
|
||||
{
|
||||
aResult.AssignLiteral("chrome://messenger/content/addressbook/abAddressBookNameDialog.xul");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetDirName(nsAString &aDirName)
|
||||
{
|
||||
if (m_DirPrefId.IsEmpty())
|
||||
{
|
||||
aDirName = m_ListDirName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCString dirName;
|
||||
nsresult rv = GetLocalizedStringValue("description", EmptyCString(), dirName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// In TB 2 only some prefs had chrome:// URIs. We had code in place that would
|
||||
// only get the localized string pref for the particular address books that
|
||||
// were built-in.
|
||||
// Additionally, nsIPrefBranch::getComplexValue will only get a non-user-set,
|
||||
// non-locked pref value if it is a chrome:// URI and will get the string
|
||||
// value at that chrome URI. This breaks extensions/autoconfig that want to
|
||||
// set default pref values and allow users to change directory names.
|
||||
//
|
||||
// Now we have to support this, and so if for whatever reason we fail to get
|
||||
// the localized version, then we try and get the non-localized version
|
||||
// instead. If the string value is empty, then we'll just get the empty value
|
||||
// back here.
|
||||
if (dirName.IsEmpty())
|
||||
{
|
||||
rv = GetStringValue("description", EmptyCString(), dirName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(dirName, aDirName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Although mailing lists could use the NotifyItemPropertyChanged
|
||||
// mechanism here, it requires some rework on how we write/save data
|
||||
// relating to mailing lists, so we're just using the old method of a
|
||||
// local variable to store the mailing list name.
|
||||
NS_IMETHODIMP nsAbDirProperty::SetDirName(const nsAString &aDirName)
|
||||
{
|
||||
if (m_DirPrefId.IsEmpty())
|
||||
{
|
||||
m_ListDirName = aDirName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Store the old value.
|
||||
nsString oldDirName;
|
||||
nsresult rv = GetDirName(oldDirName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Save the new value
|
||||
rv = SetLocalizedStringValue("description", NS_ConvertUTF16toUTF8(aDirName));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
// We inherit from nsIAbDirectory, so this static cast should be safe.
|
||||
abManager->NotifyItemPropertyChanged(static_cast<nsIAbDirectory*>(this),
|
||||
"DirName", oldDirName.get(),
|
||||
nsString(aDirName).get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetDirType(int32_t *aDirType)
|
||||
{
|
||||
return GetIntValue("dirType", LDAPDirectory, aDirType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetFileName(nsACString &aFileName)
|
||||
{
|
||||
return GetStringValue("filename", EmptyCString(), aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetURI(nsACString &aURI)
|
||||
{
|
||||
// XXX Should we complete this for Mailing Lists?
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetPosition(int32_t *aPosition)
|
||||
{
|
||||
return GetIntValue("position", kDefaultPosition, aPosition);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetLastModifiedDate(uint32_t *aLastModifiedDate)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLastModifiedDate);
|
||||
*aLastModifiedDate = m_LastModifiedDate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetLastModifiedDate(uint32_t aLastModifiedDate)
|
||||
{
|
||||
if (aLastModifiedDate)
|
||||
{
|
||||
m_LastModifiedDate = aLastModifiedDate;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetListNickName(nsAString &aListNickName)
|
||||
{
|
||||
aListNickName = m_ListNickName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetListNickName(const nsAString &aListNickName)
|
||||
{
|
||||
m_ListNickName = aListNickName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetDescription(nsAString &aDescription)
|
||||
{
|
||||
aDescription = m_Description;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetDescription(const nsAString &aDescription)
|
||||
{
|
||||
m_Description = aDescription;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetIsMailList(bool *aIsMailList)
|
||||
{
|
||||
*aIsMailList = m_IsMailList;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetIsMailList(bool aIsMailList)
|
||||
{
|
||||
m_IsMailList = aIsMailList;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetAddressLists(nsIMutableArray * *aAddressLists)
|
||||
{
|
||||
if (!m_AddressList)
|
||||
{
|
||||
nsresult rv;
|
||||
m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*aAddressLists = m_AddressList;
|
||||
NS_ADDREF(*aAddressLists);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetAddressLists(nsIMutableArray * aAddressLists)
|
||||
{
|
||||
m_AddressList = aAddressLists;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::CopyMailList(nsIAbDirectory* srcList)
|
||||
{
|
||||
SetIsMailList(true);
|
||||
|
||||
nsString str;
|
||||
srcList->GetDirName(str);
|
||||
SetDirName(str);
|
||||
srcList->GetListNickName(str);
|
||||
SetListNickName(str);
|
||||
srcList->GetDescription(str);
|
||||
SetDescription(str);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> pAddressLists;
|
||||
srcList->GetAddressLists(getter_AddRefs(pAddressLists));
|
||||
SetAddressLists(pAddressLists);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetIsQuery(bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
// Mailing lists are not queries by default, individual directory types
|
||||
// will override this.
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::Init(const char *aURI)
|
||||
{
|
||||
mURINoQuery = aURI;
|
||||
mURI = aURI;
|
||||
mIsValidURI = true;
|
||||
|
||||
int32_t searchCharLocation = mURINoQuery.FindChar('?');
|
||||
if (searchCharLocation >= 0)
|
||||
{
|
||||
mQueryString = Substring(mURINoQuery, searchCharLocation + 1);
|
||||
mURINoQuery.SetLength(searchCharLocation);
|
||||
mIsQueryURI = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIAbDirectory NOT IMPLEMENTED methods
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::GetChildNodes(nsISimpleEnumerator **childList)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::GetChildCards(nsISimpleEnumerator **childCards)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::DeleteDirectory(nsIAbDirectory *directory)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::HasCard(nsIAbCard *cards, bool *hasCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::HasDirectory(nsIAbDirectory *dir, bool *hasDir)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::HasMailListWithName(const char16_t *aName, bool *aHasList)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aName);
|
||||
NS_ENSURE_ARG_POINTER(aHasList);
|
||||
|
||||
*aHasList = false;
|
||||
|
||||
bool supportsLists = false;
|
||||
nsresult rv = GetSupportsMailingLists(&supportsLists);
|
||||
if (NS_FAILED(rv) || !supportsLists)
|
||||
return NS_OK;
|
||||
|
||||
if (m_IsMailList)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> addressLists;
|
||||
rv = GetAddressLists(getter_AddRefs(addressLists));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t listCount = 0;
|
||||
rv = addressLists->GetLength(&listCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < listCount; i++)
|
||||
{
|
||||
nsCOMPtr<nsIAbDirectory> listDir(do_QueryElementAt(addressLists, i, &rv));
|
||||
if (NS_SUCCEEDED(rv) && listDir)
|
||||
{
|
||||
nsAutoString listName;
|
||||
rv = listDir->GetDirName(listName);
|
||||
if (NS_SUCCEEDED(rv) && listName.Equals(aName))
|
||||
{
|
||||
*aHasList = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::CreateNewDirectory(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
uint32_t aType,
|
||||
const nsACString &aPrefName,
|
||||
nsACString &aResult)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbDirProperty::CreateDirectoryByURI(const nsAString &aDisplayName,
|
||||
const nsACString &aURI)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::AddMailList(nsIAbDirectory *list, nsIAbDirectory **addedList)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::EditMailListToDatabase(nsIAbCard *listCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::AddCard(nsIAbCard *childCard, nsIAbCard **addedCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::ModifyCard(nsIAbCard *aModifiedCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::DeleteCards(nsIArray *cards)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::DropCard(nsIAbCard *childCard, bool needToCopyCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::CardForEmailAddress(const nsACString &aEmailAddress,
|
||||
nsIAbCard ** aAbCard)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetCardFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool caseSensitive,
|
||||
nsIAbCard **result)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetCardsFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool caseSensitive,
|
||||
nsISimpleEnumerator **result)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetSupportsMailingLists(bool *aSupportsMailingsLists)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSupportsMailingsLists);
|
||||
// We don't currently support nested mailing lists, so only return true if
|
||||
// we're not a mailing list.
|
||||
*aSupportsMailingsLists = !m_IsMailList;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetReadOnly(bool *aReadOnly)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aReadOnly);
|
||||
// Default is that we are writable. Any implementation that is read-only must
|
||||
// override this method.
|
||||
*aReadOnly = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetIsRemote(bool *aIsRemote)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsRemote);
|
||||
*aIsRemote = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetIsSecure(bool *aIsSecure)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSecure);
|
||||
*aIsSecure = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::UseForAutocomplete(const nsACString &aIdentityKey,
|
||||
bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
// Is local autocomplete enabled?
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return prefBranch->GetBoolPref("mail.enable_autocomplete", aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetDirPrefId(nsACString &aDirPrefId)
|
||||
{
|
||||
aDirPrefId = m_DirPrefId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetDirPrefId(const nsACString &aDirPrefId)
|
||||
{
|
||||
if (!m_DirPrefId.Equals(aDirPrefId))
|
||||
{
|
||||
m_DirPrefId.Assign(aDirPrefId);
|
||||
// Clear the directory pref branch so that it is re-initialized next
|
||||
// time its required.
|
||||
m_DirectoryPrefs = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbDirProperty::InitDirectoryPrefs()
|
||||
{
|
||||
if (m_DirPrefId.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString realPrefId(m_DirPrefId);
|
||||
realPrefId.Append('.');
|
||||
|
||||
return prefService->GetBranch(realPrefId.get(), getter_AddRefs(m_DirectoryPrefs));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetIntValue(const char *aName,
|
||||
int32_t aDefaultValue,
|
||||
int32_t *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (NS_FAILED(m_DirectoryPrefs->GetIntPref(aName, aResult)))
|
||||
*aResult = aDefaultValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetBoolValue(const char *aName,
|
||||
bool aDefaultValue,
|
||||
bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (NS_FAILED(m_DirectoryPrefs->GetBoolPref(aName, aResult)))
|
||||
*aResult = aDefaultValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::GetStringValue(const char *aName,
|
||||
const nsACString &aDefaultValue,
|
||||
nsACString &aResult)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCString value;
|
||||
|
||||
/* unfortunately, there may be some prefs out there which look like (null) */
|
||||
if (NS_SUCCEEDED(m_DirectoryPrefs->GetCharPref(aName, getter_Copies(value))) &&
|
||||
!value.EqualsLiteral("(null"))
|
||||
aResult = value;
|
||||
else
|
||||
aResult = aDefaultValue;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
/*
|
||||
* Get localized unicode string pref from properties file, convert into an
|
||||
* UTF8 string since address book prefs store as UTF8 strings. So far there
|
||||
* are 2 default prefs stored in addressbook.properties.
|
||||
* "ldap_2.servers.pab.description"
|
||||
* "ldap_2.servers.history.description"
|
||||
*/
|
||||
NS_IMETHODIMP nsAbDirProperty::GetLocalizedStringValue(const char *aName,
|
||||
const nsACString &aDefaultValue,
|
||||
nsACString &aResult)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsString wvalue;
|
||||
nsCOMPtr<nsIPrefLocalizedString> locStr;
|
||||
|
||||
nsresult rv = m_DirectoryPrefs->GetComplexValue(aName,
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
getter_AddRefs(locStr));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = locStr->ToString(getter_Copies(wvalue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (wvalue.IsEmpty())
|
||||
aResult = aDefaultValue;
|
||||
else
|
||||
CopyUTF16toUTF8(wvalue, aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetIntValue(const char *aName,
|
||||
int32_t aValue)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return m_DirectoryPrefs->SetIntPref(aName, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetBoolValue(const char *aName,
|
||||
bool aValue)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return m_DirectoryPrefs->SetBoolPref(aName, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetStringValue(const char *aName,
|
||||
const nsACString &aValue)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return m_DirectoryPrefs->SetCharPref(aName, nsCString(aValue).get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirProperty::SetLocalizedStringValue(const char *aName,
|
||||
const nsACString &aValue)
|
||||
{
|
||||
if (!m_DirectoryPrefs && NS_FAILED(InitDirectoryPrefs()))
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefLocalizedString> locStr(
|
||||
do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = locStr->SetData(NS_ConvertUTF8toUTF16(aValue).get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return m_DirectoryPrefs->SetComplexValue(aName,
|
||||
NS_GET_IID(nsIPrefLocalizedString),
|
||||
locStr);
|
||||
}
|
||||
72
mailnews/addrbook/src/nsAbDirProperty.h
Normal file
72
mailnews/addrbook/src/nsAbDirProperty.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Address Book Directory
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsAbDirProperty_h__
|
||||
#define nsAbDirProperty_h__
|
||||
|
||||
#include "nsIAbDirectory.h" /* include the interface we are going to support */
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
/*
|
||||
* Address Book Directory
|
||||
*/
|
||||
|
||||
class nsAbDirProperty: public nsIAbDirectory,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsAbDirProperty(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABITEM
|
||||
NS_DECL_NSIABCOLLECTION
|
||||
NS_DECL_NSIABDIRECTORY
|
||||
|
||||
protected:
|
||||
virtual ~nsAbDirProperty(void);
|
||||
|
||||
/**
|
||||
* Initialise the directory prefs for this branch
|
||||
*/
|
||||
nsresult InitDirectoryPrefs();
|
||||
|
||||
uint32_t m_LastModifiedDate;
|
||||
|
||||
nsString m_ListDirName;
|
||||
nsString m_ListName;
|
||||
nsString m_ListNickName;
|
||||
nsString m_Description;
|
||||
bool m_IsMailList;
|
||||
|
||||
nsCString mURI;
|
||||
nsCString mQueryString;
|
||||
nsCString mURINoQuery;
|
||||
bool mIsValidURI;
|
||||
bool mIsQueryURI;
|
||||
|
||||
|
||||
/*
|
||||
* Note that any derived implementations should ensure that this item
|
||||
* (m_DirPrefId) is correctly initialised correctly
|
||||
*/
|
||||
nsCString m_DirPrefId; // ie,"ldap_2.servers.pab"
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> m_DirectoryPrefs;
|
||||
nsCOMPtr<nsIMutableArray> m_AddressList;
|
||||
};
|
||||
#endif
|
||||
528
mailnews/addrbook/src/nsAbDirectoryQuery.cpp
Normal file
528
mailnews/addrbook/src/nsAbDirectoryQuery.cpp
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbDirectoryQuery.h"
|
||||
#include "nsAbDirectoryQueryProxy.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsAbBooleanExpression.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIAbDirSearchListener.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirectoryQuerySimpleBooleanExpression, nsIAbBooleanExpression)
|
||||
|
||||
nsAbDirectoryQuerySimpleBooleanExpression::nsAbDirectoryQuerySimpleBooleanExpression() :
|
||||
mOperation (nsIAbBooleanOperationTypes::AND)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirectoryQuerySimpleBooleanExpression::~nsAbDirectoryQuerySimpleBooleanExpression()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute nsAbBooleanOperationType operation; */
|
||||
NS_IMETHODIMP nsAbDirectoryQuerySimpleBooleanExpression::GetOperation(nsAbBooleanOperationType *aOperation)
|
||||
{
|
||||
if (!aOperation)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aOperation = mOperation;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsAbDirectoryQuerySimpleBooleanExpression::SetOperation(nsAbBooleanOperationType aOperation)
|
||||
{
|
||||
if (aOperation != nsIAbBooleanOperationTypes::AND &&
|
||||
aOperation != nsIAbBooleanOperationTypes::OR)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mOperation = aOperation;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIArray expressions; */
|
||||
NS_IMETHODIMP nsAbDirectoryQuerySimpleBooleanExpression::GetExpressions(nsIArray **aExpressions)
|
||||
{
|
||||
if (!aExpressions)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (!mExpressions)
|
||||
{
|
||||
mExpressions = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (!mExpressions)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aExpressions = mExpressions);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQuerySimpleBooleanExpression::SetExpressions(nsIArray *aExpressions)
|
||||
{
|
||||
if (!aExpressions)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Ensure all the items are of the right type.
|
||||
nsresult rv;
|
||||
uint32_t count;
|
||||
rv = aExpressions->GetLength(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanConditionString> queryExpression;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
queryExpression = do_QueryElementAt(aExpressions, i, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// Values ok, so we can just save and return.
|
||||
mExpressions = aExpressions;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirectoryQueryArguments, nsIAbDirectoryQueryArguments)
|
||||
|
||||
nsAbDirectoryQueryArguments::nsAbDirectoryQueryArguments() :
|
||||
mQuerySubDirectories(true)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirectoryQueryArguments::~nsAbDirectoryQueryArguments()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute nsISupports matchItems; */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::GetExpression(nsISupports** aExpression)
|
||||
{
|
||||
if (!aExpression)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_IF_ADDREF(*aExpression = mExpression);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::SetExpression(nsISupports* aExpression)
|
||||
{
|
||||
mExpression = aExpression;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute boolean querySubDirectories; */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::GetQuerySubDirectories(bool* aQuerySubDirectories)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aQuerySubDirectories);
|
||||
*aQuerySubDirectories = mQuerySubDirectories;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::SetQuerySubDirectories(bool aQuerySubDirectories)
|
||||
{
|
||||
mQuerySubDirectories = aQuerySubDirectories;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::GetTypeSpecificArg(nsISupports** aArg)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aArg);
|
||||
|
||||
NS_IF_ADDREF(*aArg = mTypeSpecificArg);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::SetTypeSpecificArg(nsISupports* aArg)
|
||||
{
|
||||
mTypeSpecificArg = aArg;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::GetFilter(nsACString & aFilter)
|
||||
{
|
||||
aFilter.Assign(mFilter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQueryArguments::SetFilter(const nsACString & aFilter)
|
||||
{
|
||||
mFilter.Assign(aFilter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirectoryQueryPropertyValue, nsIAbDirectoryQueryPropertyValue)
|
||||
|
||||
nsAbDirectoryQueryPropertyValue::nsAbDirectoryQueryPropertyValue()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirectoryQueryPropertyValue::nsAbDirectoryQueryPropertyValue(const char* aName,
|
||||
const char16_t* aValue)
|
||||
{
|
||||
mName = aName;
|
||||
mValue = aValue;
|
||||
}
|
||||
|
||||
nsAbDirectoryQueryPropertyValue::nsAbDirectoryQueryPropertyValue(const char* aName,
|
||||
nsISupports* aValueISupports)
|
||||
{
|
||||
mName = aName;
|
||||
mValueISupports = aValueISupports;
|
||||
}
|
||||
|
||||
nsAbDirectoryQueryPropertyValue::~nsAbDirectoryQueryPropertyValue()
|
||||
{
|
||||
}
|
||||
|
||||
/* read only attribute string name; */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryPropertyValue::GetName(char* *aName)
|
||||
{
|
||||
*aName = mName.IsEmpty() ? 0 : ToNewCString(mName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* read only attribute wstring value; */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryPropertyValue::GetValue(char16_t* *aValue)
|
||||
{
|
||||
*aValue = ToNewUnicode(mValue);
|
||||
if (!(*aValue))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsISupports valueISupports; */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryPropertyValue::GetValueISupports(nsISupports* *aValueISupports)
|
||||
{
|
||||
if (!mValueISupports)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_IF_ADDREF(*aValueISupports = mValueISupports);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS(nsAbDirectoryQuery, nsIAbDirectoryQuery)
|
||||
|
||||
nsAbDirectoryQuery::nsAbDirectoryQuery()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirectoryQuery::~nsAbDirectoryQuery()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbDirectoryQuery::DoQuery(nsIAbDirectory *aDirectory,
|
||||
nsIAbDirectoryQueryArguments* arguments,
|
||||
nsIAbDirSearchListener* listener,
|
||||
int32_t resultLimit, int32_t timeOut,
|
||||
int32_t* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
|
||||
nsCOMPtr<nsISupports> supportsExpression;
|
||||
nsresult rv = arguments->GetExpression(getter_AddRefs(supportsExpression));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanExpression> expression(do_QueryInterface(supportsExpression, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool doSubDirectories;
|
||||
rv = arguments->GetQuerySubDirectories(&doSubDirectories);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = query(aDirectory, expression, listener, doSubDirectories, &resultLimit);
|
||||
|
||||
rv = NS_FAILED(rv) ? queryError(listener) : queryFinished(listener);
|
||||
|
||||
*_retval = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void stopQuery (in long contextID); */
|
||||
NS_IMETHODIMP nsAbDirectoryQuery::StopQuery(int32_t contextID)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsAbDirectoryQuery::query(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
bool doSubDirectories,
|
||||
int32_t* resultLimit)
|
||||
{
|
||||
if (*resultLimit == 0)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = queryCards(directory, expression, listener, resultLimit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (doSubDirectories && resultLimit != 0)
|
||||
{
|
||||
rv = queryChildren(directory, expression, listener, doSubDirectories,
|
||||
resultLimit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::queryChildren(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
bool doSubDirectories,
|
||||
int32_t* resultLimit)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> subDirectories;
|
||||
rv = directory->GetChildNodes(getter_AddRefs(subDirectories));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED(rv = subDirectories->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
nsCOMPtr<nsISupports> item;
|
||||
rv = subDirectories->GetNext (getter_AddRefs (item));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> subDirectory(do_QueryInterface(item, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = query(subDirectory, expression, listener, doSubDirectories, resultLimit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::queryCards(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
int32_t* resultLimit)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> cards;
|
||||
rv = directory->GetChildCards(getter_AddRefs(cards));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
if (rv != NS_ERROR_NOT_IMPLEMENTED)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!cards)
|
||||
return NS_OK;
|
||||
|
||||
bool more;
|
||||
while (NS_SUCCEEDED(cards->HasMoreElements(&more)) && more)
|
||||
{
|
||||
nsCOMPtr<nsISupports> item;
|
||||
rv = cards->GetNext(getter_AddRefs(item));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbCard> card(do_QueryInterface(item, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = matchCard (card, expression, listener, resultLimit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (*resultLimit == 0)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::matchCard(nsIAbCard* card,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
int32_t* resultLimit)
|
||||
{
|
||||
bool matchFound = false;
|
||||
nsresult rv = matchCardExpression(card, expression, &matchFound);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (matchFound)
|
||||
{
|
||||
(*resultLimit)--;
|
||||
rv = queryMatch(card, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::matchCardExpression(nsIAbCard* card,
|
||||
nsIAbBooleanExpression* expression,
|
||||
bool* result)
|
||||
{
|
||||
nsAbBooleanOperationType operation;
|
||||
nsresult rv = expression->GetOperation (&operation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIArray> childExpressions;
|
||||
rv = expression->GetExpressions (getter_AddRefs (childExpressions));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t count;
|
||||
rv = childExpressions->GetLength(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (operation == nsIAbBooleanOperationTypes::NOT &&
|
||||
count > 1)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
bool value = *result = false;
|
||||
nsCOMPtr<nsIAbBooleanConditionString> childCondition;
|
||||
nsCOMPtr<nsIAbBooleanExpression> childExpression;
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
childCondition = do_QueryElementAt(childExpressions, i, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = matchCardCondition (card, childCondition, &value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
childExpression = do_QueryElementAt(childExpressions, i, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = matchCardExpression (card, childExpression, &value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (operation == nsIAbBooleanOperationTypes::OR && value)
|
||||
break;
|
||||
else if (operation == nsIAbBooleanOperationTypes::AND && !value)
|
||||
break;
|
||||
else if (operation == nsIAbBooleanOperationTypes::NOT)
|
||||
value = !value;
|
||||
}
|
||||
*result = value;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::matchCardCondition(nsIAbCard* card,
|
||||
nsIAbBooleanConditionString* condition,
|
||||
bool* matchFound)
|
||||
{
|
||||
nsAbBooleanConditionType conditionType;
|
||||
nsresult rv = condition->GetCondition (&conditionType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString name;
|
||||
rv = condition->GetName (getter_Copies (name));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (name.Equals ("card:nsIAbCard"))
|
||||
{
|
||||
*matchFound = (conditionType == nsIAbBooleanConditionTypes::Exists);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString matchValue;
|
||||
rv = condition->GetValue (getter_Copies (matchValue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (name.EqualsLiteral("IsMailList"))
|
||||
{
|
||||
bool isMailList;
|
||||
rv = card->GetIsMailList(&isMailList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Only equals is supported.
|
||||
if (conditionType != nsIAbBooleanConditionTypes::Is)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*matchFound = isMailList ? matchValue.EqualsLiteral("TRUE") :
|
||||
matchValue.EqualsLiteral("FALSE");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString value;
|
||||
(void)card->GetPropertyAsAString(name.get(), value);
|
||||
|
||||
if (value.IsEmpty())
|
||||
{
|
||||
*matchFound = (conditionType == nsIAbBooleanConditionTypes::DoesNotExist) ?
|
||||
true : false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* What about allowing choice between case insensitive
|
||||
* and case sensitive comparisons?
|
||||
*
|
||||
*/
|
||||
switch (conditionType)
|
||||
{
|
||||
case nsIAbBooleanConditionTypes::Exists:
|
||||
*matchFound = true;
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::Contains:
|
||||
*matchFound = CaseInsensitiveFindInReadable(matchValue, value);
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::DoesNotContain:
|
||||
*matchFound = !CaseInsensitiveFindInReadable(matchValue, value);
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::Is:
|
||||
*matchFound = value.Equals(matchValue, nsCaseInsensitiveStringComparator());
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::IsNot:
|
||||
*matchFound = !value.Equals(matchValue, nsCaseInsensitiveStringComparator());
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::BeginsWith:
|
||||
*matchFound = StringBeginsWith(value, matchValue, nsCaseInsensitiveStringComparator());
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::LessThan:
|
||||
*matchFound = Compare(value, matchValue, nsCaseInsensitiveStringComparator()) < 0;
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::GreaterThan:
|
||||
*matchFound = Compare(value, matchValue, nsCaseInsensitiveStringComparator()) > 0;
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::EndsWith:
|
||||
*matchFound = StringEndsWith(value, matchValue, nsCaseInsensitiveStringComparator());
|
||||
break;
|
||||
case nsIAbBooleanConditionTypes::SoundsLike:
|
||||
case nsIAbBooleanConditionTypes::RegExp:
|
||||
*matchFound = false;
|
||||
break;
|
||||
default:
|
||||
*matchFound = false;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::queryMatch(nsIAbCard* card,
|
||||
nsIAbDirSearchListener* listener)
|
||||
{
|
||||
return listener->OnSearchFoundCard(card);
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::queryFinished(nsIAbDirSearchListener* listener)
|
||||
{
|
||||
return listener->OnSearchFinished(nsIAbDirectoryQueryResultListener::queryResultComplete, EmptyString());
|
||||
}
|
||||
|
||||
nsresult nsAbDirectoryQuery::queryError(nsIAbDirSearchListener* listener)
|
||||
{
|
||||
return listener->OnSearchFinished(nsIAbDirectoryQueryResultListener::queryResultError, EmptyString());
|
||||
}
|
||||
113
mailnews/addrbook/src/nsAbDirectoryQuery.h
Normal file
113
mailnews/addrbook/src/nsAbDirectoryQuery.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbDirectoryQuery_h__
|
||||
#define nsAbDirectoryQuery_h__
|
||||
|
||||
#include "nsIAbDirectoryQuery.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIAbBooleanExpression.h"
|
||||
|
||||
class nsAbDirectoryQuerySimpleBooleanExpression : public nsIAbBooleanExpression
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABBOOLEANEXPRESSION
|
||||
|
||||
nsAbDirectoryQuerySimpleBooleanExpression();
|
||||
|
||||
private:
|
||||
virtual ~nsAbDirectoryQuerySimpleBooleanExpression();
|
||||
|
||||
public:
|
||||
nsCOMPtr<nsIArray> mExpressions;
|
||||
nsAbBooleanOperationType mOperation;
|
||||
};
|
||||
|
||||
|
||||
class nsAbDirectoryQueryArguments : public nsIAbDirectoryQueryArguments
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABDIRECTORYQUERYARGUMENTS
|
||||
|
||||
nsAbDirectoryQueryArguments();
|
||||
|
||||
private:
|
||||
virtual ~nsAbDirectoryQueryArguments();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mExpression;
|
||||
nsCOMPtr<nsISupports> mTypeSpecificArg;
|
||||
bool mQuerySubDirectories;
|
||||
nsCString mFilter;
|
||||
};
|
||||
|
||||
|
||||
class nsAbDirectoryQueryPropertyValue : public nsIAbDirectoryQueryPropertyValue
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABDIRECTORYQUERYPROPERTYVALUE
|
||||
|
||||
nsAbDirectoryQueryPropertyValue();
|
||||
nsAbDirectoryQueryPropertyValue(const char* aName,
|
||||
const char16_t* aValue);
|
||||
nsAbDirectoryQueryPropertyValue(const char* aName,
|
||||
nsISupports* aValueISupports);
|
||||
|
||||
protected:
|
||||
virtual ~nsAbDirectoryQueryPropertyValue();
|
||||
nsCString mName;
|
||||
nsString mValue;
|
||||
nsCOMPtr<nsISupports> mValueISupports;
|
||||
};
|
||||
|
||||
|
||||
class nsAbDirectoryQuery : public nsIAbDirectoryQuery
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRECTORYQUERY
|
||||
|
||||
nsAbDirectoryQuery();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbDirectoryQuery();
|
||||
nsresult query(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
bool doSubDirectories,
|
||||
int32_t* resultLimit);
|
||||
nsresult queryChildren(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
bool doSubDirectories,
|
||||
int32_t* resultLimit);
|
||||
nsresult queryCards(nsIAbDirectory* directory,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
int32_t* resultLimit);
|
||||
nsresult matchCard(nsIAbCard* card,
|
||||
nsIAbBooleanExpression* expression,
|
||||
nsIAbDirSearchListener* listener,
|
||||
int32_t* resultLimit);
|
||||
nsresult matchCardExpression(nsIAbCard* card,
|
||||
nsIAbBooleanExpression* expression,
|
||||
bool* result);
|
||||
nsresult matchCardCondition(nsIAbCard* card,
|
||||
nsIAbBooleanConditionString* condition,
|
||||
bool* matchFound);
|
||||
|
||||
nsresult queryMatch (nsIAbCard* card,
|
||||
nsIAbDirSearchListener* listener);
|
||||
nsresult queryFinished(nsIAbDirSearchListener* listener);
|
||||
nsresult queryError(nsIAbDirSearchListener* listener);
|
||||
};
|
||||
|
||||
#endif
|
||||
33
mailnews/addrbook/src/nsAbDirectoryQueryProxy.cpp
Normal file
33
mailnews/addrbook/src/nsAbDirectoryQueryProxy.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbDirectoryQuery.h"
|
||||
#include "nsAbDirectoryQueryProxy.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbDirectoryQueryProxy, nsIAbDirectoryQueryProxy, nsIAbDirectoryQuery)
|
||||
|
||||
nsAbDirectoryQueryProxy::nsAbDirectoryQueryProxy() :
|
||||
mInitiated (false)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbDirectoryQueryProxy::~nsAbDirectoryQueryProxy()
|
||||
{
|
||||
}
|
||||
|
||||
/* void initiate (in nsIAbDirectory directory); */
|
||||
NS_IMETHODIMP nsAbDirectoryQueryProxy::Initiate()
|
||||
{
|
||||
if (mInitiated)
|
||||
return NS_OK;
|
||||
|
||||
mDirectoryQuery = new nsAbDirectoryQuery();
|
||||
|
||||
mInitiated = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
27
mailnews/addrbook/src/nsAbDirectoryQueryProxy.h
Normal file
27
mailnews/addrbook/src/nsAbDirectoryQueryProxy.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbDirectoryQueryProxy_h__
|
||||
#define nsAbDirectoryQueryProxy_h__
|
||||
|
||||
#include "nsIAbDirectoryQueryProxy.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsAbDirectoryQueryProxy : public nsIAbDirectoryQueryProxy
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIABDIRECTORYQUERY(mDirectoryQuery->)
|
||||
NS_DECL_NSIABDIRECTORYQUERYPROXY
|
||||
|
||||
nsAbDirectoryQueryProxy();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbDirectoryQueryProxy();
|
||||
bool mInitiated;
|
||||
nsCOMPtr<nsIAbDirectoryQuery> mDirectoryQuery;
|
||||
};
|
||||
|
||||
#endif
|
||||
247
mailnews/addrbook/src/nsAbLDAPAttributeMap.js
Normal file
247
mailnews/addrbook/src/nsAbLDAPAttributeMap.js
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var NS_ABLDAPATTRIBUTEMAP_CID = Components.ID(
|
||||
"{127b341a-bdda-4270-85e1-edff569a9b85}");
|
||||
var NS_ABLDAPATTRIBUTEMAPSERVICE_CID = Components.ID(
|
||||
"{4ed7d5e1-8800-40da-9e78-c4f509d7ac5e}");
|
||||
|
||||
function nsAbLDAPAttributeMap() {
|
||||
this.mPropertyMap = {};
|
||||
this.mAttrMap = {};
|
||||
}
|
||||
|
||||
nsAbLDAPAttributeMap.prototype = {
|
||||
classID: NS_ABLDAPATTRIBUTEMAP_CID,
|
||||
|
||||
getAttributeList: function getAttributeList(aProperty) {
|
||||
|
||||
if (!(aProperty in this.mPropertyMap)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// return the joined list
|
||||
return this.mPropertyMap[aProperty].join(",");
|
||||
},
|
||||
|
||||
getAttributes: function getAttributes(aProperty, aCount, aAttrs) {
|
||||
|
||||
// fail if no entry for this
|
||||
if (!(aProperty in this.mPropertyMap)) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aAttrs = this.mPropertyMap[aProperty];
|
||||
aCount = aAttrs.length;
|
||||
return aAttrs;
|
||||
},
|
||||
|
||||
getFirstAttribute: function getFirstAttribute(aProperty) {
|
||||
|
||||
// fail if no entry for this
|
||||
if (!(aProperty in this.mPropertyMap)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.mPropertyMap[aProperty][0];
|
||||
},
|
||||
|
||||
setAttributeList: function setAttributeList(aProperty, aAttributeList,
|
||||
aAllowInconsistencies) {
|
||||
|
||||
var attrs = aAttributeList.split(",");
|
||||
|
||||
// check to make sure this call won't allow multiple mappings to be
|
||||
// created, if requested
|
||||
if (!aAllowInconsistencies) {
|
||||
for (var attr of attrs) {
|
||||
if (attr in this.mAttrMap && this.mAttrMap[attr] != aProperty) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete any attr mappings created by the existing property map entry
|
||||
if (aProperty in this.mPropertyMap) {
|
||||
for (attr of this.mPropertyMap[aProperty]) {
|
||||
delete this.mAttrMap[attr];
|
||||
}
|
||||
}
|
||||
|
||||
// add these attrs to the attrmap
|
||||
for (attr of attrs) {
|
||||
this.mAttrMap[attr] = aProperty;
|
||||
}
|
||||
|
||||
// add them to the property map
|
||||
this.mPropertyMap[aProperty] = attrs;
|
||||
},
|
||||
|
||||
getProperty: function getProperty(aAttribute) {
|
||||
|
||||
if (!(aAttribute in this.mAttrMap)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.mAttrMap[aAttribute];
|
||||
},
|
||||
|
||||
getAllCardAttributes: function getAllCardAttributes() {
|
||||
var attrs = [];
|
||||
for (var prop in this.mPropertyMap) {
|
||||
let attrArray = this.mPropertyMap[prop];
|
||||
attrs = attrs.concat(attrArray);
|
||||
}
|
||||
|
||||
if (!attrs.length) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return attrs.join(",");
|
||||
},
|
||||
|
||||
getAllCardProperties: function getAllCardProperties(aCount) {
|
||||
|
||||
var props = [];
|
||||
for (var prop in this.mPropertyMap) {
|
||||
props.push(prop);
|
||||
}
|
||||
|
||||
aCount.value = props.length;
|
||||
return props;
|
||||
},
|
||||
|
||||
setFromPrefs: function setFromPrefs(aPrefBranchName) {
|
||||
// get the right pref branch
|
||||
let branch = Services.prefs.getBranch(aPrefBranchName + ".");
|
||||
|
||||
// get the list of children
|
||||
var childCount = {};
|
||||
var children = branch.getChildList("", childCount);
|
||||
|
||||
// do the actual sets
|
||||
for (var child of children) {
|
||||
this.setAttributeList(child, branch.getCharPref(child), true);
|
||||
}
|
||||
|
||||
// ensure that everything is kosher
|
||||
this.checkState();
|
||||
},
|
||||
|
||||
setCardPropertiesFromLDAPMessage: function
|
||||
setCardPropertiesFromLDAPMessage(aMessage, aCard) {
|
||||
|
||||
var cardValueWasSet = false;
|
||||
|
||||
var msgAttrCount = {};
|
||||
var msgAttrs = aMessage.getAttributes(msgAttrCount);
|
||||
|
||||
// downcase the array for comparison
|
||||
function toLower(a) { return a.toLowerCase(); }
|
||||
msgAttrs = msgAttrs.map(toLower);
|
||||
|
||||
// deal with each addressbook property
|
||||
for (var prop in this.mPropertyMap) {
|
||||
|
||||
// go through the list of possible attrs in precedence order
|
||||
for (var attr of this.mPropertyMap[prop]) {
|
||||
|
||||
attr = attr.toLowerCase();
|
||||
|
||||
// find the first attr that exists in this message
|
||||
if (msgAttrs.indexOf(attr) != -1) {
|
||||
|
||||
try {
|
||||
var values = aMessage.getValues(attr, {});
|
||||
// strip out the optional label from the labeledURI
|
||||
if (attr == "labeleduri" && values[0]) {
|
||||
var index = values[0].indexOf(" ");
|
||||
if (index != -1)
|
||||
values[0] = values[0].substring(0, index);
|
||||
}
|
||||
aCard.setProperty(prop, values[0]);
|
||||
|
||||
cardValueWasSet = true;
|
||||
break;
|
||||
} catch (ex) {
|
||||
// ignore any errors getting message values or setting card values
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cardValueWasSet) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
checkState: function checkState() {
|
||||
|
||||
var attrsSeen = [];
|
||||
|
||||
for (var prop in this.mPropertyMap) {
|
||||
let attrArray = this.mPropertyMap[prop];
|
||||
for (var attr of attrArray) {
|
||||
|
||||
// multiple attributes that mapped to the empty string are permitted
|
||||
if (!attr.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we've seen this before, there's a problem
|
||||
if (attrsSeen.indexOf(attr) != -1) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// remember that we've seen it now
|
||||
attrsSeen.push(attr);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils
|
||||
.generateQI([Components.interfaces.nsIAbLDAPAttributeMap])
|
||||
}
|
||||
|
||||
function nsAbLDAPAttributeMapService() {
|
||||
}
|
||||
|
||||
nsAbLDAPAttributeMapService.prototype = {
|
||||
|
||||
classID: NS_ABLDAPATTRIBUTEMAPSERVICE_CID,
|
||||
|
||||
mAttrMaps: {},
|
||||
|
||||
getMapForPrefBranch: function getMapForPrefBranch(aPrefBranchName) {
|
||||
|
||||
// if we've already got this map, return it
|
||||
if (aPrefBranchName in this.mAttrMaps) {
|
||||
return this.mAttrMaps[aPrefBranchName];
|
||||
}
|
||||
|
||||
// otherwise, try and create it
|
||||
var attrMap = new nsAbLDAPAttributeMap();
|
||||
attrMap.setFromPrefs("ldap_2.servers.default.attrmap");
|
||||
attrMap.setFromPrefs(aPrefBranchName + ".attrmap");
|
||||
|
||||
// cache
|
||||
this.mAttrMaps[aPrefBranchName] = attrMap;
|
||||
|
||||
// and return
|
||||
return attrMap;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils
|
||||
.generateQI([Components.interfaces.nsIAbLDAPAttributeMapService])
|
||||
}
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsAbLDAPAttributeMap, nsAbLDAPAttributeMapService]);
|
||||
|
||||
325
mailnews/addrbook/src/nsAbLDAPAutoCompleteSearch.js
Normal file
325
mailnews/addrbook/src/nsAbLDAPAutoCompleteSearch.js
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var ACR = Components.interfaces.nsIAutoCompleteResult;
|
||||
var nsIAbAutoCompleteResult = Components.interfaces.nsIAbAutoCompleteResult;
|
||||
var nsIAbDirectoryQueryResultListener =
|
||||
Components.interfaces.nsIAbDirectoryQueryResultListener;
|
||||
|
||||
// nsAbLDAPAutoCompleteResult
|
||||
// Derived from nsIAbAutoCompleteResult, provides a LDAP specific result
|
||||
// implementation.
|
||||
|
||||
function nsAbLDAPAutoCompleteResult(aSearchString) {
|
||||
// Can't create this in the prototype as we'd get the same array for
|
||||
// all instances
|
||||
this._searchResults = [];
|
||||
this.searchString = aSearchString;
|
||||
}
|
||||
|
||||
nsAbLDAPAutoCompleteResult.prototype = {
|
||||
_searchResults: null,
|
||||
_commentColumn: "",
|
||||
|
||||
// nsIAutoCompleteResult
|
||||
|
||||
searchString: null,
|
||||
searchResult: ACR.RESULT_NOMATCH,
|
||||
defaultIndex: -1,
|
||||
errorDescription: null,
|
||||
|
||||
get matchCount() {
|
||||
return this._searchResults.length;
|
||||
},
|
||||
|
||||
getLabelAt: function getLabelAt(aIndex) {
|
||||
return this.getValueAt(aIndex);
|
||||
},
|
||||
|
||||
getValueAt: function getValueAt(aIndex) {
|
||||
return this._searchResults[aIndex].value;
|
||||
},
|
||||
|
||||
getCommentAt: function getCommentAt(aIndex) {
|
||||
return this._commentColumn;
|
||||
},
|
||||
|
||||
getStyleAt: function getStyleAt(aIndex) {
|
||||
return this.searchResult == ACR.RESULT_FAILURE ? "remote-err" :
|
||||
"remote-abook";
|
||||
},
|
||||
|
||||
getImageAt: function getImageAt(aIndex) {
|
||||
return "";
|
||||
},
|
||||
|
||||
getFinalCompleteValueAt: function(aIndex) {
|
||||
return this.getValueAt(aIndex);
|
||||
},
|
||||
|
||||
removeValueAt: function removeValueAt(aRowIndex, aRemoveFromDB) {
|
||||
},
|
||||
|
||||
// nsIAbAutoCompleteResult
|
||||
|
||||
getCardAt: function getCardAt(aIndex) {
|
||||
return this._searchResults[aIndex].card;
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([ACR, nsIAbAutoCompleteResult])
|
||||
}
|
||||
|
||||
function nsAbLDAPAutoCompleteSearch() {
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
this._timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
}
|
||||
|
||||
nsAbLDAPAutoCompleteSearch.prototype = {
|
||||
// For component registration
|
||||
classID: Components.ID("227e6482-fe9f-441f-9b7d-7b60375e7449"),
|
||||
|
||||
// A short-lived LDAP directory cache.
|
||||
// To avoid recreating components as the user completes, we maintain the most
|
||||
// recently used address book, nsAbLDAPDirectoryQuery and search context.
|
||||
// However the cache is discarded if it has not been used for a minute.
|
||||
// This is done to avoid problems with LDAP sessions timing out and hanging.
|
||||
_query: null,
|
||||
_book: null,
|
||||
_attributes: null,
|
||||
_context: -1,
|
||||
_timer: null,
|
||||
|
||||
// The current search result.
|
||||
_result: null,
|
||||
// The listener to pass back results to.
|
||||
_listener: null,
|
||||
|
||||
_parser: MailServices.headerParser,
|
||||
|
||||
applicableHeaders: new Set(["addr_to", "addr_cc", "addr_bcc", "addr_reply"]),
|
||||
|
||||
// Private methods
|
||||
|
||||
_checkDuplicate: function _checkDuplicate(card, emailAddress) {
|
||||
var lcEmailAddress = emailAddress.toLocaleLowerCase();
|
||||
|
||||
return this._result._searchResults.some(function(result) {
|
||||
return result.value.toLocaleLowerCase() == lcEmailAddress;
|
||||
});
|
||||
},
|
||||
|
||||
_addToResult: function(card) {
|
||||
let mbox = this._parser.makeMailboxObject(card.displayName,
|
||||
card.isMailList ? card.getProperty("Notes", "") || card.displayName :
|
||||
card.primaryEmail);
|
||||
if (!mbox.email)
|
||||
return;
|
||||
|
||||
let emailAddress = mbox.toString();
|
||||
|
||||
// If it is a duplicate, then just return and don't add it. The
|
||||
// _checkDuplicate function deals with it all for us.
|
||||
if (this._checkDuplicate(card, emailAddress))
|
||||
return;
|
||||
|
||||
// Find out where to insert the card.
|
||||
var insertPosition = 0;
|
||||
|
||||
// Next sort on full address
|
||||
while (insertPosition < this._result._searchResults.length &&
|
||||
emailAddress > this._result._searchResults[insertPosition].value)
|
||||
++insertPosition;
|
||||
|
||||
this._result._searchResults.splice(insertPosition, 0, {
|
||||
value: emailAddress,
|
||||
card: card,
|
||||
});
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function observer(subject, topic, data) {
|
||||
if (topic == "quit-application") {
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
} else if (topic != "timer-callback") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Force the individual query items to null, so that the memory
|
||||
// gets collected straight away.
|
||||
this.stopSearch();
|
||||
this._book = null;
|
||||
this._context = -1;
|
||||
this._query = null;
|
||||
this._attributes = null;
|
||||
},
|
||||
|
||||
// nsIAutoCompleteSearch
|
||||
|
||||
startSearch: function startSearch(aSearchString, aParam,
|
||||
aPreviousResult, aListener) {
|
||||
let params = JSON.parse(aParam) || {};
|
||||
let applicable = !("type" in params) || this.applicableHeaders.has(params.type);
|
||||
|
||||
this._result = new nsAbLDAPAutoCompleteResult(aSearchString);
|
||||
aSearchString = aSearchString.toLocaleLowerCase();
|
||||
|
||||
// If the search string isn't value, or contains a comma, or the user
|
||||
// hasn't enabled autocomplete, then just return no matches / or the
|
||||
// result ignored.
|
||||
// The comma check is so that we don't autocomplete against the user
|
||||
// entering multiple addresses.
|
||||
if (!applicable || !aSearchString || aSearchString.includes(",")) {
|
||||
this._result.searchResult = ACR.RESULT_IGNORED;
|
||||
aListener.onSearchResult(this, this._result);
|
||||
return;
|
||||
}
|
||||
|
||||
// The rules here: If the current identity has a directoryServer set, then
|
||||
// use that, otherwise, try the global preference instead.
|
||||
var acDirURI = null;
|
||||
var identity;
|
||||
|
||||
if ("idKey" in params) {
|
||||
try {
|
||||
identity = MailServices.accounts.getIdentity(params.idKey);
|
||||
}
|
||||
catch(ex) {
|
||||
Components.utils.reportError("Couldn't get specified identity, " +
|
||||
"falling back to global settings");
|
||||
}
|
||||
}
|
||||
|
||||
// Does the current identity override the global preference?
|
||||
if (identity && identity.overrideGlobalPref)
|
||||
acDirURI = identity.directoryServer;
|
||||
else {
|
||||
// Try the global one
|
||||
if (Services.prefs.getBoolPref("ldap_2.autoComplete.useDirectory"))
|
||||
acDirURI = Services.prefs.getCharPref("ldap_2.autoComplete.directoryServer");
|
||||
}
|
||||
|
||||
if (!acDirURI) {
|
||||
// No directory to search, send a no match and return.
|
||||
aListener.onSearchResult(this, this._result);
|
||||
return;
|
||||
}
|
||||
|
||||
this.stopSearch();
|
||||
|
||||
// If we don't already have a cached query for this URI, build a new one.
|
||||
acDirURI = "moz-abldapdirectory://" + acDirURI;
|
||||
if (!this._book || this._book.URI != acDirURI) {
|
||||
this._query =
|
||||
Components.classes["@mozilla.org/addressbook/ldap-directory-query;1"]
|
||||
.createInstance(Components.interfaces.nsIAbDirectoryQuery);
|
||||
this._book = MailServices.ab.getDirectory(acDirURI)
|
||||
.QueryInterface(Components.interfaces.nsIAbLDAPDirectory);
|
||||
|
||||
// Create a minimal map just for the display name and primary email.
|
||||
this._attributes =
|
||||
Components.classes["@mozilla.org/addressbook/ldap-attribute-map;1"]
|
||||
.createInstance(Components.interfaces.nsIAbLDAPAttributeMap);
|
||||
this._attributes.setAttributeList("DisplayName",
|
||||
this._book.attributeMap.getAttributeList("DisplayName", {}), true);
|
||||
this._attributes.setAttributeList("PrimaryEmail",
|
||||
this._book.attributeMap.getAttributeList("PrimaryEmail", {}), true);
|
||||
}
|
||||
|
||||
this._result._commentColumn = this._book.dirName;
|
||||
this._listener = aListener;
|
||||
this._timer.init(this, 60000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
var args =
|
||||
Components.classes["@mozilla.org/addressbook/directory/query-arguments;1"]
|
||||
.createInstance(Components.interfaces.nsIAbDirectoryQueryArguments);
|
||||
|
||||
var filterTemplate = this._book.getStringValue("autoComplete.filterTemplate", "");
|
||||
|
||||
// Use default value when preference is not set or it contains empty string
|
||||
if (!filterTemplate)
|
||||
filterTemplate = "(|(cn=%v1*%v2-*)(mail=%v1*%v2-*)(sn=%v1*%v2-*))";
|
||||
|
||||
// Create filter from filter template and search string
|
||||
var ldapSvc = Components.classes["@mozilla.org/network/ldap-service;1"]
|
||||
.getService(Components.interfaces.nsILDAPService);
|
||||
var filter = ldapSvc.createFilter(1024, filterTemplate, "", "", "", aSearchString);
|
||||
if (!filter)
|
||||
throw new Error("Filter string is empty, check if filterTemplate variable is valid in prefs.js.");
|
||||
args.typeSpecificArg = this._attributes;
|
||||
args.querySubDirectories = true;
|
||||
args.filter = filter;
|
||||
|
||||
// Start the actual search
|
||||
this._context =
|
||||
this._query.doQuery(this._book, args, this, this._book.maxHits, 0);
|
||||
},
|
||||
|
||||
stopSearch: function stopSearch() {
|
||||
if (this._listener) {
|
||||
this._query.stopQuery(this._context);
|
||||
this._listener = null;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIAbDirSearchListener
|
||||
|
||||
onSearchFinished: function onSearchFinished(aResult, aErrorMsg) {
|
||||
if (!this._listener)
|
||||
return;
|
||||
|
||||
if (aResult == nsIAbDirectoryQueryResultListener.queryResultComplete) {
|
||||
if (this._result.matchCount) {
|
||||
this._result.searchResult = ACR.RESULT_SUCCESS;
|
||||
this._result.defaultIndex = 0;
|
||||
}
|
||||
else
|
||||
this._result.searchResult = ACR.RESULT_NOMATCH;
|
||||
}
|
||||
else if (aResult == nsIAbDirectoryQueryResultListener.queryResultError) {
|
||||
this._result.searchResult = ACR.RESULT_FAILURE;
|
||||
this._result.defaultIndex = 0;
|
||||
}
|
||||
// const long queryResultStopped = 2;
|
||||
// const long queryResultError = 3;
|
||||
this._listener.onSearchResult(this, this._result);
|
||||
this._listener = null;
|
||||
},
|
||||
|
||||
onSearchFoundCard: function onSearchFoundCard(aCard) {
|
||||
if (!this._listener)
|
||||
return;
|
||||
|
||||
this._addToResult(aCard);
|
||||
|
||||
/* XXX autocomplete doesn't expect you to rearrange while searching
|
||||
if (this._result.matchCount)
|
||||
this._result.searchResult = ACR.RESULT_SUCCESS_ONGOING;
|
||||
else
|
||||
this._result.searchResult = ACR.RESULT_NOMATCH_ONGOING;
|
||||
|
||||
this._listener.onSearchResult(this, this._result);
|
||||
*/
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver,
|
||||
Components.interfaces
|
||||
.nsIAutoCompleteSearch,
|
||||
Components.interfaces
|
||||
.nsIAbDirSearchListener])
|
||||
};
|
||||
|
||||
// Module
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([nsAbLDAPAutoCompleteSearch]);
|
||||
297
mailnews/addrbook/src/nsAbLDAPCard.cpp
Normal file
297
mailnews/addrbook/src/nsAbLDAPCard.cpp
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPCard.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPModification.h"
|
||||
#include "nsILDAPBERValue.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsIAbLDAPAttributeMap.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define kDNColumn "DN"
|
||||
|
||||
nsAbLDAPCard::nsAbLDAPCard()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPCard::~nsAbLDAPCard()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAbLDAPCard, nsAbCardProperty, nsIAbLDAPCard)
|
||||
|
||||
/* Retrieves the changes to the LDAP card and stores them in an LDAP
|
||||
* update message.
|
||||
*
|
||||
* Calling this method changes the LDAP card, it updates the
|
||||
* meta-properties (m_*) to reflect what the LDAP contents will be once
|
||||
* the update has been performed. This allows you to do multiple (successful)
|
||||
* consecutive edits on a card in a search result. If the meta-properties
|
||||
* were not updated, incorrect assuptions would be made about what object
|
||||
* classes to add, or what attributes to clear.
|
||||
*
|
||||
* XXX: We need to take care when integrating this code with the asynchronous
|
||||
* update dialogs, as the current code in nsAbLDAPDirectory has a problem
|
||||
* when an update fails: the modified card still gets stored and shown to
|
||||
* the user instead of being discarded. There is one especially tricky case:
|
||||
* when you do an update on a card which changes its DN, you have two
|
||||
* operations (rename, then update the other attributes). If the rename
|
||||
* operation succeeds and not the update of the attributes, you are
|
||||
* "somewhere in between" the original card and the updated card.
|
||||
*/
|
||||
NS_IMETHODIMP nsAbLDAPCard::GetLDAPMessageInfo(
|
||||
nsIAbLDAPAttributeMap *aAttributeMap,
|
||||
const uint32_t aClassCount,
|
||||
const char **aClasses,
|
||||
int32_t aType,
|
||||
nsIArray **aLDAPAddMessageInfo)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributeMap);
|
||||
NS_ENSURE_ARG_POINTER(aClasses);
|
||||
NS_ENSURE_ARG_POINTER(aLDAPAddMessageInfo);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> modArray =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add any missing object classes. We never remove any object
|
||||
// classes: if an entry has additional object classes, it's probably
|
||||
// for a good reason.
|
||||
nsAutoCString oclass;
|
||||
for (uint32_t i = 0; i < aClassCount; ++i)
|
||||
{
|
||||
oclass.Assign(nsDependentCString(aClasses[i]));
|
||||
ToLowerCase(oclass);
|
||||
|
||||
if (!m_objectClass.Contains(oclass))
|
||||
{
|
||||
m_objectClass.AppendElement(oclass);
|
||||
printf("LDAP : adding objectClass %s\n", oclass.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILDAPModification> mod =
|
||||
do_CreateInstance("@mozilla.org/network/ldap-modification;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> values =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < m_objectClass.Length(); ++i)
|
||||
{
|
||||
nsCOMPtr<nsILDAPBERValue> value =
|
||||
do_CreateInstance("@mozilla.org/network/ldap-ber-value;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = value->SetFromUTF8(m_objectClass.ElementAt(i));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = values->AppendElement(value, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = mod->SetUpModification(aType, NS_LITERAL_CSTRING("objectClass"), values);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
modArray->AppendElement(mod, false);
|
||||
|
||||
// Add card properties
|
||||
CharPtrArrayGuard props;
|
||||
rv = aAttributeMap->GetAllCardProperties(props.GetSizeAddr(),
|
||||
props.GetArrayAddr());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString attr;
|
||||
nsCString propvalue;
|
||||
for (uint32_t i = 0; i < props.GetSize(); ++i)
|
||||
{
|
||||
// Skip some attributes that don't map to LDAP.
|
||||
//
|
||||
// BirthYear : by default this is mapped to 'birthyear',
|
||||
// which is not part of mozillaAbPersonAlpha
|
||||
//
|
||||
// LastModifiedDate : by default this is mapped to 'modifytimestamp',
|
||||
// which cannot be modified
|
||||
//
|
||||
// PreferMailFormat : by default this is mapped to 'mozillaUseHtmlMail',
|
||||
// which is a boolean, not plaintext/html/unknown
|
||||
if (!strcmp(props[i], kBirthYearProperty) ||
|
||||
!strcmp(props[i], kLastModifiedDateProperty) ||
|
||||
!strcmp(props[i], kPreferMailFormatProperty))
|
||||
continue;
|
||||
|
||||
rv = aAttributeMap->GetFirstAttribute(nsDependentCString(props[i]),
|
||||
attr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
ToLowerCase(attr);
|
||||
|
||||
// If the property is not mapped to an attribute, skip it.
|
||||
if (attr.IsEmpty())
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsILDAPModification> mod =
|
||||
do_CreateInstance("@mozilla.org/network/ldap-modification;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
size_t index = m_attributes.IndexOf(attr);
|
||||
|
||||
rv = GetPropertyAsAUTF8String(props[i], propvalue);
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&!propvalue.IsEmpty())
|
||||
{
|
||||
// If the new value is not empty, add/update it
|
||||
nsCOMPtr<nsILDAPBERValue> value =
|
||||
do_CreateInstance("@mozilla.org/network/ldap-ber-value;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = value->SetFromUTF8(propvalue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mod->SetUpModificationOneValue(aType, attr, value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf("LDAP : setting attribute %s (%s) to '%s'\n", attr.get(),
|
||||
props[i], propvalue.get());
|
||||
modArray->AppendElement(mod, false);
|
||||
if (index != m_attributes.NoIndex)
|
||||
m_attributes.AppendElement(attr);
|
||||
|
||||
}
|
||||
else if (aType == nsILDAPModification::MOD_REPLACE &&
|
||||
index != m_attributes.NoIndex)
|
||||
{
|
||||
// If the new value is empty, we are performing an update
|
||||
// and the attribute was previously set, clear it
|
||||
nsCOMPtr<nsIMutableArray> novalues =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mod->SetUpModification(aType, attr, novalues);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf("LDAP : removing attribute %s (%s)\n", attr.get(), props[i]);
|
||||
modArray->AppendElement(mod, false);
|
||||
m_attributes.RemoveElementAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aLDAPAddMessageInfo = modArray);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPCard::BuildRdn(nsIAbLDAPAttributeMap *aAttributeMap,
|
||||
const uint32_t aAttrCount,
|
||||
const char **aAttributes,
|
||||
nsACString &aRdn)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributeMap);
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
|
||||
nsresult rv;
|
||||
nsCString attr;
|
||||
nsAutoCString prop;
|
||||
nsCString propvalue;
|
||||
|
||||
aRdn.Truncate();
|
||||
for (uint32_t i = 0; i < aAttrCount; ++i)
|
||||
{
|
||||
attr.Assign(nsDependentCString(aAttributes[i]));
|
||||
|
||||
// Lookup the property corresponding to the attribute
|
||||
rv = aAttributeMap->GetProperty(attr, prop);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the property value
|
||||
rv = GetPropertyAsAUTF8String(prop.get(), propvalue);
|
||||
|
||||
// XXX The case where an attribute needed to build the Relative
|
||||
// Distinguished Name is not set needs to be handled by the caller,
|
||||
// so as to let the user know what is missing.
|
||||
if (NS_FAILED(rv) || propvalue.IsEmpty())
|
||||
{
|
||||
NS_ERROR("nsAbLDAPCard::BuildRdn: a required attribute is not set");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
aRdn.Append(attr);
|
||||
aRdn.AppendLiteral("=");
|
||||
aRdn.Append(propvalue);
|
||||
if (i < aAttrCount - 1)
|
||||
aRdn.AppendLiteral("+");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPCard::GetDn(nsACString &aDN)
|
||||
{
|
||||
return GetPropertyAsAUTF8String(kDNColumn, aDN);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPCard::SetDn(const nsACString &aDN)
|
||||
{
|
||||
SetLocalId(aDN);
|
||||
return SetPropertyAsAUTF8String(kDNColumn, aDN);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPCard::SetMetaProperties(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
|
||||
// Get DN
|
||||
nsAutoCString dn;
|
||||
nsresult rv = aMessage->GetDn(dn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
SetDn(dn);
|
||||
|
||||
// Get the list of set attributes
|
||||
CharPtrArrayGuard attrs;
|
||||
rv = aMessage->GetAttributes(attrs.GetSizeAddr(), attrs.GetArrayAddr());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString attr;
|
||||
m_attributes.Clear();
|
||||
for (uint32_t i = 0; i < attrs.GetSize(); ++i)
|
||||
{
|
||||
attr.Assign(nsDependentCString(attrs[i]));
|
||||
ToLowerCase(attr);
|
||||
m_attributes.AppendElement(attr);
|
||||
}
|
||||
|
||||
// Get the objectClass values
|
||||
m_objectClass.Clear();
|
||||
PRUnicharPtrArrayGuard vals;
|
||||
rv = aMessage->GetValues("objectClass", vals.GetSizeAddr(),
|
||||
vals.GetArrayAddr());
|
||||
|
||||
// objectClass is not always included in search result entries and
|
||||
// nsILDAPMessage::GetValues returns NS_ERROR_LDAP_DECODING_ERROR if the
|
||||
// requested attribute doesn't exist.
|
||||
if (rv == NS_ERROR_LDAP_DECODING_ERROR)
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString oclass;
|
||||
for (uint32_t i = 0; i < vals.GetSize(); ++i)
|
||||
{
|
||||
oclass.Assign(NS_LossyConvertUTF16toASCII(nsDependentString(vals[i])));
|
||||
ToLowerCase(oclass);
|
||||
m_objectClass.AppendElement(oclass);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
30
mailnews/addrbook/src/nsAbLDAPCard.h
Normal file
30
mailnews/addrbook/src/nsAbLDAPCard.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPCard_h__
|
||||
#define nsAbLDAPCard_h__
|
||||
|
||||
#include "nsAbCardProperty.h"
|
||||
#include "nsIAbLDAPCard.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIMutableArray;
|
||||
|
||||
class nsAbLDAPCard : public nsAbCardProperty,
|
||||
public nsIAbLDAPCard
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIABLDAPCARD
|
||||
|
||||
nsAbLDAPCard();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbLDAPCard();
|
||||
nsTArray<nsCString> m_attributes;
|
||||
nsTArray<nsCString> m_objectClass;
|
||||
};
|
||||
|
||||
#endif
|
||||
542
mailnews/addrbook/src/nsAbLDAPChangeLogData.cpp
Normal file
542
mailnews/addrbook/src/nsAbLDAPChangeLogData.cpp
Normal file
|
|
@ -0,0 +1,542 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPChangeLogData.h"
|
||||
#include "nsAbLDAPChangeLogQuery.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsIAddrBookSession.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsAbMDBCard.h"
|
||||
#include "nsAbLDAPCard.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "plstr.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "prmem.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
// Defined here since to be used
|
||||
// only locally to this file.
|
||||
enum UpdateOp {
|
||||
NO_OP,
|
||||
ENTRY_ADD,
|
||||
ENTRY_DELETE,
|
||||
ENTRY_MODIFY
|
||||
};
|
||||
|
||||
nsAbLDAPProcessChangeLogData::nsAbLDAPProcessChangeLogData()
|
||||
: mUseChangeLog(false),
|
||||
mChangeLogEntriesCount(0),
|
||||
mEntriesAddedQueryCount(0)
|
||||
{
|
||||
mRootDSEEntry.firstChangeNumber = 0;
|
||||
mRootDSEEntry.lastChangeNumber = 0;
|
||||
}
|
||||
|
||||
nsAbLDAPProcessChangeLogData::~nsAbLDAPProcessChangeLogData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessChangeLogData::Init(nsIAbLDAPReplicationQuery * query, nsIWebProgressListener *progressListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(query);
|
||||
|
||||
// Here we are assuming that the caller will pass a nsAbLDAPChangeLogQuery object,
|
||||
// an implementation derived from the implementation of nsIAbLDAPReplicationQuery.
|
||||
nsresult rv = NS_OK;
|
||||
mChangeLogQuery = do_QueryInterface(query, &rv);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Call the parent's Init now.
|
||||
return nsAbLDAPProcessReplicationData::Init(query, progressListener);
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnLDAPBind(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
int32_t errCode;
|
||||
|
||||
nsresult rv = aMessage->GetErrorCode(&errCode);
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(errCode != nsILDAPErrors::SUCCESS) {
|
||||
Done(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
switch(mState) {
|
||||
case kAnonymousBinding :
|
||||
rv = GetAuthData();
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = mChangeLogQuery->QueryAuthDN(mAuthUserID);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
mState = kSearchingAuthDN;
|
||||
break;
|
||||
case kAuthenticatedBinding :
|
||||
rv = mChangeLogQuery->QueryRootDSE();
|
||||
if(NS_SUCCEEDED(rv))
|
||||
mState = kSearchingRootDSE;
|
||||
break;
|
||||
} //end of switch
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
Abort();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
switch(mState)
|
||||
{
|
||||
case kSearchingAuthDN :
|
||||
{
|
||||
nsAutoCString authDN;
|
||||
rv = aMessage->GetDn(authDN);
|
||||
if(NS_SUCCEEDED(rv) && !authDN.IsEmpty())
|
||||
mAuthDN = authDN.get();
|
||||
}
|
||||
break;
|
||||
case kSearchingRootDSE:
|
||||
rv = ParseRootDSEEntry(aMessage);
|
||||
break;
|
||||
case kFindingChanges:
|
||||
rv = ParseChangeLogEntries(aMessage);
|
||||
break;
|
||||
// Fall through since we only add (for updates we delete and add)
|
||||
case kReplicatingChanges:
|
||||
case kReplicatingAll :
|
||||
return nsAbLDAPProcessReplicationData::OnLDAPSearchEntry(aMessage);
|
||||
}
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
Abort();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnLDAPSearchResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
int32_t errorCode;
|
||||
|
||||
nsresult rv = aMessage->GetErrorCode(&errorCode);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
if(errorCode == nsILDAPErrors::SUCCESS || errorCode == nsILDAPErrors::SIZELIMIT_EXCEEDED) {
|
||||
switch(mState) {
|
||||
case kSearchingAuthDN :
|
||||
rv = OnSearchAuthDNDone();
|
||||
break;
|
||||
case kSearchingRootDSE:
|
||||
{
|
||||
// Before starting the changeLog check the DB file, if its not there or bogus
|
||||
// we need to create a new one and set to all.
|
||||
nsCOMPtr<nsIAddrBookSession> abSession = do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
nsCOMPtr<nsIFile> dbPath;
|
||||
rv = abSession->GetUserProfileDirectory(getter_AddRefs(dbPath));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsAutoCString fileName;
|
||||
rv = mDirectory->GetReplicationFileName(fileName);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = dbPath->AppendNative(fileName);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
bool fileExists;
|
||||
rv = dbPath->Exists(&fileExists);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
int64_t fileSize;
|
||||
rv = dbPath->GetFileSize(&fileSize);
|
||||
if(NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
if (!fileExists || !fileSize)
|
||||
mUseChangeLog = false;
|
||||
|
||||
// Open / create the AB here since it calls Done,
|
||||
// just return from here.
|
||||
if (mUseChangeLog)
|
||||
rv = OpenABForReplicatedDir(false);
|
||||
else
|
||||
rv = OpenABForReplicatedDir(true);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Now start the appropriate query
|
||||
rv = OnSearchRootDSEDone();
|
||||
break;
|
||||
}
|
||||
case kFindingChanges:
|
||||
rv = OnFindingChangesDone();
|
||||
// If success we return from here since
|
||||
// this changes state to kReplicatingChanges
|
||||
// and it falls thru into the if clause below.
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
break;
|
||||
case kReplicatingAll :
|
||||
return nsAbLDAPProcessReplicationData::OnLDAPSearchResult(aMessage);
|
||||
} // end of switch
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
// If one of the changed entry in changelog is not found,
|
||||
// continue with replicating the next one.
|
||||
if(mState == kReplicatingChanges)
|
||||
rv = OnReplicatingChangeDone();
|
||||
} // end of outer if
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
Abort();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::GetAuthData()
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
||||
if (!wwatch)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAuthPrompt> dialog;
|
||||
nsresult rv = wwatch->GetNewAuthPrompter(0, getter_AddRefs(dialog));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!dialog)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsILDAPURL> url;
|
||||
rv = mQuery->GetReplicationURL(getter_AddRefs(url));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString serverUri;
|
||||
rv = url->GetSpec(serverUri);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle("chrome://messenger/locale/addressbook/addressBook.properties", getter_AddRefs(bundle));
|
||||
if (NS_FAILED (rv))
|
||||
return rv ;
|
||||
|
||||
nsString title;
|
||||
rv = bundle->GetStringFromName(u"AuthDlgTitle", getter_Copies(title));
|
||||
if (NS_FAILED (rv))
|
||||
return rv ;
|
||||
|
||||
nsString desc;
|
||||
rv = bundle->GetStringFromName(u"AuthDlgDesc", getter_Copies(desc));
|
||||
if (NS_FAILED (rv))
|
||||
return rv ;
|
||||
|
||||
nsString username;
|
||||
nsString password;
|
||||
bool btnResult = false;
|
||||
rv = dialog->PromptUsernameAndPassword(title, desc,
|
||||
NS_ConvertUTF8toUTF16(serverUri).get(),
|
||||
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
||||
getter_Copies(username), getter_Copies(password),
|
||||
&btnResult);
|
||||
if(NS_SUCCEEDED(rv) && btnResult) {
|
||||
CopyUTF16toUTF8(username, mAuthUserID);
|
||||
CopyUTF16toUTF8(password, mAuthPswd);
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnSearchAuthDNDone()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsILDAPURL> url;
|
||||
nsresult rv = mQuery->GetReplicationURL(getter_AddRefs(url));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = mQuery->ConnectToLDAPServer(url, mAuthDN);
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
mState = kAuthenticatedBinding;
|
||||
rv = mDirectory->SetAuthDn(mAuthDN);
|
||||
}
|
||||
|
||||
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(int32_t 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);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t lastChangeNumber;
|
||||
mDirectory->GetLastChangeNumber(&lastChangeNumber);
|
||||
|
||||
if ((mRootDSEEntry.lastChangeNumber > 0) &&
|
||||
(lastChangeNumber < mRootDSEEntry.lastChangeNumber) &&
|
||||
(lastChangeNumber > mRootDSEEntry.firstChangeNumber))
|
||||
mUseChangeLog = true;
|
||||
|
||||
if (mRootDSEEntry.lastChangeNumber &&
|
||||
(lastChangeNumber == mRootDSEEntry.lastChangeNumber)) {
|
||||
Done(true); // We are up to date no need to replicate, db not open yet so call Done
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnSearchRootDSEDone()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(mUseChangeLog) {
|
||||
rv = mChangeLogQuery->QueryChangeLog(mRootDSEEntry.changeLogDN, mRootDSEEntry.lastChangeNumber);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
mState = kFindingChanges;
|
||||
if(mListener)
|
||||
mListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_START, false);
|
||||
}
|
||||
else {
|
||||
rv = mQuery->QueryAllEntries();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
mState = kReplicatingAll;
|
||||
if(mListener)
|
||||
mListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_START, true);
|
||||
}
|
||||
|
||||
rv = mDirectory->SetLastChangeNumber(mRootDSEEntry.lastChangeNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDirectory->SetDataVersion(mRootDSEEntry.dataVersion);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
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(int32_t 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(nullptr,nullptr,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;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnFindingChangesDone()
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
#ifdef DEBUG_rdayal
|
||||
printf ("ChangeLog Replication : Finding Changes Done \n");
|
||||
#endif
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// No entries to add/update (for updates too we delete and add) entries,
|
||||
// we took care of deletes in ParseChangeLogEntries, all Done!
|
||||
mEntriesAddedQueryCount = mEntriesToAdd.Count();
|
||||
if(mEntriesAddedQueryCount <= 0) {
|
||||
if(mReplicationDB && mDBOpen) {
|
||||
// Close the DB, no need to commit since we have not made
|
||||
// any changes yet to the DB.
|
||||
rv = mReplicationDB->Close(false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB Close(no commit) on Success failed");
|
||||
mDBOpen = false;
|
||||
// Once are done with the replication file, delete the backup file
|
||||
if(mBackupReplicationFile) {
|
||||
rv = mBackupReplicationFile->Remove(false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication BackupFile Remove on Success failed");
|
||||
}
|
||||
}
|
||||
Done(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Decrement the count first to get the correct array element
|
||||
mEntriesAddedQueryCount--;
|
||||
rv = mChangeLogQuery->QueryChangedEntries(NS_ConvertUTF16toUTF8(*(mEntriesToAdd[mEntriesAddedQueryCount])));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(mListener && NS_SUCCEEDED(rv))
|
||||
mListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_START, true);
|
||||
|
||||
mState = kReplicatingChanges;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessChangeLogData::OnReplicatingChangeDone()
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(!mEntriesAddedQueryCount)
|
||||
{
|
||||
if(mReplicationDB && mDBOpen) {
|
||||
rv = mReplicationDB->Close(true); // Commit and close the DB
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB Close (commit) on Success failed");
|
||||
mDBOpen = false;
|
||||
}
|
||||
// Once we done with the replication file, delete the backup file.
|
||||
if(mBackupReplicationFile) {
|
||||
rv = mBackupReplicationFile->Remove(false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication BackupFile Remove on Success failed");
|
||||
}
|
||||
Done(true); // All data is received
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove the entry already added from the list and query the next one.
|
||||
if(mEntriesAddedQueryCount < mEntriesToAdd.Count() && mEntriesAddedQueryCount >= 0)
|
||||
mEntriesToAdd.RemoveStringAt(mEntriesAddedQueryCount);
|
||||
mEntriesAddedQueryCount--;
|
||||
rv = mChangeLogQuery->QueryChangedEntries(NS_ConvertUTF16toUTF8(*(mEntriesToAdd[mEntriesAddedQueryCount])));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
57
mailnews/addrbook/src/nsAbLDAPChangeLogData.h
Normal file
57
mailnews/addrbook/src/nsAbLDAPChangeLogData.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPChangeLogData_h__
|
||||
#define nsAbLDAPChangeLogData_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbLDAPReplicationData.h"
|
||||
#include "nsAbLDAPChangeLogQuery.h"
|
||||
|
||||
typedef struct {
|
||||
nsCString changeLogDN;
|
||||
int32_t firstChangeNumber;
|
||||
int32_t lastChangeNumber;
|
||||
nsCString dataVersion;
|
||||
} RootDSEChangeLogEntry;
|
||||
|
||||
class nsAbLDAPProcessChangeLogData : public nsAbLDAPProcessReplicationData
|
||||
{
|
||||
public :
|
||||
|
||||
nsAbLDAPProcessChangeLogData();
|
||||
|
||||
NS_IMETHOD Init(nsIAbLDAPReplicationQuery * query, nsIWebProgressListener *progressListener);
|
||||
|
||||
protected :
|
||||
~nsAbLDAPProcessChangeLogData();
|
||||
|
||||
nsCOMPtr <nsIAbLDAPChangeLogQuery> mChangeLogQuery;
|
||||
|
||||
nsresult OnLDAPBind(nsILDAPMessage *aMessage);
|
||||
nsresult OnLDAPSearchEntry(nsILDAPMessage *aMessage) override;
|
||||
nsresult OnLDAPSearchResult(nsILDAPMessage *aMessage) override;
|
||||
|
||||
nsresult ParseChangeLogEntries(nsILDAPMessage *aMessage);
|
||||
nsresult ParseRootDSEEntry(nsILDAPMessage *aMessage);
|
||||
|
||||
nsresult GetAuthData(); // displays username and password prompt
|
||||
nsCString mAuthUserID; // user id of the user making the connection
|
||||
|
||||
nsresult OnSearchAuthDNDone();
|
||||
nsresult OnSearchRootDSEDone();
|
||||
nsresult OnFindingChangesDone();
|
||||
nsresult OnReplicatingChangeDone();
|
||||
|
||||
RootDSEChangeLogEntry mRootDSEEntry;
|
||||
bool mUseChangeLog;
|
||||
int32_t mChangeLogEntriesCount;
|
||||
|
||||
int32_t mEntriesAddedQueryCount;
|
||||
nsStringArray mEntriesToAdd;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsAbLDAPChangeLogData_h__
|
||||
|
||||
180
mailnews/addrbook/src/nsAbLDAPChangeLogQuery.cpp
Normal file
180
mailnews/addrbook/src/nsAbLDAPChangeLogQuery.cpp
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbLDAPChangeLogQuery.h"
|
||||
#include "nsAbLDAPReplicationService.h"
|
||||
#include "nsAbLDAPChangeLogData.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "prprf.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
|
||||
|
||||
// The tables below were originally in nsAbLDAPProperties.cpp, which has since
|
||||
// gone away.
|
||||
static const char * sChangeLogRootDSEAttribs[] =
|
||||
{
|
||||
"changelog",
|
||||
"firstChangeNumber",
|
||||
"lastChangeNumber",
|
||||
"dataVersion"
|
||||
};
|
||||
static const char * sChangeLogEntryAttribs[] =
|
||||
{
|
||||
"targetdn",
|
||||
"changetype"
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAbLDAPChangeLogQuery, nsAbLDAPReplicationQuery, nsIAbLDAPChangeLogQuery)
|
||||
|
||||
nsAbLDAPChangeLogQuery::nsAbLDAPChangeLogQuery()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPChangeLogQuery::~nsAbLDAPChangeLogQuery()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// this is to be defined only till this is not hooked to SSL to get authDN and authPswd
|
||||
#define USE_AUTHDLG
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::Init(const nsACString & aPrefName, nsIWebProgressListener *aProgressListener)
|
||||
{
|
||||
if(aPrefName.IsEmpty())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
mDirPrefName = aPrefName;
|
||||
|
||||
nsresult rv = InitLDAPData();
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// create the ChangeLog Data Processor
|
||||
mDataProcessor = do_CreateInstance(NS_ABLDAP_PROCESSCHANGELOGDATA_CONTRACTID, &rv);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// 'this' initialized
|
||||
mInitialized = true;
|
||||
|
||||
return mDataProcessor->Init(this, aProgressListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::DoReplicationQuery()
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
#ifdef USE_AUTHDLG
|
||||
return ConnectToLDAPServer(mURL, EmptyCString());
|
||||
#else
|
||||
mDataProcessor->PopulateAuthData();
|
||||
return ConnectToLDAPServer(mURL, mAuthDN);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryAuthDN(const nsACString & aValueUsedToFindDn)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIAbLDAPAttributeMap> attrMap;
|
||||
nsresult rv = mDirectory->GetAttributeMap(getter_AddRefs(attrMap));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString filter;
|
||||
rv = attrMap->GetFirstAttribute(NS_LITERAL_CSTRING("PrimaryEmail"), filter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
filter += '=';
|
||||
filter += aValueUsedToFindDn;
|
||||
|
||||
nsAutoCString dn;
|
||||
rv = mURL->GetDn(dn);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = CreateNewLDAPOperation();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX We really should be using LDAP_NO_ATTRS here once its exposed via
|
||||
// the XPCOM layer of the directory code.
|
||||
return mOperation->SearchExt(dn, nsILDAPURL::SCOPE_SUBTREE, filter,
|
||||
0, nullptr,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryRootDSE()
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = CreateNewLDAPOperation();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return mOperation->SearchExt(EmptyCString(), nsILDAPURL::SCOPE_BASE,
|
||||
NS_LITERAL_CSTRING("objectclass=*"),
|
||||
sizeof(sChangeLogRootDSEAttribs),
|
||||
sChangeLogRootDSEAttribs, 0, 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryChangeLog(const nsACString & aChangeLogDN, int32_t aLastChangeNo)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if (aChangeLogDN.IsEmpty())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
int32_t lastChangeNumber;
|
||||
nsresult rv = mDirectory->GetLastChangeNumber(&lastChangeNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// make sure that the filter here just have one condition
|
||||
// and should not be enclosed in enclosing brackets.
|
||||
// also condition '>' doesnot work, it should be '>='/
|
||||
nsAutoCString filter (NS_LITERAL_CSTRING("changenumber>="));
|
||||
filter.AppendInt(lastChangeNumber + 1);
|
||||
|
||||
rv = CreateNewLDAPOperation();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mOperation->SearchExt(aChangeLogDN, nsILDAPURL::SCOPE_ONELEVEL, filter,
|
||||
sizeof(sChangeLogEntryAttribs),
|
||||
sChangeLogEntryAttribs, 0, 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPChangeLogQuery::QueryChangedEntries(const nsACString & aChangedEntryDN)
|
||||
{
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if(aChangedEntryDN.IsEmpty())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsAutoCString urlFilter;
|
||||
nsresult rv = mURL->GetFilter(urlFilter);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
int32_t 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);
|
||||
}
|
||||
|
||||
28
mailnews/addrbook/src/nsAbLDAPChangeLogQuery.h
Normal file
28
mailnews/addrbook/src/nsAbLDAPChangeLogQuery.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPChangeLogQuery_h__
|
||||
#define nsAbLDAPChangeLogQuery_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbLDAPReplicationQuery.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsAbLDAPChangeLogQuery : public nsIAbLDAPChangeLogQuery,
|
||||
public nsAbLDAPReplicationQuery
|
||||
{
|
||||
public :
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABLDAPCHANGELOGQUERY
|
||||
|
||||
nsAbLDAPChangeLogQuery();
|
||||
virtual ~nsAbLDAPChangeLogQuery();
|
||||
|
||||
NS_IMETHOD DoReplicationQuery() override;
|
||||
NS_IMETHOD Init(const nsACString & aPrefName, nsIWebProgressListener *aProgressListener);
|
||||
};
|
||||
|
||||
#endif // nsAbLDAPChangeLogQuery_h__
|
||||
79
mailnews/addrbook/src/nsAbLDAPDirFactory.cpp
Normal file
79
mailnews/addrbook/src/nsAbLDAPDirFactory.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPDirFactory.h"
|
||||
#include "nsAbUtils.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsAbLDAPDirectory.h"
|
||||
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbLDAPDirFactory, nsIAbDirFactory)
|
||||
|
||||
nsAbLDAPDirFactory::nsAbLDAPDirFactory()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPDirFactory::~nsAbLDAPDirFactory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbLDAPDirFactory::GetDirectories(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
const nsACString &aPrefName,
|
||||
nsISimpleEnumerator **aDirectories)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectories);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
if (Substring(aURI, 0, 5).EqualsLiteral("ldap:") ||
|
||||
Substring(aURI, 0, 6).EqualsLiteral("ldaps:")) {
|
||||
/*
|
||||
* If the URI starts with ldap: or ldaps:
|
||||
* then this directory is an LDAP directory.
|
||||
*
|
||||
* We don't want to use the ldap:// or ldaps:// URI
|
||||
* as the URI because the ldap:// or ldaps:// URI
|
||||
* will contain the hostname, basedn, port, etc.
|
||||
* so if those attributes changed, we'll run into the
|
||||
* the same problem that we hit with changing username / hostname
|
||||
* for mail servers. To solve this problem, we add an extra
|
||||
* level of indirection. The URI that we generate
|
||||
* (the bridge URI) will be moz-abldapdirectory://<prefName>
|
||||
* and when we need the hostname, basedn, port, etc,
|
||||
* we'll use the <prefName> to get the necessary prefs.
|
||||
* note, <prefName> does not change.
|
||||
*/
|
||||
nsAutoCString bridgeURI;
|
||||
bridgeURI = NS_LITERAL_CSTRING(kLDAPDirectoryRoot);
|
||||
bridgeURI += aPrefName;
|
||||
rv = abManager->GetDirectory(bridgeURI, getter_AddRefs(directory));
|
||||
}
|
||||
else {
|
||||
rv = abManager->GetDirectory(aURI, getter_AddRefs(directory));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_NewSingletonEnumerator(aDirectories, directory);
|
||||
}
|
||||
|
||||
/* void deleteDirectory (in nsIAbDirectory directory); */
|
||||
NS_IMETHODIMP
|
||||
nsAbLDAPDirFactory::DeleteDirectory(nsIAbDirectory *directory)
|
||||
{
|
||||
// No actual deletion - as the LDAP Address Book is not physically
|
||||
// created in the corresponding CreateDirectory() unlike the Personal
|
||||
// Address Books. But we still need to return NS_OK from here.
|
||||
return NS_OK;
|
||||
}
|
||||
23
mailnews/addrbook/src/nsAbLDAPDirFactory.h
Normal file
23
mailnews/addrbook/src/nsAbLDAPDirFactory.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPDirFactory_h__
|
||||
#define nsAbLDAPDirFactory_h__
|
||||
|
||||
#include "nsIAbDirFactory.h"
|
||||
|
||||
class nsAbLDAPDirFactory : public nsIAbDirFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRFACTORY
|
||||
|
||||
nsAbLDAPDirFactory();
|
||||
|
||||
private:
|
||||
virtual ~nsAbLDAPDirFactory();
|
||||
};
|
||||
|
||||
#endif
|
||||
948
mailnews/addrbook/src/nsAbLDAPDirectory.cpp
Normal file
948
mailnews/addrbook/src/nsAbLDAPDirectory.cpp
Normal file
|
|
@ -0,0 +1,948 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPDirectory.h"
|
||||
|
||||
#include "nsAbQueryStringToExpression.h"
|
||||
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsIAbLDAPAttributeMap.h"
|
||||
#include "nsIAbMDBDirectory.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILDAPModification.h"
|
||||
#include "nsILDAPService.h"
|
||||
#include "nsIAbLDAPCard.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#define kDefaultMaxHits 100
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsAbLDAPDirectory::nsAbLDAPDirectory() :
|
||||
nsAbDirProperty(),
|
||||
mPerformingQuery(false),
|
||||
mContext(0),
|
||||
mLock("nsAbLDAPDirectory.mLock")
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPDirectory::~nsAbLDAPDirectory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAbLDAPDirectory, nsAbDirProperty,
|
||||
nsISupportsWeakReference, nsIAbDirSearchListener,
|
||||
nsIAbLDAPDirectory)
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetPropertiesChromeURI(nsACString &aResult)
|
||||
{
|
||||
aResult.AssignLiteral("chrome://messenger/content/addressbook/pref-directory-add.xul");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::Init(const char* aURI)
|
||||
{
|
||||
// We need to ensure that the m_DirPrefId is initialized properly
|
||||
nsAutoCString uri(aURI);
|
||||
|
||||
// Find the first ? (of the search params) if there is one.
|
||||
// We know we can start at the end of the moz-abldapdirectory:// because
|
||||
// that's the URI we should have been passed.
|
||||
int32_t searchCharLocation = uri.FindChar('?', kLDAPDirectoryRootLen);
|
||||
|
||||
if (searchCharLocation == -1)
|
||||
m_DirPrefId = Substring(uri, kLDAPDirectoryRootLen);
|
||||
else
|
||||
m_DirPrefId = Substring(uri, kLDAPDirectoryRootLen, searchCharLocation - kLDAPDirectoryRootLen);
|
||||
|
||||
return nsAbDirProperty::Init(aURI);
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPDirectory::Initiate()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* nsIAbDirectory methods
|
||||
*
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetURI(nsACString &aURI)
|
||||
{
|
||||
if (mURI.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
aURI = mURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetChildNodes(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
return NS_NewEmptyEnumerator(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetChildCards(nsISimpleEnumerator** result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// when offline, we need to get the child cards for the local, replicated mdb directory
|
||||
bool offline;
|
||||
nsCOMPtr <nsIIOService> ioService =
|
||||
mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
|
||||
rv = ioService->GetOffline(&offline);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (offline) {
|
||||
nsCString fileName;
|
||||
rv = GetReplicationFileName(fileName);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// if there is no fileName, bail out now.
|
||||
if (fileName.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
// perform the same query, but on the local directory
|
||||
nsAutoCString localDirectoryURI(NS_LITERAL_CSTRING(kMDBDirectoryRoot));
|
||||
localDirectoryURI.Append(fileName);
|
||||
if (mIsQueryURI)
|
||||
{
|
||||
localDirectoryURI.AppendLiteral("?");
|
||||
localDirectoryURI.Append(mQueryString);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIAbDirectory> directory;
|
||||
rv = abManager->GetDirectory(localDirectoryURI,
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = directory->GetChildCards(result);
|
||||
}
|
||||
else {
|
||||
// Start the search
|
||||
rv = StartSearch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewEmptyEnumerator(result);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetIsQuery(bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mIsQueryURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::HasCard(nsIAbCard* card, bool* hasCard)
|
||||
{
|
||||
nsresult rv = Initiate ();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Enter lock
|
||||
MutexAutoLock lock (mLock);
|
||||
|
||||
*hasCard = mCache.Get(card, nullptr);
|
||||
if (!*hasCard && mPerformingQuery)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetLDAPURL(nsILDAPURL** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
// Rather than using GetURI here we call GetStringValue directly so
|
||||
// we can handle the case where the URI isn't specified (see comments
|
||||
// below)
|
||||
nsAutoCString URI;
|
||||
nsresult rv = GetStringValue("uri", EmptyCString(), URI);
|
||||
if (NS_FAILED(rv) || URI.IsEmpty())
|
||||
{
|
||||
/*
|
||||
* A recent change in Mozilla now means that the LDAP Address Book
|
||||
* URI is based on the unique preference name value i.e.
|
||||
* [moz-abldapdirectory://prefName]
|
||||
* Prior to this valid change it was based on the actual uri i.e.
|
||||
* [moz-abldapdirectory://host:port/basedn]
|
||||
* Basing the resource on the prefName allows these attributes to
|
||||
* change.
|
||||
*
|
||||
* But the uri value was also the means by which third-party
|
||||
* products could integrate with Mozilla's LDAP Address Books
|
||||
* without necessarily having an entry in the preferences file
|
||||
* or more importantly needing to be able to change the
|
||||
* preferences entries. Thus to set the URI Spec now, it is
|
||||
* only necessary to read the uri pref entry, while in the
|
||||
* case where it is not a preference, we need to replace the
|
||||
* "moz-abldapdirectory".
|
||||
*/
|
||||
URI = mURINoQuery;
|
||||
if (StringBeginsWith(URI, NS_LITERAL_CSTRING(kLDAPDirectoryRoot)))
|
||||
URI.Replace(0, kLDAPDirectoryRootLen, NS_LITERAL_CSTRING("ldap://"));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIOService> ioService =
|
||||
mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIURI> result;
|
||||
rv = ioService->NewURI(URI, nullptr, nullptr, getter_AddRefs(result));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return CallQueryInterface(result, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetLDAPURL(nsILDAPURL *aUrl)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUrl);
|
||||
|
||||
nsAutoCString oldUrl;
|
||||
// Note, it doesn't matter if GetStringValue fails - we'll just send an
|
||||
// update if its blank (i.e. old value not set).
|
||||
GetStringValue("uri", EmptyCString(), oldUrl);
|
||||
|
||||
// Actually set the new value.
|
||||
nsCString tempLDAPURL;
|
||||
nsresult rv = aUrl->GetSpec(tempLDAPURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetStringValue("uri", tempLDAPURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now we need to send an update which will ensure our indicators and
|
||||
// listeners get updated correctly.
|
||||
|
||||
// See if they both start with ldaps: or ldap:
|
||||
bool newIsNotSecure = StringHead(tempLDAPURL, 5).Equals("ldap:");
|
||||
|
||||
if (oldUrl.IsEmpty() ||
|
||||
StringHead(oldUrl, 5).Equals("ldap:") != newIsNotSecure)
|
||||
{
|
||||
// They don't so its time to send round an update.
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We inherit from nsIAbDirectory, so this static cast should be safe.
|
||||
abManager->NotifyItemPropertyChanged(static_cast<nsIAbDirectory*>(this),
|
||||
"IsSecure",
|
||||
(newIsNotSecure ? u"true" : u"false"),
|
||||
(newIsNotSecure ? u"false" : u"true"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* nsIAbDirectorySearch methods
|
||||
*
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::StartSearch ()
|
||||
{
|
||||
if (!mIsQueryURI || mQueryString.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = StopSearch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectoryQueryArguments> arguments = do_CreateInstance(NS_ABDIRECTORYQUERYARGUMENTS_CONTRACTID,&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanExpression> expression;
|
||||
rv = nsAbQueryStringToExpression::Convert(mQueryString,
|
||||
getter_AddRefs(expression));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = arguments->SetExpression(expression);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = arguments->SetQuerySubDirectories(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the max hits to return
|
||||
int32_t maxHits;
|
||||
rv = GetMaxHits(&maxHits);
|
||||
if (NS_FAILED(rv))
|
||||
maxHits = kDefaultMaxHits;
|
||||
|
||||
// get the appropriate ldap attribute map, and pass it in via the
|
||||
// TypeSpecificArgument
|
||||
nsCOMPtr<nsIAbLDAPAttributeMap> attrMap;
|
||||
rv = GetAttributeMap(getter_AddRefs(attrMap));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupports> typeSpecificArg = do_QueryInterface(attrMap, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = arguments->SetTypeSpecificArg(attrMap);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mDirectoryQuery)
|
||||
{
|
||||
mDirectoryQuery = do_CreateInstance(NS_ABLDAPDIRECTORYQUERY_CONTRACTID,
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Perform the query
|
||||
rv = mDirectoryQuery->DoQuery(this, arguments, this, maxHits, 0, &mContext);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Enter lock
|
||||
MutexAutoLock lock(mLock);
|
||||
mPerformingQuery = true;
|
||||
mCache.Clear();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::StopSearch ()
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Enter lock
|
||||
{
|
||||
MutexAutoLock lockGuard(mLock);
|
||||
if (!mPerformingQuery)
|
||||
return NS_OK;
|
||||
mPerformingQuery = false;
|
||||
}
|
||||
// Exit lock
|
||||
|
||||
if (!mDirectoryQuery)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return mDirectoryQuery->StopQuery(mContext);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* nsAbDirSearchListenerContext methods
|
||||
*
|
||||
*/
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::OnSearchFinished(int32_t aResult, const nsAString &aErrorMessage)
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
mPerformingQuery = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::OnSearchFoundCard(nsIAbCard* card)
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Enter lock
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mCache.Put(card, card);
|
||||
}
|
||||
// Exit lock
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
abManager->NotifyDirectoryItemAdded(this, card);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetSupportsMailingLists(bool *aSupportsMailingsLists)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSupportsMailingsLists);
|
||||
*aSupportsMailingsLists = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetReadOnly(bool *aReadOnly)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aReadOnly);
|
||||
|
||||
*aReadOnly = true;
|
||||
|
||||
#ifdef MOZ_EXPERIMENTAL_WRITEABLE_LDAP
|
||||
bool readOnly;
|
||||
nsresult rv = GetBoolValue("readonly", false, &readOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (readOnly)
|
||||
return NS_OK;
|
||||
|
||||
// when online, we'll allow writing as well
|
||||
bool offline;
|
||||
nsCOMPtr <nsIIOService> ioService =
|
||||
mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = ioService->GetOffline(&offline);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (!offline)
|
||||
*aReadOnly = false;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetIsRemote(bool *aIsRemote)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsRemote);
|
||||
*aIsRemote = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetIsSecure(bool *aIsSecure)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSecure);
|
||||
|
||||
nsAutoCString URI;
|
||||
nsresult rv = GetStringValue("uri", EmptyCString(), URI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// to determine if this is a secure directory, check if the uri is ldaps:// or not
|
||||
*aIsSecure = (strncmp(URI.get(), "ldaps:", 6) == 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::UseForAutocomplete(const nsACString &aIdentityKey,
|
||||
bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
// Set this to false by default to make the code easier below.
|
||||
*aResult = false;
|
||||
|
||||
nsresult rv;
|
||||
bool offline = false;
|
||||
nsCOMPtr <nsIIOService> ioService =
|
||||
mozilla::services::GetIOService();
|
||||
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = ioService->GetOffline(&offline);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If we're online, then don't allow search during local autocomplete - must
|
||||
// use the separate LDAP autocomplete session due to the current interfaces
|
||||
if (!offline)
|
||||
return NS_OK;
|
||||
|
||||
// Is the use directory pref set for autocompletion?
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool useDirectory = false;
|
||||
rv = prefs->GetBoolPref("ldap_2.autoComplete.useDirectory", &useDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// No need to search if not set up globally for LDAP autocompletion and we've
|
||||
// not been given an identity.
|
||||
if (!useDirectory && aIdentityKey.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
nsCString prefName;
|
||||
if (!aIdentityKey.IsEmpty())
|
||||
{
|
||||
// If we have an identity string, try and find out the required directory
|
||||
// server.
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
|
||||
// If we failed, just return, we can't do much about this.
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgIdentity> identity;
|
||||
rv = accountManager->GetIdentity(aIdentityKey, getter_AddRefs(identity));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
bool overrideGlobalPref = false;
|
||||
identity->GetOverrideGlobalPref(&overrideGlobalPref);
|
||||
if (overrideGlobalPref)
|
||||
identity->GetDirectoryServer(prefName);
|
||||
}
|
||||
}
|
||||
|
||||
// If the preference name is still empty but useDirectory is false, then
|
||||
// the global one is not available, nor is the overriden one.
|
||||
if (prefName.IsEmpty() && !useDirectory)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we failed to get the identity preference, or the pref name is empty
|
||||
// try the global preference.
|
||||
if (prefName.IsEmpty())
|
||||
{
|
||||
nsresult rv = prefs->GetCharPref("ldap_2.autoComplete.directoryServer",
|
||||
getter_Copies(prefName));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
// Now see if the pref name matches our pref id.
|
||||
if (prefName.Equals(m_DirPrefId))
|
||||
{
|
||||
// Yes it does, one last check - does the replication file exist?
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> databaseFile;
|
||||
// If we can't get the file, then there is no database to use
|
||||
if (NS_FAILED(GetReplicationFile(getter_AddRefs(databaseFile))))
|
||||
return NS_OK;
|
||||
|
||||
bool exists;
|
||||
rv = databaseFile->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = exists;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetSearchClientControls(nsIMutableArray **aControls)
|
||||
{
|
||||
NS_IF_ADDREF(*aControls = mSearchClientControls);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetSearchClientControls(nsIMutableArray *aControls)
|
||||
{
|
||||
mSearchClientControls = aControls;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetSearchServerControls(nsIMutableArray **aControls)
|
||||
{
|
||||
NS_IF_ADDREF(*aControls = mSearchServerControls);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetSearchServerControls(nsIMutableArray *aControls)
|
||||
{
|
||||
mSearchServerControls = aControls;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetProtocolVersion(uint32_t *aProtocolVersion)
|
||||
{
|
||||
nsAutoCString versionString;
|
||||
|
||||
nsresult rv = GetStringValue("protocolVersion", NS_LITERAL_CSTRING("3"), versionString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aProtocolVersion = versionString.EqualsLiteral("3") ?
|
||||
(uint32_t)nsILDAPConnection::VERSION3 :
|
||||
(uint32_t)nsILDAPConnection::VERSION2;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetProtocolVersion(uint32_t aProtocolVersion)
|
||||
{
|
||||
// XXX We should cancel any existing LDAP connections here and
|
||||
// be ready to re-initialise them with the new auth details.
|
||||
return SetStringValue("protocolVersion",
|
||||
aProtocolVersion == nsILDAPConnection::VERSION3 ?
|
||||
NS_LITERAL_CSTRING("3") : NS_LITERAL_CSTRING("2"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetMaxHits(int32_t *aMaxHits)
|
||||
{
|
||||
return GetIntValue("maxHits", kDefaultMaxHits, aMaxHits);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetMaxHits(int32_t aMaxHits)
|
||||
{
|
||||
return SetIntValue("maxHits", aMaxHits);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetReplicationFileName(nsACString &aReplicationFileName)
|
||||
{
|
||||
return GetStringValue("filename", EmptyCString(), aReplicationFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetReplicationFileName(const nsACString &aReplicationFileName)
|
||||
{
|
||||
return SetStringValue("filename", aReplicationFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetAuthDn(nsACString &aAuthDn)
|
||||
{
|
||||
return GetStringValue("auth.dn", EmptyCString(), aAuthDn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetAuthDn(const nsACString &aAuthDn)
|
||||
{
|
||||
// XXX We should cancel any existing LDAP connections here and
|
||||
// be ready to re-initialise them with the new auth details.
|
||||
return SetStringValue("auth.dn", aAuthDn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetSaslMechanism(nsACString &aSaslMechanism)
|
||||
{
|
||||
return GetStringValue("auth.saslmech", EmptyCString(), aSaslMechanism);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetSaslMechanism(const nsACString &aSaslMechanism)
|
||||
{
|
||||
return SetStringValue("auth.saslmech", aSaslMechanism);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetLastChangeNumber(int32_t *aLastChangeNumber)
|
||||
{
|
||||
return GetIntValue("lastChangeNumber", -1, aLastChangeNumber);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetLastChangeNumber(int32_t aLastChangeNumber)
|
||||
{
|
||||
return SetIntValue("lastChangeNumber", aLastChangeNumber);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetDataVersion(nsACString &aDataVersion)
|
||||
{
|
||||
return GetStringValue("dataVersion", EmptyCString(), aDataVersion);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetDataVersion(const nsACString &aDataVersion)
|
||||
{
|
||||
return SetStringValue("dataVersion", aDataVersion);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetAttributeMap(nsIAbLDAPAttributeMap **aAttributeMap)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributeMap);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbLDAPAttributeMapService> mapSvc =
|
||||
do_GetService("@mozilla.org/addressbook/ldap-attribute-map-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mapSvc->GetMapForPrefBranch(m_DirPrefId, aAttributeMap);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetReplicationFile(nsIFile **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
nsCString fileName;
|
||||
nsresult rv = GetStringValue("filename", EmptyCString(), fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (fileName.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = profileDir->AppendNative(fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ADDREF(*aResult = profileDir);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetReplicationDatabase(nsIAddrDatabase **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> databaseFile;
|
||||
rv = GetReplicationFile(getter_AddRefs(databaseFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAddrDatabase> addrDBFactory =
|
||||
do_GetService(NS_ADDRDATABASE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return addrDBFactory->Open(databaseFile, false /* no create */, true,
|
||||
aResult);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::DeleteCards(nsIArray *aCards)
|
||||
{
|
||||
uint32_t cardCount;
|
||||
uint32_t i;
|
||||
nsAutoCString cardDN;
|
||||
|
||||
nsresult rv = aCards->GetLength(&cardCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = 0; i < cardCount; ++i)
|
||||
{
|
||||
nsCOMPtr<nsIAbLDAPCard> card(do_QueryElementAt(aCards, i, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_WARNING("Wrong type of card passed to nsAbLDAPDirectory::DeleteCards");
|
||||
break;
|
||||
}
|
||||
|
||||
// Set up the search ldap url - this is mURL
|
||||
rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = card->GetDn(cardDN);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbCard> realCard(do_QueryInterface(card));
|
||||
realCard->SetDirectoryId(EmptyCString());
|
||||
|
||||
// Launch query
|
||||
rv = DoModify(this, nsILDAPModification::MOD_DELETE, cardDN, nullptr,
|
||||
EmptyCString(), EmptyCString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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::GetRdnAttributes(nsACString &aRdnAttributes)
|
||||
{
|
||||
return GetStringValue("rdnAttributes", NS_LITERAL_CSTRING("cn"),
|
||||
aRdnAttributes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetRdnAttributes(const nsACString &aRdnAttributes)
|
||||
{
|
||||
return SetStringValue("rdnAttributes", aRdnAttributes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::GetObjectClasses(nsACString &aObjectClasses)
|
||||
{
|
||||
return GetStringValue("objectClasses", NS_LITERAL_CSTRING(
|
||||
"top,person,organizationalPerson,inetOrgPerson,mozillaAbPersonAlpha"),
|
||||
aObjectClasses);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectory::SetObjectClasses(const nsACString &aObjectClasses)
|
||||
{
|
||||
return SetStringValue("objectClasses", aObjectClasses);
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPDirectory::SplitStringList(
|
||||
const nsACString& aString,
|
||||
uint32_t *aCount,
|
||||
char ***aValues)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCount);
|
||||
NS_ENSURE_ARG_POINTER(aValues);
|
||||
|
||||
nsTArray<nsCString> strarr;
|
||||
ParseString(aString, ',', strarr);
|
||||
|
||||
char **cArray = nullptr;
|
||||
if (!(cArray = static_cast<char **>(moz_xmalloc(
|
||||
strarr.Length() * sizeof(char *)))))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (uint32_t i = 0; i < strarr.Length(); ++i)
|
||||
{
|
||||
if (!(cArray[i] = ToNewCString(strarr[i])))
|
||||
{
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(strarr.Length(), cArray);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
*aCount = strarr.Length();
|
||||
*aValues = cArray;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
75
mailnews/addrbook/src/nsAbLDAPDirectory.h
Normal file
75
mailnews/addrbook/src/nsAbLDAPDirectory.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPDirectory_h__
|
||||
#define nsAbLDAPDirectory_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbDirProperty.h"
|
||||
#include "nsAbLDAPDirectoryModify.h"
|
||||
#include "nsIAbDirectoryQuery.h"
|
||||
#include "nsIAbDirectorySearch.h"
|
||||
#include "nsIAbDirSearchListener.h"
|
||||
#include "nsIAbLDAPDirectory.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
class nsAbLDAPDirectory :
|
||||
public nsAbDirProperty, // nsIAbDirectory
|
||||
public nsAbLDAPDirectoryModify,
|
||||
public nsIAbDirectorySearch,
|
||||
public nsIAbLDAPDirectory,
|
||||
public nsIAbDirSearchListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsAbLDAPDirectory();
|
||||
|
||||
NS_IMETHOD Init(const char *aUri) override;
|
||||
|
||||
// nsIAbDirectory methods
|
||||
NS_IMETHOD GetPropertiesChromeURI(nsACString &aResult) override;
|
||||
NS_IMETHOD GetURI(nsACString &aURI) override;
|
||||
NS_IMETHOD GetChildNodes(nsISimpleEnumerator* *result) override;
|
||||
NS_IMETHOD GetChildCards(nsISimpleEnumerator* *result) override;
|
||||
NS_IMETHOD GetIsQuery(bool *aResult) override;
|
||||
NS_IMETHOD HasCard(nsIAbCard *cards, bool *hasCard) override;
|
||||
NS_IMETHOD GetSupportsMailingLists(bool *aSupportsMailingsLists) override;
|
||||
NS_IMETHOD GetReadOnly(bool *aReadOnly) override;
|
||||
NS_IMETHOD GetIsRemote(bool *aIsRemote) override;
|
||||
NS_IMETHOD GetIsSecure(bool *aIsRemote) override;
|
||||
NS_IMETHOD UseForAutocomplete(const nsACString &aIdentityKey, bool *aResult) override;
|
||||
NS_IMETHOD AddCard(nsIAbCard *aChildCard, nsIAbCard **aAddedCard) override;
|
||||
NS_IMETHOD ModifyCard(nsIAbCard *aModifiedCard) override;
|
||||
NS_IMETHOD DeleteCards(nsIArray *aCards) override;
|
||||
|
||||
// nsIAbDirectorySearch methods
|
||||
NS_DECL_NSIABDIRECTORYSEARCH
|
||||
NS_DECL_NSIABLDAPDIRECTORY
|
||||
NS_DECL_NSIABDIRSEARCHLISTENER
|
||||
|
||||
protected:
|
||||
virtual ~nsAbLDAPDirectory();
|
||||
nsresult Initiate();
|
||||
|
||||
nsresult SplitStringList(const nsACString& aString,
|
||||
uint32_t *aCount,
|
||||
char ***aValues);
|
||||
|
||||
bool mPerformingQuery;
|
||||
int32_t mContext;
|
||||
int32_t mMaxHits;
|
||||
|
||||
nsInterfaceHashtable<nsISupportsHashKey, nsIAbCard> mCache;
|
||||
|
||||
mozilla::Mutex mLock;
|
||||
nsCOMPtr<nsIAbDirectoryQuery> mDirectoryQuery;
|
||||
nsCOMPtr<nsIMutableArray> mSearchServerControls;
|
||||
nsCOMPtr<nsIMutableArray> mSearchClientControls;
|
||||
};
|
||||
|
||||
#endif
|
||||
372
mailnews/addrbook/src/nsAbLDAPDirectoryModify.cpp
Normal file
372
mailnews/addrbook/src/nsAbLDAPDirectoryModify.cpp
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPDirectoryModify.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsILDAPModification.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIAbLDAPDirectory.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
class nsAbModifyLDAPMessageListener : public nsAbLDAPListenerBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
nsAbModifyLDAPMessageListener(const int32_t type,
|
||||
const nsACString &cardDN,
|
||||
nsIArray* modArray,
|
||||
const nsACString &newRDN,
|
||||
const nsACString &newBaseDN,
|
||||
nsILDAPURL* directoryUrl,
|
||||
nsILDAPConnection* connection,
|
||||
nsIMutableArray* serverSearchControls,
|
||||
nsIMutableArray* clientSearchControls,
|
||||
const nsACString &login,
|
||||
const int32_t timeOut = 0);
|
||||
// nsILDAPMessageListener
|
||||
NS_IMETHOD OnLDAPMessage(nsILDAPMessage *aMessage) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsAbModifyLDAPMessageListener();
|
||||
|
||||
nsresult Cancel();
|
||||
virtual void InitFailed(bool aCancelled = false) override;
|
||||
virtual nsresult DoTask() override;
|
||||
nsresult DoMainTask();
|
||||
nsresult OnLDAPMessageModifyResult(nsILDAPMessage *aMessage);
|
||||
nsresult OnLDAPMessageRenameResult(nsILDAPMessage *aMessage);
|
||||
|
||||
int32_t mType;
|
||||
nsCString mCardDN;
|
||||
nsCOMPtr<nsIArray> mModification;
|
||||
nsCString mNewRDN;
|
||||
nsCString mNewBaseDN;
|
||||
|
||||
bool mFinished;
|
||||
bool mCanceled;
|
||||
bool mFlagRename;
|
||||
|
||||
nsCOMPtr<nsILDAPOperation> mModifyOperation;
|
||||
nsCOMPtr<nsIMutableArray> mServerSearchControls;
|
||||
nsCOMPtr<nsIMutableArray> mClientSearchControls;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbModifyLDAPMessageListener, nsILDAPMessageListener)
|
||||
|
||||
nsAbModifyLDAPMessageListener::nsAbModifyLDAPMessageListener(
|
||||
const int32_t type,
|
||||
const nsACString &cardDN,
|
||||
nsIArray* modArray,
|
||||
const nsACString &newRDN,
|
||||
const nsACString &newBaseDN,
|
||||
nsILDAPURL* directoryUrl,
|
||||
nsILDAPConnection* connection,
|
||||
nsIMutableArray* serverSearchControls,
|
||||
nsIMutableArray* clientSearchControls,
|
||||
const nsACString &login,
|
||||
const int32_t timeOut) :
|
||||
nsAbLDAPListenerBase(directoryUrl, connection, login, timeOut),
|
||||
mType(type),
|
||||
mCardDN(cardDN),
|
||||
mModification(modArray),
|
||||
mNewRDN(newRDN),
|
||||
mNewBaseDN(newBaseDN),
|
||||
mFinished(false),
|
||||
mCanceled(false),
|
||||
mFlagRename(false),
|
||||
mServerSearchControls(serverSearchControls),
|
||||
mClientSearchControls(clientSearchControls)
|
||||
{
|
||||
if (mType == nsILDAPModification::MOD_REPLACE &&
|
||||
!mNewRDN.IsEmpty() && !mNewBaseDN.IsEmpty())
|
||||
mFlagRename = true;
|
||||
}
|
||||
|
||||
nsAbModifyLDAPMessageListener::~nsAbModifyLDAPMessageListener ()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsAbModifyLDAPMessageListener::Cancel ()
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (mFinished || mCanceled)
|
||||
return NS_OK;
|
||||
|
||||
mCanceled = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbModifyLDAPMessageListener::OnLDAPMessage(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t messageType;
|
||||
rv = aMessage->GetType(&messageType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool cancelOperation = false;
|
||||
|
||||
// Enter lock
|
||||
{
|
||||
MutexAutoLock lock (mLock);
|
||||
|
||||
if (mFinished)
|
||||
return NS_OK;
|
||||
|
||||
// for these messages, no matter the outcome, we're done
|
||||
if ((messageType == nsILDAPMessage::RES_ADD) ||
|
||||
(messageType == nsILDAPMessage::RES_DELETE) ||
|
||||
(messageType == nsILDAPMessage::RES_MODIFY))
|
||||
mFinished = true;
|
||||
else if (mCanceled)
|
||||
{
|
||||
mFinished = true;
|
||||
cancelOperation = true;
|
||||
}
|
||||
}
|
||||
// Leave lock
|
||||
|
||||
// nsCOMPtr<nsIAbDirectoryQueryResult> queryResult;
|
||||
if (!cancelOperation)
|
||||
{
|
||||
switch (messageType)
|
||||
{
|
||||
case nsILDAPMessage::RES_BIND:
|
||||
rv = OnLDAPMessageBind(aMessage);
|
||||
if (NS_FAILED(rv))
|
||||
// We know the bind failed and hence the message has an error, so we
|
||||
// can just call ModifyResult with the message and that'll sort it out
|
||||
// for us.
|
||||
rv = OnLDAPMessageModifyResult(aMessage);
|
||||
break;
|
||||
case nsILDAPMessage::RES_ADD:
|
||||
case nsILDAPMessage::RES_MODIFY:
|
||||
case nsILDAPMessage::RES_DELETE:
|
||||
rv = OnLDAPMessageModifyResult(aMessage);
|
||||
break;
|
||||
case nsILDAPMessage::RES_MODDN:
|
||||
mFlagRename = false;
|
||||
rv = OnLDAPMessageRenameResult(aMessage);
|
||||
if (NS_FAILED(rv))
|
||||
// Rename failed, so we stop here
|
||||
mFinished = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mModifyOperation)
|
||||
rv = mModifyOperation->AbandonExt();
|
||||
|
||||
// reset because we might re-use this listener...except don't do this
|
||||
// until the search is done, so we'll ignore results from a previous
|
||||
// search.
|
||||
mCanceled = mFinished = false;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsAbModifyLDAPMessageListener::InitFailed(bool aCancelled)
|
||||
{
|
||||
// XXX Just cancel the operation for now
|
||||
// we'll need to review this when we've got the proper listeners in place.
|
||||
Cancel();
|
||||
}
|
||||
|
||||
nsresult nsAbModifyLDAPMessageListener::DoTask()
|
||||
{
|
||||
nsresult rv;
|
||||
mCanceled = mFinished = false;
|
||||
|
||||
mModifyOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mModifyOperation->Init (mConnection, this, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX do we need the search controls?
|
||||
rv = mModifyOperation->SetServerControls(mServerSearchControls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mModifyOperation->SetClientControls(mClientSearchControls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mFlagRename)
|
||||
return mModifyOperation->Rename(mCardDN, mNewRDN, mNewBaseDN, true);
|
||||
|
||||
switch (mType)
|
||||
{
|
||||
case nsILDAPModification::MOD_ADD:
|
||||
return mModifyOperation->AddExt(mCardDN, mModification);
|
||||
case nsILDAPModification::MOD_DELETE:
|
||||
return mModifyOperation->DeleteExt(mCardDN);
|
||||
case nsILDAPModification::MOD_REPLACE:
|
||||
return mModifyOperation->ModifyExt(mCardDN, mModification);
|
||||
default:
|
||||
NS_ERROR("Bad LDAP modification requested");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsAbModifyLDAPMessageListener::OnLDAPMessageModifyResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
|
||||
int32_t errCode;
|
||||
rv = aMessage->GetErrorCode(&errCode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (errCode != nsILDAPErrors::SUCCESS)
|
||||
{
|
||||
nsAutoCString errMessage;
|
||||
rv = aMessage->GetErrorMessage(errMessage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf("LDAP modification failed (code: %i, message: %s)\n",
|
||||
errCode, errMessage.get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
printf("LDAP modification succeeded\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbModifyLDAPMessageListener::OnLDAPMessageRenameResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
|
||||
int32_t errCode;
|
||||
rv = aMessage->GetErrorCode(&errCode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (errCode != nsILDAPErrors::SUCCESS)
|
||||
{
|
||||
nsAutoCString errMessage;
|
||||
rv = aMessage->GetErrorMessage(errMessage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf("LDAP rename failed (code: %i, message: %s)\n",
|
||||
errCode, errMessage.get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Rename succeeded, now update the card DN and
|
||||
// process the main task
|
||||
mCardDN.Assign(mNewRDN);
|
||||
mCardDN.AppendLiteral(",");
|
||||
mCardDN.Append(mNewBaseDN);
|
||||
|
||||
printf("LDAP rename succeeded\n");
|
||||
return DoTask();
|
||||
}
|
||||
|
||||
nsAbLDAPDirectoryModify::nsAbLDAPDirectoryModify()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPDirectoryModify::~nsAbLDAPDirectoryModify()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPDirectoryModify::DoModify(nsIAbLDAPDirectory *directory,
|
||||
const int32_t &updateType,
|
||||
const nsACString &cardDN,
|
||||
nsIArray* modArray,
|
||||
const nsACString &newRDN,
|
||||
const nsACString &newBaseDN)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(directory);
|
||||
// modArray may be null in the delete operation case.
|
||||
if (!modArray &&
|
||||
(updateType == nsILDAPModification::MOD_ADD ||
|
||||
updateType == nsILDAPModification::MOD_REPLACE))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// it's an error if we don't have a dn
|
||||
if (cardDN.IsEmpty())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsILDAPURL> currentUrl;
|
||||
rv = directory->GetLDAPURL(getter_AddRefs(currentUrl));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the ldap connection
|
||||
nsCOMPtr<nsILDAPConnection> ldapConnection =
|
||||
do_CreateInstance(NS_LDAPCONNECTION_CONTRACTID, &rv);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> serverSearchControls;
|
||||
rv = directory->GetSearchServerControls(getter_AddRefs(serverSearchControls));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> clientSearchControls;
|
||||
rv = directory->GetSearchClientControls(getter_AddRefs(clientSearchControls));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
/*
|
||||
// XXX we need to fix how this all works - specifically, see the first patch
|
||||
// on bug 124553 for how the query equivalent did this
|
||||
// too soon? Do we need a new listener?
|
||||
if (alreadyInitialized)
|
||||
{
|
||||
nsAbQueryLDAPMessageListener *msgListener =
|
||||
NS_STATIC_CAST(nsAbQueryLDAPMessageListener *,
|
||||
NS_STATIC_CAST(nsILDAPMessageListener *, mListener.get()));
|
||||
if (msgListener)
|
||||
{
|
||||
msgListener->mUrl = url;
|
||||
return msgListener->DoSearch();
|
||||
}
|
||||
}*/
|
||||
|
||||
nsCString login;
|
||||
rv = directory->GetAuthDn(login);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t protocolVersion;
|
||||
rv = directory->GetProtocolVersion(&protocolVersion);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initiate LDAP message listener
|
||||
nsAbModifyLDAPMessageListener* _messageListener =
|
||||
new nsAbModifyLDAPMessageListener(updateType, cardDN, modArray,
|
||||
newRDN, newBaseDN,
|
||||
currentUrl,
|
||||
ldapConnection,
|
||||
serverSearchControls,
|
||||
clientSearchControls,
|
||||
login,
|
||||
0);
|
||||
if (_messageListener == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Now lets initialize the LDAP connection properly. We'll kick
|
||||
// off the bind operation in the callback function, |OnLDAPInit()|.
|
||||
return ldapConnection->Init(currentUrl, login,
|
||||
_messageListener, nullptr, protocolVersion);
|
||||
}
|
||||
|
||||
31
mailnews/addrbook/src/nsAbLDAPDirectoryModify.h
Normal file
31
mailnews/addrbook/src/nsAbLDAPDirectoryModify.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPDirectoryModify_h__
|
||||
#define nsAbLDAPDirectoryModify_h__
|
||||
|
||||
#include "nsAbLDAPListenerBase.h"
|
||||
#include "nsIAbLDAPDirectory.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsIArray.h"
|
||||
|
||||
class nsILDAPURL;
|
||||
|
||||
class nsAbLDAPDirectoryModify
|
||||
{
|
||||
public:
|
||||
nsAbLDAPDirectoryModify();
|
||||
virtual ~nsAbLDAPDirectoryModify();
|
||||
|
||||
protected:
|
||||
nsresult DoModify(nsIAbLDAPDirectory *directory,
|
||||
const int32_t &aUpdateType,
|
||||
const nsACString &aCardDN,
|
||||
nsIArray* modArray,
|
||||
const nsACString &aNewRDN,
|
||||
const nsACString &aNewBaseDN);
|
||||
};
|
||||
|
||||
#endif // nsAbLDAPDirectoryModify_h__
|
||||
610
mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp
Normal file
610
mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPDirectoryQuery.h"
|
||||
#include "nsAbBoolExprToLDAPFilter.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsIAbLDAPAttributeMap.h"
|
||||
#include "nsIAbLDAPCard.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "prprf.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsAbLDAPDirectory.h"
|
||||
#include "nsAbLDAPListenerBase.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// nsAbLDAPListenerBase inherits nsILDAPMessageListener
|
||||
class nsAbQueryLDAPMessageListener : public nsAbLDAPListenerBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// Note that the directoryUrl is the details of the ldap directory
|
||||
// without any search params or return attributes specified. The searchUrl
|
||||
// therefore has the search params and return attributes specified.
|
||||
// nsAbQueryLDAPMessageListener(nsIAbDirectoryQuery* directoryQuery,
|
||||
nsAbQueryLDAPMessageListener(nsIAbDirectoryQueryResultListener* resultListener,
|
||||
nsILDAPURL* directoryUrl,
|
||||
nsILDAPURL* searchUrl,
|
||||
nsILDAPConnection* connection,
|
||||
nsIAbDirectoryQueryArguments* queryArguments,
|
||||
nsIMutableArray* serverSearchControls,
|
||||
nsIMutableArray* clientSearchControls,
|
||||
const nsACString &login,
|
||||
const nsACString &mechanism,
|
||||
const int32_t resultLimit = -1,
|
||||
const int32_t timeOut = 0);
|
||||
|
||||
// nsILDAPMessageListener
|
||||
NS_IMETHOD OnLDAPMessage(nsILDAPMessage *aMessage) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsAbQueryLDAPMessageListener ();
|
||||
nsresult OnLDAPMessageSearchEntry(nsILDAPMessage *aMessage);
|
||||
nsresult OnLDAPMessageSearchResult(nsILDAPMessage *aMessage);
|
||||
|
||||
friend class nsAbLDAPDirectoryQuery;
|
||||
|
||||
nsresult Cancel();
|
||||
virtual nsresult DoTask() override;
|
||||
virtual void InitFailed(bool aCancelled = false) override;
|
||||
|
||||
nsCOMPtr<nsILDAPURL> mSearchUrl;
|
||||
nsIAbDirectoryQueryResultListener *mResultListener;
|
||||
int32_t mContextID;
|
||||
nsCOMPtr<nsIAbDirectoryQueryArguments> mQueryArguments;
|
||||
int32_t mResultLimit;
|
||||
|
||||
bool mFinished;
|
||||
bool mCanceled;
|
||||
bool mWaitingForPrevQueryToFinish;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> mServerSearchControls;
|
||||
nsCOMPtr<nsIMutableArray> mClientSearchControls;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbQueryLDAPMessageListener, nsILDAPMessageListener)
|
||||
|
||||
nsAbQueryLDAPMessageListener::nsAbQueryLDAPMessageListener(
|
||||
nsIAbDirectoryQueryResultListener *resultListener,
|
||||
nsILDAPURL* directoryUrl,
|
||||
nsILDAPURL* searchUrl,
|
||||
nsILDAPConnection* connection,
|
||||
nsIAbDirectoryQueryArguments* queryArguments,
|
||||
nsIMutableArray* serverSearchControls,
|
||||
nsIMutableArray* clientSearchControls,
|
||||
const nsACString &login,
|
||||
const nsACString &mechanism,
|
||||
const int32_t resultLimit,
|
||||
const int32_t timeOut) :
|
||||
nsAbLDAPListenerBase(directoryUrl, connection, login, timeOut),
|
||||
mSearchUrl(searchUrl),
|
||||
mResultListener(resultListener),
|
||||
mQueryArguments(queryArguments),
|
||||
mResultLimit(resultLimit),
|
||||
mFinished(false),
|
||||
mCanceled(false),
|
||||
mWaitingForPrevQueryToFinish(false),
|
||||
mServerSearchControls(serverSearchControls),
|
||||
mClientSearchControls(clientSearchControls)
|
||||
{
|
||||
mSaslMechanism.Assign(mechanism);
|
||||
}
|
||||
|
||||
nsAbQueryLDAPMessageListener::~nsAbQueryLDAPMessageListener ()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsAbQueryLDAPMessageListener::Cancel ()
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (mFinished || mCanceled)
|
||||
return NS_OK;
|
||||
|
||||
mCanceled = true;
|
||||
if (!mFinished)
|
||||
mWaitingForPrevQueryToFinish = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbQueryLDAPMessageListener::OnLDAPMessage(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsresult rv = Initiate();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t messageType;
|
||||
rv = aMessage->GetType(&messageType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool cancelOperation = false;
|
||||
|
||||
// Enter lock
|
||||
{
|
||||
MutexAutoLock lock (mLock);
|
||||
|
||||
if (mFinished)
|
||||
return NS_OK;
|
||||
|
||||
if (messageType == nsILDAPMessage::RES_SEARCH_RESULT)
|
||||
mFinished = true;
|
||||
else if (mCanceled)
|
||||
{
|
||||
mFinished = true;
|
||||
cancelOperation = true;
|
||||
}
|
||||
}
|
||||
// Leave lock
|
||||
|
||||
if (!mResultListener)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (!cancelOperation)
|
||||
{
|
||||
switch (messageType)
|
||||
{
|
||||
case nsILDAPMessage::RES_BIND:
|
||||
rv = OnLDAPMessageBind(aMessage);
|
||||
if (NS_FAILED(rv))
|
||||
// We know the bind failed and hence the message has an error, so we
|
||||
// can just call SearchResult with the message and that'll sort it out
|
||||
// for us.
|
||||
rv = OnLDAPMessageSearchResult(aMessage);
|
||||
break;
|
||||
case nsILDAPMessage::RES_SEARCH_ENTRY:
|
||||
if (!mFinished && !mWaitingForPrevQueryToFinish)
|
||||
rv = OnLDAPMessageSearchEntry(aMessage);
|
||||
break;
|
||||
case nsILDAPMessage::RES_SEARCH_RESULT:
|
||||
mWaitingForPrevQueryToFinish = false;
|
||||
rv = OnLDAPMessageSearchResult(aMessage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mOperation)
|
||||
rv = mOperation->AbandonExt();
|
||||
|
||||
rv = mResultListener->OnQueryResult(
|
||||
nsIAbDirectoryQueryResultListener::queryResultStopped, 0);
|
||||
|
||||
// reset because we might re-use this listener...except don't do this
|
||||
// until the search is done, so we'll ignore results from a previous
|
||||
// search.
|
||||
if (messageType == nsILDAPMessage::RES_SEARCH_RESULT)
|
||||
mCanceled = mFinished = false;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryLDAPMessageListener::DoTask()
|
||||
{
|
||||
nsresult rv;
|
||||
mCanceled = mFinished = false;
|
||||
|
||||
mOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOperation->Init(mConnection, this, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString dn;
|
||||
rv = mSearchUrl->GetDn(dn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t scope;
|
||||
rv = mSearchUrl->GetScope(&scope);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString filter;
|
||||
rv = mSearchUrl->GetFilter(filter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString attributes;
|
||||
rv = mSearchUrl->GetAttributes(attributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOperation->SetServerControls(mServerSearchControls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOperation->SetClientControls(mClientSearchControls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mOperation->SearchExt(dn, scope, filter, attributes, mTimeOut,
|
||||
mResultLimit);
|
||||
}
|
||||
|
||||
void nsAbQueryLDAPMessageListener::InitFailed(bool aCancelled)
|
||||
{
|
||||
if (!mResultListener)
|
||||
return;
|
||||
|
||||
// In the !aCancelled case we know there was an error, but we won't be
|
||||
// able to translate it, so just return an error code of zero.
|
||||
mResultListener->OnQueryResult(
|
||||
aCancelled ? nsIAbDirectoryQueryResultListener::queryResultStopped :
|
||||
nsIAbDirectoryQueryResultListener::queryResultError, 0);
|
||||
}
|
||||
|
||||
nsresult nsAbQueryLDAPMessageListener::OnLDAPMessageSearchEntry(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mResultListener)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// the map for translating between LDAP attrs <-> addrbook fields
|
||||
nsCOMPtr<nsISupports> iSupportsMap;
|
||||
rv = mQueryArguments->GetTypeSpecificArg(getter_AddRefs(iSupportsMap));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbLDAPAttributeMap> map = do_QueryInterface(iSupportsMap, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbCard> card = do_CreateInstance(NS_ABLDAPCARD_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = map->SetCardPropertiesFromLDAPMessage(aMessage, card);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbLDAPCard> ldapCard = do_QueryInterface(card, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ldapCard->SetMetaProperties(aMessage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mResultListener->OnQueryFoundCard(card);
|
||||
}
|
||||
|
||||
nsresult nsAbQueryLDAPMessageListener::OnLDAPMessageSearchResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
int32_t errorCode;
|
||||
nsresult rv = aMessage->GetErrorCode(&errorCode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (errorCode == nsILDAPErrors::SUCCESS || errorCode == nsILDAPErrors::SIZELIMIT_EXCEEDED)
|
||||
return mResultListener->OnQueryResult(
|
||||
nsIAbDirectoryQueryResultListener::queryResultComplete, 0);
|
||||
|
||||
return mResultListener->OnQueryResult(
|
||||
nsIAbDirectoryQueryResultListener::queryResultError, errorCode);
|
||||
}
|
||||
|
||||
// nsAbLDAPDirectoryQuery
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbLDAPDirectoryQuery, nsIAbDirectoryQuery,
|
||||
nsIAbDirectoryQueryResultListener)
|
||||
|
||||
nsAbLDAPDirectoryQuery::nsAbLDAPDirectoryQuery() :
|
||||
mInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPDirectoryQuery::~nsAbLDAPDirectoryQuery()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectoryQuery::DoQuery(nsIAbDirectory *aDirectory,
|
||||
nsIAbDirectoryQueryArguments* aArguments,
|
||||
nsIAbDirSearchListener* aListener,
|
||||
int32_t aResultLimit,
|
||||
int32_t aTimeOut,
|
||||
int32_t* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
NS_ENSURE_ARG_POINTER(aArguments);
|
||||
|
||||
mListeners.AppendObject(aListener);
|
||||
|
||||
// Ensure existing query is stopped. Context id doesn't matter here
|
||||
nsresult rv = StopQuery(0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
// Get the current directory as LDAP specific
|
||||
nsCOMPtr<nsIAbLDAPDirectory> directory(do_QueryInterface(aDirectory, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We also need the current URL to check as well...
|
||||
nsCOMPtr<nsILDAPURL> currentUrl;
|
||||
rv = directory->GetLDAPURL(getter_AddRefs(currentUrl));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString login;
|
||||
rv = directory->GetAuthDn(login);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString saslMechanism;
|
||||
rv = directory->GetSaslMechanism(saslMechanism);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t protocolVersion;
|
||||
rv = directory->GetProtocolVersion(&protocolVersion);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// To do:
|
||||
// Ensure query is stopped
|
||||
// If connection params have changed re-create connection
|
||||
// else reuse existing connection
|
||||
|
||||
bool redoConnection = false;
|
||||
|
||||
if (!mConnection || !mDirectoryUrl)
|
||||
{
|
||||
mDirectoryUrl = currentUrl;
|
||||
aDirectory->GetUuid(mDirectoryId);
|
||||
mCurrentLogin = login;
|
||||
mCurrentMechanism = saslMechanism;
|
||||
mCurrentProtocolVersion = protocolVersion;
|
||||
redoConnection = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool equal;
|
||||
rv = mDirectoryUrl->Equals(currentUrl, &equal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!equal)
|
||||
{
|
||||
mDirectoryUrl = currentUrl;
|
||||
aDirectory->GetUuid(mDirectoryId);
|
||||
mCurrentLogin = login;
|
||||
mCurrentMechanism = saslMechanism;
|
||||
mCurrentProtocolVersion = protocolVersion;
|
||||
redoConnection = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Has login or version changed?
|
||||
if (login != mCurrentLogin ||
|
||||
saslMechanism != mCurrentMechanism ||
|
||||
protocolVersion != mCurrentProtocolVersion)
|
||||
{
|
||||
redoConnection = true;
|
||||
mCurrentLogin = login;
|
||||
mCurrentMechanism = saslMechanism;
|
||||
mCurrentProtocolVersion = protocolVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = mDirectoryUrl->Clone(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsILDAPURL> url(do_QueryInterface(uri, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get/Set the return attributes
|
||||
nsCOMPtr<nsISupports> iSupportsMap;
|
||||
rv = aArguments->GetTypeSpecificArg(getter_AddRefs(iSupportsMap));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbLDAPAttributeMap> map = do_QueryInterface(iSupportsMap, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Require all attributes that are mapped to card properties
|
||||
nsAutoCString returnAttributes;
|
||||
rv = map->GetAllCardAttributes(returnAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = url->SetAttributes(returnAttributes);
|
||||
// Now do the error check
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Also require the objectClass attribute, it is used by
|
||||
// nsAbLDAPCard::SetMetaProperties
|
||||
rv = url->AddAttribute(NS_LITERAL_CSTRING("objectClass"));
|
||||
|
||||
nsAutoCString filter;
|
||||
|
||||
// Get filter from arguments if set:
|
||||
rv = aArguments->GetFilter(filter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (filter.IsEmpty()) {
|
||||
// Get the filter
|
||||
nsCOMPtr<nsISupports> supportsExpression;
|
||||
rv = aArguments->GetExpression(getter_AddRefs(supportsExpression));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanExpression> expression(do_QueryInterface(supportsExpression, &rv));
|
||||
|
||||
// figure out how we map attribute names to addressbook fields for this
|
||||
// query
|
||||
rv = nsAbBoolExprToLDAPFilter::Convert(map, expression, filter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mozilla itself cannot arrive here with a blank filter
|
||||
* as the nsAbLDAPDirectory::StartSearch() disallows it.
|
||||
* But 3rd party LDAP query integration with Mozilla begins
|
||||
* in this method.
|
||||
*
|
||||
* Default the filter string if blank, otherwise it gets
|
||||
* set to (objectclass=*) which returns everything. Set
|
||||
* the default to (objectclass=inetorgperson) as this
|
||||
* is the most appropriate default objectclass which is
|
||||
* central to the makeup of the mozilla ldap address book
|
||||
* entries.
|
||||
*/
|
||||
if (filter.IsEmpty())
|
||||
{
|
||||
filter.AssignLiteral("(objectclass=inetorgperson)");
|
||||
}
|
||||
|
||||
// get the directoryFilter from the directory url and merge it with the user's
|
||||
// search filter
|
||||
nsAutoCString urlFilter;
|
||||
rv = mDirectoryUrl->GetFilter(urlFilter);
|
||||
|
||||
// if urlFilter is unset (or set to the default "objectclass=*"), there's
|
||||
// no need to AND in an empty search term, so leave prefix and suffix empty
|
||||
|
||||
nsAutoCString searchFilter;
|
||||
if (urlFilter.Length() && !urlFilter.EqualsLiteral("(objectclass=*)"))
|
||||
{
|
||||
// if urlFilter isn't parenthesized, we need to add in parens so that
|
||||
// the filter works as a term to &
|
||||
//
|
||||
if (urlFilter[0] != '(')
|
||||
{
|
||||
searchFilter = NS_LITERAL_CSTRING("(&(");
|
||||
searchFilter.Append(urlFilter);
|
||||
searchFilter.AppendLiteral(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
searchFilter = NS_LITERAL_CSTRING("(&");
|
||||
searchFilter.Append(urlFilter);
|
||||
}
|
||||
|
||||
searchFilter += filter;
|
||||
searchFilter += ')';
|
||||
}
|
||||
else
|
||||
searchFilter = filter;
|
||||
|
||||
rv = url->SetFilter(searchFilter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now formulate the search string
|
||||
|
||||
// Get the scope
|
||||
int32_t scope;
|
||||
bool doSubDirectories;
|
||||
rv = aArguments->GetQuerySubDirectories (&doSubDirectories);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
scope = doSubDirectories ? nsILDAPURL::SCOPE_SUBTREE :
|
||||
nsILDAPURL::SCOPE_ONELEVEL;
|
||||
|
||||
rv = url->SetScope(scope);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// too soon? Do we need a new listener?
|
||||
// If we already have a connection, and don't need to re-do it, give it the
|
||||
// new search details and go for it...
|
||||
if (!redoConnection)
|
||||
{
|
||||
nsAbQueryLDAPMessageListener *msgListener =
|
||||
static_cast<nsAbQueryLDAPMessageListener *>(static_cast<nsILDAPMessageListener *>(mListener.get()));
|
||||
if (msgListener)
|
||||
{
|
||||
// Ensure the urls are correct
|
||||
msgListener->mDirectoryUrl = mDirectoryUrl;
|
||||
msgListener->mSearchUrl = url;
|
||||
// Also ensure we set the correct result limit
|
||||
msgListener->mResultLimit = aResultLimit;
|
||||
return msgListener->DoTask();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAbLDAPDirectory> abLDAPDir = do_QueryInterface(aDirectory, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> serverSearchControls;
|
||||
rv = abLDAPDir->GetSearchServerControls(getter_AddRefs(serverSearchControls));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> clientSearchControls;
|
||||
rv = abLDAPDir->GetSearchClientControls(getter_AddRefs(clientSearchControls));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create the new connection (which cause the old one to be dropped if necessary)
|
||||
mConnection = do_CreateInstance(NS_LDAPCONNECTION_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectoryQueryResultListener> resultListener =
|
||||
do_QueryInterface((nsIAbDirectoryQuery*)this, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initiate LDAP message listener
|
||||
nsAbQueryLDAPMessageListener* _messageListener =
|
||||
new nsAbQueryLDAPMessageListener(resultListener, mDirectoryUrl, url,
|
||||
mConnection, aArguments,
|
||||
serverSearchControls, clientSearchControls,
|
||||
mCurrentLogin, mCurrentMechanism,
|
||||
aResultLimit, aTimeOut);
|
||||
if (_messageListener == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mListener = _messageListener;
|
||||
*_retval = 1;
|
||||
|
||||
// Now lets initialize the LDAP connection properly. We'll kick
|
||||
// off the bind operation in the callback function, |OnLDAPInit()|.
|
||||
rv = mConnection->Init(mDirectoryUrl, mCurrentLogin,
|
||||
mListener, nullptr, mCurrentProtocolVersion);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void stopQuery (in long contextID); */
|
||||
NS_IMETHODIMP nsAbLDAPDirectoryQuery::StopQuery(int32_t contextID)
|
||||
{
|
||||
mInitialized = true;
|
||||
|
||||
if (!mListener)
|
||||
return NS_OK;
|
||||
|
||||
nsAbQueryLDAPMessageListener *listener =
|
||||
static_cast<nsAbQueryLDAPMessageListener *>(static_cast<nsILDAPMessageListener *>(mListener.get()));
|
||||
if (listener)
|
||||
return listener->Cancel();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectoryQuery::OnQueryFoundCard(nsIAbCard *aCard)
|
||||
{
|
||||
aCard->SetDirectoryId(mDirectoryId);
|
||||
|
||||
for (int32_t i = 0; i < mListeners.Count(); ++i)
|
||||
mListeners[i]->OnSearchFoundCard(aCard);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPDirectoryQuery::OnQueryResult(int32_t aResult,
|
||||
int32_t aErrorCode)
|
||||
{
|
||||
uint32_t count = mListeners.Count();
|
||||
|
||||
// XXX: Temporary fix for crasher needs reviewing as part of bug 135231.
|
||||
// Temporarily add a reference to ourselves, in case the only thing
|
||||
// keeping us alive is the link with the listener.
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
for (int32_t i = count - 1; i >= 0; --i)
|
||||
{
|
||||
mListeners[i]->OnSearchFinished(aResult, EmptyString());
|
||||
mListeners.RemoveObjectAt(i);
|
||||
}
|
||||
|
||||
NS_RELEASE_THIS();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
44
mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h
Normal file
44
mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPDirectoryQuery_h__
|
||||
#define nsAbLDAPDirectoryQuery_h__
|
||||
|
||||
#include "nsIAbDirectoryQuery.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsAbLDAPDirectoryQuery : public nsIAbDirectoryQuery,
|
||||
public nsIAbDirectoryQueryResultListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABDIRECTORYQUERY
|
||||
NS_DECL_NSIABDIRECTORYQUERYRESULTLISTENER
|
||||
|
||||
nsAbLDAPDirectoryQuery();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsILDAPMessageListener> mListener;
|
||||
|
||||
private:
|
||||
virtual ~nsAbLDAPDirectoryQuery();
|
||||
nsCOMPtr<nsILDAPConnection> mConnection;
|
||||
nsCOMPtr<nsILDAPURL> mDirectoryUrl;
|
||||
nsCString mDirectoryId;
|
||||
nsCOMArray<nsIAbDirSearchListener> mListeners;
|
||||
nsCString mCurrentLogin;
|
||||
nsCString mCurrentMechanism;
|
||||
uint32_t mCurrentProtocolVersion;
|
||||
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
#endif // nsAbLDAPDirectoryQuery_h__
|
||||
358
mailnews/addrbook/src/nsAbLDAPListenerBase.cpp
Normal file
358
mailnews/addrbook/src/nsAbLDAPListenerBase.cpp
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbLDAPListenerBase.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsILoginInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsMemory.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsAbLDAPListenerBase::nsAbLDAPListenerBase(nsILDAPURL* url,
|
||||
nsILDAPConnection* connection,
|
||||
const nsACString &login,
|
||||
const int32_t timeOut) :
|
||||
mDirectoryUrl(url), mConnection(connection), mLogin(login),
|
||||
mTimeOut(timeOut), mBound(false), mInitialized(false),
|
||||
mLock("nsAbLDAPListenerBase.mLock")
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPListenerBase::~nsAbLDAPListenerBase()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPListenerBase::Initiate()
|
||||
{
|
||||
if (!mConnection || !mDirectoryUrl)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mInitialized)
|
||||
return NS_OK;
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If something fails in this function, we must call InitFailed() so that the
|
||||
// derived class (and listener) knows to cancel what its doing as there is
|
||||
// a problem.
|
||||
NS_IMETHODIMP nsAbLDAPListenerBase::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus)
|
||||
{
|
||||
if (!mConnection || !mDirectoryUrl)
|
||||
{
|
||||
InitFailed();
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsString passwd;
|
||||
|
||||
// Make sure that the Init() worked properly
|
||||
if (NS_FAILED(aStatus))
|
||||
{
|
||||
InitFailed();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If mLogin is set, we're expected to use it to get a password.
|
||||
//
|
||||
if (!mLogin.IsEmpty() && !mSaslMechanism.EqualsLiteral("GSSAPI"))
|
||||
{
|
||||
// get the string bundle service
|
||||
//
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleSvc =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (!stringBundleSvc)
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit():"
|
||||
" error getting string bundle service");
|
||||
InitFailed();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// get the LDAP string bundle
|
||||
//
|
||||
nsCOMPtr<nsIStringBundle> ldapBundle;
|
||||
rv = stringBundleSvc->CreateBundle("chrome://mozldap/locale/ldap.properties",
|
||||
getter_AddRefs(ldapBundle));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit(): error creating string"
|
||||
"bundle chrome://mozldap/locale/ldap.properties");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the title for the authentication prompt
|
||||
//
|
||||
nsString authPromptTitle;
|
||||
rv = ldapBundle->GetStringFromName(u"authPromptTitle",
|
||||
getter_Copies(authPromptTitle));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit(): error getting"
|
||||
"'authPromptTitle' string from bundle "
|
||||
"chrome://mozldap/locale/ldap.properties");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the host name for the auth prompt
|
||||
//
|
||||
nsAutoCString host;
|
||||
rv = mDirectoryUrl->GetAsciiHost(host);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit(): error getting ascii host"
|
||||
"name from directory url");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// hostTemp is only necessary to work around a code-generation
|
||||
// bug in egcs 1.1.2 (the version of gcc that comes with Red Hat 6.2),
|
||||
// which is the default compiler for Mozilla on linux at the moment.
|
||||
//
|
||||
NS_ConvertASCIItoUTF16 hostTemp(host);
|
||||
const char16_t *hostArray[1] = { hostTemp.get() };
|
||||
|
||||
// format the hostname into the authprompt text string
|
||||
//
|
||||
nsString authPromptText;
|
||||
rv = ldapBundle->FormatStringFromName(u"authPromptText",
|
||||
hostArray,
|
||||
sizeof(hostArray) / sizeof(const char16_t *),
|
||||
getter_Copies(authPromptText));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit():"
|
||||
"error getting 'authPromptText' string from bundle "
|
||||
"chrome://mozldap/locale/ldap.properties");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the window mediator service, so we can get an auth prompter
|
||||
//
|
||||
nsCOMPtr<nsIWindowMediator> windowMediator =
|
||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit():"
|
||||
" couldn't get window mediator service.");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the addressbook window, as it will be used to parent the auth
|
||||
// prompter dialog
|
||||
//
|
||||
nsCOMPtr<mozIDOMWindowProxy> window;
|
||||
rv = windowMediator->GetMostRecentWindow(nullptr,
|
||||
getter_AddRefs(window));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit():"
|
||||
" error getting most recent window");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the window watcher service, so we can get an auth prompter
|
||||
//
|
||||
nsCOMPtr<nsIWindowWatcher> windowWatcherSvc =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPListenerBase::OnLDAPInit():"
|
||||
" couldn't get window watcher service.");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get the auth prompter itself
|
||||
//
|
||||
nsCOMPtr<nsIAuthPrompt> authPrompter;
|
||||
rv = windowWatcherSvc->GetNewAuthPrompter(window,
|
||||
getter_AddRefs(authPrompter));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit():"
|
||||
" error getting auth prompter");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// get authentication password, prompting the user if necessary
|
||||
//
|
||||
// we're going to use the URL spec of the server as the "realm" for
|
||||
// wallet to remember the password by / for.
|
||||
|
||||
// Get the specification
|
||||
nsCString spec;
|
||||
rv = mDirectoryUrl->GetSpec(spec);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit():"
|
||||
" error getting directory url spec");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool status;
|
||||
rv = authPrompter->PromptPassword(authPromptTitle.get(),
|
||||
authPromptText.get(),
|
||||
NS_ConvertUTF8toUTF16(spec).get(),
|
||||
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
||||
getter_Copies(passwd),
|
||||
&status);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit(): failed to prompt for"
|
||||
" password");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
else if (!status)
|
||||
{
|
||||
InitFailed(true);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Initiate the LDAP operation
|
||||
mOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit(): failed to create ldap operation");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mOperation->Init(mConnection, this, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit(): failed to Initialise operation");
|
||||
InitFailed();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Try non-password mechanisms first
|
||||
if (mSaslMechanism.EqualsLiteral("GSSAPI"))
|
||||
{
|
||||
nsAutoCString service;
|
||||
rv = mDirectoryUrl->GetAsciiHost(service);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
service.Insert(NS_LITERAL_CSTRING("ldap@"), 0);
|
||||
|
||||
nsCOMPtr<nsIAuthModule> authModule =
|
||||
do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "sasl-gssapi", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOperation->SaslBind(service, mSaslMechanism, authModule);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit(): "
|
||||
"failed to perform GSSAPI bind");
|
||||
mOperation = nullptr; // Break Listener -> Operation -> Listener ref cycle
|
||||
InitFailed();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Bind
|
||||
rv = mOperation->SimpleBind(NS_ConvertUTF16toUTF8(passwd));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("nsAbLDAPMessageBase::OnLDAPInit(): failed to perform bind operation");
|
||||
mOperation = nullptr; // Break Listener->Operation->Listener reference cycle
|
||||
InitFailed();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPListenerBase::OnLDAPMessageBind(nsILDAPMessage *aMessage)
|
||||
{
|
||||
if (mBound)
|
||||
return NS_OK;
|
||||
|
||||
// see whether the bind actually succeeded
|
||||
//
|
||||
int32_t errCode;
|
||||
nsresult rv = aMessage->GetErrorCode(&errCode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (errCode != nsILDAPErrors::SUCCESS)
|
||||
{
|
||||
// if the login failed, tell the wallet to forget this password
|
||||
//
|
||||
if (errCode == nsILDAPErrors::INAPPROPRIATE_AUTH ||
|
||||
errCode == nsILDAPErrors::INVALID_CREDENTIALS)
|
||||
{
|
||||
// Login failed, so try again - but first remove the existing login(s)
|
||||
// so that the user gets prompted. This may not be the best way of doing
|
||||
// things, we need to review that later.
|
||||
|
||||
nsCOMPtr<nsILoginManager> loginMgr =
|
||||
do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString spec;
|
||||
rv = mDirectoryUrl->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString prePath;
|
||||
rv = mDirectoryUrl->GetPrePath(prePath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t count;
|
||||
nsILoginInfo** logins;
|
||||
|
||||
rv = loginMgr->FindLogins(&count, NS_ConvertUTF8toUTF16(prePath),
|
||||
EmptyString(),
|
||||
NS_ConvertUTF8toUTF16(spec), &logins);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Typically there should only be one-login stored for this url, however,
|
||||
// just in case there isn't.
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
rv = loginMgr->RemoveLogin(logins[i]);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
||||
|
||||
// XXX We should probably pop up an error dialog telling
|
||||
// the user that the login failed here, rather than just bringing
|
||||
// up the password dialog again, which is what calling OnLDAPInit()
|
||||
// does.
|
||||
return OnLDAPInit(nullptr, NS_OK);
|
||||
}
|
||||
|
||||
// Don't know how to handle this, so use the message error code in
|
||||
// the failure return value so we hopefully get it back to the UI.
|
||||
return NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, errCode);
|
||||
}
|
||||
|
||||
mBound = true;
|
||||
return DoTask();
|
||||
}
|
||||
54
mailnews/addrbook/src/nsAbLDAPListenerBase.h
Normal file
54
mailnews/addrbook/src/nsAbLDAPListenerBase.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbLDAPListenerBase_h__
|
||||
#define nsAbLDAPListenerBase_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
class nsAbLDAPListenerBase : public nsILDAPMessageListener
|
||||
{
|
||||
public:
|
||||
// Note that the directoryUrl is the details of the ldap directory
|
||||
// without any search params or attributes specified.
|
||||
nsAbLDAPListenerBase(nsILDAPURL* directoryUrl = nullptr,
|
||||
nsILDAPConnection* connection = nullptr,
|
||||
const nsACString &login = EmptyCString(),
|
||||
const int32_t timeOut = 0);
|
||||
virtual ~nsAbLDAPListenerBase();
|
||||
|
||||
NS_IMETHOD OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus) override;
|
||||
|
||||
protected:
|
||||
nsresult OnLDAPMessageBind(nsILDAPMessage *aMessage);
|
||||
|
||||
nsresult Initiate();
|
||||
|
||||
// Called if an LDAP initialization fails.
|
||||
virtual void InitFailed(bool aCancelled = false) = 0;
|
||||
|
||||
// Called to start off the required task after a bind.
|
||||
virtual nsresult DoTask() = 0;
|
||||
|
||||
nsCOMPtr<nsILDAPURL> mDirectoryUrl;
|
||||
nsCOMPtr<nsILDAPOperation> mOperation; // current ldap op
|
||||
nsILDAPConnection* mConnection;
|
||||
nsCString mLogin;
|
||||
nsCString mSaslMechanism;
|
||||
int32_t mTimeOut;
|
||||
bool mBound;
|
||||
bool mInitialized;
|
||||
|
||||
mozilla::Mutex mLock;
|
||||
};
|
||||
|
||||
#endif
|
||||
489
mailnews/addrbook/src/nsAbLDAPReplicationData.cpp
Normal file
489
mailnews/addrbook/src/nsAbLDAPReplicationData.cpp
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsAbLDAPReplicationData.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsAbLDAPReplicationQuery.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
// once bug # 101252 gets fixed, this should be reverted back to be non threadsafe
|
||||
// implementation is not really thread safe since each object should exist
|
||||
// independently along with its related independent nsAbLDAPReplicationQuery object.
|
||||
NS_IMPL_ISUPPORTS(nsAbLDAPProcessReplicationData, nsIAbLDAPProcessReplicationData, nsILDAPMessageListener)
|
||||
|
||||
nsAbLDAPProcessReplicationData::nsAbLDAPProcessReplicationData() :
|
||||
nsAbLDAPListenerBase(),
|
||||
mState(kIdle),
|
||||
mProtocol(-1),
|
||||
mCount(0),
|
||||
mDBOpen(false),
|
||||
mInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPProcessReplicationData::~nsAbLDAPProcessReplicationData()
|
||||
{
|
||||
/* destructor code */
|
||||
if(mDBOpen && mReplicationDB)
|
||||
mReplicationDB->Close(false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessReplicationData::Init(
|
||||
nsIAbLDAPDirectory *aDirectory,
|
||||
nsILDAPConnection *aConnection,
|
||||
nsILDAPURL* aURL,
|
||||
nsIAbLDAPReplicationQuery *aQuery,
|
||||
nsIWebProgressListener *aProgressListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
NS_ENSURE_ARG_POINTER(aConnection);
|
||||
NS_ENSURE_ARG_POINTER(aURL);
|
||||
NS_ENSURE_ARG_POINTER(aQuery);
|
||||
|
||||
mDirectory = aDirectory;
|
||||
mConnection = aConnection;
|
||||
mDirectoryUrl = aURL;
|
||||
mQuery = aQuery;
|
||||
|
||||
mListener = aProgressListener;
|
||||
|
||||
nsresult rv = mDirectory->GetAttributeMap(getter_AddRefs(mAttrMap));
|
||||
if (NS_FAILED(rv)) {
|
||||
mQuery = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mDirectory->GetAuthDn(mLogin);
|
||||
if (NS_FAILED(rv)) {
|
||||
mQuery = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mDirectory->GetSaslMechanism(mSaslMechanism);
|
||||
if (NS_FAILED(rv)) {
|
||||
mQuery = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessReplicationData::GetReplicationState(int32_t *aReplicationState)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aReplicationState);
|
||||
*aReplicationState = mState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessReplicationData::GetProtocolUsed(int32_t *aProtocolUsed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aProtocolUsed);
|
||||
*aProtocolUsed = mProtocol;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessReplicationData::OnLDAPMessage(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
int32_t messageType;
|
||||
nsresult rv = aMessage->GetType(&messageType);
|
||||
if (NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case nsILDAPMessage::RES_BIND:
|
||||
rv = OnLDAPMessageBind(aMessage);
|
||||
if (NS_FAILED(rv))
|
||||
rv = Abort();
|
||||
break;
|
||||
case nsILDAPMessage::RES_SEARCH_ENTRY:
|
||||
rv = OnLDAPSearchEntry(aMessage);
|
||||
break;
|
||||
case nsILDAPMessage::RES_SEARCH_RESULT:
|
||||
rv = OnLDAPSearchResult(aMessage);
|
||||
break;
|
||||
default:
|
||||
// for messageTypes we do not handle return NS_OK to LDAP and move ahead.
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPProcessReplicationData::Abort()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mState != kIdle && mOperation) {
|
||||
rv = mOperation->AbandonExt();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mState = kIdle;
|
||||
}
|
||||
|
||||
if (mReplicationDB && mDBOpen) {
|
||||
// force close since we need to delete the file.
|
||||
mReplicationDB->ForceClosed();
|
||||
mDBOpen = false;
|
||||
|
||||
// delete the unsaved replication file
|
||||
if (mReplicationFile) {
|
||||
rv = mReplicationFile->Remove(false);
|
||||
if (NS_SUCCEEDED(rv) && mDirectory) {
|
||||
nsAutoCString fileName;
|
||||
rv = mDirectory->GetReplicationFileName(fileName);
|
||||
// now put back the backed up replicated file if aborted
|
||||
if (NS_SUCCEEDED(rv) && mBackupReplicationFile)
|
||||
rv = mBackupReplicationFile->MoveToNative(nullptr, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Done(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessReplicationData::DoTask()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = OpenABForReplicatedDir(true);
|
||||
if (NS_FAILED(rv))
|
||||
// do not call done here since it is called by OpenABForReplicationDir
|
||||
return rv;
|
||||
|
||||
mOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOperation->Init(mConnection, this, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// get the relevant attributes associated with the directory server url
|
||||
nsAutoCString urlFilter;
|
||||
rv = mDirectoryUrl->GetFilter(urlFilter);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString dn;
|
||||
rv = mDirectoryUrl->GetDn(dn);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (dn.IsEmpty())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
int32_t scope;
|
||||
rv = mDirectoryUrl->GetScope(&scope);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoCString attributes;
|
||||
rv = mDirectoryUrl->GetAttributes(attributes);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mState = kReplicatingAll;
|
||||
|
||||
if (mListener && NS_SUCCEEDED(rv))
|
||||
// XXX Cast from bool to nsresult
|
||||
mListener->OnStateChange(nullptr, nullptr,
|
||||
nsIWebProgressListener::STATE_START,
|
||||
static_cast<nsresult>(true));
|
||||
|
||||
return mOperation->SearchExt(dn, scope, urlFilter, attributes, 0, 0);
|
||||
}
|
||||
|
||||
void nsAbLDAPProcessReplicationData::InitFailed(bool aCancelled)
|
||||
{
|
||||
// Just call Done() which will ensure everything is tidied up nicely.
|
||||
Done(false);
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessReplicationData::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
// since this runs on the main thread and is single threaded, this will
|
||||
// take care of entries returned by LDAP Connection thread after Abort.
|
||||
if (!mReplicationDB || !mDBOpen)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Although we would may naturally create an nsIAbLDAPCard here, we don't
|
||||
// need to as we are writing this straight to the database, so just create
|
||||
// the database version instead.
|
||||
nsCOMPtr<nsIAbCard> newCard(do_CreateInstance(NS_ABMDBCARD_CONTRACTID,
|
||||
&rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
Abort();
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mAttrMap->SetCardPropertiesFromLDAPMessage(aMessage, newCard);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_WARNING("nsAbLDAPProcessReplicationData::OnLDAPSearchEntry"
|
||||
"No card properties could be set");
|
||||
// if some entries are bogus for us, continue with next one
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mReplicationDB->CreateNewCardAndAddToDB(newCard, false, nullptr);
|
||||
if(NS_FAILED(rv)) {
|
||||
Abort();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// now set the attribute for the DN of the entry in the card in the DB
|
||||
nsAutoCString authDN;
|
||||
rv = aMessage->GetDn(authDN);
|
||||
if(NS_SUCCEEDED(rv) && !authDN.IsEmpty())
|
||||
{
|
||||
newCard->SetPropertyAsAUTF8String("_DN", authDN);
|
||||
}
|
||||
|
||||
rv = mReplicationDB->EditCard(newCard, false, nullptr);
|
||||
if(NS_FAILED(rv)) {
|
||||
Abort();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
mCount ++;
|
||||
|
||||
if (mListener && !(mCount % 10)) // inform the listener every 10 entries
|
||||
{
|
||||
mListener->OnProgressChange(nullptr,nullptr,mCount, -1, mCount, -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
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsAbLDAPProcessReplicationData::OnLDAPSearchResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
#ifdef DEBUG_rdayal
|
||||
printf("LDAP Replication : Got Results for Completion");
|
||||
#endif
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
if(!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
int32_t errorCode;
|
||||
nsresult rv = aMessage->GetErrorCode(&errorCode);
|
||||
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
// We are done with the LDAP search for all entries.
|
||||
if(errorCode == nsILDAPErrors::SUCCESS || errorCode == nsILDAPErrors::SIZELIMIT_EXCEEDED) {
|
||||
Done(true);
|
||||
if(mReplicationDB && mDBOpen) {
|
||||
rv = mReplicationDB->Close(true);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB Close on Success failed");
|
||||
mDBOpen = false;
|
||||
// once we have saved the new replication file, delete the backup file
|
||||
if(mBackupReplicationFile)
|
||||
{
|
||||
rv = mBackupReplicationFile->Remove(false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication BackupFile Remove on Success failed");
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// in case if GetErrorCode returned error or errorCode is not SUCCESS / SIZELIMIT_EXCEEDED
|
||||
if(mReplicationDB && mDBOpen) {
|
||||
// if error result is returned close the DB without saving ???
|
||||
// should we commit anyway ??? whatever is returned is not lost then !!
|
||||
rv = mReplicationDB->ForceClosed(); // force close since we need to delete the file.
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication DB ForceClosed on Failure failed");
|
||||
mDBOpen = false;
|
||||
// if error result is returned remove the replicated file
|
||||
if(mReplicationFile) {
|
||||
rv = mReplicationFile->Remove(false);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication File Remove on Failure failed");
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
// now put back the backed up replicated file
|
||||
if(mBackupReplicationFile && mDirectory)
|
||||
{
|
||||
nsAutoCString fileName;
|
||||
rv = mDirectory->GetReplicationFileName(fileName);
|
||||
if (NS_SUCCEEDED(rv) && !fileName.IsEmpty())
|
||||
{
|
||||
rv = mBackupReplicationFile->MoveToNative(nullptr, fileName);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Replication Backup File Move back on Failure failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Done(false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessReplicationData::OpenABForReplicatedDir(bool aCreate)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = mDirectory->GetReplicationFile(getter_AddRefs(mReplicationFile));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
Done(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString fileName;
|
||||
rv = mReplicationFile->GetNativeLeafName(fileName);
|
||||
if (NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// if the AB DB already exists backup existing one,
|
||||
// in case if the user cancels or Abort put back the backed up file
|
||||
bool fileExists;
|
||||
rv = mReplicationFile->Exists(&fileExists);
|
||||
if(NS_SUCCEEDED(rv) && fileExists) {
|
||||
// create the backup file object same as the Replication file object.
|
||||
// we create a backup file here since we need to cleanup the existing file
|
||||
// for create and then commit so instead of deleting existing cards we just
|
||||
// clone the existing one for a much better performance - for Download All.
|
||||
// And also important in case if replication fails we donot lose user's existing
|
||||
// replicated data for both Download all and Changelog.
|
||||
nsCOMPtr<nsIFile> clone;
|
||||
rv = mReplicationFile->Clone(getter_AddRefs(clone));
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
mBackupReplicationFile = do_QueryInterface(clone, &rv);
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
rv = mBackupReplicationFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0777);
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
nsAutoString backupFileLeafName;
|
||||
rv = mBackupReplicationFile->GetLeafName(backupFileLeafName);
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
// remove the newly created unique backup file so that move and copy succeeds.
|
||||
rv = mBackupReplicationFile->Remove(false);
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(aCreate) {
|
||||
// set backup file to existing replication file for move
|
||||
mBackupReplicationFile->SetNativeLeafName(fileName);
|
||||
|
||||
rv = mBackupReplicationFile->MoveTo(nullptr, backupFileLeafName);
|
||||
// set the backup file leaf name now
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mBackupReplicationFile->SetLeafName(backupFileLeafName);
|
||||
}
|
||||
else {
|
||||
// set backup file to existing replication file for copy
|
||||
mBackupReplicationFile->SetNativeLeafName(fileName);
|
||||
|
||||
// specify the parent here specifically,
|
||||
// passing nullptr to copy to the same dir actually renames existing file
|
||||
// instead of making another copy of the existing file.
|
||||
nsCOMPtr<nsIFile> parent;
|
||||
rv = mBackupReplicationFile->GetParent(getter_AddRefs(parent));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = mBackupReplicationFile->CopyTo(parent, backupFileLeafName);
|
||||
// set the backup file leaf name now
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mBackupReplicationFile->SetLeafName(backupFileLeafName);
|
||||
}
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAddrDatabase> addrDBFactory =
|
||||
do_GetService(NS_ADDRDATABASE_CONTRACTID, &rv);
|
||||
if(NS_FAILED(rv)) {
|
||||
if (mBackupReplicationFile)
|
||||
mBackupReplicationFile->Remove(false);
|
||||
Done(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = addrDBFactory->Open(mReplicationFile, aCreate, true, getter_AddRefs(mReplicationDB));
|
||||
if(NS_FAILED(rv)) {
|
||||
Done(false);
|
||||
if (mBackupReplicationFile)
|
||||
mBackupReplicationFile->Remove(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDBOpen = true; // replication DB is now Open
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsAbLDAPProcessReplicationData::Done(bool aSuccess)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return;
|
||||
|
||||
mState = kReplicationDone;
|
||||
|
||||
if (mQuery)
|
||||
mQuery->Done(aSuccess);
|
||||
|
||||
if (mListener)
|
||||
// XXX Cast from bool to nsresult
|
||||
mListener->OnStateChange(nullptr, nullptr,
|
||||
nsIWebProgressListener::STATE_STOP,
|
||||
static_cast<nsresult>(aSuccess));
|
||||
|
||||
// since this is called when all is done here, either on success,
|
||||
// failure or abort release the query now.
|
||||
mQuery = nullptr;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPProcessReplicationData::DeleteCard(nsString & aDn)
|
||||
{
|
||||
nsCOMPtr<nsIAbCard> cardToDelete;
|
||||
mReplicationDB->GetCardFromAttribute(nullptr, "_DN", NS_ConvertUTF16toUTF8(aDn),
|
||||
false, getter_AddRefs(cardToDelete));
|
||||
return mReplicationDB->DeleteCard(cardToDelete, false, nullptr);
|
||||
}
|
||||
66
mailnews/addrbook/src/nsAbLDAPReplicationData.h
Normal file
66
mailnews/addrbook/src/nsAbLDAPReplicationData.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef nsAbLDAPReplicationData_h__
|
||||
#define nsAbLDAPReplicationData_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIAbLDAPReplicationData.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIAbLDAPReplicationQuery.h"
|
||||
#include "nsAbLDAPListenerBase.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsIAbLDAPAttributeMap.h"
|
||||
#include "nsIAbLDAPDirectory.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsAbLDAPProcessReplicationData : public nsIAbLDAPProcessReplicationData,
|
||||
public nsAbLDAPListenerBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABLDAPPROCESSREPLICATIONDATA
|
||||
|
||||
nsAbLDAPProcessReplicationData();
|
||||
|
||||
// nsILDAPMessageListener
|
||||
NS_IMETHOD OnLDAPMessage(nsILDAPMessage *aMessage) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsAbLDAPProcessReplicationData();
|
||||
virtual nsresult DoTask() override;
|
||||
virtual void InitFailed(bool aCancelled = false) override;
|
||||
|
||||
// pointer to the interfaces used by this object
|
||||
nsCOMPtr<nsIWebProgressListener> mListener;
|
||||
// pointer to the query to call back to once we've finished
|
||||
nsCOMPtr<nsIAbLDAPReplicationQuery> mQuery;
|
||||
|
||||
nsCOMPtr<nsIAddrDatabase> mReplicationDB;
|
||||
nsCOMPtr <nsIFile> mReplicationFile;
|
||||
nsCOMPtr <nsIFile> mBackupReplicationFile;
|
||||
|
||||
// state of processing, protocol used and count of results
|
||||
int32_t mState;
|
||||
int32_t mProtocol;
|
||||
int32_t mCount;
|
||||
bool mDBOpen;
|
||||
bool mInitialized;
|
||||
|
||||
nsCOMPtr<nsIAbLDAPDirectory> mDirectory;
|
||||
nsCOMPtr<nsIAbLDAPAttributeMap> mAttrMap; // maps ab properties to ldap attrs
|
||||
|
||||
virtual nsresult OnLDAPSearchEntry(nsILDAPMessage *aMessage);
|
||||
virtual nsresult OnLDAPSearchResult(nsILDAPMessage *aMessage);
|
||||
|
||||
nsresult OpenABForReplicatedDir(bool bCreate);
|
||||
nsresult DeleteCard(nsString & aDn);
|
||||
void Done(bool aSuccess);
|
||||
};
|
||||
|
||||
|
||||
#endif // nsAbLDAPReplicationData_h__
|
||||
153
mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp
Normal file
153
mailnews/addrbook/src/nsAbLDAPReplicationQuery.cpp
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbLDAPReplicationQuery.h"
|
||||
#include "nsAbLDAPReplicationService.h"
|
||||
#include "nsAbLDAPReplicationData.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "prmem.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbLDAPReplicationQuery,
|
||||
nsIAbLDAPReplicationQuery)
|
||||
|
||||
nsAbLDAPReplicationQuery::nsAbLDAPReplicationQuery()
|
||||
: mInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPReplicationQuery::InitLDAPData()
|
||||
{
|
||||
nsAutoCString fileName;
|
||||
nsresult rv = mDirectory->GetReplicationFileName(fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// this is done here to take care of the problem related to bug # 99124.
|
||||
// earlier versions of Mozilla could have the fileName associated with the directory
|
||||
// to be abook.mab which is the profile's personal addressbook. If the pref points to
|
||||
// it, calls nsDirPrefs to generate a new server filename.
|
||||
if (fileName.IsEmpty() || fileName.EqualsLiteral(kPersonalAddressbook))
|
||||
{
|
||||
// Ensure fileName is empty for DIR_GenerateAbFileName to work
|
||||
// correctly.
|
||||
fileName.Truncate();
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> standardDir(do_QueryInterface(mDirectory, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString dirPrefId;
|
||||
rv = standardDir->GetDirPrefId(dirPrefId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX This should be replaced by a local function at some stage.
|
||||
// For now we'll continue using the nsDirPrefs version.
|
||||
DIR_Server* server = DIR_GetServerFromList(dirPrefId.get());
|
||||
if (server)
|
||||
{
|
||||
DIR_SetServerFileName(server);
|
||||
// Now ensure the prefs are saved
|
||||
DIR_SavePrefsForOneServer(server);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mDirectory->SetReplicationFileName(fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDirectory->GetLDAPURL(getter_AddRefs(mURL));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDirectory->GetAuthDn(mLogin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mConnection = do_CreateInstance(NS_LDAPCONNECTION_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbLDAPReplicationQuery::ConnectToLDAPServer()
|
||||
{
|
||||
if (!mInitialized || !mURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILDAPMessageListener> mDp = do_QueryInterface(mDataProcessor,
|
||||
&rv);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// this could be a rebind call
|
||||
int32_t replicationState = nsIAbLDAPProcessReplicationData::kIdle;
|
||||
rv = mDataProcessor->GetReplicationState(&replicationState);
|
||||
if (NS_FAILED(rv) ||
|
||||
replicationState != nsIAbLDAPProcessReplicationData::kIdle)
|
||||
return rv;
|
||||
|
||||
uint32_t protocolVersion;
|
||||
rv = mDirectory->GetProtocolVersion(&protocolVersion);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// initialize the LDAP connection
|
||||
return mConnection->Init(mURL, mLogin, mDp, nullptr, protocolVersion);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPReplicationQuery::Init(nsIAbLDAPDirectory *aDirectory,
|
||||
nsIWebProgressListener *aProgressListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
|
||||
mDirectory = aDirectory;
|
||||
|
||||
nsresult rv = InitLDAPData();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mDataProcessor =
|
||||
do_CreateInstance(NS_ABLDAP_PROCESSREPLICATIONDATA_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// 'this' initialized
|
||||
mInitialized = true;
|
||||
|
||||
return mDataProcessor->Init(mDirectory, mConnection, mURL, this,
|
||||
aProgressListener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPReplicationQuery::DoReplicationQuery()
|
||||
{
|
||||
return ConnectToLDAPServer();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPReplicationQuery::CancelQuery()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mDataProcessor->Abort();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPReplicationQuery::Done(bool aSuccess)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIAbLDAPReplicationService> replicationService =
|
||||
do_GetService(NS_ABLDAP_REPLICATIONSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
replicationService->Done(aSuccess);
|
||||
|
||||
return rv;
|
||||
}
|
||||
44
mailnews/addrbook/src/nsAbLDAPReplicationQuery.h
Normal file
44
mailnews/addrbook/src/nsAbLDAPReplicationQuery.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef nsAbLDAPReplicationQuery_h__
|
||||
#define nsAbLDAPReplicationQuery_h__
|
||||
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIAbLDAPReplicationQuery.h"
|
||||
#include "nsIAbLDAPReplicationData.h"
|
||||
#include "nsIAbLDAPDirectory.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsAbLDAPReplicationQuery final : public nsIAbLDAPReplicationQuery
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABLDAPREPLICATIONQUERY
|
||||
|
||||
nsAbLDAPReplicationQuery();
|
||||
|
||||
nsresult InitLDAPData();
|
||||
nsresult ConnectToLDAPServer();
|
||||
|
||||
protected :
|
||||
~nsAbLDAPReplicationQuery() {}
|
||||
// pointer to interfaces used by this object
|
||||
nsCOMPtr<nsILDAPConnection> mConnection;
|
||||
nsCOMPtr<nsILDAPOperation> mOperation;
|
||||
nsCOMPtr<nsILDAPURL> mURL;
|
||||
nsCOMPtr<nsIAbLDAPDirectory> mDirectory;
|
||||
|
||||
nsCOMPtr<nsIAbLDAPProcessReplicationData> mDataProcessor;
|
||||
|
||||
bool mInitialized;
|
||||
nsCString mLogin;
|
||||
};
|
||||
|
||||
#endif // nsAbLDAPReplicationQuery_h__
|
||||
136
mailnews/addrbook/src/nsAbLDAPReplicationService.cpp
Normal file
136
mailnews/addrbook/src/nsAbLDAPReplicationService.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbLDAPReplicationService.h"
|
||||
#include "nsAbLDAPReplicationQuery.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
// XXX Change log replication doesn't work. Bug 311632 should fix it.
|
||||
//#include "nsAbLDAPChangeLogQuery.h"
|
||||
#include "nsIAbLDAPReplicationData.h"
|
||||
|
||||
/*** implementation of the service ******/
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbLDAPReplicationService, nsIAbLDAPReplicationService)
|
||||
|
||||
nsAbLDAPReplicationService::nsAbLDAPReplicationService()
|
||||
: mReplicating(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbLDAPReplicationService::~nsAbLDAPReplicationService()
|
||||
{
|
||||
}
|
||||
|
||||
/* void startReplication(in string aURI, in nsIWebProgressListener progressListener); */
|
||||
NS_IMETHODIMP nsAbLDAPReplicationService::StartReplication(nsIAbLDAPDirectory *aDirectory,
|
||||
nsIWebProgressListener *progressListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
|
||||
#ifdef DEBUG_rdayal
|
||||
printf("Start Replication called");
|
||||
#endif
|
||||
|
||||
// Makes sure to allow only one replication at a time.
|
||||
if(mReplicating)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mDirectory = aDirectory;
|
||||
|
||||
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
switch (DecideProtocol())
|
||||
{
|
||||
case nsIAbLDAPProcessReplicationData::kDefaultDownloadAll:
|
||||
mQuery = do_CreateInstance(NS_ABLDAP_REPLICATIONQUERY_CONTRACTID, &rv);
|
||||
break;
|
||||
// XXX Change log replication doesn't work. Bug 311632 should fix it.
|
||||
//case nsIAbLDAPProcessReplicationData::kChangeLogProtocol:
|
||||
// mQuery = do_CreateInstance (NS_ABLDAP_CHANGELOGQUERY_CONTRACTID, &rv);
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mQuery)
|
||||
{
|
||||
rv = mQuery->Init(mDirectory, progressListener);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = mQuery->DoReplicationQuery();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
mReplicating = true;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (progressListener && NS_FAILED(rv))
|
||||
progressListener->OnStateChange(nullptr, nullptr,
|
||||
nsIWebProgressListener::STATE_STOP,
|
||||
NS_OK);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
mDirectory = nullptr;
|
||||
mQuery = nullptr;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void cancelReplication(in string aURI); */
|
||||
NS_IMETHODIMP nsAbLDAPReplicationService::CancelReplication(nsIAbLDAPDirectory *aDirectory)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (aDirectory == mDirectory)
|
||||
{
|
||||
if (mQuery && mReplicating)
|
||||
rv = mQuery->CancelQuery();
|
||||
}
|
||||
|
||||
// If query has been cancelled successfully
|
||||
if (NS_SUCCEEDED(rv))
|
||||
Done(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbLDAPReplicationService::Done(bool aSuccess)
|
||||
{
|
||||
mReplicating = false;
|
||||
if (mQuery)
|
||||
{
|
||||
mQuery = nullptr; // Release query obj
|
||||
mDirectory = nullptr; // Release directory
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// XXX: This method should query the RootDSE for the changeLog attribute,
|
||||
// if it exists ChangeLog protocol is supported.
|
||||
int32_t nsAbLDAPReplicationService::DecideProtocol()
|
||||
{
|
||||
// Do the changeLog, it will decide if there is a need to replicate all
|
||||
// entries or only update existing DB and will do the appropriate thing.
|
||||
//
|
||||
// XXX: Bug 231965 changed this from kChangeLogProtocol to
|
||||
// kDefaultDownloadAll because of a problem with ldap replication not
|
||||
// working correctly. We need to change this back at some stage (bug 311632).
|
||||
return nsIAbLDAPProcessReplicationData::kDefaultDownloadAll;
|
||||
}
|
||||
|
||||
|
||||
33
mailnews/addrbook/src/nsAbLDAPReplicationService.h
Normal file
33
mailnews/addrbook/src/nsAbLDAPReplicationService.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
|
||||
#ifndef nsAbLDAPReplicationService_h___
|
||||
#define nsAbLDAPReplicationService_h___
|
||||
|
||||
#include "nsIAbLDAPReplicationService.h"
|
||||
#include "nsIAbLDAPReplicationQuery.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsAbLDAPReplicationService : public nsIAbLDAPReplicationService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABLDAPREPLICATIONSERVICE
|
||||
|
||||
nsAbLDAPReplicationService();
|
||||
|
||||
int32_t DecideProtocol();
|
||||
|
||||
protected:
|
||||
virtual ~nsAbLDAPReplicationService();
|
||||
nsCOMPtr<nsIAbLDAPReplicationQuery> mQuery;
|
||||
bool mReplicating;
|
||||
nsCOMPtr<nsIAbLDAPDirectory> mDirectory;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsAbLDAPReplicationService_h___ */
|
||||
868
mailnews/addrbook/src/nsAbLDIFService.cpp
Normal file
868
mailnews/addrbook/src/nsAbLDIFService.cpp
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsAbLDIFService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "mdb.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbLDIFService, nsIAbLDIFService)
|
||||
|
||||
// If we get a line longer than 32K it's just toooooo bad!
|
||||
#define kTextAddressBufferSz (64 * 1024)
|
||||
|
||||
nsAbLDIFService::nsAbLDIFService()
|
||||
{
|
||||
mStoreLocAsHome = false;
|
||||
mLFCount = 0;
|
||||
mCRCount = 0;
|
||||
}
|
||||
|
||||
nsAbLDIFService::~nsAbLDIFService()
|
||||
{
|
||||
}
|
||||
|
||||
#define RIGHT2 0x03
|
||||
#define RIGHT4 0x0f
|
||||
#define CONTINUED_LINE_MARKER '\001'
|
||||
|
||||
// XXX TODO fix me
|
||||
// use the NSPR base64 library. see plbase64.h
|
||||
// see bug #145367
|
||||
static unsigned char b642nib[0x80] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
NS_IMETHODIMP nsAbLDIFService::ImportLDIFFile(nsIAddrDatabase *aDb, nsIFile *aSrc, bool aStoreLocAsHome, uint32_t *aProgress)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSrc);
|
||||
NS_ENSURE_ARG_POINTER(aDb);
|
||||
|
||||
mStoreLocAsHome = aStoreLocAsHome;
|
||||
|
||||
char buf[1024];
|
||||
char* pBuf = &buf[0];
|
||||
int32_t startPos = 0;
|
||||
uint32_t len = 0;
|
||||
nsTArray<int32_t> listPosArray; // where each list/group starts in ldif file
|
||||
nsTArray<int32_t> listSizeArray; // size of the list/group info
|
||||
int32_t savedStartPos = 0;
|
||||
int32_t filePos = 0;
|
||||
uint64_t bytesLeft = 0;
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), aSrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initialize the parser for a run...
|
||||
mLdifLine.Truncate();
|
||||
|
||||
while (NS_SUCCEEDED(inputStream->Available(&bytesLeft)) && bytesLeft > 0)
|
||||
{
|
||||
if (NS_SUCCEEDED(inputStream->Read(pBuf, sizeof(buf), &len)) && len > 0)
|
||||
{
|
||||
startPos = 0;
|
||||
|
||||
while (NS_SUCCEEDED(GetLdifStringRecord(buf, len, startPos)))
|
||||
{
|
||||
if (mLdifLine.Find("groupOfNames") == -1)
|
||||
AddLdifRowToDatabase(aDb, false);
|
||||
else
|
||||
{
|
||||
//keep file position for mailing list
|
||||
listPosArray.AppendElement(savedStartPos);
|
||||
listSizeArray.AppendElement(filePos + startPos-savedStartPos);
|
||||
ClearLdifRecordBuffer();
|
||||
}
|
||||
savedStartPos = filePos + startPos;
|
||||
}
|
||||
filePos += len;
|
||||
if (aProgress)
|
||||
*aProgress = (uint32_t)filePos;
|
||||
}
|
||||
}
|
||||
//last row
|
||||
if (!mLdifLine.IsEmpty() && mLdifLine.Find("groupOfNames") == -1)
|
||||
AddLdifRowToDatabase(aDb, false);
|
||||
|
||||
// mail Lists
|
||||
int32_t i, pos;
|
||||
uint32_t size;
|
||||
int32_t listTotal = listPosArray.Length();
|
||||
char *listBuf;
|
||||
ClearLdifRecordBuffer(); // make sure the buffer is clean
|
||||
|
||||
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(inputStream, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = 0; i < listTotal; i++)
|
||||
{
|
||||
pos = listPosArray[i];
|
||||
size = listSizeArray[i];
|
||||
if (NS_SUCCEEDED(seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, pos)))
|
||||
{
|
||||
// Allocate enough space for the lists/groups as the size varies.
|
||||
listBuf = (char *) PR_Malloc(size);
|
||||
if (!listBuf)
|
||||
continue;
|
||||
if (NS_SUCCEEDED(inputStream->Read(listBuf, size, &len)) && len > 0)
|
||||
{
|
||||
startPos = 0;
|
||||
|
||||
while (NS_SUCCEEDED(GetLdifStringRecord(listBuf, len, startPos)))
|
||||
{
|
||||
if (mLdifLine.Find("groupOfNames") != -1)
|
||||
{
|
||||
AddLdifRowToDatabase(aDb, true);
|
||||
if (NS_SUCCEEDED(seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, 0)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
PR_FREEIF(listBuf);
|
||||
}
|
||||
}
|
||||
|
||||
rv = inputStream->Close();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Finally commit everything to the database and return.
|
||||
return aDb->Commit(nsAddrDBCommitType::kLargeCommit);
|
||||
}
|
||||
|
||||
/*
|
||||
* str_parse_line - takes a line of the form "type:[:] value" and splits it
|
||||
* into components "type" and "value". if a double colon separates type from
|
||||
* value, then value is encoded in base 64, and parse_line un-decodes it
|
||||
* (in place) before returning.
|
||||
* in LDIF, non-ASCII data is treated as base64 encoded UTF-8
|
||||
*/
|
||||
|
||||
nsresult nsAbLDIFService::str_parse_line(char *line, char **type, char **value, int *vlen) const
|
||||
{
|
||||
char *p, *s, *d, *byte, *stop;
|
||||
char nib;
|
||||
int i, b64;
|
||||
|
||||
/* skip any leading space */
|
||||
while ( isspace( *line ) ) {
|
||||
line++;
|
||||
}
|
||||
*type = line;
|
||||
|
||||
for ( s = line; *s && *s != ':'; s++ )
|
||||
; /* NULL */
|
||||
if ( *s == '\0' ) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* trim any space between type and : */
|
||||
for ( p = s - 1; p > line && isspace( *p ); p-- ) {
|
||||
*p = '\0';
|
||||
}
|
||||
*s++ = '\0';
|
||||
|
||||
/* check for double : - indicates base 64 encoded value */
|
||||
if ( *s == ':' ) {
|
||||
s++;
|
||||
b64 = 1;
|
||||
/* single : - normally encoded value */
|
||||
} else {
|
||||
b64 = 0;
|
||||
}
|
||||
|
||||
/* skip space between : and value */
|
||||
while ( isspace( *s ) ) {
|
||||
s++;
|
||||
}
|
||||
|
||||
/* if no value is present, error out */
|
||||
if ( *s == '\0' ) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* check for continued line markers that should be deleted */
|
||||
for ( p = s, d = s; *p; p++ ) {
|
||||
if ( *p != CONTINUED_LINE_MARKER )
|
||||
*d++ = *p;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
*value = s;
|
||||
if ( b64 ) {
|
||||
stop = PL_strchr( s, '\0' );
|
||||
byte = s;
|
||||
for ( p = s, *vlen = 0; p < stop; p += 4, *vlen += 3 ) {
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
if ( p[i] != '=' && (p[i] & 0x80 ||
|
||||
b642nib[ p[i] & 0x7f ] > 0x3f) ) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* first digit */
|
||||
nib = b642nib[ p[0] & 0x7f ];
|
||||
byte[0] = nib << 2;
|
||||
/* second digit */
|
||||
nib = b642nib[ p[1] & 0x7f ];
|
||||
byte[0] |= nib >> 4;
|
||||
byte[1] = (nib & RIGHT4) << 4;
|
||||
/* third digit */
|
||||
if ( p[2] == '=' ) {
|
||||
*vlen += 1;
|
||||
break;
|
||||
}
|
||||
nib = b642nib[ p[2] & 0x7f ];
|
||||
byte[1] |= nib >> 2;
|
||||
byte[2] = (nib & RIGHT2) << 6;
|
||||
/* fourth digit */
|
||||
if ( p[3] == '=' ) {
|
||||
*vlen += 2;
|
||||
break;
|
||||
}
|
||||
nib = b642nib[ p[3] & 0x7f ];
|
||||
byte[2] |= nib;
|
||||
|
||||
byte += 3;
|
||||
}
|
||||
s[ *vlen ] = '\0';
|
||||
} else {
|
||||
*vlen = (int) (d - s);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* str_getline - return the next "line" (minus newline) of input from a
|
||||
* string buffer of lines separated by newlines, terminated by \n\n
|
||||
* or \0. this routine handles continued lines, bundling them into
|
||||
* a single big line before returning. if a line begins with a white
|
||||
* space character, it is a continuation of the previous line. the white
|
||||
* space character (nb: only one char), and preceeding newline are changed
|
||||
* into CONTINUED_LINE_MARKER chars, to be deleted later by the
|
||||
* str_parse_line() routine above.
|
||||
*
|
||||
* it takes a pointer to a pointer to the buffer on the first call,
|
||||
* which it updates and must be supplied on subsequent calls.
|
||||
*/
|
||||
|
||||
char* nsAbLDIFService::str_getline(char **next) const
|
||||
{
|
||||
char *lineStr;
|
||||
char c;
|
||||
|
||||
if ( *next == nullptr || **next == '\n' || **next == '\0' ) {
|
||||
return( nullptr);
|
||||
}
|
||||
|
||||
lineStr = *next;
|
||||
while ( (*next = PL_strchr( *next, '\n' )) != NULL ) {
|
||||
c = *(*next + 1);
|
||||
if ( isspace( c ) && c != '\n' ) {
|
||||
**next = CONTINUED_LINE_MARKER;
|
||||
*(*next+1) = CONTINUED_LINE_MARKER;
|
||||
} else {
|
||||
*(*next)++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( lineStr );
|
||||
}
|
||||
|
||||
nsresult nsAbLDIFService::GetLdifStringRecord(char* buf, int32_t len, int32_t& stopPos)
|
||||
{
|
||||
for (; stopPos < len; stopPos++)
|
||||
{
|
||||
char c = buf[stopPos];
|
||||
|
||||
if (c == 0xA)
|
||||
{
|
||||
mLFCount++;
|
||||
}
|
||||
else if (c == 0xD)
|
||||
{
|
||||
mCRCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mLFCount == 0 && mCRCount == 0)
|
||||
mLdifLine.Append(c);
|
||||
else if (( mLFCount > 1) || ( mCRCount > 2 && mLFCount ) ||
|
||||
( !mLFCount && mCRCount > 1 ))
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
else if ((mLFCount == 1 || mCRCount == 1))
|
||||
{
|
||||
mLdifLine.Append('\n');
|
||||
mLdifLine.Append(c);
|
||||
mLFCount = 0;
|
||||
mCRCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((stopPos == len) && (mLFCount > 1)) || (mCRCount > 2 && mLFCount) ||
|
||||
(!mLFCount && mCRCount > 1))
|
||||
return NS_OK;
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void nsAbLDIFService::AddLdifRowToDatabase(nsIAddrDatabase *aDatabase,
|
||||
bool bIsList)
|
||||
{
|
||||
// If no data to process then reset CR/LF counters and return.
|
||||
if (mLdifLine.IsEmpty())
|
||||
{
|
||||
mLFCount = 0;
|
||||
mCRCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr <nsIMdbRow> newRow;
|
||||
if (aDatabase)
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->GetNewListRow(getter_AddRefs(newRow));
|
||||
else
|
||||
aDatabase->GetNewRow(getter_AddRefs(newRow));
|
||||
|
||||
if (!newRow)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
char* cursor = ToNewCString(mLdifLine);
|
||||
char* saveCursor = cursor; /* keep for deleting */
|
||||
char* line = 0;
|
||||
char* typeSlot = 0;
|
||||
char* valueSlot = 0;
|
||||
int length = 0; // the length of an ldif attribute
|
||||
while ( (line = str_getline(&cursor)) != nullptr)
|
||||
{
|
||||
if (NS_SUCCEEDED(str_parse_line(line, &typeSlot, &valueSlot, &length))) {
|
||||
AddLdifColToDatabase(aDatabase, newRow, typeSlot, valueSlot, bIsList);
|
||||
}
|
||||
else
|
||||
continue; // parse error: continue with next loop iteration
|
||||
}
|
||||
free(saveCursor);
|
||||
aDatabase->AddCardRowToDB(newRow);
|
||||
|
||||
if (bIsList)
|
||||
aDatabase->AddListDirNode(newRow);
|
||||
|
||||
// Clear buffer for next record
|
||||
ClearLdifRecordBuffer();
|
||||
}
|
||||
|
||||
void nsAbLDIFService::AddLdifColToDatabase(nsIAddrDatabase *aDatabase,
|
||||
nsIMdbRow* newRow, char* typeSlot,
|
||||
char* valueSlot, bool bIsList)
|
||||
{
|
||||
nsAutoCString colType(typeSlot);
|
||||
nsAutoCString column(valueSlot);
|
||||
|
||||
// 4.x exports attributes like "givenname",
|
||||
// mozilla does "givenName" to be compliant with RFC 2798
|
||||
ToLowerCase(colType);
|
||||
|
||||
mdb_u1 firstByte = (mdb_u1)(colType.get())[0];
|
||||
switch ( firstByte )
|
||||
{
|
||||
case 'b':
|
||||
if (colType.EqualsLiteral("birthyear"))
|
||||
aDatabase->AddBirthYear(newRow, column.get());
|
||||
else if (colType.EqualsLiteral("birthmonth"))
|
||||
aDatabase->AddBirthMonth(newRow, column.get());
|
||||
else if (colType.EqualsLiteral("birthday"))
|
||||
aDatabase->AddBirthDay(newRow, column.get());
|
||||
break; // 'b'
|
||||
|
||||
case 'c':
|
||||
if (colType.EqualsLiteral("cn") || colType.EqualsLiteral("commonname"))
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->AddListName(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddDisplayName(newRow, column.get());
|
||||
}
|
||||
else if (colType.EqualsLiteral("c") || colType.EqualsLiteral("countryname"))
|
||||
{
|
||||
if (mStoreLocAsHome )
|
||||
aDatabase->AddHomeCountry(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddWorkCountry(newRow, column.get());
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("cellphone") )
|
||||
aDatabase->AddCellularNumber(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("carphone"))
|
||||
aDatabase->AddCellularNumber(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("custom1"))
|
||||
aDatabase->AddCustom1(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("custom2"))
|
||||
aDatabase->AddCustom2(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("custom3"))
|
||||
aDatabase->AddCustom3(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("custom4"))
|
||||
aDatabase->AddCustom4(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("company"))
|
||||
aDatabase->AddCompany(newRow, column.get());
|
||||
break; // 'c'
|
||||
|
||||
case 'd':
|
||||
if (colType.EqualsLiteral("description"))
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->AddListDescription(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddNotes(newRow, column.get());
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("department"))
|
||||
aDatabase->AddDepartment(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("displayname"))
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->AddListName(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddDisplayName(newRow, column.get());
|
||||
}
|
||||
break; // 'd'
|
||||
|
||||
case 'f':
|
||||
|
||||
if (colType.EqualsLiteral("fax") ||
|
||||
colType.EqualsLiteral("facsimiletelephonenumber"))
|
||||
aDatabase->AddFaxNumber(newRow, column.get());
|
||||
break; // 'f'
|
||||
|
||||
case 'g':
|
||||
if (colType.EqualsLiteral("givenname"))
|
||||
aDatabase->AddFirstName(newRow, column.get());
|
||||
|
||||
break; // 'g'
|
||||
|
||||
case 'h':
|
||||
if (colType.EqualsLiteral("homephone"))
|
||||
aDatabase->AddHomePhone(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("homestreet"))
|
||||
aDatabase->AddHomeAddress(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("homeurl"))
|
||||
aDatabase->AddWebPage2(newRow, column.get());
|
||||
break; // 'h'
|
||||
|
||||
case 'l':
|
||||
if (colType.EqualsLiteral("l") || colType.EqualsLiteral("locality"))
|
||||
{
|
||||
if (mStoreLocAsHome)
|
||||
aDatabase->AddHomeCity(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddWorkCity(newRow, column.get());
|
||||
}
|
||||
// labeledURI contains a URI and, optionally, a label
|
||||
// This will remove the label and place the URI as the work URL
|
||||
else if (colType.EqualsLiteral("labeleduri"))
|
||||
{
|
||||
int32_t index = column.FindChar(' ');
|
||||
if (index != -1)
|
||||
column.SetLength(index);
|
||||
|
||||
aDatabase->AddWebPage1(newRow, column.get());
|
||||
}
|
||||
|
||||
break; // 'l'
|
||||
|
||||
case 'm':
|
||||
if (colType.EqualsLiteral("mail"))
|
||||
aDatabase->AddPrimaryEmail(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("member") && bIsList)
|
||||
aDatabase->AddLdifListMember(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mobile"))
|
||||
aDatabase->AddCellularNumber(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozilla_aimscreenname"))
|
||||
aDatabase->AddAimScreenName(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillacustom1"))
|
||||
aDatabase->AddCustom1(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillacustom2"))
|
||||
aDatabase->AddCustom2(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillacustom3"))
|
||||
aDatabase->AddCustom3(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillacustom4"))
|
||||
aDatabase->AddCustom4(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomecountryname"))
|
||||
aDatabase->AddHomeCountry(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomelocalityname"))
|
||||
aDatabase->AddHomeCity(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomestate"))
|
||||
aDatabase->AddHomeState(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomestreet"))
|
||||
aDatabase->AddHomeAddress(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomestreet2"))
|
||||
aDatabase->AddHomeAddress2(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomepostalcode"))
|
||||
aDatabase->AddHomeZipCode(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillahomeurl"))
|
||||
aDatabase->AddWebPage2(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillanickname"))
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->AddListNickName(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddNickName(newRow, column.get());
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("mozillasecondemail"))
|
||||
aDatabase->Add2ndEmail(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillausehtmlmail"))
|
||||
{
|
||||
ToLowerCase(column);
|
||||
if (-1 != column.Find("true"))
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::html);
|
||||
else if (-1 != column.Find("false"))
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::plaintext);
|
||||
else
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::unknown);
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("mozillaworkstreet2"))
|
||||
aDatabase->AddWorkAddress2(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("mozillaworkurl"))
|
||||
aDatabase->AddWebPage1(newRow, column.get());
|
||||
|
||||
break; // 'm'
|
||||
|
||||
case 'n':
|
||||
if (colType.EqualsLiteral("notes"))
|
||||
aDatabase->AddNotes(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("nscpaimscreenname") ||
|
||||
colType.EqualsLiteral("nsaimid"))
|
||||
aDatabase->AddAimScreenName(newRow, column.get());
|
||||
|
||||
break; // 'n'
|
||||
|
||||
case 'o':
|
||||
if (colType.EqualsLiteral("objectclass"))
|
||||
break;
|
||||
|
||||
else if (colType.EqualsLiteral("ou") || colType.EqualsLiteral("orgunit"))
|
||||
aDatabase->AddDepartment(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("o")) // organization
|
||||
aDatabase->AddCompany(newRow, column.get());
|
||||
|
||||
break; // 'o'
|
||||
|
||||
case 'p':
|
||||
if (colType.EqualsLiteral("postalcode"))
|
||||
{
|
||||
if (mStoreLocAsHome)
|
||||
aDatabase->AddHomeZipCode(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddWorkZipCode(newRow, column.get());
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("postofficebox"))
|
||||
{
|
||||
nsAutoCString workAddr1, workAddr2;
|
||||
SplitCRLFAddressField(column, workAddr1, workAddr2);
|
||||
aDatabase->AddWorkAddress(newRow, workAddr1.get());
|
||||
aDatabase->AddWorkAddress2(newRow, workAddr2.get());
|
||||
}
|
||||
else if (colType.EqualsLiteral("pager") || colType.EqualsLiteral("pagerphone"))
|
||||
aDatabase->AddPagerNumber(newRow, column.get());
|
||||
|
||||
break; // 'p'
|
||||
|
||||
case 'r':
|
||||
if (colType.EqualsLiteral("region"))
|
||||
{
|
||||
aDatabase->AddWorkState(newRow, column.get());
|
||||
}
|
||||
|
||||
break; // 'r'
|
||||
|
||||
case 's':
|
||||
if (colType.EqualsLiteral("sn") || colType.EqualsLiteral("surname"))
|
||||
aDatabase->AddLastName(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("street"))
|
||||
aDatabase->AddWorkAddress(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("streetaddress"))
|
||||
{
|
||||
nsAutoCString addr1, addr2;
|
||||
SplitCRLFAddressField(column, addr1, addr2);
|
||||
if (mStoreLocAsHome)
|
||||
{
|
||||
aDatabase->AddHomeAddress(newRow, addr1.get());
|
||||
aDatabase->AddHomeAddress2(newRow, addr2.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
aDatabase->AddWorkAddress(newRow, addr1.get());
|
||||
aDatabase->AddWorkAddress2(newRow, addr2.get());
|
||||
}
|
||||
}
|
||||
else if (colType.EqualsLiteral("st"))
|
||||
{
|
||||
if (mStoreLocAsHome)
|
||||
aDatabase->AddHomeState(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddWorkState(newRow, column.get());
|
||||
}
|
||||
|
||||
break; // 's'
|
||||
|
||||
case 't':
|
||||
if (colType.EqualsLiteral("title"))
|
||||
aDatabase->AddJobTitle(newRow, column.get());
|
||||
|
||||
else if (colType.EqualsLiteral("telephonenumber") )
|
||||
{
|
||||
aDatabase->AddWorkPhone(newRow, column.get());
|
||||
}
|
||||
|
||||
break; // 't'
|
||||
|
||||
case 'u':
|
||||
|
||||
if (colType.EqualsLiteral("uniquemember") && bIsList)
|
||||
aDatabase->AddLdifListMember(newRow, column.get());
|
||||
|
||||
break; // 'u'
|
||||
|
||||
case 'w':
|
||||
if (colType.EqualsLiteral("workurl"))
|
||||
aDatabase->AddWebPage1(newRow, column.get());
|
||||
|
||||
break; // 'w'
|
||||
|
||||
case 'x':
|
||||
if (colType.EqualsLiteral("xmozillanickname"))
|
||||
{
|
||||
if (bIsList)
|
||||
aDatabase->AddListNickName(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddNickName(newRow, column.get());
|
||||
}
|
||||
|
||||
else if (colType.EqualsLiteral("xmozillausehtmlmail"))
|
||||
{
|
||||
ToLowerCase(column);
|
||||
if (-1 != column.Find("true"))
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::html);
|
||||
else if (-1 != column.Find("false"))
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::plaintext);
|
||||
else
|
||||
aDatabase->AddPreferMailFormat(newRow, nsIAbPreferMailFormat::unknown);
|
||||
}
|
||||
|
||||
break; // 'x'
|
||||
|
||||
case 'z':
|
||||
if (colType.EqualsLiteral("zip")) // alias for postalcode
|
||||
{
|
||||
if (mStoreLocAsHome)
|
||||
aDatabase->AddHomeZipCode(newRow, column.get());
|
||||
else
|
||||
aDatabase->AddWorkZipCode(newRow, column.get());
|
||||
}
|
||||
|
||||
break; // 'z'
|
||||
|
||||
default:
|
||||
break; // default
|
||||
}
|
||||
}
|
||||
|
||||
void nsAbLDIFService::ClearLdifRecordBuffer()
|
||||
{
|
||||
if (!mLdifLine.IsEmpty())
|
||||
{
|
||||
mLdifLine.Truncate();
|
||||
mLFCount = 0;
|
||||
mCRCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Some common ldif fields, it an ldif file has NONE of these entries
|
||||
// then it is most likely NOT an ldif file!
|
||||
static const char *const sLDIFFields[] = {
|
||||
"objectclass",
|
||||
"sn",
|
||||
"dn",
|
||||
"cn",
|
||||
"givenName",
|
||||
"mail",
|
||||
nullptr
|
||||
};
|
||||
#define kMaxLDIFLen 14
|
||||
|
||||
// Count total number of legal ldif fields and records in the first 100 lines of the
|
||||
// file and if the average legal ldif field is 3 or higher than it's a valid ldif file.
|
||||
NS_IMETHODIMP nsAbLDIFService::IsLDIFFile(nsIFile *pSrc, bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(pSrc);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
*_retval = false;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), pSrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(fileStream, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t lineLen = 0;
|
||||
int32_t lineCount = 0;
|
||||
int32_t ldifFields = 0; // total number of legal ldif fields.
|
||||
char field[kMaxLDIFLen];
|
||||
int32_t fLen = 0;
|
||||
const char *pChar;
|
||||
int32_t recCount = 0; // total number of records.
|
||||
int32_t i;
|
||||
bool gotLDIF = false;
|
||||
bool more = true;
|
||||
nsCString line;
|
||||
|
||||
while (more && NS_SUCCEEDED(rv) && (lineCount < 100))
|
||||
{
|
||||
rv = lineInputStream->ReadLine(line, &more);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && more)
|
||||
{
|
||||
pChar = line.get();
|
||||
lineLen = line.Length();
|
||||
if (!lineLen && gotLDIF)
|
||||
{
|
||||
recCount++;
|
||||
gotLDIF = false;
|
||||
}
|
||||
|
||||
if (lineLen && (*pChar != ' ') && (*pChar != '\t'))
|
||||
{
|
||||
fLen = 0;
|
||||
|
||||
while (lineLen && (fLen < (kMaxLDIFLen - 1)) && (*pChar != ':'))
|
||||
{
|
||||
field[fLen] = *pChar;
|
||||
pChar++;
|
||||
fLen++;
|
||||
lineLen--;
|
||||
}
|
||||
|
||||
field[fLen] = 0;
|
||||
|
||||
if (lineLen && (*pChar == ':') && (fLen < (kMaxLDIFLen - 1)))
|
||||
{
|
||||
// see if this is an ldif field (case insensitive)?
|
||||
i = 0;
|
||||
while (sLDIFFields[i])
|
||||
{
|
||||
if (!PL_strcasecmp( sLDIFFields[i], field))
|
||||
{
|
||||
ldifFields++;
|
||||
gotLDIF = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lineCount++;
|
||||
}
|
||||
|
||||
// If we just saw ldif address, increment recCount.
|
||||
if (gotLDIF)
|
||||
recCount++;
|
||||
|
||||
rv = fileStream->Close();
|
||||
|
||||
if (recCount > 1)
|
||||
ldifFields /= recCount;
|
||||
|
||||
// If the average field number >= 3 then it's a good ldif file.
|
||||
if (ldifFields >= 3)
|
||||
{
|
||||
*_retval = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsAbLDIFService::SplitCRLFAddressField(nsCString &inputAddress, nsCString &outputLine1, nsCString &outputLine2) const
|
||||
{
|
||||
int32_t crlfPos = inputAddress.Find("\r\n");
|
||||
if (crlfPos != -1)
|
||||
{
|
||||
outputLine1 = Substring(inputAddress, 0, crlfPos);
|
||||
outputLine2 = Substring(inputAddress, crlfPos + 2);
|
||||
}
|
||||
else
|
||||
outputLine1.Assign(inputAddress);
|
||||
}
|
||||
|
||||
37
mailnews/addrbook/src/nsAbLDIFService.h
Normal file
37
mailnews/addrbook/src/nsAbLDIFService.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef __nsAbLDIFService_h
|
||||
#define __nsAbLDIFService_h
|
||||
|
||||
#include "nsIAbLDIFService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIMdbRow;
|
||||
|
||||
class nsAbLDIFService : public nsIAbLDIFService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABLDIFSERVICE
|
||||
|
||||
nsAbLDIFService();
|
||||
private:
|
||||
virtual ~nsAbLDIFService();
|
||||
nsresult str_parse_line(char *line, char **type, char **value, int *vlen) const;
|
||||
char * str_getline(char **next) const;
|
||||
nsresult GetLdifStringRecord(char* buf, int32_t len, int32_t& stopPos);
|
||||
void AddLdifRowToDatabase(nsIAddrDatabase *aDatabase, bool aIsList);
|
||||
void AddLdifColToDatabase(nsIAddrDatabase *aDatabase, nsIMdbRow* newRow,
|
||||
char* typeSlot, char* valueSlot, bool bIsList);
|
||||
void ClearLdifRecordBuffer();
|
||||
void SplitCRLFAddressField(nsCString &inputAddress, nsCString &outputLine1, nsCString &outputLine2) const;
|
||||
|
||||
bool mStoreLocAsHome;
|
||||
nsCString mLdifLine;
|
||||
int32_t mLFCount;
|
||||
int32_t mCRCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
55
mailnews/addrbook/src/nsAbMDBCard.cpp
Normal file
55
mailnews/addrbook/src/nsAbMDBCard.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbMDBCard.h"
|
||||
|
||||
nsAbMDBCard::nsAbMDBCard(void)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbMDBCard::~nsAbMDBCard(void)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsAbMDBCard, nsAbCardProperty)
|
||||
|
||||
NS_IMETHODIMP nsAbMDBCard::Equals(nsIAbCard *card, bool *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(card);
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
|
||||
if (this == card) {
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we have the same directory, we will equal the other card merely given
|
||||
// the row IDs. If not, we are never equal. But we are dumb in that we don't
|
||||
// know who our directory is, which may change in the future. For now,
|
||||
// however, the only known users of this method are for locating us in a list
|
||||
// of cards, most commonly mailing lists; a warning on the IDL has also
|
||||
// notified consumers that this method is not generally safe to use. In this
|
||||
// respect, it is safe to assume that the directory portion is satisfied when
|
||||
// making this call.
|
||||
// However, if we make the wrong assumption, one of two things will happen.
|
||||
// If the other directory is a local address book, we could return a spurious
|
||||
// true result. If not, then DbRowID should be unset and we can definitively
|
||||
// return false.
|
||||
|
||||
uint32_t row;
|
||||
nsresult rv = card->GetPropertyAsUint32("DbRowID", &row);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
*result = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t ourRow;
|
||||
rv = GetPropertyAsUint32("DbRowID", &ourRow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*result = (row == ourRow);
|
||||
return NS_OK;
|
||||
}
|
||||
26
mailnews/addrbook/src/nsAbMDBCard.h
Normal file
26
mailnews/addrbook/src/nsAbMDBCard.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbMDBCard_h__
|
||||
#define nsAbMDBCard_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbCardProperty.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsAbMDBCard: public nsAbCardProperty
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsAbMDBCard(void);
|
||||
|
||||
NS_IMETHOD Equals(nsIAbCard *card, bool *result) override;
|
||||
|
||||
private:
|
||||
virtual ~nsAbMDBCard();
|
||||
};
|
||||
|
||||
#endif
|
||||
118
mailnews/addrbook/src/nsAbMDBDirFactory.cpp
Normal file
118
mailnews/addrbook/src/nsAbMDBDirFactory.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbMDBDirFactory.h"
|
||||
#include "nsAbUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsIAbMDBDirectory.h"
|
||||
#include "nsAbMDBDirFactory.h"
|
||||
#include "nsIAddrDBListener.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbMDBDirFactory, nsIAbDirFactory)
|
||||
|
||||
nsAbMDBDirFactory::nsAbMDBDirFactory()
|
||||
{
|
||||
}
|
||||
|
||||
nsAbMDBDirFactory::~nsAbMDBDirFactory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirFactory::GetDirectories(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
const nsACString &aPrefName,
|
||||
nsISimpleEnumerator **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
rv = abManager->GetDirectory(aURI, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = directory->SetDirPrefId(aPrefName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> dbPath;
|
||||
rv = abManager->GetUserProfileDirectory(getter_AddRefs(dbPath));
|
||||
|
||||
nsCOMPtr<nsIAddrDatabase> listDatabase;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsAutoCString fileName;
|
||||
|
||||
if (StringBeginsWith(aURI, NS_LITERAL_CSTRING(kMDBDirectoryRoot)))
|
||||
fileName = Substring(aURI, kMDBDirectoryRootLen, aURI.Length() - kMDBDirectoryRootLen);
|
||||
|
||||
rv = dbPath->AppendNative(fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAddrDatabase> addrDBFactory = do_GetService(NS_ADDRDATABASE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = addrDBFactory->Open(dbPath, true, true, getter_AddRefs(listDatabase));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = listDatabase->GetMailingListsFromDB(directory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_NewSingletonEnumerator(_retval, directory);
|
||||
}
|
||||
|
||||
/* void deleteDirectory (in nsIAbDirectory directory); */
|
||||
NS_IMETHODIMP nsAbMDBDirFactory::DeleteDirectory(nsIAbDirectory *directory)
|
||||
{
|
||||
if (!directory)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> pAddressLists;
|
||||
rv = directory->GetAddressLists(getter_AddRefs(pAddressLists));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t total;
|
||||
rv = pAddressLists->GetLength(&total);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < total; i++)
|
||||
{
|
||||
nsCOMPtr<nsIAbDirectory> listDir(do_QueryElementAt(pAddressLists, i, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIAbMDBDirectory> dblistDir(do_QueryInterface(listDir, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = directory->DeleteDirectory(listDir);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = dblistDir->RemoveElementsFromAddressList();
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
}
|
||||
pAddressLists->Clear();
|
||||
|
||||
nsCOMPtr<nsIAbMDBDirectory> dbdirectory(do_QueryInterface(directory, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return dbdirectory->ClearDatabase();
|
||||
}
|
||||
|
||||
24
mailnews/addrbook/src/nsAbMDBDirFactory.h
Normal file
24
mailnews/addrbook/src/nsAbMDBDirFactory.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbMDBDirFactory_h__
|
||||
#define nsAbMDBDirFactory_h__
|
||||
|
||||
#include "nsIAbDirFactory.h"
|
||||
|
||||
class nsAbMDBDirFactory : public nsIAbDirFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRFACTORY
|
||||
|
||||
nsAbMDBDirFactory();
|
||||
|
||||
private:
|
||||
virtual ~nsAbMDBDirFactory();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
145
mailnews/addrbook/src/nsAbMDBDirProperty.cpp
Normal file
145
mailnews/addrbook/src/nsAbMDBDirProperty.cpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbMDBDirProperty.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAddrDatabase.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsIAbListener.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "mdb.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
nsAbMDBDirProperty::nsAbMDBDirProperty(void)
|
||||
: nsAbDirProperty()
|
||||
{
|
||||
m_dbRowID = 0;
|
||||
}
|
||||
|
||||
nsAbMDBDirProperty::~nsAbMDBDirProperty(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAbMDBDirProperty, nsAbDirProperty,
|
||||
nsIAbDirectory,
|
||||
nsISupportsWeakReference, nsIAbMDBDirectory)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// nsIAbMDBDirectory attributes
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::GetDbRowID(uint32_t *aDbRowID)
|
||||
{
|
||||
*aDbRowID = m_dbRowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::SetDbRowID(uint32_t aDbRowID)
|
||||
{
|
||||
m_dbRowID = aDbRowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIAbMDBDirectory methods
|
||||
|
||||
/* add mailing list to the parent directory */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::AddMailListToDirectory(nsIAbDirectory *mailList)
|
||||
{
|
||||
if (!m_AddressList)
|
||||
{
|
||||
nsresult rv;
|
||||
m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
uint32_t position;
|
||||
if (NS_FAILED(m_AddressList->IndexOf(0, mailList, &position)))
|
||||
m_AddressList->AppendElement(mailList, false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* add addresses to the mailing list */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::AddAddressToList(nsIAbCard *card)
|
||||
{
|
||||
if (!m_AddressList)
|
||||
{
|
||||
nsresult rv;
|
||||
m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
uint32_t position;
|
||||
if (NS_FAILED(m_AddressList->IndexOf(0, card, &position)))
|
||||
m_AddressList->AppendElement(card, false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::CopyDBMailList(nsIAbMDBDirectory* srcListDB)
|
||||
{
|
||||
nsresult err = NS_OK;
|
||||
nsCOMPtr<nsIAbDirectory> srcList(do_QueryInterface(srcListDB));
|
||||
if (NS_FAILED(err))
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
CopyMailList (srcList);
|
||||
|
||||
uint32_t rowID;
|
||||
srcListDB->GetDbRowID(&rowID);
|
||||
SetDbRowID(rowID);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIAbMDBDirectory NOT IMPLEMENTED methods
|
||||
|
||||
/* nsIAbDirectory addDirectory (in string uriName); */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::AddDirectory(const char *uriName, nsIAbDirectory **_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [noscript] void removeElementsFromAddressList (); */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::RemoveElementsFromAddressList()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void removeEmailAddressAt (in unsigned long aIndex); */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::RemoveEmailAddressAt(uint32_t aIndex)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [noscript] void notifyDirItemAdded (in nsISupports item); */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::NotifyDirItemAdded(nsISupports *item)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* [noscript] void clearDatabase (); */
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::ClearDatabase()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::GetDatabaseFile(nsIFile **aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAbMDBDirProperty::GetDatabase(nsIAddrDatabase **aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
40
mailnews/addrbook/src/nsAbMDBDirProperty.h
Normal file
40
mailnews/addrbook/src/nsAbMDBDirProperty.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Address Book Directory
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsAbMDBDirProperty_h__
|
||||
#define nsAbMDBDirProperty_h__
|
||||
|
||||
#include "nsIAbMDBDirectory.h"
|
||||
#include "nsAbDirProperty.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
|
||||
/*
|
||||
* Address Book Directory
|
||||
*/
|
||||
|
||||
class nsAbMDBDirProperty: public nsIAbMDBDirectory, public nsAbDirProperty
|
||||
{
|
||||
public:
|
||||
nsAbMDBDirProperty(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABMDBDIRECTORY
|
||||
|
||||
protected:
|
||||
virtual ~nsAbMDBDirProperty();
|
||||
|
||||
uint32_t m_dbRowID;
|
||||
};
|
||||
|
||||
#endif
|
||||
1125
mailnews/addrbook/src/nsAbMDBDirectory.cpp
Normal file
1125
mailnews/addrbook/src/nsAbMDBDirectory.cpp
Normal file
File diff suppressed because it is too large
Load diff
104
mailnews/addrbook/src/nsAbMDBDirectory.h
Normal file
104
mailnews/addrbook/src/nsAbMDBDirectory.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Address Book Directory
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsAbMDBDirectory_h__
|
||||
#define nsAbMDBDirectory_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbMDBDirProperty.h"
|
||||
#include "nsIAbCard.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDirPrefs.h"
|
||||
#include "nsIAbDirectorySearch.h"
|
||||
#include "nsIAbDirSearchListener.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIAddrDBListener.h"
|
||||
|
||||
/*
|
||||
* Address Book Directory
|
||||
*/
|
||||
|
||||
class nsAbMDBDirectory:
|
||||
public nsAbMDBDirProperty, // nsIAbDirectory, nsIAbMDBDirectory
|
||||
public nsIAbDirSearchListener,
|
||||
public nsIAddrDBListener,
|
||||
public nsIAbDirectorySearch
|
||||
{
|
||||
public:
|
||||
nsAbMDBDirectory(void);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIADDRDBLISTENER
|
||||
|
||||
// Override nsAbMDBDirProperty::Init
|
||||
NS_IMETHOD Init(const char *aUri) override;
|
||||
|
||||
// nsIAbMDBDirectory methods
|
||||
NS_IMETHOD GetURI(nsACString &aURI) override;
|
||||
NS_IMETHOD ClearDatabase() override;
|
||||
NS_IMETHOD NotifyDirItemAdded(nsISupports *item) override { return NotifyItemAdded(item);}
|
||||
NS_IMETHOD RemoveElementsFromAddressList() override;
|
||||
NS_IMETHOD RemoveEmailAddressAt(uint32_t aIndex) override;
|
||||
NS_IMETHOD AddDirectory(const char *uriName, nsIAbDirectory **childDir) override;
|
||||
NS_IMETHOD GetDatabaseFile(nsIFile **aResult) override;
|
||||
NS_IMETHOD GetDatabase(nsIAddrDatabase **aResult) override;
|
||||
|
||||
// nsIAbDirectory methods:
|
||||
NS_IMETHOD GetChildNodes(nsISimpleEnumerator* *result) override;
|
||||
NS_IMETHOD GetChildCards(nsISimpleEnumerator* *result) override;
|
||||
NS_IMETHOD GetIsQuery(bool *aResult) override;
|
||||
NS_IMETHOD DeleteDirectory(nsIAbDirectory *directory) override;
|
||||
NS_IMETHOD DeleteCards(nsIArray *cards) override;
|
||||
NS_IMETHOD HasCard(nsIAbCard *cards, bool *hasCard) override;
|
||||
NS_IMETHOD HasDirectory(nsIAbDirectory *dir, bool *hasDir) override;
|
||||
NS_IMETHOD HasMailListWithName(const char16_t *aName, bool *aHasList) override;
|
||||
NS_IMETHOD AddMailList(nsIAbDirectory *list, nsIAbDirectory **addedList) override;
|
||||
NS_IMETHOD AddCard(nsIAbCard *card, nsIAbCard **addedCard) override;
|
||||
NS_IMETHOD ModifyCard(nsIAbCard *aModifiedCard) override;
|
||||
NS_IMETHOD DropCard(nsIAbCard *card, bool needToCopyCard) override;
|
||||
NS_IMETHOD EditMailListToDatabase(nsIAbCard *listCard) override;
|
||||
NS_IMETHOD CardForEmailAddress(const nsACString &aEmailAddress,
|
||||
nsIAbCard ** aAbCard) override;
|
||||
NS_IMETHOD GetCardFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool caseSensitive, nsIAbCard **result) override;
|
||||
NS_IMETHOD GetCardsFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool caseSensitive,
|
||||
nsISimpleEnumerator **result) override;
|
||||
|
||||
// nsIAbDirectorySearch methods
|
||||
NS_DECL_NSIABDIRECTORYSEARCH
|
||||
|
||||
// nsIAbDirSearchListener methods
|
||||
NS_DECL_NSIABDIRSEARCHLISTENER
|
||||
|
||||
protected:
|
||||
virtual ~nsAbMDBDirectory();
|
||||
nsresult NotifyPropertyChanged(nsIAbDirectory *list, const char *property, const char16_t* oldValue, const char16_t* newValue);
|
||||
nsresult NotifyItemAdded(nsISupports *item);
|
||||
nsresult NotifyItemDeleted(nsISupports *item);
|
||||
nsresult NotifyItemChanged(nsISupports *item);
|
||||
nsresult RemoveCardFromAddressList(nsIAbCard* card);
|
||||
|
||||
nsresult GetAbDatabase();
|
||||
nsCOMPtr<nsIAddrDatabase> mDatabase;
|
||||
|
||||
nsCOMArray<nsIAbDirectory> mSubDirectories;
|
||||
|
||||
int32_t mContext;
|
||||
bool mPerformingQuery;
|
||||
|
||||
nsInterfaceHashtable<nsISupportsHashKey, nsIAbCard> mSearchCache;
|
||||
};
|
||||
|
||||
#endif
|
||||
1422
mailnews/addrbook/src/nsAbManager.cpp
Normal file
1422
mailnews/addrbook/src/nsAbManager.cpp
Normal file
File diff suppressed because it is too large
Load diff
71
mailnews/addrbook/src/nsAbManager.h
Normal file
71
mailnews/addrbook/src/nsAbManager.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __nsAbManager_h
|
||||
#define __nsAbManager_h
|
||||
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICommandLineHandler.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIAbDirFactoryService.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
|
||||
class nsIAbLDAPAttributeMap;
|
||||
|
||||
class nsAbManager : public nsIAbManager,
|
||||
public nsICommandLineHandler,
|
||||
public nsIObserver
|
||||
{
|
||||
|
||||
public:
|
||||
nsAbManager();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIABMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSICOMMANDLINEHANDLER
|
||||
|
||||
nsresult Init();
|
||||
|
||||
private:
|
||||
virtual ~nsAbManager();
|
||||
nsresult GetRootDirectory(nsIAbDirectory **aResult);
|
||||
nsresult ExportDirectoryToDelimitedText(nsIAbDirectory *aDirectory, const char *aDelim,
|
||||
uint32_t aDelimLen, nsIFile *aLocalFile, bool useUTF8);
|
||||
nsresult ExportDirectoryToVCard(nsIAbDirectory *aDirectory, nsIFile *aLocalFile);
|
||||
nsresult ExportDirectoryToLDIF(nsIAbDirectory *aDirectory, nsIFile *aLocalFile);
|
||||
nsresult AppendLDIFForMailList(nsIAbCard *aCard, nsIAbLDAPAttributeMap *aAttrMap, nsACString &aResult);
|
||||
nsresult AppendDNForCard(const char *aProperty, nsIAbCard *aCard, nsIAbLDAPAttributeMap *aAttrMap, nsACString &aResult);
|
||||
nsresult AppendBasicLDIFForCard(nsIAbCard *aCard, nsIAbLDAPAttributeMap *aAttrMap, nsACString &aResult);
|
||||
nsresult AppendProperty(const char *aProperty, const char16_t *aValue, nsACString &aResult);
|
||||
bool IsSafeLDIFString(const char16_t *aStr);
|
||||
|
||||
struct abListener {
|
||||
nsCOMPtr<nsIAbListener> mListener;
|
||||
uint32_t mNotifyFlags;
|
||||
|
||||
abListener(nsIAbListener *aListener, uint32_t aNotifyFlags)
|
||||
: mListener(aListener), mNotifyFlags(aNotifyFlags) {}
|
||||
abListener(const abListener &aListener)
|
||||
: mListener(aListener.mListener), mNotifyFlags(aListener.mNotifyFlags) {}
|
||||
~abListener() {}
|
||||
|
||||
int operator==(nsIAbListener* aListener) const {
|
||||
return mListener == aListener;
|
||||
}
|
||||
int operator==(const abListener &aListener) const {
|
||||
return mListener == aListener.mListener;
|
||||
}
|
||||
};
|
||||
|
||||
nsTObserverArray<abListener> mListeners;
|
||||
nsCOMPtr<nsIAbDirectory> mCacheTopLevelAb;
|
||||
nsInterfaceHashtable<nsCStringHashKey, nsIAbDirectory> mAbStore;
|
||||
};
|
||||
|
||||
#endif
|
||||
47
mailnews/addrbook/src/nsAbOSXCard.h
Normal file
47
mailnews/addrbook/src/nsAbOSXCard.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbOSXCard_h___
|
||||
#define nsAbOSXCard_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbCardProperty.h"
|
||||
|
||||
#define NS_ABOSXCARD_URI_PREFIX NS_ABOSXCARD_PREFIX "://"
|
||||
|
||||
#define NS_IABOSXCARD_IID \
|
||||
{ 0xa7e5b697, 0x772d, 0x4fb5, \
|
||||
{ 0x81, 0x16, 0x23, 0xb7, 0x5a, 0xac, 0x94, 0x56 } }
|
||||
|
||||
class nsIAbOSXCard : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABOSXCARD_IID)
|
||||
|
||||
virtual nsresult Init(const char *aUri) = 0;
|
||||
virtual nsresult Update(bool aNotify) = 0;
|
||||
virtual nsresult GetURI(nsACString &aURI) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIAbOSXCard, NS_IABOSXCARD_IID)
|
||||
|
||||
class nsAbOSXCard : public nsAbCardProperty,
|
||||
public nsIAbOSXCard
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsresult Update(bool aNotify) override;
|
||||
nsresult GetURI(nsACString &aURI) override;
|
||||
nsresult Init(const char *aUri) override;
|
||||
// this is needed so nsAbOSXUtils.mm can get at nsAbCardProperty
|
||||
friend class nsAbOSXUtils;
|
||||
private:
|
||||
nsCString mURI;
|
||||
|
||||
virtual ~nsAbOSXCard() {}
|
||||
};
|
||||
|
||||
#endif // nsAbOSXCard_h___
|
||||
401
mailnews/addrbook/src/nsAbOSXCard.mm
Normal file
401
mailnews/addrbook/src/nsAbOSXCard.mm
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbOSXCard.h"
|
||||
#include "nsAbOSXDirectory.h"
|
||||
#include "nsAbOSXUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include <AddressBook/AddressBook.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAbOSXCard,
|
||||
nsAbCardProperty,
|
||||
nsIAbOSXCard)
|
||||
|
||||
#ifdef DEBUG
|
||||
static ABPropertyType
|
||||
GetPropertType(ABRecord *aCard, NSString *aProperty)
|
||||
{
|
||||
ABPropertyType propertyType = kABErrorInProperty;
|
||||
if ([aCard isKindOfClass:[ABPerson class]])
|
||||
propertyType = [ABPerson typeOfProperty:aProperty];
|
||||
else if ([aCard isKindOfClass:[ABGroup class]])
|
||||
propertyType = [ABGroup typeOfProperty:aProperty];
|
||||
return propertyType;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
SetStringProperty(nsAbOSXCard *aCard, const nsString &aValue,
|
||||
const char *aMemberName, bool aNotify,
|
||||
nsIAbManager *aAbManager)
|
||||
{
|
||||
nsString oldValue;
|
||||
nsresult rv = aCard->GetPropertyAsAString(aMemberName, oldValue);
|
||||
if (NS_FAILED(rv))
|
||||
oldValue.Truncate();
|
||||
|
||||
if (!aNotify) {
|
||||
aCard->SetPropertyAsAString(aMemberName, aValue);
|
||||
}
|
||||
else if (!oldValue.Equals(aValue)) {
|
||||
aCard->SetPropertyAsAString(aMemberName, aValue);
|
||||
|
||||
nsISupports *supports = NS_ISUPPORTS_CAST(nsAbCardProperty*, aCard);
|
||||
|
||||
aAbManager->NotifyItemPropertyChanged(supports, aMemberName,
|
||||
oldValue.get(), aValue.get());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SetStringProperty(nsAbOSXCard *aCard, NSString *aValue, const char *aMemberName,
|
||||
bool aNotify, nsIAbManager *aAbManager)
|
||||
{
|
||||
nsAutoString value;
|
||||
if (aValue)
|
||||
AppendToString(aValue, value);
|
||||
|
||||
SetStringProperty(aCard, value, aMemberName, aNotify, aAbManager);
|
||||
}
|
||||
|
||||
static void
|
||||
MapStringProperty(nsAbOSXCard *aCard, ABRecord *aOSXCard, NSString *aProperty,
|
||||
const char *aMemberName, bool aNotify,
|
||||
nsIAbManager *aAbManager)
|
||||
{
|
||||
NS_ASSERTION(aProperty, "This is bad! You asked for an unresolved symbol.");
|
||||
NS_ASSERTION(GetPropertType(aOSXCard, aProperty) == kABStringProperty,
|
||||
"Wrong type!");
|
||||
|
||||
SetStringProperty(aCard, [aOSXCard valueForProperty:aProperty], aMemberName,
|
||||
aNotify, aAbManager);
|
||||
}
|
||||
|
||||
static ABMutableMultiValue*
|
||||
GetMultiValue(ABRecord *aCard, NSString *aProperty)
|
||||
{
|
||||
NS_ASSERTION(aProperty, "This is bad! You asked for an unresolved symbol.");
|
||||
NS_ASSERTION(GetPropertType(aCard, aProperty) & kABMultiValueMask,
|
||||
"Wrong type!");
|
||||
|
||||
return [aCard valueForProperty:aProperty];
|
||||
}
|
||||
|
||||
static void
|
||||
MapDate(nsAbOSXCard *aCard, NSDate *aDate, const char *aYearPropName,
|
||||
const char *aMonthPropName, const char *aDayPropName, bool aNotify,
|
||||
nsIAbManager *aAbManager)
|
||||
{
|
||||
// XXX Should we pass a format and timezone?
|
||||
NSCalendarDate *date = [aDate dateWithCalendarFormat:nil timeZone:nil];
|
||||
|
||||
nsAutoString value;
|
||||
value.AppendInt(static_cast<int32_t>([date yearOfCommonEra]));
|
||||
SetStringProperty(aCard, value, aYearPropName, aNotify, aAbManager);
|
||||
value.Truncate();
|
||||
value.AppendInt(static_cast<int32_t>([date monthOfYear]));
|
||||
SetStringProperty(aCard, value, aMonthPropName, aNotify, aAbManager);
|
||||
value.Truncate();
|
||||
value.AppendInt(static_cast<int32_t>([date dayOfMonth]));
|
||||
SetStringProperty(aCard, value, aDayPropName, aNotify, aAbManager);
|
||||
}
|
||||
|
||||
static bool
|
||||
MapMultiValue(nsAbOSXCard *aCard, ABRecord *aOSXCard,
|
||||
const nsAbOSXPropertyMap &aMap, bool aNotify,
|
||||
nsIAbManager *aAbManager)
|
||||
{
|
||||
ABMultiValue *value = GetMultiValue(aOSXCard, aMap.mOSXProperty);
|
||||
if (value) {
|
||||
unsigned int j;
|
||||
unsigned int count = [value count];
|
||||
for (j = 0; j < count; ++j) {
|
||||
if ([[value labelAtIndex:j] isEqualToString:aMap.mOSXLabel]) {
|
||||
NSString *stringValue = (aMap.mOSXKey)
|
||||
? [[value valueAtIndex:j] objectForKey:aMap.mOSXKey]
|
||||
: [value valueAtIndex:j];
|
||||
|
||||
SetStringProperty(aCard, stringValue, aMap.mPropertyName, aNotify,
|
||||
aAbManager);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// String wasn't found, set value of card to empty if it was set previously
|
||||
SetStringProperty(aCard, EmptyString(), aMap.mPropertyName, aNotify,
|
||||
aAbManager);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Maps Address Book's instant messenger name to the corresponding nsIAbCard field name.
|
||||
static const char*
|
||||
InstantMessengerFieldName(NSString* aInstantMessengerName)
|
||||
{
|
||||
if ([aInstantMessengerName isEqualToString:@"AIMInstant"]) {
|
||||
return "_AimScreenName";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"GoogleTalkInstant"]) {
|
||||
return "_GoogleTalk";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"ICQInstant"]) {
|
||||
return "_ICQ";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"JabberInstant"]) {
|
||||
return "_JabberId";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"MSNInstant"]) {
|
||||
return "_MSN";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"QQInstant"]) {
|
||||
return "_QQ";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"SkypeInstant"]) {
|
||||
return "_Skype";
|
||||
}
|
||||
if ([aInstantMessengerName isEqualToString:@"YahooInstant"]) {
|
||||
return "_Yahoo";
|
||||
}
|
||||
|
||||
// Fall back to AIM for everything else.
|
||||
// We don't have nsIAbCard fields for FacebookInstant and GaduGaduInstant.
|
||||
return "_AimScreenName";
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAbOSXCard::Init(const char *aUri)
|
||||
{
|
||||
if (strncmp(aUri, NS_ABOSXCARD_URI_PREFIX,
|
||||
sizeof(NS_ABOSXCARD_URI_PREFIX) - 1) != 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mURI = aUri;
|
||||
|
||||
SetLocalId(nsDependentCString(aUri));
|
||||
|
||||
return Update(false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAbOSXCard::GetURI(nsACString &aURI)
|
||||
{
|
||||
if (mURI.IsEmpty())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
aURI = mURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAbOSXCard::Update(bool aNotify)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
|
||||
|
||||
const char *uid = &((mURI.get())[16]);
|
||||
ABRecord *card = [addressBook recordForUniqueId:[NSString stringWithUTF8String:uid]];
|
||||
NS_ENSURE_TRUE(card, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager;
|
||||
nsresult rv;
|
||||
if (aNotify) {
|
||||
abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if ([card isKindOfClass:[ABGroup class]]) {
|
||||
m_IsMailList = true;
|
||||
m_MailListURI.AssignLiteral(NS_ABOSXDIRECTORY_URI_PREFIX);
|
||||
m_MailListURI.Append(uid);
|
||||
MapStringProperty(this, card, kABGroupNameProperty, "DisplayName", aNotify,
|
||||
abManager);
|
||||
MapStringProperty(this, card, kABGroupNameProperty, "LastName", aNotify,
|
||||
abManager);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool foundHome = false, foundWork = false;
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < nsAbOSXUtils::kPropertyMapSize; ++i) {
|
||||
const nsAbOSXPropertyMap &propertyMap = nsAbOSXUtils::kPropertyMap[i];
|
||||
if (!propertyMap.mOSXProperty)
|
||||
continue;
|
||||
|
||||
if (propertyMap.mOSXLabel) {
|
||||
if (MapMultiValue(this, card, propertyMap, aNotify,
|
||||
abManager) && propertyMap.mOSXProperty == kABAddressProperty) {
|
||||
if (propertyMap.mOSXLabel == kABAddressHomeLabel)
|
||||
foundHome = true;
|
||||
else
|
||||
foundWork = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
MapStringProperty(this, card, propertyMap.mOSXProperty,
|
||||
propertyMap.mPropertyName, aNotify, abManager);
|
||||
}
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if (kABPersonFlags)
|
||||
flags = [[card valueForProperty:kABPersonFlags] intValue];
|
||||
|
||||
#define SET_STRING(_value, _name, _notify, _session) \
|
||||
SetStringProperty(this, _value, #_name, _notify, _session)
|
||||
|
||||
// If kABShowAsCompany is set we use the company name as display name.
|
||||
if (kABPersonFlags && (flags & kABShowAsCompany)) {
|
||||
nsString company;
|
||||
nsresult rv = GetPropertyAsAString(kCompanyProperty, company);
|
||||
if (NS_FAILED(rv))
|
||||
company.Truncate();
|
||||
SET_STRING(company, DisplayName, aNotify, abManager);
|
||||
}
|
||||
else {
|
||||
// Use the order used in the OS X address book to set DisplayName.
|
||||
int order = kABPersonFlags && (flags & kABNameOrderingMask);
|
||||
if (kABPersonFlags && (order == kABDefaultNameOrdering)) {
|
||||
order = [addressBook defaultNameOrdering];
|
||||
}
|
||||
|
||||
nsAutoString displayName, tempName;
|
||||
if (kABPersonFlags && (order == kABFirstNameFirst)) {
|
||||
GetFirstName(tempName);
|
||||
displayName.Append(tempName);
|
||||
|
||||
GetLastName(tempName);
|
||||
|
||||
// Only append a space if the last name and the first name are not empty
|
||||
if (!tempName.IsEmpty() && !displayName.IsEmpty())
|
||||
displayName.Append(' ');
|
||||
|
||||
displayName.Append(tempName);
|
||||
}
|
||||
else {
|
||||
GetLastName(tempName);
|
||||
displayName.Append(tempName);
|
||||
|
||||
GetFirstName(tempName);
|
||||
|
||||
// Only append a space if the last name and the first name are not empty
|
||||
if (!tempName.IsEmpty() && !displayName.IsEmpty())
|
||||
displayName.Append(' ');
|
||||
|
||||
displayName.Append(tempName);
|
||||
}
|
||||
SET_STRING(displayName, DisplayName, aNotify, abManager);
|
||||
}
|
||||
|
||||
ABMultiValue *value = GetMultiValue(card, kABEmailProperty);
|
||||
if (value) {
|
||||
unsigned int count = [value count];
|
||||
if (count > 0) {
|
||||
unsigned int j = [value indexForIdentifier:[value primaryIdentifier]];
|
||||
|
||||
if (j < count)
|
||||
SET_STRING([value valueAtIndex:j], PrimaryEmail, aNotify,
|
||||
abManager);
|
||||
|
||||
// If j is 0 (first in the list) we want the second in the list
|
||||
// (index 1), if j is anything else we want the first in the list
|
||||
// (index 0).
|
||||
j = (j == 0);
|
||||
if (j < count)
|
||||
SET_STRING([value valueAtIndex:j], SecondEmail, aNotify,
|
||||
abManager);
|
||||
}
|
||||
}
|
||||
|
||||
// We map the first home address we can find and the first work address
|
||||
// we can find. If we find none, we map the primary address to the home
|
||||
// address.
|
||||
if (!foundHome && !foundWork) {
|
||||
value = GetMultiValue(card, kABAddressProperty);
|
||||
if (value) {
|
||||
unsigned int count = [value count];
|
||||
unsigned int j = [value indexForIdentifier:[value primaryIdentifier]];
|
||||
|
||||
if (j < count) {
|
||||
NSDictionary *address = [value valueAtIndex:j];
|
||||
if (address) {
|
||||
SET_STRING([address objectForKey:kABAddressStreetKey],
|
||||
HomeAddress, aNotify, abManager);
|
||||
SET_STRING([address objectForKey:kABAddressCityKey],
|
||||
HomeCity, aNotify, abManager);
|
||||
SET_STRING([address objectForKey:kABAddressStateKey],
|
||||
HomeState, aNotify, abManager);
|
||||
SET_STRING([address objectForKey:kABAddressZIPKey],
|
||||
HomeZipCode, aNotify, abManager);
|
||||
SET_STRING([address objectForKey:kABAddressCountryKey],
|
||||
HomeCountry, aNotify, abManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This was kABAIMInstantProperty previously, but it was deprecated in OS X 10.7.
|
||||
value = GetMultiValue(card, kABInstantMessageProperty);
|
||||
if (value) {
|
||||
unsigned int count = [value count];
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
id imValue = [value valueAtIndex:i];
|
||||
// Depending on the macOS version, imValue can be an NSString or an NSDictionary.
|
||||
if ([imValue isKindOfClass:[NSString class]]) {
|
||||
if (i == [value indexForIdentifier:[value primaryIdentifier]]) {
|
||||
SET_STRING(imValue, _AimScreenName, aNotify, abManager);
|
||||
}
|
||||
} else if ([imValue isKindOfClass:[NSDictionary class]]) {
|
||||
NSString* instantMessageService = [imValue objectForKey:@"InstantMessageService"];
|
||||
const char* fieldName = InstantMessengerFieldName(instantMessageService);
|
||||
NSString* userName = [imValue objectForKey:@"InstantMessageUsername"];
|
||||
SetStringProperty(this, userName, fieldName, aNotify, abManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAP_DATE(_date, _name, _notify, _session) \
|
||||
MapDate(this, _date, #_name"Year", #_name"Month", #_name"Day", _notify, \
|
||||
_session)
|
||||
|
||||
NSDate *date = [card valueForProperty:kABBirthdayProperty];
|
||||
if (date)
|
||||
MAP_DATE(date, Birth, aNotify, abManager);
|
||||
|
||||
if (kABOtherDatesProperty) {
|
||||
value = GetMultiValue(card, kABOtherDatesProperty);
|
||||
if (value) {
|
||||
unsigned int j, count = [value count];
|
||||
for (j = 0; j < count; ++j) {
|
||||
if ([[value labelAtIndex:j] isEqualToString:kABAnniversaryLabel]) {
|
||||
date = [value valueAtIndex:j];
|
||||
if (date) {
|
||||
MAP_DATE(date, Anniversary, aNotify, abManager);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef MAP_DATE
|
||||
#undef SET_STRING
|
||||
|
||||
date = [card valueForProperty:kABModificationDateProperty];
|
||||
if (date)
|
||||
SetPropertyAsUint32("LastModifiedDate",
|
||||
uint32_t([date timeIntervalSince1970]));
|
||||
// XXX No way to notify about this?
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
50
mailnews/addrbook/src/nsAbOSXDirFactory.cpp
Normal file
50
mailnews/addrbook/src/nsAbOSXDirFactory.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbOSXDirFactory.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsAbOSXDirectory.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbOSXDirFactory, nsIAbDirFactory)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbOSXDirFactory::GetDirectories(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
const nsACString &aPrefName,
|
||||
nsISimpleEnumerator **aDirectories)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectories);
|
||||
|
||||
*aDirectories = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
rv = abManager->GetDirectory(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX "/"),
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbOSXDirectory> osxDirectory(do_QueryInterface(directory, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = osxDirectory->AssertChildNodes();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_NewSingletonEnumerator(aDirectories, osxDirectory);
|
||||
}
|
||||
|
||||
// No actual deletion, since you cannot create the address books from Mozilla.
|
||||
NS_IMETHODIMP
|
||||
nsAbOSXDirFactory::DeleteDirectory(nsIAbDirectory *aDirectory)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
21
mailnews/addrbook/src/nsAbOSXDirFactory.h
Normal file
21
mailnews/addrbook/src/nsAbOSXDirFactory.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbOSXDirFactory_h___
|
||||
#define nsAbOSXDirFactory_h___
|
||||
|
||||
#include "nsIAbDirFactory.h"
|
||||
|
||||
class nsAbOSXDirFactory final : public nsIAbDirFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRFACTORY
|
||||
|
||||
private:
|
||||
~nsAbOSXDirFactory() {}
|
||||
};
|
||||
|
||||
#endif // nsAbOSXDirFactory_h___
|
||||
126
mailnews/addrbook/src/nsAbOSXDirectory.h
Normal file
126
mailnews/addrbook/src/nsAbOSXDirectory.h
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbOSXDirectory_h___
|
||||
#define nsAbOSXDirectory_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsAbDirProperty.h"
|
||||
#include "nsIAbDirectoryQuery.h"
|
||||
#include "nsIAbDirectorySearch.h"
|
||||
#include "nsIAbDirSearchListener.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsAbOSXCard.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
class nsIAbManager;
|
||||
class nsIAbBooleanExpression;
|
||||
|
||||
#define NS_ABOSXDIRECTORY_URI_PREFIX NS_ABOSXDIRECTORY_PREFIX "://"
|
||||
|
||||
#define NS_IABOSXDIRECTORY_IID \
|
||||
{ 0x87ee4bd9, 0x8552, 0x498f, \
|
||||
{ 0x80, 0x85, 0x34, 0xf0, 0x2a, 0xbb, 0x56, 0x16 } }
|
||||
|
||||
class nsIAbOSXDirectory : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABOSXDIRECTORY_IID)
|
||||
|
||||
virtual nsresult AssertChildNodes() = 0;
|
||||
virtual nsresult Update() = 0;
|
||||
virtual nsresult AssertDirectory(nsIAbManager *aManager,
|
||||
nsIAbDirectory *aDirectory) = 0;
|
||||
virtual nsresult AssertCard(nsIAbManager *aManager,
|
||||
nsIAbCard *aCard) = 0;
|
||||
virtual nsresult UnassertCard(nsIAbManager *aManager,
|
||||
nsIAbCard *aCard,
|
||||
nsIMutableArray *aCardList) = 0;
|
||||
virtual nsresult UnassertDirectory(nsIAbManager *aManager,
|
||||
nsIAbDirectory *aDirectory) = 0;
|
||||
virtual nsresult DeleteUid(const nsACString &aUid) = 0;
|
||||
virtual nsresult GetURI(nsACString &aURI) = 0;
|
||||
virtual nsresult Init(const char *aUri) = 0;
|
||||
virtual nsresult GetCardByUri(const nsACString &aUri, nsIAbOSXCard **aResult) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIAbOSXDirectory, NS_IABOSXDIRECTORY_IID)
|
||||
|
||||
class nsAbOSXDirectory final : public nsAbDirProperty,
|
||||
public nsIAbDirSearchListener,
|
||||
public nsIAbOSXDirectory
|
||||
{
|
||||
public:
|
||||
nsAbOSXDirectory();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIABDIRSEARCHLISTENER
|
||||
|
||||
// nsIAbOSXDirectory method
|
||||
NS_IMETHOD Init(const char *aUri) override;
|
||||
|
||||
// nsAbDirProperty methods
|
||||
NS_IMETHOD GetReadOnly(bool *aReadOnly) override;
|
||||
NS_IMETHOD GetChildCards(nsISimpleEnumerator **aCards) override;
|
||||
NS_IMETHOD GetChildNodes(nsISimpleEnumerator **aNodes) override;
|
||||
NS_IMETHOD GetIsQuery(bool *aResult) override;
|
||||
NS_IMETHOD HasCard(nsIAbCard *aCard, bool *aHasCard) override;
|
||||
NS_IMETHOD HasDirectory(nsIAbDirectory *aDirectory, bool *aHasDirectory) override;
|
||||
NS_IMETHOD GetURI(nsACString &aURI) override;
|
||||
NS_IMETHOD GetCardFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool caseSensitive,
|
||||
nsIAbCard **aResult) override;
|
||||
NS_IMETHOD GetCardsFromProperty(const char *aProperty,
|
||||
const nsACString &aValue,
|
||||
bool aCaseSensitive,
|
||||
nsISimpleEnumerator **aResult) override;
|
||||
NS_IMETHOD CardForEmailAddress(const nsACString &aEmailAddress,
|
||||
nsIAbCard **aResult) override;
|
||||
|
||||
// nsIAbOSXDirectory
|
||||
nsresult AssertChildNodes() override;
|
||||
nsresult AssertDirectory(nsIAbManager *aManager,
|
||||
nsIAbDirectory *aDirectory) override;
|
||||
nsresult AssertCard(nsIAbManager *aManager,
|
||||
nsIAbCard *aCard) override;
|
||||
nsresult UnassertCard(nsIAbManager *aManager,
|
||||
nsIAbCard *aCard,
|
||||
nsIMutableArray *aCardList) override;
|
||||
nsresult UnassertDirectory(nsIAbManager *aManager,
|
||||
nsIAbDirectory *aDirectory) override;
|
||||
|
||||
nsresult Update() override;
|
||||
|
||||
nsresult DeleteUid(const nsACString &aUid) override;
|
||||
|
||||
nsresult GetCardByUri(const nsACString &aUri, nsIAbOSXCard **aResult) override;
|
||||
|
||||
nsresult GetRootOSXDirectory(nsIAbOSXDirectory **aResult);
|
||||
|
||||
private:
|
||||
~nsAbOSXDirectory();
|
||||
nsresult FallbackSearch(nsIAbBooleanExpression *aExpression,
|
||||
nsISimpleEnumerator **aCards);
|
||||
|
||||
// This is a list of nsIAbCards, kept separate from m_AddressList because:
|
||||
// - nsIAbDirectory items that are mailing lists, must keep a list of
|
||||
// nsIAbCards in m_AddressList, however
|
||||
// - nsIAbDirectory items that are address books, must keep a list of
|
||||
// nsIAbDirectory (i.e. mailing lists) in m_AddressList, AND no nsIAbCards.
|
||||
//
|
||||
// This wasn't too bad for mork, as that just gets a list from its database,
|
||||
// but because we store our own copy of the list, we must store a separate
|
||||
// list of nsIAbCards here. nsIMutableArray is used, because then it is
|
||||
// interchangeable with m_AddressList.
|
||||
nsCOMPtr<nsIMutableArray> mCardList;
|
||||
nsInterfaceHashtable<nsCStringHashKey, nsIAbOSXCard> mCardStore;
|
||||
nsCOMPtr<nsIAbOSXDirectory> mCacheTopLevelOSXAb;
|
||||
};
|
||||
|
||||
#endif // nsAbOSXDirectory_h___
|
||||
1374
mailnews/addrbook/src/nsAbOSXDirectory.mm
Normal file
1374
mailnews/addrbook/src/nsAbOSXDirectory.mm
Normal file
File diff suppressed because it is too large
Load diff
36
mailnews/addrbook/src/nsAbOSXUtils.h
Normal file
36
mailnews/addrbook/src/nsAbOSXUtils.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbOSXUtils_h___
|
||||
#define nsAbOSXUtils_h___
|
||||
|
||||
#include <Foundation/NSString.h>
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsString;
|
||||
class nsCString;
|
||||
class nsAbCardProperty;
|
||||
|
||||
NSString *WrapString(const nsString &aString);
|
||||
void AppendToString(const NSString *aString, nsString &aResult);
|
||||
void AssignToString(const NSString *aString, nsString &aResult);
|
||||
void AppendToCString(const NSString *aString, nsCString &aResult);
|
||||
|
||||
struct nsAbOSXPropertyMap
|
||||
{
|
||||
NSString * const mOSXProperty;
|
||||
NSString * const mOSXLabel;
|
||||
NSString * const mOSXKey;
|
||||
const char *mPropertyName;
|
||||
};
|
||||
|
||||
class nsAbOSXUtils
|
||||
{
|
||||
public:
|
||||
static const nsAbOSXPropertyMap kPropertyMap[];
|
||||
static const uint32_t kPropertyMapSize;
|
||||
};
|
||||
|
||||
#endif // nsAbOSXUtils_h___
|
||||
117
mailnews/addrbook/src/nsAbOSXUtils.mm
Normal file
117
mailnews/addrbook/src/nsAbOSXUtils.mm
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbOSXUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsAbOSXCard.h"
|
||||
#include "nsMemory.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
using namespace mozilla;
|
||||
|
||||
#include <AddressBook/AddressBook.h>
|
||||
#define kABDepartmentProperty (kABDepartmentProperty ? kABDepartmentProperty : @"ABDepartment")
|
||||
|
||||
NSString*
|
||||
WrapString(const nsString &aString)
|
||||
{
|
||||
unichar* chars = reinterpret_cast<unichar*>(const_cast<char16_t*>(aString.get()));
|
||||
|
||||
return [NSString stringWithCharacters:chars
|
||||
length:aString.Length()];
|
||||
}
|
||||
|
||||
void
|
||||
AppendToString(const NSString *aString, nsString &aResult)
|
||||
{
|
||||
if (aString) {
|
||||
const char *chars = [aString UTF8String];
|
||||
if (chars) {
|
||||
aResult.Append(NS_ConvertUTF8toUTF16(chars));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignToString(const NSString *aString, nsString &aResult)
|
||||
{
|
||||
if (aString) {
|
||||
const char *chars = [aString UTF8String];
|
||||
if (chars)
|
||||
CopyUTF8toUTF16(nsDependentCString(chars), aResult);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AppendToCString(const NSString *aString, nsCString &aResult)
|
||||
{
|
||||
if (aString) {
|
||||
const char *chars = [aString UTF8String];
|
||||
if (chars) {
|
||||
aResult.Append(chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some properties can't be easily mapped back and forth.
|
||||
#define DONT_MAP(moz_name, osx_property, osx_label, osx_key)
|
||||
|
||||
#define DEFINE_PROPERTY(moz_name, osx_property, osx_label, osx_key) \
|
||||
{ osx_property, osx_label, osx_key, #moz_name },
|
||||
|
||||
const nsAbOSXPropertyMap nsAbOSXUtils::kPropertyMap[] = {
|
||||
DEFINE_PROPERTY(FirstName, kABFirstNameProperty, nil, nil)
|
||||
DEFINE_PROPERTY(LastName, kABLastNameProperty, nil, nil)
|
||||
DONT_MAP("DisplayName", nil, nil, nil)
|
||||
DEFINE_PROPERTY(PhoneticFirstName, kABFirstNamePhoneticProperty, nil, nil)
|
||||
DEFINE_PROPERTY(PhoneticLastName, kABLastNamePhoneticProperty, nil, nil)
|
||||
DEFINE_PROPERTY(NickName, kABNicknameProperty, nil, nil)
|
||||
DONT_MAP(PrimaryEmail, kABEmailProperty, nil, nil)
|
||||
DONT_MAP(SecondEmail, kABEmailProperty, nil, nil)
|
||||
DEFINE_PROPERTY(WorkPhone, kABPhoneProperty, kABPhoneWorkLabel, nil)
|
||||
DEFINE_PROPERTY(HomePhone, kABPhoneProperty, kABPhoneHomeLabel, nil)
|
||||
DEFINE_PROPERTY(FaxNumber, kABPhoneProperty, kABPhoneWorkFAXLabel, nil)
|
||||
DEFINE_PROPERTY(PagerNumber, kABPhoneProperty, kABPhonePagerLabel, nil)
|
||||
DEFINE_PROPERTY(CellularNumber, kABPhoneProperty, kABPhoneMobileLabel, nil)
|
||||
DEFINE_PROPERTY(HomeAddress, kABAddressProperty, kABAddressHomeLabel,
|
||||
kABAddressStreetKey)
|
||||
DEFINE_PROPERTY(HomeCity, kABAddressProperty, kABAddressHomeLabel,
|
||||
kABAddressCityKey)
|
||||
DEFINE_PROPERTY(HomeState, kABAddressProperty, kABAddressHomeLabel,
|
||||
kABAddressStateKey)
|
||||
DEFINE_PROPERTY(HomeZipCode, kABAddressProperty, kABAddressHomeLabel,
|
||||
kABAddressZIPKey)
|
||||
DEFINE_PROPERTY(HomeCountry, kABAddressProperty, kABAddressHomeLabel,
|
||||
kABAddressCountryKey)
|
||||
DEFINE_PROPERTY(WorkAddress, kABAddressProperty, kABAddressWorkLabel,
|
||||
kABAddressStreetKey)
|
||||
DEFINE_PROPERTY(WorkCity, kABAddressProperty, kABAddressWorkLabel,
|
||||
kABAddressCityKey)
|
||||
DEFINE_PROPERTY(WorkState, kABAddressProperty, kABAddressWorkLabel,
|
||||
kABAddressStateKey)
|
||||
DEFINE_PROPERTY(WorkZipCode, kABAddressProperty, kABAddressWorkLabel,
|
||||
kABAddressZIPKey)
|
||||
DEFINE_PROPERTY(WorkCountry, kABAddressProperty, kABAddressWorkLabel,
|
||||
kABAddressCountryKey)
|
||||
DEFINE_PROPERTY(JobTitle, kABJobTitleProperty, nil, nil)
|
||||
DEFINE_PROPERTY(Department, kABDepartmentProperty, nil, nil)
|
||||
DEFINE_PROPERTY(Company, kABOrganizationProperty, nil, nil)
|
||||
// This was kABAIMInstantProperty previously, but it was deprecated in OS X 10.7.
|
||||
DONT_MAP(_AimScreenName, kABInstantMessageProperty, nil, nil)
|
||||
DEFINE_PROPERTY(WebPage1, kABHomePageProperty, nil, nil)
|
||||
DONT_MAP(WebPage2, kABHomePageProperty, nil, nil)
|
||||
DONT_MAP(BirthYear, "birthyear", nil, nil)
|
||||
DONT_MAP(BirthMonth, "birthmonth", nil, nil)
|
||||
DONT_MAP(BirthDay, "birthday", nil, nil)
|
||||
DONT_MAP(Custom1, "custom1", nil, nil)
|
||||
DONT_MAP(Custom2, "custom2", nil, nil)
|
||||
DONT_MAP(Custom3, "custom3", nil, nil)
|
||||
DONT_MAP(Custom4, "custom4", nil, nil)
|
||||
DEFINE_PROPERTY(Note, kABNoteProperty, nil, nil)
|
||||
DONT_MAP("PreferMailFormat", nil, nil, nil)
|
||||
DONT_MAP("LastModifiedDate", modifytimestamp, nil, nil)
|
||||
};
|
||||
|
||||
const uint32_t nsAbOSXUtils::kPropertyMapSize =
|
||||
ArrayLength(nsAbOSXUtils::kPropertyMap);
|
||||
87
mailnews/addrbook/src/nsAbOutlookDirFactory.cpp
Normal file
87
mailnews/addrbook/src/nsAbOutlookDirFactory.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "nsAbOutlookDirFactory.h"
|
||||
#include "nsAbWinHelper.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gAbOutlookDirFactoryLog
|
||||
= PR_NewLogModule("nsAbOutlookDirFactoryLog");
|
||||
#endif
|
||||
|
||||
#define PRINTF(args) MOZ_LOG(nsAbOutlookDirFactoryLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAbOutlookDirFactory, nsIAbDirFactory)
|
||||
|
||||
nsAbOutlookDirFactory::nsAbOutlookDirFactory(void)
|
||||
{
|
||||
}
|
||||
|
||||
nsAbOutlookDirFactory::~nsAbOutlookDirFactory(void)
|
||||
{
|
||||
}
|
||||
|
||||
extern const char *kOutlookDirectoryScheme;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbOutlookDirFactory::GetDirectories(const nsAString &aDirName,
|
||||
const nsACString &aURI,
|
||||
const nsACString &aPrefName,
|
||||
nsISimpleEnumerator **aDirectories)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectories);
|
||||
|
||||
*aDirectories = nullptr;
|
||||
nsresult rv = NS_OK;
|
||||
nsCString stub;
|
||||
nsCString entry;
|
||||
nsAbWinType abType = getAbWinType(kOutlookDirectoryScheme,
|
||||
nsCString(aURI).get(), stub, entry);
|
||||
|
||||
if (abType == nsAbWinType_Unknown) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAbWinHelperGuard mapiAddBook(abType);
|
||||
nsMapiEntryArray folders;
|
||||
ULONG nbFolders = 0;
|
||||
nsCOMPtr<nsIMutableArray> directories(do_CreateInstance(NS_ARRAY_CONTRACTID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!mapiAddBook->IsOK() || !mapiAddBook->GetFolders(folders)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString entryId;
|
||||
nsAutoCString uri;
|
||||
|
||||
for (ULONG i = 0; i < folders.mNbEntries; ++i) {
|
||||
folders.mEntries[i].ToString(entryId);
|
||||
buildAbWinUri(kOutlookDirectoryScheme, abType, uri);
|
||||
uri.Append(entryId);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
rv = abManager->GetDirectory(uri, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
directories->AppendElement(directory, false);
|
||||
}
|
||||
return NS_NewArrayEnumerator(aDirectories, directories);
|
||||
}
|
||||
|
||||
// No actual deletion, since you cannot create the address books from Mozilla.
|
||||
NS_IMETHODIMP nsAbOutlookDirFactory::DeleteDirectory(nsIAbDirectory *aDirectory)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
22
mailnews/addrbook/src/nsAbOutlookDirFactory.h
Normal file
22
mailnews/addrbook/src/nsAbOutlookDirFactory.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsAbOutlookDirFactory_h___
|
||||
#define nsAbOutlookDirFactory_h___
|
||||
|
||||
#include "nsIAbDirFactory.h"
|
||||
|
||||
class nsAbOutlookDirFactory : public nsIAbDirFactory
|
||||
{
|
||||
public:
|
||||
nsAbOutlookDirFactory(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABDIRFACTORY
|
||||
|
||||
private:
|
||||
virtual ~nsAbOutlookDirFactory(void);
|
||||
};
|
||||
|
||||
#endif // nsAbOutlookDirFactory_h___
|
||||
1539
mailnews/addrbook/src/nsAbOutlookDirectory.cpp
Normal file
1539
mailnews/addrbook/src/nsAbOutlookDirectory.cpp
Normal file
File diff suppressed because it is too large
Load diff
152
mailnews/addrbook/src/nsAbOutlookDirectory.h
Normal file
152
mailnews/addrbook/src/nsAbOutlookDirectory.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsAbOutlookDirectory_h___
|
||||
#define nsAbOutlookDirectory_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbDirProperty.h"
|
||||
#include "nsIAbDirectoryQuery.h"
|
||||
#include "nsIAbDirectorySearch.h"
|
||||
#include "nsIAbDirSearchListener.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsAbWinHelper.h"
|
||||
|
||||
struct nsMapiEntry ;
|
||||
|
||||
class nsAbOutlookDirectory : public nsAbDirProperty, // nsIAbDirectory
|
||||
public nsIAbDirectoryQuery,
|
||||
public nsIAbDirectorySearch,
|
||||
public nsIAbDirSearchListener,
|
||||
public nsIAbDirectoryQueryResultListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIABDIRSEARCHLISTENER
|
||||
NS_DECL_NSIABDIRECTORYQUERYRESULTLISTENER
|
||||
|
||||
nsAbOutlookDirectory(void);
|
||||
|
||||
// nsAbDirProperty methods
|
||||
NS_IMETHOD GetDirType(int32_t *aDirType) override;
|
||||
NS_IMETHOD GetURI(nsACString &aURI) override;
|
||||
NS_IMETHOD GetChildCards(nsISimpleEnumerator **aCards) override;
|
||||
NS_IMETHOD GetChildNodes(nsISimpleEnumerator **aNodes) override;
|
||||
NS_IMETHOD GetIsQuery(bool *aResult) override;
|
||||
NS_IMETHOD HasCard(nsIAbCard *aCard, bool *aHasCard) override;
|
||||
NS_IMETHOD HasDirectory(nsIAbDirectory *aDirectory, bool *aHasDirectory) override;
|
||||
NS_IMETHOD DeleteCards(nsIArray *aCardList) override;
|
||||
NS_IMETHOD DeleteDirectory(nsIAbDirectory *aDirectory) override;
|
||||
NS_IMETHOD UseForAutocomplete(const nsACString &aIdentityKey, bool *aResult) override;
|
||||
NS_IMETHOD AddCard(nsIAbCard *aData, nsIAbCard **addedCard) override;
|
||||
NS_IMETHOD ModifyCard(nsIAbCard *aModifiedCard) override;
|
||||
NS_IMETHOD DropCard(nsIAbCard *aData, bool needToCopyCard) override;
|
||||
NS_IMETHOD AddMailList(nsIAbDirectory *aMailList, nsIAbDirectory **addedList) override;
|
||||
NS_IMETHOD EditMailListToDatabase(nsIAbCard *listCard) override;
|
||||
|
||||
// nsAbDirProperty method
|
||||
NS_IMETHOD Init(const char *aUri) override;
|
||||
// nsIAbDirectoryQuery methods
|
||||
NS_DECL_NSIABDIRECTORYQUERY
|
||||
// nsIAbDirectorySearch methods
|
||||
NS_DECL_NSIABDIRECTORYSEARCH
|
||||
// Perform a MAPI query (function executed in a separate thread)
|
||||
nsresult ExecuteQuery(SRestriction &aRestriction,
|
||||
nsIAbDirSearchListener *aListener,
|
||||
int32_t aResultLimit, int32_t aTimeout,
|
||||
int32_t aThreadId);
|
||||
|
||||
protected:
|
||||
// Retrieve hierarchy as cards, with an optional restriction
|
||||
nsresult GetChildCards(nsIMutableArray *aCards, void *aRestriction);
|
||||
// Retrieve hierarchy as directories
|
||||
nsresult GetChildNodes(nsIMutableArray *aNodes);
|
||||
// Create a new card
|
||||
nsresult CreateCard(nsIAbCard *aData, nsIAbCard **aNewCard);
|
||||
// Notification for the UI
|
||||
nsresult NotifyItemDeletion(nsISupports *aItem);
|
||||
nsresult NotifyItemAddition(nsISupports *aItem);
|
||||
// Force update of MAPI repository for mailing list
|
||||
nsresult CommitAddressList(void);
|
||||
// Read MAPI repository
|
||||
nsresult UpdateAddressList(void);
|
||||
|
||||
nsMapiEntry *mMapiData;
|
||||
// Container for the query threads
|
||||
nsDataHashtable<nsUint32HashKey, PRThread*> mQueryThreads;
|
||||
int32_t mCurrentQueryId;
|
||||
PRLock *mProtector;
|
||||
// Data for the search interfaces
|
||||
nsInterfaceHashtable<nsISupportsHashKey, nsIAbCard> mCardList;
|
||||
int32_t mSearchContext;
|
||||
// Windows AB type
|
||||
uint32_t mAbWinType;
|
||||
|
||||
private:
|
||||
virtual ~nsAbOutlookDirectory(void);
|
||||
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
index_DisplayName = 0,
|
||||
index_EmailAddress,
|
||||
index_FirstName,
|
||||
index_LastName,
|
||||
index_NickName,
|
||||
index_WorkPhoneNumber,
|
||||
index_HomePhoneNumber,
|
||||
index_WorkFaxNumber,
|
||||
index_PagerNumber,
|
||||
index_MobileNumber,
|
||||
index_HomeCity,
|
||||
index_HomeState,
|
||||
index_HomeZip,
|
||||
index_HomeCountry,
|
||||
index_WorkCity,
|
||||
index_WorkState,
|
||||
index_WorkZip,
|
||||
index_WorkCountry,
|
||||
index_JobTitle,
|
||||
index_Department,
|
||||
index_Company,
|
||||
index_WorkWebPage,
|
||||
index_HomeWebPage,
|
||||
index_Comments,
|
||||
index_LastProp
|
||||
};
|
||||
|
||||
static const ULONG OutlookCardMAPIProps[] =
|
||||
{
|
||||
PR_DISPLAY_NAME_W,
|
||||
PR_EMAIL_ADDRESS_W,
|
||||
PR_GIVEN_NAME_W,
|
||||
PR_SURNAME_W,
|
||||
PR_NICKNAME_W,
|
||||
PR_BUSINESS_TELEPHONE_NUMBER_W,
|
||||
PR_HOME_TELEPHONE_NUMBER_W,
|
||||
PR_BUSINESS_FAX_NUMBER_W,
|
||||
PR_PAGER_TELEPHONE_NUMBER_W,
|
||||
PR_MOBILE_TELEPHONE_NUMBER_W,
|
||||
PR_HOME_ADDRESS_CITY_W,
|
||||
PR_HOME_ADDRESS_STATE_OR_PROVINCE_W,
|
||||
PR_HOME_ADDRESS_POSTAL_CODE_W,
|
||||
PR_HOME_ADDRESS_COUNTRY_W,
|
||||
PR_BUSINESS_ADDRESS_CITY_W,
|
||||
PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_W,
|
||||
PR_BUSINESS_ADDRESS_POSTAL_CODE_W,
|
||||
PR_BUSINESS_ADDRESS_COUNTRY_W,
|
||||
PR_TITLE_W,
|
||||
PR_DEPARTMENT_NAME_W,
|
||||
PR_COMPANY_NAME_W,
|
||||
PR_BUSINESS_HOME_PAGE_W,
|
||||
PR_PERSONAL_HOME_PAGE_W,
|
||||
PR_COMMENT_W
|
||||
};
|
||||
|
||||
nsresult OutlookCardForURI(const nsACString &aUri, nsIAbCard **card);
|
||||
|
||||
#endif // nsAbOutlookDirectory_h___
|
||||
337
mailnews/addrbook/src/nsAbQueryStringToExpression.cpp
Normal file
337
mailnews/addrbook/src/nsAbQueryStringToExpression.cpp
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAbQueryStringToExpression.h"
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsITextToSubURI.h"
|
||||
#include "nsAbBooleanExpression.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "plstr.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
/**
|
||||
* This code parses the query expression passed in as an addressbook URI.
|
||||
* The expression takes the form:
|
||||
* (BOOL1(FIELD1,OP1,VALUE1)..(FIELDn,OPn,VALUEn)(BOOL2(FIELD1,OP1,VALUE1)...)...)
|
||||
*
|
||||
* BOOLn A boolean operator joining subsequent terms delimited by ().
|
||||
* For possible values see CreateBooleanExpression().
|
||||
* FIELDn An addressbook card data field.
|
||||
* OPn An operator for the search term.
|
||||
* For possible values see CreateBooleanConditionString().
|
||||
* VALUEn The value to be matched in the FIELDn via the OPn operator.
|
||||
* The value must be URL encoded by the caller, if it contains any special
|
||||
* characters including '(' and ')'.
|
||||
*/
|
||||
nsresult nsAbQueryStringToExpression::Convert (
|
||||
const nsACString &aQueryString,
|
||||
nsIAbBooleanExpression** expression)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString q(aQueryString);
|
||||
q.StripWhitespace();
|
||||
const char *queryChars = q.get();
|
||||
|
||||
nsCOMPtr<nsISupports> s;
|
||||
rv = ParseExpression(&queryChars, getter_AddRefs(s));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Case: Not end of string
|
||||
if (*queryChars != 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAbBooleanExpression> e(do_QueryInterface(s, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*expression = e);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::ParseExpression (
|
||||
const char** index,
|
||||
nsISupports** expression)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (**index != '(')
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
const char* indexBracket = *index + 1;
|
||||
while (*indexBracket &&
|
||||
*indexBracket != '(' && *indexBracket != ')')
|
||||
indexBracket++;
|
||||
|
||||
// Case: End of string
|
||||
if (*indexBracket == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Case: "((" or "()"
|
||||
if (indexBracket == *index + 1)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Case: "(*("
|
||||
else if (*indexBracket == '(')
|
||||
{
|
||||
// printf ("Case: (*(: %s\n", *index);
|
||||
|
||||
nsCString operation;
|
||||
rv = ParseOperationEntry (
|
||||
*index, indexBracket,
|
||||
getter_Copies (operation));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanExpression> e;
|
||||
rv = CreateBooleanExpression(operation.get(),
|
||||
getter_AddRefs(e));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Case: "(*)(*)....(*))"
|
||||
*index = indexBracket;
|
||||
rv = ParseExpressions (index, e);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*expression = e);
|
||||
}
|
||||
// Case" "(*)"
|
||||
else if (*indexBracket == ')')
|
||||
{
|
||||
// printf ("Case: (*): %s\n", *index);
|
||||
|
||||
nsCOMPtr<nsIAbBooleanConditionString> conditionString;
|
||||
rv = ParseCondition (index, indexBracket,
|
||||
getter_AddRefs(conditionString));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*expression = conditionString);
|
||||
}
|
||||
|
||||
if (**index != ')')
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
(*index)++;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsAbQueryStringToExpression::ParseExpressions (
|
||||
const char** index,
|
||||
nsIAbBooleanExpression* expression)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> expressions(do_CreateInstance(NS_ARRAY_CONTRACTID,
|
||||
&rv));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Case: ")(*)(*)....(*))"
|
||||
// printf ("Case: )(*)(*)....(*)): %s\n", *index);
|
||||
while (**index == '(')
|
||||
{
|
||||
nsCOMPtr<nsISupports> childExpression;
|
||||
rv = ParseExpression(index, getter_AddRefs (childExpression));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
expressions->AppendElement(childExpression, false);
|
||||
}
|
||||
|
||||
if (**index == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Case: "))"
|
||||
// printf ("Case: )): %s\n", *index);
|
||||
|
||||
if (**index != ')')
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
expression->SetExpressions (expressions);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::ParseCondition (
|
||||
const char** index,
|
||||
const char* indexBracketClose,
|
||||
nsIAbBooleanConditionString** conditionString)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
(*index)++;
|
||||
|
||||
nsCString entries[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
rv = ParseConditionEntry (index, indexBracketClose,
|
||||
getter_Copies (entries[i]));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (*index == indexBracketClose)
|
||||
break;
|
||||
}
|
||||
|
||||
if (*index != indexBracketClose)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAbBooleanConditionString> c;
|
||||
rv = CreateBooleanConditionString (
|
||||
entries[0].get(),
|
||||
entries[1].get(),
|
||||
entries[2].get(),
|
||||
getter_AddRefs (c));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*conditionString = c);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::ParseConditionEntry (
|
||||
const char** index,
|
||||
const char* indexBracketClose,
|
||||
char** entry)
|
||||
{
|
||||
const char* indexDeliminator = *index;
|
||||
while (indexDeliminator != indexBracketClose &&
|
||||
*indexDeliminator != ',')
|
||||
indexDeliminator++;
|
||||
|
||||
int entryLength = indexDeliminator - *index;
|
||||
if (entryLength)
|
||||
*entry = PL_strndup (*index, entryLength);
|
||||
else
|
||||
*entry = 0;
|
||||
|
||||
if (indexDeliminator != indexBracketClose)
|
||||
*index = indexDeliminator + 1;
|
||||
else
|
||||
*index = indexDeliminator;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::ParseOperationEntry (
|
||||
const char* indexBracketOpen1,
|
||||
const char* indexBracketOpen2,
|
||||
char** operation)
|
||||
{
|
||||
int operationLength = indexBracketOpen2 - indexBracketOpen1 - 1;
|
||||
if (operationLength)
|
||||
*operation = PL_strndup (indexBracketOpen1 + 1,
|
||||
operationLength);
|
||||
else
|
||||
*operation = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::CreateBooleanExpression(
|
||||
const char* operation,
|
||||
nsIAbBooleanExpression** expression)
|
||||
{
|
||||
nsAbBooleanOperationType op;
|
||||
if (PL_strcasecmp (operation, "and") == 0)
|
||||
op = nsIAbBooleanOperationTypes::AND;
|
||||
else if (PL_strcasecmp (operation, "or") == 0)
|
||||
op = nsIAbBooleanOperationTypes::OR;
|
||||
else if (PL_strcasecmp (operation, "not") == 0)
|
||||
op = nsIAbBooleanOperationTypes::NOT;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr <nsIAbBooleanExpression> expr = do_CreateInstance(NS_BOOLEANEXPRESSION_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*expression = expr);
|
||||
|
||||
rv = expr->SetOperation (op);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsAbQueryStringToExpression::CreateBooleanConditionString (
|
||||
const char* attribute,
|
||||
const char* condition,
|
||||
const char* value,
|
||||
nsIAbBooleanConditionString** conditionString)
|
||||
{
|
||||
if (attribute == 0 || condition == 0 || value == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAbBooleanConditionType c;
|
||||
|
||||
if (PL_strcasecmp (condition, "=") == 0)
|
||||
c = nsIAbBooleanConditionTypes::Is;
|
||||
else if (PL_strcasecmp (condition, "!=") == 0)
|
||||
c = nsIAbBooleanConditionTypes::IsNot;
|
||||
else if (PL_strcasecmp (condition, "lt") == 0)
|
||||
c = nsIAbBooleanConditionTypes::LessThan;
|
||||
else if (PL_strcasecmp (condition, "gt") == 0)
|
||||
c = nsIAbBooleanConditionTypes::GreaterThan;
|
||||
else if (PL_strcasecmp (condition, "bw") == 0)
|
||||
c = nsIAbBooleanConditionTypes::BeginsWith;
|
||||
else if (PL_strcasecmp (condition, "ew") == 0)
|
||||
c = nsIAbBooleanConditionTypes::EndsWith;
|
||||
else if (PL_strcasecmp (condition, "c")== 0)
|
||||
c = nsIAbBooleanConditionTypes::Contains;
|
||||
else if (PL_strcasecmp (condition, "!c") == 0)
|
||||
c = nsIAbBooleanConditionTypes::DoesNotContain;
|
||||
else if (PL_strcasecmp (condition, "~=") == 0)
|
||||
c = nsIAbBooleanConditionTypes::SoundsLike;
|
||||
else if (PL_strcasecmp (condition, "regex") == 0)
|
||||
c = nsIAbBooleanConditionTypes::RegExp;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAbBooleanConditionString> cs = do_CreateInstance(NS_BOOLEANCONDITIONSTRING_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cs->SetCondition (c);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsITextToSubURI> textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID,&rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsString attributeUCS2;
|
||||
nsString valueUCS2;
|
||||
|
||||
rv = textToSubURI->UnEscapeAndConvert("UTF-8",
|
||||
attribute, getter_Copies(attributeUCS2));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = textToSubURI->UnEscapeAndConvert("UTF-8",
|
||||
value, getter_Copies(valueUCS2));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertUTF16toUTF8 attributeUTF8(attributeUCS2);
|
||||
|
||||
rv = cs->SetName (attributeUTF8.get ());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cs->SetValue(valueUCS2.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ConvertUTF8toUTF16 valueUCS2(value);
|
||||
|
||||
rv = cs->SetName (attribute);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cs->SetValue (valueUCS2.get ());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
||||
NS_IF_ADDREF(*conditionString = cs);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
49
mailnews/addrbook/src/nsAbQueryStringToExpression.h
Normal file
49
mailnews/addrbook/src/nsAbQueryStringToExpression.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbQueryStringToExpression_h__
|
||||
#define nsAbQueryStringToExpression_h__
|
||||
|
||||
#include "nsIAbBooleanExpression.h"
|
||||
|
||||
class nsAbQueryStringToExpression
|
||||
{
|
||||
public:
|
||||
static nsresult Convert (
|
||||
const nsACString &aQueryString,
|
||||
nsIAbBooleanExpression** expression);
|
||||
|
||||
protected:
|
||||
static nsresult ParseExpression (
|
||||
const char** index,
|
||||
nsISupports** expression);
|
||||
static nsresult ParseExpressions (
|
||||
const char** index,
|
||||
nsIAbBooleanExpression* expression);
|
||||
static nsresult ParseCondition (
|
||||
const char** index,
|
||||
const char* indexBracketClose,
|
||||
nsIAbBooleanConditionString** conditionString);
|
||||
|
||||
static nsresult ParseConditionEntry (
|
||||
const char** index,
|
||||
const char* indexBracketClose,
|
||||
char** entry);
|
||||
static nsresult ParseOperationEntry (
|
||||
const char* indexBracketOpen1,
|
||||
const char* indexBracketOpen2,
|
||||
char** operation);
|
||||
|
||||
static nsresult CreateBooleanExpression(
|
||||
const char* operation,
|
||||
nsIAbBooleanExpression** expression);
|
||||
static nsresult CreateBooleanConditionString (
|
||||
const char* attribute,
|
||||
const char* condition,
|
||||
const char* value,
|
||||
nsIAbBooleanConditionString** conditionString);
|
||||
};
|
||||
|
||||
#endif
|
||||
140
mailnews/addrbook/src/nsAbUtils.h
Normal file
140
mailnews/addrbook/src/nsAbUtils.h
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAbUtils_h__
|
||||
#define nsAbUtils_h__
|
||||
|
||||
#include "nsMemory.h"
|
||||
|
||||
/*
|
||||
* Wrapper class to automatically free an array of
|
||||
* char* when class goes out of scope
|
||||
*/
|
||||
class CharPtrArrayGuard
|
||||
{
|
||||
public:
|
||||
CharPtrArrayGuard (bool freeElements = true) :
|
||||
mFreeElements (freeElements),
|
||||
mArray (0),
|
||||
mSize (0)
|
||||
{
|
||||
}
|
||||
|
||||
~CharPtrArrayGuard ()
|
||||
{
|
||||
Free ();
|
||||
}
|
||||
|
||||
char* operator[](int i)
|
||||
{
|
||||
return mArray[i];
|
||||
}
|
||||
|
||||
uint32_t* GetSizeAddr(void)
|
||||
{
|
||||
return &mSize;
|
||||
}
|
||||
|
||||
uint32_t GetSize(void)
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
char*** GetArrayAddr(void)
|
||||
{
|
||||
return &mArray;
|
||||
}
|
||||
|
||||
const char** GetArray(void)
|
||||
{
|
||||
return (const char** ) mArray;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
bool mFreeElements;
|
||||
char **mArray;
|
||||
uint32_t mSize;
|
||||
|
||||
void Free ()
|
||||
{
|
||||
if (!mArray)
|
||||
return;
|
||||
|
||||
if (mFreeElements)
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mSize, mArray);
|
||||
else
|
||||
{
|
||||
free(mArray);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper class to automatically free an array of
|
||||
* char16_t* when class goes out of scope
|
||||
*/
|
||||
class PRUnicharPtrArrayGuard
|
||||
{
|
||||
public:
|
||||
PRUnicharPtrArrayGuard (bool freeElements = true) :
|
||||
mFreeElements (freeElements),
|
||||
mArray (0),
|
||||
mSize (0)
|
||||
{
|
||||
}
|
||||
|
||||
~PRUnicharPtrArrayGuard ()
|
||||
{
|
||||
Free ();
|
||||
}
|
||||
|
||||
char16_t* operator[](int i)
|
||||
{
|
||||
return mArray[i];
|
||||
}
|
||||
|
||||
uint32_t* GetSizeAddr(void)
|
||||
{
|
||||
return &mSize;
|
||||
}
|
||||
|
||||
uint32_t GetSize(void)
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
char16_t*** GetArrayAddr(void)
|
||||
{
|
||||
return &mArray;
|
||||
}
|
||||
|
||||
const char16_t** GetArray(void)
|
||||
{
|
||||
return (const char16_t** ) mArray;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
bool mFreeElements;
|
||||
char16_t **mArray;
|
||||
uint32_t mSize;
|
||||
void Free ()
|
||||
{
|
||||
if (!mArray)
|
||||
return;
|
||||
|
||||
if (mFreeElements)
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mSize, mArray);
|
||||
else
|
||||
{
|
||||
free(mArray);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* nsAbUtils_h__ */
|
||||
1451
mailnews/addrbook/src/nsAbView.cpp
Normal file
1451
mailnews/addrbook/src/nsAbView.cpp
Normal file
File diff suppressed because it is too large
Load diff
83
mailnews/addrbook/src/nsAbView.h
Normal file
83
mailnews/addrbook/src/nsAbView.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsAbView_H_
|
||||
#define _nsAbView_H_
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIAbView.h"
|
||||
#include "nsITreeView.h"
|
||||
#include "nsITreeBoxObject.h"
|
||||
#include "nsITreeSelection.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsIAbListener.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
typedef struct AbCard
|
||||
{
|
||||
nsIAbCard *card;
|
||||
uint32_t primaryCollationKeyLen;
|
||||
uint32_t secondaryCollationKeyLen;
|
||||
uint8_t *primaryCollationKey;
|
||||
uint8_t *secondaryCollationKey;
|
||||
} AbCard;
|
||||
|
||||
|
||||
class nsAbView : public nsIAbView, public nsITreeView, public nsIAbListener, public nsIObserver
|
||||
{
|
||||
public:
|
||||
nsAbView();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABVIEW
|
||||
NS_DECL_NSITREEVIEW
|
||||
NS_DECL_NSIABLISTENER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
int32_t CompareCollationKeys(uint8_t *key1, uint32_t len1, uint8_t *key2, uint32_t len2);
|
||||
|
||||
private:
|
||||
virtual ~nsAbView();
|
||||
nsresult Initialize();
|
||||
int32_t FindIndexForInsert(AbCard *abcard);
|
||||
int32_t FindIndexForCard(nsIAbCard *card);
|
||||
nsresult GenerateCollationKeysForCard(const char16_t *colID, AbCard *abcard);
|
||||
nsresult InvalidateTree(int32_t row);
|
||||
nsresult RemoveCardAt(int32_t row);
|
||||
nsresult AddCard(AbCard *abcard, bool selectCardAfterAdding, int32_t *index);
|
||||
nsresult RemoveCardAndSelectNextCard(nsISupports *item);
|
||||
nsresult EnumerateCards();
|
||||
nsresult SetGeneratedNameFormatFromPrefs();
|
||||
nsresult GetSelectedCards(nsCOMPtr<nsIMutableArray> &aSelectedCards);
|
||||
nsresult ReselectCards(nsIArray *aCards, nsIAbCard *aIndexCard);
|
||||
nsresult GetCardValue(nsIAbCard *card, const char16_t *colID, nsAString &_retval);
|
||||
nsresult RefreshTree();
|
||||
|
||||
nsCOMPtr<nsITreeBoxObject> mTree;
|
||||
nsCOMPtr<nsITreeSelection> mTreeSelection;
|
||||
nsCOMPtr <nsIAbDirectory> mDirectory;
|
||||
nsTArray<AbCard*> mCards;
|
||||
nsString mSortColumn;
|
||||
nsString mSortDirection;
|
||||
nsCOMPtr<nsICollation> mCollationKeyGenerator;
|
||||
nsCOMPtr<nsIAbViewListener> mAbViewListener;
|
||||
nsCOMPtr<nsIStringBundle> mABBundle;
|
||||
|
||||
bool mInitialized;
|
||||
bool mIsAllDirectoryRootView;
|
||||
bool mSuppressSelectionChange;
|
||||
bool mSuppressCountChange;
|
||||
int32_t mGeneratedNameFormat;
|
||||
};
|
||||
|
||||
#endif /* _nsAbView_H_ */
|
||||
1003
mailnews/addrbook/src/nsAbWinHelper.cpp
Normal file
1003
mailnews/addrbook/src/nsAbWinHelper.cpp
Normal file
File diff suppressed because it is too large
Load diff
156
mailnews/addrbook/src/nsAbWinHelper.h
Normal file
156
mailnews/addrbook/src/nsAbWinHelper.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsAbWinHelper_h___
|
||||
#define nsAbWinHelper_h___
|
||||
|
||||
#include <windows.h>
|
||||
#include <mapix.h>
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
struct nsMapiEntry
|
||||
{
|
||||
ULONG mByteCount ;
|
||||
LPENTRYID mEntryId ;
|
||||
|
||||
nsMapiEntry(void) ;
|
||||
~nsMapiEntry(void) ;
|
||||
nsMapiEntry(ULONG aByteCount, LPENTRYID aEntryId) ;
|
||||
|
||||
void Assign(ULONG aByteCount, LPENTRYID aEntryId) ;
|
||||
void Assign(const nsCString& aString) ;
|
||||
void ToString(nsCString& aString) const ;
|
||||
void Dump(void) const ;
|
||||
} ;
|
||||
|
||||
struct nsMapiEntryArray
|
||||
{
|
||||
nsMapiEntry *mEntries ;
|
||||
ULONG mNbEntries ;
|
||||
|
||||
nsMapiEntryArray(void) ;
|
||||
~nsMapiEntryArray(void) ;
|
||||
|
||||
const nsMapiEntry& operator [] (int aIndex) const { return mEntries [aIndex] ; }
|
||||
void CleanUp(void) ;
|
||||
} ;
|
||||
|
||||
class nsAbWinHelper
|
||||
{
|
||||
public:
|
||||
nsAbWinHelper(void) ;
|
||||
virtual ~nsAbWinHelper(void) ;
|
||||
|
||||
// Get the top address books
|
||||
BOOL GetFolders(nsMapiEntryArray& aFolders) ;
|
||||
// Get a list of entries for cards/mailing lists in a folder/mailing list
|
||||
BOOL GetCards(const nsMapiEntry& aParent, LPSRestriction aRestriction,
|
||||
nsMapiEntryArray& aCards) ;
|
||||
// Get a list of mailing lists in a folder
|
||||
BOOL GetNodes(const nsMapiEntry& aParent, nsMapiEntryArray& aNodes) ;
|
||||
// Get the number of cards/mailing lists in a folder/mailing list
|
||||
BOOL GetCardsCount(const nsMapiEntry& aParent, ULONG& aNbCards) ;
|
||||
// Access last MAPI error
|
||||
HRESULT LastError(void) const { return mLastError ; }
|
||||
// Get the value of a MAPI property of type string
|
||||
BOOL GetPropertyString(const nsMapiEntry& aObject, ULONG aPropertyTag, nsCString& aValue) ;
|
||||
// Same as previous, but string is returned as unicode
|
||||
BOOL GetPropertyUString(const nsMapiEntry& aObject, ULONG aPropertyTag, nsString& aValue) ;
|
||||
// Get multiple string MAPI properties in one call.
|
||||
BOOL GetPropertiesUString(const nsMapiEntry& aObject, const ULONG *aPropertiesTag,
|
||||
ULONG aNbProperties, nsString *aValues);
|
||||
// Get the value of a MAPI property of type SYSTIME
|
||||
BOOL GetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag,
|
||||
WORD& aYear, WORD& aMonth, WORD& aDay) ;
|
||||
// Get the value of a MAPI property of type LONG
|
||||
BOOL GetPropertyLong(const nsMapiEntry& aObject, ULONG aPropertyTag, ULONG& aValue) ;
|
||||
// Get the value of a MAPI property of type BIN
|
||||
BOOL GetPropertyBin(const nsMapiEntry& aObject, ULONG aPropertyTag, nsMapiEntry& aValue) ;
|
||||
// Tests if a container contains an entry
|
||||
BOOL TestOpenEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ;
|
||||
// Delete an entry in the address book
|
||||
BOOL DeleteEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ;
|
||||
// Set the value of a MAPI property of type string in unicode
|
||||
BOOL SetPropertyUString (const nsMapiEntry& aObject, ULONG aPropertyTag,
|
||||
const char16_t *aValue) ;
|
||||
// Same as previous, but with a bunch of properties in one call
|
||||
BOOL SetPropertiesUString(const nsMapiEntry& aObject, const ULONG *aPropertiesTag,
|
||||
ULONG aNbProperties, nsString *aValues) ;
|
||||
// Set the value of a MAPI property of type SYSTIME
|
||||
BOOL SetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag,
|
||||
WORD aYear, WORD aMonth, WORD aDay) ;
|
||||
// Create entry in the address book
|
||||
BOOL CreateEntry(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ;
|
||||
// Create a distribution list in the address book
|
||||
BOOL CreateDistList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ;
|
||||
// Copy an existing entry in the address book
|
||||
BOOL CopyEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aSource, nsMapiEntry& aTarget) ;
|
||||
// Get a default address book container
|
||||
BOOL GetDefaultContainer(nsMapiEntry& aContainer) ;
|
||||
// Is the helper correctly initialised?
|
||||
BOOL IsOK(void) const { return mAddressBook != NULL ; }
|
||||
|
||||
protected:
|
||||
HRESULT mLastError ;
|
||||
LPADRBOOK mAddressBook ;
|
||||
static uint32_t mEntryCounter ;
|
||||
static uint32_t mUseCount ;
|
||||
static nsAutoPtr<mozilla::Mutex> mMutex ;
|
||||
|
||||
// Retrieve the contents of a container, with an optional restriction
|
||||
BOOL GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction,
|
||||
nsMapiEntry **aList, ULONG &aNbElements, ULONG aMapiType) ;
|
||||
// Retrieve the values of a set of properties on a MAPI object
|
||||
BOOL GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags,
|
||||
ULONG aNbProperties,
|
||||
LPSPropValue& aValues, ULONG& aValueCount) ;
|
||||
// Set the values of a set of properties on a MAPI object
|
||||
BOOL SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties,
|
||||
const LPSPropValue& aValues) ;
|
||||
// Clean-up a rowset returned by QueryRows
|
||||
void MyFreeProws(LPSRowSet aSet) ;
|
||||
// Allocation of a buffer for transmission to interfaces
|
||||
virtual void AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) = 0 ;
|
||||
// Destruction of a buffer provided by the interfaces
|
||||
virtual void FreeBuffer(LPVOID aBuffer) = 0 ;
|
||||
|
||||
private:
|
||||
} ;
|
||||
|
||||
enum nsAbWinType
|
||||
{
|
||||
nsAbWinType_Unknown,
|
||||
nsAbWinType_Outlook,
|
||||
nsAbWinType_OutlookExp
|
||||
} ;
|
||||
|
||||
class nsAbWinHelperGuard
|
||||
{
|
||||
public :
|
||||
nsAbWinHelperGuard(uint32_t aType) ;
|
||||
~nsAbWinHelperGuard(void) ;
|
||||
|
||||
nsAbWinHelper *operator ->(void) { return mHelper ; }
|
||||
|
||||
private:
|
||||
nsAbWinHelper *mHelper ;
|
||||
} ;
|
||||
|
||||
extern const char *kOutlookDirectoryScheme ;
|
||||
extern const int kOutlookDirSchemeLength ;
|
||||
extern const char *kOutlookStub ;
|
||||
extern const char *kOutlookExpStub ;
|
||||
extern const char *kOutlookCardScheme ;
|
||||
|
||||
nsAbWinType getAbWinType(const char *aScheme, const char *aUri,
|
||||
nsCString& aStub, nsCString& aEntry) ;
|
||||
void buildAbWinUri(const char *aScheme, uint32_t aType, nsCString& aUri) ;
|
||||
|
||||
#endif // nsAbWinHelper_h___
|
||||
|
||||
|
||||
|
||||
323
mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
Normal file
323
mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIIOService.h"
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsAddbookProtocolHandler.h"
|
||||
|
||||
#include "nsAddbookUrl.h"
|
||||
#include "nsAddbookProtocolHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsIAbDirectory.h"
|
||||
#include "nsIAbManager.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIAbView.h"
|
||||
#include "nsITreeView.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
nsAddbookProtocolHandler::nsAddbookProtocolHandler()
|
||||
{
|
||||
mAddbookOperation = nsIAddbookUrlOperation::InvalidUrl;
|
||||
}
|
||||
|
||||
nsAddbookProtocolHandler::~nsAddbookProtocolHandler()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAddbookProtocolHandler, nsIProtocolHandler)
|
||||
|
||||
NS_IMETHODIMP nsAddbookProtocolHandler::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
aScheme = "addbook";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookProtocolHandler::GetDefaultPort(int32_t *aDefaultPort)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookProtocolHandler::GetProtocolFlags(uint32_t *aUritype)
|
||||
{
|
||||
*aUritype = URI_STD | URI_LOADABLE_BY_ANYONE | URI_FORBIDS_COOKIE_ACCESS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookProtocolHandler::NewURI(const nsACString &aSpec,
|
||||
const char *aOriginCharset, // ignored
|
||||
nsIURI *aBaseURI,
|
||||
nsIURI **_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIAddbookUrl> addbookUrl = do_CreateInstance(NS_ADDBOOKURL_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = addbookUrl->SetSpec(aSpec);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr <nsIURI> uri = do_QueryInterface(addbookUrl, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
NS_ADDREF(*_retval = uri);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
||||
{
|
||||
// don't override anything.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAddbookProtocolHandler::GenerateXMLOutputChannel( nsString &aOutput,
|
||||
nsIAddbookUrl *addbookUrl,
|
||||
nsIURI *aURI,
|
||||
nsILoadInfo *aLoadInfo,
|
||||
nsIChannel **_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringInputStream> inStr(do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertUTF16toUTF8 utf8String(aOutput.get());
|
||||
|
||||
rv = inStr->SetData(utf8String.get(), utf8String.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aLoadInfo) {
|
||||
return NS_NewInputStreamChannelInternal(_retval,
|
||||
aURI,
|
||||
inStr,
|
||||
NS_LITERAL_CSTRING("text/xml"),
|
||||
EmptyCString(),
|
||||
aLoadInfo);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CreateInstance of nullprincipalfailed.");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return NS_NewInputStreamChannel(_retval, aURI, inStr,
|
||||
nullPrincipal, nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
NS_LITERAL_CSTRING("text/xml"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
||||
{
|
||||
return NewChannel2(aURI, nullptr, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookProtocolHandler::NewChannel2(nsIURI *aURI,
|
||||
nsILoadInfo* aLoadInfo,
|
||||
nsIChannel **_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIAddbookUrl> addbookUrl = do_QueryInterface(aURI, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = addbookUrl->GetAddbookOperation(&mAddbookOperation);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (mAddbookOperation == nsIAddbookUrlOperation::InvalidUrl) {
|
||||
nsAutoString errorString;
|
||||
errorString.AssignLiteral("Unsupported format/operation requested for ");
|
||||
nsAutoCString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
errorString.Append(NS_ConvertUTF8toUTF16(spec));
|
||||
rv = GenerateXMLOutputChannel(errorString, addbookUrl, aURI, aLoadInfo, _retval);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mAddbookOperation == nsIAddbookUrlOperation::AddVCard) {
|
||||
// create an empty pipe for use with the input stream channel.
|
||||
nsCOMPtr<nsIAsyncInputStream> pipeIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
|
||||
nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
|
||||
|
||||
rv = pipe->Init(false, false, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// These always succeed because the pipe is initialized above.
|
||||
MOZ_ALWAYS_SUCCEEDS(pipe->GetInputStream(getter_AddRefs(pipeIn)));
|
||||
MOZ_ALWAYS_SUCCEEDS(pipe->GetOutputStream(getter_AddRefs(pipeOut)));
|
||||
|
||||
pipeOut->Close();
|
||||
if (aLoadInfo) {
|
||||
return NS_NewInputStreamChannelInternal(_retval,
|
||||
aURI,
|
||||
pipeIn,
|
||||
NS_LITERAL_CSTRING("application/x-addvcard"),
|
||||
EmptyCString(),
|
||||
aLoadInfo);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CreateInstance of nullprincipal failed.");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return NS_NewInputStreamChannel(_retval, aURI, pipeIn,
|
||||
nullPrincipal, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER,
|
||||
NS_LITERAL_CSTRING("application/x-addvcard"));
|
||||
}
|
||||
|
||||
nsString output;
|
||||
rv = GeneratePrintOutput(addbookUrl, output);
|
||||
if (NS_FAILED(rv)) {
|
||||
output.AssignLiteral("failed to print. url=");
|
||||
nsAutoCString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
output.Append(NS_ConvertUTF8toUTF16(spec));
|
||||
}
|
||||
|
||||
rv = GenerateXMLOutputChannel(output, addbookUrl, aURI, aLoadInfo, _retval);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAddbookProtocolHandler::GeneratePrintOutput(nsIAddbookUrl *addbookUrl,
|
||||
nsString &aOutput)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(addbookUrl);
|
||||
|
||||
nsAutoCString uri;
|
||||
nsresult rv = addbookUrl->GetPath(uri);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
/* turn
|
||||
"//moz-abmdbdirectory/abook.mab?action=print"
|
||||
into "moz-abmdbdirectory://abook.mab"
|
||||
*/
|
||||
|
||||
/* step 1:
|
||||
turn "//moz-abmdbdirectory/abook.mab?action=print"
|
||||
into "moz-abmdbdirectory/abook.mab?action=print"
|
||||
*/
|
||||
if (uri[0] != '/' && uri[1] != '/')
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
uri.Cut(0,2);
|
||||
|
||||
/* step 2:
|
||||
turn "moz-abmdbdirectory/abook.mab?action=print"
|
||||
into "moz-abmdbdirectory/abook.mab"
|
||||
*/
|
||||
int32_t pos = uri.Find("?action=print");
|
||||
if (pos == -1)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
uri.SetLength(pos);
|
||||
|
||||
/* step 2:
|
||||
turn "moz-abmdbdirectory/abook.mab"
|
||||
into "moz-abmdbdirectory://abook.mab"
|
||||
*/
|
||||
pos = uri.FindChar('/');
|
||||
if (pos == -1)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
uri.Insert('/', pos);
|
||||
uri.Insert(':', pos);
|
||||
|
||||
nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAbDirectory> directory;
|
||||
rv = abManager->GetDirectory(uri, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = BuildDirectoryXML(directory, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAddbookProtocolHandler::BuildDirectoryXML(nsIAbDirectory *aDirectory,
|
||||
nsString &aOutput)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDirectory);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> cardsEnumerator;
|
||||
nsCOMPtr<nsIAbCard> card;
|
||||
|
||||
aOutput.AppendLiteral("<?xml version=\"1.0\"?>\n"
|
||||
"<?xml-stylesheet type=\"text/css\" href=\"chrome://messagebody/content/addressbook/print.css\"?>\n"
|
||||
"<directory>\n");
|
||||
|
||||
// Get Address Book string and set it as title of XML document
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (stringBundleService) {
|
||||
rv = stringBundleService->CreateBundle("chrome://messenger/locale/addressbook/addressBook.properties", getter_AddRefs(bundle));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsString addrBook;
|
||||
rv = bundle->GetStringFromName(u"addressBook", getter_Copies(addrBook));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aOutput.AppendLiteral("<title xmlns=\"http://www.w3.org/1999/xhtml\">");
|
||||
aOutput.Append(addrBook);
|
||||
aOutput.AppendLiteral("</title>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a view and init it with the generated name sort order. Then, iterate
|
||||
// over the view, getting the card for each row, and printing them.
|
||||
nsString sortColumn;
|
||||
nsCOMPtr <nsIAbView> view = do_CreateInstance("@mozilla.org/addressbook/abview;1", &rv);
|
||||
|
||||
view->SetView(aDirectory, nullptr, NS_LITERAL_STRING("GeneratedName"),
|
||||
NS_LITERAL_STRING("ascending"), sortColumn);
|
||||
|
||||
int32_t numRows;
|
||||
nsCOMPtr <nsITreeView> treeView = do_QueryInterface(view, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
treeView->GetRowCount(&numRows);
|
||||
|
||||
for (int32_t row = 0; row < numRows; row++)
|
||||
{
|
||||
|
||||
nsCOMPtr <nsIAbCard> card;
|
||||
view->GetCardFromRow(row, getter_AddRefs(card));
|
||||
nsCString xmlSubstr;
|
||||
|
||||
rv = card->TranslateTo(NS_LITERAL_CSTRING("xml"), xmlSubstr);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
aOutput.AppendLiteral("<separator/>");
|
||||
aOutput.Append(NS_ConvertUTF8toUTF16(xmlSubstr));
|
||||
aOutput.AppendLiteral("<separator/>");
|
||||
}
|
||||
|
||||
aOutput.AppendLiteral("</directory>\n");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
45
mailnews/addrbook/src/nsAddbookProtocolHandler.h
Normal file
45
mailnews/addrbook/src/nsAddbookProtocolHandler.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAddbookProtocolHandler_h___
|
||||
#define nsAddbookProtocolHandler_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAddbookProtocolHandler.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIAddbookUrl.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
|
||||
class nsAddbookProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
nsAddbookProtocolHandler();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// We support the nsIProtocolHandler interface.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
|
||||
private:
|
||||
virtual ~nsAddbookProtocolHandler();
|
||||
nsresult GenerateXMLOutputChannel(nsString &aOutput,
|
||||
nsIAddbookUrl *addbookUrl,
|
||||
nsIURI *aURI,
|
||||
nsILoadInfo *aLoadInfo,
|
||||
nsIChannel **_retval);
|
||||
|
||||
nsresult GeneratePrintOutput(nsIAddbookUrl *addbookUrl,
|
||||
nsString &aOutput);
|
||||
|
||||
nsresult BuildDirectoryXML(nsIAbDirectory *aDirectory,
|
||||
nsString &aOutput);
|
||||
|
||||
int32_t mAddbookOperation;
|
||||
};
|
||||
|
||||
#endif /* nsAddbookProtocolHandler_h___ */
|
||||
282
mailnews/addrbook/src/nsAddbookUrl.cpp
Normal file
282
mailnews/addrbook/src/nsAddbookUrl.cpp
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsAddbookUrl.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsAbBaseCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// addbook url definition
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
nsAddbookUrl::nsAddbookUrl()
|
||||
{
|
||||
m_baseURL = do_CreateInstance(NS_SIMPLEURI_CONTRACTID);
|
||||
|
||||
mOperationType = nsIAddbookUrlOperation::InvalidUrl;
|
||||
}
|
||||
|
||||
nsAddbookUrl::~nsAddbookUrl()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAddbookUrl, nsIAddbookUrl, nsIURI)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::SetSpec(const nsACString &aSpec)
|
||||
{
|
||||
nsresult rv = m_baseURL->SetSpec(aSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
nsresult nsAddbookUrl::ParseUrl()
|
||||
{
|
||||
nsAutoCString pathStr;
|
||||
|
||||
nsresult rv = m_baseURL->GetPath(pathStr);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (strstr(pathStr.get(), "?action=print"))
|
||||
mOperationType = nsIAddbookUrlOperation::PrintAddressBook;
|
||||
else if (strstr(pathStr.get(), "?action=add"))
|
||||
mOperationType = nsIAddbookUrlOperation::AddVCard;
|
||||
else
|
||||
mOperationType = nsIAddbookUrlOperation::InvalidUrl;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIURI support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetSpec(nsACString &aSpec)
|
||||
{
|
||||
return m_baseURL->GetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetPrePath(nsACString &aPrePath)
|
||||
{
|
||||
return m_baseURL->GetPrePath(aPrePath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
return m_baseURL->GetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetScheme(const nsACString &aScheme)
|
||||
{
|
||||
return m_baseURL->SetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetUserPass(nsACString &aUserPass)
|
||||
{
|
||||
return m_baseURL->GetUserPass(aUserPass);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetUserPass(const nsACString &aUserPass)
|
||||
{
|
||||
return m_baseURL->SetUserPass(aUserPass);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetUsername(nsACString &aUsername)
|
||||
{
|
||||
return m_baseURL->GetUsername(aUsername);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetUsername(const nsACString &aUsername)
|
||||
{
|
||||
return m_baseURL->SetUsername(aUsername);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetPassword(nsACString &aPassword)
|
||||
{
|
||||
return m_baseURL->GetPassword(aPassword);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetPassword(const nsACString &aPassword)
|
||||
{
|
||||
return m_baseURL->SetPassword(aPassword);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetHostPort(nsACString &aHostPort)
|
||||
{
|
||||
return m_baseURL->GetHostPort(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetHostPort(const nsACString &aHostPort)
|
||||
{
|
||||
return m_baseURL->SetHostPort(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetHostAndPort(const nsACString &aHostPort)
|
||||
{
|
||||
return m_baseURL->SetHostAndPort(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetHost(nsACString &aHost)
|
||||
{
|
||||
return m_baseURL->GetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetHost(const nsACString &aHost)
|
||||
{
|
||||
return m_baseURL->SetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetPort(int32_t *aPort)
|
||||
{
|
||||
return m_baseURL->GetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetPort(int32_t aPort)
|
||||
{
|
||||
return m_baseURL->SetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetPath(nsACString &aPath)
|
||||
{
|
||||
return m_baseURL->GetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SetPath(const nsACString &aPath)
|
||||
{
|
||||
m_baseURL->SetPath(aPath);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetAsciiHost(nsACString &aHostA)
|
||||
{
|
||||
return m_baseURL->GetAsciiHost(aHostA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetAsciiHostPort(nsACString &aHostPortA)
|
||||
{
|
||||
return m_baseURL->GetAsciiHostPort(aHostPortA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetAsciiSpec(nsACString &aSpecA)
|
||||
{
|
||||
return m_baseURL->GetAsciiSpec(aSpecA);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::GetOriginCharset(nsACString &aOriginCharset)
|
||||
{
|
||||
return m_baseURL->GetOriginCharset(aOriginCharset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::SchemeIs(const char *aScheme, bool *_retval)
|
||||
{
|
||||
return m_baseURL->SchemeIs(aScheme, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::Equals(nsIURI *other, bool *_retval)
|
||||
{
|
||||
// The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
|
||||
// Equals method. The other nsMailtoUrl will then pass its inner URL to
|
||||
// to the Equals method of our inner URL. Other URIs will return false.
|
||||
if (other)
|
||||
return other->Equals(m_baseURL, _retval);
|
||||
|
||||
return m_baseURL->Equals(other, _retval);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAddbookUrl::CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
RefPtr<nsAddbookUrl> clone = new nsAddbookUrl();
|
||||
|
||||
if (!clone)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv;
|
||||
if (aRefHandlingMode == eHonorRef) {
|
||||
rv = m_baseURL->Clone(getter_AddRefs(clone->m_baseURL));
|
||||
} else if (aRefHandlingMode == eReplaceRef) {
|
||||
rv = m_baseURL->CloneWithNewRef(newRef, getter_AddRefs(clone->m_baseURL));
|
||||
} else {
|
||||
rv = m_baseURL->CloneIgnoringRef(getter_AddRefs(clone->m_baseURL));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
clone->ParseUrl();
|
||||
clone.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::Clone(nsIURI **_retval)
|
||||
{
|
||||
return CloneInternal(eHonorRef, EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::CloneIgnoringRef(nsIURI** _retval)
|
||||
{
|
||||
return CloneInternal(eIgnoreRef, EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::CloneWithNewRef(const nsACString& newRef, nsIURI** _retval)
|
||||
{
|
||||
return CloneInternal(eReplaceRef, newRef, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::Resolve(const nsACString &relativePath, nsACString &result)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::GetRef(nsACString &result)
|
||||
{
|
||||
return m_baseURL->GetRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::SetRef(const nsACString &aRef)
|
||||
{
|
||||
m_baseURL->SetRef(aRef);
|
||||
return ParseUrl();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAddbookUrl::EqualsExceptRef(nsIURI *other, bool *_retval)
|
||||
{
|
||||
// The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
|
||||
// Equals method. The other nsMailtoUrl will then pass its inner URL to
|
||||
// to the Equals method of our inner URL. Other URIs will return false.
|
||||
if (other)
|
||||
return other->EqualsExceptRef(m_baseURL, _retval);
|
||||
|
||||
return m_baseURL->EqualsExceptRef(other, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::GetSpecIgnoringRef(nsACString &result)
|
||||
{
|
||||
return m_baseURL->GetSpecIgnoringRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::GetHasRef(bool *result)
|
||||
{
|
||||
return m_baseURL->GetHasRef(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Specific nsAddbookUrl operations
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsAddbookUrl::GetAddbookOperation(int32_t *_retval)
|
||||
{
|
||||
*_retval = mOperationType;
|
||||
return NS_OK;
|
||||
}
|
||||
39
mailnews/addrbook/src/nsAddbookUrl.h
Normal file
39
mailnews/addrbook/src/nsAddbookUrl.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAddbookUrl_h__
|
||||
#define nsAddbookUrl_h__
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAddbookUrl.h"
|
||||
|
||||
class nsAddbookUrl : public nsIAddbookUrl
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSIADDBOOKURL
|
||||
|
||||
nsAddbookUrl();
|
||||
|
||||
protected:
|
||||
enum RefHandlingEnum {
|
||||
eIgnoreRef,
|
||||
eHonorRef,
|
||||
eReplaceRef
|
||||
};
|
||||
virtual ~nsAddbookUrl();
|
||||
nsresult
|
||||
CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** _retval);
|
||||
|
||||
nsresult ParseUrl();
|
||||
int32_t mOperationType; // the internal ID for the operation
|
||||
|
||||
nsCOMPtr<nsIURI> m_baseURL; // the base URL for the object
|
||||
};
|
||||
|
||||
#endif // nsAddbookUrl_h__
|
||||
3335
mailnews/addrbook/src/nsAddrDatabase.cpp
Normal file
3335
mailnews/addrbook/src/nsAddrDatabase.cpp
Normal file
File diff suppressed because it is too large
Load diff
439
mailnews/addrbook/src/nsAddrDatabase.h
Normal file
439
mailnews/addrbook/src/nsAddrDatabase.h
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsAddrDatabase_H_
|
||||
#define _nsAddrDatabase_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIAddrDatabase.h"
|
||||
#include "mdb.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIAddrDBListener.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AB_NotifyInserted,
|
||||
AB_NotifyDeleted,
|
||||
AB_NotifyPropertyChanged
|
||||
} AB_NOTIFY_CODE;
|
||||
|
||||
class nsAddrDatabase : public nsIAddrDatabase
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIADDRDBANNOUNCER
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAddrDatabase methods:
|
||||
|
||||
NS_IMETHOD GetDbPath(nsIFile * *aDbPath) override;
|
||||
NS_IMETHOD SetDbPath(nsIFile * aDbPath) override;
|
||||
NS_IMETHOD Open(nsIFile *aMabFile, bool aCreate, bool upgrading, nsIAddrDatabase **pCardDB) override;
|
||||
NS_IMETHOD Close(bool forceCommit) override;
|
||||
NS_IMETHOD OpenMDB(nsIFile *dbName, bool create) override;
|
||||
NS_IMETHOD CloseMDB(bool commit) override;
|
||||
NS_IMETHOD Commit(uint32_t commitType) override;
|
||||
NS_IMETHOD ForceClosed() override;
|
||||
|
||||
NS_IMETHOD CreateNewCardAndAddToDB(nsIAbCard *newCard, bool notify, nsIAbDirectory *parent) override;
|
||||
NS_IMETHOD CreateNewListCardAndAddToDB(nsIAbDirectory *list, uint32_t listRowID, nsIAbCard *newCard, bool notify) override;
|
||||
NS_IMETHOD CreateMailListAndAddToDB(nsIAbDirectory *newList, bool notify, nsIAbDirectory *parent) override;
|
||||
NS_IMETHOD EnumerateCards(nsIAbDirectory *directory, nsISimpleEnumerator **result) override;
|
||||
NS_IMETHOD GetMailingListsFromDB(nsIAbDirectory *parentDir) override;
|
||||
NS_IMETHOD EnumerateListAddresses(nsIAbDirectory *directory, nsISimpleEnumerator **result) override;
|
||||
NS_IMETHOD DeleteCard(nsIAbCard *newCard, bool notify, nsIAbDirectory *parent) override;
|
||||
NS_IMETHOD EditCard(nsIAbCard *card, bool notify, nsIAbDirectory *parent) override;
|
||||
NS_IMETHOD ContainsCard(nsIAbCard *card, bool *hasCard) override;
|
||||
NS_IMETHOD DeleteMailList(nsIAbDirectory *aMailList, nsIAbDirectory *aParent) override;
|
||||
NS_IMETHOD EditMailList(nsIAbDirectory *mailList, nsIAbCard *listCard, bool notify) override;
|
||||
NS_IMETHOD ContainsMailList(nsIAbDirectory *mailList, bool *hasCard) override;
|
||||
NS_IMETHOD DeleteCardFromMailList(nsIAbDirectory *mailList, nsIAbCard *card, bool aNotify) override;
|
||||
NS_IMETHOD GetCardFromAttribute(nsIAbDirectory *aDirectory, const char *aName,
|
||||
const nsACString &aValue,
|
||||
bool aCaseInsensitive, nsIAbCard **card) override;
|
||||
NS_IMETHOD GetCardsFromAttribute(nsIAbDirectory *aDirectory,
|
||||
const char *aName,
|
||||
const nsACString & uUTF8Value,
|
||||
bool aCaseInsensitive,
|
||||
nsISimpleEnumerator **cards) override;
|
||||
NS_IMETHOD GetNewRow(nsIMdbRow * *newRow) override;
|
||||
NS_IMETHOD GetNewListRow(nsIMdbRow * *newRow) override;
|
||||
NS_IMETHOD AddCardRowToDB(nsIMdbRow *newRow) override;
|
||||
NS_IMETHOD AddLdifListMember(nsIMdbRow* row, const char * value) override;
|
||||
|
||||
NS_IMETHOD GetDeletedCardList(nsIArray **aResult) override;
|
||||
NS_IMETHOD GetDeletedCardCount(uint32_t *aCount) override;
|
||||
NS_IMETHOD PurgeDeletedCardTable();
|
||||
|
||||
NS_IMETHOD AddFirstName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_FirstNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddLastName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_LastNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPhoneticFirstName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_PhoneticFirstNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPhoneticLastName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_PhoneticLastNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddDisplayName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_DisplayNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddNickName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_NickNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPrimaryEmail(nsIMdbRow * row, const char * value) override;
|
||||
|
||||
NS_IMETHOD Add2ndEmail(nsIMdbRow * row, const char * value) override;
|
||||
|
||||
NS_IMETHOD AddPreferMailFormat(nsIMdbRow * row, uint32_t value) override
|
||||
{ return AddIntColumn(row, m_MailFormatColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPopularityIndex(nsIMdbRow * row, uint32_t value) override
|
||||
{ return AddIntColumn(row, m_PopularityIndexColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkPhone(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkPhoneColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomePhone(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomePhoneColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddFaxNumber(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_FaxColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPagerNumber(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_PagerColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCellularNumber(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_CellularColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkPhoneType(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkPhoneTypeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomePhoneType(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomePhoneTypeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddFaxNumberType(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_FaxTypeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddPagerNumberType(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_PagerTypeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCellularNumberType(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_CellularTypeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeAddress(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeAddressColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeAddress2(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeAddress2ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeCity(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeCityColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeState(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeStateColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeZipCode(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeZipCodeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddHomeCountry(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_HomeCountryColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkAddress(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkAddressColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkAddress2(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkAddress2ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkCity(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkCityColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkState(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkStateColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkZipCode(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkZipCodeColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWorkCountry(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WorkCountryColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddJobTitle(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_JobTitleColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddDepartment(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_DepartmentColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCompany(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_CompanyColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddAimScreenName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_AimScreenNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddAnniversaryYear(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_AnniversaryYearColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddAnniversaryMonth(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_AnniversaryMonthColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddAnniversaryDay(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_AnniversaryDayColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddSpouseName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_SpouseNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddFamilyName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_FamilyNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddDefaultAddress(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_DefaultAddressColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCategory(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_CategoryColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWebPage1(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WebPage1ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddWebPage2(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_WebPage2ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddBirthYear(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_BirthYearColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddBirthMonth(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_BirthMonthColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddBirthDay(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_BirthDayColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCustom1(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_Custom1ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCustom2(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_Custom2ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCustom3(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_Custom3ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddCustom4(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_Custom4ColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddNotes(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_NotesColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddListName(nsIMdbRow * row, const char * value) override;
|
||||
|
||||
NS_IMETHOD AddListNickName(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_ListNickNameColumnToken, value); }
|
||||
|
||||
NS_IMETHOD AddListDescription(nsIMdbRow * row, const char * value) override
|
||||
{ return AddCharStringColumn(row, m_ListDescriptionColumnToken, value); }
|
||||
|
||||
|
||||
NS_IMETHOD AddListDirNode(nsIMdbRow * listRow) override;
|
||||
|
||||
NS_IMETHOD FindMailListbyUnicodeName(const char16_t *listName, bool *exist) override;
|
||||
|
||||
NS_IMETHOD GetCardCount(uint32_t *count) override;
|
||||
|
||||
NS_IMETHOD SetCardValue(nsIAbCard *card, const char *name, const char16_t *value, bool notify) override;
|
||||
NS_IMETHOD GetCardValue(nsIAbCard *card, const char *name, char16_t **value) override;
|
||||
// nsAddrDatabase methods:
|
||||
|
||||
nsAddrDatabase();
|
||||
|
||||
void GetMDBFactory(nsIMdbFactory ** aMdbFactory);
|
||||
nsIMdbEnv *GetEnv() {return m_mdbEnv;}
|
||||
uint32_t GetCurVersion();
|
||||
nsIMdbTableRowCursor *GetTableRowCursor();
|
||||
nsIMdbTable *GetPabTable() {return m_mdbPabTable;}
|
||||
|
||||
static nsAddrDatabase* FindInCache(nsIFile *dbName);
|
||||
|
||||
static void CleanupCache();
|
||||
|
||||
nsresult CreateABCard(nsIMdbRow* cardRow, mdb_id listRowID, nsIAbCard **result);
|
||||
nsresult CreateABListCard(nsIMdbRow* listRow, nsIAbCard **result);
|
||||
nsresult CreateABList(nsIMdbRow* listRow, nsIAbDirectory **result);
|
||||
|
||||
bool IsListRowScopeToken(mdb_scope scope) { return (scope == m_ListRowScopeToken) ? true: false; }
|
||||
bool IsCardRowScopeToken(mdb_scope scope) { return (scope == m_CardRowScopeToken) ? true: false; }
|
||||
bool IsDataRowScopeToken(mdb_scope scope) { return (scope == m_DataRowScopeToken) ? true: false; }
|
||||
nsresult GetCardRowByRowID(mdb_id rowID, nsIMdbRow **dbRow);
|
||||
nsresult GetListRowByRowID(mdb_id rowID, nsIMdbRow **dbRow);
|
||||
|
||||
uint32_t GetListAddressTotal(nsIMdbRow* listRow);
|
||||
nsresult GetAddressRowByPos(nsIMdbRow* listRow, uint16_t pos, nsIMdbRow** cardRow);
|
||||
|
||||
NS_IMETHOD AddListCardColumnsToRow(nsIAbCard *aPCard, nsIMdbRow *aPListRow, uint32_t aPos, nsIAbCard** aPNewCard, bool aInMailingList, nsIAbDirectory *aParent, nsIAbDirectory *aRoot) override;
|
||||
NS_IMETHOD InitCardFromRow(nsIAbCard *aNewCard, nsIMdbRow* aCardRow) override;
|
||||
NS_IMETHOD SetListAddressTotal(nsIMdbRow* aListRow, uint32_t aTotal) override;
|
||||
NS_IMETHOD FindRowByCard(nsIAbCard * card,nsIMdbRow **aRow) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsAddrDatabase();
|
||||
|
||||
static void RemoveFromCache(nsAddrDatabase* pAddrDB);
|
||||
bool MatchDbName(nsIFile *dbName); // returns TRUE if they match
|
||||
|
||||
void YarnToUInt32(struct mdbYarn *yarn, uint32_t *pResult);
|
||||
void GetCharStringYarn(char* str, struct mdbYarn* strYarn);
|
||||
void GetStringYarn(const nsAString & aStr, struct mdbYarn* strYarn);
|
||||
void GetIntYarn(uint32_t nValue, struct mdbYarn* intYarn);
|
||||
nsresult AddCharStringColumn(nsIMdbRow* cardRow, mdb_column inColumn, const char* str);
|
||||
nsresult AddStringColumn(nsIMdbRow* aCardRow, mdb_column aInColumn, const nsAString & aStr);
|
||||
nsresult AddIntColumn(nsIMdbRow* cardRow, mdb_column inColumn, uint32_t nValue);
|
||||
nsresult AddBoolColumn(nsIMdbRow* cardRow, mdb_column inColumn, bool bValue);
|
||||
nsresult GetStringColumn(nsIMdbRow *cardRow, mdb_token outToken, nsString& str);
|
||||
nsresult GetIntColumn(nsIMdbRow *cardRow, mdb_token outToken,
|
||||
uint32_t* pValue, uint32_t defaultValue);
|
||||
nsresult GetBoolColumn(nsIMdbRow *cardRow, mdb_token outToken, bool* pValue);
|
||||
nsresult GetListCardFromDB(nsIAbCard *listCard, nsIMdbRow* listRow);
|
||||
nsresult GetListFromDB(nsIAbDirectory *newCard, nsIMdbRow* listRow);
|
||||
nsresult AddRecordKeyColumnToRow(nsIMdbRow *pRow);
|
||||
nsresult AddAttributeColumnsToRow(nsIAbCard *card, nsIMdbRow *cardRow);
|
||||
nsresult AddListAttributeColumnsToRow(nsIAbDirectory *list, nsIMdbRow *listRow, nsIAbDirectory *parent);
|
||||
nsresult CreateCard(nsIMdbRow* cardRow, mdb_id listRowID, nsIAbCard **result);
|
||||
nsresult CreateCardFromDeletedCardsTable(nsIMdbRow* cardRow, mdb_id listRowID, nsIAbCard **result);
|
||||
nsresult DeleteCardFromListRow(nsIMdbRow* pListRow, mdb_id cardRowID);
|
||||
void DeleteCardFromAllMailLists(mdb_id cardRowID);
|
||||
nsresult NotifyListEntryChange(uint32_t abCode, nsIAbDirectory *dir);
|
||||
|
||||
nsresult AddLowercaseColumn(nsIMdbRow * row, mdb_token columnToken, const char* utf8String);
|
||||
nsresult GetRowFromAttribute(const char *aName, const nsACString &aUTF8Value,
|
||||
bool aCaseInsensitive, nsIMdbRow **aCardRow,
|
||||
mdb_pos *aRowPos);
|
||||
|
||||
static nsTArray<nsAddrDatabase*>* m_dbCache;
|
||||
static nsTArray<nsAddrDatabase*>* GetDBCache();
|
||||
|
||||
// mdb bookkeeping stuff
|
||||
nsresult InitExistingDB();
|
||||
nsresult InitNewDB();
|
||||
nsresult InitMDBInfo();
|
||||
nsresult InitPabTable();
|
||||
nsresult InitDeletedCardsTable(bool aCreate);
|
||||
nsresult AddRowToDeletedCardsTable(nsIAbCard *card, nsIMdbRow **pCardRow);
|
||||
nsresult DeleteRowFromDeletedCardsTable(nsIMdbRow *pCardRow);
|
||||
|
||||
nsresult InitLastRecorKey();
|
||||
nsresult GetDataRow(nsIMdbRow **pDataRow);
|
||||
nsresult GetLastRecordKey();
|
||||
nsresult UpdateLastRecordKey();
|
||||
nsresult CheckAndUpdateRecordKey();
|
||||
nsresult UpdateLowercaseEmailListName();
|
||||
nsresult ConvertAndAddLowercaseColumn(nsIMdbRow * row, mdb_token fromCol, mdb_token toCol);
|
||||
nsresult AddUnicodeToColumn(nsIMdbRow * row, mdb_token colToken, mdb_token lowerCaseColToken, const char16_t* pUnicodeStr);
|
||||
|
||||
nsresult DeleteRow(nsIMdbTable* dbTable, nsIMdbRow* dbRow);
|
||||
|
||||
nsIMdbEnv *m_mdbEnv; // to be used in all the db calls.
|
||||
nsIMdbStore *m_mdbStore;
|
||||
nsIMdbTable *m_mdbPabTable;
|
||||
nsIMdbTable *m_mdbDeletedCardsTable;
|
||||
nsCOMPtr<nsIFile> m_dbName;
|
||||
bool m_mdbTokensInitialized;
|
||||
nsTObserverArray<nsIAddrDBListener*> m_ChangeListeners;
|
||||
|
||||
mdb_kind m_PabTableKind;
|
||||
mdb_kind m_MailListTableKind;
|
||||
mdb_kind m_DeletedCardsTableKind;
|
||||
|
||||
mdb_scope m_CardRowScopeToken;
|
||||
mdb_scope m_ListRowScopeToken;
|
||||
mdb_scope m_DataRowScopeToken;
|
||||
|
||||
mdb_token m_FirstNameColumnToken;
|
||||
mdb_token m_LastNameColumnToken;
|
||||
mdb_token m_PhoneticFirstNameColumnToken;
|
||||
mdb_token m_PhoneticLastNameColumnToken;
|
||||
mdb_token m_DisplayNameColumnToken;
|
||||
mdb_token m_NickNameColumnToken;
|
||||
mdb_token m_PriEmailColumnToken;
|
||||
mdb_token m_2ndEmailColumnToken;
|
||||
mdb_token m_DefaultEmailColumnToken;
|
||||
mdb_token m_CardTypeColumnToken;
|
||||
mdb_token m_WorkPhoneColumnToken;
|
||||
mdb_token m_HomePhoneColumnToken;
|
||||
mdb_token m_FaxColumnToken;
|
||||
mdb_token m_PagerColumnToken;
|
||||
mdb_token m_CellularColumnToken;
|
||||
mdb_token m_WorkPhoneTypeColumnToken;
|
||||
mdb_token m_HomePhoneTypeColumnToken;
|
||||
mdb_token m_FaxTypeColumnToken;
|
||||
mdb_token m_PagerTypeColumnToken;
|
||||
mdb_token m_CellularTypeColumnToken;
|
||||
mdb_token m_HomeAddressColumnToken;
|
||||
mdb_token m_HomeAddress2ColumnToken;
|
||||
mdb_token m_HomeCityColumnToken;
|
||||
mdb_token m_HomeStateColumnToken;
|
||||
mdb_token m_HomeZipCodeColumnToken;
|
||||
mdb_token m_HomeCountryColumnToken;
|
||||
mdb_token m_WorkAddressColumnToken;
|
||||
mdb_token m_WorkAddress2ColumnToken;
|
||||
mdb_token m_WorkCityColumnToken;
|
||||
mdb_token m_WorkStateColumnToken;
|
||||
mdb_token m_WorkZipCodeColumnToken;
|
||||
mdb_token m_WorkCountryColumnToken;
|
||||
mdb_token m_JobTitleColumnToken;
|
||||
mdb_token m_DepartmentColumnToken;
|
||||
mdb_token m_CompanyColumnToken;
|
||||
mdb_token m_AimScreenNameColumnToken;
|
||||
mdb_token m_AnniversaryYearColumnToken;
|
||||
mdb_token m_AnniversaryMonthColumnToken;
|
||||
mdb_token m_AnniversaryDayColumnToken;
|
||||
mdb_token m_SpouseNameColumnToken;
|
||||
mdb_token m_FamilyNameColumnToken;
|
||||
mdb_token m_DefaultAddressColumnToken;
|
||||
mdb_token m_CategoryColumnToken;
|
||||
mdb_token m_WebPage1ColumnToken;
|
||||
mdb_token m_WebPage2ColumnToken;
|
||||
mdb_token m_BirthYearColumnToken;
|
||||
mdb_token m_BirthMonthColumnToken;
|
||||
mdb_token m_BirthDayColumnToken;
|
||||
mdb_token m_Custom1ColumnToken;
|
||||
mdb_token m_Custom2ColumnToken;
|
||||
mdb_token m_Custom3ColumnToken;
|
||||
mdb_token m_Custom4ColumnToken;
|
||||
mdb_token m_NotesColumnToken;
|
||||
mdb_token m_LastModDateColumnToken;
|
||||
mdb_token m_RecordKeyColumnToken;
|
||||
mdb_token m_LowerPriEmailColumnToken;
|
||||
mdb_token m_Lower2ndEmailColumnToken;
|
||||
|
||||
mdb_token m_MailFormatColumnToken;
|
||||
mdb_token m_PopularityIndexColumnToken;
|
||||
|
||||
mdb_token m_AddressCharSetColumnToken;
|
||||
mdb_token m_LastRecordKeyColumnToken;
|
||||
|
||||
mdb_token m_ListNameColumnToken;
|
||||
mdb_token m_ListNickNameColumnToken;
|
||||
mdb_token m_ListDescriptionColumnToken;
|
||||
mdb_token m_ListTotalColumnToken;
|
||||
mdb_token m_LowerListNameColumnToken;
|
||||
|
||||
uint32_t m_LastRecordKey;
|
||||
nsWeakPtr m_dbDirectory;
|
||||
nsCOMPtr<nsIMdbFactory> mMdbFactory;
|
||||
|
||||
private:
|
||||
nsresult GetRowForCharColumn(const char16_t *unicodeStr,
|
||||
mdb_column findColumn, bool bIsCard,
|
||||
bool aCaseInsensitive, nsIMdbRow **findRow,
|
||||
mdb_pos *aRowPos);
|
||||
bool HasRowButDeletedForCharColumn(const char16_t *unicodeStr, mdb_column findColumn, bool aIsCard, nsIMdbRow **aFindRow);
|
||||
nsresult OpenInternal(nsIFile *aMabFile, bool aCreate, nsIAddrDatabase **pCardDB);
|
||||
nsresult AlertAboutCorruptMabFile(const char16_t *aOldFileName, const char16_t *aNewFileName);
|
||||
nsresult AlertAboutLockedMabFile(const char16_t *aFileName);
|
||||
nsresult DisplayAlert(const char16_t *titleName, const char16_t *alertStringName,
|
||||
const char16_t **formatStrings, int32_t numFormatStrings);
|
||||
};
|
||||
|
||||
#endif
|
||||
12
mailnews/addrbook/src/nsAddrbook.manifest
Normal file
12
mailnews/addrbook/src/nsAddrbook.manifest
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
component {5b259db2-e451-4de9-8a6f-cfba91402973} nsAbAutoCompleteMyDomain.js
|
||||
contract @mozilla.org/autocomplete/search;1?name=mydomain {5b259db2-e451-4de9-8a6f-cfba91402973}
|
||||
component {2f946df9-114c-41fe-8899-81f10daf4f0c} nsAbAutoCompleteSearch.js
|
||||
contract @mozilla.org/autocomplete/search;1?name=addrbook {2f946df9-114c-41fe-8899-81f10daf4f0c}
|
||||
component {127b341a-bdda-4270-85e1-edff569a9b85} nsAbLDAPAttributeMap.js
|
||||
contract @mozilla.org/addressbook/ldap-attribute-map;1 {127b341a-bdda-4270-85e1-edff569a9b85}
|
||||
component {4ed7d5e1-8800-40da-9e78-c4f509d7ac5e} nsAbLDAPAttributeMap.js
|
||||
contract @mozilla.org/addressbook/ldap-attribute-map-service;1 {4ed7d5e1-8800-40da-9e78-c4f509d7ac5e}
|
||||
#ifdef MOZ_LDAP_XPCOM
|
||||
component {227e6482-fe9f-441f-9b7d-7b60375e7449} nsAbLDAPAutoCompleteSearch.js
|
||||
contract @mozilla.org/autocomplete/search;1?name=ldap {227e6482-fe9f-441f-9b7d-7b60375e7449}
|
||||
#endif
|
||||
1452
mailnews/addrbook/src/nsDirPrefs.cpp
Normal file
1452
mailnews/addrbook/src/nsDirPrefs.cpp
Normal file
File diff suppressed because it is too large
Load diff
86
mailnews/addrbook/src/nsDirPrefs.h
Normal file
86
mailnews/addrbook/src/nsDirPrefs.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _NSDIRPREFS_H_
|
||||
#define _NSDIRPREFS_H_
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
//
|
||||
// XXX nsDirPrefs is being greatly reduced if not removed altogether. Directory
|
||||
// Prefs etc. should be handled via their appropriate nsAb*Directory classes.
|
||||
//
|
||||
|
||||
#define kPreviousListVersion 2
|
||||
#define kCurrentListVersion 3
|
||||
#define PREF_LDAP_GLOBAL_TREE_NAME "ldap_2"
|
||||
#define PREF_LDAP_VERSION_NAME "ldap_2.version"
|
||||
#define PREF_LDAP_SERVER_TREE_NAME "ldap_2.servers"
|
||||
|
||||
#define kMainLdapAddressBook "ldap.mab" /* v3 main ldap address book file */
|
||||
|
||||
/* DIR_Server.dirType */
|
||||
typedef enum
|
||||
{
|
||||
LDAPDirectory,
|
||||
HTMLDirectory,
|
||||
PABDirectory,
|
||||
MAPIDirectory,
|
||||
FixedQueryLDAPDirectory = 777
|
||||
} DirectoryType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
idNone = 0, /* Special value */
|
||||
idPrefName,
|
||||
idPosition,
|
||||
idDescription,
|
||||
idFileName,
|
||||
idUri,
|
||||
idType
|
||||
} DIR_PrefId;
|
||||
|
||||
#define DIR_Server_typedef 1 /* this quiets a redeclare warning in libaddr */
|
||||
|
||||
typedef struct DIR_Server
|
||||
{
|
||||
/* Housekeeping fields */
|
||||
char *prefName; /* preference name, this server's subtree */
|
||||
int32_t position; /* relative position in server list */
|
||||
|
||||
/* General purpose fields */
|
||||
char *description; /* human readable name */
|
||||
char *fileName; /* XP path name of local DB */
|
||||
DirectoryType dirType;
|
||||
char *uri; // URI of the address book
|
||||
|
||||
// Set whilst saving the server to avoid updating it again
|
||||
bool savingServer;
|
||||
} DIR_Server;
|
||||
|
||||
/* We are developing a new model for managing DIR_Servers. In the 4.0x world, the FEs managed each list.
|
||||
Calls to FE_GetDirServer caused the FEs to manage and return the DIR_Server list. In our new view of the
|
||||
world, the back end does most of the list management so we are going to have the back end create and
|
||||
manage the list. Replace calls to FE_GetDirServers() with DIR_GetDirServers(). */
|
||||
|
||||
nsTArray<DIR_Server*>* DIR_GetDirectories();
|
||||
DIR_Server* DIR_GetServerFromList(const char* prefName);
|
||||
nsresult DIR_ShutDown(void); /* FEs should call this when the app is shutting down. It frees all DIR_Servers regardless of ref count values! */
|
||||
|
||||
nsresult DIR_AddNewAddressBook(const nsAString &dirName,
|
||||
const nsACString &fileName,
|
||||
const nsACString &uri,
|
||||
DirectoryType dirType,
|
||||
const nsACString &prefName,
|
||||
DIR_Server** pServer);
|
||||
nsresult DIR_ContainsServer(DIR_Server* pServer, bool *hasDir);
|
||||
|
||||
nsresult DIR_DeleteServerFromList (DIR_Server *);
|
||||
|
||||
void DIR_SavePrefsForOneServer(DIR_Server *server);
|
||||
|
||||
void DIR_SetServerFileName(DIR_Server* pServer);
|
||||
|
||||
#endif /* dirprefs.h */
|
||||
147
mailnews/addrbook/src/nsMapiAddressBook.cpp
Normal file
147
mailnews/addrbook/src/nsMapiAddressBook.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "nsMapiAddressBook.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gMapiAddressBookLog
|
||||
= PR_NewLogModule("nsMapiAddressBookLog");
|
||||
#endif
|
||||
|
||||
#define PRINTF(args) MOZ_LOG(gMapiAddressBookLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
HMODULE nsMapiAddressBook::mLibrary = NULL ;
|
||||
int32_t nsMapiAddressBook::mLibUsage = 0 ;
|
||||
LPMAPIINITIALIZE nsMapiAddressBook::mMAPIInitialize = NULL ;
|
||||
LPMAPIUNINITIALIZE nsMapiAddressBook::mMAPIUninitialize = NULL ;
|
||||
LPMAPIALLOCATEBUFFER nsMapiAddressBook::mMAPIAllocateBuffer = NULL ;
|
||||
LPMAPIFREEBUFFER nsMapiAddressBook::mMAPIFreeBuffer = NULL ;
|
||||
LPMAPILOGONEX nsMapiAddressBook::mMAPILogonEx = NULL ;
|
||||
|
||||
BOOL nsMapiAddressBook::mInitialized = FALSE ;
|
||||
BOOL nsMapiAddressBook::mLogonDone = FALSE ;
|
||||
LPMAPISESSION nsMapiAddressBook::mRootSession = NULL ;
|
||||
LPADRBOOK nsMapiAddressBook::mRootBook = NULL ;
|
||||
|
||||
BOOL nsMapiAddressBook::LoadMapiLibrary(void)
|
||||
{
|
||||
if (mLibrary) { ++ mLibUsage ; return TRUE ; }
|
||||
HMODULE libraryHandle = LoadLibrary("MAPI32.DLL") ;
|
||||
|
||||
if (!libraryHandle) { return FALSE ; }
|
||||
FARPROC entryPoint = GetProcAddress(libraryHandle, "MAPIGetNetscapeVersion") ;
|
||||
|
||||
if (entryPoint) {
|
||||
FreeLibrary(libraryHandle) ;
|
||||
libraryHandle = LoadLibrary("MAPI32BAK.DLL") ;
|
||||
if (!libraryHandle) { return FALSE ; }
|
||||
}
|
||||
mLibrary = libraryHandle ;
|
||||
++ mLibUsage ;
|
||||
mMAPIInitialize = reinterpret_cast<LPMAPIINITIALIZE>(GetProcAddress(mLibrary, "MAPIInitialize")) ;
|
||||
if (!mMAPIInitialize) { return FALSE ; }
|
||||
mMAPIUninitialize = reinterpret_cast<LPMAPIUNINITIALIZE>(GetProcAddress(mLibrary, "MAPIUninitialize")) ;
|
||||
if (!mMAPIUninitialize) { return FALSE ; }
|
||||
mMAPIAllocateBuffer = reinterpret_cast<LPMAPIALLOCATEBUFFER>(GetProcAddress(mLibrary, "MAPIAllocateBuffer")) ;
|
||||
if (!mMAPIAllocateBuffer) { return FALSE ; }
|
||||
mMAPIFreeBuffer = reinterpret_cast<LPMAPIFREEBUFFER>(GetProcAddress(mLibrary, "MAPIFreeBuffer")) ;
|
||||
if (!mMAPIFreeBuffer) { return FALSE ; }
|
||||
mMAPILogonEx = reinterpret_cast<LPMAPILOGONEX>(GetProcAddress(mLibrary, "MAPILogonEx")) ;
|
||||
if (!mMAPILogonEx) { return FALSE ; }
|
||||
MAPIINIT_0 mapiInit = { MAPI_INIT_VERSION, MAPI_MULTITHREAD_NOTIFICATIONS } ;
|
||||
HRESULT retCode = mMAPIInitialize(&mapiInit) ;
|
||||
|
||||
if (HR_FAILED(retCode)) {
|
||||
PRINTF(("Cannot initialize MAPI %08x.\n", retCode)) ; return FALSE ;
|
||||
}
|
||||
mInitialized = TRUE ;
|
||||
retCode = mMAPILogonEx(0, NULL, NULL,
|
||||
MAPI_NO_MAIL |
|
||||
MAPI_USE_DEFAULT |
|
||||
MAPI_EXTENDED |
|
||||
MAPI_NEW_SESSION,
|
||||
&mRootSession) ;
|
||||
if (HR_FAILED(retCode)) {
|
||||
PRINTF(("Cannot logon to MAPI %08x.\n", retCode)) ; return FALSE ;
|
||||
}
|
||||
mLogonDone = TRUE ;
|
||||
retCode = mRootSession->OpenAddressBook(0, NULL, 0, &mRootBook) ;
|
||||
if (HR_FAILED(retCode)) {
|
||||
PRINTF(("Cannot open MAPI address book %08x.\n", retCode)) ;
|
||||
}
|
||||
return HR_SUCCEEDED(retCode) ;
|
||||
}
|
||||
|
||||
void nsMapiAddressBook::FreeMapiLibrary(void)
|
||||
{
|
||||
if (mLibrary) {
|
||||
if (-- mLibUsage == 0) {
|
||||
{
|
||||
if (mRootBook) { mRootBook->Release() ; }
|
||||
if (mRootSession) {
|
||||
if (mLogonDone) {
|
||||
mRootSession->Logoff(NULL, 0, 0) ;
|
||||
mLogonDone = FALSE ;
|
||||
}
|
||||
mRootSession->Release() ;
|
||||
}
|
||||
if (mInitialized) {
|
||||
mMAPIUninitialize() ;
|
||||
mInitialized = FALSE ;
|
||||
}
|
||||
}
|
||||
FreeLibrary(mLibrary) ;
|
||||
mLibrary = NULL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsMapiAddressBook::nsMapiAddressBook(void)
|
||||
: nsAbWinHelper()
|
||||
{
|
||||
BOOL result = Initialize() ;
|
||||
|
||||
NS_ASSERTION(result == TRUE, "Couldn't initialize Mapi Helper") ;
|
||||
MOZ_COUNT_CTOR(nsMapiAddressBook) ;
|
||||
}
|
||||
|
||||
nsMapiAddressBook::~nsMapiAddressBook(void)
|
||||
{
|
||||
MutexAutoLock guard(*mMutex) ;
|
||||
|
||||
FreeMapiLibrary() ;
|
||||
MOZ_COUNT_DTOR(nsMapiAddressBook) ;
|
||||
}
|
||||
|
||||
BOOL nsMapiAddressBook::Initialize(void)
|
||||
{
|
||||
if (mAddressBook) { return TRUE ; }
|
||||
MutexAutoLock guard(*mMutex) ;
|
||||
|
||||
if (!LoadMapiLibrary()) {
|
||||
PRINTF(("Cannot load library.\n")) ;
|
||||
return FALSE ;
|
||||
}
|
||||
mAddressBook = mRootBook ;
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
void nsMapiAddressBook::AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer)
|
||||
{
|
||||
mMAPIAllocateBuffer(aByteCount, aBuffer) ;
|
||||
}
|
||||
|
||||
void nsMapiAddressBook::FreeBuffer(LPVOID aBuffer)
|
||||
{
|
||||
mMAPIFreeBuffer(aBuffer) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
54
mailnews/addrbook/src/nsMapiAddressBook.h
Normal file
54
mailnews/addrbook/src/nsMapiAddressBook.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsMapiAddressBook_h___
|
||||
#define nsMapiAddressBook_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbWinHelper.h"
|
||||
|
||||
class nsMapiAddressBook : public nsAbWinHelper
|
||||
{
|
||||
public :
|
||||
nsMapiAddressBook(void) ;
|
||||
virtual ~nsMapiAddressBook(void) ;
|
||||
|
||||
protected :
|
||||
// Class members to handle the library/entry points
|
||||
static HMODULE mLibrary ;
|
||||
static int32_t mLibUsage ;
|
||||
static LPMAPIINITIALIZE mMAPIInitialize ;
|
||||
static LPMAPIUNINITIALIZE mMAPIUninitialize ;
|
||||
static LPMAPIALLOCATEBUFFER mMAPIAllocateBuffer ;
|
||||
static LPMAPIFREEBUFFER mMAPIFreeBuffer ;
|
||||
static LPMAPILOGONEX mMAPILogonEx ;
|
||||
// Shared session and address book used by all instances.
|
||||
// For reasons best left unknown, MAPI doesn't seem to like
|
||||
// having different threads playing with supposedly different
|
||||
// sessions and address books. They ll end up fighting over
|
||||
// the same resources, with hangups and GPF resulting. Not nice.
|
||||
// So it seems that if everybody (as long as some client is
|
||||
// still alive) is using the same sessions and address books,
|
||||
// MAPI feels better. And who are we to get in the way of MAPI
|
||||
// happiness? Thus the following class members:
|
||||
static BOOL mInitialized ;
|
||||
static BOOL mLogonDone ;
|
||||
static LPMAPISESSION mRootSession ;
|
||||
static LPADRBOOK mRootBook ;
|
||||
|
||||
// Load the MAPI environment
|
||||
BOOL Initialize(void) ;
|
||||
// Allocation of a buffer for transmission to interfaces
|
||||
virtual void AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) override;
|
||||
// Destruction of a buffer provided by the interfaces
|
||||
virtual void FreeBuffer(LPVOID aBuffer) override;
|
||||
// Library management
|
||||
static BOOL LoadMapiLibrary(void) ;
|
||||
static void FreeMapiLibrary(void) ;
|
||||
|
||||
private :
|
||||
} ;
|
||||
|
||||
#endif // nsMapiAddressBook_h___
|
||||
|
||||
77
mailnews/addrbook/src/nsMsgVCardService.cpp
Normal file
77
mailnews/addrbook/src/nsMsgVCardService.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsMsgVCardService.h"
|
||||
#include "nsVCard.h"
|
||||
#include "prmem.h"
|
||||
#include "plstr.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgVCardService, nsIMsgVCardService)
|
||||
|
||||
nsMsgVCardService::nsMsgVCardService()
|
||||
{
|
||||
}
|
||||
|
||||
nsMsgVCardService::~nsMsgVCardService()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void) nsMsgVCardService::CleanVObject(VObject * o)
|
||||
{
|
||||
cleanVObject(o);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(VObject *) nsMsgVCardService::NextVObjectInList(VObject * o)
|
||||
{
|
||||
return nextVObjectInList(o);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(VObject *) nsMsgVCardService::Parse_MIME(const char *input, uint32_t len)
|
||||
{
|
||||
return parse_MIME(input, (unsigned long)len);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(char *) nsMsgVCardService::FakeCString(VObject * o)
|
||||
{
|
||||
return fakeCString(vObjectUStringZValue(o));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(VObject *) nsMsgVCardService::IsAPropertyOf(VObject * o, const char *id)
|
||||
{
|
||||
return isAPropertyOf(o,id);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(char *) nsMsgVCardService::WriteMemoryVObjects(const char *s, int32_t *len, VObject * list, bool expandSpaces)
|
||||
{
|
||||
return writeMemoryVObjects((char *)s, len, list, expandSpaces);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(VObject *) nsMsgVCardService::NextVObject(VObjectIterator * i)
|
||||
{
|
||||
return nextVObject(i);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void) nsMsgVCardService::InitPropIterator(VObjectIterator * i, VObject * o)
|
||||
{
|
||||
initPropIterator(i,o);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(int32_t) nsMsgVCardService::MoreIteration(VObjectIterator * i)
|
||||
{
|
||||
return ((int32_t)moreIteration(i));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(const char *) nsMsgVCardService::VObjectName(VObject * o)
|
||||
{
|
||||
return vObjectName(o);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(char *) nsMsgVCardService::VObjectAnyValue(VObject * o)
|
||||
{
|
||||
char *retval = (char *)PR_MALLOC(strlen((char *)vObjectAnyValue(o)) + 1);
|
||||
if (retval)
|
||||
PL_strcpy(retval, (char *) vObjectAnyValue(o));
|
||||
return retval;
|
||||
}
|
||||
24
mailnews/addrbook/src/nsMsgVCardService.h
Normal file
24
mailnews/addrbook/src/nsMsgVCardService.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsMsgVCardService_h___
|
||||
#define nsMsgVCardService_h___
|
||||
|
||||
#include "nsIMsgVCardService.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsMsgVCardService : public nsIMsgVCardService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGVCARDSERVICE
|
||||
|
||||
nsMsgVCardService();
|
||||
|
||||
private:
|
||||
virtual ~nsMsgVCardService();
|
||||
};
|
||||
|
||||
#endif /* nsMsgVCardService_h___ */
|
||||
1571
mailnews/addrbook/src/nsVCard.cpp
Normal file
1571
mailnews/addrbook/src/nsVCard.cpp
Normal file
File diff suppressed because it is too large
Load diff
64
mailnews/addrbook/src/nsVCard.h
Normal file
64
mailnews/addrbook/src/nsVCard.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
|
||||
For purposes of this license notice, the term Licensors shall mean,
|
||||
collectively, Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
The term Licensor shall mean any of the Licensors.
|
||||
|
||||
Subject to acceptance of the following conditions, permission is hereby
|
||||
granted by Licensors without the need for written agreement and without
|
||||
license or royalty fees, to use, copy, modify and distribute this
|
||||
software for any purpose.
|
||||
|
||||
The above copyright notice and the following four paragraphs must be
|
||||
reproduced in all copies of this software and any software including
|
||||
this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
||||
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
||||
MODIFICATIONS.
|
||||
|
||||
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The software is provided with RESTRICTED RIGHTS. Use, duplication, or
|
||||
disclosure by the government are subject to restrictions set forth in
|
||||
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __VCC_H__
|
||||
#define __VCC_H__ 1
|
||||
|
||||
#include "nsVCardObj.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
VObject* parse_MIME(const char *input, unsigned long len);
|
||||
|
||||
typedef void (*MimeErrorHandler)(char *);
|
||||
|
||||
void registerMimeErrorHandler(MimeErrorHandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VCC_H__ */
|
||||
1330
mailnews/addrbook/src/nsVCardObj.cpp
Normal file
1330
mailnews/addrbook/src/nsVCardObj.cpp
Normal file
File diff suppressed because it is too large
Load diff
396
mailnews/addrbook/src/nsVCardObj.h
Normal file
396
mailnews/addrbook/src/nsVCardObj.h
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/***************************************************************************
|
||||
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
|
||||
For purposes of this license notice, the term Licensors shall mean,
|
||||
collectively, Apple Computer, Inc., AT&T Corp., International
|
||||
Business Machines Corporation and Siemens Rolm Communications Inc.
|
||||
The term Licensor shall mean any of the Licensors.
|
||||
|
||||
Subject to acceptance of the following conditions, permission is hereby
|
||||
granted by Licensors without the need for written agreement and without
|
||||
license or royalty fees, to use, copy, modify and distribute this
|
||||
software for any purpose.
|
||||
|
||||
The above copyright notice and the following four paragraphs must be
|
||||
reproduced in all copies of this software and any software including
|
||||
this software.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
||||
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
||||
MODIFICATIONS.
|
||||
|
||||
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
||||
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
||||
The software is provided with RESTRICTED RIGHTS. Use, duplication, or
|
||||
disclosure by the government are subject to restrictions set forth in
|
||||
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
The vCard/vCalendar C interface is implemented in the set
|
||||
of files as follows:
|
||||
|
||||
vcc.y, yacc source, and vcc.c, the yacc output you will use
|
||||
implements the core parser
|
||||
|
||||
vobject.c implements an API that insulates the caller from
|
||||
the parser and changes in the vCard/vCalendar BNF
|
||||
|
||||
port.h defines compilation environment dependent stuff
|
||||
|
||||
vcc.h and vobject.h are header files for their .c counterparts
|
||||
|
||||
vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
|
||||
which you may find useful.
|
||||
|
||||
test.c is a standalone test driver that exercises some of
|
||||
the features of the APIs provided. Invoke test.exe on a
|
||||
VCARD/VCALENDAR input text file and you will see the pretty
|
||||
print output of the internal representation (this pretty print
|
||||
output should give you a good idea of how the internal
|
||||
representation looks like -- there is one such output in the
|
||||
following too). Also, a file with the .out suffix is generated
|
||||
to show that the internal representation can be written back
|
||||
in the original text format.
|
||||
|
||||
For more information on this API see the readme.txt file
|
||||
which accompanied this distribution.
|
||||
|
||||
Also visit:
|
||||
|
||||
http://www.versit.com
|
||||
http://www.ralden.com
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __VOBJECT_H__
|
||||
#define __VOBJECT_H__ 1
|
||||
|
||||
/*
|
||||
Unfortunately, on the Mac (and possibly other platforms) with our current, out-dated
|
||||
libraries (Plauger), |wchar_t| is defined incorrectly, which breaks vcards.
|
||||
|
||||
We can't fix Plauger because it doesn't come with source. Later, when we
|
||||
upgrade to MSL, we can make this evil hack go away. In the mean time,
|
||||
vcards are not allowed to use the (incorrectly defined) |wchar_t| type. Instead,
|
||||
they will use an appropriately defined local type |vwchar_t|.
|
||||
*/
|
||||
|
||||
typedef wchar_t vwchar_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VC7bitProp "7bit"
|
||||
#define VC8bitProp "8bit"
|
||||
#define VCAAlarmProp "aalarm"
|
||||
#define VCAdditionalNamesProp "addn"
|
||||
#define VCAdrProp "adr"
|
||||
#define VCAgentProp "agent"
|
||||
#define VCAIFFProp "aiff"
|
||||
#define VCAOLProp "aol"
|
||||
#define VCAppleLinkProp "applelink"
|
||||
#define VCAttachProp "attach"
|
||||
#define VCAttendeeProp "attendee"
|
||||
#define VCATTMailProp "attmail"
|
||||
#define VCAudioContentProp "audiocontent"
|
||||
#define VCAVIProp "avi"
|
||||
#define VCBase64Prop "base64"
|
||||
#define VCBBSProp "bbs"
|
||||
#define VCBirthDateProp "bday"
|
||||
#define VCBMPProp "bmp"
|
||||
#define VCBodyProp "body"
|
||||
#define VCBusinessRoleProp "role"
|
||||
#define VCCalProp "vcalendar"
|
||||
#define VCCaptionProp "cap"
|
||||
#define VCCardProp "vcard"
|
||||
#define VCCarProp "car"
|
||||
#define VCCategoriesProp "categories"
|
||||
#define VCCellularProp "cell"
|
||||
#define VCCGMProp "cgm"
|
||||
#define VCCharSetProp "cs"
|
||||
#define VCCIDProp "cid"
|
||||
#define VCCISProp "cis"
|
||||
#define VCCityProp "l"
|
||||
#define VCClassProp "class"
|
||||
#define VCCommentProp "note"
|
||||
#define VCCompletedProp "completed"
|
||||
#define VCContentIDProp "content-id"
|
||||
#define VCCountryNameProp "c"
|
||||
#define VCDAlarmProp "dalarm"
|
||||
#define VCDataSizeProp "datasize"
|
||||
#define VCDayLightProp "daylight"
|
||||
#define VCDCreatedProp "dcreated"
|
||||
#define VCDeliveryLabelProp "label"
|
||||
#define VCDescriptionProp "description"
|
||||
#define VCDIBProp "dib"
|
||||
#define VCDisplayStringProp "displaystring"
|
||||
#define VCDomesticProp "dom"
|
||||
#define VCDTendProp "dtend"
|
||||
#define VCDTstartProp "dtstart"
|
||||
#define VCDueProp "due"
|
||||
#define VCEmailAddressProp "email"
|
||||
#define VCEncodingProp "encoding"
|
||||
#define VCEndProp "end"
|
||||
#define VCEventProp "vevent"
|
||||
#define VCEWorldProp "eworld"
|
||||
#define VCExNumProp "exnum"
|
||||
#define VCExpDateProp "exdate"
|
||||
#define VCExpectProp "expect"
|
||||
#define VCExtAddressProp "ext add"
|
||||
#define VCFamilyNameProp "f"
|
||||
#define VCFaxProp "fax"
|
||||
#define VCFullNameProp "fn"
|
||||
#define VCGeoProp "geo"
|
||||
#define VCGeoLocationProp "geo"
|
||||
#define VCGIFProp "gif"
|
||||
#define VCGivenNameProp "g"
|
||||
#define VCGroupingProp "grouping"
|
||||
#define VCHomeProp "home"
|
||||
#define VCIBMMailProp "ibmmail"
|
||||
#define VCInlineProp "inline"
|
||||
#define VCInternationalProp "intl"
|
||||
#define VCInternetProp "internet"
|
||||
#define VCISDNProp "isdn"
|
||||
#define VCJPEGProp "jpeg"
|
||||
#define VCLanguageProp "lang"
|
||||
#define VCLastModifiedProp "last-modified"
|
||||
#define VCLastRevisedProp "rev"
|
||||
#define VCLocationProp "location"
|
||||
#define VCLogoProp "logo"
|
||||
#define VCMailerProp "mailer"
|
||||
#define VCMAlarmProp "malarm"
|
||||
#define VCMCIMailProp "mcimail"
|
||||
#define VCMessageProp "msg"
|
||||
#define VCMETProp "met"
|
||||
#define VCModemProp "modem"
|
||||
#define VCMPEG2Prop "mpeg2"
|
||||
#define VCMPEGProp "mpeg"
|
||||
#define VCMSNProp "msn"
|
||||
#define VCNamePrefixesProp "npre"
|
||||
#define VCNameProp "n"
|
||||
#define VCNameSuffixesProp "nsuf"
|
||||
#define VCNoteProp "note"
|
||||
#define VCOrgNameProp "orgname"
|
||||
#define VCOrgProp "org"
|
||||
#define VCOrgUnit2Prop "oun2"
|
||||
#define VCOrgUnit3Prop "oun3"
|
||||
#define VCOrgUnit4Prop "oun4"
|
||||
#define VCOrgUnitProp "oun"
|
||||
#define VCPagerProp "pager"
|
||||
#define VCPAlarmProp "palarm"
|
||||
#define VCParcelProp "parcel"
|
||||
#define VCPartProp "part"
|
||||
#define VCPCMProp "pcm"
|
||||
#define VCPDFProp "pdf"
|
||||
#define VCPGPProp "pgp"
|
||||
#define VCPhotoProp "photo"
|
||||
#define VCPICTProp "pict"
|
||||
#define VCPMBProp "pmb"
|
||||
#define VCPostalBoxProp "box"
|
||||
#define VCPostalCodeProp "pc"
|
||||
#define VCPostalProp "postal"
|
||||
#define VCPowerShareProp "powershare"
|
||||
#define VCPreferredProp "pref"
|
||||
#define VCPriorityProp "priority"
|
||||
#define VCProcedureNameProp "procedurename"
|
||||
#define VCProdIdProp "prodid"
|
||||
#define VCProdigyProp "prodigy"
|
||||
#define VCPronunciationProp "sound"
|
||||
#define VCPSProp "ps"
|
||||
#define VCPublicKeyProp "key"
|
||||
#define VCQPProp "qp"
|
||||
#define VCQuickTimeProp "qtime"
|
||||
#define VCQuotedPrintableProp "quoted-printable"
|
||||
#define VCRDateProp "rdate"
|
||||
#define VCRegionProp "r"
|
||||
#define VCRelatedToProp "related-to"
|
||||
#define VCRepeatCountProp "repeatcount"
|
||||
#define VCResourcesProp "resources"
|
||||
#define VCRNumProp "rnum"
|
||||
#define VCRoleProp "role"
|
||||
#define VCRRuleProp "rrule"
|
||||
#define VCRSVPProp "rsvp"
|
||||
#define VCRunTimeProp "runtime"
|
||||
#define VCSequenceProp "sequence"
|
||||
#define VCSnoozeTimeProp "snoozetime"
|
||||
#define VCStartProp "start"
|
||||
#define VCStatusProp "status"
|
||||
#define VCStreetAddressProp "street"
|
||||
#define VCSubTypeProp "subtype"
|
||||
#define VCSummaryProp "summary"
|
||||
#define VCTelephoneProp "tel"
|
||||
#define VCTIFFProp "tiff"
|
||||
#define VCTimeZoneProp "tz"
|
||||
#define VCTitleProp "title"
|
||||
#define VCTLXProp "tlx"
|
||||
#define VCTodoProp "vtodo"
|
||||
#define VCTranspProp "transp"
|
||||
#define VCUniqueStringProp "uid"
|
||||
#define VCURLProp "url"
|
||||
#define VCURLValueProp "urlval"
|
||||
#define VCValueProp "value"
|
||||
#define VCVersionProp "version"
|
||||
#define VCVideoProp "video"
|
||||
#define VCVoiceProp "voice"
|
||||
#define VCWAVEProp "wave"
|
||||
#define VCWMFProp "wmf"
|
||||
#define VCWorkProp "work"
|
||||
#define VCX400Prop "x400"
|
||||
#define VCX509Prop "x509"
|
||||
#define VCXRuleProp "xrule"
|
||||
#define VCCooltalk "x-mozilla-cpt"
|
||||
#define VCCooltalkAddress "x-moxilla-cpadr"
|
||||
#define VCUseServer "x-mozilla-cpsrv"
|
||||
#define VCUseHTML "x-mozilla-html"
|
||||
|
||||
/* return type of vObjectValueType: */
|
||||
#define VCVT_NOVALUE 0
|
||||
/* if the VObject has no value associated with it. */
|
||||
#define VCVT_STRINGZ 1
|
||||
/* if the VObject has value set by setVObjectStringZValue. */
|
||||
#define VCVT_USTRINGZ 2
|
||||
/* if the VObject has value set by setVObjectUStringZValue. */
|
||||
#define VCVT_UINT 3
|
||||
/* if the VObject has value set by setVObjectIntegerValue. */
|
||||
#define VCVT_ULONG 4
|
||||
/* if the VObject has value set by setVObjectLongValue. */
|
||||
#define VCVT_RAW 5
|
||||
/* if the VObject has value set by setVObjectAnyValue. */
|
||||
#define VCVT_VOBJECT 6
|
||||
/* if the VObject has value set by setVObjectVObjectValue. */
|
||||
|
||||
#define NAME_OF(o) o->id
|
||||
#define VALUE_TYPE(o) o->valType
|
||||
#define STRINGZ_VALUE_OF(o) o->val.strs
|
||||
#define USTRINGZ_VALUE_OF(o) o->val.ustrs
|
||||
#define INTEGER_VALUE_OF(o) o->val.i
|
||||
#define LONG_VALUE_OF(o) o->val.l
|
||||
#define ANY_VALUE_OF(o) o->val.any
|
||||
#define VOBJECT_VALUE_OF(o) o->val.vobj
|
||||
|
||||
typedef struct VObject VObject;
|
||||
|
||||
typedef union ValueItem {
|
||||
const char *strs;
|
||||
const vwchar_t *ustrs;
|
||||
unsigned int i;
|
||||
unsigned long l;
|
||||
void *any;
|
||||
VObject *vobj;
|
||||
} ValueItem;
|
||||
|
||||
struct VObject {
|
||||
VObject *next;
|
||||
const char *id;
|
||||
VObject *prop;
|
||||
unsigned short valType;
|
||||
ValueItem val;
|
||||
};
|
||||
|
||||
typedef struct StrItem StrItem;
|
||||
|
||||
struct StrItem {
|
||||
StrItem *next;
|
||||
const char *s;
|
||||
unsigned int refCnt;
|
||||
};
|
||||
|
||||
typedef struct OFile {
|
||||
char *s;
|
||||
int len;
|
||||
int limit;
|
||||
int alloc:1;
|
||||
int fail:1;
|
||||
} OFile;
|
||||
|
||||
typedef struct VObjectIterator {
|
||||
VObject* start;
|
||||
VObject* next;
|
||||
} VObjectIterator;
|
||||
|
||||
VObject* newVObject(const char *id);
|
||||
void deleteVObject(VObject *p);
|
||||
char* dupStr(const char *s, unsigned int size);
|
||||
extern "C" void deleteString(char *p);
|
||||
void unUseStr(const char *s);
|
||||
|
||||
void setVObjectName(VObject *o, const char* id);
|
||||
void setVObjectStringZValue(VObject *o, const char *s);
|
||||
void setVObjectStringZValue_(VObject *o, const char *s);
|
||||
void setVObjectUStringZValue(VObject *o, const vwchar_t *s);
|
||||
void setVObjectUStringZValue_(VObject *o, const vwchar_t *s);
|
||||
void setVObjectIntegerValue(VObject *o, unsigned int i);
|
||||
void setVObjectLongValue(VObject *o, unsigned long l);
|
||||
void setVObjectAnyValue(VObject *o, void *t);
|
||||
VObject* setValueWithSize(VObject *prop, void *val, unsigned int size);
|
||||
VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size);
|
||||
|
||||
const char* vObjectName(VObject *o);
|
||||
const char* vObjectStringZValue(VObject *o);
|
||||
const vwchar_t* vObjectUStringZValue(VObject *o);
|
||||
unsigned int vObjectIntegerValue(VObject *o);
|
||||
unsigned long vObjectLongValue(VObject *o);
|
||||
void* vObjectAnyValue(VObject *o);
|
||||
VObject* vObjectVObjectValue(VObject *o);
|
||||
void setVObjectVObjectValue(VObject *o, VObject *p);
|
||||
|
||||
VObject* addVObjectProp(VObject *o, VObject *p);
|
||||
VObject* addProp(VObject *o, const char *id);
|
||||
VObject* addProp_(VObject *o, const char *id);
|
||||
VObject* addPropValue(VObject *o, const char *p, const char *v);
|
||||
VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
|
||||
VObject* addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
|
||||
VObject* addGroup(VObject *o, const char *g);
|
||||
void addList(VObject **o, VObject *p);
|
||||
|
||||
VObject* isAPropertyOf(VObject *o, const char *id);
|
||||
|
||||
VObject* nextVObjectInList(VObject *o);
|
||||
void initPropIterator(VObjectIterator *i, VObject *o);
|
||||
int moreIteration(VObjectIterator *i);
|
||||
VObject* nextVObject(VObjectIterator *i);
|
||||
|
||||
void writeVObject_(OFile *fp, VObject *o);
|
||||
char* writeMemVObject(char *s, int *len, VObject *o);
|
||||
extern "C" char* writeMemoryVObjects(char *s, int *len, VObject *list, bool expandSpaces);
|
||||
|
||||
const char* lookupStr(const char *s);
|
||||
|
||||
void cleanVObject(VObject *o);
|
||||
void cleanVObjects(VObject *list);
|
||||
|
||||
const char* lookupProp(const char* str);
|
||||
const char* lookupProp_(const char* str);
|
||||
|
||||
vwchar_t* fakeUnicode(const char *ps, int *bytes);
|
||||
int uStrLen(const vwchar_t *u);
|
||||
char* fakeCString(const vwchar_t *u);
|
||||
|
||||
#define MAXPROPNAMESIZE 256
|
||||
#define MAXMOZPROPNAMESIZE 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VOBJECT_H__ */
|
||||
|
||||
|
||||
128
mailnews/addrbook/src/nsWabAddressBook.cpp
Normal file
128
mailnews/addrbook/src/nsWabAddressBook.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <tchar.h>
|
||||
#include "nsWabAddressBook.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gWabAddressBookLog
|
||||
= PR_NewLogModule("nsWabAddressBookLog");
|
||||
#endif
|
||||
|
||||
#define PRINTF(args) MOZ_LOG(gWabAddressBookLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
HMODULE nsWabAddressBook::mLibrary = NULL ;
|
||||
int32_t nsWabAddressBook::mLibUsage = 0 ;
|
||||
LPWABOPEN nsWabAddressBook::mWABOpen = NULL ;
|
||||
LPWABOBJECT nsWabAddressBook::mRootSession = NULL ;
|
||||
LPADRBOOK nsWabAddressBook::mRootBook = NULL ;
|
||||
|
||||
BOOL nsWabAddressBook::LoadWabLibrary(void)
|
||||
{
|
||||
if (mLibrary) { ++ mLibUsage ; return TRUE ; }
|
||||
// We try to fetch the location of the WAB DLL from the registry
|
||||
TCHAR wabDLLPath [MAX_PATH] ;
|
||||
DWORD keyType = 0 ;
|
||||
ULONG byteCount = sizeof(wabDLLPath) ;
|
||||
HKEY keyHandle = NULL ;
|
||||
wabDLLPath [MAX_PATH - 1] = 0 ;
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &keyHandle) == ERROR_SUCCESS) {
|
||||
RegQueryValueEx(keyHandle, "", NULL, &keyType, (LPBYTE) wabDLLPath, &byteCount) ;
|
||||
if (keyType == REG_EXPAND_SZ) {
|
||||
// Expand the environment variables
|
||||
DWORD bufferSize = ExpandEnvironmentStrings(wabDLLPath, NULL, 0);
|
||||
if (bufferSize && bufferSize < MAX_PATH) {
|
||||
TCHAR tmp[MAX_PATH];
|
||||
ExpandEnvironmentStrings(wabDLLPath, tmp, bufferSize);
|
||||
_tcscpy(wabDLLPath, tmp);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (GetSystemDirectory(wabDLLPath, MAX_PATH)) {
|
||||
_tcsncat(wabDLLPath, WAB_DLL_NAME,
|
||||
std::min(_tcslen(WAB_DLL_NAME), MAX_PATH - _tcslen(wabDLLPath) - 1));
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (keyHandle) { RegCloseKey(keyHandle) ; }
|
||||
mLibrary = LoadLibrary( (lstrlen(wabDLLPath)) ? wabDLLPath : WAB_DLL_NAME );
|
||||
if (!mLibrary) { return FALSE ; }
|
||||
++ mLibUsage ;
|
||||
mWABOpen = reinterpret_cast<LPWABOPEN>(GetProcAddress(mLibrary, "WABOpen")) ;
|
||||
if (!mWABOpen) { return FALSE ; }
|
||||
HRESULT retCode = mWABOpen(&mRootBook, &mRootSession, NULL, 0) ;
|
||||
|
||||
if (HR_FAILED(retCode)) {
|
||||
PRINTF(("Cannot initialize WAB %08x.\n", retCode)) ; return FALSE ;
|
||||
}
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
void nsWabAddressBook::FreeWabLibrary(void)
|
||||
{
|
||||
if (mLibrary) {
|
||||
if (-- mLibUsage == 0) {
|
||||
if (mRootBook) { mRootBook->Release() ; }
|
||||
if (mRootSession) { mRootSession->Release() ; }
|
||||
FreeLibrary(mLibrary) ;
|
||||
mLibrary = NULL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsWabAddressBook::nsWabAddressBook(void)
|
||||
: nsAbWinHelper()
|
||||
{
|
||||
BOOL result = Initialize() ;
|
||||
|
||||
NS_ASSERTION(result == TRUE, "Couldn't initialize Wab Helper") ;
|
||||
MOZ_COUNT_CTOR(nsWabAddressBook) ;
|
||||
}
|
||||
|
||||
nsWabAddressBook::~nsWabAddressBook(void)
|
||||
{
|
||||
MutexAutoLock guard(*mMutex) ;
|
||||
FreeWabLibrary() ;
|
||||
MOZ_COUNT_DTOR(nsWabAddressBook) ;
|
||||
}
|
||||
|
||||
BOOL nsWabAddressBook::Initialize(void)
|
||||
{
|
||||
if (mAddressBook) { return TRUE ; }
|
||||
MutexAutoLock guard(*mMutex) ;
|
||||
|
||||
if (!LoadWabLibrary()) {
|
||||
PRINTF(("Cannot load library.\n")) ;
|
||||
return FALSE ;
|
||||
}
|
||||
mAddressBook = mRootBook ;
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
void nsWabAddressBook::AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer)
|
||||
{
|
||||
mRootSession->AllocateBuffer(aByteCount, aBuffer) ;
|
||||
}
|
||||
|
||||
void nsWabAddressBook::FreeBuffer(LPVOID aBuffer)
|
||||
{
|
||||
mRootSession->FreeBuffer(aBuffer) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
57
mailnews/addrbook/src/nsWabAddressBook.h
Normal file
57
mailnews/addrbook/src/nsWabAddressBook.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsWabAddressBook_h___
|
||||
#define nsWabAddressBook_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAbWinHelper.h"
|
||||
#include <wab.h>
|
||||
|
||||
class nsWabAddressBook : public nsAbWinHelper
|
||||
{
|
||||
public :
|
||||
nsWabAddressBook(void) ;
|
||||
virtual ~nsWabAddressBook(void) ;
|
||||
|
||||
protected :
|
||||
// Session and address book that will be shared by all instances
|
||||
// (see nsMapiAddressBook.h for details)
|
||||
static LPWABOBJECT mRootSession ;
|
||||
static LPADRBOOK mRootBook ;
|
||||
// Class members to handle library loading/entry points
|
||||
static int32_t mLibUsage ;
|
||||
static HMODULE mLibrary ;
|
||||
static LPWABOPEN mWABOpen ;
|
||||
|
||||
// Load the WAB environment
|
||||
BOOL Initialize(void) ;
|
||||
// Allocation of a buffer for transmission to interfaces
|
||||
virtual void AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) override;
|
||||
// Destruction of a buffer provided by the interfaces
|
||||
virtual void FreeBuffer(LPVOID aBuffer) override;
|
||||
// Manage the library
|
||||
static BOOL LoadWabLibrary(void) ;
|
||||
static void FreeWabLibrary(void) ;
|
||||
|
||||
private :
|
||||
} ;
|
||||
|
||||
// Additional definitions for WAB stuff. These properties are
|
||||
// only defined with regards to the default character sizes,
|
||||
// and not in two _A and _W versions...
|
||||
#define PR_BUSINESS_ADDRESS_CITY_A PR_LOCALITY_A
|
||||
#define PR_BUSINESS_ADDRESS_COUNTRY_A PR_COUNTRY_A
|
||||
#define PR_BUSINESS_ADDRESS_POSTAL_CODE_A PR_POSTAL_CODE_A
|
||||
#define PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_A PR_STATE_OR_PROVINCE_A
|
||||
#define PR_BUSINESS_ADDRESS_STREET_A PR_STREET_ADDRESS_A
|
||||
|
||||
#define PR_BUSINESS_ADDRESS_CITY_W PR_LOCALITY_W
|
||||
#define PR_BUSINESS_ADDRESS_COUNTRY_W PR_COUNTRY_W
|
||||
#define PR_BUSINESS_ADDRESS_POSTAL_CODE_W PR_POSTAL_CODE_W
|
||||
#define PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_W PR_STATE_OR_PROVINCE_W
|
||||
#define PR_BUSINESS_ADDRESS_STREET_W PR_STREET_ADDRESS_W
|
||||
|
||||
#endif // nsWABAddressBook_h___
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue