|
|
|
@ -7,16 +7,16 @@ var { pEpController } = ChromeUtils.import("chrome://pEp4Tb/content/pEpControlle
|
|
|
|
|
|
|
|
|
|
// Add preferences info (see developer.thunderbird.net/add-ons/updates/tb68).
|
|
|
|
|
Preferences.addAll([
|
|
|
|
|
{ id: "extensions.pEp.storeAllSecurely", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.warnUnencrypted", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.protectSubjects", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.passiveMode", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.pEpSync", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.keyFingerprint", type: "string" },
|
|
|
|
|
{ id: "extensions.pEp.keyLocation", type: "string" },
|
|
|
|
|
// examples with different types
|
|
|
|
|
// { id: "extensions.nameOfAddon.pref2", type: "string" },
|
|
|
|
|
// { id: "extensions.nameOfAddon.pref3", type: "int" },
|
|
|
|
|
{ id: "extensions.pEp.storeAllSecurely", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.warnUnencrypted", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.protectSubjects", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.passiveMode", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.pEpSync", type: "bool" },
|
|
|
|
|
{ id: "extensions.pEp.keyFingerprint", type: "string" },
|
|
|
|
|
{ id: "extensions.pEp.keyLocation", type: "string" },
|
|
|
|
|
// examples with different types
|
|
|
|
|
// { id: "extensions.nameOfAddon.pref2", type: "string" },
|
|
|
|
|
// { id: "extensions.nameOfAddon.pref3", type: "int" },
|
|
|
|
|
]);
|
|
|
|
|
Preferences.get("extensions.pEp.protectSubjects").on(
|
|
|
|
|
"change",
|
|
|
|
@ -32,189 +32,189 @@ Preferences.get("extensions.pEp.storeAllSecurely").on(
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
function protectSubjectsChange() {
|
|
|
|
|
if (Services.prefs.getBoolPref("extensions.pEp.protectSubjects", true)) {
|
|
|
|
|
pEpController.enableprotectSubjects();
|
|
|
|
|
} else {
|
|
|
|
|
pEpController.disableprotectSubjects();
|
|
|
|
|
}
|
|
|
|
|
if (Services.prefs.getBoolPref("extensions.pEp.protectSubjects", true)) {
|
|
|
|
|
pEpController.enableprotectSubjects();
|
|
|
|
|
} else {
|
|
|
|
|
pEpController.disableprotectSubjects();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function passiveModeChange() {
|
|
|
|
|
if (Services.prefs.getBoolPref("extensions.pEp.passiveMode", true)) {
|
|
|
|
|
pEpController.enablePassiveMode();
|
|
|
|
|
} else {
|
|
|
|
|
pEpController.disablePassiveMode();
|
|
|
|
|
}
|
|
|
|
|
if (Services.prefs.getBoolPref("extensions.pEp.passiveMode", true)) {
|
|
|
|
|
pEpController.enablePassiveMode();
|
|
|
|
|
} else {
|
|
|
|
|
pEpController.disablePassiveMode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function storeAllSecurelyChange() {
|
|
|
|
|
const storeAllSecurely = Services.prefs.getBoolPref("extensions.pEp.storeAllSecurely", true);
|
|
|
|
|
const root = document.getElementById("root");
|
|
|
|
|
let checkboxes = root.querySelectorAll(".account-storeSecurely");
|
|
|
|
|
for (let checkbox of checkboxes) {
|
|
|
|
|
checkbox.setAttribute("disabled", storeAllSecurely);
|
|
|
|
|
if (storeAllSecurely) {
|
|
|
|
|
// Override.
|
|
|
|
|
let accountKey = checkbox.getAttribute("id");
|
|
|
|
|
let id = `mail.account.${accountKey}.storeSecurely`;
|
|
|
|
|
Services.prefs.setBoolPref(id, true);
|
|
|
|
|
}
|
|
|
|
|
const storeAllSecurely = Services.prefs.getBoolPref("extensions.pEp.storeAllSecurely", true);
|
|
|
|
|
const root = document.getElementById("root");
|
|
|
|
|
let checkboxes = root.querySelectorAll(".account-storeSecurely");
|
|
|
|
|
for (let checkbox of checkboxes) {
|
|
|
|
|
checkbox.setAttribute("disabled", storeAllSecurely);
|
|
|
|
|
if (storeAllSecurely) {
|
|
|
|
|
// Override.
|
|
|
|
|
let accountKey = checkbox.getAttribute("id");
|
|
|
|
|
let id = `mail.account.${accountKey}.storeSecurely`;
|
|
|
|
|
Services.prefs.setBoolPref(id, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function loadAccounts() {
|
|
|
|
|
function makeIdentityFragment(identity) {
|
|
|
|
|
const fragment = new pEpUtils.Fragment("#identity-options", document);
|
|
|
|
|
const root = fragment.getRoot();
|
|
|
|
|
const [delim, delim2] = identity.fullName ? [" <", ">"] : ["", ""];
|
|
|
|
|
root.querySelector(".identity-title").textContent = `${identity.fullName}${delim}${identity.email}${delim2}`;
|
|
|
|
|
|
|
|
|
|
let checkbox = root.querySelector(".identity-enableEncryption");
|
|
|
|
|
let id = `mail.identity.${identity.key}.enableEncryption`;
|
|
|
|
|
// Get prior value, if any. Default to true.
|
|
|
|
|
let value = Services.prefs.getBoolPref(id, true);
|
|
|
|
|
Preferences.add({ id, type: "bool" });
|
|
|
|
|
checkbox.setAttribute("preference", id);
|
|
|
|
|
Services.prefs.setBoolPref(id, value);
|
|
|
|
|
|
|
|
|
|
return root;
|
|
|
|
|
function makeIdentityFragment(identity) {
|
|
|
|
|
const fragment = new pEpUtils.Fragment("#identity-options", document);
|
|
|
|
|
const root = fragment.getRoot();
|
|
|
|
|
const [delim, delim2] = identity.fullName ? [" <", ">"] : ["", ""];
|
|
|
|
|
root.querySelector(".identity-title").textContent = `${identity.fullName}${delim}${identity.email}${delim2}`;
|
|
|
|
|
|
|
|
|
|
let checkbox = root.querySelector(".identity-enableEncryption");
|
|
|
|
|
let id = `mail.identity.${identity.key}.enableEncryption`;
|
|
|
|
|
// Get prior value, if any. Default to true.
|
|
|
|
|
let value = Services.prefs.getBoolPref(id, true);
|
|
|
|
|
Preferences.add({ id, type: "bool" });
|
|
|
|
|
checkbox.setAttribute("preference", id);
|
|
|
|
|
Services.prefs.setBoolPref(id, value);
|
|
|
|
|
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function makeAccountFragment(account) {
|
|
|
|
|
const fragment = new pEpUtils.Fragment("#account-options", document);
|
|
|
|
|
const root = fragment.getRoot();
|
|
|
|
|
let accName = account.key;
|
|
|
|
|
const server = Services.prefs.getStringPref(`mail.account.${account.key}.server`);
|
|
|
|
|
if (server) {
|
|
|
|
|
accName = Services.prefs.getStringPref(`mail.server.${server}.name`, accName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function makeAccountFragment(account) {
|
|
|
|
|
const fragment = new pEpUtils.Fragment("#account-options", document);
|
|
|
|
|
const root = fragment.getRoot();
|
|
|
|
|
let accName = account.key;
|
|
|
|
|
const server = Services.prefs.getStringPref(`mail.account.${account.key}.server`);
|
|
|
|
|
if (server) {
|
|
|
|
|
accName = Services.prefs.getStringPref(`mail.server.${server}.name`, accName);
|
|
|
|
|
}
|
|
|
|
|
root.querySelector(".account-title").textContent = accName;
|
|
|
|
|
|
|
|
|
|
// Check global override.
|
|
|
|
|
let storeAllSecurely = Services.prefs.getBoolPref("extensions.pEp.storeAllSecurely", true);
|
|
|
|
|
|
|
|
|
|
let checkbox = root.querySelector(".account-storeSecurely");
|
|
|
|
|
let id = `mail.account.${account.key}.storeSecurely`;
|
|
|
|
|
// Get prior value, if any. Default to true.
|
|
|
|
|
let value = storeAllSecurely ? true : Services.prefs.getBoolPref(id, true);
|
|
|
|
|
Preferences.add({ id, type: "bool" });
|
|
|
|
|
checkbox.setAttribute("preference", id);
|
|
|
|
|
Services.prefs.setBoolPref(id, value);
|
|
|
|
|
checkbox.setAttribute("disabled", storeAllSecurely);
|
|
|
|
|
checkbox.setAttribute("id", account.key);
|
|
|
|
|
|
|
|
|
|
let identities = [];
|
|
|
|
|
for (let identity of fixIterator(account.identities, Ci.nsIMsgIdentity)) {
|
|
|
|
|
identities.push({ key: identity.key, fullName: identity.fullName, email: identity.email });
|
|
|
|
|
}
|
|
|
|
|
identities
|
|
|
|
|
.map(makeIdentityFragment)
|
|
|
|
|
.map((r) => root.querySelector(".insert-here").insertBefore(r, null));
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const root = document.getElementById("root");
|
|
|
|
|
pEpUtils.removeChildren(root);
|
|
|
|
|
|
|
|
|
|
let accounts = [];
|
|
|
|
|
for (let account of fixIterator(MailServices.accounts.accounts, Ci.nsIMsgAccount)) {
|
|
|
|
|
const server = Services.prefs.getStringPref(`mail.account.${account.key}.server`);
|
|
|
|
|
if (!server) continue;
|
|
|
|
|
const type = Services.prefs.getStringPref(`mail.server.${server}.type`, "badtype");
|
|
|
|
|
if (["rss", "im", "nntp", "badtype"].includes(type)) continue; // Skip Feeds, Chat and News.
|
|
|
|
|
accounts.push({ key: account.key, identities: account.identities });
|
|
|
|
|
root.querySelector(".account-title").textContent = accName;
|
|
|
|
|
|
|
|
|
|
// Check global override.
|
|
|
|
|
let storeAllSecurely = Services.prefs.getBoolPref("extensions.pEp.storeAllSecurely", true);
|
|
|
|
|
|
|
|
|
|
let checkbox = root.querySelector(".account-storeSecurely");
|
|
|
|
|
let id = `mail.account.${account.key}.storeSecurely`;
|
|
|
|
|
// Get prior value, if any. Default to true.
|
|
|
|
|
let value = storeAllSecurely ? true : Services.prefs.getBoolPref(id, true);
|
|
|
|
|
Preferences.add({ id, type: "bool" });
|
|
|
|
|
checkbox.setAttribute("preference", id);
|
|
|
|
|
Services.prefs.setBoolPref(id, value);
|
|
|
|
|
checkbox.setAttribute("disabled", storeAllSecurely);
|
|
|
|
|
checkbox.setAttribute("id", account.key);
|
|
|
|
|
|
|
|
|
|
let identities = [];
|
|
|
|
|
for (let identity of fixIterator(account.identities, Ci.nsIMsgIdentity)) {
|
|
|
|
|
identities.push({ key: identity.key, fullName: identity.fullName, email: identity.email });
|
|
|
|
|
}
|
|
|
|
|
accounts
|
|
|
|
|
.map(makeAccountFragment)
|
|
|
|
|
.map(root.appendChild.bind(root));
|
|
|
|
|
identities
|
|
|
|
|
.map(makeIdentityFragment)
|
|
|
|
|
.map((r) => root.querySelector(".insert-here").insertBefore(r, null));
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const root = document.getElementById("root");
|
|
|
|
|
pEpUtils.removeChildren(root);
|
|
|
|
|
|
|
|
|
|
let accounts = [];
|
|
|
|
|
for (let account of fixIterator(MailServices.accounts.accounts, Ci.nsIMsgAccount)) {
|
|
|
|
|
const server = Services.prefs.getStringPref(`mail.account.${account.key}.server`);
|
|
|
|
|
if (!server) continue;
|
|
|
|
|
const type = Services.prefs.getStringPref(`mail.server.${server}.type`, "badtype");
|
|
|
|
|
if (["rss", "im", "nntp", "badtype"].includes(type)) continue; // Skip Feeds, Chat and News.
|
|
|
|
|
accounts.push({ key: account.key, identities: account.identities });
|
|
|
|
|
}
|
|
|
|
|
accounts
|
|
|
|
|
.map(makeAccountFragment)
|
|
|
|
|
.map(root.appendChild.bind(root));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function convertURLToLocalFile(aFileURL) {
|
|
|
|
|
// convert the file url into a nsIFile
|
|
|
|
|
if (aFileURL) {
|
|
|
|
|
return Services.io.getProtocolHandler("file")
|
|
|
|
|
.QueryInterface(Ci.nsIFileProtocolHandler)
|
|
|
|
|
.getFileFromURLSpec(aFileURL);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
// convert the file url into a nsIFile
|
|
|
|
|
if (aFileURL) {
|
|
|
|
|
return Services.io.getProtocolHandler("file")
|
|
|
|
|
.QueryInterface(Ci.nsIFileProtocolHandler)
|
|
|
|
|
.getFileFromURLSpec(aFileURL);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function browseForKey() {
|
|
|
|
|
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
|
|
|
|
|
|
|
|
|
// if we already have a key, then use the path.
|
|
|
|
|
var localFile = convertURLToLocalFile(document.getElementById("keyLocation").value);
|
|
|
|
|
if (localFile) {
|
|
|
|
|
fp.displayDirectory = localFile.parent;
|
|
|
|
|
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
|
|
|
|
|
|
|
|
|
// if we already have a key, then use the path.
|
|
|
|
|
var localFile = convertURLToLocalFile(document.getElementById("keyLocation").value);
|
|
|
|
|
if (localFile) {
|
|
|
|
|
fp.displayDirectory = localFile.parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp.init(
|
|
|
|
|
window,
|
|
|
|
|
"Select ASCII-armored file", // L10N
|
|
|
|
|
Ci.nsIFilePicker.modeOpen,
|
|
|
|
|
);
|
|
|
|
|
fp.appendFilter("ASC File", "*.asc"); // L10N
|
|
|
|
|
fp.appendFilters(Ci.nsIFilePicker.filterAll);
|
|
|
|
|
|
|
|
|
|
fp.open((rv) => {
|
|
|
|
|
if (rv != Ci.nsIFilePicker.returnOK || !fp.file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp.init(
|
|
|
|
|
window,
|
|
|
|
|
"Select ASCII-armored file", // L10N
|
|
|
|
|
Ci.nsIFilePicker.modeOpen,
|
|
|
|
|
);
|
|
|
|
|
fp.appendFilter("ASC File", "*.asc"); // L10N
|
|
|
|
|
fp.appendFilters(Ci.nsIFilePicker.filterAll);
|
|
|
|
|
|
|
|
|
|
fp.open((rv) => {
|
|
|
|
|
if (rv != Ci.nsIFilePicker.returnOK || !fp.file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// convert the nsIFile into a nsIFile url
|
|
|
|
|
Preferences.get("extensions.pEp.keyLocation").value = fp.fileURL.spec;
|
|
|
|
|
});
|
|
|
|
|
// convert the nsIFile into a nsIFile url
|
|
|
|
|
Preferences.get("extensions.pEp.keyLocation").value = fp.fileURL.spec;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function importKey() {
|
|
|
|
|
let location = Preferences.get("extensions.pEp.keyLocation").value;
|
|
|
|
|
let channel = Services.io.newChannelFromURI(Services.io.newURI(location), null,
|
|
|
|
|
Services.scriptSecurityManager.getSystemPrincipal(), null,
|
|
|
|
|
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
|
|
|
|
Ci.nsIContentPolicy.TYPE_OTHER);
|
|
|
|
|
let inputStream = channel.open();
|
|
|
|
|
let stream = Cc["@mozilla.org/binaryinputstream;1"]
|
|
|
|
|
.createInstance(Ci.nsIBinaryInputStream);
|
|
|
|
|
stream.setInputStream(inputStream);
|
|
|
|
|
let streamData = "";
|
|
|
|
|
try {
|
|
|
|
|
while (stream.available() > 0) {
|
|
|
|
|
streamData += stream.readBytes(stream.available());
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
stream.close();
|
|
|
|
|
// eslint-disable-next-line prefer-template
|
|
|
|
|
throw new Error("Couldn't read all data from location " + location + " (" + e + ")");
|
|
|
|
|
let location = Preferences.get("extensions.pEp.keyLocation").value;
|
|
|
|
|
let channel = Services.io.newChannelFromURI(Services.io.newURI(location), null,
|
|
|
|
|
Services.scriptSecurityManager.getSystemPrincipal(), null,
|
|
|
|
|
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
|
|
|
|
Ci.nsIContentPolicy.TYPE_OTHER);
|
|
|
|
|
let inputStream = channel.open();
|
|
|
|
|
let stream = Cc["@mozilla.org/binaryinputstream;1"]
|
|
|
|
|
.createInstance(Ci.nsIBinaryInputStream);
|
|
|
|
|
stream.setInputStream(inputStream);
|
|
|
|
|
let streamData = "";
|
|
|
|
|
try {
|
|
|
|
|
while (stream.available() > 0) {
|
|
|
|
|
streamData += stream.readBytes(stream.available());
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
stream.close();
|
|
|
|
|
|
|
|
|
|
// Send to the engine.
|
|
|
|
|
pEpController.importKey(streamData).then((result) => {
|
|
|
|
|
let msg;
|
|
|
|
|
// If we get identites returned, we imported a private key,
|
|
|
|
|
// if we get empty identities, we imported a public key.
|
|
|
|
|
// Anything else is an error.
|
|
|
|
|
if (typeof result !== "object") {
|
|
|
|
|
console.log(`Key import error ${result}`);
|
|
|
|
|
msg = "Key import failed"; // L10N
|
|
|
|
|
} else if (result.length == 0) {
|
|
|
|
|
console.log("Public key import not supported");
|
|
|
|
|
msg = "Public key import not supported"; // L10N
|
|
|
|
|
} else {
|
|
|
|
|
result[0].user_id = "pEp_own_userId";
|
|
|
|
|
pEpController.setOwnKey(result[0]);
|
|
|
|
|
// TODO: Check error.
|
|
|
|
|
const username = result[0].username;
|
|
|
|
|
const [delim, delim2] = username ? [" <", ">"] : ["", ""];
|
|
|
|
|
msg = `Key successfully imported for ${username}${delim}${result[0].address}${delim2}`; // L10N
|
|
|
|
|
}
|
|
|
|
|
Services.prompt.alert(
|
|
|
|
|
null,
|
|
|
|
|
"Key import", // L10N
|
|
|
|
|
msg,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
// eslint-disable-next-line prefer-template
|
|
|
|
|
throw new Error("Couldn't read all data from location " + location + " (" + e + ")");
|
|
|
|
|
}
|
|
|
|
|
stream.close();
|
|
|
|
|
|
|
|
|
|
// Send to the engine.
|
|
|
|
|
pEpController.importKey(streamData).then((result) => {
|
|
|
|
|
let msg;
|
|
|
|
|
// If we get identites returned, we imported a private key,
|
|
|
|
|
// if we get empty identities, we imported a public key.
|
|
|
|
|
// Anything else is an error.
|
|
|
|
|
if (typeof result !== "object") {
|
|
|
|
|
console.log(`Key import error ${result}`);
|
|
|
|
|
msg = "Key import failed"; // L10N
|
|
|
|
|
} else if (result.length == 0) {
|
|
|
|
|
console.log("Public key import not supported");
|
|
|
|
|
msg = "Public key import not supported"; // L10N
|
|
|
|
|
} else {
|
|
|
|
|
result[0].user_id = "pEp_own_userId";
|
|
|
|
|
pEpController.setOwnKey(result[0]);
|
|
|
|
|
// TODO: Check error.
|
|
|
|
|
const username = result[0].username;
|
|
|
|
|
const [delim, delim2] = username ? [" <", ">"] : ["", ""];
|
|
|
|
|
msg = `Key successfully imported for ${username}${delim}${result[0].address}${delim2}`; // L10N
|
|
|
|
|
}
|
|
|
|
|
Services.prompt.alert(
|
|
|
|
|
null,
|
|
|
|
|
"Key import", // L10N
|
|
|
|
|
msg,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.addEventListener("load", () => {
|
|
|
|
|
loadAccounts();
|
|
|
|
|
loadAccounts();
|
|
|
|
|
});
|
|
|
|
|