var globalDb = []; var globalGroups = []; var globalCurrentGroup = ""; 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 LoadTestData() { globalDb = []; var f; for(f = 1; f < 21; f++) { var rec = {id: f, group: "Group 1", description: "Test " + f, username: "user" + f, password: ""}; globalDb.push(rec); } } 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 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 AddTableInputCell(id, text, name, maxlen, classname, type, node) { var td = document.createElement("td"); var input = document.createElement("input"); input.value = text; input.id = name + id; input.type = type; input.maxLength = maxlen; input.className = "fill"; td.className = classname; td.appendChild(input); node.appendChild(td); } function AddSmallButton(node, text, func, id) { var button = document.createElement("input"); button.type = "button"; button.onclick = func; button.value = text; button.className = "smalltext"; button.dataset.pmId = id; node.appendChild(button); } function AddSmallButtonPrevNext(node, text, func, id, prev, next) { var button = document.createElement("input"); button.type = "button"; button.onclick = func; button.value = text; button.className = "smalltext"; button.dataset.pmId = id; button.dataset.pmPrevId = prev; button.dataset.pmNextId = next; node.appendChild(button); } function AddSmallButtonUpDown(node, text, down_func, up_func, id) { var button = document.createElement("input"); button.type = "button"; button.onmousedown = down_func; button.onmouseup = up_func; button.value = text; button.className = "smalltext"; button.dataset.pmId = id; node.appendChild(button); } function AddText(node, text) { var t = document.createTextNode(text); node.appendChild(t); } function AddElement(node, elementname) { var elem = document.createElement(elementname); node.appendChild(elem); } function AddRow(table, id, prev_id, next_id, desc, username, password, rowcount) { var tr = document.createElement("tr"); if ((rowcount % 2) == 1) { tr.className = "style1"; } else { tr.className = "style2"; } AddTableInputCell(id, desc, "Description", 1024, "description", "text", tr); AddTableInputCell(id, username, "Username", 256, "username", "text", tr); if (ShowPasswords()) { AddTableInputCell(id, password, "Password", 256, "password", "text", tr); } else { AddTableInputCell(id, password, "Password", 256, "password", "password", tr); } var td = document.createElement("td"); td.className = "commands"; if (id == -1) { AddSmallButton(td, "Add", DoAdd, id); } else { AddSmallButton(td, "Edit", DoEdit, id); AddText(td, "\u00a0"); AddSmallButton(td, "Delete", DoDelete, id); AddText(td, "\u00a0"); AddSmallButtonUpDown(td, "Show", DoShow, DoHide, id); if (next_id != -1 || prev_id != -1) { AddElement(td, "br"); if (prev_id != -1) { AddSmallButtonPrevNext(td, "Up", DoUp, id, prev_id, next_id); AddText(td, "\u00a0"); } if (next_id != -1) { AddSmallButtonPrevNext (td, "Down", DoDown, id, prev_id, next_id); } } AddElement(td, "br"); AddSmallButton(td, "Copy Username", DoCopyUsername, id); AddText(td, "\u00a0"); AddSmallButton(td, "Copy Password", DoCopyPassword, id); } tr.appendChild(td); table.appendChild(tr); } function AddHeaderRow(table, rowcount) { var tr = document.createElement("tr"); if ((rowcount % 2) == 1) { tr.className = "style1"; } else { tr.className = "style2"; } var td; td = document.createElement("td"); td.className = "description"; AddText(td, "Description"); tr.appendChild(td); td = document.createElement("td"); td.className = "username"; AddText(td, "Username"); tr.appendChild(td); td = document.createElement("td"); td.className = "password"; AddText(td, "Password"); tr.appendChild(td); td = document.createElement("td"); td.className = "commands"; AddText(td, "Commands"); tr.appendChild(td); table.appendChild(tr); } function GetGroupRows() { var result = []; for(var f = 0; f < globalDb.length; f++) { if (globalDb[f].group == globalCurrentGroup) { result.push(globalDb[f]); } } return result; } function LoadTable() { var table = document.getElementById("DataTable"); table.innerHTML = ""; var rowcount = 0; AddHeaderRow(table, rowcount++); var rows = GetGroupRows(); for(var f = 0; f < rows.length; f++) { var prevId = -1; var nextId = -1; if (f > 0) { prevId = rows[f-1].id; } if (f < rows.length - 1) { nextId = rows[f+1].id; } AddRow(table, rows[f].id, prevId, nextId, rows[f].description, rows[f].username, Decrypt(rows[f].password), rowcount++); } AddRow(table, -1, -1, -1, "", "", "", rowcount++); } function RefreshDataAsync() { try { globalDb = JSON.parse(this.responseText); } catch(e) { Error(e); globalDb = []; return; } if (globalDb.error) { Error(globalDb.error); globalDb = []; } else { LoadGroups(true); LoadTable(); } } function RefreshData() { WebRequest("get.php", RefreshDataAsync, []); } function LoadInitialData() { LoadGroups(false); LoadTable(); } function DoLoadAsync() { try { globalDb = JSON.parse(this.responseText); } catch(e) { Error(e); globalDb = []; return; } if (globalDb.error) { Error(globalDb.error); globalDb = []; } else { LoadInitialData(); SetEnable("ChangePassphrase", true); } } function DoLoad() { if (IsEmpty("PassPhrase")) { Error("Passphrase empty"); return; } WebRequest("get.php", DoLoadAsync, []); } function DoChangePassphraseAsync() { try { var response = JSON.parse(this.responseText); } catch(e) { Error(e); return; } 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 = ""; LoadTable(); } function DoAddAsync() { try { var response = JSON.parse(this.responseText); } catch(e) { Error(e); return; } if (response.error) { Error(response.error); } else { globalCurrentGroup = response.group; RefreshData(); } } function DoAdd() { if (IsEmpty("Group") && IsEmpty("NewGroup")) { Error("No groups defined -- please enter a group name"); return; } var id = this.dataset.pmId; var description = document.getElementById("Description" + id).value; var username = document.getElementById("Username" + id).value; var password = document.getElementById("Password" + id).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() { try { var response = JSON.parse(this.responseText); } catch(e) { Error(e); return; } if (response.error) { Error(response.error); } else { globalCurrentGroup = response.group; RefreshData(); } } function DoEdit() { var id = this.dataset.pmId; var description = document.getElementById("Description" + id).value; var username = document.getElementById("Username" + id).value; var password = document.getElementById("Password" + id).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", id, "description", description, "group", group, "username", username, "password", Encrypt(password) ] ); } function DoDeleteAsync() { try { var response = JSON.parse(this.responseText); } catch(e) { Error(e); return; } if (response.error) { Error(response.error); } else { RefreshData(); } } function DoDelete() { var id = this.dataset.pmId; WebRequest("delete.php", DoDeleteAsync, [ "id", id ] ); } function DoCopyUsername() { var id = "Username" + this.dataset.pmId; Copy(id); } function DoCopyPassword() { var id = "Password" + this.dataset.pmId; 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() { try { var response = JSON.parse(this.responseText); } catch(e) { Error(e); return; } if (response.error) { Error(response.error); } else { RefreshData(); } } function DoUp() { var id = this.dataset.pmId; var prev = this.dataset.pmPrevId; WebRequest("reorder.php", DoReorderAsync, [ "from_id", id, "to_id", prev ] ); } function DoDown() { var id = this.dataset.pmId; var next = this.dataset.pmNextId; WebRequest("reorder.php", DoReorderAsync, [ "from_id", id, "to_id", next ] ); } function DoShowPasswords() { var type; if (ShowPasswords()) { type = "text"; } else { type = "password"; } SetInputType("PassPhrase", type); SetInputType("NewPassPhrase", type); SetInputType("Password-1", type); var rows = GetGroupRows(); var f; for(f = 0; f < rows.length;f++) { var id = "Password" + rows[f].id; SetInputType(id, type); } } function DoDocumentLoaded() { var div = document.getElementById("Header"); var height = div.clientHeight + 2; var table = document.getElementById("DataTable"); table.style.marginTop = height + "px"; } window.addEventListener("load", DoDocumentLoaded); // vim: sw=4 ts=4