# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # The contents of this file are subject to the Netscape Public # License Version 1.1 (the "License"); you may not use this file # except in compliance with the License. You may obtain a copy of # the License at http://www.mozilla.org/NPL/ # # Software distributed under the License is distributed on an "AS # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or # implied. See the License for the specific language governing # rights and limitations under the License. # # The Original Code is Mozilla Communicator client code, released March # 31, 1998. # # The Initial Developer of the Original Code is Netscape Communications # Corporation. Portions created by Netscape are # Copyright (C) 1998 Netscape Communications Corporation. All # Rights Reserved. # # Contributor(s): # Ben "Count XULula" Goodger # Brian Ryner /*** =================== INITIALISATION CODE =================== ***/ var kObserverService; var kSignonBundle; var gSelectUserInUse = false; // interface variables var passwordmanager = null; // password-manager lists var signons = []; var rejects = []; var deletedSignons = []; var deletedRejects = []; var showingPasswords = false; function Startup() { // xpconnect to password manager interfaces passwordmanager = Components.classes["@mozilla.org/passwordmanager;1"].getService(Components.interfaces.nsIPasswordManager); kSignonBundle = document.getElementById("signonBundle"); // be prepared to reload the display if anything changes kObserverService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); kObserverService.addObserver(signonReloadDisplay, "signonChanged", false); // be prepared to disable the buttons when selectuser dialog is in use kObserverService.addObserver(signonReloadDisplay, "signonSelectUser", false); signonsTree = document.getElementById("signonsTree"); rejectsTree = document.getElementById("rejectsTree"); // set initial password-manager tab var tabBox = document.getElementById("tabbox"); tabBox.selectedTab = document.getElementById("signonsTab"); // label the show/hide password button and the close button document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords"); document.documentElement.getButton("accept").label = kSignonBundle.getString("close"); // load password manager items if (!LoadSignons()) { return; /* user failed to unlock the database */ } LoadRejects(); } function Shutdown() { kObserverService.removeObserver(signonReloadDisplay, "signonChanged"); kObserverService.removeObserver(signonReloadDisplay, "signonSelectUser"); } var signonReloadDisplay = { observe: function(subject, topic, state) { if (topic == "signonChanged") { if (state == "signons") { signons.length = 0; if (lastSignonSortColumn == "host") { lastSignonSortAscending = !lastSignonSortAscending; // prevents sort from being reversed } LoadSignons(); } else if (state == "rejects") { rejects.length = 0; if (lastRejectSortColumn == "host") { lastRejectSortAscending = !lastRejectSortAscending; // prevents sort from being reversed } LoadRejects(); } } else if (topic == "signonSelectUser") { if (state == "suspend") { gSelectUserInUse = true; document.getElementById("removeSignon").disabled = true; document.getElementById("removeAllSignons").disabled = true; document.getElementById("togglePasswords").disabled = true; } else if (state == "resume") { gSelectUserInUse = false; var selections = GetTreeSelections(signonsTree); if (selections.length > 0) { document.getElementById("removeSignon").disabled = false; } if (signons.length > 0) { document.getElementById("removeAllSignons").disabled = false; document.getElementById("togglePasswords").disabled = false; } } else if (state == "inUse") { gSelectUserInUse = true; } } } } /*** =================== SAVED SIGNONS CODE =================== ***/ var signonsTreeView = { rowCount : 0, setTree : function(tree) {}, getImageSrc : function(row,column) {}, getProgressMode : function(row,column) {}, getCellValue : function(row,column) {}, getCellText : function(row,column) { var rv=""; if (column.id=="siteCol") { rv = signons[row].host; } else if (column.id=="userCol") { rv = signons[row].user; } else if (column.id=="passwordCol") { rv = signons[row].password; } return rv; }, isSeparator : function(index) { return false; }, isSorted : function() { return false; }, isContainer : function(index) { return false; }, cycleHeader : function(column) {}, getRowProperties : function(row,prop) {}, getColumnProperties : function(column,prop) {}, getCellProperties : function(row,column,prop) {} }; var signonsTree; function Signon(number, host, user, rawuser, password) { this.number = number; this.host = host; this.user = user; this.rawuser = rawuser; this.password = password; } function LoadSignons() { // loads signons into table var enumerator = passwordmanager.enumerator; var count = 0; while (enumerator.hasMoreElements()) { var nextPassword; try { nextPassword = enumerator.getNext(); } catch(e) { /* user supplied invalid database key */ window.close(); return false; } nextPassword = nextPassword.QueryInterface(Components.interfaces.nsIPassword); var host = nextPassword.host; var user; var password; // try/catch in case decryption fails (invalid signon entry) try { user = nextPassword.user; password = nextPassword.password; } catch (e) { // hide this entry dump("could not decrypt user/password for host " + host + "\n"); continue; } var rawuser = user; // if no username supplied, try to parse it out of the url if (user == "") { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); try { user = ioService.newURI(host, null, null).username; if (user == "") { user = "<>"; } } catch(e) { user = "<>"; } } signons[count] = new Signon(count++, host, user, rawuser, password); } signonsTreeView.rowCount = signons.length; // sort and display the table signonsTree.treeBoxObject.view = signonsTreeView; SignonColumnSort('host'); // disable "remove all signons" button if there are no signons var element = document.getElementById("removeAllSignons"); var toggle = document.getElementById("togglePasswords"); if (signons.length == 0 || gSelectUserInUse) { element.setAttribute("disabled","true"); toggle.setAttribute("disabled","true"); } else { element.removeAttribute("disabled"); toggle.removeAttribute("disabled"); } return true; } function SignonSelected() { var selections = GetTreeSelections(signonsTree); if (selections.length && !gSelectUserInUse) { document.getElementById("removeSignon").removeAttribute("disabled"); } } function DeleteSignon() { DeleteSelectedItemFromTree(signonsTree, signonsTreeView, signons, deletedSignons, "removeSignon", "removeAllSignons"); FinalizeSignonDeletions(); } function DeleteAllSignons() { DeleteAllFromTree(signonsTree, signonsTreeView, signons, deletedSignons, "removeSignon", "removeAllSignons"); FinalizeSignonDeletions(); } function TogglePasswordVisible() { if (!showingPasswords && !ConfirmShowPasswords()) return; showingPasswords = !showingPasswords; document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords"); document.getElementById("passwordCol").hidden = !showingPasswords; } function AskUserShowPasswords() { var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); var dummy = { value: false }; // Confirm the user wants to display passwords return prompter.confirmEx(window, null, kSignonBundle.getString("noMasterPasswordPrompt"), prompter.BUTTON_TITLE_YES * prompter.BUTTON_POS_0 + prompter.BUTTON_TITLE_NO * prompter.BUTTON_POS_1, null, null, null, null, dummy) == 0; // 0=="Yes" button } function ConfirmShowPasswords() { // This doesn't harm if passwords are not encrypted var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"] .createInstance(Components.interfaces.nsIPK11TokenDB); var token = tokendb.getInternalKeyToken(); // If there is no master password, still give the user a chance to opt-out of displaying passwords if (token.checkPassword("")) return AskUserShowPasswords(); // So there's a master password. But since checkPassword didn't succeed, we're logged out (per nsIPK11Token.idl). try { // Relogin and ask for the master password. token.login(true); // 'true' means always prompt for token password. User will be prompted until // clicking 'Cancel' or entering the correct password. } catch (e) { // An exception will be thrown if the user cancels the login prompt dialog. // User is also logged out of Software Security Device. } return token.isLoggedIn(); } function FinalizeSignonDeletions() { for (var s=0; s=0 && updateSelection) { for (var s=0; s= 0) { tree.treeBoxObject.ensureRowIsVisible(selectedRow) } return ascending; } /** * Case insensitive string comparator. */ function CompareLowerCase(first, second) { var firstLower = first.toLowerCase(); var secondLower = second.toLowerCase(); if (firstLower < secondLower) { return -1; } if (firstLower > secondLower) { return 1; } return 0; }