summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/addrbook/prefs/content/pref-directory-add.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/addrbook/prefs/content/pref-directory-add.js')
-rw-r--r--comm/mailnews/addrbook/prefs/content/pref-directory-add.js454
1 files changed, 454 insertions, 0 deletions
diff --git a/comm/mailnews/addrbook/prefs/content/pref-directory-add.js b/comm/mailnews/addrbook/prefs/content/pref-directory-add.js
new file mode 100644
index 0000000000..23bee12a0e
--- /dev/null
+++ b/comm/mailnews/addrbook/prefs/content/pref-directory-add.js
@@ -0,0 +1,454 @@
+/* -*- Mode: JavaScript; 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/. */
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { isLegalHostNameOrIP, cleanUpHostName } = ChromeUtils.import(
+ "resource:///modules/hostnameUtils.jsm"
+);
+
+var gCurrentDirectory = null;
+var gReplicationBundle = null;
+var gReplicationService = Cc[
+ "@mozilla.org/addressbook/ldap-replication-service;1"
+].getService(Ci.nsIAbLDAPReplicationService);
+var gReplicationCancelled = false;
+var gProgressText;
+var gProgressMeter;
+var gDownloadInProgress = false;
+
+var kDefaultLDAPPort = 389;
+var kDefaultSecureLDAPPort = 636;
+
+window.addEventListener("DOMContentLoaded", Startup);
+window.addEventListener("unload", onUnload);
+document.addEventListener("dialogaccept", onAccept);
+document.addEventListener("dialogcancel", onCancel);
+
+var ldapOfflineObserver = {
+ observe(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] &&
+ window.arguments[0].selectedDirectory
+ ) {
+ 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"
+ );
+
+ // 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] &&
+ window.arguments[0].selectedDirectory &&
+ !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(aWebProgress, aRequest, aStateFlags, aStatus) {
+ if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
+ // start the spinning
+ gProgressMeter.removeAttribute("value");
+ 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 & Ci.nsIWebProgressListener.STATE_STOP) {
+ EndDownload(aStatus);
+ }
+ },
+ onProgressChange(
+ aWebProgress,
+ aRequest,
+ aCurSelfProgress,
+ aMaxSelfProgress,
+ aCurTotalProgress,
+ aMaxTotalProgress
+ ) {
+ gProgressText.value = gReplicationBundle.getFormattedString(
+ "currentCount",
+ [aCurSelfProgress]
+ );
+ },
+ onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {},
+ onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {},
+ onSecurityChange(aWebProgress, aRequest, state) {},
+ onContentBlockingEvent(aWebProgress, aRequest, aEvent) {},
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+};
+
+function DownloadNow() {
+ if (!gDownloadInProgress) {
+ gProgressText = document.getElementById("replicationProgressText");
+ gProgressMeter = document.getElementById("replicationProgressMeter");
+
+ gProgressText.hidden = false;
+ gProgressMeter.hidden = false;
+ gReplicationCancelled = false;
+
+ try {
+ if (gCurrentDirectory instanceof Ci.nsIAbLDAPDirectory) {
+ gReplicationService.startReplication(
+ gCurrentDirectory,
+ progressListener
+ );
+ } else {
+ EndDownload(Cr.NS_ERROR_FAILURE);
+ }
+ } catch (ex) {
+ EndDownload(Cr.NS_ERROR_FAILURE);
+ }
+ } else {
+ gReplicationCancelled = true;
+ try {
+ gReplicationService.cancelReplication(gCurrentDirectory);
+ } 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.value = 100;
+ gProgressMeter.hidden = true;
+
+ gDownloadInProgress = false;
+ if (Components.isSuccessCode(aStatus)) {
+ gProgressText.value = gReplicationBundle.getString("replicationSucceeded");
+ } else if (gReplicationCancelled) {
+ gProgressText.value = gReplicationBundle.getString("replicationCancelled");
+ } else {
+ gProgressText.value = gReplicationBundle.getString("replicationFailed");
+ }
+}
+
+// fill the settings panel with the data from the preferences.
+//
+function fillSettings() {
+ document.getElementById("description").value = gCurrentDirectory.dirName;
+
+ if (gCurrentDirectory instanceof Ci.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 Ci.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;
+ 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;
+ }
+ return true;
+}
+
+function onAccept(event) {
+ try {
+ let description = document.getElementById("description").value.trim();
+ let hostname = cleanUpHostName(document.getElementById("hostname").value);
+ let port = document.getElementById("port").value;
+ let secure = document.getElementById("secure");
+ let results = document.getElementById("results").value;
+ let errorValue = null;
+ let errorArg = null;
+ let saslMechanism = "";
+
+ let findDupeName = function (newName) {
+ // Do not allow an already existing name.
+ for (let ab of MailServices.ab.directories) {
+ if (
+ ab.dirName.toLowerCase() == newName.toLowerCase() &&
+ (!gCurrentDirectory || ab.URI != gCurrentDirectory.URI)
+ ) {
+ return ab.dirName;
+ }
+ }
+ return null;
+ };
+
+ if (!description) {
+ errorValue = "invalidName";
+ } else if ((errorArg = findDupeName(description))) {
+ errorValue = "duplicateNameText";
+ } else if (!isLegalHostNameOrIP(hostname)) {
+ errorValue = "invalidHostname";
+ } else if (port && hasCharacters(port)) {
+ // XXX write isValidDn and call it on the dn string here?
+ errorValue = "invalidPortNumber";
+ } else if (results && hasCharacters(results)) {
+ errorValue = "invalidResults";
+ }
+
+ if (!errorValue) {
+ if (!port) {
+ port = secure.checked ? kDefaultSecureLDAPPort : kDefaultLDAPPort;
+ }
+ if (hostname.includes(":")) {
+ // Wrap IPv6 address in [].
+ hostname = `[${hostname}]`;
+ }
+ let ldapUrl = Services.io
+ .newURI(`${secure.checked ? "ldaps" : "ldap"}://${hostname}:${port}`)
+ .QueryInterface(Ci.nsILDAPURL);
+
+ ldapUrl.dn = document.getElementById("basedn").value;
+ ldapUrl.scope = document.getElementById("one").selected
+ ? Ci.nsILDAPURL.SCOPE_ONELEVEL
+ : Ci.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;
+ window.opener.gNewServerString = gCurrentDirectory.dirPrefId;
+ } else {
+ // adding a new directory
+ window.opener.gNewServerString = MailServices.ab.newAddressBook(
+ description,
+ ldapUrl.spec,
+ Ci.nsIAbManager.LDAP_DIRECTORY_TYPE
+ );
+ }
+
+ // 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(Ci.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;
+ window.arguments[0].newDirectoryUID = theDirectory.UID;
+ if ("onNewDirectory" in window.arguments[0]) {
+ window.arguments[0].onNewDirectory(theDirectory);
+ }
+ } else {
+ let addressBookBundle = document.getElementById("bundle_addressBook");
+
+ let errorText;
+ if (errorArg) {
+ errorText = addressBookBundle.getFormattedString(errorValue, [
+ errorArg,
+ ]);
+ } else {
+ errorText = addressBookBundle.getString(errorValue);
+ }
+
+ Services.prompt.alert(window, document.title, errorText);
+ event.preventDefault();
+ return;
+ }
+ } catch (outer) {
+ console.error(
+ "Internal error in pref-directory-add.js:onAccept() " + outer
+ );
+ }
+}
+
+function onCancel() {
+ window.opener.gUpdate = false;
+}
+
+// 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;
+}