summaryrefslogtreecommitdiffstats
path: root/mailnews/addrbook/prefs/content
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/addrbook/prefs/content')
-rw-r--r--mailnews/addrbook/prefs/content/pref-directory-add.js394
-rw-r--r--mailnews/addrbook/prefs/content/pref-directory-add.xul152
-rw-r--r--mailnews/addrbook/prefs/content/pref-editdirectories.js142
-rw-r--r--mailnews/addrbook/prefs/content/pref-editdirectories.xul43
4 files changed, 731 insertions, 0 deletions
diff --git a/mailnews/addrbook/prefs/content/pref-directory-add.js b/mailnews/addrbook/prefs/content/pref-directory-add.js
new file mode 100644
index 000000000..011b8aed9
--- /dev/null
+++ b/mailnews/addrbook/prefs/content/pref-directory-add.js
@@ -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;
+}
diff --git a/mailnews/addrbook/prefs/content/pref-directory-add.xul b/mailnews/addrbook/prefs/content/pref-directory-add.xul
new file mode 100644
index 000000000..33fe0cd31
--- /dev/null
+++ b/mailnews/addrbook/prefs/content/pref-directory-add.xul
@@ -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>
+
diff --git a/mailnews/addrbook/prefs/content/pref-editdirectories.js b/mailnews/addrbook/prefs/content/pref-editdirectories.js
new file mode 100644
index 000000000..dfb3e0559
--- /dev/null
+++ b/mailnews/addrbook/prefs/content/pref-editdirectories.js
@@ -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);
+}
diff --git a/mailnews/addrbook/prefs/content/pref-editdirectories.xul b/mailnews/addrbook/prefs/content/pref-editdirectories.xul
new file mode 100644
index 000000000..43ca17a95
--- /dev/null
+++ b/mailnews/addrbook/prefs/content/pref-editdirectories.xul
@@ -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>