Some enhancements in server interface :

* Display PHP parsed URL in new URL case, not raw URL
	* Add a filter for unciphered passwords (supports regular expressions)
	* Add a button to copy unciphered password into clipboard
	* Don't clear URL and login when adding a new password
This commit is contained in:
Gregory Soutade 2022-02-09 21:10:13 +01:00
parent 2def010612
commit 42142cbca9
3 changed files with 107 additions and 45 deletions

View File

@ -180,7 +180,7 @@ else
}
}
echo "</select>\n";
echo ' <b>Master key </b> <input id="master_key" type="password" onkeypress="if (event.keyCode == 13) update_master_key(true);"/>';
echo ' <b>Master key </b> <input id="master_key" type="password" onchange="update_master_key(true);"/>';
echo "<input type=\"button\" value=\"See\" onclick=\"update_master_key(true);\" />" . "\n";
if (!isset($_SERVER['HTTPS']))
@ -197,10 +197,10 @@ if ($user != "")
{
echo "<div class=\"title\">Add a new password</div>\n";
echo 'URL <input type="text" id="new_url" name="url" value="' . (filter_input(INPUT_GET, "url", FILTER_SANITIZE_SPECIAL_CHARS) ?: "") . '"/>';
echo 'URL <input type="text" id="new_url" name="url" value="' . (parse_url(filter_input(INPUT_GET, "url", FILTER_SANITIZE_SPECIAL_CHARS))['host'] ?: "") . '"/>';
echo 'login <input type="text" id="new_login" name="login" value="' . (filter_input(INPUT_GET, "user", FILTER_SANITIZE_SPECIAL_CHARS) ?: "") . '"/>';
echo 'password <input id="new_password" type="text" name="password"/>';
echo 'master key <input type="text" name="mkey" id="new_mkey" onkeypress="if (event.keyCode == 13) add_password();" onkeyup="chkPass(this.value);"/>';
echo 'master key <input type="text" name="mkey" id="new_mkey" onchange="add_password();" onkeyup="chkPass(this.value);"/>';
echo '<input type="button" value="Generate password" onClick="generate_password();"/>';
echo '<input type="button" value="Generate simple password" onClick="generate_simple_password();"/>';
echo "<input type=\"button\" name=\"add\" value=\"Add\" onclick=\"add_password();\"/>";
@ -237,8 +237,13 @@ if ($user != "")
}
?>
</div>
<div id="passwords">
<div id="filter">
Filter <input id='password_filter' value=<?php echo "'" . (parse_url(filter_input(INPUT_GET, "url", FILTER_SANITIZE_SPECIAL_CHARS))['host'] ?: "") . "'" ?> onchange='password_filter_changed();'/>
<input type="button" onclick="password_filter_changed();" value="Apply"/>
<input type="button" onclick="document.getElementById('password_filter').value = '';password_filter_changed();" value="Clear"/>
</div>
<div id="passwords"></div>
</div>
</body>
</html>

View File

@ -124,6 +124,10 @@ input {
visibility:hidden;
}
#filter {
font-weight:bold;
}
.error {
text-align:center;
color:red;

View File

@ -161,6 +161,8 @@ var current_mkey = "";
var clearTimer = null;
var global_iv = null;
var server_url = window.location.href.split('?')[0];
var clear_passwords = new Array();
var block_filter = true;
function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
this.ciphered_login = ciphered_login;
@ -426,6 +428,51 @@ async function get_ciphered_credentials(masterkey)
req.send("get_secure_passwords=1&user=" + current_user + "&access_tokens=" + access_tokens);
}
function password_filter_changed()
{
if (block_filter) return;
filter = document.getElementById('password_filter').value ;
if (filter !== '')
filter = '.*' + filter + '.*';
password_div = document.getElementById("clear_passwords");
password_div.removeAllChilds();
for (idx in clear_passwords)
{
div = clear_passwords[idx];
if (typeof(div) === 'function')
continue;
if (filter === '')
password_div.appendChild(div);
else
{
childs = clear_passwords[idx].children;
for (elem_idx in childs)
{
elem = childs[elem_idx];
if (elem.name == 'url')
{
// Remove * for wildcards domains
target_url = elem.value.replace('*', '') ;
try {
if (target_url.match(filter))
password_div.appendChild(div);
}
/* Forgive re errors */
catch(error)
{
// console.log(error);
}
break;
}
}
}
}
}
async function change_master_key(warning_unciphered)
{
var nb_unciphered = 0;
@ -439,9 +486,6 @@ async function change_master_key(warning_unciphered)
nb_unciphered++;
}
if (!nb_unciphered && warning_unciphered)
alert("No password unciphered with this master key !");
password_div = document.getElementById("passwords");
password_div.removeAllChilds();
@ -449,6 +493,11 @@ async function change_master_key(warning_unciphered)
div.setAttribute("id", "nb_unciphered_passwords");
password_div.appendChild(div);
div = document.createElement("div");
div.setAttribute("id", "clear_passwords");
password_div.appendChild(div);
clear_passwords = new Array();
for(i=0; i<passwords.length; i++)
{
if (passwords[i].isUnciphered(current_mkey))
@ -497,10 +546,19 @@ async function change_master_key(warning_unciphered)
update_button.setAttribute("onclick", "update_entry(\"unciph_entry_" + i + "\");");
div.appendChild(update_button);
password_div.appendChild(div);
clipboard_button = document.createElement("input");
clipboard_button.setAttribute("type", "button");
clipboard_button.setAttribute("value", "Copy password");
clipboard_button.setAttribute("onclick", "copy_clipboard(\"unciph_entry_" + i + "\");");
div.appendChild(clipboard_button);
clear_passwords.push(div);
}
}
if (warning_unciphered && !nb_unciphered)
alert("No password unciphered with this master key !");
div = document.createElement("div");
div.setAttribute("id", "nb_ciphered_passwords");
password_div.appendChild(div);
@ -557,41 +615,12 @@ async function change_master_key(warning_unciphered)
}
}
cur_url = document.getElementById("new_url").value;
/* If we have a current URL in add form and we have a password entry that match this URL, go to the last */
/* Can't do this before, because everything is not displayed from browser */
if (cur_url !== "")
{
cur_url = url_domain(cur_url);
for(i=0; i<passwords.length; i++)
{
if (!passwords[i].isUnciphered(current_mkey))
continue;
url_elem = document.getElementById("unciph_url_" + i);
target_url = url_elem.value;
// Replace wildcard domain by .*<domain>
if (target_url[0] == "*")
target_url = "." + target_url;
try {
if (cur_url.match(target_url))
{
window.scrollTo(0, url_elem.offsetTop);
break;
}
}
/* Forgive re errors */
catch(error)
{
//console.log(error);
}
}
}
input = document.getElementById("master_key");
input.value = "";
update_stats();
block_filter = false;
password_filter_changed();
}
function update_master_key(warning_unciphered)
@ -783,16 +812,14 @@ function add_password()
for(i=0; i<inputs.length; i++)
{
if (inputs[i].getAttribute("type") == "text" ||
inputs[i].getAttribute("type") == "password")
name = inputs[i].getAttribute("name");
if (name === "password" || name === "mkey")
inputs[i].value = "";
}
startClearTimer();
});
window.scrollTo(0,document.body.scrollHeight);
return true;
}
@ -988,6 +1015,32 @@ async function update_masterkey()
}
}
function copy_clipboard(entry_number)
{
var password = "";
entry = document.getElementById(entry_number);
if (entry == null) {
alert(entry_number + " not found");
return;
}
inputs = entry.getElementsByTagName("input");
for(i=0; i<inputs.length; i++)
{
if (inputs[i].getAttribute("name") == "password")
{
inputs[i].select();
document.execCommand('copy');
inputs[i].setSelectionRange(0,0); // Unselect
alert('Password copied into clipboard');
break;
}
}
}
function makeText(text) {
var data = new Blob([text], {type: 'application/xml'});