summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/search/content/CustomHeaders.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/search/content/CustomHeaders.js')
-rw-r--r--comm/mailnews/search/content/CustomHeaders.js194
1 files changed, 194 insertions, 0 deletions
diff --git a/comm/mailnews/search/content/CustomHeaders.js b/comm/mailnews/search/content/CustomHeaders.js
new file mode 100644
index 0000000000..4bfc4a3b78
--- /dev/null
+++ b/comm/mailnews/search/content/CustomHeaders.js
@@ -0,0 +1,194 @@
+/* -*- 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/. */
+
+var gAddButton;
+var gRemoveButton;
+var gHeaderInputElement;
+var gArrayHdrs;
+var gHdrsList;
+var gContainer;
+var gFilterBundle = null;
+var gCustomBundle = null;
+
+window.addEventListener("DOMContentLoaded", onLoad);
+document.addEventListener("dialogaccept", onOk);
+document.addEventListener("dialogextra1", onAddHeader);
+document.addEventListener("dialogextra2", onRemoveHeader);
+
+function onLoad() {
+ let hdrs = Services.prefs.getCharPref("mailnews.customHeaders");
+ gHeaderInputElement = document.getElementById("headerInput");
+ gHeaderInputElement.focus();
+
+ gHdrsList = document.getElementById("headerList");
+ gArrayHdrs = [];
+ gAddButton = document.getElementById("addButton");
+ gRemoveButton = document.getElementById("removeButton");
+
+ initializeDialog(hdrs);
+ updateAddButton(true);
+ updateRemoveButton();
+}
+
+function initializeDialog(hdrs) {
+ if (hdrs) {
+ hdrs = hdrs.replace(/\s+/g, ""); // remove white spaces before splitting
+ gArrayHdrs = hdrs.split(":");
+ for (var i = 0; i < gArrayHdrs.length; i++) {
+ if (!gArrayHdrs[i]) {
+ // Remove any null elements.
+ gArrayHdrs.splice(i, 1);
+ }
+ }
+ initializeRows();
+ }
+}
+
+function initializeRows() {
+ for (var i = 0; i < gArrayHdrs.length; i++) {
+ addRow(TrimString(gArrayHdrs[i]));
+ }
+}
+
+function onTextInput() {
+ // enable the add button if the user has started to type text
+ updateAddButton(gHeaderInputElement.value == "");
+}
+
+function onOk() {
+ if (gArrayHdrs.length) {
+ var hdrs;
+ if (gArrayHdrs.length == 1) {
+ hdrs = gArrayHdrs;
+ } else {
+ hdrs = gArrayHdrs.join(": ");
+ }
+ Services.prefs.setCharPref("mailnews.customHeaders", hdrs);
+ // flush prefs to disk, in case we crash, to avoid dataloss and problems with filters that use the custom headers
+ Services.prefs.savePrefFile(null);
+ } else {
+ Services.prefs.clearUserPref("mailnews.customHeaders"); // clear the pref, no custom headers
+ }
+
+ window.arguments[0].selectedVal = gHdrsList.selectedItem
+ ? gHdrsList.selectedItem.label
+ : null;
+}
+
+function customHeaderOverflow() {
+ var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
+ if (
+ gArrayHdrs.length >=
+ nsMsgSearchAttrib.kNumMsgSearchAttributes -
+ nsMsgSearchAttrib.OtherHeader -
+ 1
+ ) {
+ if (!gFilterBundle) {
+ gFilterBundle = document.getElementById("bundle_filter");
+ }
+
+ var alertText = gFilterBundle.getString("customHeaderOverflow");
+ Services.prompt.alert(window, null, alertText);
+ return true;
+ }
+ return false;
+}
+
+function onAddHeader() {
+ var newHdr = TrimString(gHeaderInputElement.value);
+
+ if (!isRFC2822Header(newHdr)) {
+ // if user entered an invalid rfc822 header field name, bail out.
+ if (!gCustomBundle) {
+ gCustomBundle = document.getElementById("bundle_custom");
+ }
+
+ var alertText = gCustomBundle.getString("colonInHeaderName");
+ Services.prompt.alert(window, null, alertText);
+ return;
+ }
+
+ gHeaderInputElement.value = "";
+ if (!newHdr || customHeaderOverflow()) {
+ return;
+ }
+ if (!duplicateHdrExists(newHdr)) {
+ gArrayHdrs[gArrayHdrs.length] = newHdr;
+ var newItem = addRow(newHdr);
+ gHdrsList.selectItem(newItem); // make sure the new entry is selected in the tree
+ // now disable the add button
+ updateAddButton(true);
+ gHeaderInputElement.focus(); // refocus the input field for the next custom header
+ }
+}
+
+function isRFC2822Header(hdr) {
+ var charCode;
+ for (var i = 0; i < hdr.length; i++) {
+ charCode = hdr.charCodeAt(i);
+ // 58 is for colon and 33 and 126 are us-ascii bounds that should be used for header field name, as per rfc2822
+
+ if (charCode < 33 || charCode == 58 || charCode > 126) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function duplicateHdrExists(hdr) {
+ for (var i = 0; i < gArrayHdrs.length; i++) {
+ if (gArrayHdrs[i] == hdr) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function onRemoveHeader() {
+ var listitem = gHdrsList.selectedItems[0];
+ if (!listitem) {
+ return;
+ }
+ listitem.remove();
+ var selectedHdr = listitem.firstElementChild.getAttribute("value").trim();
+ for (let i = 0; i < gArrayHdrs.length; i++) {
+ if (gArrayHdrs[i] == selectedHdr) {
+ gArrayHdrs.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function addRow(newHdr) {
+ return gHdrsList.appendItem(newHdr, "");
+}
+
+function updateAddButton(aDisable) {
+ // only update the button if the disabled state changed
+ if (aDisable == gAddButton.disabled) {
+ return;
+ }
+
+ gAddButton.disabled = aDisable;
+ document.querySelector("dialog").defaultButton = aDisable
+ ? "accept"
+ : "extra1";
+}
+
+function updateRemoveButton() {
+ var headerSelected = gHdrsList.selectedItems.length > 0;
+ gRemoveButton.disabled = !headerSelected;
+ if (gRemoveButton.disabled) {
+ gHeaderInputElement.focus();
+ }
+}
+
+// Remove whitespace from both ends of a string
+function TrimString(string) {
+ if (!string) {
+ return "";
+ }
+ return string.trim();
+}