mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-28 03:17:31 +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
72
mailnews/addrbook/content/abAddressBookNameDialog.js
Normal file
72
mailnews/addrbook/content/abAddressBookNameDialog.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* 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");
|
||||
|
||||
var gOkButton;
|
||||
var gNameInput;
|
||||
var gDirectory = null;
|
||||
|
||||
var kPersonalAddressbookURI = "moz-abmdbdirectory://abook.mab";
|
||||
var kCollectedAddressbookURI = "moz-abmdbdirectory://history.mab";
|
||||
var kAllDirectoryRoot = "moz-abdirectory://";
|
||||
var kPABDirectory = 2; // defined in nsDirPrefs.h
|
||||
|
||||
function abNameOnLoad()
|
||||
{
|
||||
// Get the document elements.
|
||||
gOkButton = document.documentElement.getButton('accept');
|
||||
gNameInput = document.getElementById('name');
|
||||
|
||||
// look in arguments[0] for parameters to see if we have a directory or not
|
||||
if ("arguments" in window && window.arguments[0] &&
|
||||
"selectedDirectory" in window.arguments[0]) {
|
||||
gDirectory = window.arguments[0].selectedDirectory;
|
||||
gNameInput.value = gDirectory.dirName;
|
||||
}
|
||||
|
||||
// Work out the window title (if we have a directory specified, then it's a
|
||||
// rename).
|
||||
var bundle = document.getElementById("bundle_addressBook");
|
||||
|
||||
if (gDirectory) {
|
||||
let oldListName = gDirectory.dirName;
|
||||
document.title = bundle.getFormattedString("addressBookTitleEdit", [oldListName]);
|
||||
} else {
|
||||
document.title = bundle.getString("addressBookTitleNew");
|
||||
}
|
||||
|
||||
if (gDirectory &&
|
||||
(gDirectory.URI == kCollectedAddressbookURI ||
|
||||
gDirectory.URI == kPersonalAddressbookURI ||
|
||||
gDirectory.URI == kAllDirectoryRoot + "?")) {
|
||||
// Address book name is not editable, therefore disable the field and
|
||||
// only have an ok button that doesn't do anything.
|
||||
gNameInput.readOnly = true;
|
||||
document.documentElement.buttons = "accept";
|
||||
document.documentElement.removeAttribute("ondialogaccept");
|
||||
} else {
|
||||
gNameInput.focus();
|
||||
abNameDoOkEnabling();
|
||||
}
|
||||
}
|
||||
|
||||
function abNameOKButton()
|
||||
{
|
||||
var newName = gNameInput.value.trim();
|
||||
|
||||
// Either create a new directory or update an existing one depending on what
|
||||
// we were given when we started.
|
||||
if (gDirectory)
|
||||
gDirectory.dirName = newName;
|
||||
else
|
||||
MailServices.ab.newAddressBook(newName, "", kPABDirectory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function abNameDoOkEnabling()
|
||||
{
|
||||
gOkButton.disabled = gNameInput.value.trim() == "";
|
||||
}
|
||||
26
mailnews/addrbook/content/abAddressBookNameDialog.xul
Normal file
26
mailnews/addrbook/content/abAddressBookNameDialog.xul
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/dialogs.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abAddressBookNameDialog.dtd">
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
style="width: 36em;"
|
||||
onload="abNameOnLoad();"
|
||||
ondialogaccept="return abNameOKButton();">
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="bundle_addressBook"
|
||||
src="chrome://messenger/locale/addressbook/addressBook.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/addressbook/abAddressBookNameDialog.js"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label control="name" value="&name.label;" accesskey="&name.accesskey;"/>
|
||||
<textbox id="name" oninput="abNameDoOkEnabling();" flex="1"/>
|
||||
</hbox>
|
||||
</dialog>
|
||||
424
mailnews/addrbook/content/abDragDrop.js
Normal file
424
mailnews/addrbook/content/abDragDrop.js
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/* -*- 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://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
// Returns the load context for the current window
|
||||
function getLoadContext() {
|
||||
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext);
|
||||
}
|
||||
|
||||
var abFlavorDataProvider = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFlavorDataProvider]),
|
||||
|
||||
getFlavorData: function(aTransferable, aFlavor, aData, aDataLen)
|
||||
{
|
||||
if (aFlavor == "application/x-moz-file-promise")
|
||||
{
|
||||
var primitive = {};
|
||||
aTransferable.getTransferData("text/vcard", primitive, {});
|
||||
var vCard = primitive.value.QueryInterface(Components.interfaces.nsISupportsString).data;
|
||||
aTransferable.getTransferData("application/x-moz-file-promise-dest-filename", primitive, {});
|
||||
var leafName = primitive.value.QueryInterface(Components.interfaces.nsISupportsString).data;
|
||||
aTransferable.getTransferData("application/x-moz-file-promise-dir", primitive, {});
|
||||
var localFile = primitive.value.QueryInterface(Components.interfaces.nsIFile).clone();
|
||||
localFile.append(leafName);
|
||||
|
||||
var ofStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
ofStream.init(localFile, -1, -1, 0);
|
||||
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
converter.init(ofStream, null, 0, 0);
|
||||
converter.writeString(vCard);
|
||||
converter.close();
|
||||
|
||||
aData.value = localFile;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var abResultsPaneObserver = {
|
||||
onDragStart: function (aEvent, aXferData, aDragAction)
|
||||
{
|
||||
var selectedRows = GetSelectedRows();
|
||||
|
||||
if (!selectedRows)
|
||||
return;
|
||||
|
||||
var selectedAddresses = GetSelectedAddresses();
|
||||
|
||||
aXferData.data = new TransferData();
|
||||
aXferData.data.addDataForFlavour("moz/abcard", selectedRows);
|
||||
aXferData.data.addDataForFlavour("text/x-moz-address", selectedAddresses);
|
||||
aXferData.data.addDataForFlavour("text/unicode", selectedAddresses);
|
||||
|
||||
let srcDirectory = getSelectedDirectory();
|
||||
// The default allowable actions are copy, move and link, so we need
|
||||
// to restrict them here.
|
||||
if (!srcDirectory.readOnly)
|
||||
// Only allow copy & move from read-write directories.
|
||||
aDragAction.action = Components.interfaces.
|
||||
nsIDragService.DRAGDROP_ACTION_COPY |
|
||||
Components.interfaces.
|
||||
nsIDragService.DRAGDROP_ACTION_MOVE;
|
||||
else
|
||||
// Only allow copy from read-only directories.
|
||||
aDragAction.action = Components.interfaces.
|
||||
nsIDragService.DRAGDROP_ACTION_COPY;
|
||||
|
||||
var card = GetSelectedCard();
|
||||
if (card && card.displayName) {
|
||||
let vCard = card.translateTo("vcard");
|
||||
aXferData.data.addDataForFlavour("text/vcard", decodeURIComponent(vCard));
|
||||
aXferData.data.addDataForFlavour("application/x-moz-file-promise-dest-filename", card.displayName + ".vcf");
|
||||
aXferData.data.addDataForFlavour("application/x-moz-file-promise-url", "data:text/vcard," + vCard);
|
||||
aXferData.data.addDataForFlavour("application/x-moz-file-promise", abFlavorDataProvider);
|
||||
}
|
||||
},
|
||||
|
||||
onDrop: function (aEvent, aXferData, aDragSession)
|
||||
{
|
||||
},
|
||||
|
||||
onDragExit: function (aEvent, aDragSession)
|
||||
{
|
||||
},
|
||||
|
||||
onDragOver: function (aEvent, aFlavour, aDragSession)
|
||||
{
|
||||
},
|
||||
|
||||
getSupportedFlavours: function ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var dragService = Components.classes["@mozilla.org/widget/dragservice;1"]
|
||||
.getService(Components.interfaces.nsIDragService);
|
||||
|
||||
var abDirTreeObserver = {
|
||||
/**
|
||||
* canDrop - determine if the tree will accept the dropping of a item
|
||||
* onto it.
|
||||
*
|
||||
* Note 1: We don't allow duplicate mailing list names, therefore copy
|
||||
* is not allowed for mailing lists.
|
||||
* Note 2: Mailing lists currently really need a card in the parent
|
||||
* address book, therefore only moving to an address book is allowed.
|
||||
*
|
||||
* The possibilities:
|
||||
*
|
||||
* anything -> same place = Not allowed
|
||||
* anything -> read only directory = Not allowed
|
||||
* mailing list -> mailing list = Not allowed
|
||||
* (we currently do not support recursive lists)
|
||||
* address book card -> different address book = MOVE or COPY
|
||||
* address book card -> mailing list = COPY only
|
||||
* (cards currently have to exist outside list for list to work correctly)
|
||||
* mailing list -> different address book = MOVE only
|
||||
* (lists currently need to have unique names)
|
||||
* card in mailing list -> parent mailing list = Not allowed
|
||||
* card in mailing list -> other mailing list = MOVE or COPY
|
||||
* card in mailing list -> other address book = MOVE or COPY
|
||||
* read only directory item -> anywhere = COPY only
|
||||
*/
|
||||
canDrop: function(index, orientation, dataTransfer)
|
||||
{
|
||||
if (orientation != Components.interfaces.nsITreeView.DROP_ON)
|
||||
return false;
|
||||
if (!dataTransfer.types.includes("moz/abcard")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let targetURI = gDirectoryTreeView.getDirectoryAtIndex(index).URI;
|
||||
|
||||
let srcURI = getSelectedDirectoryURI();
|
||||
|
||||
// We cannot allow copy/move to "All Address Books".
|
||||
if (targetURI == kAllDirectoryRoot + "?")
|
||||
return false;
|
||||
|
||||
// The same place case
|
||||
if (targetURI == srcURI)
|
||||
return false;
|
||||
|
||||
// determine if we dragging from a mailing list on a directory x to the parent (directory x).
|
||||
// if so, don't allow the drop
|
||||
if (srcURI.startsWith(targetURI))
|
||||
return false;
|
||||
|
||||
// check if we can write to the target directory
|
||||
// e.g. LDAP is readonly currently
|
||||
var targetDirectory = GetDirectoryFromURI(targetURI);
|
||||
|
||||
if (targetDirectory.readOnly)
|
||||
return false;
|
||||
|
||||
var dragSession = dragService.getCurrentSession();
|
||||
if (!dragSession)
|
||||
return false;
|
||||
|
||||
// XXX Due to bug 373125/bug 349044 we can't specify a default action,
|
||||
// so we default to move and this means that the user would have to press
|
||||
// ctrl to copy which most users don't realise.
|
||||
//
|
||||
// If target directory is a mailing list, then only allow copies.
|
||||
// if (targetDirectory.isMailList &&
|
||||
// dragSession.dragAction != Components.interfaces.
|
||||
// nsIDragService.DRAGDROP_ACTION_COPY)
|
||||
//return false;
|
||||
|
||||
var srcDirectory = GetDirectoryFromURI(srcURI);
|
||||
|
||||
// Only allow copy from read-only directories.
|
||||
if (srcDirectory.readOnly &&
|
||||
dragSession.dragAction != Components.interfaces.
|
||||
nsIDragService.DRAGDROP_ACTION_COPY)
|
||||
return false;
|
||||
|
||||
// Go through the cards checking to see if one of them is a mailing list
|
||||
// (if we are attempting a copy) - we can't copy mailing lists as
|
||||
// that would give us duplicate names which isn't allowed at the
|
||||
// moment.
|
||||
var draggingMailList = false;
|
||||
|
||||
// The data contains the a string of "selected rows", eg.: "1,2".
|
||||
var rows = dataTransfer.getData("moz/abcard").split(",").map(j => parseInt(j, 10));
|
||||
|
||||
for (var j = 0; j < rows.length; j++)
|
||||
{
|
||||
if (gAbView.getCardFromRow(rows[j]).isMailList)
|
||||
{
|
||||
draggingMailList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The rest of the cases - allow cards for copy or move, but only allow
|
||||
// move of mailing lists if we're not going into another mailing list.
|
||||
if (draggingMailList &&
|
||||
(targetDirectory.isMailList ||
|
||||
dragSession.dragAction == Components.interfaces.
|
||||
nsIDragService.DRAGDROP_ACTION_COPY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dragSession.canDrop = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* onDrop - we don't need to check again for correctness as the
|
||||
* tree view calls canDrop just before calling onDrop.
|
||||
*
|
||||
*/
|
||||
onDrop: function(index, orientation, dataTransfer)
|
||||
{
|
||||
var dragSession = dragService.getCurrentSession();
|
||||
if (!dragSession)
|
||||
return;
|
||||
if (!dataTransfer.types.includes("moz/abcard")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetURI = gDirectoryTreeView.getDirectoryAtIndex(index).URI;
|
||||
let srcURI = getSelectedDirectoryURI();
|
||||
|
||||
// The data contains the a string of "selected rows", eg.: "1,2".
|
||||
var rows = dataTransfer.getData("moz/abcard").split(",").map(j => parseInt(j, 10));
|
||||
var numrows = rows.length;
|
||||
|
||||
var result;
|
||||
// needToCopyCard is used for whether or not we should be creating
|
||||
// copies of the cards in a mailing list in a different address book
|
||||
// - it's not for if we are moving or not.
|
||||
var needToCopyCard = true;
|
||||
if (srcURI.length > targetURI.length) {
|
||||
result = srcURI.split(targetURI);
|
||||
if (result[0] != srcURI) {
|
||||
// src directory is a mailing list on target directory, no need to copy card
|
||||
needToCopyCard = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = targetURI.split(srcURI);
|
||||
if (result[0] != targetURI) {
|
||||
// target directory is a mailing list on src directory, no need to copy card
|
||||
needToCopyCard = false;
|
||||
}
|
||||
}
|
||||
|
||||
// if we still think we have to copy the card,
|
||||
// check if srcURI and targetURI are mailing lists on same directory
|
||||
// if so, we don't have to copy the card
|
||||
if (needToCopyCard) {
|
||||
var targetParentURI = GetParentDirectoryFromMailingListURI(targetURI);
|
||||
if (targetParentURI && (targetParentURI == GetParentDirectoryFromMailingListURI(srcURI)))
|
||||
needToCopyCard = false;
|
||||
}
|
||||
|
||||
var directory = GetDirectoryFromURI(targetURI);
|
||||
|
||||
// Only move if we are not transferring to a mail list
|
||||
var actionIsMoving = (dragSession.dragAction & dragSession.DRAGDROP_ACTION_MOVE) && !directory.isMailList;
|
||||
|
||||
let cardsToCopy = [];
|
||||
for (let j = 0; j < numrows; j++) {
|
||||
cardsToCopy.push(gAbView.getCardFromRow(rows[j]));
|
||||
}
|
||||
for (let card of cardsToCopy) {
|
||||
if (card.isMailList) {
|
||||
// This check ensures we haven't slipped through by mistake
|
||||
if (needToCopyCard && actionIsMoving) {
|
||||
directory.addMailList(GetDirectoryFromURI(card.mailListURI));
|
||||
}
|
||||
} else {
|
||||
let srcDirectory = null;
|
||||
if (srcURI == (kAllDirectoryRoot + "?") && actionIsMoving) {
|
||||
let dirId = card.directoryId.substring(0, card.directoryId.indexOf("&"));
|
||||
srcDirectory = MailServices.ab.getDirectoryFromId(dirId);
|
||||
}
|
||||
|
||||
directory.dropCard(card, needToCopyCard);
|
||||
|
||||
// This is true only if srcURI is "All ABs" and action is moving.
|
||||
if (srcDirectory) {
|
||||
let cardArray =
|
||||
Components.classes["@mozilla.org/array;1"]
|
||||
.createInstance(Components.interfaces.nsIMutableArray);
|
||||
cardArray.appendElement(card, false);
|
||||
srcDirectory.deleteCards(cardArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cardsTransferredText;
|
||||
|
||||
// If we are moving, but not moving to a directory, then delete the
|
||||
// selected cards and display the appropriate text
|
||||
if (actionIsMoving && srcURI != (kAllDirectoryRoot + "?")) {
|
||||
// If we have moved the cards, then delete them as well.
|
||||
gAbView.deleteSelectedCards();
|
||||
}
|
||||
|
||||
if (actionIsMoving) {
|
||||
cardsTransferredText = PluralForm.get(numrows,
|
||||
gAddressBookBundle.getFormattedString("contactsMoved", [numrows]));
|
||||
} else {
|
||||
cardsTransferredText = PluralForm.get(numrows,
|
||||
gAddressBookBundle.getFormattedString("contactsCopied", [numrows]));
|
||||
}
|
||||
|
||||
if (srcURI == kAllDirectoryRoot + "?") {
|
||||
SetAbView(srcURI);
|
||||
}
|
||||
|
||||
document.getElementById("statusText").label = cardsTransferredText;
|
||||
},
|
||||
|
||||
onToggleOpenState: function()
|
||||
{
|
||||
},
|
||||
|
||||
onCycleHeader: function(colID, elt)
|
||||
{
|
||||
},
|
||||
|
||||
onCycleCell: function(row, colID)
|
||||
{
|
||||
},
|
||||
|
||||
onSelectionChanged: function()
|
||||
{
|
||||
},
|
||||
|
||||
onPerformAction: function(action)
|
||||
{
|
||||
},
|
||||
|
||||
onPerformActionOnRow: function(action, row)
|
||||
{
|
||||
},
|
||||
|
||||
onPerformActionOnCell: function(action, row, colID)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
function DragAddressOverTargetControl(event)
|
||||
{
|
||||
var dragSession = gDragService.getCurrentSession();
|
||||
|
||||
if (!dragSession.isDataFlavorSupported("text/x-moz-address"))
|
||||
return;
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
trans.addDataFlavor("text/x-moz-address");
|
||||
|
||||
var canDrop = true;
|
||||
|
||||
for ( var i = 0; i < dragSession.numDropItems; ++i )
|
||||
{
|
||||
dragSession.getData ( trans, i );
|
||||
var dataObj = new Object();
|
||||
var bestFlavor = new Object();
|
||||
var len = new Object();
|
||||
try
|
||||
{
|
||||
trans.getAnyTransferData ( bestFlavor, dataObj, len );
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
canDrop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dragSession.canDrop = canDrop;
|
||||
}
|
||||
|
||||
function DropAddressOverTargetControl(event)
|
||||
{
|
||||
var dragSession = gDragService.getCurrentSession();
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
|
||||
trans.addDataFlavor("text/x-moz-address");
|
||||
|
||||
for ( var i = 0; i < dragSession.numDropItems; ++i )
|
||||
{
|
||||
dragSession.getData ( trans, i );
|
||||
var dataObj = new Object();
|
||||
var bestFlavor = new Object();
|
||||
var len = new Object();
|
||||
|
||||
// Ensure we catch any empty data that may have slipped through
|
||||
try
|
||||
{
|
||||
trans.getAnyTransferData ( bestFlavor, dataObj, len);
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( dataObj )
|
||||
dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString);
|
||||
if ( !dataObj )
|
||||
continue;
|
||||
|
||||
// pull the address out of the data object
|
||||
var address = dataObj.data.substring(0, len.value);
|
||||
if (!address)
|
||||
continue;
|
||||
|
||||
DropRecipient(address);
|
||||
}
|
||||
}
|
||||
17
mailnews/addrbook/content/abEditCardDialog.xul
Normal file
17
mailnews/addrbook/content/abEditCardDialog.xul
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://messenger/content/addressbook/abCardOverlay.xul"?>
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="abcardWindow"
|
||||
onload="OnLoadEditCard()"
|
||||
ondialogaccept="return EditCardOKButton();">
|
||||
|
||||
<stringbundleset id="stringbundleset"/>
|
||||
<vbox id="editcard"/>
|
||||
</dialog>
|
||||
613
mailnews/addrbook/content/abMailListDialog.js
Normal file
613
mailnews/addrbook/content/abMailListDialog.js
Normal file
|
|
@ -0,0 +1,613 @@
|
|||
/* 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/. */
|
||||
|
||||
top.MAX_RECIPIENTS = 1;
|
||||
var inputElementType = "";
|
||||
|
||||
var gListCard;
|
||||
var gEditList;
|
||||
var oldListName = "";
|
||||
var gLoadListeners = [];
|
||||
var gSaveListeners = [];
|
||||
|
||||
try
|
||||
{
|
||||
var gDragService = Components.classes["@mozilla.org/widget/dragservice;1"]
|
||||
.getService(Components.interfaces.nsIDragService);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
}
|
||||
|
||||
// Returns the load context for the current window
|
||||
function getLoadContext() {
|
||||
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext);
|
||||
}
|
||||
|
||||
function awHandleKeyPress(element, event)
|
||||
{
|
||||
// allow dialog to close on enter if focused textbox has no value
|
||||
if (element.value != "" && event.keyCode == KeyEvent.DOM_VK_RETURN) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function mailingListExists(listname)
|
||||
{
|
||||
if (MailServices.ab.mailListNameExists(listname))
|
||||
{
|
||||
Services.prompt.alert(window,
|
||||
gAddressBookBundle.getString("mailListNameExistsTitle"),
|
||||
gAddressBookBundle.getString("mailListNameExistsMessage"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function GetListValue(mailList, doAdd)
|
||||
{
|
||||
var listname = document.getElementById("ListName").value.trim();
|
||||
|
||||
if (listname.length == 0)
|
||||
{
|
||||
var alertText = gAddressBookBundle.getString("emptyListName");
|
||||
alert(alertText);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var canonicalNewListName = listname.toLowerCase();
|
||||
var canonicalOldListName = oldListName.toLowerCase();
|
||||
if (doAdd)
|
||||
{
|
||||
if (mailingListExists(canonicalNewListName))
|
||||
return false;
|
||||
}
|
||||
else if (canonicalOldListName != canonicalNewListName)
|
||||
{
|
||||
if (mailingListExists(canonicalNewListName))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mailList.isMailList = true;
|
||||
mailList.dirName = listname;
|
||||
mailList.listNickName = document.getElementById('ListNickName').value;
|
||||
mailList.description = document.getElementById('ListDescription').value;
|
||||
|
||||
var oldTotal = mailList.addressLists.length;
|
||||
var i = 1;
|
||||
var pos = 0;
|
||||
var inputField, fieldValue, cardproperty;
|
||||
while ((inputField = awGetInputElement(i)))
|
||||
{
|
||||
|
||||
fieldValue = inputField.value;
|
||||
|
||||
if (doAdd || (!doAdd && pos >= oldTotal))
|
||||
cardproperty = Components.classes["@mozilla.org/addressbook/cardproperty;1"].createInstance();
|
||||
else
|
||||
cardproperty = mailList.addressLists.queryElementAt(pos, Components.interfaces.nsIAbCard);
|
||||
|
||||
if (fieldValue == "")
|
||||
{
|
||||
if (!doAdd && cardproperty)
|
||||
try
|
||||
{
|
||||
mailList.addressLists.removeElementAt(pos);
|
||||
--oldTotal;
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
// Ignore attempting to remove an item
|
||||
// at a position greater than the number
|
||||
// of elements in the addressLists attribute
|
||||
}
|
||||
}
|
||||
else if (cardproperty)
|
||||
{
|
||||
cardproperty = cardproperty.QueryInterface(Components.interfaces.nsIAbCard);
|
||||
if (cardproperty)
|
||||
{
|
||||
let addrObjects = MailServices.headerParser
|
||||
.makeFromDisplayAddress(fieldValue, {});
|
||||
for (let j = 0; j < addrObjects.length; j++)
|
||||
{
|
||||
if (j > 0)
|
||||
{
|
||||
cardproperty = Components.classes["@mozilla.org/addressbook/cardproperty;1"].createInstance();
|
||||
cardproperty = cardproperty.QueryInterface(Components.interfaces.nsIAbCard);
|
||||
}
|
||||
cardproperty.primaryEmail = addrObjects[j].email;
|
||||
cardproperty.displayName = addrObjects[j].name || addrObjects[j].email;
|
||||
|
||||
if (doAdd || (doAdd == false && pos >= oldTotal))
|
||||
mailList.addressLists.appendElement(cardproperty, false);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
--i;
|
||||
|
||||
if (doAdd == false && i < oldTotal)
|
||||
{
|
||||
for (var j = i; j < oldTotal; j++)
|
||||
mailList.addressLists.removeElementAt(j);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function MailListOKButton()
|
||||
{
|
||||
var popup = document.getElementById('abPopup');
|
||||
if (popup)
|
||||
{
|
||||
var uri = popup.getAttribute('value');
|
||||
|
||||
// FIX ME - hack to avoid crashing if no ab selected because of blank option bug from template
|
||||
// should be able to just remove this if we are not seeing blank lines in the ab popup
|
||||
if (!uri)
|
||||
return false; // don't close window
|
||||
// -----
|
||||
|
||||
//Add mailing list to database
|
||||
var mailList = Components.classes["@mozilla.org/addressbook/directoryproperty;1"].createInstance();
|
||||
mailList = mailList.QueryInterface(Components.interfaces.nsIAbDirectory);
|
||||
|
||||
if (GetListValue(mailList, true))
|
||||
{
|
||||
var parentDirectory = GetDirectoryFromURI(uri);
|
||||
mailList = parentDirectory.addMailList(mailList);
|
||||
NotifySaveListeners(mailList);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // close the window
|
||||
}
|
||||
|
||||
function OnLoadNewMailList()
|
||||
{
|
||||
var selectedAB = null;
|
||||
|
||||
InitCommonJS();
|
||||
|
||||
if ("arguments" in window && window.arguments[0])
|
||||
{
|
||||
var abURI = window.arguments[0].selectedAB;
|
||||
if (abURI && abURI != kAllDirectoryRoot + "?") {
|
||||
var directory = GetDirectoryFromURI(abURI);
|
||||
if (directory.isMailList) {
|
||||
var parentURI = GetParentDirectoryFromMailingListURI(abURI);
|
||||
if (parentURI) {
|
||||
selectedAB = parentURI;
|
||||
}
|
||||
}
|
||||
else if (directory.readOnly) {
|
||||
selectedAB = kPersonalAddressbookURI;
|
||||
}
|
||||
else {
|
||||
selectedAB = abURI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedAB)
|
||||
selectedAB = kPersonalAddressbookURI;
|
||||
|
||||
// set popup with address book names
|
||||
var abPopup = document.getElementById('abPopup');
|
||||
abPopup.value = selectedAB;
|
||||
|
||||
AppendNewRowAndSetFocus();
|
||||
awFitDummyRows(1);
|
||||
|
||||
document.addEventListener("keypress", awDocumentKeyPress, true);
|
||||
|
||||
// focus on first name
|
||||
var listName = document.getElementById('ListName');
|
||||
if (listName)
|
||||
setTimeout( function(firstTextBox) { firstTextBox.focus(); }, 0, listName );
|
||||
|
||||
NotifyLoadListeners(directory);
|
||||
}
|
||||
|
||||
function EditListOKButton()
|
||||
{
|
||||
//edit mailing list in database
|
||||
if (GetListValue(gEditList, false))
|
||||
{
|
||||
if (gListCard) {
|
||||
// modify the list card (for the results pane) from the mailing list
|
||||
gListCard.displayName = gEditList.dirName;
|
||||
gListCard.lastName = gEditList.dirName;
|
||||
gListCard.setProperty("NickName", gEditList.listNickName);
|
||||
gListCard.setProperty("Notes", gEditList.description);
|
||||
}
|
||||
|
||||
NotifySaveListeners(gEditList);
|
||||
gEditList.editMailListToDatabase(gListCard);
|
||||
|
||||
window.arguments[0].refresh = true;
|
||||
return true; // close the window
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function OnLoadEditList()
|
||||
{
|
||||
InitCommonJS();
|
||||
|
||||
gListCard = window.arguments[0].abCard;
|
||||
var listUri = window.arguments[0].listURI;
|
||||
|
||||
gEditList = GetDirectoryFromURI(listUri);
|
||||
|
||||
document.getElementById('ListName').value = gEditList.dirName;
|
||||
document.getElementById('ListNickName').value = gEditList.listNickName;
|
||||
document.getElementById('ListDescription').value = gEditList.description;
|
||||
oldListName = gEditList.dirName;
|
||||
|
||||
document.title = gAddressBookBundle.getFormattedString("mailingListTitleEdit", [oldListName]);
|
||||
|
||||
if (gEditList.addressLists)
|
||||
{
|
||||
let total = gEditList.addressLists.length;
|
||||
if (total)
|
||||
{
|
||||
let listbox = document.getElementById('addressingWidget');
|
||||
let newListBoxNode = listbox.cloneNode(false);
|
||||
let templateNode = listbox.querySelector("listitem");
|
||||
|
||||
top.MAX_RECIPIENTS = 0;
|
||||
for (let i = 0; i < total; i++)
|
||||
{
|
||||
let card = gEditList.addressLists.queryElementAt(i, Components.interfaces.nsIAbCard);
|
||||
let address = MailServices.headerParser.makeMailboxObject(
|
||||
card.displayName, card.primaryEmail).toString();
|
||||
SetInputValue(address, newListBoxNode, templateNode);
|
||||
}
|
||||
listbox.parentNode.replaceChild(newListBoxNode, listbox);
|
||||
}
|
||||
}
|
||||
|
||||
// Is this directory read-only? If so, we now need to set all the fields to
|
||||
// read-only.
|
||||
if (gEditList.readOnly) {
|
||||
const kMailListFields = [ 'ListName', 'ListNickName', 'ListDescription' ];
|
||||
|
||||
for (let i = 0; i < kMailListFields.length; ++i)
|
||||
document.getElementById(kMailListFields[i]).readOnly = true;
|
||||
|
||||
document.documentElement.buttons = "accept";
|
||||
document.documentElement.removeAttribute("ondialogaccept");
|
||||
|
||||
// Getting a sane read-only implementation for the addressing widget would
|
||||
// basically need a separate dialog. Given I'm not sure about the future of
|
||||
// the mailing list dialog in its current state, let's just disable it
|
||||
// completely.
|
||||
document.getElementById("addressingWidget").disabled = true;
|
||||
}
|
||||
|
||||
document.addEventListener("keypress", awDocumentKeyPress, true);
|
||||
|
||||
// workaround for bug 118337 - for mailing lists that have more rows than fits inside
|
||||
// the display, the value of the textbox inside the new row isn't inherited into the input -
|
||||
// the first row then appears to be duplicated at the end although it is actually empty.
|
||||
// see awAppendNewRow which copies first row and clears it
|
||||
setTimeout(AppendLastRow, 0);
|
||||
NotifyLoadListeners(gEditList);
|
||||
}
|
||||
|
||||
function AppendLastRow()
|
||||
{
|
||||
AppendNewRowAndSetFocus();
|
||||
awFitDummyRows(1);
|
||||
|
||||
// focus on first name
|
||||
var listName = document.getElementById('ListName');
|
||||
if (listName)
|
||||
listName.focus();
|
||||
}
|
||||
|
||||
function AppendNewRowAndSetFocus()
|
||||
{
|
||||
var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
|
||||
if (lastInput && lastInput.value)
|
||||
awAppendNewRow(true);
|
||||
else
|
||||
awSetFocus(top.MAX_RECIPIENTS, lastInput);
|
||||
}
|
||||
|
||||
function SetInputValue(inputValue, parentNode, templateNode)
|
||||
{
|
||||
top.MAX_RECIPIENTS++;
|
||||
|
||||
var newNode = templateNode.cloneNode(true);
|
||||
parentNode.appendChild(newNode); // we need to insert the new node before we set the value of the select element!
|
||||
|
||||
var input = newNode.getElementsByTagName(awInputElementName());
|
||||
if (input && input.length == 1)
|
||||
{
|
||||
//We need to set the value using both setAttribute and .value else we will
|
||||
// lose the content when the field is not visible. See bug 37435
|
||||
input[0].setAttribute("value", inputValue);
|
||||
input[0].value = inputValue;
|
||||
input[0].setAttribute("id", "addressCol1#" + top.MAX_RECIPIENTS);
|
||||
}
|
||||
}
|
||||
|
||||
function awNotAnEmptyArea(event)
|
||||
{
|
||||
//This is temporary until i figure out how to ensure to always having an empty space after the last row
|
||||
|
||||
var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
|
||||
if (lastInput && lastInput.value)
|
||||
awAppendNewRow(false);
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
function awClickEmptySpace(target, setFocus)
|
||||
{
|
||||
if (target == null ||
|
||||
(target.localName != "listboxbody" &&
|
||||
target.localName != "listcell" &&
|
||||
target.localName != "listitem"))
|
||||
return;
|
||||
|
||||
var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
|
||||
|
||||
if (lastInput && lastInput.value)
|
||||
awAppendNewRow(setFocus);
|
||||
else
|
||||
if (setFocus)
|
||||
awSetFocus(top.MAX_RECIPIENTS, lastInput);
|
||||
}
|
||||
|
||||
function awReturnHit(inputElement)
|
||||
{
|
||||
var row = awGetRowByInputElement(inputElement);
|
||||
if (inputElement.value)
|
||||
{
|
||||
var nextInput = awGetInputElement(row+1);
|
||||
if (!nextInput)
|
||||
awAppendNewRow(true);
|
||||
else
|
||||
awSetFocus(row+1, nextInput);
|
||||
}
|
||||
}
|
||||
|
||||
function awDeleteRow(rowToDelete)
|
||||
{
|
||||
/* When we delete a row, we must reset the id of others row in order to not break the sequence */
|
||||
var maxRecipients = top.MAX_RECIPIENTS;
|
||||
awRemoveRow(rowToDelete);
|
||||
|
||||
var numberOfCols = awGetNumberOfCols();
|
||||
for (var row = rowToDelete + 1; row <= maxRecipients; row ++)
|
||||
for (var col = 1; col <= numberOfCols; col++)
|
||||
awGetElementByCol(row, col).setAttribute("id", "addressCol" + (col) + "#" + (row-1));
|
||||
|
||||
awTestRowSequence();
|
||||
}
|
||||
|
||||
function awInputChanged(inputElement)
|
||||
{
|
||||
// AutoCompleteAddress(inputElement);
|
||||
|
||||
//Do we need to add a new row?
|
||||
var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
|
||||
if (lastInput && lastInput.value && !top.doNotCreateANewRow)
|
||||
awAppendNewRow(false);
|
||||
top.doNotCreateANewRow = false;
|
||||
}
|
||||
|
||||
function awInputElementName()
|
||||
{
|
||||
if (inputElementType == "")
|
||||
inputElementType = document.getElementById("addressCol1#1").localName;
|
||||
return inputElementType;
|
||||
}
|
||||
|
||||
function awAppendNewRow(setFocus)
|
||||
{
|
||||
var body = document.getElementById("addressingWidget");
|
||||
var listitem1 = awGetListItem(1);
|
||||
|
||||
if (body && listitem1)
|
||||
{
|
||||
var nextDummy = awGetNextDummyRow();
|
||||
var newNode = listitem1.cloneNode(true);
|
||||
if (nextDummy)
|
||||
body.replaceChild(newNode, nextDummy);
|
||||
else
|
||||
body.appendChild(newNode);
|
||||
|
||||
top.MAX_RECIPIENTS++;
|
||||
|
||||
var input = newNode.getElementsByTagName(awInputElementName());
|
||||
if (input && input.length == 1)
|
||||
{
|
||||
input[0].setAttribute("value", "");
|
||||
input[0].setAttribute("id", "addressCol1#" + top.MAX_RECIPIENTS);
|
||||
|
||||
if (input[0].getAttribute('focused') != '')
|
||||
input[0].removeAttribute('focused');
|
||||
}
|
||||
// focus on new input widget
|
||||
if (setFocus && input )
|
||||
awSetFocus(top.MAX_RECIPIENTS, input[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// functions for accessing the elements in the addressing widget
|
||||
|
||||
function awGetInputElement(row)
|
||||
{
|
||||
return document.getElementById("addressCol1#" + row);
|
||||
}
|
||||
|
||||
|
||||
function _awSetFocus()
|
||||
{
|
||||
var listbox = document.getElementById('addressingWidget');
|
||||
try
|
||||
{
|
||||
var theNewRow = awGetListItem(top.awRow);
|
||||
|
||||
listbox.ensureElementIsVisible(theNewRow);
|
||||
top.awInputElement.focus();
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
top.awFocusRetry ++;
|
||||
if (top.awFocusRetry < 8)
|
||||
{
|
||||
dump("_awSetFocus failed, try it again...\n");
|
||||
setTimeout(_awSetFocus, 0);
|
||||
}
|
||||
else
|
||||
dump("_awSetFocus failed, forget about it!\n");
|
||||
}
|
||||
}
|
||||
|
||||
function awTabFromRecipient(element, event)
|
||||
{
|
||||
//If we are the last element in the listbox, we don't want to create a new row.
|
||||
if (element == awGetInputElement(top.MAX_RECIPIENTS))
|
||||
top.doNotCreateANewRow = true;
|
||||
}
|
||||
|
||||
function DragOverAddressListTree(event)
|
||||
{
|
||||
var validFlavor = false;
|
||||
var dragSession = gDragService.getCurrentSession();
|
||||
|
||||
// XXX add support for other flavors here
|
||||
if (dragSession.isDataFlavorSupported("text/x-moz-address")) {
|
||||
dragSession.canDrop = true;
|
||||
}
|
||||
}
|
||||
|
||||
function DropOnAddressListTree(event)
|
||||
{
|
||||
let dragSession = gDragService.getCurrentSession();
|
||||
let trans;
|
||||
|
||||
try {
|
||||
trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
trans.addDataFlavor("text/x-moz-address");
|
||||
}
|
||||
catch (ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < dragSession.numDropItems; ++i)
|
||||
{
|
||||
dragSession.getData(trans, i);
|
||||
let dataObj = new Object();
|
||||
let bestFlavor = new Object();
|
||||
let len = new Object();
|
||||
trans.getAnyTransferData(bestFlavor, dataObj, len);
|
||||
if (dataObj)
|
||||
dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString);
|
||||
if (!dataObj)
|
||||
continue;
|
||||
|
||||
// pull the URL out of the data object
|
||||
let address = dataObj.data.substring(0, len.value);
|
||||
if (!address)
|
||||
continue;
|
||||
|
||||
DropListAddress(event.target, address);
|
||||
}
|
||||
}
|
||||
|
||||
function DropListAddress(target, address)
|
||||
{
|
||||
// Set focus on a new available, visible row.
|
||||
awClickEmptySpace(target, true);
|
||||
if (top.MAX_RECIPIENTS == 0)
|
||||
top.MAX_RECIPIENTS = 1;
|
||||
|
||||
// Break apart the MIME-ready header address into individual addressees to
|
||||
// add to the dialog.
|
||||
let addresses = {}, names = {}, fullNames = {};
|
||||
MailServices.headerParser.parseHeadersWithArray(address, addresses, names,
|
||||
fullNames);
|
||||
for (let full of fullNames.value)
|
||||
{
|
||||
let lastInput = awGetInputElement(top.MAX_RECIPIENTS);
|
||||
lastInput.value = full;
|
||||
awAppendNewRow(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allows extensions to register a listener function for
|
||||
* when a mailing list is loaded. The listener function
|
||||
* should take two parameters - the first being the
|
||||
* mailing list being loaded, the second one being the
|
||||
* current window document.
|
||||
*/
|
||||
function RegisterLoadListener(aListener)
|
||||
{
|
||||
gLoadListeners.push(aListener);
|
||||
}
|
||||
|
||||
/* Allows extensions to unload a load listener function.
|
||||
*/
|
||||
function UnregisterLoadListener(aListener)
|
||||
{
|
||||
var fIndex = gLoadListeners.indexOf(aListener);
|
||||
if (fIndex != -1)
|
||||
gLoadListeners.splice(fIndex, 1);
|
||||
}
|
||||
|
||||
/* Allows extensions to register a listener function for
|
||||
* when a mailing list is saved. Like a load listener,
|
||||
* the save listener should take two parameters: the first
|
||||
* being a copy of the mailing list that is being saved,
|
||||
* and the second being the current window document.
|
||||
*/
|
||||
function RegisterSaveListener(aListener)
|
||||
{
|
||||
gSaveListeners.push(aListener);
|
||||
}
|
||||
|
||||
/* Allows extensions to unload a save listener function.
|
||||
*/
|
||||
function UnregisterSaveListener(aListener)
|
||||
{
|
||||
var fIndex = gSaveListeners.indexOf(aListener);
|
||||
if (fIndex != -1)
|
||||
gSaveListeners.splice(fIndex, 1);
|
||||
}
|
||||
|
||||
/* Notifies all load listeners.
|
||||
*/
|
||||
function NotifyLoadListeners(aMailingList)
|
||||
{
|
||||
for (let i = 0; i < gLoadListeners.length; i++)
|
||||
gLoadListeners[i](aMailingList, document);
|
||||
}
|
||||
|
||||
/* Notifies all save listeners.
|
||||
*/
|
||||
function NotifySaveListeners(aMailingList)
|
||||
{
|
||||
for (let i = 0; i < gSaveListeners.length; i++)
|
||||
gSaveListeners[i](aMailingList, document);
|
||||
}
|
||||
|
||||
33
mailnews/addrbook/content/abNewCardDialog.xul
Normal file
33
mailnews/addrbook/content/abNewCardDialog.xul
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://messenger/content/addressbook/abCardOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abNewCardDialog.dtd">
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="abcardWindow"
|
||||
onload="OnLoadNewCard()"
|
||||
ondialogaccept="return NewCardOKButton();">
|
||||
|
||||
<stringbundleset id="stringbundleset"/>
|
||||
|
||||
<hbox align="center">
|
||||
|
||||
<label id="abPopupLabel" control="abPopup" value="&chooseAddressBook.label;" accesskey="&chooseAddressBook.accesskey;"/>
|
||||
|
||||
<menulist id="abPopup">
|
||||
<menupopup id="abPopup-menupopup" class="addrbooksPopup" writable="true"/>
|
||||
</menulist>
|
||||
|
||||
</hbox>
|
||||
|
||||
<spacer style="height:1em"/>
|
||||
|
||||
<vbox id="editcard"/>
|
||||
|
||||
</dialog>
|
||||
502
mailnews/addrbook/content/abResultsPane.js
Normal file
502
mailnews/addrbook/content/abResultsPane.js
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Use of items in this file require:
|
||||
*
|
||||
* getSelectedDirectoryURI()
|
||||
* returns the URI of the selected directory
|
||||
* AbResultsPaneDoubleClick(card)
|
||||
* Is called when the results pane is double-clicked, with the clicked card.
|
||||
* AbEditCard(card)
|
||||
* Is called when a card is to be edited, with the card as the parameter.
|
||||
*
|
||||
* The following function is only required if ResultsPaneController is used:
|
||||
*
|
||||
* goSetMenuValue()
|
||||
* Core function in globalOverlay.js
|
||||
*/
|
||||
|
||||
// List/card selections in the results pane.
|
||||
var kNothingSelected = 0;
|
||||
var kListsAndCards = 1;
|
||||
var kMultipleListsOnly = 2;
|
||||
var kSingleListOnly = 3;
|
||||
var kCardsOnly = 4;
|
||||
|
||||
// Global Variables
|
||||
|
||||
// gAbView holds an object with an nsIAbView interface
|
||||
var gAbView = null;
|
||||
// Holds a reference to the "abResultsTree" document element. Initially
|
||||
// set up by SetAbView.
|
||||
var gAbResultsTree = null;
|
||||
|
||||
function SetAbView(aURI)
|
||||
{
|
||||
// If we don't have a URI, just clear the view and leave everything else
|
||||
// alone.
|
||||
if (!aURI) {
|
||||
gAbView.clearView();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we do have a URI, we want to allow updating the review even if the
|
||||
// URI is the same, as the search results may be different.
|
||||
|
||||
var sortColumn = kDefaultSortColumn;
|
||||
var sortDirection = kDefaultAscending;
|
||||
|
||||
if (!gAbResultsTree) {
|
||||
gAbResultsTree = document.getElementById("abResultsTree");
|
||||
gAbResultsTree.controllers.appendController(ResultsPaneController);
|
||||
}
|
||||
|
||||
if (gAbView) {
|
||||
sortColumn = gAbView.sortColumn;
|
||||
sortDirection = gAbView.sortDirection;
|
||||
}
|
||||
else {
|
||||
if (gAbResultsTree.hasAttribute("sortCol"))
|
||||
sortColumn = gAbResultsTree.getAttribute("sortCol");
|
||||
var sortColumnNode = document.getElementById(sortColumn);
|
||||
if (sortColumnNode && sortColumnNode.hasAttribute("sortDirection"))
|
||||
sortDirection = sortColumnNode.getAttribute("sortDirection");
|
||||
}
|
||||
|
||||
var directory = GetDirectoryFromURI(aURI);
|
||||
|
||||
if (!gAbView)
|
||||
gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
|
||||
.createInstance(Components.interfaces.nsIAbView);
|
||||
|
||||
var actualSortColumn = gAbView.setView(directory, GetAbViewListener(),
|
||||
sortColumn, sortDirection);
|
||||
|
||||
gAbResultsTree.treeBoxObject.view =
|
||||
gAbView.QueryInterface(Components.interfaces.nsITreeView);
|
||||
|
||||
UpdateSortIndicators(actualSortColumn, sortDirection);
|
||||
|
||||
// If the selected address book is LDAP and the search box is empty,
|
||||
// inform the user of the empty results pane.
|
||||
let abResultsTree = document.getElementById("abResultsTree");
|
||||
let cardViewOuterBox = document.getElementById("CardViewOuterBox");
|
||||
let blankResultsPaneMessageBox = document.getElementById("blankResultsPaneMessageBox");
|
||||
if (aURI.startsWith("moz-abldapdirectory://") && !aURI.includes("?")) {
|
||||
if (abResultsTree)
|
||||
abResultsTree.hidden = true;
|
||||
if (cardViewOuterBox)
|
||||
cardViewOuterBox.hidden = true;
|
||||
if (blankResultsPaneMessageBox)
|
||||
blankResultsPaneMessageBox.hidden = false;
|
||||
} else {
|
||||
if (abResultsTree)
|
||||
abResultsTree.hidden = false;
|
||||
if (cardViewOuterBox)
|
||||
cardViewOuterBox.hidden = false;
|
||||
if (blankResultsPaneMessageBox)
|
||||
blankResultsPaneMessageBox.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
function CloseAbView()
|
||||
{
|
||||
if (gAbView)
|
||||
gAbView.clearView();
|
||||
}
|
||||
|
||||
function GetOneOrMoreCardsSelected()
|
||||
{
|
||||
return (gAbView && (gAbView.selection.getRangeCount() > 0));
|
||||
}
|
||||
|
||||
function GetSelectedAddresses()
|
||||
{
|
||||
return GetAddressesForCards(GetSelectedAbCards());
|
||||
}
|
||||
|
||||
function GetNumSelectedCards()
|
||||
{
|
||||
try {
|
||||
return gAbView.selection.count;
|
||||
}
|
||||
catch (ex) {
|
||||
}
|
||||
|
||||
// if something went wrong, return 0 for the count.
|
||||
return 0;
|
||||
}
|
||||
|
||||
function GetSelectedCardTypes()
|
||||
{
|
||||
var cards = GetSelectedAbCards();
|
||||
if (!cards) {
|
||||
Components.utils.reportError("ERROR: GetSelectedCardTypes: |cards| is null.");
|
||||
return kNothingSelected; // no view
|
||||
}
|
||||
var count = cards.length;
|
||||
if (count == 0)
|
||||
return kNothingSelected; // nothing selected
|
||||
|
||||
var mailingListCnt = 0;
|
||||
var cardCnt = 0;
|
||||
for (let i = 0; i < count; i++) {
|
||||
// We can assume no values from GetSelectedAbCards will be null.
|
||||
if (cards[i].isMailList)
|
||||
mailingListCnt++;
|
||||
else
|
||||
cardCnt++;
|
||||
}
|
||||
|
||||
return (mailingListCnt == 0) ? kCardsOnly :
|
||||
(cardCnt > 0) ? kListsAndCards :
|
||||
(mailingListCnt == 1) ? kSingleListOnly :
|
||||
kMultipleListsOnly;
|
||||
}
|
||||
|
||||
// NOTE, will return -1 if more than one card selected, or no cards selected.
|
||||
function GetSelectedCardIndex()
|
||||
{
|
||||
if (!gAbView)
|
||||
return -1;
|
||||
|
||||
var treeSelection = gAbView.selection;
|
||||
if (treeSelection.getRangeCount() == 1) {
|
||||
var start = new Object;
|
||||
var end = new Object;
|
||||
treeSelection.getRangeAt(0, start, end);
|
||||
if (start.value == end.value)
|
||||
return start.value;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE, returns the card if exactly one card is selected, null otherwise
|
||||
function GetSelectedCard()
|
||||
{
|
||||
var index = GetSelectedCardIndex();
|
||||
return (index == -1) ? null : gAbView.getCardFromRow(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a (possibly empty) list of cards
|
||||
*
|
||||
* It pushes only non-null/empty element, if any, into the returned list.
|
||||
*/
|
||||
function GetSelectedAbCards()
|
||||
{
|
||||
var abView = gAbView;
|
||||
|
||||
// if sidebar is open, and addressbook panel is open and focused,
|
||||
// then use the ab view from sidebar (gCurFrame is from sidebarOverlay.js)
|
||||
if (document.getElementById("sidebar-box")) {
|
||||
const abPanelUrl =
|
||||
"chrome://messenger/content/addressbook/addressbook-panel.xul";
|
||||
if (gCurFrame &&
|
||||
gCurFrame.getAttribute("src") == abPanelUrl &&
|
||||
document.commandDispatcher.focusedWindow == gCurFrame.contentDocument.defaultView)
|
||||
abView = gCurFrame.contentDocument.defaultView.gAbView;
|
||||
}
|
||||
|
||||
if (!abView)
|
||||
return [];
|
||||
|
||||
let cards = [];
|
||||
var count = abView.selection.getRangeCount();
|
||||
var current = 0;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
let start = {};
|
||||
let end = {};
|
||||
|
||||
abView.selection.getRangeAt(i, start, end);
|
||||
|
||||
for (let j = start.value; j <= end.value; ++j) {
|
||||
// avoid inserting null element into the list. GetRangeAt() may be buggy.
|
||||
let tmp = abView.getCardFromRow(j);
|
||||
if (tmp) {
|
||||
cards.push(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
|
||||
// XXX todo
|
||||
// an optimization might be to make this return
|
||||
// the selected ranges, which would be faster
|
||||
// when the user does large selections, but for now, let's keep it simple.
|
||||
function GetSelectedRows()
|
||||
{
|
||||
var selectedRows = "";
|
||||
|
||||
if (!gAbView)
|
||||
return selectedRows;
|
||||
|
||||
var rangeCount = gAbView.selection.getRangeCount();
|
||||
for (let i = 0; i < rangeCount; ++i) {
|
||||
var start = new Object;
|
||||
var end = new Object;
|
||||
gAbView.selection.getRangeAt(i, start, end);
|
||||
for (let j = start.value;j <= end.value; ++j) {
|
||||
if (selectedRows)
|
||||
selectedRows += ",";
|
||||
selectedRows += j;
|
||||
}
|
||||
}
|
||||
|
||||
return selectedRows;
|
||||
}
|
||||
|
||||
function AbSwapFirstNameLastName()
|
||||
{
|
||||
if (gAbView)
|
||||
gAbView.swapFirstNameLastName();
|
||||
}
|
||||
|
||||
function AbEditSelectedCard()
|
||||
{
|
||||
AbEditCard(GetSelectedCard());
|
||||
}
|
||||
|
||||
function AbResultsPaneOnClick(event)
|
||||
{
|
||||
// we only care about button 0 (left click) events
|
||||
if (event.button != 0) return;
|
||||
|
||||
// all we need to worry about here is double clicks
|
||||
// and column header clicks.
|
||||
//
|
||||
// we get in here for clicks on the "treecol" (headers)
|
||||
// and the "scrollbarbutton" (scrollbar buttons)
|
||||
// we don't want those events to cause a "double click"
|
||||
|
||||
var t = event.originalTarget;
|
||||
|
||||
if (t.localName == "treecol") {
|
||||
var sortDirection;
|
||||
var currentDirection = t.getAttribute("sortDirection");
|
||||
|
||||
// Revert the sort order. If none is set, use Ascending.
|
||||
sortDirection = currentDirection == kDefaultAscending ?
|
||||
kDefaultDescending : kDefaultAscending;
|
||||
|
||||
SortAndUpdateIndicators(t.id, sortDirection);
|
||||
}
|
||||
else if (t.localName == "treechildren") {
|
||||
// figure out what row the click was in
|
||||
var row = gAbResultsTree.treeBoxObject.getRowAt(event.clientX,
|
||||
event.clientY);
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
if (event.detail == 2)
|
||||
AbResultsPaneDoubleClick(gAbView.getCardFromRow(row));
|
||||
}
|
||||
}
|
||||
|
||||
function AbSortAscending()
|
||||
{
|
||||
var sortColumn = gAbResultsTree.getAttribute("sortCol");
|
||||
SortAndUpdateIndicators(sortColumn, kDefaultAscending);
|
||||
}
|
||||
|
||||
function AbSortDescending()
|
||||
{
|
||||
var sortColumn = gAbResultsTree.getAttribute("sortCol");
|
||||
SortAndUpdateIndicators(sortColumn, kDefaultDescending);
|
||||
}
|
||||
|
||||
function SortResultPane(sortColumn)
|
||||
{
|
||||
var sortDirection = kDefaultAscending;
|
||||
if (gAbView)
|
||||
sortDirection = gAbView.sortDirection;
|
||||
|
||||
SortAndUpdateIndicators(sortColumn, sortDirection);
|
||||
}
|
||||
|
||||
function SortAndUpdateIndicators(sortColumn, sortDirection)
|
||||
{
|
||||
UpdateSortIndicators(sortColumn, sortDirection);
|
||||
|
||||
if (gAbView)
|
||||
gAbView.sortBy(sortColumn, sortDirection);
|
||||
}
|
||||
|
||||
function UpdateSortIndicators(colID, sortDirection)
|
||||
{
|
||||
var sortedColumn = null;
|
||||
|
||||
// set the sort indicator on the column we are sorted by
|
||||
if (colID) {
|
||||
sortedColumn = document.getElementById(colID);
|
||||
if (sortedColumn) {
|
||||
sortedColumn.setAttribute("sortDirection",sortDirection);
|
||||
gAbResultsTree.setAttribute("sortCol", colID);
|
||||
}
|
||||
}
|
||||
|
||||
// remove the sort indicator from all the columns
|
||||
// except the one we are sorted by
|
||||
var currCol = gAbResultsTree.firstChild.firstChild;
|
||||
while (currCol) {
|
||||
if (currCol != sortedColumn && currCol.localName == "treecol")
|
||||
currCol.removeAttribute("sortDirection");
|
||||
currCol = currCol.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
function InvalidateResultsPane()
|
||||
{
|
||||
if (gAbResultsTree)
|
||||
gAbResultsTree.treeBoxObject.invalidate();
|
||||
}
|
||||
|
||||
// Controller object for Results Pane
|
||||
var ResultsPaneController =
|
||||
{
|
||||
supportsCommand: function(command)
|
||||
{
|
||||
switch (command) {
|
||||
case "cmd_selectAll":
|
||||
case "cmd_delete":
|
||||
case "button_delete":
|
||||
case "cmd_properties":
|
||||
case "cmd_newlist":
|
||||
case "cmd_newCard":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
isCommandEnabled: function(command)
|
||||
{
|
||||
switch (command) {
|
||||
case "cmd_selectAll":
|
||||
return true;
|
||||
case "cmd_delete":
|
||||
case "button_delete":
|
||||
var numSelected;
|
||||
var enabled = false;
|
||||
if (gAbView && gAbView.selection) {
|
||||
if (gAbView.directory)
|
||||
enabled = !gAbView.directory.readOnly;
|
||||
numSelected = gAbView.selection.count;
|
||||
}
|
||||
else
|
||||
numSelected = 0;
|
||||
|
||||
// fix me, don't update on isCommandEnabled
|
||||
if (command == "cmd_delete") {
|
||||
switch (GetSelectedCardTypes()) {
|
||||
case kSingleListOnly:
|
||||
goSetMenuValue(command, "valueList");
|
||||
break;
|
||||
case kMultipleListsOnly:
|
||||
goSetMenuValue(command, "valueLists");
|
||||
break;
|
||||
case kListsAndCards:
|
||||
goSetMenuValue(command, "valueItems");
|
||||
break;
|
||||
case kCardsOnly:
|
||||
default:
|
||||
if (numSelected < 2)
|
||||
goSetMenuValue(command, "valueCard");
|
||||
else
|
||||
goSetMenuValue(command, "valueCards");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (enabled && (numSelected > 0));
|
||||
case "cmd_properties":
|
||||
// Temporary fix for SeaMonkey (see bug 1318852).
|
||||
// goSetLabelAccesskeyTooltiptext() is only defined in mail/.
|
||||
// This will be removed in due course and therefore the
|
||||
// block wasn't indented.
|
||||
if (typeof goSetLabelAccesskeyTooltiptext == "function") {
|
||||
let labelAttr = "valueGeneric";
|
||||
let accKeyAttr = "valueGenericAccessKey";
|
||||
let tooltipTextAttr = "valueGenericTooltipText";
|
||||
switch (GetSelectedCardTypes()) {
|
||||
// Set cmd_properties UI according to the type of the selected item(s),
|
||||
// even with multiple selections for which cmd_properties is
|
||||
// not yet available and hence disabled.
|
||||
case kMultipleListsOnly:
|
||||
case kSingleListOnly:
|
||||
labelAttr = "valueMailingList";
|
||||
accKeyAttr = "valueMailingListAccessKey";
|
||||
tooltipTextAttr = "valueMailingListTooltipText";
|
||||
break;
|
||||
case kCardsOnly:
|
||||
labelAttr = "valueContact";
|
||||
accKeyAttr = "valueContactAccessKey";
|
||||
tooltipTextAttr = "valueContactTooltipText";
|
||||
break;
|
||||
case kListsAndCards:
|
||||
default:
|
||||
//use generic set of attributes declared above
|
||||
break;
|
||||
}
|
||||
// This code is shared between main AB and composition's contacts sidebar.
|
||||
// Note that in composition, there's no cmd_properties-button (yet);
|
||||
// the resulting dump() should be ignored.
|
||||
goSetLabelAccesskeyTooltiptext("cmd_properties-button", null, null,
|
||||
tooltipTextAttr);
|
||||
goSetLabelAccesskeyTooltiptext("cmd_properties-contextMenu",
|
||||
labelAttr, accKeyAttr);
|
||||
goSetLabelAccesskeyTooltiptext("cmd_properties-menu",
|
||||
labelAttr, accKeyAttr);
|
||||
}
|
||||
// While "Edit Contact" dialogue is still modal (bug 115904, bug 135126),
|
||||
// only enable "Properties" button for single selection; then fix bug 119999.
|
||||
return (GetNumSelectedCards() == 1);
|
||||
case "cmd_newlist":
|
||||
case "cmd_newCard":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
doCommand: function(command)
|
||||
{
|
||||
switch (command) {
|
||||
case "cmd_selectAll":
|
||||
if (gAbView)
|
||||
gAbView.selectAll();
|
||||
break;
|
||||
case "cmd_delete":
|
||||
case "button_delete":
|
||||
AbDelete();
|
||||
break;
|
||||
case "cmd_properties":
|
||||
AbEditSelectedCard();
|
||||
break;
|
||||
case "cmd_newlist":
|
||||
AbNewList();
|
||||
break;
|
||||
case "cmd_newCard":
|
||||
AbNewCard();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onEvent: function(event)
|
||||
{
|
||||
// on blur events set the menu item texts back to the normal values
|
||||
if (event == "blur")
|
||||
goSetMenuValue("cmd_delete", "valueDefault");
|
||||
}
|
||||
};
|
||||
|
||||
function SelectFirstCard()
|
||||
{
|
||||
if (gAbView && gAbView.selection && (gAbView.selection.count > 0))
|
||||
gAbView.selection.select(0);
|
||||
}
|
||||
90
mailnews/addrbook/content/abResultsPaneOverlay.xul
Normal file
90
mailnews/addrbook/content/abResultsPaneOverlay.xul
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/addressbook/abResultsPane.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/addressbook/abResultsPaneOverlay.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/addressbook/abResultsPane.js"/>
|
||||
<script type="application/javascript" src="chrome://global/content/nsDragAndDrop.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/addressbook/abDragDrop.js"/>
|
||||
|
||||
<tree id="abResultsTree" flex="1" enableColumnDrag="true" class="plain focusring"
|
||||
onclick="AbResultsPaneOnClick(event);"
|
||||
onselect="this.view.selectionChanged(); document.commandDispatcher.updateCommands('addrbook-select');"
|
||||
sortCol="GeneratedName"
|
||||
persist="sortCol height">
|
||||
|
||||
<treecols id="abResultsTreeCols">
|
||||
<!-- these column ids must match up to the mork column names, except for GeneratedName, see nsIAddrDatabase.idl -->
|
||||
<treecol id="GeneratedName"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&GeneratedName.label;" primary="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="PrimaryEmail"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&PrimaryEmail.label;"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="_AimScreenName"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&ScreenName.label;"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="Company"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&Company.label;"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="NickName"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&NickName.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="SecondEmail"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&SecondEmail.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="Department"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&Department.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="JobTitle"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&JobTitle.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="CellularNumber"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&CellularNumber.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="PagerNumber"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&PagerNumber.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="FaxNumber"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&FaxNumber.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="HomePhone"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&HomePhone.label;" hidden="true"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="WorkPhone"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&WorkPhone.label;"/>
|
||||
|
||||
<!-- LOCALIZATION NOTE: _PhoneticName may be enabled for Japanese builds. -->
|
||||
<!--
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="_PhoneticName"
|
||||
persist="hidden ordinal width sortDirection" flex="1"
|
||||
label="&_PhoneticName.label;" hidden="true"/>
|
||||
-->
|
||||
|
||||
</treecols>
|
||||
<treechildren ondragstart="nsDragAndDrop.startDrag(event, abResultsPaneObserver);"/>
|
||||
</tree>
|
||||
|
||||
</overlay>
|
||||
|
||||
439
mailnews/addrbook/content/addrbookWidgets.xml
Normal file
439
mailnews/addrbook/content/addrbookWidgets.xml
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<bindings id="addrbookBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="addrbooks-menupopup"
|
||||
extends="chrome://global/content/bindings/popup.xml#popup">
|
||||
<implementation implements="nsIAbListener">
|
||||
<!-- A cache of nsIAbDirectory objects. -->
|
||||
<field name="_directories">[]</field>
|
||||
|
||||
<!-- Represents the nsIAbDirectory attribute used as the value of the
|
||||
parent menulist. Defaults to URI but can be e.g. dirPrefId -->
|
||||
<field name="_value">this.getAttribute("value") || "URI"</field>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
// Init the address book cache.
|
||||
const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
|
||||
let directories = MailServices.ab.directories;
|
||||
while (directories && directories.hasMoreElements()) {
|
||||
var ab = directories.getNext();
|
||||
if (ab instanceof nsIAbDirectory && this._matches(ab))
|
||||
this._directories.push(ab);
|
||||
}
|
||||
|
||||
this._directories.sort(this._compare);
|
||||
|
||||
// Now create menuitems for all displayed directories.
|
||||
var menulist = this.parentNode;
|
||||
var value = this._value;
|
||||
this._directories.forEach(function (ab) {
|
||||
menulist.appendItem(ab.dirName, ab[value]);
|
||||
});
|
||||
if (this.hasAttribute("none")) {
|
||||
// Create a dummy menuitem representing no selection.
|
||||
this._directories.unshift(null);
|
||||
menulist.insertItemAt(0, this.getAttribute("none"), "");
|
||||
}
|
||||
|
||||
// Attempt to select the persisted or otherwise first directory.
|
||||
menulist.value = menulist.value;
|
||||
if (!menulist.selectedItem && this.hasChildNodes())
|
||||
menulist.selectedIndex = 0;
|
||||
|
||||
const nsIAbListener = Components.interfaces.nsIAbListener;
|
||||
// Add a listener so we can update correctly if the list should change
|
||||
MailServices.ab.addAddressBookListener(this,
|
||||
nsIAbListener.itemAdded |
|
||||
nsIAbListener.directoryRemoved |
|
||||
nsIAbListener.itemChanged);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
MailServices.ab.removeAddressBookListener(this);
|
||||
|
||||
// Empty out anything in the list.
|
||||
while (this.hasChildNodes())
|
||||
this.lastChild.remove();
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<!-- nsIAbListener methods -->
|
||||
<method name="onItemAdded">
|
||||
<parameter name="aParentDir"/>
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
// Are we interested in this new directory?
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList && this._matches(aItem)) {
|
||||
this._directories.push(aItem);
|
||||
this._directories.sort(this._compare);
|
||||
// Insert the new menuitem at the position to which it was sorted.
|
||||
this.parentNode.insertItemAt(this._directories.indexOf(aItem),
|
||||
aItem.dirName, aItem[this._value]);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="onItemRemoved">
|
||||
<parameter name="aParentDir"/>
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList) {
|
||||
// Find the item in the list to remove
|
||||
// We can't use indexOf here because we need loose equality
|
||||
for (var index = this._directories.length; --index >= 0; )
|
||||
if (this._directories[index] == aItem)
|
||||
break;
|
||||
if (index != -1)
|
||||
// Are we removing the selected directory?
|
||||
if (this.parentNode.selectedItem ==
|
||||
this.removeChild(this.childNodes[index]))
|
||||
// If so, try to select the first directory, if available.
|
||||
if (this.hasChildNodes())
|
||||
this.firstChild.doCommand();
|
||||
else
|
||||
this.parentNode.selectedItem = null;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="onItemPropertyChanged">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aProperty"/>
|
||||
<parameter name="aOldValue"/>
|
||||
<parameter name="aNewValue"/>
|
||||
<body><![CDATA[
|
||||
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
|
||||
!aItem.isMailList) {
|
||||
// Find the item in the list to rename.
|
||||
// We can't use indexOf here because we need loose equality
|
||||
for (var oldIndex = this._directories.length; --oldIndex >= 0; )
|
||||
if (this._directories[oldIndex] == aItem)
|
||||
break;
|
||||
if (oldIndex != -1) {
|
||||
// Cache the matching item so that we can use indexOf next time.
|
||||
aItem = this._directories[oldIndex];
|
||||
var child = this.childNodes[oldIndex];
|
||||
child.label = aItem.dirName;
|
||||
this._directories.sort(this._compare);
|
||||
// Reorder the menuitems if renaming changed the directory index.
|
||||
var newIndex = this._directories.indexOf(aItem);
|
||||
if (newIndex < oldIndex)
|
||||
this.insertBefore(child, this.childNodes[newIndex]);
|
||||
else if (newIndex > oldIndex)
|
||||
this.insertBefore(child, this.childNodes[newIndex].nextSibling);
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Private methods -->
|
||||
<!-- Tests to see whether this directory should display in the list. -->
|
||||
<method name="_matches">
|
||||
<parameter name="ab"/>
|
||||
<body><![CDATA[
|
||||
// This condition is used for instance when creating cards
|
||||
if (this.getAttribute("writable") == "true" && ab.readOnly)
|
||||
return false;
|
||||
|
||||
// This condition is used for instance when creating mailing lists
|
||||
if (this.getAttribute("supportsmaillists") == "true" &&
|
||||
!ab.supportsMailingLists)
|
||||
return false;
|
||||
|
||||
return this.getAttribute(ab.isRemote ? "localonly" : "remoteonly") != "true";
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Used to sort directories in order -->
|
||||
<method name="_compare">
|
||||
<parameter name="a"/>
|
||||
<parameter name="b"/>
|
||||
<body><![CDATA[
|
||||
// Null at the very top.
|
||||
if (!a)
|
||||
return -1;
|
||||
|
||||
if (!b)
|
||||
return 1;
|
||||
|
||||
// Personal at the top.
|
||||
const kPersonalAddressbookURI = "moz-abmdbdirectory://abook.mab";
|
||||
if (a.URI == kPersonalAddressbookURI)
|
||||
return -1;
|
||||
|
||||
if (b.URI == kPersonalAddressbookURI)
|
||||
return 1;
|
||||
|
||||
// Collected at the bottom.
|
||||
const kCollectedAddressbookURI = "moz-abmdbdirectory://history.mab";
|
||||
if (a.URI == kCollectedAddressbookURI)
|
||||
return 1;
|
||||
|
||||
if (b.URI == kCollectedAddressbookURI)
|
||||
return -1;
|
||||
|
||||
// Sort books of the same type by name.
|
||||
if (a.dirType == b.dirType)
|
||||
return a.dirName.localeCompare(b.dirName);
|
||||
|
||||
// If one of the dirTypes is PAB and the other is something else,
|
||||
// then the other will go below the one of type PAB.
|
||||
const PABDirectory = 2;
|
||||
if (a.dirType == PABDirectory)
|
||||
return -1;
|
||||
|
||||
if (b.dirType == PABDirectory)
|
||||
return 1;
|
||||
|
||||
// Sort anything else by the dir type.
|
||||
return a.dirType - b.dirType;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="map-list"
|
||||
extends="chrome://global/content/bindings/popup.xml#popup">
|
||||
<implementation>
|
||||
<property name="mapURL" readonly="true">
|
||||
<getter><![CDATA[
|
||||
return this._createMapItURL();
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._setWidgetDisabled(true);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<!--
|
||||
Initializes the necessary address data from an addressbook card.
|
||||
@param aCard A nsIAbCard to get the address data from.
|
||||
@param aAddrPrefix A prefix of the card properties to use. Use "Home" or "Work".
|
||||
-->
|
||||
<method name="initMapAddressFromCard">
|
||||
<parameter name="aCard"/>
|
||||
<parameter name="aAddrPrefix"/>
|
||||
<body><![CDATA[
|
||||
let mapItURLFormat = this._getMapURLPref(0);
|
||||
let doNotShowMap = !mapItURLFormat || !aAddrPrefix || !aCard;
|
||||
this._setWidgetDisabled(doNotShowMap);
|
||||
if (doNotShowMap)
|
||||
return;
|
||||
|
||||
this.setAttribute("map_address1", aCard.getProperty(aAddrPrefix + "Address"));
|
||||
this.setAttribute("map_address2", aCard.getProperty(aAddrPrefix + "Address2"));
|
||||
this.setAttribute("map_city" , aCard.getProperty(aAddrPrefix + "City"));
|
||||
this.setAttribute("map_state" , aCard.getProperty(aAddrPrefix + "State"));
|
||||
this.setAttribute("map_zip" , aCard.getProperty(aAddrPrefix + "ZipCode"));
|
||||
this.setAttribute("map_country" , aCard.getProperty(aAddrPrefix + "Country"));
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Initializes the necessary address data from passed in values.
|
||||
-->
|
||||
<method name="initMapAddress">
|
||||
<parameter name="aAddr1"/>
|
||||
<parameter name="aAddr2"/>
|
||||
<parameter name="aCity"/>
|
||||
<parameter name="aState"/>
|
||||
<parameter name="aZip"/>
|
||||
<parameter name="aCountry"/>
|
||||
<body><![CDATA[
|
||||
let mapItURLFormat = this._getMapURLPref(0);
|
||||
let doNotShowMap = !mapItURLFormat || !(aAddr1 + aAddr2 + aCity + aState + aZip + aCountry);
|
||||
this._setWidgetDisabled(doNotShowMap);
|
||||
if (doNotShowMap)
|
||||
return;
|
||||
|
||||
this.setAttribute("map_address1", aAddr1);
|
||||
this.setAttribute("map_address2", aAddr2);
|
||||
this.setAttribute("map_city" , aCity);
|
||||
this.setAttribute("map_state" , aState);
|
||||
this.setAttribute("map_zip" , aZip);
|
||||
this.setAttribute("map_country" , aCountry);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Sets the disabled/enabled state of the parent widget (e.g. a button).
|
||||
-->
|
||||
<method name="_setWidgetDisabled">
|
||||
<parameter name="aDisabled"/>
|
||||
<body><![CDATA[
|
||||
this.parentNode.disabled = aDisabled;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Returns the Map service URL from localized pref. Returns null if there
|
||||
is none at the given index.
|
||||
@param aIndex The index of the service to return. 0 is the default service.
|
||||
-->
|
||||
<method name="_getMapURLPref">
|
||||
<parameter name="aIndex"/>
|
||||
<body><![CDATA[
|
||||
let url = null;
|
||||
if (!aIndex) {
|
||||
url = Services.prefs.getComplexValue("mail.addr_book.mapit_url.format",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
} else {
|
||||
try {
|
||||
url = Services.prefs.getComplexValue("mail.addr_book.mapit_url." + aIndex + ".format",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
return url;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Builds menuitem elements representing map services defined in prefs
|
||||
and attaches them to the specified button.
|
||||
-->
|
||||
<method name="_listMapServices">
|
||||
<body><![CDATA[
|
||||
let index = 1;
|
||||
let itemFound = true;
|
||||
let defaultFound = false;
|
||||
const kUserIndex = 100;
|
||||
let aMapList = this;
|
||||
while (aMapList.hasChildNodes()) {
|
||||
aMapList.lastChild.remove();
|
||||
}
|
||||
|
||||
let defaultUrl = this._getMapURLPref(0);
|
||||
|
||||
// Creates the menuitem with supplied data.
|
||||
function addMapService(aUrl, aName) {
|
||||
let item = document.createElement("menuitem");
|
||||
item.setAttribute("url", aUrl);
|
||||
item.setAttribute("label", aName);
|
||||
item.setAttribute("type", "radio");
|
||||
item.setAttribute("name", "mapit_service");
|
||||
if (aUrl == defaultUrl)
|
||||
item.setAttribute("checked", "true");
|
||||
aMapList.appendChild(item);
|
||||
}
|
||||
|
||||
// Generates a useful generic name by cutting out only the host address.
|
||||
function generateName(aUrl) {
|
||||
return new URL(aUrl).hostname;
|
||||
}
|
||||
|
||||
// Add all defined map services as menuitems.
|
||||
while (itemFound) {
|
||||
let urlName;
|
||||
let urlTemplate = this._getMapURLPref(index);
|
||||
if (!urlTemplate) {
|
||||
itemFound = false;
|
||||
} else {
|
||||
// Name is not mandatory, generate one if not found.
|
||||
try {
|
||||
urlName = Services.prefs.getComplexValue("mail.addr_book.mapit_url." + index + ".name",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
} catch (e) {
|
||||
urlName = generateName(urlTemplate);
|
||||
}
|
||||
}
|
||||
if (itemFound) {
|
||||
addMapService(urlTemplate, urlName);
|
||||
index++;
|
||||
if (urlTemplate == defaultUrl)
|
||||
defaultFound = true;
|
||||
} else if (index < kUserIndex) {
|
||||
// After iterating the base region provided urls, check for user defined ones.
|
||||
index = kUserIndex;
|
||||
itemFound = true;
|
||||
}
|
||||
}
|
||||
if (!defaultFound) {
|
||||
// If user had put a customized map URL into mail.addr_book.mapit_url.format
|
||||
// preserve it as a new map service named with the URL.
|
||||
// 'index' now points to the first unused entry in prefs.
|
||||
let defaultName = generateName(defaultUrl);
|
||||
addMapService(defaultUrl, defaultName);
|
||||
Services.prefs.setCharPref("mail.addr_book.mapit_url." + index + ".format",
|
||||
defaultUrl);
|
||||
Services.prefs.setCharPref("mail.addr_book.mapit_url." + index + ".name",
|
||||
defaultName);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Save user selected mapping service.
|
||||
@param aItem The chosen menuitem with map service.
|
||||
-->
|
||||
<method name="_chooseMapService">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
// Save selected URL as the default.
|
||||
let defaultUrl = Components.classes["@mozilla.org/pref-localizedstring;1"]
|
||||
.createInstance(Components.interfaces.nsIPrefLocalizedString);
|
||||
defaultUrl.data = aItem.getAttribute("url");
|
||||
Services.prefs.setComplexValue("mail.addr_book.mapit_url.format",
|
||||
Components.interfaces.nsIPrefLocalizedString, defaultUrl);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Generate map URL in the href attribute.
|
||||
-->
|
||||
<method name="_createMapItURL">
|
||||
<body><![CDATA[
|
||||
let urlFormat = this._getMapURLPref(0);
|
||||
if (!urlFormat)
|
||||
return null;
|
||||
|
||||
let address1 = this.getAttribute("map_address1");
|
||||
let address2 = this.getAttribute("map_address2");
|
||||
let city = this.getAttribute("map_city");
|
||||
let state = this.getAttribute("map_state");
|
||||
let zip = this.getAttribute("map_zip");
|
||||
let country = this.getAttribute("map_country");
|
||||
|
||||
urlFormat = urlFormat.replace("@A1", encodeURIComponent(address1));
|
||||
urlFormat = urlFormat.replace("@A2", encodeURIComponent(address2));
|
||||
urlFormat = urlFormat.replace("@CI", encodeURIComponent(city));
|
||||
urlFormat = urlFormat.replace("@ST", encodeURIComponent(state));
|
||||
urlFormat = urlFormat.replace("@ZI", encodeURIComponent(zip));
|
||||
urlFormat = urlFormat.replace("@CO", encodeURIComponent(country));
|
||||
|
||||
return urlFormat;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="command">
|
||||
<![CDATA[
|
||||
this._chooseMapService(event.target);
|
||||
event.stopPropagation();
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="popupshowing">
|
||||
<![CDATA[
|
||||
this._listMapServices();
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
||||
94
mailnews/addrbook/content/print.css
Normal file
94
mailnews/addrbook/content/print.css
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* 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/. */
|
||||
|
||||
directory {
|
||||
display: block;
|
||||
}
|
||||
|
||||
section {
|
||||
display:block;
|
||||
margin: 15px 20px;
|
||||
}
|
||||
|
||||
sectiontitle {
|
||||
display:block;
|
||||
font-weight:bold;
|
||||
font-family:verdana;
|
||||
font-size:small;
|
||||
}
|
||||
|
||||
labelrow {
|
||||
display:block;
|
||||
}
|
||||
|
||||
label {
|
||||
display:inline;
|
||||
font-family:verdana;
|
||||
font-size:small;
|
||||
}
|
||||
|
||||
GeneratedName {
|
||||
display:block;
|
||||
font-weight:bold;
|
||||
font-family:verdana;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 3px;
|
||||
margin-inline-end: 10px;
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
|
||||
FirstName, LastName,
|
||||
HomeAddress, HomeAddress2, HomeCountry,
|
||||
WorkAddress, WorkAddress2, WorkCountry,
|
||||
JobTitle, Department, Company, Notes {
|
||||
display: block;
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
DisplayName, NickName,
|
||||
WorkPhone, HomePhone, FaxNumber, PagerNumber, CellularNumber,
|
||||
HomeCity, HomeState, HomeZipCode,
|
||||
WorkCity, WorkState, WorkZipCode,
|
||||
Custom1, Custom2, Custom3, Custom4 {
|
||||
display: inline;
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
PrimaryEmail, SecondEmail,
|
||||
WebPage1, WebPage2 {
|
||||
display: block;
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
text-decoration: underline;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
separator {
|
||||
display: block;
|
||||
border-bottom: 1px solid #000000;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-inline-end: 0px;
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
display: table;
|
||||
}
|
||||
|
||||
tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
td {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
PreferMailFormat {
|
||||
display: none;
|
||||
}
|
||||
|
||||
9
mailnews/addrbook/moz.build
Normal file
9
mailnews/addrbook/moz.build
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'public',
|
||||
'src',
|
||||
]
|
||||
394
mailnews/addrbook/prefs/content/pref-directory-add.js
Normal file
394
mailnews/addrbook/prefs/content/pref-directory-add.js
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
/* -*- Mode: Java; 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://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
|
||||
var gCurrentDirectory = null;
|
||||
var gReplicationBundle = null;
|
||||
var gReplicationService =
|
||||
Components.classes["@mozilla.org/addressbook/ldap-replication-service;1"].
|
||||
getService(Components.interfaces.nsIAbLDAPReplicationService);
|
||||
var gReplicationCancelled = false;
|
||||
var gProgressText;
|
||||
var gProgressMeter;
|
||||
var gDownloadInProgress = false;
|
||||
|
||||
var kDefaultMaxHits = 100;
|
||||
var kDefaultLDAPPort = 389;
|
||||
var kDefaultSecureLDAPPort = 636;
|
||||
var kLDAPDirectory = 0; // defined in nsDirPrefs.h
|
||||
|
||||
var ldapOfflineObserver = {
|
||||
observe: function(subject, topic, state)
|
||||
{
|
||||
// sanity checks
|
||||
if (topic != "network:offline-status-changed") return;
|
||||
setDownloadOfflineOnlineState(state == "offline");
|
||||
}
|
||||
}
|
||||
|
||||
function Startup()
|
||||
{
|
||||
gReplicationBundle = document.getElementById("bundle_replication");
|
||||
|
||||
document.getElementById("download").label =
|
||||
gReplicationBundle.getString("downloadButton");
|
||||
document.getElementById("download").accessKey =
|
||||
gReplicationBundle.getString("downloadButton.accesskey");
|
||||
|
||||
if ("arguments" in window && window.arguments[0]) {
|
||||
gCurrentDirectory = window.arguments[0].selectedDirectory;
|
||||
try {
|
||||
fillSettings();
|
||||
} catch (ex) {
|
||||
dump("pref-directory-add.js:Startup(): fillSettings() exception: "
|
||||
+ ex + "\n");
|
||||
}
|
||||
|
||||
let oldListName = gCurrentDirectory.dirName;
|
||||
document.title = gReplicationBundle.getFormattedString("directoryTitleEdit", [oldListName]);
|
||||
|
||||
// Only set up the download button for online/offline status toggling
|
||||
// if the pref isn't locked to disable the button.
|
||||
if (!Services.prefs.prefIsLocked(gCurrentDirectory.dirPrefId +
|
||||
".disable_button_download")) {
|
||||
// Now connect to the offline/online observer
|
||||
Services.obs.addObserver(ldapOfflineObserver,
|
||||
"network:offline-status-changed", false);
|
||||
|
||||
// Now set the initial offline/online state and update the state
|
||||
setDownloadOfflineOnlineState(Services.io.offline);
|
||||
}
|
||||
} else {
|
||||
document.title = gReplicationBundle.getString("directoryTitleNew");
|
||||
fillDefaultSettings();
|
||||
// Don't add observer here as it doesn't make any sense.
|
||||
}
|
||||
}
|
||||
|
||||
function onUnload()
|
||||
{
|
||||
if ("arguments" in window &&
|
||||
window.arguments[0] &&
|
||||
!Services.prefs.prefIsLocked(gCurrentDirectory.dirPrefId +
|
||||
".disable_button_download")) {
|
||||
// Remove the observer that we put in on dialog startup
|
||||
Services.obs.removeObserver(ldapOfflineObserver,
|
||||
"network:offline-status-changed");
|
||||
}
|
||||
}
|
||||
|
||||
var progressListener = {
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
|
||||
{
|
||||
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START) {
|
||||
// start the spinning
|
||||
gProgressMeter.setAttribute("mode", "undetermined");
|
||||
gProgressText.value = gReplicationBundle.getString(aStatus ?
|
||||
"replicationStarted" :
|
||||
"changesStarted");
|
||||
gDownloadInProgress = true;
|
||||
document.getElementById("download").label =
|
||||
gReplicationBundle.getString("cancelDownloadButton");
|
||||
document.getElementById("download").accessKey =
|
||||
gReplicationBundle.getString("cancelDownloadButton.accesskey");
|
||||
}
|
||||
|
||||
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
|
||||
EndDownload(aStatus);
|
||||
}
|
||||
},
|
||||
onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
|
||||
{
|
||||
gProgressText.value = gReplicationBundle.getFormattedString("currentCount",
|
||||
[aCurSelfProgress]);
|
||||
},
|
||||
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags)
|
||||
{
|
||||
},
|
||||
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
|
||||
{
|
||||
},
|
||||
onSecurityChange: function(aWebProgress, aRequest, state)
|
||||
{
|
||||
},
|
||||
QueryInterface : function(iid)
|
||||
{
|
||||
if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
iid.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
function DownloadNow()
|
||||
{
|
||||
if (!gDownloadInProgress) {
|
||||
gProgressText = document.getElementById("replicationProgressText");
|
||||
gProgressMeter = document.getElementById("replicationProgressMeter");
|
||||
|
||||
gProgressText.hidden = false;
|
||||
gProgressMeter.hidden = false;
|
||||
gReplicationCancelled = false;
|
||||
|
||||
try {
|
||||
if (gCurrentDirectory instanceof Components.interfaces.nsIAbLDAPDirectory)
|
||||
gReplicationService.startReplication(gCurrentDirectory,
|
||||
progressListener);
|
||||
else
|
||||
EndDownload(false);
|
||||
}
|
||||
catch (ex) {
|
||||
EndDownload(false);
|
||||
}
|
||||
} else {
|
||||
gReplicationCancelled = true;
|
||||
try {
|
||||
gReplicationService.cancelReplication(gCurrentDirectory.dirPrefId);
|
||||
}
|
||||
catch (ex) {
|
||||
// XXX todo
|
||||
// perhaps replication hasn't started yet? This can happen if you hit cancel after attempting to replication when offline
|
||||
dump("unexpected failure while cancelling. ex=" + ex + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EndDownload(aStatus)
|
||||
{
|
||||
document.getElementById("download").label =
|
||||
gReplicationBundle.getString("downloadButton");
|
||||
document.getElementById("download").accessKey =
|
||||
gReplicationBundle.getString("downloadButton.accesskey");
|
||||
|
||||
// stop the spinning
|
||||
gProgressMeter.setAttribute("mode", "normal");
|
||||
gProgressMeter.setAttribute("value", "100");
|
||||
gProgressMeter.hidden = true;
|
||||
|
||||
gDownloadInProgress = false;
|
||||
gProgressText.value =
|
||||
gReplicationBundle.getString(aStatus ? "replicationSucceeded" :
|
||||
gReplicationCancelled ? "replicationCancelled" :
|
||||
"replicationFailed");
|
||||
}
|
||||
|
||||
// fill the settings panel with the data from the preferences.
|
||||
//
|
||||
function fillSettings()
|
||||
{
|
||||
document.getElementById("description").value = gCurrentDirectory.dirName;
|
||||
|
||||
if (gCurrentDirectory instanceof Components.interfaces.nsIAbLDAPDirectory) {
|
||||
var ldapUrl = gCurrentDirectory.lDAPURL;
|
||||
|
||||
document.getElementById("results").value = gCurrentDirectory.maxHits;
|
||||
document.getElementById("login").value = gCurrentDirectory.authDn;
|
||||
document.getElementById("hostname").value = ldapUrl.host;
|
||||
document.getElementById("basedn").value = ldapUrl.dn;
|
||||
document.getElementById("search").value = ldapUrl.filter;
|
||||
|
||||
var sub = document.getElementById("sub");
|
||||
switch(ldapUrl.scope) {
|
||||
case Components.interfaces.nsILDAPURL.SCOPE_ONELEVEL:
|
||||
sub.radioGroup.selectedItem = document.getElementById("one");
|
||||
break;
|
||||
default:
|
||||
sub.radioGroup.selectedItem = sub;
|
||||
break;
|
||||
}
|
||||
|
||||
var sasl = document.getElementById("saslMechanism");
|
||||
switch (gCurrentDirectory.saslMechanism) {
|
||||
case "GSSAPI":
|
||||
sasl.selectedItem = document.getElementById("GSSAPI");
|
||||
break;
|
||||
default:
|
||||
sasl.selectedItem = document.getElementById("Simple");
|
||||
break;
|
||||
}
|
||||
|
||||
var secure = ldapUrl.options & ldapUrl.OPT_SECURE
|
||||
if (secure)
|
||||
document.getElementById("secure").setAttribute("checked", "true");
|
||||
|
||||
if (ldapUrl.port == -1)
|
||||
document.getElementById("port").value =
|
||||
(secure ? kDefaultSecureLDAPPort : kDefaultLDAPPort);
|
||||
else
|
||||
document.getElementById("port").value = ldapUrl.port;
|
||||
}
|
||||
|
||||
// check if any of the preferences for this server are locked.
|
||||
//If they are locked disable them
|
||||
DisableUriFields(gCurrentDirectory.dirPrefId + ".uri");
|
||||
DisableElementIfPrefIsLocked(gCurrentDirectory.dirPrefId + ".description", "description");
|
||||
DisableElementIfPrefIsLocked(gCurrentDirectory.dirPrefId + ".disable_button_download", "download");
|
||||
DisableElementIfPrefIsLocked(gCurrentDirectory.dirPrefId + ".maxHits", "results");
|
||||
DisableElementIfPrefIsLocked(gCurrentDirectory.dirPrefId + ".auth.dn", "login");
|
||||
}
|
||||
|
||||
function DisableElementIfPrefIsLocked(aPrefName, aElementId)
|
||||
{
|
||||
if (Services.prefs.prefIsLocked(aPrefName))
|
||||
document.getElementById(aElementId).setAttribute('disabled', true);
|
||||
}
|
||||
|
||||
// disables all the text fields corresponding to the .uri pref.
|
||||
function DisableUriFields(aPrefName)
|
||||
{
|
||||
if (Services.prefs.prefIsLocked(aPrefName)) {
|
||||
let lockedElements = document.querySelectorAll('[disableiflocked="true"]');
|
||||
for (let i = 0; i < lockedElements.length; i++)
|
||||
lockedElements[i].setAttribute('disabled', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function onSecure()
|
||||
{
|
||||
document.getElementById("port").value =
|
||||
document.getElementById("secure").checked ? kDefaultSecureLDAPPort :
|
||||
kDefaultLDAPPort;
|
||||
}
|
||||
|
||||
function fillDefaultSettings()
|
||||
{
|
||||
document.getElementById("port").value = kDefaultLDAPPort;
|
||||
document.getElementById("results").value = kDefaultMaxHits;
|
||||
var sub = document.getElementById("sub");
|
||||
sub.radioGroup.selectedItem = sub;
|
||||
|
||||
// Disable the download button and add some text indicating why.
|
||||
document.getElementById("download").disabled = true;
|
||||
document.getElementById("downloadWarningMsg").hidden = false;
|
||||
document.getElementById("downloadWarningMsg").textContent = document.
|
||||
getElementById("bundle_addressBook").
|
||||
getString("abReplicationSaveSettings");
|
||||
}
|
||||
|
||||
function hasCharacters(number)
|
||||
{
|
||||
var re = /[0-9]/g;
|
||||
var num = number.match(re);
|
||||
if(num && (num.length == number.length))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
function onAccept()
|
||||
{
|
||||
try {
|
||||
var pref_string_content = "";
|
||||
var pref_string_title = "";
|
||||
|
||||
var description = document.getElementById("description").value;
|
||||
var hostname = cleanUpHostName(document.getElementById("hostname").value);
|
||||
var port = document.getElementById("port").value;
|
||||
var secure = document.getElementById("secure");
|
||||
var results = document.getElementById("results").value;
|
||||
var errorValue = null;
|
||||
var saslMechanism = "";
|
||||
if ((!description) || (description.trim() == ""))
|
||||
errorValue = "invalidName";
|
||||
else if (!isLegalHostNameOrIP(hostname))
|
||||
errorValue = "invalidHostname";
|
||||
// XXX write isValidDn and call it on the dn string here?
|
||||
else if (port && hasCharacters(port))
|
||||
errorValue = "invalidPortNumber";
|
||||
else if (results && hasCharacters(results))
|
||||
errorValue = "invalidResults";
|
||||
if (!errorValue) {
|
||||
// XXX Due to the LDAP c-sdk pass a dummy url to the IO service, then
|
||||
// update the parts (bug 473351).
|
||||
let ldapUrl = Services.io.newURI(
|
||||
(secure.checked ? "ldaps://" : "ldap://") + "localhost/dc=???", null, null)
|
||||
.QueryInterface(Components.interfaces.nsILDAPURL);
|
||||
|
||||
ldapUrl.host = hostname;
|
||||
ldapUrl.port = port ? port :
|
||||
(secure.checked ? kDefaultSecureLDAPPort :
|
||||
kDefaultLDAPPort);
|
||||
ldapUrl.dn = document.getElementById("basedn").value;
|
||||
ldapUrl.scope = document.getElementById("one").selected ?
|
||||
Components.interfaces.nsILDAPURL.SCOPE_ONELEVEL :
|
||||
Components.interfaces.nsILDAPURL.SCOPE_SUBTREE;
|
||||
|
||||
ldapUrl.filter = document.getElementById("search").value;
|
||||
if (document.getElementById("GSSAPI").selected) {
|
||||
saslMechanism = "GSSAPI";
|
||||
}
|
||||
|
||||
// check if we are modifying an existing directory or adding a new directory
|
||||
if (gCurrentDirectory) {
|
||||
gCurrentDirectory.dirName = description;
|
||||
gCurrentDirectory.lDAPURL = ldapUrl.QueryInterface(Components.interfaces.nsILDAPURL);
|
||||
window.opener.gNewServerString = gCurrentDirectory.dirPrefId;
|
||||
}
|
||||
else { // adding a new directory
|
||||
window.opener.gNewServerString =
|
||||
MailServices.ab.newAddressBook(description, ldapUrl.spec, kLDAPDirectory);
|
||||
}
|
||||
|
||||
// XXX This is really annoying - both new/modify Address Book don't
|
||||
// give us back the new directory we just created - so go find it from
|
||||
// rdf so we can set a few final things up on it.
|
||||
var targetURI = "moz-abldapdirectory://" + window.opener.gNewServerString;
|
||||
var theDirectory =
|
||||
MailServices.ab.getDirectory(targetURI)
|
||||
.QueryInterface(Components.interfaces.nsIAbLDAPDirectory);
|
||||
|
||||
theDirectory.maxHits = results;
|
||||
theDirectory.authDn = document.getElementById("login").value;
|
||||
theDirectory.saslMechanism = saslMechanism;
|
||||
|
||||
window.opener.gNewServer = description;
|
||||
// set window.opener.gUpdate to true so that LDAP Directory Servers
|
||||
// dialog gets updated
|
||||
window.opener.gUpdate = true;
|
||||
} else {
|
||||
var addressBookBundle = document.getElementById("bundle_addressBook");
|
||||
|
||||
Services.prompt.alert(window,
|
||||
document.title,
|
||||
addressBookBundle.getString(errorValue));
|
||||
return false;
|
||||
}
|
||||
} catch (outer) {
|
||||
dump("Internal error in pref-directory-add.js:onAccept() " + outer + "\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function onCancel()
|
||||
{
|
||||
window.opener.gUpdate = false;
|
||||
}
|
||||
|
||||
|
||||
// called by Help button in platform overlay
|
||||
function doHelpButton()
|
||||
{
|
||||
openHelp("mail-ldap-properties");
|
||||
}
|
||||
|
||||
// Sets the download button state for offline or online.
|
||||
// This function should only be called for ldap edit dialogs.
|
||||
function setDownloadOfflineOnlineState(isOffline)
|
||||
{
|
||||
if (isOffline)
|
||||
{
|
||||
// Disable the download button and add some text indicating why.
|
||||
document.getElementById("downloadWarningMsg").textContent = document.
|
||||
getElementById("bundle_addressBook").
|
||||
getString("abReplicationOfflineWarning");
|
||||
}
|
||||
document.getElementById("downloadWarningMsg").hidden = !isOffline;
|
||||
document.getElementById("download").disabled = isOffline;
|
||||
}
|
||||
152
mailnews/addrbook/prefs/content/pref-directory-add.xul
Normal file
152
mailnews/addrbook/prefs/content/pref-directory-add.xul
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/pref-directory-add.dtd">
|
||||
|
||||
<dialog id="addDirectory"
|
||||
style="width: &newDirectoryWidth;"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="Startup();"
|
||||
onunload="onUnload();"
|
||||
buttons="accept,cancel"
|
||||
ondialogaccept="return onAccept();"
|
||||
ondialogcancel="return onCancel();">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/addressbook/pref-directory-add.js"/>
|
||||
<stringbundle id="bundle_addressBook" src="chrome://messenger/locale/addressbook/addressBook.properties"/>
|
||||
<stringbundle id="bundle_replication" src="chrome://messenger/locale/addressbook/replicationProgress.properties"/>
|
||||
|
||||
<keyset id="keyset"/>
|
||||
<vbox id="editDirectory">
|
||||
|
||||
<tabbox style="margin:5px">
|
||||
<tabs id="directoryTabBox">
|
||||
<tab label="&General.tab;"/>
|
||||
<tab label="&Offline.tab;"/>
|
||||
<tab label="&Advanced.tab;"/>
|
||||
</tabs>
|
||||
|
||||
<tabpanels id="directoryTabPanels" flex="1">
|
||||
<vbox>
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
<column/>
|
||||
</columns>
|
||||
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&directoryName.label;" accesskey="&directoryName.accesskey;"
|
||||
control="description"/>
|
||||
<textbox id="description" flex="1"/>
|
||||
<spacer flex="1"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&directoryHostname.label;" accesskey="&directoryHostname.accesskey;"
|
||||
control="hostname"/>
|
||||
<textbox id="hostname" flex="1" disableiflocked="true" class="uri-element"/>
|
||||
<spacer flex="1"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&directoryBaseDN.label;"
|
||||
accesskey="&directoryBaseDN.accesskey;"
|
||||
control="basedn"/>
|
||||
<vbox>
|
||||
<textbox id="basedn" disableiflocked="true" class="uri-element"/>
|
||||
</vbox>
|
||||
<button label="&findButton.label;"
|
||||
accesskey="&findButton.accesskey;" disabled="true"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&portNumber.label;"
|
||||
accesskey="&portNumber.accesskey;"
|
||||
control="port"/>
|
||||
<hbox>
|
||||
<textbox id="port" type="number" size="5" min="1"
|
||||
max="65535" hidespinbuttons="true"
|
||||
disableiflocked="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&directoryLogin.label;"
|
||||
accesskey="&directoryLogin.accesskey;"
|
||||
control="login"/>
|
||||
<textbox id="login" flex="1" class="uri-element"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<separator/>
|
||||
<checkbox id="secure" label="&directorySecure.label;"
|
||||
accesskey="&directorySecure.accesskey;"
|
||||
oncommand="onSecure();" disableiflocked="true"/>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<description>&offlineText.label;</description>
|
||||
<separator/>
|
||||
<hbox>
|
||||
<button id="download" oncommand="DownloadNow();"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<description id="downloadWarningMsg" hidden="true" class="error"/>
|
||||
<description id="replicationProgressText" hidden="true"/>
|
||||
|
||||
<progressmeter id="replicationProgressMeter" mode="normal" value="0" hidden="true"/>
|
||||
</vbox>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&return.label;"
|
||||
accesskey="&return.accesskey;"
|
||||
control="results"/>
|
||||
<hbox align="center">
|
||||
<textbox id="results" type="number" size="10" min="1"
|
||||
max="2147483647" increment="10"/>
|
||||
<label value="&results.label;"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&scope.label;" control="scope" accesskey="&scope.accesskey;"/>
|
||||
<radiogroup id="scope" orient="horizontal">
|
||||
<radio id="one" value="1" label="&scopeOneLevel.label;"
|
||||
disableiflocked="true" accesskey="&scopeOneLevel.accesskey;"/>
|
||||
<radio id="sub" value="2" label="&scopeSubtree.label;"
|
||||
disableiflocked="true" accesskey="&scopeSubtree.accesskey;"/>
|
||||
</radiogroup>
|
||||
</row>
|
||||
<row>
|
||||
<label value="&searchFilter.label;"
|
||||
accesskey="&searchFilter.accesskey;"
|
||||
control="search"/>
|
||||
<textbox id="search" multiline="true" flex="1" disableiflocked="true"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&saslMechanism.label;" control="saslMechanism" accesskey="&saslMechanism.accesskey;"/>
|
||||
<menulist id="saslMechanism">
|
||||
<menupopup>
|
||||
<menuitem id="Simple" value=""
|
||||
label="&saslOff.label;"
|
||||
accesskey="&saslOff.accesskey;"/>
|
||||
<menuitem id="GSSAPI" value="GSSAPI"
|
||||
label="&saslGSSAPI.label;"
|
||||
accesskey="&saslGSSAPI.accesskey;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</vbox>
|
||||
|
||||
</dialog>
|
||||
|
||||
142
mailnews/addrbook/prefs/content/pref-editdirectories.js
Normal file
142
mailnews/addrbook/prefs/content/pref-editdirectories.js
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/* -*- 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://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
// Listener to refresh the list items if something changes. In all these
|
||||
// cases we just rebuild the list as it is easier than searching/adding in the
|
||||
// correct places an would be an infrequent operation.
|
||||
var gAddressBookAbListener = {
|
||||
onItemAdded: function(parentDir, item) {
|
||||
if (item instanceof Components.interfaces.nsIAbDirectory) {
|
||||
fillDirectoryList();
|
||||
}
|
||||
},
|
||||
onItemRemoved: function(parentDir, item) {
|
||||
if (item instanceof Components.interfaces.nsIAbDirectory) {
|
||||
fillDirectoryList();
|
||||
}
|
||||
},
|
||||
onItemPropertyChanged: function(item, property, oldValue, newValue) {
|
||||
if (item instanceof Components.interfaces.nsIAbDirectory) {
|
||||
fillDirectoryList();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onInitEditDirectories()
|
||||
{
|
||||
// For AbDeleteDirectory in abCommon.js
|
||||
gAddressBookBundle = document.getElementById("bundle_addressBook");
|
||||
|
||||
// If the pref is locked disable the "Add" button
|
||||
if (Services.prefs.prefIsLocked("ldap_2.disable_button_add"))
|
||||
document.getElementById("addButton").setAttribute('disabled', true);
|
||||
|
||||
// Fill out the directory list
|
||||
fillDirectoryList();
|
||||
|
||||
const nsIAbListener = Components.interfaces.nsIAbListener;
|
||||
// Add a listener so we can update correctly if the list should change
|
||||
MailServices.ab.addAddressBookListener(gAddressBookAbListener,
|
||||
nsIAbListener.itemAdded |
|
||||
nsIAbListener.directoryRemoved |
|
||||
nsIAbListener.itemChanged);
|
||||
}
|
||||
|
||||
function onUninitEditDirectories()
|
||||
{
|
||||
MailServices.ab.removeAddressBookListener(gAddressBookAbListener);
|
||||
}
|
||||
|
||||
function fillDirectoryList()
|
||||
{
|
||||
var abList = document.getElementById("directoriesList");
|
||||
|
||||
// Empty out anything in the list
|
||||
while (abList.hasChildNodes())
|
||||
abList.lastChild.remove();
|
||||
|
||||
// Init the address book list
|
||||
let directories = MailServices.ab.directories;
|
||||
let holdingArray = [];
|
||||
while (directories && directories.hasMoreElements()) {
|
||||
let ab = directories.getNext();
|
||||
if (ab instanceof Components.interfaces.nsIAbDirectory && ab.isRemote)
|
||||
holdingArray.push(ab);
|
||||
}
|
||||
|
||||
holdingArray.sort(function (a, b) { return a.dirName.localeCompare(b.dirName); });
|
||||
|
||||
holdingArray.forEach(function (ab) {
|
||||
var item = document.createElement('listitem');
|
||||
item.setAttribute("label", ab.dirName);
|
||||
item.setAttribute("value", ab.URI);
|
||||
|
||||
abList.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
function selectDirectory()
|
||||
{
|
||||
var abList = document.getElementById("directoriesList");
|
||||
var editButton = document.getElementById("editButton");
|
||||
var removeButton = document.getElementById("removeButton");
|
||||
|
||||
if (abList && abList.selectedItem) {
|
||||
editButton.removeAttribute("disabled");
|
||||
|
||||
// If the disable delete button pref for the selected directory is set,
|
||||
// disable the delete button for that directory.
|
||||
let disable = false;
|
||||
let ab = MailServices.ab.getDirectory(abList.value);
|
||||
try {
|
||||
disable = Services.prefs.getBoolPref(ab.dirPrefId + ".disable_delete");
|
||||
}
|
||||
catch(ex){
|
||||
// If this preference is not set, it's ok.
|
||||
}
|
||||
if (disable)
|
||||
removeButton.setAttribute("disabled", true);
|
||||
else
|
||||
removeButton.removeAttribute("disabled");
|
||||
}
|
||||
else {
|
||||
editButton.setAttribute("disabled", true);
|
||||
removeButton.setAttribute("disabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
function dblClickDirectory(event)
|
||||
{
|
||||
// We only care about left click events.
|
||||
if (event.button != 0)
|
||||
return;
|
||||
|
||||
editDirectory();
|
||||
}
|
||||
|
||||
function editDirectory()
|
||||
{
|
||||
var abList = document.getElementById("directoriesList");
|
||||
|
||||
if (abList && abList.selectedItem) {
|
||||
let abURI = abList.value;
|
||||
let ab = MailServices.ab.getDirectory(abURI);
|
||||
|
||||
window.openDialog(ab.propertiesChromeURI, "editDirectory",
|
||||
"chrome,modal=yes,resizable=no",
|
||||
{ selectedDirectory: ab });
|
||||
}
|
||||
}
|
||||
|
||||
function removeDirectory()
|
||||
{
|
||||
var abList = document.getElementById("directoriesList");
|
||||
|
||||
if (abList && abList.selectedItem)
|
||||
AbDeleteDirectory(abList.value);
|
||||
}
|
||||
43
mailnews/addrbook/prefs/content/pref-editdirectories.xul
Normal file
43
mailnews/addrbook/prefs/content/pref-editdirectories.xul
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/pref-directory.dtd">
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
id="editDirectories"
|
||||
title="&pref.ldap.window.title;"
|
||||
buttons="accept"
|
||||
onload="onInitEditDirectories();"
|
||||
onunload="onUninitEditDirectories();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/addressbook/abCommon.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/addressbook/pref-editdirectories.js"/>
|
||||
|
||||
<stringbundle id="bundle_addressBook"
|
||||
src="chrome://messenger/locale/addressbook/addressBook.properties"/>
|
||||
|
||||
<label value="&directoriesText.label;"
|
||||
accesskey="&directoriesText.accesskey;" control="directoriesList"/>
|
||||
<hbox flex="1">
|
||||
<listbox id="directoriesList" flex="1" onselect="selectDirectory();"
|
||||
ondblclick="dblClickDirectory(event);"/>
|
||||
<vbox>
|
||||
<button id="addButton" label="&addDirectory.label;"
|
||||
accesskey="&addDirectory.accesskey;"
|
||||
oncommand="AbNewLDAPDirectory();"/>
|
||||
<button id="editButton" label="&editDirectory.label;"
|
||||
accesskey="&editDirectory.accesskey;" disabled="true"
|
||||
oncommand="editDirectory();"/>
|
||||
<button id="removeButton" label="&deleteDirectory.label;"
|
||||
accesskey="&deleteDirectory.accesskey;" disabled="true"
|
||||
oncommand="removeDirectory();"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</dialog>
|
||||
47
mailnews/addrbook/public/moz.build
Normal file
47
mailnews/addrbook/public/moz.build
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# 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/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIAbAddressCollector.idl',
|
||||
'nsIAbAutoCompleteResult.idl',
|
||||
'nsIAbBooleanExpression.idl',
|
||||
'nsIAbCard.idl',
|
||||
'nsIAbCollection.idl',
|
||||
'nsIAbDirectory.idl',
|
||||
'nsIAbDirectoryQuery.idl',
|
||||
'nsIAbDirectoryQueryProxy.idl',
|
||||
'nsIAbDirectorySearch.idl',
|
||||
'nsIAbDirFactory.idl',
|
||||
'nsIAbDirFactoryService.idl',
|
||||
'nsIAbDirSearchListener.idl',
|
||||
'nsIAbItem.idl',
|
||||
'nsIAbLDAPAttributeMap.idl',
|
||||
'nsIAbLDIFService.idl',
|
||||
'nsIAbListener.idl',
|
||||
'nsIAbManager.idl',
|
||||
'nsIAbMDBDirectory.idl',
|
||||
'nsIAbView.idl',
|
||||
'nsIAddbookUrl.idl',
|
||||
'nsIAddrDatabase.idl',
|
||||
'nsIAddrDBAnnouncer.idl',
|
||||
'nsIAddrDBListener.idl',
|
||||
'nsIMsgVCardService.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_LDAP_XPCOM']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIAbLDAPCard.idl',
|
||||
'nsIAbLDAPDirectory.idl',
|
||||
'nsIAbLDAPReplicationData.idl',
|
||||
'nsIAbLDAPReplicationQuery.idl',
|
||||
'nsIAbLDAPReplicationService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'addrbook'
|
||||
|
||||
EXPORTS += [
|
||||
'nsAbBaseCID.h',
|
||||
]
|
||||
|
||||
445
mailnews/addrbook/public/nsAbBaseCID.h
Normal file
445
mailnews/addrbook/public/nsAbBaseCID.h
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
/* -*- 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 nsAbBaseCID_h__
|
||||
#define nsAbBaseCID_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
//
|
||||
// The start of the contract ID for address book directory factories.
|
||||
//
|
||||
#define NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX \
|
||||
"@mozilla.org/addressbook/directory-factory;1?name="
|
||||
|
||||
//
|
||||
// The start of the contract ID for address book directory types
|
||||
//
|
||||
#define NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX \
|
||||
"@mozilla.org/addressbook/directory;1?type="
|
||||
|
||||
//
|
||||
// nsAbManager
|
||||
//
|
||||
#define NS_ABMANAGER_CONTRACTID \
|
||||
"@mozilla.org/abmanager;1"
|
||||
|
||||
#define NS_ABMANAGERSTARTUPHANDLER_CONTRACTID \
|
||||
"@mozilla.org/commandlinehandler/general-startup;1?type=addressbook"
|
||||
|
||||
#define NS_ABMANAGER_CID \
|
||||
{ /* {ad81b321-8a8a-42ca-a508-fe659de84586} */ \
|
||||
0xad81b321, 0x8a8a, 0x42ca, \
|
||||
{0xa5, 0x08, 0xfe, 0x65, 0x9d, 0x8e, 0x45, 0x86} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbContentHandler
|
||||
//
|
||||
#define NS_ABCONTENTHANDLER_CID \
|
||||
{ /* {a72ad552-0484-4b5f-8d45-2d79158d22e3} */ \
|
||||
0xa72ad552, 0x0484, 0x4b5f, \
|
||||
{0x8d, 0x45, 0x2d, 0x79, 0x15, 0x8d, 0x22, 0xe3} \
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsAbBSDirectory - the root address book
|
||||
//
|
||||
#define NS_ABDIRECTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX "moz-abdirectory"
|
||||
|
||||
#define NS_ABDIRECTORY_CID \
|
||||
{ /* {012D3C24-1DD2-11B2-BA79-B4AD359FC461}*/ \
|
||||
0x012D3C24, 0x1DD2, 0x11B2, \
|
||||
{0xBA, 0x79, 0xB4, 0xAD, 0x35, 0x9F, 0xC4, 0x61} \
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsAddressBookDB
|
||||
//
|
||||
#define NS_ADDRDATABASE_CONTRACTID \
|
||||
"@mozilla.org/addressbook/carddatabase;1"
|
||||
|
||||
#define NS_ADDRDATABASE_CID \
|
||||
{ /* 63187917-1D19-11d3-A302-001083003D0C */ \
|
||||
0x63187917, 0x1d19, 0x11d3, \
|
||||
{0xa3, 0x2, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbCardProperty
|
||||
//
|
||||
#define NS_ABCARDPROPERTY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/cardproperty;1"
|
||||
#define NS_ABCARDPROPERTY_CID \
|
||||
{ /* 2B722171-2CEA-11d3-9E0B-00A0C92B5F0D */ \
|
||||
0x2b722171, 0x2cea, 0x11d3, \
|
||||
{0x9e, 0xb, 0x0, 0xa0, 0xc9, 0x2b, 0x5f, 0xd} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbDirProperty
|
||||
//
|
||||
#define NS_ABDIRPROPERTY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/directoryproperty;1"
|
||||
#define NS_ABDIRPROPERTY_CID \
|
||||
{ /* 6FD8EC67-3965-11d3-A316-001083003D0C */ \
|
||||
0x6fd8ec67, 0x3965, 0x11d3, \
|
||||
{0xa3, 0x16, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbDirectoryProperties
|
||||
//
|
||||
#define NS_ABDIRECTORYPROPERTIES_CONTRACTID \
|
||||
"@mozilla.org/addressbook/properties;1"
|
||||
#define NS_ABDIRECTORYPROPERTIES_CID \
|
||||
{ /* 8b00a972-1dd2-11b2-9d9c-9c377a9c3dba */ \
|
||||
0x8b00a972, 0x1dd2, 0x11b2, \
|
||||
{0x9d, 0x9c, 0x9c, 0x37, 0x7a, 0x9c, 0x3d, 0xba} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbAddressCollector
|
||||
//
|
||||
#define NS_ABADDRESSCOLLECTOR_CONTRACTID \
|
||||
"@mozilla.org/addressbook/services/addressCollector;1"
|
||||
#define NS_ABADDRESSCOLLECTOR_CID \
|
||||
{ /* e7702d5a-99d8-4648-bab7-919ea29f30b6 */ \
|
||||
0xe7702d5a, 0x99d8, 0x4648, \
|
||||
{0xba, 0xb7, 0x91, 0x9e, 0xa2, 0x9f, 0x30, 0xb6} \
|
||||
}
|
||||
|
||||
//
|
||||
// addbook URL
|
||||
//
|
||||
#define NS_ADDBOOKURL_CONTRACTID \
|
||||
"@mozilla.org/addressbook/services/url;1?type=addbook"
|
||||
|
||||
#define NS_ADDBOOKURL_CID \
|
||||
{ /* ff04c8e6-501e-11d3-a527-0060b0fc0444 */ \
|
||||
0xff04c8e6, 0x501e, 0x11d3, \
|
||||
{0xa5, 0x27, 0x0, 0x60, 0xb0, 0xfc, 0x4, 0x44} \
|
||||
}
|
||||
|
||||
//
|
||||
// addbook Protocol Handler
|
||||
//
|
||||
#define NS_ADDBOOK_HANDLER_CONTRACTID \
|
||||
"@mozilla.org/addressbook/services/addbook;1"
|
||||
#define NS_ADDBOOK_HANDLER_CID \
|
||||
{ /* ff04c8e6-501e-11d3-ffcc-0060b0fc0444 */ \
|
||||
0xff04c8e6, 0x501e, 0x11d3, \
|
||||
{0xff, 0xcc, 0x0, 0x60, 0xb0, 0xfc, 0x4, 0x44} \
|
||||
}
|
||||
|
||||
//
|
||||
// directory factory service
|
||||
//
|
||||
#define NS_ABDIRFACTORYSERVICE_CONTRACTID \
|
||||
"@mozilla.org/addressbook/directory-factory-service;1"
|
||||
|
||||
#define NS_ABDIRFACTORYSERVICE_CID \
|
||||
{ /* {F8B212F2-742B-4A48-B7A0-4C44D4DDB121}*/ \
|
||||
0xF8B212F2, 0x742B, 0x4A48, \
|
||||
{0xB7, 0xA0, 0x4C, 0x44, 0xD4, 0xDD, 0xB1, 0x21} \
|
||||
}
|
||||
|
||||
//
|
||||
// mdb directory factory
|
||||
//
|
||||
#define NS_ABMDBDIRECTORY "moz-abmdbdirectory"
|
||||
|
||||
#define NS_ABMDBDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX NS_ABMDBDIRECTORY
|
||||
|
||||
#define NS_ABMDBDIRFACTORY_CID \
|
||||
{ /* {E1CB9C8A-722D-43E4-9D7B-7CCAE4B0338A}*/ \
|
||||
0xE1CB9C8A, 0x722D, 0x43E4, \
|
||||
{0x9D, 0x7B, 0x7C, 0xCA, 0xE4, 0xB0, 0x33, 0x8A} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbMDBDirectory
|
||||
//
|
||||
#define NS_ABMDBDIRECTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX NS_ABMDBDIRECTORY
|
||||
|
||||
#define NS_ABMDBDIRECTORY_CID \
|
||||
{ /* {e618f894-1dd1-11b2-889c-9aaefaa90dde}*/ \
|
||||
0xe618f894, 0x1dd1, 0x11b2, \
|
||||
{0x88, 0x9c, 0x9a, 0xae, 0xfa, 0xa9, 0x0d, 0xde} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbMDBCard
|
||||
//
|
||||
#define NS_ABMDBCARD_CONTRACTID \
|
||||
"@mozilla.org/addressbook/moz-abmdbcard;1"
|
||||
|
||||
#define NS_ABMDBCARD_CID \
|
||||
{ /* {f578a5d2-1dd1-11b2-8841-f45cc5e765f8} */ \
|
||||
0xf578a5d2, 0x1dd1, 0x11b2, \
|
||||
{0x88, 0x41, 0xf4, 0x5c, 0xc5, 0xe7, 0x65, 0xf8} \
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
//
|
||||
// nsAbOutlookDirectory
|
||||
//
|
||||
#define NS_ABOUTLOOKDIRECTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX "moz-aboutlookdirectory"
|
||||
|
||||
#define NS_ABOUTLOOKDIRECTORY_CID \
|
||||
{ /* {9cc57822-0599-4c47-a399-1c6fa185a05c}*/ \
|
||||
0x9cc57822, 0x0599, 0x4c47, \
|
||||
{0xa3, 0x99, 0x1c, 0x6f, 0xa1, 0x85, 0xa0, 0x5c} \
|
||||
}
|
||||
|
||||
//
|
||||
// Outlook directory factory
|
||||
//
|
||||
#define NS_ABOUTLOOKDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX "moz-aboutlookdirectory"
|
||||
|
||||
#define NS_ABOUTLOOKDIRFACTORY_CID \
|
||||
{ /* {558ccc0f-2681-4dac-a066-debd8d26faf6}*/ \
|
||||
0x558ccc0f, 0x2681, 0x4dac, \
|
||||
{0xa0, 0x66, 0xde, 0xbd, 0x8d, 0x26, 0xfa, 0xf6} \
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Addressbook Query support
|
||||
//
|
||||
|
||||
#define NS_ABDIRECTORYQUERYARGUMENTS_CONTRACTID \
|
||||
"@mozilla.org/addressbook/directory/query-arguments;1"
|
||||
|
||||
#define NS_ABDIRECTORYQUERYARGUMENTS_CID \
|
||||
{ /* {f7dc2aeb-8e62-4750-965c-24b9e09ed8d2} */ \
|
||||
0xf7dc2aeb, 0x8e62, 0x4750, \
|
||||
{ 0x96, 0x5c, 0x24, 0xb9, 0xe0, 0x9e, 0xd8, 0xd2 } \
|
||||
}
|
||||
|
||||
|
||||
#define NS_BOOLEANCONDITIONSTRING_CONTRACTID \
|
||||
"@mozilla.org/boolean-expression/condition-string;1"
|
||||
|
||||
#define NS_BOOLEANCONDITIONSTRING_CID \
|
||||
{ /* {ca1944a9-527e-4c77-895d-d0466dd41cf5} */ \
|
||||
0xca1944a9, 0x527e, 0x4c77, \
|
||||
{ 0x89, 0x5d, 0xd0, 0x46, 0x6d, 0xd4, 0x1c, 0xf5 } \
|
||||
}
|
||||
|
||||
|
||||
#define NS_BOOLEANEXPRESSION_CONTRACTID \
|
||||
"@mozilla.org/boolean-expression/n-peer;1"
|
||||
|
||||
#define NS_BOOLEANEXPRESSION_CID \
|
||||
{ /* {2c2e75c8-6f56-4a50-af1c-72af5d0e8d41} */ \
|
||||
0x2c2e75c8, 0x6f56, 0x4a50, \
|
||||
{ 0xaf, 0x1c, 0x72, 0xaf, 0x5d, 0x0e, 0x8d, 0x41 } \
|
||||
}
|
||||
|
||||
#define NS_ABDIRECTORYQUERYPROXY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/directory-query/proxy;1"
|
||||
|
||||
#define NS_ABDIRECTORYQUERYPROXY_CID \
|
||||
{ /* {E162E335-541B-43B4-AAEA-FE591E240CAF}*/ \
|
||||
0xE162E335, 0x541B, 0x43B4, \
|
||||
{0xAA, 0xEA, 0xFE, 0x59, 0x1E, 0x24, 0x0C, 0xAF} \
|
||||
}
|
||||
|
||||
// nsAbLDAPDirectory
|
||||
//
|
||||
#define NS_ABLDAPDIRECTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX "moz-abldapdirectory"
|
||||
|
||||
#define NS_ABLDAPDIRECTORY_CID \
|
||||
{ /* {783E2777-66D7-4826-9E4B-8AB58C228A52}*/ \
|
||||
0x783E2777, 0x66D7, 0x4826, \
|
||||
{0x9E, 0x4B, 0x8A, 0xB5, 0x8C, 0x22, 0x8A, 0x52} \
|
||||
}
|
||||
|
||||
// nsAbLDAPDirectoryQuery
|
||||
//
|
||||
#define NS_ABLDAPDIRECTORYQUERY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-directory-query;1"
|
||||
|
||||
#define NS_ABLDAPDIRECTORYQUERY_CID \
|
||||
{ /* {783E2777-66D7-4826-9E4B-8AB58C228A53}*/ \
|
||||
0x783E2777, 0x66D7, 0x4826, \
|
||||
{0x9E, 0x4B, 0x8A, 0xB5, 0x8C, 0x22, 0x8A, 0x53} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbLDAPCard
|
||||
//
|
||||
#define NS_ABLDAPCARD_CONTRACTID \
|
||||
"@mozilla.org/addressbook/moz-abldapcard"
|
||||
|
||||
#define NS_ABLDAPCARD_CID \
|
||||
{ /* {10307B01-EBD6-465F-B972-1630410F70E6}*/ \
|
||||
0x10307B01, 0xEBD6, 0x465F, \
|
||||
{0xB9, 0x72, 0x16, 0x30, 0x41, 0x0F, 0x70, 0xE6} \
|
||||
}
|
||||
|
||||
//
|
||||
// LDAP directory factory
|
||||
//
|
||||
#define NS_ABLDAPDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX "moz-abldapdirectory"
|
||||
|
||||
#define NS_ABLDAPDIRFACTORY_CID \
|
||||
{ /* {8e3701af-8828-426c-84ac-124825c778f8} */ \
|
||||
0x8e3701af, 0x8828, 0x426c, \
|
||||
{0x84, 0xac, 0x12, 0x48, 0x25, 0xc7, 0x78, 0xf8} \
|
||||
}
|
||||
|
||||
//
|
||||
// LDAP autocomplete directory factory
|
||||
//
|
||||
#define NS_ABLDAPACDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX "ldap"
|
||||
#define NS_ABLDAPSACDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX "ldaps"
|
||||
|
||||
// nsAbLDAPAutoCompFormatter
|
||||
|
||||
// 4e276d6d-9981-46b4-9070-92f344ac5f5a
|
||||
//
|
||||
#define NS_ABLDAPAUTOCOMPFORMATTER_CID \
|
||||
{ 0x4e276d6d, 0x9981, 0x46b4, \
|
||||
{ 0x90, 0x70, 0x92, 0xf3, 0x44, 0xac, 0x5f, 0x5a }}
|
||||
|
||||
#define NS_ABLDAPAUTOCOMPFORMATTER_CONTRACTID \
|
||||
"@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"
|
||||
|
||||
|
||||
// nsAbLDAPReplicationService
|
||||
//
|
||||
// {ece81280-2639-11d6-b791-00b0d06e5f27}
|
||||
//
|
||||
#define NS_ABLDAP_REPLICATIONSERVICE_CID \
|
||||
{0xece81280, 0x2639, 0x11d6, \
|
||||
{ 0xb7, 0x91, 0x00, 0xb0, 0xd0, 0x6e, 0x5f, 0x27 }}
|
||||
|
||||
#define NS_ABLDAP_REPLICATIONSERVICE_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-replication-service;1"
|
||||
|
||||
// nsAbLDAPReplicationQuery
|
||||
//
|
||||
// {5414fff0-263b-11d6-b791-00b0d06e5f27}
|
||||
//
|
||||
#define NS_ABLDAP_REPLICATIONQUERY_CID \
|
||||
{0x5414fff0, 0x263b, 0x11d6, \
|
||||
{ 0xb7, 0x91, 0x00, 0xb0, 0xd0, 0x6e, 0x5f, 0x27 }}
|
||||
|
||||
#define NS_ABLDAP_REPLICATIONQUERY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-replication-query;1"
|
||||
|
||||
|
||||
// nsAbLDAPChangeLogQuery
|
||||
//
|
||||
// {63E11D51-3C9B-11d6-B7B9-00B0D06E5F27}
|
||||
#define NS_ABLDAP_CHANGELOGQUERY_CID \
|
||||
{0x63e11d51, 0x3c9b, 0x11d6, \
|
||||
{ 0xb7, 0xb9, 0x0, 0xb0, 0xd0, 0x6e, 0x5f, 0x27 }}
|
||||
|
||||
#define NS_ABLDAP_CHANGELOGQUERY_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-changelog-query;1"
|
||||
|
||||
// nsAbLDAPProcessReplicationData
|
||||
//
|
||||
// {5414fff1-263b-11d6-b791-00b0d06e5f27}
|
||||
//
|
||||
#define NS_ABLDAP_PROCESSREPLICATIONDATA_CID \
|
||||
{0x5414fff1, 0x263b, 0x11d6, \
|
||||
{ 0xb7, 0x91, 0x00, 0xb0, 0xd0, 0x6e, 0x5f, 0x27 }}
|
||||
|
||||
#define NS_ABLDAP_PROCESSREPLICATIONDATA_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-process-replication-data;1"
|
||||
|
||||
|
||||
// nsAbLDAPProcessChangeLogData
|
||||
//
|
||||
// {63E11D52-3C9B-11d6-B7B9-00B0D06E5F27}
|
||||
#define NS_ABLDAP_PROCESSCHANGELOGDATA_CID \
|
||||
{0x63e11d52, 0x3c9b, 0x11d6, \
|
||||
{0xb7, 0xb9, 0x0, 0xb0, 0xd0, 0x6e, 0x5f, 0x27 }}
|
||||
|
||||
#define NS_ABLDAP_PROCESSCHANGELOGDATA_CONTRACTID \
|
||||
"@mozilla.org/addressbook/ldap-process-changelog-data;1"
|
||||
|
||||
// nsABView
|
||||
|
||||
#define NS_ABVIEW_CID \
|
||||
{ 0xc5eb5d6a, 0x1dd1, 0x11b2, \
|
||||
{ 0xa0, 0x25, 0x94, 0xd1, 0x18, 0x1f, 0xc5, 0x9c }}
|
||||
|
||||
#define NS_ABVIEW_CONTRACTID \
|
||||
"@mozilla.org/addressbook/abview;1"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
//
|
||||
// nsAbOSXDirectory
|
||||
//
|
||||
#define NS_ABOSXDIRECTORY_PREFIX "moz-abosxdirectory"
|
||||
#define NS_ABOSXCARD_PREFIX "moz-abosxcard"
|
||||
|
||||
#define NS_ABOSXDIRECTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX NS_ABOSXDIRECTORY_PREFIX
|
||||
|
||||
#define NS_ABOSXDIRECTORY_CID \
|
||||
{ /* {83781cc6-c682-11d6-bdeb-0005024967b8}*/ \
|
||||
0x83781cc6, 0xc682, 0x11d6, \
|
||||
{0xbd, 0xeb, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
|
||||
}
|
||||
|
||||
//
|
||||
// nsAbOSXCard
|
||||
//
|
||||
#define NS_ABOSXCARD_CONTRACTID \
|
||||
NS_AB_DIRECTORY_TYPE_CONTRACTID_PREFIX NS_ABOSXCARD_PREFIX
|
||||
|
||||
#define NS_ABOSXCARD_CID \
|
||||
{ /* {89bbf582-c682-11d6-bc9d-0005024967b8}*/ \
|
||||
0x89bbf582, 0xc682, 0x11d6, \
|
||||
{0xbc, 0x9d, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
|
||||
}
|
||||
|
||||
//
|
||||
// OS X directory factory
|
||||
//
|
||||
#define NS_ABOSXDIRFACTORY_CONTRACTID \
|
||||
NS_AB_DIRECTORY_FACTORY_CONTRACTID_PREFIX NS_ABOSXDIRECTORY_PREFIX
|
||||
|
||||
#define NS_ABOSXDIRFACTORY_CID \
|
||||
{ /* {90efe2fe-c682-11d6-9c83-0005024967b8}*/ \
|
||||
0x90efe2fe, 0xc682, 0x11d6, \
|
||||
{0x9c, 0x83, 0x00, 0x05, 0x02, 0x49, 0x67, 0xb8} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NS_MSGVCARDSERVICE_CID \
|
||||
{ 0x3c4ac0da, 0x2cda, 0x4018, \
|
||||
{ 0x95, 0x51, 0xe1, 0x58, 0xb2, 0xe1, 0x22, 0xd3 }}
|
||||
|
||||
#define NS_MSGVCARDSERVICE_CONTRACTID \
|
||||
"@mozilla.org/addressbook/msgvcardservice;1"
|
||||
|
||||
#define NS_ABLDIFSERVICE_CID \
|
||||
{ 0xdb6f46da, 0x8de3, 0x478d, \
|
||||
{ 0xb5, 0x39, 0x80, 0x13, 0x98, 0x65, 0x6c, 0xf6 }}
|
||||
|
||||
#define NS_ABLDIFSERVICE_CONTRACTID \
|
||||
"@mozilla.org/addressbook/abldifservice;1"
|
||||
|
||||
#endif // nsAbBaseCID_h__
|
||||
58
mailnews/addrbook/public/nsIAbAddressCollector.idl
Normal file
58
mailnews/addrbook/public/nsIAbAddressCollector.idl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: IDL; 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 "nsISupports.idl"
|
||||
|
||||
interface nsIAbCard;
|
||||
|
||||
/**
|
||||
* nsIAbAddressCollector is the interface to the address collecter service.
|
||||
* It will save and update the supplied addresses into the address book
|
||||
* specified by the "mail.collect_addressbook" pref.
|
||||
*/
|
||||
[scriptable, uuid(069d3fba-37d4-4158-b401-a8efaeea0b66)]
|
||||
interface nsIAbAddressCollector : nsISupports {
|
||||
/**
|
||||
* Collects email addresses into the address book.
|
||||
* If a card already exists for the email, the first/last/display names
|
||||
* will be updated if they are supplied alongside the address.
|
||||
* If a card does not exist for the email it will be created if aCreateCard
|
||||
* is true.
|
||||
*
|
||||
* @param aAddresses The list of emails (in standard header format)
|
||||
* to collect into the address book.
|
||||
* @param aCreateCard Set to true if a card should be created if the
|
||||
* email address doesn't exist.
|
||||
* @param aSendFormat The send format to save for the card. See
|
||||
* nsIAbPreferMailFormat for values. If updating a card
|
||||
* this value will only be changed if the current value
|
||||
* for the card is "unknown".
|
||||
*/
|
||||
void collectAddress(in AUTF8String aAddresses, in boolean aCreateCard,
|
||||
in unsigned long aSendFormat);
|
||||
|
||||
/**
|
||||
* Collects a single name and email address into the address book.
|
||||
* By default, it saves the address without checking for an existing one.
|
||||
* See collectAddress for the general implementation.
|
||||
*
|
||||
* @param aEmail The email address to collect.
|
||||
* @param aDisplayName The display name associated with the email address.
|
||||
* @param aCreateCard Set to true if a card should be created if the
|
||||
* email address doesn't exist (ignored if
|
||||
* aSkipCheckExisting is true).
|
||||
* @param aSendFormat The send format to save for the card. See
|
||||
* nsIAbPreferMailFormat for values. If updating a card
|
||||
* this value will only be changed if the current value
|
||||
* for the card is "unknown".
|
||||
* @param aSkipCheckExisting Optional parameter, if this is set then the
|
||||
* implementation will skip checking for an
|
||||
* existing card, and just create a new card.
|
||||
*/
|
||||
void collectSingleAddress(in AUTF8String aEmail, in AUTF8String aDisplayName,
|
||||
in boolean aCreateCard,
|
||||
in unsigned long aSendFormat,
|
||||
[optional] in boolean aSkipCheckExisting);
|
||||
};
|
||||
36
mailnews/addrbook/public/nsIAbAutoCompleteResult.idl
Normal file
36
mailnews/addrbook/public/nsIAbAutoCompleteResult.idl
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/. */
|
||||
|
||||
#include "nsIAutoCompleteResult.idl"
|
||||
|
||||
interface nsIAbCard;
|
||||
|
||||
/**
|
||||
* This interface is used to extend the nsIAutoCompleteResult interface to
|
||||
* provide extra facilities for obtaining more details of the results of
|
||||
* an address book search.
|
||||
*/
|
||||
[scriptable, uuid(c0d35623-f719-4e43-ae24-573e393f87f9)]
|
||||
interface nsIAbAutoCompleteResult : nsIAutoCompleteResult {
|
||||
/**
|
||||
* Get the card from the result at the given index
|
||||
*/
|
||||
nsIAbCard getCardAt(in long index);
|
||||
|
||||
/**
|
||||
* Gets the email to use for the card within the result at the given index.
|
||||
* This is the email that was matched against for the card where there are
|
||||
* multiple email addresses on a card.
|
||||
*
|
||||
* @param index Index of the autocomplete result to return the value for.
|
||||
* @result The email address to use from the card.
|
||||
*/
|
||||
AString getEmailToUse(in long index);
|
||||
|
||||
/**
|
||||
* The template used to build the query for this search. Optional.
|
||||
*/
|
||||
attribute AString modelQuery;
|
||||
};
|
||||
122
mailnews/addrbook/public/nsIAbBooleanExpression.idl
Normal file
122
mailnews/addrbook/public/nsIAbBooleanExpression.idl
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIArray;
|
||||
typedef long nsAbBooleanConditionType;
|
||||
|
||||
/**
|
||||
* Condition types
|
||||
*
|
||||
* Constants defining the types of condition
|
||||
* to obtain a boolean result of TRUE or FALSE
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(F51387B1-5AEF-4A1C-830E-7CD3B02366CE)]
|
||||
interface nsIAbBooleanConditionTypes
|
||||
{
|
||||
const long Exists = 0;
|
||||
const long DoesNotExist = 1;
|
||||
const long Contains = 2;
|
||||
const long DoesNotContain = 3;
|
||||
const long Is = 4;
|
||||
const long IsNot = 5;
|
||||
const long BeginsWith = 6;
|
||||
const long EndsWith = 7;
|
||||
const long LessThan = 8;
|
||||
const long GreaterThan = 9;
|
||||
const long SoundsLike = 10;
|
||||
const long RegExp = 11;
|
||||
};
|
||||
|
||||
|
||||
typedef long nsAbBooleanOperationType;
|
||||
|
||||
/*
|
||||
* Operation types
|
||||
*
|
||||
* Constants defining the boolean operation that
|
||||
* should be performed between two boolean expressions
|
||||
*
|
||||
*/
|
||||
[uuid(9bdd2e51-2be4-49a4-a558-36d1a812231a)]
|
||||
interface nsIAbBooleanOperationTypes
|
||||
{
|
||||
const long AND = 0;
|
||||
const long OR = 1;
|
||||
const long NOT = 2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* String condition
|
||||
*
|
||||
* A string condition represents a leaf node in a
|
||||
* boolean expression tree and represents
|
||||
* test which will return TRUE or FALSE
|
||||
*
|
||||
* Condition is an expression which is a
|
||||
* leaf node in a boolean expression tree
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(C3869D72-CFD0-45F0-A0EC-3F67D83C7110)]
|
||||
interface nsIAbBooleanConditionString : nsISupports
|
||||
{
|
||||
/**
|
||||
* The condition for how the a value
|
||||
* should be compared
|
||||
*
|
||||
*/
|
||||
attribute nsAbBooleanConditionType condition;
|
||||
|
||||
/**
|
||||
* The lhs of the condition
|
||||
*
|
||||
* Represents a property name which
|
||||
* should be evaluated to obtain the
|
||||
* lhs.
|
||||
*
|
||||
*/
|
||||
attribute string name;
|
||||
|
||||
/**
|
||||
* The rhs of the condition
|
||||
*
|
||||
* <name> [condition] value
|
||||
*
|
||||
*/
|
||||
attribute wstring value;
|
||||
};
|
||||
|
||||
/**
|
||||
* N Boolean expression type
|
||||
*
|
||||
* Supports Unary Binary and N boolean expressions
|
||||
*
|
||||
* An operation represents a node in a boolean
|
||||
* expression tree which may contain one or more
|
||||
* child conditions or expressions
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(223a9462-1aeb-4c1f-b069-5fc6278989b2)]
|
||||
interface nsIAbBooleanExpression: nsISupports
|
||||
{
|
||||
/**
|
||||
* The boolean operation to be applied to
|
||||
* results of all evaluated expressions
|
||||
*
|
||||
*/
|
||||
attribute nsAbBooleanOperationType operation;
|
||||
|
||||
/**
|
||||
* List of peer expressions
|
||||
*
|
||||
* e1 [op] e2 [op] .... en
|
||||
*
|
||||
*/
|
||||
attribute nsIArray expressions;
|
||||
};
|
||||
|
||||
358
mailnews/addrbook/public/nsIAbCard.idl
Normal file
358
mailnews/addrbook/public/nsIAbCard.idl
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 "nsIAbItem.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(97448252-F189-11d4-A422-001083003D0C)]
|
||||
interface nsIAbPreferMailFormat {
|
||||
const unsigned long unknown = 0;
|
||||
const unsigned long plaintext = 1;
|
||||
const unsigned long html = 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface representing an address book card.
|
||||
*
|
||||
* The UUID of a card is a composition of a directory ID and a per-directory ID.
|
||||
* The per-directory ID is reflected in the localId property. If either of these
|
||||
* properties change, the UUID will change correspondingly.
|
||||
*
|
||||
* None of these IDs will be reflected in the property collection. Neither
|
||||
* nsIAbCard::properties, nsIAbCard::deleteProperty, nor any of the property
|
||||
* getters and setters are able to interact with these properties.
|
||||
*
|
||||
* Fundamentally, a card is a collection of properties. Modifying a property in
|
||||
* some way on a card does not change the backend used to store the card; the
|
||||
* directory is required to do make the changes here.
|
||||
*
|
||||
* The following are the core properties that are used:
|
||||
* - Names:
|
||||
* - FirstName, LastName
|
||||
* - PhoneticFirstName, PhoneticLastName
|
||||
* - DisplayName, NickName
|
||||
* - SpouseName, FamilyName
|
||||
* - PrimaryEmail, SecondEmail
|
||||
* - Home Contact:
|
||||
* - HomeAddress, HomeAddress2, HomeCity, HomeState, HomeZipCode, HomeCountry
|
||||
* - HomePhone, HomePhoneType
|
||||
* - Work contact. Same as home, but with `Work' instead of `Home'
|
||||
* - Other Contact:
|
||||
* - FaxNumber, FaxNumberType
|
||||
* - PagerNumber, PagerNumberType
|
||||
* - CellularNumber, CellularNumberType
|
||||
* - JobTitle, Department, Company
|
||||
* - _AimScreenName
|
||||
* - Dates:
|
||||
* - AnniversaryYear, AnniversaryMonth, AnniversaryDay
|
||||
* - BirthYear, BirthMonth, BirthDay
|
||||
* - WebPage1 (work), WebPage2 (home)
|
||||
* - Custom1, Custom2, Custom3, Custom4
|
||||
* - Notes
|
||||
* - Integral properties:
|
||||
* - LastModifiedDate
|
||||
* - PopularityIndex
|
||||
* - PreferMailFormat (see nsIAbPreferMailFormat)
|
||||
* - Photo properties:
|
||||
* - PhotoName
|
||||
* - PhotoType
|
||||
* - PhotoURI
|
||||
*
|
||||
* The contract id for the standard implementation is
|
||||
* <tt>\@mozilla.org/addressbook/cardproperty;1</tt>.
|
||||
*/
|
||||
[scriptable, uuid(9bddf024-5178-4097-894e-d84b4ddde101)]
|
||||
interface nsIAbCard : nsIAbItem {
|
||||
/**
|
||||
* The UUID for the nsIAbDirectory containing this card.
|
||||
*
|
||||
* The directory considered to contain this card is the directory which
|
||||
* produced this card (e.g., through nsIAbDirectory::getCardForProperty) or
|
||||
* the last directory to modify this card, if another directory did so. If the
|
||||
* last directory to modify this card deleted it, then this card is considered
|
||||
* unassociated.
|
||||
*
|
||||
* If this card is not associated with a directory, this string will be empty.
|
||||
*
|
||||
* There is no standardized way to associate a card with multiple directories.
|
||||
*
|
||||
* Consumers of this interface outside of directory implementations SHOULD
|
||||
* NOT, in general, modify this property.
|
||||
*/
|
||||
attribute AUTF8String directoryId;
|
||||
|
||||
/**
|
||||
* The per-directory ID of this card.
|
||||
*
|
||||
* This property is the second part of the tuple logically representing a card
|
||||
* UUID. It shares many requirements with that of nsIAbItem::uuid. In
|
||||
* particular:
|
||||
* - It MUST be unique (within the scope of its directory).
|
||||
* - The empty string MUST only be used to indicate that it has not yet been
|
||||
* assigned a localId.
|
||||
* - It is STRONGLY RECOMMENDED that this id is consistent across sessions and
|
||||
* that, should the card be deleted, its ids will not be reused.
|
||||
* - The format of localId is left undefined.
|
||||
*
|
||||
* As long as directoryId is not changed, this property SHOULD NOT be changed.
|
||||
* If directoryId is changed, the new directory MAY choose to reuse the same
|
||||
* localId if reasonable. However, consumers MUST NOT assume that two cards
|
||||
* with different directoryIds but the same localId are logically the same
|
||||
* card.
|
||||
*
|
||||
* Similar to directoryId, consumers of cards outside of directory
|
||||
* implementations SHOULD NOT, in general, modify this property.
|
||||
*/
|
||||
attribute AUTF8String localId;
|
||||
|
||||
/**
|
||||
* A list of all the properties that this card has as an enumerator, whose
|
||||
* members are all nsIProperty objects.
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator properties;
|
||||
|
||||
/**
|
||||
* Returns a property for the given name.
|
||||
*
|
||||
* @param name The case-sensitive name of the property to get.
|
||||
* @param defaultValue The value to return if the property does not exist.
|
||||
* @exception NS_ERROR_NOT_AVAILABLE if the named property does not exist.
|
||||
* @exception NS_ERROR_CANNOT_CONVERT_DATA if the property cannot be converted
|
||||
* to the desired type.
|
||||
*/
|
||||
nsIVariant getProperty(in AUTF8String name, in nsIVariant defaultValue);
|
||||
/**
|
||||
* @{
|
||||
* Returns a property for the given name. Javascript callers should NOT use these,
|
||||
* but use getProperty instead. XPConnect will do the type conversion automagically.
|
||||
*
|
||||
* These functions convert values in the same manner as the default
|
||||
* implementation of nsIVariant. Of particular note is that boolean variables
|
||||
* are converted to integers as in C/C++ (true is a non-zero value), so that
|
||||
* false will be converted to a string of "0" and not "false."
|
||||
*
|
||||
*
|
||||
* @param name The case-sensitive name of the property to get.
|
||||
* @exception NS_ERROR_NOT_AVAILABLE if the named property does not exist.
|
||||
* @exception NS_ERROR_CANNOT_CONVERT_DATA if the property cannot be converted
|
||||
* to the desired type.
|
||||
*/
|
||||
AString getPropertyAsAString(in string name);
|
||||
AUTF8String getPropertyAsAUTF8String(in string name);
|
||||
unsigned long getPropertyAsUint32(in string name);
|
||||
boolean getPropertyAsBool(in string name);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Assigns the given to value to the property of the given name.
|
||||
*
|
||||
* Should the property exist, its value will be overwritten. An
|
||||
* implementation may impose additional semantic constraints for certain
|
||||
* properties. However, such constraints might not be checked by this method.
|
||||
*
|
||||
* @warning A value MUST be convertible to a string; if this convention is not
|
||||
* followed, consumers of cards may fail unpredictably or return incorrect
|
||||
* results.
|
||||
*
|
||||
* @param name The case-sensitive name of the property to set.
|
||||
* @param value The new value of the property.
|
||||
*/
|
||||
void setProperty(in AUTF8String name, in nsIVariant value);
|
||||
|
||||
/**
|
||||
* @{
|
||||
* Sets a property for the given name. Javascript callers should NOT use these,
|
||||
* but use setProperty instead. XPConnect will do the type conversion automagically.
|
||||
*
|
||||
* These functions convert values in the same manner as the default
|
||||
* implementation of nsIVariant.
|
||||
*/
|
||||
void setPropertyAsAString(in string name, in AString value);
|
||||
void setPropertyAsAUTF8String(in string name, in AUTF8String value);
|
||||
void setPropertyAsUint32(in string name, in unsigned long value);
|
||||
void setPropertyAsBool(in string name, in boolean value);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Deletes the property with the given name.
|
||||
*
|
||||
* Some properties may not be deleted. However, the implementation will not
|
||||
* check this constraint at this method. If such a property is deleted, an
|
||||
* error may be thrown when the card is modified at the database level.
|
||||
*
|
||||
* @param name The case-sensitive name of the property to set.
|
||||
*/
|
||||
void deleteProperty(in AUTF8String name);
|
||||
|
||||
/**
|
||||
* @{
|
||||
* These properties are shorthand for getProperty and setProperty.
|
||||
*/
|
||||
attribute AString firstName;
|
||||
attribute AString lastName;
|
||||
attribute AString displayName;
|
||||
attribute AString primaryEmail;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Determines whether or not a card has the supplied email address in either
|
||||
* of its PrimaryEmail or SecondEmail attributes.
|
||||
*
|
||||
* Note: This function is likely to be temporary whilst we work out proper
|
||||
* APIs for multi-valued attributes in bug 118665.
|
||||
*
|
||||
* @param aEmailAddress The email address to attempt to match against.
|
||||
* @return True if aEmailAddress matches any of the email
|
||||
* addresses stored in the card.
|
||||
*/
|
||||
boolean hasEmailAddress(in AUTF8String aEmailAddress);
|
||||
|
||||
/**
|
||||
* Translates a card into a specific format.
|
||||
* The following types are supported:
|
||||
* - base64xml
|
||||
* - xml
|
||||
* - vcard
|
||||
*
|
||||
* @param aType The type of item to translate the card into.
|
||||
* @return A string containing the translated card.
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE if we do not recognize the type.
|
||||
*/
|
||||
AUTF8String translateTo(in AUTF8String aType);
|
||||
|
||||
/**
|
||||
* Translates a card from the specified format
|
||||
*/
|
||||
//void translateFrom(in AUTF8String aType, in AUTF8String aData);
|
||||
|
||||
/**
|
||||
* Generate a phonetic name from the card, using the firstName and lastName
|
||||
* values.
|
||||
*
|
||||
* @param aLastNameFirst Set to True to put the last name before the first.
|
||||
* @return A string containing the generated phonetic name.
|
||||
*/
|
||||
AString generatePhoneticName(in boolean aLastNameFirst);
|
||||
|
||||
/**
|
||||
* Generate a chat name from the card, containing the value of the
|
||||
* first non-empty chat field.
|
||||
*
|
||||
* @return A string containing the generated chat name.
|
||||
*/
|
||||
AString generateChatName();
|
||||
|
||||
/**
|
||||
* This function will copy all values from one card to another.
|
||||
*
|
||||
* @param srcCard The source card to copy values from.
|
||||
*/
|
||||
void copy(in nsIAbCard aSrcCard);
|
||||
|
||||
/**
|
||||
* Returns true if this card is equal to the other card.
|
||||
*
|
||||
* The default implementation defines equal as this card pointing to the
|
||||
* same object as @arg aCard; another implementation defines it as equality of
|
||||
* properties and values.
|
||||
*
|
||||
* @warning The exact nature of equality is still undefined, and actual
|
||||
* results may not match theoretical results. Most notably, the code
|
||||
* <tt>a.equals(b) == b.equals(a)</tt> might not return true. In
|
||||
* particular, calling equals on cards from different address books
|
||||
* may return inaccurate results.
|
||||
*
|
||||
*
|
||||
* @return Equality, as defined above.
|
||||
* @param aCard The card to compare against.
|
||||
*/
|
||||
boolean equals(in nsIAbCard aCard);
|
||||
|
||||
// PROPERTIES TO BE DELETED AS PART OF REWRITE
|
||||
|
||||
attribute boolean isMailList;
|
||||
/**
|
||||
* If isMailList is true then mailListURI
|
||||
* will contain the URI of the associated
|
||||
* mail list
|
||||
*/
|
||||
attribute string mailListURI;
|
||||
};
|
||||
|
||||
%{C++
|
||||
// A nice list of properties for the benefit of C++ clients
|
||||
#define kFirstNameProperty "FirstName"
|
||||
#define kLastNameProperty "LastName"
|
||||
#define kDisplayNameProperty "DisplayName"
|
||||
#define kNicknameProperty "NickName"
|
||||
#define kPriEmailProperty "PrimaryEmail"
|
||||
#define kPreferMailFormatProperty "PreferMailFormat"
|
||||
#define kLastModifiedDateProperty "LastModifiedDate"
|
||||
#define kPopularityIndexProperty "PopularityIndex"
|
||||
|
||||
#define kPhoneticFirstNameProperty "PhoneticFirstName"
|
||||
#define kPhoneticLastNameProperty "PhoneticLastName"
|
||||
#define kSpouseNameProperty "SpouseName"
|
||||
#define kFamilyNameProperty "FamilyName"
|
||||
#define k2ndEmailProperty "SecondEmail"
|
||||
|
||||
#define kHomeAddressProperty "HomeAddress"
|
||||
#define kHomeAddress2Property "HomeAddress2"
|
||||
#define kHomeCityProperty "HomeCity"
|
||||
#define kHomeStateProperty "HomeState"
|
||||
#define kHomeZipCodeProperty "HomeZipCode"
|
||||
#define kHomeCountryProperty "HomeCountry"
|
||||
#define kHomeWebPageProperty "WebPage2"
|
||||
|
||||
#define kWorkAddressProperty "WorkAddress"
|
||||
#define kWorkAddress2Property "WorkAddress2"
|
||||
#define kWorkCityProperty "WorkCity"
|
||||
#define kWorkStateProperty "WorkState"
|
||||
#define kWorkZipCodeProperty "WorkZipCode"
|
||||
#define kWorkCountryProperty "WorkCountry"
|
||||
#define kWorkWebPageProperty "WebPage1"
|
||||
|
||||
#define kHomePhoneProperty "HomePhone"
|
||||
#define kHomePhoneTypeProperty "HomePhoneType"
|
||||
#define kWorkPhoneProperty "WorkPhone"
|
||||
#define kWorkPhoneTypeProperty "WorkPhoneType"
|
||||
#define kFaxProperty "FaxNumber"
|
||||
#define kFaxTypeProperty "FaxNumberType"
|
||||
#define kPagerTypeProperty "PagerNumberType"
|
||||
#define kPagerProperty "PagerNumber"
|
||||
#define kCellularProperty "CellularNumber"
|
||||
#define kCellularTypeProperty "CellularNumberType"
|
||||
|
||||
#define kJobTitleProperty "JobTitle"
|
||||
#define kDepartmentProperty "Department"
|
||||
#define kCompanyProperty "Company"
|
||||
#define kScreenNameProperty "_AimScreenName"
|
||||
#define kCustom1Property "Custom1"
|
||||
#define kCustom2Property "Custom2"
|
||||
#define kCustom3Property "Custom3"
|
||||
#define kCustom4Property "Custom4"
|
||||
#define kNotesProperty "Notes"
|
||||
|
||||
#define kGtalkProperty "_GoogleTalk"
|
||||
#define kAIMProperty "_AimScreenName"
|
||||
#define kYahooProperty "_Yahoo"
|
||||
#define kSkypeProperty "_Skype"
|
||||
#define kQQProperty "_QQ"
|
||||
#define kMSNProperty "_MSN"
|
||||
#define kICQProperty "_ICQ"
|
||||
#define kXMPPProperty "_JabberId"
|
||||
#define kIRCProperty "_IRC"
|
||||
|
||||
#define kAnniversaryYearProperty "AnniversaryYear"
|
||||
#define kAnniversaryMonthProperty "AnniversaryMonth"
|
||||
#define kAnniversaryDayProperty "AnniversaryDay"
|
||||
#define kBirthYearProperty "BirthYear"
|
||||
#define kBirthMonthProperty "BirthMonth"
|
||||
#define kBirthDayProperty "BirthDay"
|
||||
%}
|
||||
92
mailnews/addrbook/public/nsIAbCollection.idl
Normal file
92
mailnews/addrbook/public/nsIAbCollection.idl
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/* -*- 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 "nsIAbItem.idl"
|
||||
|
||||
interface nsIAbCard;
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
/**
|
||||
* A collection of address book items.
|
||||
*/
|
||||
[scriptable, uuid(70f6123f-e06b-4101-9750-4ce73b38134b)]
|
||||
interface nsIAbCollection : nsIAbItem {
|
||||
|
||||
/**
|
||||
* Returns true if this collection is read-only.
|
||||
*/
|
||||
readonly attribute boolean readOnly;
|
||||
|
||||
/**
|
||||
* Returns true if this collection is accessed over a network connection.
|
||||
*/
|
||||
readonly attribute boolean isRemote;
|
||||
|
||||
/**
|
||||
* Returns true if this collection is accessed over a secure connection.
|
||||
*
|
||||
* If isRemote returns false, then this value MUST be false as well.
|
||||
*/
|
||||
readonly attribute boolean isSecure;
|
||||
|
||||
/**
|
||||
* Returns an address book card for the specified email address if found.
|
||||
*
|
||||
* If there are multiple cards with the given email address, this method will
|
||||
* return one of these cards in an implementation-defined manner.
|
||||
*
|
||||
* Matching is performed in a case-insensitive manner.
|
||||
*
|
||||
* This method performs a synchronous operation. If the collection cannot do
|
||||
* the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
|
||||
*
|
||||
* @param emailAddress The email address to find in any of the email address
|
||||
* fields. If emailAddress is empty, the database won't
|
||||
* be searched and the function will return as if no card
|
||||
* was found.
|
||||
* @return An nsIAbCard if one was found, else returns NULL.
|
||||
* @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
|
||||
*/
|
||||
nsIAbCard cardForEmailAddress(in AUTF8String emailAddress);
|
||||
|
||||
/**
|
||||
* Returns an address book card for the specified property if found.
|
||||
*
|
||||
* If there are multiple cards with the given value for the property, this
|
||||
* method will return one of these cards in an implementation-defined manner.
|
||||
*
|
||||
* This method performs a synchronous operation. If the collection cannot do
|
||||
* the search in such a manner, then it should throw NS_ERROR_NOT_IMPLEMENTED.
|
||||
*
|
||||
* If the property is not natively a string, it can still be searched for
|
||||
* using the string-encoded value of the property, e.g. "0". See
|
||||
* nsIAbCard::getPropertyAsAUTF8String for more information. Empty values will
|
||||
* return no match, to prevent spurious results.
|
||||
*
|
||||
* @param aProperty The property to look for.
|
||||
* @param aValue The value to search for.
|
||||
* @param aCaseSensitive True if matching should be done case-sensitively.
|
||||
* @result An nsIAbCard if one was found, else returns NULL.
|
||||
* @exception NS_ERROR_NOT_IMPLEMENTED If the collection cannot do this.
|
||||
*/
|
||||
nsIAbCard getCardFromProperty(in string aProperty, in AUTF8String aValue,
|
||||
in boolean aCaseSensitive);
|
||||
|
||||
/**
|
||||
* Returns all address book cards with a specific property matching value
|
||||
*
|
||||
* This function is almost identical to getCardFromProperty, with the
|
||||
* exception of returning all cards rather than just the first.
|
||||
*
|
||||
* @param aProperty The property to look for.
|
||||
* @param aValue The value to search for.
|
||||
* @param aCaseSensitive True if matching should be done case-sensitively.
|
||||
* @result A nsISimpleEnumerator that holds nsIAbCard
|
||||
* instances.
|
||||
*/
|
||||
nsISimpleEnumerator getCardsFromProperty(in string aProperty,
|
||||
in AUTF8String aValue,
|
||||
in boolean aCaseSensitive);
|
||||
};
|
||||
35
mailnews/addrbook/public/nsIAbDirFactory.idl
Normal file
35
mailnews/addrbook/public/nsIAbDirFactory.idl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
#include "nsISimpleEnumerator.idl"
|
||||
|
||||
interface nsIAbDirectory;
|
||||
|
||||
[scriptable, uuid(ad61b4fc-d8d8-40b2-b924-4c10f28a8a17)]
|
||||
interface nsIAbDirFactory : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get a top level address book directory and sub directories, given some
|
||||
* properties.
|
||||
*
|
||||
* @param aDirName Name of the address book
|
||||
*
|
||||
* @param aURI URI of the address book
|
||||
*
|
||||
* @param aPrefName Pref name for the preferences of the address book
|
||||
*
|
||||
* @return Enumeration of nsIAbDirectory interfaces
|
||||
*/
|
||||
nsISimpleEnumerator getDirectories(in AString aDirName, in ACString aURI,
|
||||
in ACString aPrefName);
|
||||
|
||||
/**
|
||||
* Delete a top level address book directory
|
||||
*
|
||||
*/
|
||||
void deleteDirectory (in nsIAbDirectory directory);
|
||||
};
|
||||
|
||||
28
mailnews/addrbook/public/nsIAbDirFactoryService.idl
Normal file
28
mailnews/addrbook/public/nsIAbDirFactoryService.idl
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/. */
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIAbDirFactory;
|
||||
|
||||
[scriptable, uuid(154a951b-a310-400c-b98f-d769cc5d575f)]
|
||||
interface nsIAbDirFactoryService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Obtain a directory factory component given a uri representing an address
|
||||
* book. The scheme is extracted from the uri and contract id is generated
|
||||
* of the form:
|
||||
* @mozilla.org/addressbook/directory-factory;1?name=<scheme>
|
||||
*
|
||||
* This id is used to instantiate a registered component which implemented
|
||||
* the nsIAbDirFactory interface.
|
||||
*
|
||||
* @param aURI The uri which contains the scheme that defines what directory
|
||||
* factory instance is returned
|
||||
*/
|
||||
nsIAbDirFactory getDirFactory(in ACString aURI);
|
||||
};
|
||||
|
||||
15
mailnews/addrbook/public/nsIAbDirSearchListener.idl
Normal file
15
mailnews/addrbook/public/nsIAbDirSearchListener.idl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIAbCard;
|
||||
|
||||
[scriptable, uuid(eafe2488-4efb-4ac8-a6b4-7756eb1650a3)]
|
||||
interface nsIAbDirSearchListener : nsISupports {
|
||||
void onSearchFinished(in long aResult, in AString aErrorMsg);
|
||||
|
||||
void onSearchFoundCard(in nsIAbCard aCard);
|
||||
};
|
||||
296
mailnews/addrbook/public/nsIAbDirectory.idl
Normal file
296
mailnews/addrbook/public/nsIAbDirectory.idl
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/* -*- 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 "nsIAbCollection.idl"
|
||||
#include "nsIAbCard.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIArray;
|
||||
interface nsIMutableArray;
|
||||
|
||||
/* moz-abdirectory:// is the URI to access nsAbBSDirectory,
|
||||
* which is the root directory for all types of address books
|
||||
* this is used to get all address book directories. */
|
||||
|
||||
%{C++
|
||||
#define kAllDirectoryRoot "moz-abdirectory://"
|
||||
|
||||
#define kPersonalAddressbook "abook.mab"
|
||||
#define kPersonalAddressbookUri "moz-abmdbdirectory://abook.mab"
|
||||
#define kCollectedAddressbook "history.mab"
|
||||
#define kCollectedAddressbookUri "moz-abmdbdirectory://history.mab"
|
||||
|
||||
#define kABFileName_PreviousSuffix ".na2" /* final v2 address book format */
|
||||
#define kABFileName_PreviousSuffixLen 4
|
||||
#define kABFileName_CurrentSuffix ".mab" /* v3 address book extension */
|
||||
%}
|
||||
|
||||
/**
|
||||
* A top-level address book directory.
|
||||
*
|
||||
* Please note that in order to be properly instantiated by nsIAbManager, every
|
||||
* type of nsIAbDirectory must have a contract ID of the form:
|
||||
*
|
||||
* @mozilla.org/addressbook/directory;1?type=<AB URI Scheme>
|
||||
*
|
||||
* Where AB URI Scheme does not include the ://. For example, for the Mork-based
|
||||
* address book, the scheme is "moz-abmdbdirectory", so the contract ID for
|
||||
* the Mork-based address book type is:
|
||||
*
|
||||
* @mozilla.org/addressbook/directory;1?type=moz-abmdbdirectory
|
||||
*
|
||||
* The UUID of an nsIAbDirectory is its preference ID and its name, concatenated
|
||||
* together.
|
||||
*/
|
||||
[scriptable, uuid(72dc868b-db5b-4daa-b6c6-071be4a05d02)]
|
||||
interface nsIAbDirectory : nsIAbCollection {
|
||||
|
||||
/**
|
||||
* The chrome URI to use for bringing up a dialog to edit this directory.
|
||||
* When opening the dialog, use a JS argument of
|
||||
* {selectedDirectory: thisdir} where thisdir is this directory that you just
|
||||
* got the chrome URI from.
|
||||
*/
|
||||
readonly attribute ACString propertiesChromeURI;
|
||||
|
||||
/**
|
||||
* The description of the directory. If this directory is not a mailing list,
|
||||
* then setting this attribute will send round a "DirName" update via
|
||||
* nsIAddrBookSession.
|
||||
*/
|
||||
attribute AString dirName;
|
||||
|
||||
// XXX This should really be replaced by a QI or something better
|
||||
readonly attribute long dirType;
|
||||
|
||||
// eliminated a bit more.
|
||||
|
||||
// The filename for address books within this directory.
|
||||
readonly attribute ACString fileName;
|
||||
|
||||
// The URI of the address book
|
||||
readonly attribute ACString URI;
|
||||
|
||||
// The position of the directory on the display.
|
||||
readonly attribute long position;
|
||||
|
||||
// will be used for LDAP replication
|
||||
attribute unsigned long lastModifiedDate;
|
||||
|
||||
// Defines whether this directory is a mail
|
||||
// list or not
|
||||
attribute boolean isMailList;
|
||||
|
||||
// Get the children directories
|
||||
readonly attribute nsISimpleEnumerator childNodes;
|
||||
|
||||
/**
|
||||
* Get the cards associated with the directory. This will return the cards
|
||||
* associated with the mailing lists too.
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator childCards;
|
||||
|
||||
/**
|
||||
* Returns true if this directory represents a query - i.e. the rdf resource
|
||||
* was something like moz-abmdbdirectory://abook.mab?....
|
||||
*/
|
||||
readonly attribute boolean isQuery;
|
||||
|
||||
/**
|
||||
* Initializes a directory, pointing to a particular
|
||||
* URI
|
||||
*/
|
||||
void init(in string aURI);
|
||||
|
||||
// Deletes either a mailing list or a top
|
||||
// level directory, which also updates the
|
||||
// preferences
|
||||
void deleteDirectory(in nsIAbDirectory directory);
|
||||
|
||||
// Check if directory contains card
|
||||
// If the implementation is asynchronous the card
|
||||
// may not yet have arrived. If it is in the process
|
||||
// of obtaining cards the method will throw an
|
||||
// NS_ERROR_NOT_AVAILABLE exception if the card
|
||||
// cannot be found.
|
||||
boolean hasCard(in nsIAbCard cards);
|
||||
|
||||
// Check if directory contains directory
|
||||
boolean hasDirectory(in nsIAbDirectory dir);
|
||||
|
||||
// Check if directory contains a mailinglist by name
|
||||
boolean hasMailListWithName(in wstring aName);
|
||||
|
||||
/**
|
||||
* Adds a card to the database.
|
||||
*
|
||||
* This card does not need to be of the same type as the database, e.g., one
|
||||
* can add an nsIAbLDAPCard to an nsIAbMDBDirectory.
|
||||
*
|
||||
* @return "Real" card (eg nsIAbLDAPCard) that can be used for some
|
||||
* extra functions.
|
||||
*/
|
||||
nsIAbCard addCard(in nsIAbCard card);
|
||||
|
||||
/**
|
||||
* Modifies a card in the database to match that supplied.
|
||||
*/
|
||||
void modifyCard(in nsIAbCard modifiedCard);
|
||||
|
||||
/**
|
||||
* Deletes the array of cards from the database.
|
||||
*
|
||||
* @param aCards The cards to delete from the database.
|
||||
*/
|
||||
void deleteCards(in nsIArray aCards);
|
||||
|
||||
void dropCard(in nsIAbCard card, in boolean needToCopyCard);
|
||||
|
||||
/**
|
||||
* Whether or not the directory should be searched when doing autocomplete,
|
||||
* (currently by using GetChildCards); LDAP does not support this in online
|
||||
* mode, so that should return false; additionally any other directory types
|
||||
* that also do not support GetChildCards should return false.
|
||||
*
|
||||
* @param aIdentity An optional parameter detailing the identity key (see
|
||||
* nsIMsgAccountManager) that this autocomplete is being
|
||||
* run against.
|
||||
* @return True if this directory should/can be used during
|
||||
* local autocomplete.
|
||||
*/
|
||||
boolean useForAutocomplete(in ACString aIdentityKey);
|
||||
|
||||
/**
|
||||
* Does this directory support mailing lists? Note that in the case
|
||||
* this directory is a mailing list and nested mailing lists are not
|
||||
* supported, this will return false rather than true which the parent
|
||||
* directory might.
|
||||
*/
|
||||
readonly attribute boolean supportsMailingLists;
|
||||
|
||||
/**
|
||||
* This attribute serves two purposes
|
||||
* 1. If this directory is not a mail list, directories are stored here
|
||||
* 2. If it is a mail list card entries are stored here
|
||||
*
|
||||
* @note This is a *live* array and not a static copy
|
||||
*/
|
||||
attribute nsIMutableArray addressLists;
|
||||
|
||||
// Specific to a directory which stores mail lists
|
||||
|
||||
/**
|
||||
* Creates a new mailing list in the directory. Currently only supported
|
||||
* for top-level directories.
|
||||
*
|
||||
* @param list The new mailing list to add.
|
||||
* @return The mailing list directory added, which may have been modified.
|
||||
*/
|
||||
nsIAbDirectory addMailList(in nsIAbDirectory list);
|
||||
|
||||
/**
|
||||
* Nick Name of the mailing list. This attribute is only really used when
|
||||
* the nsIAbDirectory represents a mailing list.
|
||||
*/
|
||||
attribute AString listNickName;
|
||||
|
||||
/**
|
||||
* Description of the mailing list. This attribute is only really used when
|
||||
* the nsIAbDirectory represents a mailing list.
|
||||
*/
|
||||
attribute AString description;
|
||||
|
||||
/**
|
||||
* Edits an existing mailing list (specified as listCard) into its parent
|
||||
* directory. You should call this function on the resource with the same
|
||||
* uri as the listCard.
|
||||
*
|
||||
* @param listCard A nsIAbCard version of the mailing list with the new
|
||||
* values.
|
||||
*/
|
||||
void editMailListToDatabase(in nsIAbCard listCard);
|
||||
|
||||
// Copies mail list properties from the srcList
|
||||
void copyMailList(in nsIAbDirectory srcList);
|
||||
|
||||
/**
|
||||
* Only creates a top level address book
|
||||
* which is stored in the preferences
|
||||
*
|
||||
* Need to change to factory based approach
|
||||
* to create new address books
|
||||
*
|
||||
* This method should become redundant or
|
||||
* be only associated with card folders
|
||||
*
|
||||
* The parameters are the same as for
|
||||
* nsIAbManager::newAddressBook
|
||||
*/
|
||||
ACString createNewDirectory(in AString aDirName, in ACString aURI,
|
||||
in unsigned long aType, in ACString aPrefName);
|
||||
|
||||
/* create a directory by passing the display name and address book uri */
|
||||
void createDirectoryByURI(in AString displayName, in ACString aURI);
|
||||
|
||||
/**
|
||||
* The id of the directory used in prefs e.g. "ldap_2.servers.pab"
|
||||
* Setting this will cause directoryPrefs to be updated.
|
||||
*/
|
||||
attribute ACString dirPrefId;
|
||||
|
||||
/**
|
||||
* @name getXXXValue
|
||||
*
|
||||
* Helper functions to get different types of pref, but return a default
|
||||
* value if a pref value was not obtained.
|
||||
*
|
||||
* @param aName The name of the pref within the branch dirPrefId to
|
||||
* get a value from.
|
||||
*
|
||||
* @param aDefaultValue The default value to return if getting the pref fails
|
||||
* or the pref is not present.
|
||||
*
|
||||
* @return The value of the pref or the default value.
|
||||
*
|
||||
* @exception NS_ERROR_NOT_INITIALIZED if the pref branch couldn't
|
||||
* be obtained (e.g. dirPrefId isn't set).
|
||||
*/
|
||||
//@{
|
||||
long getIntValue(in string aName, in long aDefaultValue);
|
||||
boolean getBoolValue(in string aName, in boolean aDefaultValue);
|
||||
ACString getStringValue(in string aName, in ACString aDefaultValue);
|
||||
AUTF8String getLocalizedStringValue(in string aName, in AUTF8String aDefaultValue);
|
||||
//@}
|
||||
|
||||
/**
|
||||
* The following attributes are read from an nsIAbDirectory via the above methods:
|
||||
*
|
||||
* HidesRecipients (Boolean)
|
||||
* If true, and this nsIAbDirectory is a mailing list, then when sending mail to
|
||||
* this list, recipients addresses will be hidden from one another by sending
|
||||
* via BCC.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name setXXXValue
|
||||
*
|
||||
* Helper functions to set different types of pref values.
|
||||
*
|
||||
* @param aName The name of the pref within the branch dirPrefId to
|
||||
* get a value from.
|
||||
*
|
||||
* @param aValue The value to set the pref to.
|
||||
*
|
||||
* @exception NS_ERROR_NOT_INITIALIZED if the pref branch couldn't
|
||||
* be obtained (e.g. dirPrefId isn't set).
|
||||
*/
|
||||
//@{
|
||||
void setIntValue(in string aName, in long aValue);
|
||||
void setBoolValue(in string aName, in boolean aValue);
|
||||
void setStringValue(in string aName, in ACString aValue);
|
||||
void setLocalizedStringValue(in string aName, in AUTF8String aValue);
|
||||
//@}
|
||||
|
||||
};
|
||||
164
mailnews/addrbook/public/nsIAbDirectoryQuery.idl
Normal file
164
mailnews/addrbook/public/nsIAbDirectoryQuery.idl
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIAbDirSearchListener;
|
||||
interface nsIAbCard;
|
||||
interface nsIAbDirectory;
|
||||
|
||||
/**
|
||||
* The arguments for a query.
|
||||
*
|
||||
* Contains an expression for perform matches
|
||||
* and an array of properties which should be
|
||||
* returned if a match is found from the expression
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(03af3018-2590-4f4c-a88c-1fff6595ef05)]
|
||||
interface nsIAbDirectoryQueryArguments : nsISupports
|
||||
{
|
||||
/**
|
||||
* Defines the boolean expression for
|
||||
* the matching of cards
|
||||
*
|
||||
*/
|
||||
attribute nsISupports expression;
|
||||
|
||||
/**
|
||||
* Defines if sub directories should be
|
||||
* queried
|
||||
*
|
||||
*/
|
||||
attribute boolean querySubDirectories;
|
||||
|
||||
/**
|
||||
* A parameter which can be used to pass in data specific to a particular
|
||||
* type of addressbook.
|
||||
*/
|
||||
attribute nsISupports typeSpecificArg;
|
||||
|
||||
/**
|
||||
* A custom search filter which user wants to use in LDAP query.
|
||||
*/
|
||||
attribute AUTF8String filter;
|
||||
};
|
||||
|
||||
|
||||
[scriptable, uuid(3A6E0C0C-1DD2-11B2-B23D-EA3A8CCB333C)]
|
||||
interface nsIAbDirectoryQueryPropertyValue : nsISupports
|
||||
{
|
||||
/**
|
||||
* The property which should be matched
|
||||
*
|
||||
* For example 'primaryEmail' or 'homePhone'
|
||||
* for card properties.
|
||||
*
|
||||
* Two further properties are defined that
|
||||
* do not exist as properties on a card.
|
||||
*
|
||||
* 'card:nsIAbCard' which represents the interface
|
||||
* of a card component
|
||||
*
|
||||
*/
|
||||
readonly attribute string name;
|
||||
|
||||
/**
|
||||
* The value of the property
|
||||
*
|
||||
*/
|
||||
readonly attribute wstring value;
|
||||
|
||||
/**
|
||||
* The value of the property
|
||||
* as an interface
|
||||
*
|
||||
* Only valid if the corresponding
|
||||
* property name is related to an
|
||||
* interface instead of a wstring
|
||||
*
|
||||
*/
|
||||
readonly attribute nsISupports valueISupports;
|
||||
};
|
||||
|
||||
[scriptable, uuid(516e7ffa-69bc-41db-a493-dfb4895832f3)]
|
||||
interface nsIAbDirectoryQueryResultListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called when a match is found. May be called from a different thread to
|
||||
* the one that initiates the query.
|
||||
*
|
||||
* @param aCard An individual result associated returned from a query
|
||||
*/
|
||||
void onQueryFoundCard(in nsIAbCard aCard);
|
||||
|
||||
/**
|
||||
* List of defined query results
|
||||
*
|
||||
*/
|
||||
const long queryResultMatch = 0;
|
||||
const long queryResultComplete = 1;
|
||||
const long queryResultStopped = 2;
|
||||
const long queryResultError = 3;
|
||||
|
||||
/**
|
||||
* Called when a query has finished. May be called from a different thread
|
||||
* to the one that initiates the query.
|
||||
*
|
||||
* @param aResult A result code from the list above.
|
||||
*
|
||||
* @param aErrorCode An error code specific to the type of query.
|
||||
*/
|
||||
void onQueryResult(in long aResult, in long aErrorCode);
|
||||
};
|
||||
|
||||
[scriptable, uuid(60b5961c-ce61-47b3-aa99-6d865f734dee)]
|
||||
interface nsIAbDirectoryQuery : nsISupports
|
||||
{
|
||||
/**
|
||||
* Initiates a query on a directory and sub-directories for properties
|
||||
* on cards
|
||||
*
|
||||
* @param aDirectory A directory that the query may get extra details
|
||||
* from.
|
||||
*
|
||||
* @param aArguments The properties and values to match value could of
|
||||
* type nsIAbDirectoryQueryMatchItem for matches other
|
||||
* than ?contains?
|
||||
*
|
||||
* @param aListener The listener which will obtain individual query
|
||||
* results.
|
||||
*
|
||||
* @param aResultLimit Limits the number of results returned to a maximum
|
||||
* value.
|
||||
*
|
||||
* @param aTimeOut The maximum length of time for the query
|
||||
*
|
||||
* @return A context id for the query
|
||||
*/
|
||||
long doQuery(in nsIAbDirectory aDirectory,
|
||||
in nsIAbDirectoryQueryArguments aArguments,
|
||||
in nsIAbDirSearchListener aListener,
|
||||
in long aResultLimit,
|
||||
in long aTimeOut);
|
||||
|
||||
/**
|
||||
* Stops an existing query operation if
|
||||
* query operation is asynchronous
|
||||
*
|
||||
* The nsIAbDirectoryQueryResultListener will
|
||||
* be notified when query has stopped
|
||||
*
|
||||
* It is implementation specific if notification
|
||||
* synchronous or asynchronous
|
||||
*
|
||||
* @param contextID
|
||||
* The unique number returned from
|
||||
* the doQuery methods
|
||||
*
|
||||
*/
|
||||
void stopQuery (in long contextID);
|
||||
};
|
||||
14
mailnews/addrbook/public/nsIAbDirectoryQueryProxy.idl
Normal file
14
mailnews/addrbook/public/nsIAbDirectoryQueryProxy.idl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* -*- 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 "nsIAbDirectoryQuery.idl"
|
||||
|
||||
[scriptable, uuid(b8034849-1e98-4d39-819c-15ba61a7434f)]
|
||||
interface nsIAbDirectoryQueryProxy : nsIAbDirectoryQuery
|
||||
{
|
||||
void initiate();
|
||||
};
|
||||
|
||||
53
mailnews/addrbook/public/nsIAbDirectorySearch.idl
Normal file
53
mailnews/addrbook/public/nsIAbDirectorySearch.idl
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Searching of cards on a directory.
|
||||
*
|
||||
* The search data is defined in the query
|
||||
* section of the directory URI, for example
|
||||
*
|
||||
* moz-abldapdirectory://ldap1.holland/dc=sun,dc=com?<query>
|
||||
*
|
||||
* If no search data is defined then the methods
|
||||
* will return immediately with no error.
|
||||
*/
|
||||
[scriptable, uuid(ABF26047-37E3-44FD-A28A-6D37A1B9CCB3)]
|
||||
interface nsIAbDirectorySearch : nsISupports
|
||||
{
|
||||
/**
|
||||
* Starts a search on the directory.
|
||||
*
|
||||
* If a search is already being performed
|
||||
* it is stopped.
|
||||
*
|
||||
* The results from a search, cards, will
|
||||
* returned by informing the address book
|
||||
* session that a new card has been added
|
||||
* to the directory.
|
||||
*
|
||||
* The nsIAbDirectoryQuery implementation
|
||||
* of the directory component (or a proxy)
|
||||
* may be used as an implementation for
|
||||
* this specialization of query.
|
||||
*
|
||||
* This method is semantically equivalent
|
||||
* to the nsIAbDirectory.getChildCards
|
||||
* method when there is search criteria
|
||||
* defined in the directory uri.
|
||||
*
|
||||
*/
|
||||
void startSearch ();
|
||||
|
||||
/**
|
||||
* Stops a search on the directory.
|
||||
*
|
||||
*/
|
||||
void stopSearch ();
|
||||
};
|
||||
|
||||
90
mailnews/addrbook/public/nsIAbItem.idl
Normal file
90
mailnews/addrbook/public/nsIAbItem.idl
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIMsgHeaderParser;
|
||||
interface nsIStringBundle;
|
||||
|
||||
/**
|
||||
* A containable item for address books.
|
||||
*/
|
||||
[scriptable, uuid(bb691a55-cbfe-4cf8-974a-e18cfa845a73)]
|
||||
interface nsIAbItem : nsISupports {
|
||||
/**
|
||||
* A universally-unique identifier for this item.
|
||||
*
|
||||
* If this item cannot be associated with a UUID for some reason, it MUST
|
||||
* return the empty string. The empty string MUST NOT be a valid UUID for any
|
||||
* item. Under no circumstances may this function throw an error.
|
||||
*
|
||||
* It is STRONGLY RECOMMENDED that implementations guarantee that this UUID
|
||||
* will not change between two different sessions of the application and that,
|
||||
* if this item is deleted, the UUID will not be reused.
|
||||
*
|
||||
* The format of the UUID for a generic nsIAbItem is purposefully left
|
||||
* undefined, although any item contained by an nsIAbDirectory SHOULD use
|
||||
* nsIAbManager::generateUUID to generate the UUID.
|
||||
*/
|
||||
readonly attribute AUTF8String uuid;
|
||||
|
||||
/**
|
||||
* @{
|
||||
* These constants reflect the possible values of the
|
||||
* mail.addr_book.lastnamefirst preferences. They are intended to be used in
|
||||
* generateName, defined below.
|
||||
*/
|
||||
const unsigned long GENERATE_DISPLAY_NAME = 0;
|
||||
const unsigned long GENERATE_LAST_FIRST_ORDER = 1;
|
||||
const unsigned long GENERATE_FIRST_LAST_ORDER = 2;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Generate a name from the item for display purposes.
|
||||
*
|
||||
* If this item is an nsIAbCard, then it will use the aGenerateFormat option
|
||||
* to determine the string to return.
|
||||
* If this item is not an nsIAbCard, then the aGenerateFormat option may be
|
||||
* ignored, and the displayName of the item returned.
|
||||
*
|
||||
* @param aGenerateFormat The format to generate as per the GENERATE_*
|
||||
* constants above.
|
||||
* @param aBundle An optional parameter that is a pointer to a string
|
||||
* bundle that holds:
|
||||
* chrome://messenger/locale/addressbook/addressBook.properties
|
||||
* If this bundle is not supplied, then the function
|
||||
* will obtain the bundle itself. If cached by the
|
||||
* caller and supplied to this function, then
|
||||
* performance will be improved over many calls.
|
||||
* @return A string containing the generated name.
|
||||
*/
|
||||
AString generateName(in long aGenerateFormat,
|
||||
[optional] in nsIStringBundle aBundle);
|
||||
|
||||
/**
|
||||
* Generate a formatted email address from the card, that can be used for
|
||||
* sending emails.
|
||||
*
|
||||
* @param aExpandList If this card is a list, and this parameter is set
|
||||
* to true, then the list will be expanded to include
|
||||
* the emails of the cards within the list.
|
||||
* @param aGroupMailLists If this card (or the items within this card) is a
|
||||
* list, and this is set to true, then the list will
|
||||
* be expanded in the RFC 2822 group format
|
||||
* "displayname : email1 ; email2 ; etc".
|
||||
* @param aHeaderParser An optional parameter pointing to the
|
||||
* nsIMsgHeaderParser service. If this is not supplied
|
||||
* the function will obtain the service itself. If
|
||||
* cached by the called and supplied to this function,
|
||||
* then performance will be improved over many calls.
|
||||
* @return A string containing a comma-separated list of
|
||||
* formatted addresses.
|
||||
*/
|
||||
//AString generateFormattedEmail(in boolean aExpandList,
|
||||
// in boolean aAsGroupMailLists,
|
||||
// [optional] in nsIMsgHeaderParser aHeaderParser);
|
||||
|
||||
};
|
||||
|
||||
194
mailnews/addrbook/public/nsIAbLDAPAttributeMap.idl
Normal file
194
mailnews/addrbook/public/nsIAbLDAPAttributeMap.idl
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 "nsISupports.idl"
|
||||
|
||||
interface nsILDAPMessage;
|
||||
interface nsIAbCard;
|
||||
|
||||
/**
|
||||
* A mapping between addressbook properties and ldap attributes.
|
||||
*
|
||||
* Each addressbook property can map to one or more attributes. If
|
||||
* there is no entry in preferences for a field, the getters generally
|
||||
* return null; empty strings are passed through as usual. The intent is
|
||||
* that properties with a non-zero number of attributes can be overridden for
|
||||
* a specific server by supplying a zero-length string. For this to work,
|
||||
* most callers are likely to want to check for both success and a
|
||||
* non-empty string.
|
||||
*
|
||||
* Note that the one exception to this pattern is getAttributes, which
|
||||
* throws NS_ERROR_FAILURE for non-existent property entries, since
|
||||
* XPConnect doesn't like returning null arrays.
|
||||
*
|
||||
* Note that each LDAP attribute can map to at most one addressbook
|
||||
* property. The checkState method is a useful tool in enforcing
|
||||
* this. Failure to enforce it may make it impossible to guarantee
|
||||
* that getProperty will do something consistent and reasonable.
|
||||
*
|
||||
* Maybe someday once we support ldap autoconfig stuff (ie
|
||||
* draft-joslin-config-schema-11.txt), we can simplify this and other
|
||||
* code and only allow a property to map to a single attribute.
|
||||
*/
|
||||
[scriptable, uuid(fa019fd1-7f3d-417a-8957-154cca0240be)]
|
||||
interface nsIAbLDAPAttributeMap : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get all the LDAP attributes associated with a given property
|
||||
* name, in order of precedence (highest to lowest).
|
||||
*
|
||||
* @param aProperty the address book property to return attrs for
|
||||
*
|
||||
* @return a comma-separated list of attributes, null if no entry is
|
||||
* present
|
||||
*/
|
||||
ACString getAttributeList(in ACString aProperty);
|
||||
|
||||
/**
|
||||
* Get all the LDAP attributes associated with a given property name, in
|
||||
* order of precedence (highest to lowest).
|
||||
*
|
||||
* @param aProperty the address book property to return attrs for
|
||||
*
|
||||
* @return an array of attributes
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE if there is no entry for this property
|
||||
*/
|
||||
void getAttributes(in ACString aProperty, out unsigned long aCount,
|
||||
[retval, array, size_is(aCount)] out string aAttrs);
|
||||
|
||||
/**
|
||||
* Get the first (canonical) LDAP attribute associated with a given property
|
||||
* name
|
||||
*
|
||||
* @param aProperty the address book property to return attrs for
|
||||
*
|
||||
* @return the first attribute associated with a given property,
|
||||
* null if there is no entry for this property
|
||||
*/
|
||||
ACString getFirstAttribute(in ACString aProperty);
|
||||
|
||||
/**
|
||||
* Set an existing mapping to the comma-separated list of attributes.
|
||||
*
|
||||
* @param aProperty the mozilla addressbook property name
|
||||
*
|
||||
* @param aAttributeList a comma-separated list of attributes in
|
||||
* order of precedence from high to low
|
||||
*
|
||||
* @param aAllowInconsistencies allow changes that would result in
|
||||
* a map with an LDAP attribute associated
|
||||
* with more than one property. Useful for
|
||||
* doing a bunch of sets at once, and
|
||||
* calling checkState at the end.
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE making this change would result in a map
|
||||
* with an LDAP attribute pointing to more
|
||||
* than one property
|
||||
*/
|
||||
void setAttributeList(in ACString aProperty, in ACString aAttributeList,
|
||||
in boolean allowInconsistencies);
|
||||
|
||||
/**
|
||||
* Find the Mozilla addressbook property name that this attribute should
|
||||
* map to.
|
||||
*
|
||||
* @return the addressbook property name, null if it's not used in the map
|
||||
*/
|
||||
ACString getProperty(in ACString aAttribute);
|
||||
|
||||
/**
|
||||
* Get all attributes that may be used in an addressbook card via this
|
||||
* property map (used for passing to to an LDAP search when you want
|
||||
* everything that could be in a card returned).
|
||||
*
|
||||
* @return a comma-separated list of attribute names
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there are no attributes in this property map
|
||||
*/
|
||||
ACString getAllCardAttributes();
|
||||
|
||||
/**
|
||||
* Get all properties that may be used in an addressbook card via this
|
||||
* property map.
|
||||
*
|
||||
* @return an array of properties
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there are no attributes in this property map
|
||||
*/
|
||||
void getAllCardProperties(out unsigned long aCount,
|
||||
[retval, array, size_is(aCount)] out string aProps);
|
||||
|
||||
/**
|
||||
* Check that no LDAP attributes are listed in more than one property.
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE one or more LDAP attributes are listed
|
||||
* multiple times. The object is now in an
|
||||
* inconsistent state, and should be either
|
||||
* manually repaired or discarded.
|
||||
*/
|
||||
void checkState();
|
||||
|
||||
/* These last two methods are really just for the convenience of the caller
|
||||
* and to avoid tons of unnecessary crossing of the XPConnect boundary.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set any attributes specified in the given prefbranch on this object.
|
||||
*
|
||||
* @param aPrefBranchName the pref branch containing all the
|
||||
* property names
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE one or more LDAP attributes are listed
|
||||
* multiple times. The object is now in an
|
||||
* inconsistent state, and should be either
|
||||
* manually repaired or discarded.
|
||||
*/
|
||||
void setFromPrefs(in ACString aPrefBranchName);
|
||||
|
||||
/**
|
||||
* Set the properties on an addressbook card from the given LDAP message
|
||||
* using the map in this object.
|
||||
*
|
||||
* @param aCard is the card object whose values are to be set
|
||||
* @param aMessage is the LDAP message to get the values from
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE is thrown if no addressbook properties
|
||||
* are found in the message
|
||||
*/
|
||||
void setCardPropertiesFromLDAPMessage(in nsILDAPMessage aMessage,
|
||||
in nsIAbCard aCard);
|
||||
};
|
||||
|
||||
/**
|
||||
* The nsIAbLDAPAttributeMapService is used to build and hold a cache
|
||||
* of maps.
|
||||
*/
|
||||
[scriptable, uuid(12e2d589-3c2a-48e4-8c82-b1e6464a0dfd)]
|
||||
interface nsIAbLDAPAttributeMapService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Accessor to construct or return a cached copy of the attribute
|
||||
* map for a given preference branch. The map is constructed by
|
||||
* first taking the default map (as specified by the
|
||||
* "ldap_2.servers.default.attrmap" prefbranch), and then having any
|
||||
* preferences specified by aPrefBranchName override the defaults.
|
||||
* LDIF import and export code should use the default map.
|
||||
*
|
||||
* @return the requested map
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE error constructing the map;
|
||||
* possibly because of a failure
|
||||
* from checkState()
|
||||
*/
|
||||
nsIAbLDAPAttributeMap getMapForPrefBranch(in ACString aPrefBranchName);
|
||||
};
|
||||
|
||||
|
||||
%{C++
|
||||
// test whether one of the getters has actually found an attribute
|
||||
#define ATTRMAP_FOUND_ATTR(rv, str) (NS_SUCCEEDED(rv) && !(str).IsEmpty())
|
||||
%}
|
||||
56
mailnews/addrbook/public/nsIAbLDAPCard.idl
Normal file
56
mailnews/addrbook/public/nsIAbLDAPCard.idl
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* -*- 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 "nsIAbCard.idl"
|
||||
|
||||
interface nsIAbLDAPAttributeMap;
|
||||
interface nsILDAPModification;
|
||||
interface nsILDAPMessage;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(2831b3b0-30ef-4070-8ad3-90ae04980e11)]
|
||||
interface nsIAbLDAPCard : nsISupports
|
||||
{
|
||||
/**
|
||||
* Returns the required information for an LDAP update message.
|
||||
*
|
||||
* @param aAttrMap The map between LDAP attributes and card properties
|
||||
* @param aClassCount The number of objectClass values
|
||||
* @param aClasses The objectClass values that the card needs to have
|
||||
* @param updateType This should be one of:
|
||||
* nsILDAPModification::MOD_ADD
|
||||
* nsILDAPModification::MOD_REPLACE
|
||||
*
|
||||
* @return Returns an array of modifications required to
|
||||
* add or replace the card in the ldap directory.
|
||||
*/
|
||||
nsIArray getLDAPMessageInfo(in nsIAbLDAPAttributeMap aAttrMap,
|
||||
in unsigned long aClassCount,
|
||||
[array, size_is(aClassCount)] in string aClasses,
|
||||
in long updateType);
|
||||
|
||||
/**
|
||||
* Builds a relative distinguished name (RDN) with the given set of
|
||||
* attributes.
|
||||
*
|
||||
* @param aAttrMap The map between LDAP attributes and card properties
|
||||
* @param aAttrCount The number of attributes to use for the RDN
|
||||
* @param aAttributes The name of the attributes to use for the RDN
|
||||
*
|
||||
*/
|
||||
ACString buildRdn(in nsIAbLDAPAttributeMap aAttrMap,
|
||||
in unsigned long aAttrCount,
|
||||
[array, size_is(aAttrCount)] in string aAttributes);
|
||||
|
||||
/**
|
||||
* Stores meta-properties from a raw LDAP search result.
|
||||
*
|
||||
* @param aMessage The LDAP search result message.
|
||||
*
|
||||
*/
|
||||
void setMetaProperties(in nsILDAPMessage aMessage);
|
||||
|
||||
attribute ACString dn;
|
||||
};
|
||||
112
mailnews/addrbook/public/nsIAbLDAPDirectory.idl
Normal file
112
mailnews/addrbook/public/nsIAbLDAPDirectory.idl
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIMutableArray;
|
||||
interface nsIFile;
|
||||
interface nsIAddrDatabase;
|
||||
interface nsIAbLDAPAttributeMap;
|
||||
interface nsILDAPURL;
|
||||
|
||||
%{C++
|
||||
#define kLDAPDirectoryRoot "moz-abldapdirectory://"
|
||||
#define kLDAPDirectoryRootLen 22
|
||||
%}
|
||||
|
||||
/**
|
||||
* XXX This should really inherit from nsIAbDirectory, and some day it will.
|
||||
* But for now, doing that complicates implementation.
|
||||
*/
|
||||
[scriptable, uuid(90dde295-e354-4d58-Add8-f9b29a95942d)]
|
||||
interface nsIAbLDAPDirectory : nsISupports
|
||||
{
|
||||
/**
|
||||
* If set, these arrays of nsILDAPControls are passed through to the
|
||||
* nsILDAPOperation that searchExt is called on.
|
||||
*/
|
||||
attribute nsIMutableArray searchServerControls;
|
||||
attribute nsIMutableArray searchClientControls;
|
||||
|
||||
/**
|
||||
* The Replication File Name to use.
|
||||
*/
|
||||
attribute ACString replicationFileName;
|
||||
|
||||
/**
|
||||
* The version of LDAP protocol in use.
|
||||
*/
|
||||
attribute unsigned long protocolVersion;
|
||||
|
||||
/**
|
||||
* The SASL mechanism to use to authenticate to the LDAP server
|
||||
* If this is an empty string, then a simple bind will be performed
|
||||
* A non-zero string is assumed to be the name of the SASL mechanism.
|
||||
* Currently the only supported mechanism is GSSAPI
|
||||
*/
|
||||
attribute ACString saslMechanism;
|
||||
|
||||
/**
|
||||
* The AuthDN to use to access the server.
|
||||
*/
|
||||
attribute AUTF8String authDn;
|
||||
|
||||
/**
|
||||
* The maximum number of matches that the server will return per a search.
|
||||
*/
|
||||
attribute long maxHits;
|
||||
|
||||
/**
|
||||
* The Last Change Number used for replication.
|
||||
*/
|
||||
attribute long lastChangeNumber;
|
||||
|
||||
/**
|
||||
* The LDAP server's scoping of the lastChangeNumber.
|
||||
*/
|
||||
attribute ACString dataVersion;
|
||||
|
||||
/**
|
||||
* The attribute map that is associated with this directory's server.
|
||||
*/
|
||||
readonly attribute nsIAbLDAPAttributeMap attributeMap;
|
||||
|
||||
/**
|
||||
* The LDAP URL for this directory. Note that this differs from
|
||||
* nsIAbDirectory::URI. This attribute will give you a true ldap
|
||||
* url, e.g. ldap://localhost:389/ whereas the uri will give you the
|
||||
* directories rdf uri, e.g. moz-abldapdirectory://<pref base name>/.
|
||||
*/
|
||||
attribute nsILDAPURL lDAPURL;
|
||||
|
||||
/**
|
||||
* The replication (offline) file that this database uses.
|
||||
*/
|
||||
readonly attribute nsIFile replicationFile;
|
||||
|
||||
/**
|
||||
* A database that is set up for the replication file.
|
||||
*/
|
||||
readonly attribute nsIAddrDatabase replicationDatabase;
|
||||
|
||||
/**
|
||||
* The LDAP attributes used to build the Relative Distinguished Name
|
||||
* of new cards, in the form of a comma separated list.
|
||||
*
|
||||
* The default is to use the common name (cn) attribute.
|
||||
*/
|
||||
attribute ACString rdnAttributes;
|
||||
|
||||
/**
|
||||
* The LDAP objectClass values added to cards when they are created/added,
|
||||
* in the form of a comma separated list.
|
||||
*
|
||||
* The default is to use the following classes:
|
||||
* top,person,organizationalPerson,inetOrgPerson,mozillaAbPersonAlpha
|
||||
*/
|
||||
attribute ACString objectClasses;
|
||||
|
||||
};
|
||||
|
||||
68
mailnews/addrbook/public/nsIAbLDAPReplicationData.idl
Normal file
68
mailnews/addrbook/public/nsIAbLDAPReplicationData.idl
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIAbLDAPDirectory;
|
||||
interface nsILDAPConnection;
|
||||
interface nsILDAPURL;
|
||||
interface nsIAbLDAPReplicationQuery;
|
||||
interface nsIWebProgressListener;
|
||||
|
||||
/**
|
||||
* this service does replication of an LDAP directory to a local Mork AB Database.
|
||||
*/
|
||||
[scriptable, uuid(e628bbc9-8793-4f0b-bce4-990d399b1fca)]
|
||||
interface nsIAbLDAPProcessReplicationData : nsISupports
|
||||
{
|
||||
/**
|
||||
* readonly attribute giving the current replication state
|
||||
*/
|
||||
readonly attribute int32_t replicationState;
|
||||
|
||||
/**
|
||||
* replication states
|
||||
*/
|
||||
const long kIdle = 0;
|
||||
const long kAnonymousBinding = 1;
|
||||
const long kAuthenticatedBinding = 2;
|
||||
const long kSyncServerBinding = 3;
|
||||
const long kSearchingAuthDN = 4;
|
||||
const long kDecidingProtocol = 5;
|
||||
const long kAuthenticating = 6;
|
||||
const long kReplicatingAll = 7;
|
||||
const long kSearchingRootDSE = 8;
|
||||
const long kFindingChanges = 9;
|
||||
const long kReplicatingChanges = 10;
|
||||
const long kReplicationDone = 11;
|
||||
|
||||
/**
|
||||
* readonly attribute giving the current protocol used
|
||||
*/
|
||||
readonly attribute int32_t protocolUsed ;
|
||||
|
||||
/**
|
||||
* replication protocols
|
||||
*/
|
||||
const long kDefaultDownloadAll = 0;
|
||||
const long kChangeLogProtocol = 1;
|
||||
const long kLCUPProtocol = 2;
|
||||
const long kLastUpdatedTimeStampMethod = 3;
|
||||
|
||||
/**
|
||||
* this method initializes the implementation
|
||||
*/
|
||||
void init(in nsIAbLDAPDirectory directory,
|
||||
in nsILDAPConnection connection,
|
||||
in nsILDAPURL url,
|
||||
in nsIAbLDAPReplicationQuery query,
|
||||
in nsIWebProgressListener progressListener);
|
||||
|
||||
/**
|
||||
* this method a aborts the ongoing processing
|
||||
*/
|
||||
void abort();
|
||||
};
|
||||
|
||||
67
mailnews/addrbook/public/nsIAbLDAPReplicationQuery.idl
Normal file
67
mailnews/addrbook/public/nsIAbLDAPReplicationQuery.idl
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
interface nsIWebProgressListener;
|
||||
interface nsILDAPURL;
|
||||
interface nsILDAPConnection;
|
||||
interface nsILDAPOperation;
|
||||
interface nsIAbLDAPDirectory;
|
||||
|
||||
/**
|
||||
* this interface provides methods to perform LDAP Replication Queries
|
||||
*/
|
||||
[scriptable, uuid(460a739c-a8c1-4f24-b705-c89d136ab9f5)]
|
||||
interface nsIAbLDAPReplicationQuery : nsISupports
|
||||
{
|
||||
/**
|
||||
* initialize for the query
|
||||
*/
|
||||
void init(in nsIAbLDAPDirectory aDirectory,
|
||||
in nsIWebProgressListener aProgressListener);
|
||||
|
||||
/**
|
||||
* Starts an LDAP query to do replication as needed
|
||||
*/
|
||||
void doReplicationQuery();
|
||||
|
||||
/**
|
||||
* Cancels the currently executing query
|
||||
*/
|
||||
void cancelQuery();
|
||||
|
||||
/**
|
||||
* this method is the callback when query is done, failed or successful
|
||||
*/
|
||||
void done(in boolean aSuccess);
|
||||
};
|
||||
|
||||
// XXX This interface currently isn't implemented as it didn't work.
|
||||
// Bug 311632 should fix it
|
||||
[scriptable, uuid(126202D1-4460-11d6-B7C2-00B0D06E5F27)]
|
||||
interface nsIAbLDAPChangeLogQuery : nsISupports
|
||||
{
|
||||
/**
|
||||
* Starts an LDAP query to find auth DN
|
||||
*/
|
||||
void queryAuthDN(in AUTF8String aValueUsedToFindDn);
|
||||
|
||||
/**
|
||||
* Starts an LDAP query to search server's Root DSE
|
||||
*/
|
||||
void queryRootDSE();
|
||||
|
||||
/**
|
||||
* Starts an LDAP ChangeLog query to find changelog entries
|
||||
*/
|
||||
void queryChangeLog(in AUTF8String aChangeLogDN, in int32_t aLastChangeNo);
|
||||
|
||||
/**
|
||||
* Starts an LDAP query to find changed entries
|
||||
*/
|
||||
void queryChangedEntries(in AUTF8String aChangedEntryDN);
|
||||
};
|
||||
|
||||
32
mailnews/addrbook/public/nsIAbLDAPReplicationService.idl
Normal file
32
mailnews/addrbook/public/nsIAbLDAPReplicationService.idl
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* 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 "nsISupports.idl"
|
||||
|
||||
interface nsIWebProgressListener;
|
||||
interface nsIAbLDAPDirectory;
|
||||
|
||||
/**
|
||||
* this service does replication of an LDAP directory to a local Mork AB Database.
|
||||
*/
|
||||
[scriptable, uuid(3f499c70-5ceb-4b91-8b7f-62c366859383)]
|
||||
interface nsIAbLDAPReplicationService: nsISupports {
|
||||
|
||||
/**
|
||||
* Start Replication of given LDAP directory represented by the URI
|
||||
*/
|
||||
void startReplication(in nsIAbLDAPDirectory aDirectory,
|
||||
in nsIWebProgressListener progressListener);
|
||||
|
||||
/**
|
||||
* Cancel Replication of given LDAP directory represented by the URI
|
||||
*/
|
||||
void cancelReplication(in nsIAbLDAPDirectory aDirectory);
|
||||
|
||||
/**
|
||||
* callback when replication is done, failure or success
|
||||
*/
|
||||
void done(in boolean aSuccess);
|
||||
};
|
||||
|
||||
40
mailnews/addrbook/public/nsIAbLDIFService.idl
Normal file
40
mailnews/addrbook/public/nsIAbLDIFService.idl
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/. */
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFile;
|
||||
interface nsIAddrDatabase;
|
||||
|
||||
[scriptable, uuid(7afaa95f-0b1c-4d8a-a65f-bb5073ed6d39)]
|
||||
interface nsIAbLDIFService : nsISupports {
|
||||
|
||||
/**
|
||||
* Determine if a file is likely to be an LDIF file based on field
|
||||
* names that commonly appear in LDIF files.
|
||||
*
|
||||
* @param aSrc The file to examine
|
||||
*
|
||||
* @return true if the file appears to be of LDIF type,
|
||||
* false otherwise
|
||||
*/
|
||||
boolean isLDIFFile(in nsIFile aSrc);
|
||||
|
||||
/**
|
||||
* Imports a file into the specified address book.
|
||||
*
|
||||
* @param aDb The address book to import addresses into.
|
||||
*
|
||||
* @param aSrc The file to import addresses from.
|
||||
*
|
||||
* @param aStoreLocAsHome Stores the address as a home rather than work
|
||||
* address.
|
||||
*
|
||||
* @param aProgress May be null, but if a pointer is supplied,
|
||||
* then it will be updated regularly with the
|
||||
* current position of reading from the file.
|
||||
*
|
||||
*/
|
||||
void importLDIFFile(in nsIAddrDatabase aDb, in nsIFile aSrc, in boolean aStoreLocAsHome, inout unsigned long aProgress);
|
||||
};
|
||||
90
mailnews/addrbook/public/nsIAbListener.idl
Normal file
90
mailnews/addrbook/public/nsIAbListener.idl
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
typedef unsigned long abListenerNotifyFlagValue;
|
||||
|
||||
/**
|
||||
* nsIAbListener
|
||||
*
|
||||
* Implement this interface to receive notifications of address book
|
||||
* items being added, removed or changed with loaded address books.
|
||||
*
|
||||
* Subscribe to events by using nsIAbManager.
|
||||
*/
|
||||
[scriptable, uuid(b3ca8745-2dad-4032-ae2f-0b8622f32697)]
|
||||
interface nsIAbListener : nsISupports {
|
||||
/**
|
||||
* These flags are used when registering the listener with nsIAbManager to
|
||||
* specify when to receive notifications of address book updates.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An address book, mailing list or card is added.
|
||||
*/
|
||||
const abListenerNotifyFlagValue itemAdded = 0x1;
|
||||
/**
|
||||
* A mailing list or card is removed from an address book.
|
||||
*/
|
||||
const abListenerNotifyFlagValue directoryItemRemoved = 0x2;
|
||||
/**
|
||||
* An address book is removed
|
||||
*/
|
||||
const abListenerNotifyFlagValue directoryRemoved = 0x4;
|
||||
/**
|
||||
* An address book, mailing list or card is changed.
|
||||
*/
|
||||
const abListenerNotifyFlagValue itemChanged = 0x8;
|
||||
/**
|
||||
* All of the above notifications are to be received.
|
||||
*/
|
||||
const abListenerNotifyFlagValue all = 0xFFFFFFFF;
|
||||
|
||||
/**
|
||||
* Called when an address book item (book, card or list) is added
|
||||
*
|
||||
* @param parentDir The parent of the item being added.
|
||||
*
|
||||
* @param item The item being added to the database (a
|
||||
* directory or card).
|
||||
*
|
||||
*/
|
||||
void onItemAdded(in nsISupports parentDir, in nsISupports item);
|
||||
|
||||
/**
|
||||
* Called when an address book, mailing list or card is removed. This
|
||||
* is partially configurable when setting up the listener via
|
||||
* nsIAddrBookSession
|
||||
*
|
||||
* @param parentDir The parent of the item being removed, this
|
||||
* may be an empty directory in the case of a
|
||||
* top level address book.
|
||||
*
|
||||
* @param item The item being removed from the database.
|
||||
*
|
||||
*/
|
||||
void onItemRemoved(in nsISupports parentDir, in nsISupports item);
|
||||
|
||||
/**
|
||||
* Called when an address book item is changed. Note the current
|
||||
* implementation means that property is either the literal string "DirName"
|
||||
* or null, with oldValue and newValue being specified if the property is
|
||||
* "DirName" otherwise they are null.
|
||||
*
|
||||
* @param item The item being updated (a directory or a
|
||||
* card).
|
||||
*
|
||||
* @param property The property of the item being changed.
|
||||
*
|
||||
* @param oldValue The old value of the item property being
|
||||
* changed if it is known, null otherwise.
|
||||
*
|
||||
* @param newValue The new value of the item property being
|
||||
* changed.
|
||||
*
|
||||
*/
|
||||
void onItemPropertyChanged(in nsISupports item, in string property, in wstring oldValue, in wstring newValue);
|
||||
};
|
||||
71
mailnews/addrbook/public/nsIAbMDBDirectory.idl
Normal file
71
mailnews/addrbook/public/nsIAbMDBDirectory.idl
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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFile;
|
||||
interface nsIAbDirectory;
|
||||
interface nsIAbCard;
|
||||
interface nsIAddrDatabase;
|
||||
|
||||
%{C++
|
||||
#define kMDBDirectoryRoot "moz-abmdbdirectory://"
|
||||
#define kMDBDirectoryRootLen 21
|
||||
%}
|
||||
|
||||
[scriptable, uuid(744072be-1ba0-46bc-af24-46e22567a2ea)]
|
||||
interface nsIAbMDBDirectory : nsISupports {
|
||||
|
||||
// Creates a directory component from the
|
||||
// uriName, adds it to its children and returns
|
||||
// the component
|
||||
nsIAbDirectory addDirectory(in string uriName);
|
||||
|
||||
/**
|
||||
* Supplies a nsIFile point to the database file for this directory
|
||||
*
|
||||
* @exception NS_ERROR_NOT_INITIALIZED If there is no filename preference
|
||||
* present or it is empty
|
||||
*/
|
||||
readonly attribute nsIFile databaseFile;
|
||||
|
||||
/**
|
||||
* Supplies a nsIAddrDatabase that uses the databaseFile. See also
|
||||
* databaseFile for possible exceptions.
|
||||
*/
|
||||
readonly attribute nsIAddrDatabase database;
|
||||
|
||||
// Mail list specific
|
||||
//
|
||||
|
||||
// Removes all elements from the addressLists
|
||||
// property
|
||||
[noscript] void removeElementsFromAddressList();
|
||||
|
||||
// Specific to a directory which stores mail lists
|
||||
//
|
||||
|
||||
// Adds a directory to the addressLists attribute
|
||||
void addMailListToDirectory(in nsIAbDirectory mailList);
|
||||
|
||||
// Specific to a directory which is a mail list
|
||||
//
|
||||
|
||||
// Copies mail list properties from the srcList
|
||||
void copyDBMailList(in nsIAbMDBDirectory srcListDB);
|
||||
|
||||
// Adds a card to the addressList attribute
|
||||
void addAddressToList(in nsIAbCard card);
|
||||
|
||||
// Removes items from the addressLists member
|
||||
void removeEmailAddressAt(in unsigned long aIndex);
|
||||
|
||||
attribute unsigned long dbRowID;
|
||||
|
||||
// Empty implementation, called by the data base
|
||||
[noscript] void notifyDirItemAdded(in nsISupports item);
|
||||
|
||||
[noscript] void clearDatabase();
|
||||
};
|
||||
190
mailnews/addrbook/public/nsIAbManager.idl
Normal file
190
mailnews/addrbook/public/nsIAbManager.idl
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* -*- Mode: IDL; 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 "nsISupports.idl"
|
||||
#include "nsIAbListener.idl"
|
||||
|
||||
interface mozIDOMWindowProxy;
|
||||
interface nsIAbDirectory;
|
||||
interface nsIAbCard;
|
||||
interface nsIAbDirectoryProperties;
|
||||
interface nsIFile;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIAbBooleanExpression;
|
||||
|
||||
/**
|
||||
* nsIAbManager is an interface to the main address book mananger
|
||||
* via the contract id "@mozilla.org/abmanager;1"
|
||||
*
|
||||
* It contains the main functions to create and delete address books as well
|
||||
* as some helper functions.
|
||||
*/
|
||||
[scriptable, uuid(ea0d8b3d-a549-4874-82d8-3a82cee2a3f1)]
|
||||
interface nsIAbManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Returns an enumerator containing all the top-level directories
|
||||
* (non-recursive)
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator directories;
|
||||
|
||||
/**
|
||||
* Returns the directory that represents the supplied URI.
|
||||
*
|
||||
* @param aURI The URI of the address book to find.
|
||||
* @return The found address book.
|
||||
*/
|
||||
nsIAbDirectory getDirectory(in ACString aURI);
|
||||
|
||||
/**
|
||||
* Returns the directory that has the supplied dirPrefId.
|
||||
*
|
||||
* @param aDirPrefId The dirPrefId of the directory.
|
||||
* @return The found AB directory.
|
||||
*/
|
||||
nsIAbDirectory getDirectoryFromId(in ACString aDirPrefId);
|
||||
|
||||
/**
|
||||
* Creates a new address book.
|
||||
*
|
||||
* @param aDirName The description of the address book.
|
||||
* @param aURI The URI for the address book. This is specific to each
|
||||
* type of address book.
|
||||
* @param aType The type of the address book (see nsDirPrefs.h)
|
||||
* @param aPrefName Overrides the default of ldap_2.servers.<aDirName>
|
||||
* (note that the caller must ensure its uniqueness).
|
||||
*/
|
||||
ACString newAddressBook(in AString aDirName, in ACString aURI,
|
||||
in unsigned long aType,
|
||||
[optional] in ACString aPrefName);
|
||||
|
||||
/**
|
||||
* Deletes an address book.
|
||||
*
|
||||
* @param aURI The URI for the address book. This is specific to each
|
||||
* type of address book.
|
||||
*/
|
||||
void deleteAddressBook(in ACString aURI);
|
||||
|
||||
/**
|
||||
* Exports an address book, it will provide a dialog to the user for the
|
||||
* location to save the file to and will then save the address book to media.
|
||||
*
|
||||
* @param aParentWin Parent Window for the file save dialog to use.
|
||||
* @param aDirectory The directory to export.
|
||||
*/
|
||||
void exportAddressBook(in mozIDOMWindowProxy aParentWin, in nsIAbDirectory aDirectory);
|
||||
|
||||
/**
|
||||
* Adds a nsIAbListener to receive notifications of address book updates
|
||||
* according to the specified notifyFlags.
|
||||
*
|
||||
* @param aListener The listener that is to receive updates.
|
||||
* @param aNotifyFlags A bitwise-or of abListenerNotifyFlagValue items
|
||||
* specifying which notifications to receive. See
|
||||
* nsIAbListener for possible values.
|
||||
*/
|
||||
void addAddressBookListener(in nsIAbListener aListener,
|
||||
in abListenerNotifyFlagValue aNotifyFlags);
|
||||
|
||||
/**
|
||||
* Removes a nsIAbListener from receive notifications of address book
|
||||
* updates.
|
||||
*
|
||||
* @param aListener The listener that is to no longer receive updates.
|
||||
*/
|
||||
void removeAddressBookListener(in nsIAbListener aListener);
|
||||
|
||||
/**
|
||||
* Call to notify the registered listeners when a property on an item has
|
||||
* changed.
|
||||
*
|
||||
* @param aItem The items that has changed (e.g. an nsIAbDirectory)
|
||||
* @param aProperty The property that has changed (e.g. DirName)
|
||||
* @param aOldValue The old value of the property.
|
||||
* @param aNewValue The new value of the property.
|
||||
*/
|
||||
void notifyItemPropertyChanged(in nsISupports aItem,
|
||||
in string aProperty,
|
||||
in wstring aOldValue,
|
||||
in wstring aNewValue);
|
||||
|
||||
/**
|
||||
* Call to notify the registered listeners when a directory item is added.
|
||||
*
|
||||
* @param aParentDirectory The parent directory of the item that has been
|
||||
* added.
|
||||
* @param aItem The item that has been added.
|
||||
*/
|
||||
void notifyDirectoryItemAdded(in nsIAbDirectory aParentDirectory,
|
||||
in nsISupports aItem);
|
||||
|
||||
/**
|
||||
* Call to notify the registered listeners when a directory item is removed.
|
||||
*
|
||||
* @param aParentDirectory The parent directory of the item that has been
|
||||
* removed.
|
||||
* @param aItem The item that has been removed.
|
||||
*/
|
||||
void notifyDirectoryItemDeleted(in nsIAbDirectory aParentDirectory,
|
||||
in nsISupports aItem);
|
||||
|
||||
/**
|
||||
* Call to notify the registered listeners when a directory is removed.
|
||||
*
|
||||
* @param aParentDirectory The parent directory of the directory that has
|
||||
* been removed.
|
||||
* @param aDirectory The directory that has been removed.
|
||||
*/
|
||||
void notifyDirectoryDeleted(in nsIAbDirectory aParentDirectory,
|
||||
in nsISupports aDirectory);
|
||||
|
||||
/**
|
||||
* Returns the user profile directory. NOTE: this should not be used
|
||||
* as it may go away soon.
|
||||
*/
|
||||
readonly attribute nsIFile userProfileDirectory;
|
||||
|
||||
/**
|
||||
* Finds out if the mailing list name exists in any *mork/MDB* based
|
||||
* address book
|
||||
*
|
||||
* @param aName The name of the list to try and find.
|
||||
*
|
||||
* @return True if the name exists.
|
||||
*/
|
||||
boolean mailListNameExists(in wstring name);
|
||||
|
||||
/**
|
||||
* Translates an escaped vcard string into a nsIAbCard.
|
||||
*
|
||||
* @param escapedVCardStr The string containing the vcard.
|
||||
*
|
||||
* @return A card containing the translated vcard data.
|
||||
*/
|
||||
nsIAbCard escapedVCardToAbCard(in string escapedVCardStr);
|
||||
|
||||
/**
|
||||
* Generates a UUID from a (directory ID, local ID) tuple.
|
||||
*
|
||||
* Use of this method is preferred in such cases, since it is designed to work
|
||||
* with other methods of this interface.
|
||||
*
|
||||
* @param directoryId The directory ID.
|
||||
* @param localId The per-directory ID.
|
||||
* @return A string to use for the UUID.
|
||||
*/
|
||||
AUTF8String generateUUID(in AUTF8String directoryId, in AUTF8String localId);
|
||||
|
||||
|
||||
/**
|
||||
* A utility function that converts an nsIAbDirectory query string to an
|
||||
* nsIAbBooleanExpression.
|
||||
*
|
||||
* @param aQueryString The nsIAbDirectory query string
|
||||
* @return an nsIAbBooleanExpression for the query string
|
||||
*/
|
||||
nsIAbBooleanExpression convertQueryStringToExpression(in AUTF8String aQueryString);
|
||||
};
|
||||
109
mailnews/addrbook/public/nsIAbView.idl
Normal file
109
mailnews/addrbook/public/nsIAbView.idl
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: IDL; 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 "nsISupports.idl"
|
||||
|
||||
interface nsIAbCard;
|
||||
interface nsIAbDirectory;
|
||||
interface nsIArray;
|
||||
|
||||
/// Define a class using this interface to listen to updates from nsIAbView.
|
||||
[scriptable, uuid(79ad5d6e-1dd2-11b2-addd-f547dab50d75)]
|
||||
interface nsIAbViewListener : nsISupports
|
||||
{
|
||||
/// Called when the selection is changed in the tree
|
||||
void onSelectionChanged();
|
||||
|
||||
/// Called when the total count of cards is changed.
|
||||
void onCountChanged(in long total);
|
||||
};
|
||||
|
||||
/**
|
||||
* This interface and its associated nsAbView object provides an interface
|
||||
* to allow a tree to be associated with an address book, and the results
|
||||
* to be displayed in that tree.
|
||||
*
|
||||
* If you wish for the tree to display the results of a different address
|
||||
* book, then call setView again. There is no need to delete and recreate the
|
||||
* nsAbView object. If you wish to clear the view, then just call clearView.
|
||||
*/
|
||||
[scriptable, uuid(45e2fa9f-0b59-4090-a2fa-fb7042cf64a2)]
|
||||
interface nsIAbView : nsISupports
|
||||
{
|
||||
/**
|
||||
* Sets up the nsIAbView to look at the specified directory. This may be
|
||||
* called multiple times.
|
||||
*
|
||||
* @param aDirectory The directory to search, this may be a directory
|
||||
* with a query string.
|
||||
* @param aViewListener An optional listener.
|
||||
* @param aSortColumn The column to sort by. See the xul element with
|
||||
* id abResultsTreeCols for possible values.
|
||||
* @param aSortDirection The sort direction to use ("ascending"/"descending")
|
||||
* @return The actual sortColumn (various switching of apps
|
||||
* could cause the persisted sortColumn to be bogus).
|
||||
*/
|
||||
AString setView(in nsIAbDirectory aAddressBook,
|
||||
in nsIAbViewListener aAbViewListener,
|
||||
in AString aSortColumn,
|
||||
in AString aSortDirection);
|
||||
|
||||
/**
|
||||
* Clears the view and releases any locally held copies of the address book
|
||||
* directory. This should be called when the view is no longer required, e.g.
|
||||
* on unload.
|
||||
*/
|
||||
void clearView();
|
||||
|
||||
/**
|
||||
* Sorts the tree by the specified parameters.
|
||||
*
|
||||
* @param aSortColumn The column to sort by. See the xul element with
|
||||
* id abResultsTreeCols for possible values.
|
||||
* @param aSortDirection The sort direction to use ("ascending"/"descending")
|
||||
* @param aResort The function DOES optimize for the case when sortColumn
|
||||
* and sortDirection is identical since the last call.
|
||||
* If an unconditional resort is needed, set this to true.
|
||||
*/
|
||||
void sortBy(in wstring aSortColumn, in wstring aSortDirection,
|
||||
[optional] in boolean aResort);
|
||||
|
||||
/// Returns the current sort column
|
||||
readonly attribute AString sortColumn;
|
||||
|
||||
/// Returns the current sort direction
|
||||
readonly attribute AString sortDirection;
|
||||
|
||||
/**
|
||||
* Returns the current directory that this view is hooked up to. May be
|
||||
* null if no directory has been set.
|
||||
*/
|
||||
readonly attribute nsIAbDirectory directory;
|
||||
|
||||
/**
|
||||
* Returns the card associated with the given row.
|
||||
*
|
||||
* @param aRow The row from which to return the card.
|
||||
* @return A card associated with the row, or null if row is not valid.
|
||||
*/
|
||||
nsIAbCard getCardFromRow(in long aRow);
|
||||
|
||||
/// Selects all rows in the view.
|
||||
void selectAll();
|
||||
|
||||
/// Deletes all the selected cards (no prompts are given).
|
||||
void deleteSelectedCards();
|
||||
|
||||
/**
|
||||
* Swaps the first and last name order, and updates the appropriate
|
||||
* preference.
|
||||
*/
|
||||
void swapFirstNameLastName();
|
||||
|
||||
/**
|
||||
* Returns an array of the currently selected addresses.
|
||||
*/
|
||||
readonly attribute nsIArray selectedAddresses;
|
||||
};
|
||||
19
mailnews/addrbook/public/nsIAddbookUrl.idl
Normal file
19
mailnews/addrbook/public/nsIAddbookUrl.idl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- 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.idl"
|
||||
|
||||
[scriptable, uuid(6EB9D874-01AA-11d4-8FBE-000064657374)]
|
||||
interface nsIAddbookUrlOperation
|
||||
{
|
||||
const long InvalidUrl = 0;
|
||||
const long PrintAddressBook = 1;
|
||||
const long AddVCard = 2;
|
||||
};
|
||||
|
||||
[uuid(5f965083-e866-4bfb-ba40-13c344395798)]
|
||||
interface nsIAddbookUrl : nsIURI {
|
||||
readonly attribute long addbookOperation;
|
||||
};
|
||||
35
mailnews/addrbook/public/nsIAddrDBAnnouncer.idl
Normal file
35
mailnews/addrbook/public/nsIAddrDBAnnouncer.idl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
#include "nsIAbCard.idl"
|
||||
#include "nsIAbDirectory.idl"
|
||||
|
||||
interface nsIAddrDBListener;
|
||||
|
||||
[scriptable, uuid(166b19a1-1235-4613-9601-816dedc48c9e)]
|
||||
interface nsIAddrDBAnnouncer : nsISupports {
|
||||
|
||||
void addListener(in nsIAddrDBListener listener);
|
||||
void removeListener(in nsIAddrDBListener listener);
|
||||
|
||||
void notifyCardAttribChange(in unsigned long abCode);
|
||||
|
||||
/**
|
||||
* Notify all the listeners of the database about an event performed
|
||||
* on a card entry.
|
||||
*
|
||||
* @param aAbCode The code to indicate the type of event
|
||||
* (see nsAddrDatabase.h AB_NOTIFY_CODE for values).
|
||||
* @param aCard The card entry on which the event occurred.
|
||||
* @param aParent The parent of card entry. This is set by
|
||||
* object which performs the operation.
|
||||
*/
|
||||
void notifyCardEntryChange(in unsigned long aAbCode,
|
||||
in nsIAbCard aCard,
|
||||
in nsIAbDirectory aParent);
|
||||
|
||||
void notifyAnnouncerGoingAway();
|
||||
};
|
||||
36
mailnews/addrbook/public/nsIAddrDBListener.idl
Normal file
36
mailnews/addrbook/public/nsIAddrDBListener.idl
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/. */
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIAbCard.idl"
|
||||
#include "nsIAbDirectory.idl"
|
||||
|
||||
interface nsIAddrDBAnnouncer;
|
||||
|
||||
[scriptable, uuid(5d7e5a7a-1ac9-46dc-abfd-758c98be26e9)]
|
||||
interface nsIAddrDBListener : nsISupports {
|
||||
|
||||
void onCardAttribChange(in unsigned long abCode);
|
||||
|
||||
/**
|
||||
* Handle the card entry change event.
|
||||
*
|
||||
* @param aAbCode The code to indicate the type of event
|
||||
* (see nsAddrDatabase.h AB_NOTIFY_CODE for values).
|
||||
* @param aCard The card entry on which the event occurred.
|
||||
* @param aParent The parent of card entry.
|
||||
* If set to null, the event can be ignored.
|
||||
* This happens during import & sync operations when
|
||||
* listeners of a database need not be notified about
|
||||
* card entry changes.
|
||||
*/
|
||||
void onCardEntryChange (in unsigned long aAbCode,
|
||||
in nsIAbCard aCard,
|
||||
in nsIAbDirectory aParent);
|
||||
|
||||
void onListEntryChange (in unsigned long abCode,
|
||||
in nsIAbDirectory list);
|
||||
void onAnnouncerGoingAway();
|
||||
|
||||
};
|
||||
311
mailnews/addrbook/public/nsIAddrDatabase.idl
Normal file
311
mailnews/addrbook/public/nsIAddrDatabase.idl
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/* -*- 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 "nsIAddrDBAnnouncer.idl"
|
||||
#include "nsIAbCard.idl"
|
||||
#include "nsIAbDirectory.idl"
|
||||
|
||||
interface nsIFile;
|
||||
interface nsIMdbTableRowCursor;
|
||||
interface nsIMdbEnv;
|
||||
interface nsIMdbRow;
|
||||
interface nsIArray;
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
%{C++
|
||||
// this is the prefix we for attributes that are specific
|
||||
// to the mozilla addressbook, and weren't in 4.x and aren't specified in
|
||||
// RFC 2789. used when exporting and import LDIF
|
||||
// see nsTextAddress.cpp, nsAddressBook.cpp
|
||||
#define MOZ_AB_LDIF_PREFIX "mozilla"
|
||||
|
||||
// note, GeneratedName is not a real column
|
||||
// if you change any of this, make sure to change
|
||||
// Get / Set CardValue in nsAbCardProperty.cpp
|
||||
#define kPhoneticNameColumn "_PhoneticName"
|
||||
#define kAddressCharSetColumn "AddrCharSet"
|
||||
#define kMailListName "ListName"
|
||||
#define kMailListNickName "ListNickName"
|
||||
#define kMailListDescription "ListDescription"
|
||||
#define kMailListTotalAddresses "ListTotalAddresses"
|
||||
// not shown in the UI
|
||||
#define kLowerPriEmailColumn "LowercasePrimaryEmail"
|
||||
#define kLower2ndEmailColumn "LowercaseSecondEmail"
|
||||
|
||||
// Palm Integration
|
||||
#define CARD_ATTRIB_PALMID "PalmRecId"
|
||||
#define CARD_ATTRIB_DISPLAY "DisplayName"
|
||||
|
||||
%}
|
||||
|
||||
[scriptable, uuid(20d4c6c3-0460-403e-aa9c-813654641566)]
|
||||
interface nsAddrDBCommitType
|
||||
{
|
||||
const long kLargeCommit = 1;
|
||||
const long kSessionCommit = 2;
|
||||
const long kCompressCommit = 3;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c54973e4-d251-4b93-a0d0-81a616225061)]
|
||||
interface nsIAddrDatabase : nsIAddrDBAnnouncer {
|
||||
|
||||
/**
|
||||
* Path to the address book database that this instance represents.
|
||||
*/
|
||||
attribute nsIFile dbPath;
|
||||
nsIAddrDatabase open(in nsIFile dbFile, in boolean create, in boolean upgrading);
|
||||
|
||||
void close(in boolean forceCommit);
|
||||
|
||||
/**
|
||||
* Open the MDB database synchronously creating it if required. If
|
||||
* successful, this routine will set up the m_mdbStore and m_mdbEnv of the
|
||||
* database object so other database calls can work.
|
||||
*
|
||||
* @param dbName The location of the database file
|
||||
* to open.
|
||||
* @param create If set to true, will create the
|
||||
* database file if it does not
|
||||
* already exist.
|
||||
* @exception NS_ERROR_FILE_NOT_FOUND The file was not found at the
|
||||
* specified location (and create was
|
||||
* false).
|
||||
* @exception NS_ERROR_FILE_ACCESS_DENIED The file could not be opened as
|
||||
* access was denied.
|
||||
*/
|
||||
void openMDB(in nsIFile dbName, in boolean create);
|
||||
void closeMDB(in boolean commit);
|
||||
|
||||
void commit(in unsigned long commitType);
|
||||
void forceClosed();
|
||||
|
||||
/**
|
||||
* Create a new card and add to the database
|
||||
*
|
||||
* @param aNewCard the card to be added
|
||||
* @param aNotify if set to true, all the listeners of the
|
||||
* database will be notified.
|
||||
* @param aParent parent directory or mailing list to which the
|
||||
* card is added. If set to null, listeners of the
|
||||
* database will not be notified of card creation.
|
||||
*/
|
||||
void createNewCardAndAddToDB(in nsIAbCard aNewCard, in boolean aNotify, in nsIAbDirectory aParent);
|
||||
|
||||
void createNewListCardAndAddToDB(in nsIAbDirectory list, in unsigned long listRowID, in nsIAbCard newCard, in boolean aNotify);
|
||||
|
||||
/**
|
||||
* Create a new mailing list and add to the database
|
||||
*
|
||||
* @param aNewList the mailing list to be added.
|
||||
* @param aNotify if set to true, all the listeners of the
|
||||
* database will be notified.
|
||||
* @param aParent parent directory to which the mailing list
|
||||
* is added. If set to null, listeners of the database
|
||||
* will not be notified of mailing list creation.
|
||||
*/
|
||||
void createMailListAndAddToDB(in nsIAbDirectory aNewList, in boolean aNotify, in nsIAbDirectory aParent);
|
||||
|
||||
/**
|
||||
* Enumerate the cards in the directory. The enumerator will return the
|
||||
* cards associated with mailing lists too.
|
||||
*
|
||||
* @param directory the directory of which to enumerate the cards.
|
||||
* @return an enumerator.
|
||||
*/
|
||||
nsISimpleEnumerator enumerateCards(in nsIAbDirectory directory);
|
||||
|
||||
/**
|
||||
* Enumerate the cards associated with the mailing lists in the directory.
|
||||
*
|
||||
* @param directory the directory of which to enumerate the cards.
|
||||
* @return an enumerator.
|
||||
*/
|
||||
nsISimpleEnumerator enumerateListAddresses(in nsIAbDirectory directory);
|
||||
|
||||
void getMailingListsFromDB(in nsIAbDirectory parentDir);
|
||||
|
||||
/**
|
||||
* Delete a card from the database.
|
||||
*
|
||||
* @param aCard the card to be deleted.
|
||||
* @param aNotify if set to true, all the listeners of the
|
||||
* database will be notified.
|
||||
* @param aParent parent directory from which the card
|
||||
* is to be deleted. If set to null, listeners of
|
||||
* the database will not be notified of card deletion.
|
||||
*/
|
||||
void deleteCard(in nsIAbCard aCard, in boolean aNotify, in nsIAbDirectory aParent);
|
||||
|
||||
/**
|
||||
* Edit a card in the database.
|
||||
*
|
||||
* @param aCard the card to be edited.
|
||||
* @param aNotify if set to true, all the listeners of the
|
||||
* database will be notified.
|
||||
* @param aParent parent directory in which the card
|
||||
* is to be edited. If set to null, listeners of
|
||||
* the database will not be notified of card entry
|
||||
* change.
|
||||
*/
|
||||
void editCard(in nsIAbCard aCard, in boolean aNotify, in nsIAbDirectory aParent);
|
||||
boolean containsCard(in nsIAbCard card);
|
||||
/**
|
||||
* Deletes a mailing list from the directory
|
||||
*
|
||||
* @param aMailList The nsIAbDirectory implementation of the mailing
|
||||
* list that is to be deleted.
|
||||
* @param aParent The parent of the mailing list that is being
|
||||
* deleted. If this is supplied, then a notification
|
||||
* of card entry change in the database will be made.
|
||||
*/
|
||||
void deleteMailList(in nsIAbDirectory aMailList,
|
||||
[optional] in nsIAbDirectory aParent);
|
||||
void editMailList(in nsIAbDirectory mailList, in nsIAbCard listCard, in boolean aNotify);
|
||||
boolean containsMailList(in nsIAbDirectory mailList);
|
||||
void deleteCardFromMailList(in nsIAbDirectory mailList, in nsIAbCard card, in boolean aNotify);
|
||||
|
||||
/**
|
||||
* Gets the first card which matches the attribute/value pair supplied.
|
||||
*
|
||||
* @param aDirectory The current nsIAbDirectory associated with this
|
||||
* instance of the database.
|
||||
* @param aName The attribute to look up the value in.
|
||||
* @param aUTF8Value The value to look up in UTF8 format.
|
||||
* @param aCaseInsensitive Set to true for case-insenstive matching.
|
||||
* @result Returns an nsIAbCard if one is found, otherwise
|
||||
* NULL.
|
||||
*/
|
||||
nsIAbCard getCardFromAttribute(in nsIAbDirectory aDirectory, in string aName,
|
||||
in AUTF8String aUTF8Value,
|
||||
in boolean aCaseInsensitive);
|
||||
|
||||
/**
|
||||
* Gets all cards which matches the attribute/value pair supplied.
|
||||
*
|
||||
* @param aDirectory The current nsIAbDirectory associated with this
|
||||
* instance of the database.
|
||||
* @param aName The attribute to look up the value in.
|
||||
* @param aUTF8Value The value to look up in UTF8 format.
|
||||
* @param aCaseInsensitive Set to true for case-insenstive matching.
|
||||
* @result Returns an nsISimpleEnumerator of nsIAbCard
|
||||
* instances.
|
||||
*/
|
||||
nsISimpleEnumerator getCardsFromAttribute(in nsIAbDirectory aDirectory,
|
||||
in string aName,
|
||||
in AUTF8String uUTF8Value,
|
||||
in boolean aCaseInsensitive);
|
||||
|
||||
boolean findMailListbyUnicodeName(in wstring listName);
|
||||
|
||||
void getCardCount(out uint32_t count);
|
||||
|
||||
[noscript] readonly attribute nsIMdbRow newRow;
|
||||
[noscript] readonly attribute nsIMdbRow newListRow;
|
||||
[noscript] void addCardRowToDB(in nsIMdbRow newRow);
|
||||
[noscript] void addLdifListMember(in nsIMdbRow row, in string value);
|
||||
[noscript] void addFirstName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addLastName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPhoneticFirstName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPhoneticLastName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addDisplayName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addNickName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPrimaryEmail(in nsIMdbRow row, in string value);
|
||||
[noscript] void add2ndEmail(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkPhone(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomePhone(in nsIMdbRow row, in string value);
|
||||
[noscript] void addFaxNumber(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPagerNumber(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCellularNumber(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkPhoneType(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomePhoneType(in nsIMdbRow row, in string value);
|
||||
[noscript] void addFaxNumberType(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPagerNumberType(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCellularNumberType(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeAddress(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeAddress2(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeCity(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeState(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeZipCode(in nsIMdbRow row, in string value);
|
||||
[noscript] void addHomeCountry(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkAddress(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkAddress2(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkCity(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkState(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkZipCode(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWorkCountry(in nsIMdbRow row, in string value);
|
||||
[noscript] void addJobTitle(in nsIMdbRow row, in string value);
|
||||
[noscript] void addDepartment(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCompany(in nsIMdbRow row, in string value);
|
||||
[noscript] void addAimScreenName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addAnniversaryYear(in nsIMdbRow row, in string value);
|
||||
[noscript] void addAnniversaryMonth(in nsIMdbRow row, in string value);
|
||||
[noscript] void addAnniversaryDay(in nsIMdbRow row, in string value);
|
||||
[noscript] void addSpouseName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addFamilyName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addDefaultAddress(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCategory(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWebPage1(in nsIMdbRow row, in string value);
|
||||
[noscript] void addWebPage2(in nsIMdbRow row, in string value);
|
||||
[noscript] void addBirthYear(in nsIMdbRow row, in string value);
|
||||
[noscript] void addBirthMonth(in nsIMdbRow row, in string value);
|
||||
[noscript] void addBirthDay(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCustom1(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCustom2(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCustom3(in nsIMdbRow row, in string value);
|
||||
[noscript] void addCustom4(in nsIMdbRow row, in string value);
|
||||
[noscript] void addNotes(in nsIMdbRow row, in string value);
|
||||
[noscript] void addPreferMailFormat(in nsIMdbRow row, in unsigned long value);
|
||||
[noscript] void addPopularityIndex(in nsIMdbRow row, in unsigned long value);
|
||||
|
||||
[noscript] void addListName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addListNickName(in nsIMdbRow row, in string value);
|
||||
[noscript] void addListDescription(in nsIMdbRow row, in string value);
|
||||
[noscript] void addListDirNode(in nsIMdbRow listRow);
|
||||
|
||||
/**
|
||||
* use for getting and setting generic string attributes
|
||||
* like _AimScreenName
|
||||
*/
|
||||
void setCardValue(in nsIAbCard card, in string name, in wstring value, in boolean notify);
|
||||
wstring getCardValue(in nsIAbCard card, in string name);
|
||||
|
||||
/**
|
||||
* Returns an array of the deleted cards currently stored in the mork file.
|
||||
*/
|
||||
readonly attribute nsIArray deletedCardList;
|
||||
|
||||
/**
|
||||
* Returns the count of the deleted card currently stored in the mork file.
|
||||
*/
|
||||
readonly attribute unsigned long deletedCardCount;
|
||||
|
||||
/**
|
||||
* Add the column representing the card to the mailing list row
|
||||
* in the database.
|
||||
*
|
||||
* @param aPCard the card to be added.
|
||||
* @param aPListRow the row to which the column will be added.
|
||||
* @param aPos the position of the card in the mailing list.
|
||||
* @param aPNewCard a pointer to hold the new card added to the row.
|
||||
* @param aInMailingList If set to true, the card is already present
|
||||
* in the mailing list
|
||||
* @param aParent parent mailing list to which the card
|
||||
* is added. If set to null, listeners of the
|
||||
* database will not be notified of card creation.
|
||||
* @param aRoot If the card is created while creating a new mailing
|
||||
* list, its set to the parent addressbook.
|
||||
* Set to null in other case.
|
||||
*/
|
||||
void AddListCardColumnsToRow(in nsIAbCard aPCard,
|
||||
in nsIMdbRow aPListRow,
|
||||
in unsigned long aPos,
|
||||
out nsIAbCard aPNewCard,
|
||||
in boolean aInMailingList,
|
||||
in nsIAbDirectory aParent,
|
||||
in nsIAbDirectory aRoot);
|
||||
void InitCardFromRow(in nsIAbCard aNewCard,in nsIMdbRow aCardRow);
|
||||
void SetListAddressTotal(in nsIMdbRow aListRow, in uint32_t aTotal);
|
||||
nsIMdbRow FindRowByCard(in nsIAbCard aCard);
|
||||
};
|
||||
29
mailnews/addrbook/public/nsIMsgVCardService.idl
Normal file
29
mailnews/addrbook/public/nsIMsgVCardService.idl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
%{C++
|
||||
#include "nsVCardObj.h"
|
||||
%}
|
||||
|
||||
[ptr] native VObject_ptr(VObject);
|
||||
[ptr] native VObjectIterator_ptr(VObjectIterator);
|
||||
[ptr] native const_char_ptr(const char);
|
||||
|
||||
[uuid(8b6ae917-676d-4f1f-bbad-2ecc9be0d9b1)]
|
||||
interface nsIMsgVCardService : nsISupports {
|
||||
[noscript, notxpcom] void cleanVObject(in VObject_ptr o);
|
||||
[noscript, notxpcom] VObject_ptr nextVObjectInList(in VObject_ptr o);
|
||||
[noscript, notxpcom] VObject_ptr parse_MIME(in string input, in unsigned long len);
|
||||
[noscript, notxpcom] charPtr fakeCString(in VObject_ptr o);
|
||||
[noscript, notxpcom] VObject_ptr isAPropertyOf(in VObject_ptr o, in string id);
|
||||
[noscript, notxpcom] charPtr writeMemoryVObjects(in string s, out long len, in VObject_ptr list, in boolean expandSpaces);
|
||||
[noscript, notxpcom] VObject_ptr nextVObject(in VObjectIterator_ptr i);
|
||||
[noscript, notxpcom] void initPropIterator(in VObjectIterator_ptr i, in VObject_ptr o);
|
||||
[noscript, notxpcom] long moreIteration(in VObjectIterator_ptr i);
|
||||
[noscript, notxpcom] const_char_ptr vObjectName(in VObject_ptr o);
|
||||
[noscript, notxpcom] charPtr vObjectAnyValue(in VObject_ptr o);
|
||||
};
|
||||
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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue