var globalDb = []; var globalGroups = []; var globalCurrentGroup = ""; var globalCurrentSelection = -1; function Error(message) { alert(message); } function SetEnable(id, enabled) { var elem = document.getElementById(id); elem.disabled = !enabled; } function Copy(id) { var elem = document.getElementById(id); elem.select(); document.execCommand("copy"); } function AESEncrypt(source, phrase) { var encryptedAES = CryptoJS.AES.encrypt(source, phrase); return encryptedAES.toString(); } function AESDecrypt(source, phrase) { var decryptedBytes = CryptoJS.AES.decrypt(source, phrase); return decryptedBytes.toString(CryptoJS.enc.Latin1); } function Decrypt(val) { var phrase = document.getElementById("PassPhrase").value; return AESDecrypt(val, phrase); } function Encrypt(val) { var phrase = document.getElementById("PassPhrase").value; return AESEncrypt(val, phrase); } function WebRequest(url, func, args) { var f; url += "?t=" + Math.random(); for(f = 0; f < args.length; f += 2) { url += "&"; url += args[f] + "="; url += encodeURIComponent(args[f+1]); } var req = new XMLHttpRequest(); if (func) { req.addEventListener("load", func); } req.open("GET", url); req.send(); } function ArrayContains(haystack, needle) { for(var f = 0; f < haystack.length; f++) { if (haystack[f] === needle) { return true; } } return false; } function IsEmpty(id) { var elem = document.getElementById(id); return elem.value == ""; } function ShowPasswords() { var elem = document.getElementById("ShowPasswords"); return elem.checked; } function SetInputType(id, type) { document.getElementById(id).type = type; } function GetGroupRows() { var result = []; for(var f = 0; f < globalDb.length; f++) { if (globalDb[f].group == globalCurrentGroup) { result.push(globalDb[f]); } } return result; } function GetData(id) { for(var f = 0; f < globalDb.length; f++) { if (globalDb[f].id == id) { return globalDb[f]; } } return null; } function FindNextPrevious() { var rows = GetGroupRows(); var f; var ret = {prev: -1, next: -1}; var prev = -1; for(f = 0; f < rows.length; f++) { if (rows[f].id == globalCurrentSelection) { ret.prev = prev; if (f < rows.length - 1) { ret.next = rows[f + 1].id; } } prev = rows[f].id; } return ret; } function SetButtonState() { SetEnable("Add", true); SetEnable("Edit", globalCurrentSelection != -1); SetEnable("Delete", globalCurrentSelection != -1); SetEnable("CopyUsername", globalCurrentSelection != -1); SetEnable("CopyPassword", globalCurrentSelection != -1); SetEnable("Up", globalCurrentSelection != -1); SetEnable("Down", globalCurrentSelection != -1); } function LoadGroups(keep_selection) { globalGroups = []; for(var f = 0; f < globalDb.length; f++) { var group = globalDb[f].group; if (!ArrayContains(globalGroups, group)) { globalGroups.push(group); } } if (!keep_selection) { globalCurrentGroup = ""; } if (!ArrayContains(globalGroups, globalCurrentGroup)) { if (globalGroups.length > 0) { globalCurrentGroup = globalGroups[0]; } else { globalCurrentGroup = ""; } } var elem = document.getElementById("Group"); while(elem.length > 0) { elem.remove(0); } for(var f = 0; f < globalGroups.length; f++) { var option = document.createElement("option"); option.text = globalGroups[f]; option.value = globalGroups[f]; elem.add(option); } elem.value = globalCurrentGroup; } function LoadDescriptions(keep_selection) { var rows = GetGroupRows(); var elem = document.getElementById("DescriptionSelect"); var f; if (!keep_selection) { globalCurrentSelection = -1; } while(elem.length > 0) { elem.remove(0); } var firstid = -1; var selected = false; for(f = 0; f < rows.length; f++) { var option = document.createElement("option"); option.text = rows[f].description; option.value = rows[f].id; if (firstid == -1) { firstid = rows[f].id; } if (globalCurrentSelection == rows[f].id) { selected = true; } elem.add(option); } if (!selected) { globalCurrentSelection = firstid; } if (globalCurrentSelection != -1) { elem.value = globalCurrentSelection; } } function LoadTable() { var record = GetData(globalCurrentSelection); if (record != null) { var elem; elem = document.getElementById("Description"); elem.value = record.description; elem = document.getElementById("Username"); elem.value = record.username; elem = document.getElementById("Password"); elem.value = Decrypt(record.password); } } function RefreshDataAsync() { globalDb = JSON.parse(this.responseText); LoadGroups(true); LoadDescriptions(true); LoadTable(); SetButtonState(); } function RefreshData() { WebRequest("get.php", RefreshDataAsync, []); } function LoadInitialData() { LoadGroups(false); LoadDescriptions(false); LoadTable(); } function DoLoadAsync() { globalDb = JSON.parse(this.responseText); if (globalDb.error) { Error(globalDb.error); globalDb = []; } else { LoadInitialData(); SetButtonState(); SetEnable("ChangePassphrase", true); } } function DoLoad() { if (IsEmpty("PassPhrase")) { Error("Passphrase empty"); return; } WebRequest("get.php", DoLoadAsync, []); LoadInitialData(); } function DoChangePassphraseAsync() { var response = JSON.parse(this.responseText); if (response.error) { Error(response.error); } } function DoChangePassphrase() { if (IsEmpty("NewPassPhrase")) { Error("New passphrase empty"); return; } var msg = "WARNING: If you have not successfully loaded the passwords\n"; msg += "then this option will destroy the saved passwords. Proceed?"; if (confirm(msg)) { var f; var newphrase = document.getElementById("NewPassPhrase").value; for(f = 0; f < globalDb.length; f++) { var password = Decrypt(globalDb[f].password); WebRequest("edit.php", DoChangePassphraseAsync, [ "id", globalDb[f].id, "description", globalDb[f].description, "group", globalDb[f].group, "username", globalDb[f].username, "password", AESEncrypt(password, newphrase) ] ); } document.getElementById("PassPhrase").value = newphrase; document.getElementById("NewPassPhrase").value = ""; } } function DoSelectGroup() { var elem = document.getElementById("Group"); globalCurrentGroup = elem.value; document.getElementById("NewGroup").value = ""; LoadDescriptions(false); LoadTable(); } function DoSelectDescription() { var elem = document.getElementById("DescriptionSelect"); globalCurrentSelection = elem.value; LoadTable(); } function DoAddAsync() { var response = JSON.parse(this.responseText); if (response.error) { Error(response.error); } else { globalCurrentGroup = response.group; globalCurrentSelection = response.id; RefreshData(); } } function DoAdd() { if (IsEmpty("PassPhrase")) { Error("Passphrase empty"); return; } if (IsEmpty("Group") && IsEmpty("NewGroup")) { Error("No groups defined -- please enter a group name"); return; } var description = document.getElementById("Description").value; var username = document.getElementById("Username").value; var password = document.getElementById("Password").value; var group; if (description == "" || username == "" | password == "") { Error("Please enter the description, username and password"); return; } if (!IsEmpty("NewGroup")) { group = document.getElementById("NewGroup").value; document.getElementById("NewGroup").value = ""; } else { group = document.getElementById("Group").value; } WebRequest("add.php", DoAddAsync, [ "description", description, "group", group, "username", username, "password", Encrypt(password) ] ); } function DoEditAsync() { var response = JSON.parse(this.responseText); if (response.error) { Error(response.error); } else { globalCurrentGroup = response.group; globalCurrentSelection = response.id; RefreshData(); } } function DoEdit() { var description = document.getElementById("Description").value; var username = document.getElementById("Username").value; var password = document.getElementById("Password").value; var group; if (description == "" || username == "" | password == "") { Error("Please enter the description, username and password"); return; } if (!IsEmpty("NewGroup")) { group = document.getElementById("NewGroup").value; document.getElementById("NewGroup").value = ""; } else { group = document.getElementById("Group").value; } WebRequest("edit.php", DoEditAsync, [ "id", globalCurrentSelection, "description", description, "group", group, "username", username, "password", Encrypt(password) ] ); } function DoDeleteAsync() { var response = JSON.parse(this.responseText); if (response.error) { Error(response.error); } else { RefreshData(); } } function DoDelete() { WebRequest("delete.php", DoDeleteAsync, [ "id", globalCurrentSelection ] ); } function DoCopyUsername() { Copy("Username"); } function DoCopyPassword() { var id = "Password"; if (!ShowPasswords()) { SetInputType(id, "text"); } Copy(id); if (!ShowPasswords()) { SetInputType(id, "password"); } } function DoShow() { if (!ShowPasswords()) { SetInputType("Password" + this.dataset.pmId, "text"); } } function DoHide() { if (!ShowPasswords()) { SetInputType("Password" + this.dataset.pmId, "password"); } } function DoReorderAsync() { var response = JSON.parse(this.responseText); if (response.error) { Error(response.error); } else { RefreshData(); } } function DoUp() { var rec = FindNextPrevious(); if (rec.prev != -1) { WebRequest("reorder.php", DoReorderAsync, [ "from_id", globalCurrentSelection, "to_id", rec.prev ] ); } } function DoDown() { var rec = FindNextPrevious(); if (rec.next != -1) { WebRequest("reorder.php", DoReorderAsync, [ "from_id", globalCurrentSelection, "to_id", rec.next ] ); } } function DoShowPasswords() { var type; if (ShowPasswords()) { type = "text"; } else { type = "password"; } SetInputType("PassPhrase", type); SetInputType("NewPassPhrase", type); SetInputType("Password", type); } // vim: sw=4 ts=4