Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 422178bc9d | |||
| 736d717676 | |||
| 7f95b19264 | |||
| 354ddbbba9 | |||
| d25436f597 | |||
| b79000accb | |||
| 0e48a34d71 | |||
| 96b378695e | |||
| a485267da8 | |||
| 267a809019 | |||
| 6611641534 | |||
| 12d49fab4e | |||
|
|
4cfd61d077 | ||
|
|
d2fe770463 | ||
|
|
0f74943e92 | ||
|
|
4271551fed |
30
ChangeLog
30
ChangeLog
@@ -1,3 +1,33 @@
|
||||
**v1.1 :**
|
||||
|
||||
Server
|
||||
* Remove old v1 crypto functions & compatibility
|
||||
|
||||
Addon
|
||||
* Add always_disabled feature
|
||||
* Fix bug in gpass icon management
|
||||
* Set activated icon only when a username is filled
|
||||
* Add a checkbox to only copy password into clipboard from popup (and a default behaviour from options)
|
||||
|
||||
CLI
|
||||
|
||||
|
||||
**v1.0 :**
|
||||
|
||||
Server
|
||||
|
||||
* Add clear form button for "Add new password" div
|
||||
* If we have a current URL in add form and we have a password entry that match this URL, go to the last when all is deciphered
|
||||
|
||||
Addon
|
||||
* Remove old v1 crypto functions & compatibility
|
||||
* Remove old firefox addon code
|
||||
* Remove block_url feature to increase websites compatibility
|
||||
* Force copy password into clipboard for @_ request from popup even if we can fill it
|
||||
* Fix a bug: wait for promise before displaying message for clipboard pasted password
|
||||
|
||||
CLI
|
||||
|
||||
**v0.9 :**
|
||||
|
||||
Server
|
||||
|
||||
@@ -25,7 +25,9 @@ When you're in a login form and you want to use gPass, type your login (case sen
|
||||
|
||||
**You can also type "@_masterkey" to only replace your password without automatic submit. This allows to support more websites.**
|
||||
|
||||
Another option is to enter your credentials in the new popup menu by clicking on gPass icon. If it's possible, gPass will auto fill password field, if not result password is stored into your clipboard. Popup path is a safest method as website page will never see your masterkey. There is also an option to disable addon for a specific website (it's a local configuration, so it must be done for each browser).
|
||||
Another option is to enter your credentials in the new popup menu by clicking on gPass icon. If it's possible, gPass will auto fill password field, if not result password is stored into your clipboard. **Popup path is a safest method as website page will never see your masterkey.**
|
||||
|
||||
** Warning ** : Sometimes, addon could make some websites unusable, especially for login form. In this case, you can deactivate it for only one website by clicking right on gPass icon and "disable or enable gPass for this website" in addon menu. It's a local configuration, so it must be done for each browser. gPass can also be disabled for ALL websites thanks to addon menu "Disable or enable gPass for ALL websites". _When gPass is disabled, you can still use popup feature_.
|
||||
|
||||
|
||||
Technical details
|
||||
@@ -82,7 +84,7 @@ A sample configuration file is available _gpass.ini.sample_
|
||||
Version Information
|
||||
-------------------
|
||||
|
||||
Current version is 0.9.
|
||||
Current version is 1.1.
|
||||
|
||||
|
||||
License
|
||||
|
||||
@@ -162,7 +162,7 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||
{
|
||||
debug("New pbkdf2 level " + server_pbkdf2_level);
|
||||
pbkdf2_level = server_pbkdf2_level;
|
||||
set_preference("pbkdf2_level", pbkdf2_level);
|
||||
set_preference("pbkdf2_level", pbkdf2_level, null);
|
||||
ret = SERVER.RESTART_REQUEST;
|
||||
}
|
||||
break;
|
||||
@@ -234,6 +234,8 @@ function update_gpass_icon(iconId, tabId)
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
debug(icon_name);
|
||||
|
||||
icon_infos["path"] = {
|
||||
16:"icons/gpass" + icon_name + "_icon_16.png",
|
||||
@@ -245,12 +247,29 @@ function update_gpass_icon(iconId, tabId)
|
||||
browser.browserAction.setIcon(icon_infos);
|
||||
}
|
||||
|
||||
function is_gpass_enabled(uri)
|
||||
async function is_gpass_enabled(uri)
|
||||
{
|
||||
var domain = parseURI.parseUri(uri);
|
||||
domain = domain["host"];
|
||||
debug("Is gpass enabled for " + domain + " ?");
|
||||
return get_preference("disable-" + domain);
|
||||
return await get_preference("always_disabled").then(
|
||||
function(always_disabled) {
|
||||
if (always_disabled)
|
||||
{
|
||||
debug("Always disabled");
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(1); // null -> enabled, 1 -> disabled
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Check for enable");
|
||||
var domain = parseURI.parseUri(uri);
|
||||
domain = domain["host"];
|
||||
debug("Is gpass enabled for " + domain + " ?");
|
||||
|
||||
return get_preference("disable-" + domain);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function save_gpass_enable_config(uri, enable)
|
||||
@@ -267,7 +286,7 @@ function save_gpass_enable_config(uri, enable)
|
||||
else
|
||||
{
|
||||
debug("Disable gpass for " + domain);
|
||||
set_preference(key, true);
|
||||
set_preference(key, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +297,7 @@ function _query_tabs_is_gpass_enabled(tabs, sendResponse)
|
||||
is_gpass_enabled(tabs[0].url).then(
|
||||
function (key_present) {
|
||||
enabled = (key_present == null);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.ENABLED:GPASS_ICON.DISABLED, tabs[0].id);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tabs[0].id);
|
||||
sendResponse({"enabled":enabled});
|
||||
}
|
||||
);
|
||||
@@ -300,28 +319,36 @@ function _query_tabs_update_icon(tabs, iconId)
|
||||
}
|
||||
}
|
||||
|
||||
function update_enable(enabled, tab, saveConfig)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
parameters = {type:"blockForms"};
|
||||
saveConfig = true;// Force save when enable website
|
||||
debug("Now enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = {type:"unblockForms"};
|
||||
debug("Now disabled");
|
||||
}
|
||||
|
||||
if (saveConfig)
|
||||
save_gpass_enable_config(tab.url, enabled);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tab.id);
|
||||
browser.tabs.sendMessage(tab.id, parameters);
|
||||
}
|
||||
|
||||
function gpass_switch_enable(tab)
|
||||
{
|
||||
debug("Switch enable");
|
||||
is_gpass_enabled(tab.url).then(
|
||||
function (key_present)
|
||||
{
|
||||
enabled = (key_present == null);
|
||||
// Do switch
|
||||
enabled = !enabled;
|
||||
if (enabled)
|
||||
{
|
||||
parameters = {type:"blockForms"};
|
||||
debug("Now enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = {type:"unblockForms"};
|
||||
debug("Now disabled");
|
||||
}
|
||||
|
||||
save_gpass_enable_config(tab.url, enabled);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.ENABLED:GPASS_ICON.DISABLED, tab.id);
|
||||
browser.tabs.sendMessage(tab.id, parameters);
|
||||
update_enable(enabled, tab, true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -353,6 +380,14 @@ function extension_load()
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "getPopupClipboard")
|
||||
{
|
||||
get_preference("popup_clipboard").then(
|
||||
function (value) {
|
||||
sendResponse({"value" : value});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "is_gpass_enabled")
|
||||
{
|
||||
browser.tabs.query({active:true, currentWindow:true},
|
||||
@@ -361,15 +396,6 @@ function extension_load()
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "switch_enable")
|
||||
{
|
||||
debug("Switch enable");
|
||||
browser.tabs.query({active:true, currentWindow:true},
|
||||
function cb(tabs) {
|
||||
_query_tabs_switch_enable(tabs, sendResponse)
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "update_icon")
|
||||
{
|
||||
debug("update_icon");
|
||||
@@ -387,7 +413,8 @@ function extension_load()
|
||||
|
||||
if (!browser.menus && browser.contextMenus)
|
||||
browser.menus = browser.contextMenus;
|
||||
|
||||
|
||||
/* Settings */
|
||||
browser.menus.create({
|
||||
id: 'settings',
|
||||
title: 'gPass Settings',
|
||||
@@ -396,16 +423,30 @@ function extension_load()
|
||||
|
||||
/* Not supported by Chrome */
|
||||
if (browser.menus.onShown)
|
||||
title = 'disable gPass for this website';
|
||||
title = 'Disable gPass for this website';
|
||||
else
|
||||
title = 'disable or enable gPass for this website';
|
||||
title = 'Disable or enable gPass for this website';
|
||||
|
||||
/* Enable/disable */
|
||||
browser.menus.create({
|
||||
id: 'switch_enable',
|
||||
title: title,
|
||||
contexts: ['browser_action']
|
||||
});
|
||||
|
||||
/* Not supported by Chrome */
|
||||
if (browser.menus.onShown)
|
||||
title = 'Disable gPass for ALL websites';
|
||||
else
|
||||
title = 'Disable or enable gPass for ALL websites';
|
||||
|
||||
/* Always enable/disable */
|
||||
browser.menus.create({
|
||||
id: 'always_disable',
|
||||
title: title,
|
||||
contexts: ['browser_action']
|
||||
});
|
||||
|
||||
browser.menus.onClicked.addListener(
|
||||
function(info, tab) {
|
||||
switch (info.menuItemId) {
|
||||
@@ -413,6 +454,26 @@ function extension_load()
|
||||
browser.runtime.openOptionsPage();
|
||||
break;
|
||||
|
||||
case 'always_disable':
|
||||
get_preference('always_disabled').then(
|
||||
function (always_disabled) {
|
||||
debug('Change always disable');
|
||||
debug(always_disabled);
|
||||
always_disabled = !always_disabled;
|
||||
|
||||
set_preference('always_disabled', always_disabled,
|
||||
function(error)
|
||||
{
|
||||
browser.tabs.query({},
|
||||
function cb(tabs) {
|
||||
for (i=0; i<tabs.length; i++)
|
||||
update_enable(!always_disabled, tabs[i], false);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
break;
|
||||
case 'switch_enable':
|
||||
gpass_switch_enable(tab);
|
||||
break;
|
||||
@@ -428,9 +489,9 @@ function extension_load()
|
||||
function (key_present) {
|
||||
enabled = (key_present == null);
|
||||
if (enabled)
|
||||
title = 'disable gPass for this website';
|
||||
title = 'Disable gPass for this website';
|
||||
else
|
||||
title = 'enable gPass for this website';
|
||||
title = 'Enable gPass for this website';
|
||||
browser.menus.update("switch_enable",
|
||||
{
|
||||
"title":title
|
||||
@@ -441,6 +502,25 @@ function extension_load()
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
browser.menus.onShown.addListener(
|
||||
function(info, tab) {
|
||||
get_preference('always_disabled').then(
|
||||
function (always_disabled) {
|
||||
if (always_disabled)
|
||||
title = 'Enable gPass for ALL websites';
|
||||
else
|
||||
title = 'Disable gPass for ALL websites';
|
||||
browser.menus.update("always_disable",
|
||||
{
|
||||
"title":title
|
||||
}
|
||||
);
|
||||
browser.menus.refresh();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"always_disabled":false,
|
||||
"popup_clipboard":false
|
||||
};
|
||||
|
||||
function get_preference(key)
|
||||
{
|
||||
// Inspired from https://github.com/akiomik/chrome-storage-promise/
|
||||
@@ -44,12 +50,14 @@ function get_preference(key)
|
||||
return promise;
|
||||
}
|
||||
|
||||
function set_preference(key, value)
|
||||
function set_preference(key, value, sendResponse)
|
||||
{
|
||||
pref = {[key]:value};
|
||||
chrome.storage.local.set(pref, function (result) {
|
||||
if (chrome.runtime.lastError)
|
||||
alert(chrome.runtime.lastError);
|
||||
if (sendResponse)
|
||||
sendResponse(chrome.runtime.lastError);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -56,23 +56,35 @@ function try_get_name(fields, type_filters, match)
|
||||
for (var i=0; i<fields.length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
var to_test = !match;
|
||||
|
||||
for (var a=0; a<type_filters.length; a++)
|
||||
{
|
||||
if ((match && field.getAttribute("type") == type_filters[a]) ||
|
||||
(!match && field.getAttribute("type") != type_filters[a]))
|
||||
{
|
||||
if (field.hasAttribute("name") && field.value != "")
|
||||
{
|
||||
name = field.getAttribute("name");
|
||||
// Subset of common user field
|
||||
if (name == "user") user = field.value;
|
||||
else if (name == "usr") user = field.value;
|
||||
else if (name == "username") user = field.value;
|
||||
else if (name == "login") user = field.value;
|
||||
if (match && field.getAttribute("type") == type_filters[a])
|
||||
{
|
||||
to_test = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_add_name(all_logins, field.value);
|
||||
}
|
||||
if(!match && field.getAttribute("type") == type_filters[a])
|
||||
{
|
||||
to_test = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (to_test)
|
||||
{
|
||||
if (field.hasAttribute("name") && field.value != "")
|
||||
{
|
||||
name = field.getAttribute("name");
|
||||
// Subset of common user field
|
||||
if (name == "user") user = field.value;
|
||||
else if (name == "usr") user = field.value;
|
||||
else if (name == "username") user = field.value;
|
||||
else if (name == "login") user = field.value;
|
||||
|
||||
_add_name(all_logins, field.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,28 +95,59 @@ function try_get_name(fields, type_filters, match)
|
||||
return all_logins;
|
||||
}
|
||||
|
||||
function get_logins(form, all_logins)
|
||||
{
|
||||
var fields = form.getElementsByTagName("input");
|
||||
var logins = null;
|
||||
|
||||
debug("get_logins");
|
||||
|
||||
var type_filters = new Array();
|
||||
|
||||
// Get all <input type="text"> && <input type="email">
|
||||
type_filters.push("text");
|
||||
type_filters.push("email");
|
||||
if (all_logins)
|
||||
logins = try_get_name(fields, type_filters, true);
|
||||
else
|
||||
{
|
||||
// Get all other fields except text, email and password
|
||||
type_filters.push("password");
|
||||
type_filters.push("hidden");
|
||||
logins = try_get_name(fields, type_filters, false);
|
||||
}
|
||||
|
||||
return logins;
|
||||
}
|
||||
|
||||
function on_focus(e)
|
||||
{
|
||||
if (gpass_enabled)
|
||||
if (!gpass_enabled)
|
||||
return;
|
||||
|
||||
var logins = get_logins(this.form, true);
|
||||
var all_logins = get_logins(this.form, false);
|
||||
|
||||
if (logins.length || all_logins.length)
|
||||
{
|
||||
parameters = {
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.ACTIVATED,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
}
|
||||
|
||||
function on_blur(e)
|
||||
{
|
||||
if (gpass_enabled)
|
||||
{
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.NORMAL,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
if (!gpass_enabled)
|
||||
return;
|
||||
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.NORMAL,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
|
||||
function on_sumbit(e)
|
||||
@@ -116,15 +159,8 @@ function on_sumbit(e)
|
||||
|
||||
debug("on_submit");
|
||||
|
||||
type_filters = new Array();
|
||||
// Get all <input type="text"> && <input type="email">
|
||||
type_filters.push("text");
|
||||
type_filters.push("email");
|
||||
logins = try_get_name(fields, type_filters, true);
|
||||
|
||||
// Get all other fields except text, email and password
|
||||
type_filters.push("password");
|
||||
all_logins = try_get_name(fields, type_filters, false);
|
||||
logins = get_logins(form, true);
|
||||
all_logins = get_logins(form, false);
|
||||
|
||||
if (!logins.length)
|
||||
logins = all_logins;
|
||||
@@ -259,8 +295,6 @@ function unblock_all_forms()
|
||||
{
|
||||
debug("unblock all forms");
|
||||
|
||||
on_blur(null);
|
||||
|
||||
for(var i=0; i<managed_forms.length; i++)
|
||||
{
|
||||
var form = managed_forms[i];
|
||||
|
||||
@@ -22,10 +22,6 @@ var DEBUG = false;
|
||||
SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2};
|
||||
GPASS_ICON = {NORMAL:0, DISABLED:1, ACTIVATED:2};
|
||||
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"crypto_v1_compatible": true};
|
||||
|
||||
var browser = browser || chrome;
|
||||
var crypto = crypto || window.crypto;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
"name": "gPass",
|
||||
"short_name": "gPass",
|
||||
"version": "1.0",
|
||||
"version": "1.1",
|
||||
"description": "gPass : global password manager",
|
||||
"icons" : {"16":"icons/gpass_icon_16.png", "32":"icons/gpass_icon_32.png", "64":"icons/gpass_icon_64.png", "128":"icons/gpass_icon_128.png"},
|
||||
"author" : "Grégory Soutadé",
|
||||
@@ -35,8 +35,6 @@
|
||||
"<all_urls>",
|
||||
"activeTab",
|
||||
"notifications",
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"tabs",
|
||||
"storage",
|
||||
"clipboardWrite",
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
<b>Account URL</b> URL of your gPass account <input id="account_url" type="text"/><br />
|
||||
<b>WARNING</b> It should be a valid HTTPS URL because navigator doesn't like mixed content (HTTPS/HTTP). If not, requests will silentely failed. If you have an auto-signed certificate, add it to trusted ones.<br/>
|
||||
<br/>
|
||||
<b>PBKDF2 level</b> Number of iterations used to derivate master key <input id="pbkdf2" type="number"/><br />
|
||||
<b>PBKDF2 level</b> Number of iterations used to derivate master key <input id="pbkdf2_level" type="number"/><br />
|
||||
<br/>
|
||||
<b>Always disabled</b> Disable gPass for all websites. You can still use popup, but no hook is attached to login forms <input id="always_disabled" type="checkbox"/><br />
|
||||
<br/>
|
||||
<b>Popup clipboard copy</b> Copy password into clipboard (by default) when using popup <input id="popup_clipboard" type="checkbox"/><br />
|
||||
<br/>
|
||||
<br/>
|
||||
<input type="button" id="save" value="Save"/>
|
||||
|
||||
@@ -1,32 +1,46 @@
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo"
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"always_disabled":false,
|
||||
"popup_clipboard":false
|
||||
};
|
||||
|
||||
function save() {
|
||||
var account_url = document.getElementById('account_url').value;
|
||||
var pbkdf2 = document.getElementById('pbkdf2').value;
|
||||
var pbkdf2_level = document.getElementById('pbkdf2_level').value;
|
||||
var always_disabled = document.getElementById('always_disabled').checked;
|
||||
var popup_clipboard = document.getElementById('popup_clipboard').checked;
|
||||
|
||||
chrome.storage.local.set({
|
||||
'account_url': account_url,
|
||||
'pbkdf2': pbkdf2,
|
||||
'pbkdf2_level': pbkdf2_level,
|
||||
'always_disabled': always_disabled,
|
||||
'popup_clipboard': popup_clipboard,
|
||||
}, function() {
|
||||
alert('Saved');
|
||||
});
|
||||
}
|
||||
|
||||
function restoreOption(preferences, pref)
|
||||
{
|
||||
var res;
|
||||
|
||||
if (!preferences.hasOwnProperty(pref))
|
||||
res = default_preferences[pref];
|
||||
else
|
||||
res = preferences[pref];
|
||||
|
||||
var element = document.getElementById(pref);
|
||||
if (element.type == 'checkbox')
|
||||
element.checked = res;
|
||||
else
|
||||
element.value = res;
|
||||
}
|
||||
|
||||
chrome.storage.local.get(null, function(prefs) {
|
||||
if (!prefs.hasOwnProperty("account_url"))
|
||||
account_url = default_preferences['account_url'];
|
||||
else
|
||||
account_url = prefs['account_url'];
|
||||
|
||||
if (!prefs.hasOwnProperty("pbkdf2_level"))
|
||||
pbkdf2 = default_preferences['pbkdf2_level'];
|
||||
else
|
||||
pbkdf2 = prefs['pbkdf2_level'];
|
||||
|
||||
document.getElementById('account_url').value = account_url;
|
||||
document.getElementById('pbkdf2').value = pbkdf2;
|
||||
restoreOption(prefs, 'account_url');
|
||||
restoreOption(prefs, 'pbkdf2_level');
|
||||
restoreOption(prefs, 'always_disabled');
|
||||
restoreOption(prefs, 'popup_clipboard');
|
||||
});
|
||||
|
||||
document.getElementById('save').addEventListener("click", save);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<body>
|
||||
<form id="passwordForm" autocomplete="off">
|
||||
Username <input type="text" id="gPassUsername" autofocus></input><br/> Master key <input type="password" id="gPassMasterKey"/><br/>
|
||||
Copy password into clipboard <input id="clipboard" type="checkbox"/><br />
|
||||
<input id="getButton" type="submit" value="Get"/> <a id="serverLink" href="">Your server</a>
|
||||
</form>
|
||||
<script src="misc.js"></script>
|
||||
|
||||
@@ -17,7 +17,52 @@
|
||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var username_filled = false
|
||||
var username_filled = false;
|
||||
|
||||
function _server_response(response, tabs, do_submit, force_copy)
|
||||
{
|
||||
debug("Get Response");
|
||||
if (response.value == SERVER.OK)
|
||||
{
|
||||
/* Only copy */
|
||||
if (document.getElementById("clipboard").checked)
|
||||
{
|
||||
navigator.clipboard.writeText(response.password).then(function() {
|
||||
notify("Password pasted into clipboard", "");
|
||||
window.close();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fill + optional copy */
|
||||
parameters = {
|
||||
"type":"setPassword",
|
||||
"password":response.password,
|
||||
"submit":do_submit
|
||||
};
|
||||
send_tab_message(tabs[0].id, parameters,
|
||||
function(arg)
|
||||
{
|
||||
debug("Response to setPassword " + arg);
|
||||
if (arg === "" || force_copy)
|
||||
{
|
||||
navigator.clipboard.writeText(response.password).then(function() {
|
||||
notify("Password pasted into clipboard", "");
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
notify("Password filled", "");
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function _query_tabs_get_password(tabs)
|
||||
{
|
||||
@@ -55,34 +100,11 @@ function _query_tabs_get_password(tabs)
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
function (response)
|
||||
{
|
||||
debug("Get Response");
|
||||
if (response.value == SERVER.OK)
|
||||
{
|
||||
parameters = {
|
||||
"type":"setPassword",
|
||||
"password":response.password,
|
||||
"submit":do_submit
|
||||
};
|
||||
send_tab_message(tabs[0].id, parameters,
|
||||
function(arg)
|
||||
{
|
||||
debug("Response to setPassword " + arg);
|
||||
if (arg == "" || force_copy)
|
||||
{
|
||||
navigator.clipboard.writeText(response.password);
|
||||
notify("Password pasted into clipboard", "");
|
||||
}
|
||||
else
|
||||
notify("Password filled", "");
|
||||
window.close();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
function (response)
|
||||
{
|
||||
return _server_response(response, tabs, do_submit, force_copy);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -125,9 +147,22 @@ function _query_tabs_init(tabs)
|
||||
}
|
||||
});
|
||||
|
||||
/* Clipboard copy */
|
||||
parameters = {
|
||||
"type":"getPopupClipboard"
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
function (response)
|
||||
{
|
||||
document.getElementById("clipboard").checked = response.value;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/* Setup server link address */
|
||||
parameters = {
|
||||
type:"getServerAddress"
|
||||
"type":"getServerAddress"
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
|
||||
@@ -162,7 +162,7 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||
{
|
||||
debug("New pbkdf2 level " + server_pbkdf2_level);
|
||||
pbkdf2_level = server_pbkdf2_level;
|
||||
set_preference("pbkdf2_level", pbkdf2_level);
|
||||
set_preference("pbkdf2_level", pbkdf2_level, null);
|
||||
ret = SERVER.RESTART_REQUEST;
|
||||
}
|
||||
break;
|
||||
@@ -234,6 +234,8 @@ function update_gpass_icon(iconId, tabId)
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
debug(icon_name);
|
||||
|
||||
icon_infos["path"] = {
|
||||
16:"icons/gpass" + icon_name + "_icon_16.png",
|
||||
@@ -245,12 +247,29 @@ function update_gpass_icon(iconId, tabId)
|
||||
browser.browserAction.setIcon(icon_infos);
|
||||
}
|
||||
|
||||
function is_gpass_enabled(uri)
|
||||
async function is_gpass_enabled(uri)
|
||||
{
|
||||
var domain = parseURI.parseUri(uri);
|
||||
domain = domain["host"];
|
||||
debug("Is gpass enabled for " + domain + " ?");
|
||||
return get_preference("disable-" + domain);
|
||||
return await get_preference("always_disabled").then(
|
||||
function(always_disabled) {
|
||||
if (always_disabled)
|
||||
{
|
||||
debug("Always disabled");
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(1); // null -> enabled, 1 -> disabled
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Check for enable");
|
||||
var domain = parseURI.parseUri(uri);
|
||||
domain = domain["host"];
|
||||
debug("Is gpass enabled for " + domain + " ?");
|
||||
|
||||
return get_preference("disable-" + domain);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function save_gpass_enable_config(uri, enable)
|
||||
@@ -267,7 +286,7 @@ function save_gpass_enable_config(uri, enable)
|
||||
else
|
||||
{
|
||||
debug("Disable gpass for " + domain);
|
||||
set_preference(key, true);
|
||||
set_preference(key, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +297,7 @@ function _query_tabs_is_gpass_enabled(tabs, sendResponse)
|
||||
is_gpass_enabled(tabs[0].url).then(
|
||||
function (key_present) {
|
||||
enabled = (key_present == null);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.ENABLED:GPASS_ICON.DISABLED, tabs[0].id);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tabs[0].id);
|
||||
sendResponse({"enabled":enabled});
|
||||
}
|
||||
);
|
||||
@@ -300,28 +319,36 @@ function _query_tabs_update_icon(tabs, iconId)
|
||||
}
|
||||
}
|
||||
|
||||
function update_enable(enabled, tab, saveConfig)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
parameters = {type:"blockForms"};
|
||||
saveConfig = true;// Force save when enable website
|
||||
debug("Now enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = {type:"unblockForms"};
|
||||
debug("Now disabled");
|
||||
}
|
||||
|
||||
if (saveConfig)
|
||||
save_gpass_enable_config(tab.url, enabled);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tab.id);
|
||||
browser.tabs.sendMessage(tab.id, parameters);
|
||||
}
|
||||
|
||||
function gpass_switch_enable(tab)
|
||||
{
|
||||
debug("Switch enable");
|
||||
is_gpass_enabled(tab.url).then(
|
||||
function (key_present)
|
||||
{
|
||||
enabled = (key_present == null);
|
||||
// Do switch
|
||||
enabled = !enabled;
|
||||
if (enabled)
|
||||
{
|
||||
parameters = {type:"blockForms"};
|
||||
debug("Now enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = {type:"unblockForms"};
|
||||
debug("Now disabled");
|
||||
}
|
||||
|
||||
save_gpass_enable_config(tab.url, enabled);
|
||||
update_gpass_icon((enabled)?GPASS_ICON.ENABLED:GPASS_ICON.DISABLED, tab.id);
|
||||
browser.tabs.sendMessage(tab.id, parameters);
|
||||
update_enable(enabled, tab, true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -353,6 +380,14 @@ function extension_load()
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "getPopupClipboard")
|
||||
{
|
||||
get_preference("popup_clipboard").then(
|
||||
function (value) {
|
||||
sendResponse({"value" : value});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "is_gpass_enabled")
|
||||
{
|
||||
browser.tabs.query({active:true, currentWindow:true},
|
||||
@@ -361,15 +396,6 @@ function extension_load()
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "switch_enable")
|
||||
{
|
||||
debug("Switch enable");
|
||||
browser.tabs.query({active:true, currentWindow:true},
|
||||
function cb(tabs) {
|
||||
_query_tabs_switch_enable(tabs, sendResponse)
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (request.type == "update_icon")
|
||||
{
|
||||
debug("update_icon");
|
||||
@@ -387,7 +413,8 @@ function extension_load()
|
||||
|
||||
if (!browser.menus && browser.contextMenus)
|
||||
browser.menus = browser.contextMenus;
|
||||
|
||||
|
||||
/* Settings */
|
||||
browser.menus.create({
|
||||
id: 'settings',
|
||||
title: 'gPass Settings',
|
||||
@@ -396,16 +423,30 @@ function extension_load()
|
||||
|
||||
/* Not supported by Chrome */
|
||||
if (browser.menus.onShown)
|
||||
title = 'disable gPass for this website';
|
||||
title = 'Disable gPass for this website';
|
||||
else
|
||||
title = 'disable or enable gPass for this website';
|
||||
title = 'Disable or enable gPass for this website';
|
||||
|
||||
/* Enable/disable */
|
||||
browser.menus.create({
|
||||
id: 'switch_enable',
|
||||
title: title,
|
||||
contexts: ['browser_action']
|
||||
});
|
||||
|
||||
/* Not supported by Chrome */
|
||||
if (browser.menus.onShown)
|
||||
title = 'Disable gPass for ALL websites';
|
||||
else
|
||||
title = 'Disable or enable gPass for ALL websites';
|
||||
|
||||
/* Always enable/disable */
|
||||
browser.menus.create({
|
||||
id: 'always_disable',
|
||||
title: title,
|
||||
contexts: ['browser_action']
|
||||
});
|
||||
|
||||
browser.menus.onClicked.addListener(
|
||||
function(info, tab) {
|
||||
switch (info.menuItemId) {
|
||||
@@ -413,6 +454,26 @@ function extension_load()
|
||||
browser.runtime.openOptionsPage();
|
||||
break;
|
||||
|
||||
case 'always_disable':
|
||||
get_preference('always_disabled').then(
|
||||
function (always_disabled) {
|
||||
debug('Change always disable');
|
||||
debug(always_disabled);
|
||||
always_disabled = !always_disabled;
|
||||
|
||||
set_preference('always_disabled', always_disabled,
|
||||
function(error)
|
||||
{
|
||||
browser.tabs.query({},
|
||||
function cb(tabs) {
|
||||
for (i=0; i<tabs.length; i++)
|
||||
update_enable(!always_disabled, tabs[i], false);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
break;
|
||||
case 'switch_enable':
|
||||
gpass_switch_enable(tab);
|
||||
break;
|
||||
@@ -428,9 +489,9 @@ function extension_load()
|
||||
function (key_present) {
|
||||
enabled = (key_present == null);
|
||||
if (enabled)
|
||||
title = 'disable gPass for this website';
|
||||
title = 'Disable gPass for this website';
|
||||
else
|
||||
title = 'enable gPass for this website';
|
||||
title = 'Enable gPass for this website';
|
||||
browser.menus.update("switch_enable",
|
||||
{
|
||||
"title":title
|
||||
@@ -441,6 +502,25 @@ function extension_load()
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
browser.menus.onShown.addListener(
|
||||
function(info, tab) {
|
||||
get_preference('always_disabled').then(
|
||||
function (always_disabled) {
|
||||
if (always_disabled)
|
||||
title = 'Enable gPass for ALL websites';
|
||||
else
|
||||
title = 'Disable gPass for ALL websites';
|
||||
browser.menus.update("always_disable",
|
||||
{
|
||||
"title":title
|
||||
}
|
||||
);
|
||||
browser.menus.refresh();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"always_disabled":false,
|
||||
"popup_clipboard":false
|
||||
};
|
||||
|
||||
function get_preference(key)
|
||||
{
|
||||
return browser.storage.local.get(key)
|
||||
@@ -38,9 +44,11 @@ function get_preference(key)
|
||||
);
|
||||
}
|
||||
|
||||
function set_preference(key, value)
|
||||
function set_preference(key, value, sendResponse)
|
||||
{
|
||||
browser.storage.local.set({[key]:value});
|
||||
if (sendResponse)
|
||||
sendResponse(true);
|
||||
}
|
||||
|
||||
function delete_preference(key)
|
||||
|
||||
@@ -56,23 +56,35 @@ function try_get_name(fields, type_filters, match)
|
||||
for (var i=0; i<fields.length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
var to_test = !match;
|
||||
|
||||
for (var a=0; a<type_filters.length; a++)
|
||||
{
|
||||
if ((match && field.getAttribute("type") == type_filters[a]) ||
|
||||
(!match && field.getAttribute("type") != type_filters[a]))
|
||||
{
|
||||
if (field.hasAttribute("name") && field.value != "")
|
||||
{
|
||||
name = field.getAttribute("name");
|
||||
// Subset of common user field
|
||||
if (name == "user") user = field.value;
|
||||
else if (name == "usr") user = field.value;
|
||||
else if (name == "username") user = field.value;
|
||||
else if (name == "login") user = field.value;
|
||||
if (match && field.getAttribute("type") == type_filters[a])
|
||||
{
|
||||
to_test = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_add_name(all_logins, field.value);
|
||||
}
|
||||
if(!match && field.getAttribute("type") == type_filters[a])
|
||||
{
|
||||
to_test = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (to_test)
|
||||
{
|
||||
if (field.hasAttribute("name") && field.value != "")
|
||||
{
|
||||
name = field.getAttribute("name");
|
||||
// Subset of common user field
|
||||
if (name == "user") user = field.value;
|
||||
else if (name == "usr") user = field.value;
|
||||
else if (name == "username") user = field.value;
|
||||
else if (name == "login") user = field.value;
|
||||
|
||||
_add_name(all_logins, field.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,28 +95,59 @@ function try_get_name(fields, type_filters, match)
|
||||
return all_logins;
|
||||
}
|
||||
|
||||
function get_logins(form, all_logins)
|
||||
{
|
||||
var fields = form.getElementsByTagName("input");
|
||||
var logins = null;
|
||||
|
||||
debug("get_logins");
|
||||
|
||||
var type_filters = new Array();
|
||||
|
||||
// Get all <input type="text"> && <input type="email">
|
||||
type_filters.push("text");
|
||||
type_filters.push("email");
|
||||
if (all_logins)
|
||||
logins = try_get_name(fields, type_filters, true);
|
||||
else
|
||||
{
|
||||
// Get all other fields except text, email and password
|
||||
type_filters.push("password");
|
||||
type_filters.push("hidden");
|
||||
logins = try_get_name(fields, type_filters, false);
|
||||
}
|
||||
|
||||
return logins;
|
||||
}
|
||||
|
||||
function on_focus(e)
|
||||
{
|
||||
if (gpass_enabled)
|
||||
if (!gpass_enabled)
|
||||
return;
|
||||
|
||||
var logins = get_logins(this.form, true);
|
||||
var all_logins = get_logins(this.form, false);
|
||||
|
||||
if (logins.length || all_logins.length)
|
||||
{
|
||||
parameters = {
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.ACTIVATED,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
}
|
||||
|
||||
function on_blur(e)
|
||||
{
|
||||
if (gpass_enabled)
|
||||
{
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.NORMAL,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
if (!gpass_enabled)
|
||||
return;
|
||||
|
||||
parameters = {
|
||||
type:"update_icon",
|
||||
icon_id:GPASS_ICON.NORMAL,
|
||||
};
|
||||
browser.runtime.sendMessage(parameters, {});
|
||||
}
|
||||
|
||||
function on_sumbit(e)
|
||||
@@ -116,15 +159,8 @@ function on_sumbit(e)
|
||||
|
||||
debug("on_submit");
|
||||
|
||||
type_filters = new Array();
|
||||
// Get all <input type="text"> && <input type="email">
|
||||
type_filters.push("text");
|
||||
type_filters.push("email");
|
||||
logins = try_get_name(fields, type_filters, true);
|
||||
|
||||
// Get all other fields except text, email and password
|
||||
type_filters.push("password");
|
||||
all_logins = try_get_name(fields, type_filters, false);
|
||||
logins = get_logins(form, true);
|
||||
all_logins = get_logins(form, false);
|
||||
|
||||
if (!logins.length)
|
||||
logins = all_logins;
|
||||
@@ -259,8 +295,6 @@ function unblock_all_forms()
|
||||
{
|
||||
debug("unblock all forms");
|
||||
|
||||
on_blur(null);
|
||||
|
||||
for(var i=0; i<managed_forms.length; i++)
|
||||
{
|
||||
var form = managed_forms[i];
|
||||
|
||||
@@ -22,10 +22,6 @@ var DEBUG = false;
|
||||
SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2};
|
||||
GPASS_ICON = {NORMAL:0, DISABLED:1, ACTIVATED:2};
|
||||
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"crypto_v1_compatible": true};
|
||||
|
||||
var browser = browser || chrome;
|
||||
var crypto = crypto || window.crypto;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
"name": "gPass",
|
||||
"short_name": "gPass",
|
||||
"version": "1.0",
|
||||
"version": "1.1",
|
||||
"description": "gPass : global password manager",
|
||||
"icons" : {"16":"icons/gpass_icon_16.png", "32":"icons/gpass_icon_32.png", "64":"icons/gpass_icon_64.png", "128":"icons/gpass_icon_128.png"},
|
||||
"author" : "Grégory Soutadé",
|
||||
@@ -39,8 +39,6 @@
|
||||
"<all_urls>",
|
||||
"activeTab",
|
||||
"notifications",
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"tabs",
|
||||
"storage",
|
||||
"clipboardWrite",
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
<b>Account URL</b> URL of your gPass account <input id="account_url" type="text"/><br />
|
||||
<b>WARNING</b> It should be a valid HTTPS URL because navigator doesn't like mixed content (HTTPS/HTTP). If not, requests will silentely failed. If you have an auto-signed certificate, add it to trusted ones.<br/>
|
||||
<br/>
|
||||
<b>PBKDF2 level</b> Number of iterations used to derivate master key <input id="pbkdf2" type="number"/><br />
|
||||
<b>PBKDF2 level</b> Number of iterations used to derivate master key <input id="pbkdf2_level" type="number"/><br />
|
||||
<br/>
|
||||
<b>Always disabled</b> Disable gPass for all websites. You can still use popup, but no hook is attached to login forms <input id="always_disabled" type="checkbox"/><br />
|
||||
<br/>
|
||||
<b>Popup clipboard copy</b> Copy password into clipboard (by default) when using popup <input id="popup_clipboard" type="checkbox"/><br />
|
||||
<br/>
|
||||
<br/>
|
||||
<input type="button" id="save" value="Save"/>
|
||||
|
||||
@@ -1,33 +1,51 @@
|
||||
var default_preferences = {"pbkdf2_level": 1000,
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo"
|
||||
"account_url": "https://gpass-demo.soutade.fr/demo",
|
||||
"always_disabled":false,
|
||||
"popup_clipboard":false
|
||||
};
|
||||
|
||||
function save() {
|
||||
var account_url = document.getElementById('account_url').value;
|
||||
var pbkdf2 = document.getElementById('pbkdf2').value;
|
||||
var pbkdf2_level = document.getElementById('pbkdf2_level').value;
|
||||
var always_disabled = document.getElementById('always_disabled').checked;
|
||||
var popup_clipboard = document.getElementById('popup_clipboard').checked;
|
||||
|
||||
browser.storage.local.set({
|
||||
"account_url":account_url,
|
||||
"pbkdf2_level":pbkdf2,
|
||||
"pbkdf2_level":pbkdf2_level,
|
||||
"always_disabled": always_disabled,
|
||||
"popup_clipboard": popup_clipboard,
|
||||
})
|
||||
.then(function ok() { alert("Saved"); },
|
||||
function err() { alert("Cannot save your preferences");}
|
||||
);
|
||||
}
|
||||
|
||||
function restoreOption(preferences, pref)
|
||||
{
|
||||
var res;
|
||||
|
||||
if (!preferences.hasOwnProperty(pref))
|
||||
res = default_preferences[pref];
|
||||
else
|
||||
res = preferences[pref];
|
||||
|
||||
var element = document.getElementById(pref);
|
||||
if (element.type == 'checkbox')
|
||||
element.checked = res;
|
||||
else
|
||||
element.value = res;
|
||||
}
|
||||
|
||||
function restoreOptions()
|
||||
{
|
||||
document.getElementById('account_url').value = default_preferences['account_url'];
|
||||
document.getElementById('pbkdf2').value = default_preferences['pbkdf2_level'];
|
||||
|
||||
browser.storage.local.get().then(
|
||||
function(prefs)
|
||||
{
|
||||
if (prefs.hasOwnProperty("account_url"))
|
||||
document.getElementById('account_url').value = prefs["account_url"];
|
||||
|
||||
if (prefs.hasOwnProperty("pbkdf2_level"))
|
||||
document.getElementById('pbkdf2').value = prefs["pbkdf2_level"];
|
||||
restoreOption(prefs, 'account_url');
|
||||
restoreOption(prefs, 'pbkdf2_level');
|
||||
restoreOption(prefs, 'always_disabled');
|
||||
restoreOption(prefs, 'popup_clipboard');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<body>
|
||||
<form id="passwordForm" autocomplete="off">
|
||||
Username <input type="text" id="gPassUsername" autofocus></input><br/> Master key <input type="password" id="gPassMasterKey"/><br/>
|
||||
Copy password into clipboard <input id="clipboard" type="checkbox"/><br />
|
||||
<input id="getButton" type="submit" value="Get"/> <a id="serverLink" href="">Your server</a>
|
||||
</form>
|
||||
<script src="misc.js"></script>
|
||||
|
||||
@@ -17,10 +17,57 @@
|
||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var username_filled = false
|
||||
var username_filled = false;
|
||||
|
||||
function _server_response(response, tabs, do_submit, force_copy)
|
||||
{
|
||||
debug("Get Response");
|
||||
if (response.value == SERVER.OK)
|
||||
{
|
||||
/* Only copy */
|
||||
if (document.getElementById("clipboard").checked)
|
||||
{
|
||||
navigator.clipboard.writeText(response.password).then(function() {
|
||||
notify("Password pasted into clipboard", "");
|
||||
window.close();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fill + optional copy */
|
||||
parameters = {
|
||||
"type":"setPassword",
|
||||
"password":response.password,
|
||||
"submit":do_submit
|
||||
};
|
||||
send_tab_message(tabs[0].id, parameters,
|
||||
function(arg)
|
||||
{
|
||||
debug("Response to setPassword " + arg);
|
||||
if (arg === "" || force_copy)
|
||||
{
|
||||
navigator.clipboard.writeText(response.password).then(function() {
|
||||
notify("Password pasted into clipboard", "");
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
notify("Password filled", "");
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function _query_tabs_get_password(tabs)
|
||||
{
|
||||
var force_copy = false;
|
||||
|
||||
if (tabs.length <= 0) return;
|
||||
|
||||
var username = document.getElementById("gPassUsername").value;
|
||||
@@ -32,6 +79,10 @@ function _query_tabs_get_password(tabs)
|
||||
document.getElementById("gPassMasterKey").value = "";
|
||||
|
||||
var do_submit = !mkey.startsWith("@_") && username_filled;
|
||||
|
||||
if (mkey.startsWith("@_"))
|
||||
force_copy = true;
|
||||
|
||||
if (mkey.startsWith("@@") || mkey.startsWith("@_"))
|
||||
mkey = mkey.substring(2);
|
||||
|
||||
@@ -49,34 +100,11 @@ function _query_tabs_get_password(tabs)
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
function (response)
|
||||
{
|
||||
debug("Get Response");
|
||||
if (response.value == SERVER.OK)
|
||||
{
|
||||
parameters = {
|
||||
"type":"setPassword",
|
||||
"password":response.password,
|
||||
"submit":do_submit
|
||||
};
|
||||
send_tab_message(tabs[0].id, parameters,
|
||||
function(arg)
|
||||
{
|
||||
debug("Response to setPassword " + arg);
|
||||
if (arg == "")
|
||||
{
|
||||
navigator.clipboard.writeText(response.password);
|
||||
notify("Password pasted into clipboard", "");
|
||||
}
|
||||
else
|
||||
notify("Password filled", "");
|
||||
window.close();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
function (response)
|
||||
{
|
||||
return _server_response(response, tabs, do_submit, force_copy);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -119,9 +147,22 @@ function _query_tabs_init(tabs)
|
||||
}
|
||||
});
|
||||
|
||||
/* Clipboard copy */
|
||||
parameters = {
|
||||
"type":"getPopupClipboard"
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
function (response)
|
||||
{
|
||||
document.getElementById("clipboard").checked = response.value;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/* Setup server link address */
|
||||
parameters = {
|
||||
type:"getServerAddress"
|
||||
"type":"getServerAddress"
|
||||
};
|
||||
|
||||
browser.runtime.sendMessage(parameters, {},
|
||||
|
||||
@@ -79,10 +79,4 @@ $REQUESTS_MIN_DELAY=1000;
|
||||
*/
|
||||
$CLEAR_TIME=15*60*1000;
|
||||
|
||||
/*
|
||||
The first crypto schema use an AES-ECB process to encrypt logins.
|
||||
It's used until version 0.7.
|
||||
Since version 0.8, we use AES-CBC + SHA256.
|
||||
*/
|
||||
$CRYPTO_V1_COMPATIBLE=1;
|
||||
?>
|
||||
@@ -79,7 +79,6 @@ else
|
||||
<?php
|
||||
echo "pbkdf2_level=$PBKDF2_LEVEL; use_shadow_logins=$USE_SHADOW_LOGINS;\n";
|
||||
echo "CLEAR_TIME=$CLEAR_TIME; // Clear master key after 15 minutes\n";
|
||||
echo "CRYPTO_V1_COMPATIBLE=$CRYPTO_V1_COMPATIBLE;\n";
|
||||
?>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.onscroll = function(ev) {
|
||||
@@ -158,15 +157,16 @@ if ($user != "")
|
||||
{
|
||||
echo "<b>Add a new password</b><br/>\n";
|
||||
|
||||
echo 'URL <input type="text" name="url" value="' . (filter_input(INPUT_GET, "url", FILTER_SANITIZE_SPECIAL_CHARS) ?: "") . '"/>';
|
||||
echo 'login <input type="text" name="login" value="' . (filter_input(INPUT_GET, "user", FILTER_SANITIZE_SPECIAL_CHARS) ?: "") . '"/>';
|
||||
echo 'URL <input type="text" id="new_url" name="url" value="' . (filter_input(INPUT_GET, "url", FILTER_SANITIZE_SPECIAL_CHARS) ?: "") . '"/>';
|
||||
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" onkeypress="if (event.keyCode == 13) add_password();" onkeyup="chkPass(this.value);"/>';
|
||||
echo 'master key <input type="text" name="mkey" id="new_mkey" onkeypress="if (event.keyCode == 13) 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();\"/>";
|
||||
echo "<br />";
|
||||
echo '<div><a href="http://en.wikipedia.org/wiki/Password_strength">Master key strength</a><div id="scorebarBorder"><div id="score">0%</div><div id="scorebar"> </div></div></div>';
|
||||
echo "<input type=\"button\" name=\"clear\" value=\"Clear Form\" onclick=\"clear_form();\"/>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
@@ -109,6 +109,21 @@ function generate_simple_password()
|
||||
document.getElementById("new_password").value = _generate_random(8, symbols);
|
||||
}
|
||||
|
||||
function clear_form()
|
||||
{
|
||||
div = document.getElementById("add_new_password");
|
||||
|
||||
inputs = div.getElementsByTagName("input");
|
||||
|
||||
for(i=0; i<inputs.length; i++)
|
||||
{
|
||||
if (inputs[i].type == "text" ||
|
||||
inputs[i].type == "password")
|
||||
inputs[i].value = "";
|
||||
}
|
||||
chkPass("");
|
||||
}
|
||||
|
||||
function url_domain(data) {
|
||||
var uri = parseUri(data)
|
||||
return uri['host'];
|
||||
@@ -211,7 +226,6 @@ function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
|
||||
if (masterkey == this.masterkey)
|
||||
return (this.unciphered == true);
|
||||
|
||||
var old = false;
|
||||
var iv = await global_iv;
|
||||
iv = iv.slice(0, 16);
|
||||
var login = await decrypt_cbc(masterkey, iv, hex2a(this.ciphered_login));
|
||||
@@ -223,38 +237,16 @@ function PasswordEntry (ciphered_login, ciphered_password, salt, shadow_login) {
|
||||
{
|
||||
login = login.slice(0, login.length-16).replace(/\0*$/, "");
|
||||
}
|
||||
else if (CRYPTO_V1_COMPATIBLE)
|
||||
{
|
||||
login = await decrypt_ecb(masterkey, hex2a(this.ciphered_login));
|
||||
if (login.indexOf("@@") != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
login = login.replace(/\0*$/, "");
|
||||
// Remove @@
|
||||
login = login.substring(2);
|
||||
old = true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
infos = login.split(";");
|
||||
this.clear_url = infos[0];
|
||||
this.clear_login = infos[1];
|
||||
if (old)
|
||||
{
|
||||
this.clear_password = await decrypt_ecb(masterkey, hex2a(this.ciphered_password));
|
||||
// Remove salt
|
||||
this.clear_password = this.clear_password.replace(/\0*$/, "");
|
||||
this.clear_password = this.clear_password.substr(0, this.clear_password.length-3);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.clear_password = await decrypt_cbc(masterkey, iv, hex2a(this.ciphered_password));
|
||||
// Remove salt
|
||||
this.clear_password = this.clear_password.replace(/\0*$/, "");
|
||||
this.clear_password = this.clear_password.substr(3, this.clear_password.length);
|
||||
}
|
||||
this.clear_password = await decrypt_cbc(masterkey, iv, hex2a(this.ciphered_password));
|
||||
// Remove salt
|
||||
this.clear_password = this.clear_password.replace(/\0*$/, "");
|
||||
this.clear_password = this.clear_password.substr(3, this.clear_password.length);
|
||||
this.unciphered = true;
|
||||
this.masterkey = masterkey;
|
||||
|
||||
@@ -475,6 +467,7 @@ async function change_master_key(warning_unciphered)
|
||||
url = document.createElement("input");
|
||||
url.setAttribute("type", "text");
|
||||
url.setAttribute("name", "url");
|
||||
url.setAttribute("id", "unciph_url_" + i);
|
||||
url.setAttribute("value", passwords[i].clear_url);
|
||||
div.appendChild(url);
|
||||
|
||||
@@ -562,6 +555,37 @@ 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 = "";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user