summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/base/prefs/content/am-server.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/base/prefs/content/am-server.js')
-rw-r--r--comm/mailnews/base/prefs/content/am-server.js615
1 files changed, 615 insertions, 0 deletions
diff --git a/comm/mailnews/base/prefs/content/am-server.js b/comm/mailnews/base/prefs/content/am-server.js
new file mode 100644
index 0000000000..f73535b35c
--- /dev/null
+++ b/comm/mailnews/base/prefs/content/am-server.js
@@ -0,0 +1,615 @@
+/* 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/. */
+
+/* import-globals-from am-prefs.js */
+/* import-globals-from amUtils.js */
+
+var { MailUtils } = ChromeUtils.import("resource:///modules/MailUtils.jsm");
+
+var gServer;
+var gOriginalStoreType;
+
+/**
+ * Called when the store type menu is clicked.
+ *
+ * @param {object} aStoreTypeElement - store type menu list element.
+ */
+function clickStoreTypeMenu(aStoreTypeElement) {
+ if (aStoreTypeElement.value == gOriginalStoreType) {
+ return;
+ }
+
+ // Response from migration dialog modal. If the conversion is complete
+ // 'response.newRootFolder' will hold the path to the new account root folder,
+ // otherwise 'response.newRootFolder' will be null.
+ let response = { newRootFolder: null };
+ // Send 'response' as an argument to converterDialog.xhtml.
+ window.browsingContext.topChromeWindow.openDialog(
+ "converterDialog.xhtml",
+ "mailnews:mailstoreconverter",
+ "modal,centerscreen,resizable=no,width=700,height=130",
+ gServer,
+ aStoreTypeElement.value,
+ response
+ );
+ changeStoreType(response);
+}
+
+/**
+ * Revert store type to the original store type if converter modal closes
+ * before migration is complete, otherwise change original store type to
+ * currently selected store type.
+ *
+ * @param {object} aResponse - response from migration dialog modal.
+ */
+function changeStoreType(aResponse) {
+ if (aResponse.newRootFolder) {
+ // The conversion is complete.
+ // Set local path to the new account root folder which is present
+ // in 'aResponse.newRootFolder'.
+ if (gServer.type == "nntp") {
+ let newRootFolder = aResponse.newRootFolder;
+ let lastSlash = newRootFolder.lastIndexOf("/");
+ let newsrc =
+ newRootFolder.slice(0, lastSlash) +
+ "/newsrc-" +
+ newRootFolder.slice(lastSlash + 1);
+ document.getElementById("nntp.newsrcFilePath").value = newsrc;
+ }
+
+ document.getElementById("server.localPath").value = aResponse.newRootFolder;
+ gOriginalStoreType = document.getElementById(
+ "server.storeTypeMenulist"
+ ).value;
+ MailUtils.restartApplication();
+ } else {
+ // The conversion failed or was cancelled.
+ // Restore selected item to what was selected before conversion.
+ document.getElementById("server.storeTypeMenulist").value =
+ gOriginalStoreType;
+ }
+}
+
+function onSave() {
+ let storeContractID = document.getElementById("server.storeTypeMenulist")
+ .selectedItem.value;
+ document
+ .getElementById("server.storeContractID")
+ .setAttribute("value", storeContractID);
+}
+
+function onInit(aPageId, aServerId) {
+ initServerType();
+
+ onCheckItem("server.biffMinutes", ["server.doBiff"]);
+ onCheckItem("nntp.maxArticles", ["nntp.notifyOn"]);
+ setupMailOnServerUI();
+ setupFixedUI();
+ let serverType = document.getElementById("server.type").getAttribute("value");
+ if (serverType == "imap") {
+ setupImapDeleteUI(aServerId);
+ }
+
+ // OAuth2 are only supported on IMAP and POP.
+ document.getElementById("authMethod-oauth2").hidden =
+ serverType != "imap" && serverType != "pop3";
+ // TLS Cert (External) only supported on IMAP.
+ document.getElementById("authMethod-external").hidden = serverType != "imap";
+
+ // "STARTTLS, if available" is vulnerable to MITM attacks so we shouldn't
+ // allow users to choose it anymore. Hide the option unless the user already
+ // has it set.
+ hideUnlessSelected(document.getElementById("connectionSecurityType-1"));
+
+ // UI for account store type.
+ let storeTypeElement = document.getElementById("server.storeTypeMenulist");
+ // set the menuitem to match the account
+ let currentStoreID = document
+ .getElementById("server.storeContractID")
+ .getAttribute("value");
+ let targetItem = storeTypeElement.getElementsByAttribute(
+ "value",
+ currentStoreID
+ );
+ storeTypeElement.selectedItem = targetItem[0];
+ // Disable store type change if store has not been used yet.
+ storeTypeElement.setAttribute(
+ "disabled",
+ gServer.getBoolValue("canChangeStoreType")
+ ? "false"
+ : !Services.prefs.getBoolPref("mail.store_conversion_enabled")
+ );
+ // Initialise 'gOriginalStoreType' to the item that was originally selected.
+ gOriginalStoreType = storeTypeElement.value;
+}
+
+function onPreInit(account, accountValues) {
+ var type = parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "type",
+ null,
+ false
+ );
+ hideShowControls(type);
+
+ gServer = account.incomingServer;
+}
+
+function initServerType() {
+ var serverType = document.getElementById("server.type").getAttribute("value");
+ var propertyName = "serverType-" + serverType;
+
+ var messengerBundle = document.getElementById("bundle_messenger");
+ var verboseName;
+ try {
+ verboseName = messengerBundle.getString(propertyName);
+ } catch (e) {
+ // Addon-provided server types do not have a description string,
+ // then display the raw server type.
+ verboseName = serverType;
+ }
+ setDivText("servertypeVerbose", verboseName);
+
+ secureSelect(true);
+
+ setLabelFromStringBundle("authMethod-no", "authNo");
+ setLabelFromStringBundle("authMethod-old", "authOld");
+ setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
+ setLabelFromStringBundle("authMethod-external", "authExternal");
+ setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
+ setLabelFromStringBundle("authMethod-oauth2", "authOAuth2");
+ setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
+ setLabelFromStringBundle("authMethod-any", "authAny");
+ setLabelFromStringBundle(
+ "authMethod-password-encrypted",
+ "authPasswordEncrypted"
+ );
+ // authMethod-password-cleartext already set in secureSelect()
+
+ // Hide deprecated/hidden auth options, unless selected
+ hideUnlessSelected(document.getElementById("authMethod-no"));
+ hideUnlessSelected(document.getElementById("authMethod-old"));
+ hideUnlessSelected(document.getElementById("authMethod-anysecure"));
+ hideUnlessSelected(document.getElementById("authMethod-any"));
+}
+
+function hideUnlessSelected(element) {
+ element.hidden = !element.selected;
+}
+
+function setLabelFromStringBundle(elementID, stringName) {
+ document.getElementById(elementID).label = document
+ .getElementById("bundle_messenger")
+ .getString(stringName);
+}
+
+function setDivText(divname, value) {
+ var div = document.getElementById(divname);
+ if (!div) {
+ return;
+ }
+ div.setAttribute("value", value);
+}
+
+function onAdvanced() {
+ // Store the server type and, if an IMAP or POP3 server,
+ // the settings needed for the IMAP/POP3 tab into the array
+ var serverSettings = {};
+ var serverType = document.getElementById("server.type").getAttribute("value");
+ serverSettings.serverType = serverType;
+
+ serverSettings.serverPrettyName = gServer.prettyName;
+ serverSettings.account = top.getCurrentAccount();
+
+ if (serverType == "imap") {
+ serverSettings.dualUseFolders = document.getElementById(
+ "imap.dualUseFolders"
+ ).checked;
+ serverSettings.usingSubscription = document.getElementById(
+ "imap.usingSubscription"
+ ).checked;
+ serverSettings.maximumConnectionsNumber = document
+ .getElementById("imap.maximumConnectionsNumber")
+ .getAttribute("value");
+ serverSettings.personalNamespace = document
+ .getElementById("imap.personalNamespace")
+ .getAttribute("value");
+ serverSettings.publicNamespace = document
+ .getElementById("imap.publicNamespace")
+ .getAttribute("value");
+ serverSettings.serverDirectory = document
+ .getElementById("imap.serverDirectory")
+ .getAttribute("value");
+ serverSettings.otherUsersNamespace = document
+ .getElementById("imap.otherUsersNamespace")
+ .getAttribute("value");
+ serverSettings.overrideNamespaces = document.getElementById(
+ "imap.overrideNamespaces"
+ ).checked;
+ } else if (serverType == "pop3") {
+ serverSettings.deferGetNewMail = document.getElementById(
+ "pop3.deferGetNewMail"
+ ).checked;
+ serverSettings.deferredToAccount = document
+ .getElementById("pop3.deferredToAccount")
+ .getAttribute("value");
+ }
+
+ let onCloseAdvanced = function () {
+ if (serverType == "imap") {
+ document.getElementById("imap.dualUseFolders").checked =
+ serverSettings.dualUseFolders;
+ document.getElementById("imap.usingSubscription").checked =
+ serverSettings.usingSubscription;
+ document
+ .getElementById("imap.maximumConnectionsNumber")
+ .setAttribute("value", serverSettings.maximumConnectionsNumber);
+ document
+ .getElementById("imap.personalNamespace")
+ .setAttribute("value", serverSettings.personalNamespace);
+ document
+ .getElementById("imap.publicNamespace")
+ .setAttribute("value", serverSettings.publicNamespace);
+ document
+ .getElementById("imap.serverDirectory")
+ .setAttribute("value", serverSettings.serverDirectory);
+ document
+ .getElementById("imap.otherUsersNamespace")
+ .setAttribute("value", serverSettings.otherUsersNamespace);
+ document.getElementById("imap.overrideNamespaces").checked =
+ serverSettings.overrideNamespaces;
+ } else if (serverType == "pop3") {
+ document.getElementById("pop3.deferGetNewMail").checked =
+ serverSettings.deferGetNewMail;
+ document
+ .getElementById("pop3.deferredToAccount")
+ .setAttribute("value", serverSettings.deferredToAccount);
+ let pop3Server = gServer.QueryInterface(Ci.nsIPop3IncomingServer);
+ // we're explicitly setting this so we'll go through the SetDeferredToAccount method
+ pop3Server.deferredToAccount = serverSettings.deferredToAccount;
+ // Setting the server to be deferred causes a rebuild of the account tree,
+ // losing the current selection. Reselect the current server again as it
+ // didn't really disappear.
+ parent.selectServer(
+ parent.getCurrentAccount().incomingServer,
+ parent.currentPageId
+ );
+
+ // Iterate over all accounts to see if any of their junk targets are now
+ // invalid (pointed to the account that is now deferred).
+ // If any such target is found it is reset to a new safe folder
+ // (the deferred to account or Local Folders). If junk was really moved
+ // to that folder (moveOnSpam = true) then moving junk is disabled
+ // (so that the user notices it and checks the settings).
+ // This is the same sanitization as in am-junk.js, just applied to all POP accounts.
+ let deferredURI =
+ serverSettings.deferredToAccount &&
+ MailServices.accounts.getAccount(serverSettings.deferredToAccount)
+ .incomingServer.serverURI;
+
+ for (let account of MailServices.accounts.accounts) {
+ let accountValues = parent.getValueArrayFor(account);
+ let type = parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "type",
+ null,
+ false
+ );
+ // Try to keep this list of account types not having Junk settings
+ // synchronized with the list in AccountManager.js.
+ if (type != "nntp" && type != "rss" && type != "im") {
+ let spamActionTargetAccount = parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "spamActionTargetAccount",
+ "string",
+ true
+ );
+ let spamActionTargetFolder = parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "spamActionTargetFolder",
+ "wstring",
+ true
+ );
+ let moveOnSpam = parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "moveOnSpam",
+ "bool",
+ true
+ );
+
+ // Check if there are any invalid junk targets and fix them.
+ [spamActionTargetAccount, spamActionTargetFolder, moveOnSpam] =
+ sanitizeJunkTargets(
+ spamActionTargetAccount,
+ spamActionTargetFolder,
+ deferredURI || account.incomingServer.serverURI,
+ parent.getAccountValue(
+ account,
+ accountValues,
+ "server",
+ "moveTargetMode",
+ "int",
+ true
+ ),
+ account.incomingServer.spamSettings,
+ moveOnSpam
+ );
+
+ parent.setAccountValue(
+ accountValues,
+ "server",
+ "moveOnSpam",
+ moveOnSpam
+ );
+ parent.setAccountValue(
+ accountValues,
+ "server",
+ "spamActionTargetAccount",
+ spamActionTargetAccount
+ );
+ parent.setAccountValue(
+ accountValues,
+ "server",
+ "spamActionTargetFolder",
+ spamActionTargetFolder
+ );
+ }
+ }
+ }
+ document.dispatchEvent(new CustomEvent("prefchange"));
+ };
+
+ parent.gSubDialog.open(
+ "chrome://messenger/content/am-server-advanced.xhtml",
+ { closingCallback: onCloseAdvanced },
+ serverSettings
+ );
+}
+
+function secureSelect(aLoading) {
+ var socketType = document.getElementById("server.socketType").value;
+ var defaultPort = gServer.protocolInfo.getDefaultServerPort(false);
+ var defaultPortSecure = gServer.protocolInfo.getDefaultServerPort(true);
+ var port = document.getElementById("server.port");
+ var portDefault = document.getElementById("defaultPort");
+ var prevDefaultPort = portDefault.value;
+
+ if (socketType == Ci.nsMsgSocketType.SSL) {
+ portDefault.value = defaultPortSecure;
+ if (
+ port.value == "" ||
+ (!aLoading &&
+ port.value == defaultPort &&
+ prevDefaultPort != portDefault.value)
+ ) {
+ port.value = defaultPortSecure;
+ }
+ } else {
+ portDefault.value = defaultPort;
+ if (
+ port.value == "" ||
+ (!aLoading &&
+ port.value == defaultPortSecure &&
+ prevDefaultPort != portDefault.value)
+ ) {
+ port.value = defaultPort;
+ }
+ }
+
+ // switch "insecure password" label
+ setLabelFromStringBundle(
+ "authMethod-password-cleartext",
+ socketType == Ci.nsMsgSocketType.SSL ||
+ socketType == Ci.nsMsgSocketType.alwaysSTARTTLS
+ ? "authPasswordCleartextViaSSL"
+ : "authPasswordCleartextInsecurely"
+ );
+}
+
+function setupMailOnServerUI() {
+ onCheckItem("pop3.deleteMailLeftOnServer", ["pop3.leaveMessagesOnServer"]);
+ setupAgeMsgOnServerUI();
+}
+
+function setupAgeMsgOnServerUI() {
+ const kLeaveMsgsId = "pop3.leaveMessagesOnServer";
+ const kDeleteByAgeId = "pop3.deleteByAgeFromServer";
+ onCheckItem(kDeleteByAgeId, [kLeaveMsgsId]);
+ onCheckItem("daysEnd", [kLeaveMsgsId]);
+ onCheckItem("pop3.numDaysToLeaveOnServer", [kLeaveMsgsId, kDeleteByAgeId]);
+}
+
+function setupFixedUI() {
+ var controls = [
+ document.getElementById("fixedServerName"),
+ document.getElementById("fixedUserName"),
+ document.getElementById("fixedServerPort"),
+ ];
+
+ var len = controls.length;
+ for (let i = 0; i < len; i++) {
+ var fixedElement = controls[i];
+ var otherElement = document.getElementById(
+ fixedElement.getAttribute("use")
+ );
+
+ fixedElement.setAttribute("collapsed", "true");
+ otherElement.removeAttribute("collapsed");
+ }
+}
+
+function BrowseForNewsrc() {
+ const nsIFilePicker = Ci.nsIFilePicker;
+ const nsIFile = Ci.nsIFile;
+
+ var newsrcTextBox = document.getElementById("nntp.newsrcFilePath");
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ fp.init(
+ window,
+ document.getElementById("browseForNewsrc").getAttribute("filepickertitle"),
+ nsIFilePicker.modeSave
+ );
+
+ var currentNewsrcFile;
+ try {
+ currentNewsrcFile = Cc["@mozilla.org/file/local;1"].createInstance(nsIFile);
+ currentNewsrcFile.initWithPath(newsrcTextBox.value);
+ } catch (e) {
+ dump("Failed to create nsIFile instance for the current newsrc file.\n");
+ }
+
+ if (currentNewsrcFile) {
+ fp.displayDirectory = currentNewsrcFile.parent;
+ fp.defaultString = currentNewsrcFile.leafName;
+ }
+
+ fp.appendFilters(nsIFilePicker.filterAll);
+
+ fp.open(rv => {
+ if (rv != nsIFilePicker.returnOK || !fp.file) {
+ return;
+ }
+ newsrcTextBox.value = fp.file.path;
+ newsrcTextBox.dispatchEvent(new CustomEvent("change"));
+ });
+}
+
+function setupImapDeleteUI(aServerId) {
+ // read delete_model preference
+ let deleteModel = document
+ .getElementById("imap.deleteModel")
+ .getAttribute("value");
+ selectImapDeleteModel(deleteModel);
+
+ // read trash folder path preference
+ let trashFolderName = getTrashFolderName();
+
+ // set folderPicker menulist
+ let trashPopup = document.getElementById("msgTrashFolderPopup");
+ trashPopup._teardown();
+ trashPopup._parentFolder = MailUtils.getOrCreateFolder(aServerId);
+ trashPopup._ensureInitialized();
+
+ // Escape backslash and double-quote with another backslash before encoding.
+ let trashEscaped = trashFolderName.replace(/([\\"])/g, "\\$1");
+
+ // Convert the folder path from JS Unicode to MUTF-7 if necessary.
+ let imapServer = trashPopup._parentFolder.server.QueryInterface(
+ Ci.nsIImapIncomingServer
+ );
+
+ let trashFolder;
+ if (imapServer.utf8AcceptEnabled) {
+ // Trash folder with UTF8=ACCEPT capability in effect.
+ trashFolder = MailUtils.getOrCreateFolder(aServerId + "/" + trashEscaped);
+ } else {
+ // Traditional MUTF-7.
+ let manager = Cc["@mozilla.org/charset-converter-manager;1"].getService(
+ Ci.nsICharsetConverterManager
+ );
+ trashFolder = MailUtils.getOrCreateFolder(
+ aServerId + "/" + manager.unicodeToMutf7(trashEscaped)
+ );
+ }
+ trashPopup.selectFolder(trashFolder);
+ trashPopup.parentNode.folder = trashFolder;
+}
+
+function selectImapDeleteModel(choice) {
+ // set deleteModel to selected mode
+ document.getElementById("imap.deleteModel").setAttribute("value", choice);
+
+ switch (choice) {
+ case "0": // markDeleted
+ // disable folderPicker
+ document
+ .getElementById("msgTrashFolderPicker")
+ .setAttribute("disabled", "true");
+ break;
+ case "1": // moveToTrashFolder
+ // enable folderPicker
+ document
+ .getElementById("msgTrashFolderPicker")
+ .removeAttribute("disabled");
+ break;
+ case "2": // deleteImmediately
+ // disable folderPicker
+ document
+ .getElementById("msgTrashFolderPicker")
+ .setAttribute("disabled", "true");
+ break;
+ default:
+ dump("Error in enabling/disabling server.TrashFolderPicker\n");
+ break;
+ }
+}
+
+// Capture any menulist changes from folderPicker
+function folderPickerChange(aEvent) {
+ let folder = aEvent.target._folder;
+ // Since we need to deal with localised folder names, we simply use
+ // the path of the URI like we do in nsImapIncomingServer::DiscoveryDone().
+ // Note that the path is returned with a leading slash which we need to remove.
+ let folderPath = Services.io.newURI(folder.URI).pathQueryRef.substring(1);
+ let folderPathUnescaped = Services.io.unescapeString(
+ folderPath,
+ Ci.nsINetUtil.ESCAPE_URL_PATH
+ );
+
+ // Convert the folder path from MUTF-7 or UTF-8 to Unicode.
+ let imapServer = folder.server.QueryInterface(Ci.nsIImapIncomingServer);
+
+ let trashUnicode;
+ if (imapServer.utf8AcceptEnabled) {
+ // UTF8=ACCEPT capability in effect. Unescaping has brought back
+ // raw UTF-8 bytes, so convert them to JS Unicode.
+ let typedarray = new Uint8Array(folderPathUnescaped.length);
+ for (let i = 0; i < folderPathUnescaped.length; i++) {
+ typedarray[i] = folderPathUnescaped.charCodeAt(i);
+ }
+ let utf8Decoder = new TextDecoder("utf-8");
+ trashUnicode = utf8Decoder.decode(typedarray);
+ } else {
+ // We need to convert that from MUTF-7 to Unicode.
+ let manager = Cc["@mozilla.org/charset-converter-manager;1"].getService(
+ Ci.nsICharsetConverterManager
+ );
+ trashUnicode = manager.mutf7ToUnicode(folderPathUnescaped);
+ }
+
+ // Set the value to be persisted.
+ document
+ .getElementById("imap.trashFolderName")
+ .setAttribute("value", trashUnicode);
+
+ // Update the widget to show/do correct things even for subfolders.
+ let trashFolderPicker = document.getElementById("msgTrashFolderPicker");
+ trashFolderPicker.menupopup.selectFolder(folder);
+}
+
+// Get trash_folder_name from prefs. Despite its name this returns
+// a folder path, for example INBOX/Trash.
+function getTrashFolderName() {
+ let trashFolderName = document
+ .getElementById("imap.trashFolderName")
+ .getAttribute("value");
+ // if the preference hasn't been set, set it to a sane default
+ if (!trashFolderName) {
+ trashFolderName = "Trash"; // XXX Is this a useful default?
+ document
+ .getElementById("imap.trashFolderName")
+ .setAttribute("value", trashFolderName);
+ }
+ return trashFolderName;
+}