Update manifest to v3 (Chrome only)
This commit is contained in:
parent
2cb26d6d40
commit
129335dc2d
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
**v1.2 :**
|
||||||
|
|
||||||
|
Server
|
||||||
|
* Rework UI
|
||||||
|
* 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
|
||||||
|
* Change alert() by button name update for "Update" and "Copy clipboard" functions
|
||||||
|
|
||||||
|
Addon
|
||||||
|
* Update manifest to v3 (Chrome only)
|
||||||
|
|
||||||
|
CLI
|
||||||
|
|
||||||
**v1.1 :**
|
**v1.1 :**
|
||||||
|
|
||||||
Server
|
Server
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2013-2020 Grégory Soutadé
|
Copyright (C) 2013-2022 Grégory Soutadé
|
||||||
|
|
||||||
This file is part of gPass.
|
This file is part of gPass.
|
||||||
|
|
||||||
|
@ -17,6 +17,11 @@
|
||||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {parseUri} from "./lib/parseuri.js";
|
||||||
|
import {SERVER, GPASS_ICON, wildcard_domain, simple_pbkdf2, crypto_pbkdf2,
|
||||||
|
encrypt_ecb, encrypt_cbc, decrypt_cbc, digest, a2hex, hex2a, debug} from "./lib/misc.js";
|
||||||
|
import {get_preference, set_preference, delete_preference} from "./compat.js";
|
||||||
|
|
||||||
var browser = browser || chrome;
|
var browser = browser || chrome;
|
||||||
var protocol_version = 4;
|
var protocol_version = 4;
|
||||||
var account_url = null;
|
var account_url = null;
|
||||||
|
@ -26,16 +31,14 @@ function _notification(message, data)
|
||||||
if (message !== data)
|
if (message !== data)
|
||||||
message += data;
|
message += data;
|
||||||
|
|
||||||
options = {
|
var options = {
|
||||||
type: "basic",
|
type: "basic",
|
||||||
title : "gPass",
|
title : "gPass",
|
||||||
message : message,
|
message : message,
|
||||||
iconUrl:browser.extension.getURL("icons/gpass_icon_64.png")
|
iconUrl:"icons/gpass_icon_64.png"
|
||||||
};
|
};
|
||||||
|
|
||||||
browser.notifications.create("gPass", options, function(){});
|
browser.notifications.create("gPass", options, function(){});
|
||||||
|
|
||||||
window.setTimeout(function() {browser.notifications.clear("gPass", function(){})}, 2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generate_request(domain, login, mkey, iv)
|
async function generate_request(domain, login, mkey, iv)
|
||||||
|
@ -44,34 +47,36 @@ async function generate_request(domain, login, mkey, iv)
|
||||||
debug("will encrypt " + v);
|
debug("will encrypt " + v);
|
||||||
while ((v.length % 16))
|
while ((v.length % 16))
|
||||||
v += "\0";
|
v += "\0";
|
||||||
hash = await digest(v);
|
var hash = await digest(crypto, v);
|
||||||
v += hash.slice(8, 24);
|
v += hash.slice(8, 24);
|
||||||
enc = encrypt_cbc(mkey, iv, v);
|
var enc = encrypt_cbc(mkey, iv, v);
|
||||||
|
|
||||||
return enc;
|
return enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
{
|
{
|
||||||
account_url = await get_preference("account_url");
|
var account_url = await get_preference("account_url");
|
||||||
|
|
||||||
var salt = parseURI.parseUri(account_url);
|
var salt = parseUri(account_url);
|
||||||
salt = salt["host"] + salt["path"];
|
salt = salt["host"] + salt["path"];
|
||||||
|
|
||||||
debug("salt " + salt);
|
debug("salt " + salt);
|
||||||
|
|
||||||
pbkdf2_level = await get_preference("pbkdf2_level");
|
var pbkdf2_level = await get_preference("pbkdf2_level");
|
||||||
|
|
||||||
global_iv = await simple_pbkdf2(salt, mkey, pbkdf2_level);
|
var global_iv = await simple_pbkdf2(crypto, salt, mkey, pbkdf2_level);
|
||||||
global_iv = global_iv.slice(0, 16);
|
global_iv = global_iv.slice(0, 16);
|
||||||
mkey = crypto_pbkdf2(mkey, salt, pbkdf2_level);
|
var mkey = crypto_pbkdf2(crypto, mkey, salt, pbkdf2_level);
|
||||||
|
|
||||||
debug("global_iv " + a2hex(global_iv));
|
debug("global_iv " + a2hex(global_iv));
|
||||||
|
|
||||||
keys = "";
|
var keys = "";
|
||||||
|
var key_index;
|
||||||
|
var a;
|
||||||
for(key_index=0, a=0; a<logins.length; a++, key_index++)
|
for(key_index=0, a=0; a<logins.length; a++, key_index++)
|
||||||
{
|
{
|
||||||
enc = await generate_request(domain, logins[a], mkey, global_iv);
|
var enc = await generate_request(domain, logins[a], mkey, global_iv);
|
||||||
keys += (keys.length != 0) ? "&" : "";
|
keys += (keys.length != 0) ? "&" : "";
|
||||||
keys += "k" + key_index + "=" + a2hex(enc);
|
keys += "k" + key_index + "=" + a2hex(enc);
|
||||||
|
|
||||||
|
@ -85,30 +90,43 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
|
|
||||||
debug("Keys " + keys);
|
debug("Keys " + keys);
|
||||||
|
|
||||||
var gPassRequest = new XMLHttpRequest();
|
|
||||||
|
|
||||||
var ret = SERVER.OK;
|
var ret = SERVER.OK;
|
||||||
|
|
||||||
// gPassRequest.addEventListener("progress", function(evt) { ; }, false);
|
debug("connect to " + account_url);
|
||||||
gPassRequest.addEventListener("load", async function(evt) {
|
const headers = {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'};
|
||||||
|
const request = new Request(account_url, {method: 'POST', headers: headers, body: keys});
|
||||||
|
|
||||||
|
const response = await fetch(request).catch((e) => {
|
||||||
|
debug(e);
|
||||||
|
_notification("Network error : check your server address", "");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response === undefined)
|
||||||
|
{
|
||||||
|
ret = SERVER.ERROR;
|
||||||
|
sendResponse({"value": ret, options:options});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseText = await response.text();
|
||||||
|
|
||||||
var ciphered_password = "";
|
var ciphered_password = "";
|
||||||
var clear_password = "";
|
|
||||||
var server_pbkdf2_level = 0;
|
var server_pbkdf2_level = 0;
|
||||||
var server_version = 0;
|
var server_version = 0;
|
||||||
var matched_key = 0;
|
var matched_key = 0;
|
||||||
|
|
||||||
var r = this.responseText.split("\n");
|
var r = responseText.split("\n");
|
||||||
debug("resp " + r);
|
debug("resp " + r);
|
||||||
|
|
||||||
for(var a=0; a<r.length; a++)
|
for(var a=0; a<r.length; a++)
|
||||||
{
|
{
|
||||||
debug("Analyse " + r[a]);
|
debug("Analyse " + r[a]);
|
||||||
|
|
||||||
params = r[a].split("=");
|
var params = r[a].split("=");
|
||||||
if (params.length != 2 && params[0] != "<end>")
|
if (params.length != 2 && params[0] != "<end>")
|
||||||
{
|
{
|
||||||
_notification("Error : It seems that it's not a gPass server",
|
_notification("Error : It seems that it's not a gPass server",
|
||||||
this.responseText);
|
responseText);
|
||||||
ret = SERVER.FAILED;
|
ret = SERVER.FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -121,12 +139,12 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
if (params[1].indexOf("gpass-") != 0)
|
if (params[1].indexOf("gpass-") != 0)
|
||||||
{
|
{
|
||||||
_notification("Error : It seems that it's not a gPass server",
|
_notification("Error : It seems that it's not a gPass server",
|
||||||
this.responseText);
|
responseText);
|
||||||
ret = SERVER.FAILED;
|
ret = SERVER.FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
server_protocol_version = params[1].match(/\d+/)[0];
|
var server_protocol_version = params[1].match(/\d+/)[0];
|
||||||
|
|
||||||
if (server_protocol_version > protocol_version)
|
if (server_protocol_version > protocol_version)
|
||||||
{
|
{
|
||||||
|
@ -172,7 +190,7 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
debug("Unknown command " + params[0]);
|
debug("Unknown command " + params[0]);
|
||||||
|
|
||||||
_notification("Error : It seems that it's not a gPass server",
|
_notification("Error : It seems that it's not a gPass server",
|
||||||
this.responseText);
|
responseText);
|
||||||
ret = SERVER.FAILED;
|
ret = SERVER.FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,10 +205,11 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
if (ciphered_password != "")
|
if (ciphered_password != "")
|
||||||
{
|
{
|
||||||
debug("Ciphered password : " + ciphered_password);
|
debug("Ciphered password : " + ciphered_password);
|
||||||
clear_password = await decrypt_cbc(mkey, global_iv, hex2a(ciphered_password));
|
var clear_password = await decrypt_cbc(mkey, global_iv, hex2a(ciphered_password));
|
||||||
clear_password = clear_password.replace(/\0*$/, "");
|
clear_password = clear_password.replace(/\0*$/, "");
|
||||||
clear_password = clear_password.substr(3, clear_password.length);
|
clear_password = clear_password.substr(3, clear_password.length);
|
||||||
debug("Clear password " + clear_password);
|
debug("Clear password " + clear_password);
|
||||||
|
sendResponse({"value": ret, "password":clear_password, "options":options});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -199,29 +218,19 @@ async function ask_server(logins, domain, wdomain, mkey, sendResponse, options)
|
||||||
ret = SERVER.FAILED;
|
ret = SERVER.FAILED;
|
||||||
|
|
||||||
_notification("No password found in database", "")
|
_notification("No password found in database", "")
|
||||||
|
|
||||||
|
sendResponse({"value": ret, "options":options});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResponse({"value": ret, "password":clear_password, "options":options});
|
return;
|
||||||
}, false);
|
|
||||||
gPassRequest.addEventListener("error", function(evt) {
|
|
||||||
debug("error");
|
|
||||||
ret = false;
|
|
||||||
_notification("Error");
|
|
||||||
}, false);
|
|
||||||
debug("connect to " + account_url);
|
|
||||||
gPassRequest.open("POST", account_url, true);
|
|
||||||
gPassRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
|
||||||
gPassRequest.send(keys);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_gpass_icon(iconId, tabId)
|
function update_gpass_icon(iconId, tabId)
|
||||||
{
|
{
|
||||||
debug("update_gpass_icon");
|
debug("update_gpass_icon");
|
||||||
|
|
||||||
icon_infos = {"tabId":tabId};
|
var icon_infos = {"tabId":tabId};
|
||||||
icon_name = "";
|
var icon_name = "";
|
||||||
|
|
||||||
switch (iconId)
|
switch (iconId)
|
||||||
{
|
{
|
||||||
|
@ -237,6 +246,8 @@ function update_gpass_icon(iconId, tabId)
|
||||||
|
|
||||||
debug(icon_name);
|
debug(icon_name);
|
||||||
|
|
||||||
|
var icon_infos = {};
|
||||||
|
|
||||||
icon_infos["path"] = {
|
icon_infos["path"] = {
|
||||||
16:"icons/gpass" + icon_name + "_icon_16.png",
|
16:"icons/gpass" + icon_name + "_icon_16.png",
|
||||||
32:"icons/gpass" + icon_name + "_icon_32.png",
|
32:"icons/gpass" + icon_name + "_icon_32.png",
|
||||||
|
@ -244,7 +255,10 @@ function update_gpass_icon(iconId, tabId)
|
||||||
128:"icons/gpass" + icon_name + "_icon_128.png",
|
128:"icons/gpass" + icon_name + "_icon_128.png",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (browser.browserAction)
|
||||||
browser.browserAction.setIcon(icon_infos);
|
browser.browserAction.setIcon(icon_infos);
|
||||||
|
else
|
||||||
|
browser.action.setIcon(icon_infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function is_gpass_enabled(uri)
|
async function is_gpass_enabled(uri)
|
||||||
|
@ -262,7 +276,7 @@ async function is_gpass_enabled(uri)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("Check for enable");
|
debug("Check for enable");
|
||||||
var domain = parseURI.parseUri(uri);
|
var domain = parseUri(uri);
|
||||||
domain = domain["host"];
|
domain = domain["host"];
|
||||||
debug("Is gpass enabled for " + domain + " ?");
|
debug("Is gpass enabled for " + domain + " ?");
|
||||||
|
|
||||||
|
@ -274,10 +288,10 @@ async function is_gpass_enabled(uri)
|
||||||
|
|
||||||
function save_gpass_enable_config(uri, enable)
|
function save_gpass_enable_config(uri, enable)
|
||||||
{
|
{
|
||||||
var domain = parseURI.parseUri(uri);
|
var domain = parseUri(uri);
|
||||||
domain = domain["host"];
|
domain = domain["host"];
|
||||||
|
|
||||||
key = "disable-" + domain;
|
var key = "disable-" + domain;
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
debug("Enable gpass for " + domain);
|
debug("Enable gpass for " + domain);
|
||||||
|
@ -296,7 +310,7 @@ function _query_tabs_is_gpass_enabled(tabs, sendResponse)
|
||||||
{
|
{
|
||||||
is_gpass_enabled(tabs[0].url).then(
|
is_gpass_enabled(tabs[0].url).then(
|
||||||
function (key_present) {
|
function (key_present) {
|
||||||
enabled = (key_present == null);
|
var enabled = (key_present == null);
|
||||||
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tabs[0].id);
|
update_gpass_icon((enabled)?GPASS_ICON.NORMAL:GPASS_ICON.DISABLED, tabs[0].id);
|
||||||
sendResponse({"enabled":enabled});
|
sendResponse({"enabled":enabled});
|
||||||
}
|
}
|
||||||
|
@ -321,6 +335,8 @@ function _query_tabs_update_icon(tabs, iconId)
|
||||||
|
|
||||||
function update_enable(enabled, tab, saveConfig)
|
function update_enable(enabled, tab, saveConfig)
|
||||||
{
|
{
|
||||||
|
var parameters;
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
parameters = {type:"blockForms"};
|
parameters = {type:"blockForms"};
|
||||||
|
@ -345,20 +361,54 @@ function gpass_switch_enable(tab)
|
||||||
is_gpass_enabled(tab.url).then(
|
is_gpass_enabled(tab.url).then(
|
||||||
function (key_present)
|
function (key_present)
|
||||||
{
|
{
|
||||||
enabled = (key_present == null);
|
var enabled = (key_present == null);
|
||||||
// Do switch
|
// Do switch
|
||||||
enabled = !enabled;
|
enabled = !enabled;
|
||||||
update_enable(enabled, tab, true);
|
update_enable(enabled, tab, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createMenus(browser)
|
||||||
|
{
|
||||||
|
var title;
|
||||||
|
|
||||||
|
debug("Create menus");
|
||||||
|
|
||||||
|
/* Not supported by Chrome */
|
||||||
|
if (browser.menus.onShown)
|
||||||
|
title = 'Disable gPass for this website';
|
||||||
|
else
|
||||||
|
title = 'Disable or enable gPass for this website';
|
||||||
|
|
||||||
|
/* Enable/disable */
|
||||||
|
browser.menus.create({
|
||||||
|
id: 'switch_enable',
|
||||||
|
title: title,
|
||||||
|
contexts: ['action'],
|
||||||
|
}, () => {console.log(chrome.runtime.lastError);});
|
||||||
|
|
||||||
|
/* 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: ['action']
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function extension_load()
|
function extension_load()
|
||||||
{
|
{
|
||||||
browser.runtime.onMessage.addListener(
|
browser.runtime.onMessage.addListener(
|
||||||
function(request, sender, sendResponse) {
|
function(request, sender, sendResponse) {
|
||||||
if (request.type == "password")
|
if (request.type == "password")
|
||||||
{
|
{
|
||||||
var domain = parseURI.parseUri(request.domain);
|
var domain = parseUri(request.domain);
|
||||||
domain = domain["host"];
|
domain = domain["host"];
|
||||||
var wdomain = wildcard_domain(domain);
|
var wdomain = wildcard_domain(domain);
|
||||||
|
|
||||||
|
@ -390,8 +440,8 @@ function extension_load()
|
||||||
}
|
}
|
||||||
else if (request.type == "is_gpass_enabled")
|
else if (request.type == "is_gpass_enabled")
|
||||||
{
|
{
|
||||||
browser.tabs.query({active:true, currentWindow:true},
|
browser.tabs.query({active:true, currentWindow:true}).then( (tabs) =>
|
||||||
function cb(tabs) {
|
{
|
||||||
_query_tabs_is_gpass_enabled(tabs, sendResponse);
|
_query_tabs_is_gpass_enabled(tabs, sendResponse);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
@ -399,8 +449,8 @@ function extension_load()
|
||||||
else if (request.type == "update_icon")
|
else if (request.type == "update_icon")
|
||||||
{
|
{
|
||||||
debug("update_icon");
|
debug("update_icon");
|
||||||
browser.tabs.query({active:true, currentWindow:true},
|
browser.tabs.query({active:true, currentWindow:true}).then( (tabs) =>
|
||||||
function cb(tabs) {
|
{
|
||||||
_query_tabs_update_icon(tabs, request.icon_id);
|
_query_tabs_update_icon(tabs, request.icon_id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -411,48 +461,19 @@ function extension_load()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Chrome */
|
||||||
if (!browser.menus && browser.contextMenus)
|
if (!browser.menus && browser.contextMenus)
|
||||||
|
{
|
||||||
browser.menus = browser.contextMenus;
|
browser.menus = browser.contextMenus;
|
||||||
|
}
|
||||||
|
|
||||||
/* Settings */
|
browser.runtime.onInstalled.addListener(() => {
|
||||||
browser.menus.create({
|
createMenus(browser)
|
||||||
id: 'settings',
|
|
||||||
title: 'gPass Settings',
|
|
||||||
contexts: ['browser_action']
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Not supported by Chrome */
|
|
||||||
if (browser.menus.onShown)
|
|
||||||
title = 'Disable gPass for this website';
|
|
||||||
else
|
|
||||||
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(
|
browser.menus.onClicked.addListener(
|
||||||
function(info, tab) {
|
function(info, tab) {
|
||||||
switch (info.menuItemId) {
|
switch (info.menuItemId) {
|
||||||
case 'settings':
|
|
||||||
browser.runtime.openOptionsPage();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'always_disable':
|
case 'always_disable':
|
||||||
get_preference('always_disabled').then(
|
get_preference('always_disabled').then(
|
||||||
|
@ -464,9 +485,9 @@ function extension_load()
|
||||||
set_preference('always_disabled', always_disabled,
|
set_preference('always_disabled', always_disabled,
|
||||||
function(error)
|
function(error)
|
||||||
{
|
{
|
||||||
browser.tabs.query({},
|
browser.tabs.query({active:true, currentWindow:true},
|
||||||
function cb(tabs) {
|
(tabs) => {
|
||||||
for (i=0; i<tabs.length; i++)
|
for (var i=0; i<tabs.length; i++)
|
||||||
update_enable(!always_disabled, tabs[i], false);
|
update_enable(!always_disabled, tabs[i], false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -481,6 +502,7 @@ function extension_load()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Firefox only */
|
||||||
if (browser.menus.onShown)
|
if (browser.menus.onShown)
|
||||||
{
|
{
|
||||||
browser.menus.onShown.addListener(
|
browser.menus.onShown.addListener(
|
||||||
|
@ -540,5 +562,4 @@ async function self_test()
|
||||||
}
|
}
|
||||||
|
|
||||||
//self_test();
|
//self_test();
|
||||||
|
|
||||||
extension_load();
|
extension_load();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2013-2020 Grégory Soutadé
|
Copyright (C) 2013-2022 Grégory Soutadé
|
||||||
|
|
||||||
This file is part of gPass.
|
This file is part of gPass.
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ var default_preferences = {"pbkdf2_level": 1000,
|
||||||
"popup_clipboard":false
|
"popup_clipboard":false
|
||||||
};
|
};
|
||||||
|
|
||||||
function get_preference(key)
|
export function get_preference(key)
|
||||||
{
|
{
|
||||||
// Inspired from https://github.com/akiomik/chrome-storage-promise/
|
// Inspired from https://github.com/akiomik/chrome-storage-promise/
|
||||||
var promise = new Promise((resolve, reject) => {
|
var promise = new Promise((resolve, reject) => {
|
||||||
|
@ -50,9 +50,9 @@ function get_preference(key)
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_preference(key, value, sendResponse)
|
export function set_preference(key, value, sendResponse)
|
||||||
{
|
{
|
||||||
pref = {[key]:value};
|
var pref = {[key]:value};
|
||||||
chrome.storage.local.set(pref, function (result) {
|
chrome.storage.local.set(pref, function (result) {
|
||||||
if (chrome.runtime.lastError)
|
if (chrome.runtime.lastError)
|
||||||
alert(chrome.runtime.lastError);
|
alert(chrome.runtime.lastError);
|
||||||
|
@ -61,12 +61,13 @@ function set_preference(key, value, sendResponse)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete_preference(key)
|
export function delete_preference(key)
|
||||||
{
|
{
|
||||||
chrome.storage.local.remove(key);
|
chrome.storage.local.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function send_tab_message(tab_id, parameters, callback)
|
export function send_tab_message(tab_id, parameters, callback)
|
||||||
{
|
{
|
||||||
chrome.tabs.sendMessage(tab_id, parameters, {}, callback);
|
chrome.tabs.sendMessage(tab_id, parameters, {}, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2013-2020 Grégory Soutadé
|
Copyright (C) 2013-2022 Grégory Soutadé
|
||||||
|
|
||||||
This file is part of gPass.
|
This file is part of gPass.
|
||||||
|
|
||||||
|
@ -17,30 +17,27 @@
|
||||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* from misc.js */
|
||||||
|
/* Can't directly add it, because it's now a module */
|
||||||
|
var DEBUG = false;
|
||||||
|
var browser = browser || chrome;
|
||||||
|
const SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2};
|
||||||
|
const GPASS_ICON = {NORMAL:0, DISABLED:1, ACTIVATED:2};
|
||||||
|
|
||||||
|
function debug(s)
|
||||||
|
{
|
||||||
|
if (DEBUG)
|
||||||
|
console.log(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function notify(text, data)
|
||||||
|
{
|
||||||
|
browser.runtime.sendMessage({type: "notification", options:{"message":text, "data":data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var gpass_enabled = true;
|
var gpass_enabled = true;
|
||||||
|
|
||||||
function _notification(message, data)
|
|
||||||
{
|
|
||||||
if (message !== data)
|
|
||||||
message += data;
|
|
||||||
|
|
||||||
options = {
|
|
||||||
type: "basic",
|
|
||||||
title : "gPass",
|
|
||||||
message : message,
|
|
||||||
iconUrl:browser.extension.getURL("icons/gpass_icon_64.png")
|
|
||||||
};
|
|
||||||
|
|
||||||
browser.notifications.create(options).then(
|
|
||||||
function created(notification_id)
|
|
||||||
{
|
|
||||||
window.setTimeout(function() {
|
|
||||||
browser.notifications.clear(notification_id);
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _add_name(logins, name)
|
function _add_name(logins, name)
|
||||||
{
|
{
|
||||||
for(var i=0; i<logins.length; i++)
|
for(var i=0; i<logins.length; i++)
|
||||||
|
@ -77,7 +74,7 @@ function try_get_name(fields, type_filters, match)
|
||||||
{
|
{
|
||||||
if (field.hasAttribute("name") && field.value != "")
|
if (field.hasAttribute("name") && field.value != "")
|
||||||
{
|
{
|
||||||
name = field.getAttribute("name");
|
var name = field.getAttribute("name");
|
||||||
// Subset of common user field
|
// Subset of common user field
|
||||||
if (name == "user") user = field.value;
|
if (name == "user") user = field.value;
|
||||||
else if (name == "usr") user = field.value;
|
else if (name == "usr") user = field.value;
|
||||||
|
@ -130,7 +127,7 @@ function on_focus(e)
|
||||||
|
|
||||||
if (logins.length || all_logins.length)
|
if (logins.length || all_logins.length)
|
||||||
{
|
{
|
||||||
parameters = {
|
var parameters = {
|
||||||
type:"update_icon",
|
type:"update_icon",
|
||||||
icon_id:GPASS_ICON.ACTIVATED,
|
icon_id:GPASS_ICON.ACTIVATED,
|
||||||
};
|
};
|
||||||
|
@ -143,7 +140,7 @@ function on_blur(e)
|
||||||
if (!gpass_enabled)
|
if (!gpass_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
parameters = {
|
var parameters = {
|
||||||
type:"update_icon",
|
type:"update_icon",
|
||||||
icon_id:GPASS_ICON.NORMAL,
|
icon_id:GPASS_ICON.NORMAL,
|
||||||
};
|
};
|
||||||
|
@ -159,8 +156,8 @@ function on_sumbit(e)
|
||||||
|
|
||||||
debug("on_submit");
|
debug("on_submit");
|
||||||
|
|
||||||
logins = get_logins(form, true);
|
var logins = get_logins(form, true);
|
||||||
all_logins = get_logins(form, false);
|
var all_logins = get_logins(form, false);
|
||||||
|
|
||||||
if (!logins.length)
|
if (!logins.length)
|
||||||
logins = all_logins;
|
logins = all_logins;
|
||||||
|
@ -174,17 +171,17 @@ function on_sumbit(e)
|
||||||
|
|
||||||
if (field.getAttribute("type") == "password")
|
if (field.getAttribute("type") == "password")
|
||||||
{
|
{
|
||||||
password = field.value;
|
var password = field.value;
|
||||||
if (!password.startsWith("@@") && !password.startsWith("@_"))
|
if (!password.startsWith("@@") && !password.startsWith("@_"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove current value to limit master key stealing
|
// Remove current value to limit master key stealing
|
||||||
field.value = "";
|
field.value = "";
|
||||||
password_computed = true;
|
password_computed = true;
|
||||||
do_submit = !password.startsWith("@_");
|
var do_submit = !password.startsWith("@_");
|
||||||
mkey = password.substring(2);
|
var mkey = password.substring(2);
|
||||||
|
|
||||||
parameters = {
|
var parameters = {
|
||||||
type:"password",
|
type:"password",
|
||||||
logins:logins,
|
logins:logins,
|
||||||
domain:domain,
|
domain:domain,
|
||||||
|
@ -195,16 +192,17 @@ function on_sumbit(e)
|
||||||
browser.runtime.sendMessage(parameters, {},
|
browser.runtime.sendMessage(parameters, {},
|
||||||
function (response) {
|
function (response) {
|
||||||
debug(response);
|
debug(response);
|
||||||
var field = fields[response.options.field_id];
|
|
||||||
switch(response.value)
|
switch(response.value)
|
||||||
{
|
{
|
||||||
case SERVER.OK:
|
case SERVER.OK:
|
||||||
|
var field = fields[response.options.field_id];
|
||||||
set_password(form, field, response.password, do_submit)
|
set_password(form, field, response.password, do_submit)
|
||||||
notify("Password successfully replaced", "");
|
notify("Password successfully replaced", "");
|
||||||
break;
|
break;
|
||||||
case SERVER.FAILED:
|
case SERVER.FAILED:
|
||||||
if (logins.length != all_logins.length)
|
if (logins.length != all_logins.length && all_logins.length != 0)
|
||||||
{
|
{
|
||||||
|
debug("Try with all logins");
|
||||||
parameters[logins] = all_logins;
|
parameters[logins] = all_logins;
|
||||||
browser.runtime.sendMessage(parameters);
|
browser.runtime.sendMessage(parameters);
|
||||||
}
|
}
|
||||||
|
@ -222,10 +220,9 @@ function on_sumbit(e)
|
||||||
{
|
{
|
||||||
debug("No password computed");
|
debug("No password computed");
|
||||||
form.submit();
|
form.submit();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_password(form, field, password, do_submit)
|
function set_password(form, field, password, do_submit)
|
||||||
|
@ -236,7 +233,7 @@ function set_password(form, field, password, do_submit)
|
||||||
if (do_submit)
|
if (do_submit)
|
||||||
{
|
{
|
||||||
// Propagate change
|
// Propagate change
|
||||||
change_cb = field.onchange;
|
var change_cb = field.onchange;
|
||||||
if (change_cb)
|
if (change_cb)
|
||||||
change_cb();
|
change_cb();
|
||||||
// Try to type "enter"
|
// Try to type "enter"
|
||||||
|
@ -272,7 +269,7 @@ function block_all_forms(doc, do_block)
|
||||||
{
|
{
|
||||||
if (do_block)
|
if (do_block)
|
||||||
{
|
{
|
||||||
old_cb = form.onsubmit;
|
var old_cb = form.onsubmit;
|
||||||
if (old_cb)
|
if (old_cb)
|
||||||
form.removeEventListener("submit", old_cb);
|
form.removeEventListener("submit", old_cb);
|
||||||
form.addEventListener("submit", on_sumbit);
|
form.addEventListener("submit", on_sumbit);
|
||||||
|
@ -325,13 +322,13 @@ browser.runtime.onMessage.addListener(
|
||||||
debug("getUsername");
|
debug("getUsername");
|
||||||
if (managed_forms.length == 1)
|
if (managed_forms.length == 1)
|
||||||
{
|
{
|
||||||
fields = managed_forms[0].getElementsByTagName("input");
|
var fields = managed_forms[0].getElementsByTagName("input");
|
||||||
|
|
||||||
type_filters = new Array();
|
var type_filters = new Array();
|
||||||
// Get all <input type="text"> && <input type="email">
|
// Get all <input type="text"> && <input type="email">
|
||||||
type_filters.push("text");
|
type_filters.push("text");
|
||||||
type_filters.push("email");
|
type_filters.push("email");
|
||||||
logins = try_get_name(fields, type_filters, true);
|
var logins = try_get_name(fields, type_filters, true);
|
||||||
|
|
||||||
if (logins.length == 1)
|
if (logins.length == 1)
|
||||||
sendResponse(logins[0]);
|
sendResponse(logins[0]);
|
||||||
|
@ -347,12 +344,12 @@ browser.runtime.onMessage.addListener(
|
||||||
var response = "";
|
var response = "";
|
||||||
if (managed_forms.length == 1)
|
if (managed_forms.length == 1)
|
||||||
{
|
{
|
||||||
fields = managed_forms[0].getElementsByTagName("input");
|
var fields = managed_forms[0].getElementsByTagName("input");
|
||||||
password_field = null;
|
var password_field = null;
|
||||||
|
|
||||||
for (a=0; a<fields.length; a++)
|
for (var a=0; a<fields.length; a++)
|
||||||
{
|
{
|
||||||
field = fields[a];
|
var field = fields[a];
|
||||||
if (field.getAttribute("type") == "password")
|
if (field.getAttribute("type") == "password")
|
||||||
{
|
{
|
||||||
if (password_field == null)
|
if (password_field == null)
|
||||||
|
@ -374,7 +371,6 @@ browser.runtime.onMessage.addListener(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendResponse(response);
|
sendResponse(response);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (request.type == "blockForms")
|
else if (request.type == "blockForms")
|
||||||
{
|
{
|
||||||
|
@ -384,11 +380,13 @@ browser.runtime.onMessage.addListener(
|
||||||
{
|
{
|
||||||
unblock_all_forms();
|
unblock_all_forms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
function document_loaded()
|
function document_loaded()
|
||||||
{
|
{
|
||||||
parameters = {
|
var parameters = {
|
||||||
"type": "is_gpass_enabled",
|
"type": "is_gpass_enabled",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2013-2020 Grégory Soutadé
|
Copyright (C) 2013-2022 Grégory Soutadé
|
||||||
|
|
||||||
This file is part of gPass.
|
This file is part of gPass.
|
||||||
|
|
||||||
|
@ -19,13 +19,12 @@
|
||||||
|
|
||||||
var DEBUG = false;
|
var DEBUG = false;
|
||||||
|
|
||||||
SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2};
|
export const SERVER = {OK : 0, FAILED : 1, RESTART_REQUEST : 2};
|
||||||
GPASS_ICON = {NORMAL:0, DISABLED:1, ACTIVATED:2};
|
export const GPASS_ICON = {NORMAL:0, DISABLED:1, ACTIVATED:2};
|
||||||
|
|
||||||
var browser = browser || chrome;
|
export var browser = browser || chrome;
|
||||||
var crypto = crypto || window.crypto;
|
|
||||||
|
|
||||||
function notify(text, data)
|
export function notify(text, data)
|
||||||
{
|
{
|
||||||
browser.runtime.sendMessage({type: "notification", options:{"message":text, "data":data}});
|
browser.runtime.sendMessage({type: "notification", options:{"message":text, "data":data}});
|
||||||
}
|
}
|
||||||
|
@ -54,9 +53,9 @@ function str2ab(str) {
|
||||||
return bufView;
|
return bufView;
|
||||||
}
|
}
|
||||||
|
|
||||||
function crypto_pbkdf2(mkey, salt, level)
|
export function crypto_pbkdf2(crypto, mkey, salt, level)
|
||||||
{
|
{
|
||||||
AESCBC = {
|
var AESCBC = {
|
||||||
name: "AES-CBC",
|
name: "AES-CBC",
|
||||||
length: 256,
|
length: 256,
|
||||||
}
|
}
|
||||||
|
@ -83,9 +82,9 @@ function crypto_pbkdf2(mkey, salt, level)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function simple_pbkdf2(mkey, salt, level)
|
export function simple_pbkdf2(crypto, mkey, salt, level)
|
||||||
{
|
{
|
||||||
AESCBC = {
|
var AESCBC = {
|
||||||
name: "AES-CBC",
|
name: "AES-CBC",
|
||||||
length: 256,
|
length: 256,
|
||||||
}
|
}
|
||||||
|
@ -122,7 +121,7 @@ function _encrypt(mkey, iv, data)
|
||||||
|
|
||||||
data = str2ab(data);
|
data = str2ab(data);
|
||||||
|
|
||||||
promise = mkey.then(function(mkey){
|
var promise = mkey.then(function(mkey){
|
||||||
return crypto.subtle.encrypt({
|
return crypto.subtle.encrypt({
|
||||||
name: "AES-CBC",
|
name: "AES-CBC",
|
||||||
iv: iv
|
iv: iv
|
||||||
|
@ -142,15 +141,15 @@ async function _decrypt(mkey, iv, data)
|
||||||
while ((data.length % 16))
|
while ((data.length % 16))
|
||||||
data += "\0";
|
data += "\0";
|
||||||
|
|
||||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
var nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
pkcs7_padding = new Uint8Array([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
|
var pkcs7_padding = new Uint8Array([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
|
||||||
pkcs7_padding = await _encrypt(mkey, nulliv, ab2str(pkcs7_padding));
|
pkcs7_padding = await _encrypt(mkey, nulliv, ab2str(pkcs7_padding));
|
||||||
|
|
||||||
data = str2ab(data + pkcs7_padding);
|
data = str2ab(data + pkcs7_padding);
|
||||||
|
|
||||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
promise = mkey.then(function(mkey){
|
var promise = mkey.then(function(mkey){
|
||||||
return crypto.subtle.decrypt({
|
return crypto.subtle.decrypt({
|
||||||
name: "AES-CBC",
|
name: "AES-CBC",
|
||||||
iv: iv
|
iv: iv
|
||||||
|
@ -165,13 +164,14 @@ async function _decrypt(mkey, iv, data)
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function encrypt_ecb(mkey, data)
|
export async function encrypt_ecb(mkey, data)
|
||||||
{
|
{
|
||||||
var result = "";
|
var result = "";
|
||||||
|
var res;
|
||||||
|
|
||||||
debug("Encrypt ECB " + data);
|
debug("Encrypt ECB " + data);
|
||||||
|
|
||||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
var nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
while (data.length > 16)
|
while (data.length > 16)
|
||||||
{
|
{
|
||||||
|
@ -186,13 +186,14 @@ async function encrypt_ecb(mkey, data)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function decrypt_ecb(mkey, data)
|
export async function decrypt_ecb(mkey, data)
|
||||||
{
|
{
|
||||||
var result = "";
|
var result = "";
|
||||||
|
var res;
|
||||||
|
|
||||||
debug("Decrypt ECB " + data);
|
debug("Decrypt ECB " + data);
|
||||||
|
|
||||||
nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
var nulliv = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
while (data.length > 16)
|
while (data.length > 16)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +208,7 @@ async function decrypt_ecb(mkey, data)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function encrypt_cbc(mkey, iv, data)
|
export async function encrypt_cbc(mkey, iv, data)
|
||||||
{
|
{
|
||||||
debug("Encrypt CBC " + data);
|
debug("Encrypt CBC " + data);
|
||||||
|
|
||||||
|
@ -217,7 +218,7 @@ async function encrypt_cbc(mkey, iv, data)
|
||||||
return result.slice(0, result.length-16);
|
return result.slice(0, result.length-16);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function decrypt_cbc(mkey, iv, data)
|
export async function decrypt_cbc(mkey, iv, data)
|
||||||
{
|
{
|
||||||
debug("Decrypt CBC " + data);
|
debug("Decrypt CBC " + data);
|
||||||
|
|
||||||
|
@ -227,22 +228,22 @@ async function decrypt_cbc(mkey, iv, data)
|
||||||
return result.slice(0, result.length-16);
|
return result.slice(0, result.length-16);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function digest(data)
|
export async function digest(crypto, data)
|
||||||
{
|
{
|
||||||
return crypto.subtle.digest("SHA-256", str2ab(data)).then(function (hash) {
|
return crypto.subtle.digest("SHA-256", str2ab(data)).then(function (hash) {
|
||||||
return ab2str(hash);
|
return ab2str(hash);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function wildcard_domain(domain)
|
export function wildcard_domain(domain)
|
||||||
{
|
{
|
||||||
var parts = domain.split(".");
|
var parts = domain.split(".");
|
||||||
|
|
||||||
// Standard root domain (zzz.xxx.com) or more
|
// Standard root domain (zzz.xxx.com) or more
|
||||||
if (parts.length > 2)
|
if (parts.length > 2)
|
||||||
{
|
{
|
||||||
res = "*.";
|
var res = "*.";
|
||||||
for (i=1; i<parts.length; i++)
|
for (var i=1; i<parts.length; i++)
|
||||||
res += parts[i] + ".";
|
res += parts[i] + ".";
|
||||||
return res.substr(0, res.length-1);
|
return res.substr(0, res.length-1);
|
||||||
}
|
}
|
||||||
|
@ -254,14 +255,14 @@ function wildcard_domain(domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/3745666/how-to-convert-from-hex-to-ascii-in-javascript
|
// http://stackoverflow.com/questions/3745666/how-to-convert-from-hex-to-ascii-in-javascript
|
||||||
function hex2a(hex) {
|
export function hex2a(hex) {
|
||||||
var str = '';
|
var str = '';
|
||||||
for (var i = 0; i < hex.length; i += 2)
|
for (var i = 0; i < hex.length; i += 2)
|
||||||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
function a2hex(_str_) {
|
export function a2hex(_str_) {
|
||||||
var hex = '';
|
var hex = '';
|
||||||
for (var i = 0; i < _str_.length; i++)
|
for (var i = 0; i < _str_.length; i++)
|
||||||
{
|
{
|
||||||
|
@ -272,8 +273,9 @@ function a2hex(_str_) {
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug(s)
|
export function debug(s)
|
||||||
{
|
{
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
console.log(s);
|
console.log(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
// (c) Steven Levithan <stevenlevithan.com>
|
// (c) Steven Levithan <stevenlevithan.com>
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
parseURI = {
|
export function parseUri (str) {
|
||||||
|
|
||||||
parseUri : function (str) {
|
|
||||||
var o = {
|
var o = {
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
|
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
|
||||||
|
@ -29,4 +27,4 @@ parseURI = {
|
||||||
|
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 3,
|
||||||
|
|
||||||
"name": "gPass",
|
"name": "gPass",
|
||||||
"short_name": "gPass",
|
"short_name": "gPass",
|
||||||
"version": "1.1",
|
"version": "1.2",
|
||||||
"description": "gPass : global password manager",
|
"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"},
|
"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é",
|
"author" : "Grégory Soutadé",
|
||||||
|
@ -12,30 +12,32 @@
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["<all_urls>"],
|
"matches": ["<all_urls>"],
|
||||||
"js": ["lib/misc.js", "lib/main.js"],
|
"js": ["lib/main.js"],
|
||||||
"run_at" : "document_idle",
|
"run_at" : "document_idle",
|
||||||
"all_frames" : true
|
"all_frames" : true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"background": {
|
"background": {
|
||||||
"persistent": true,
|
"service_worker": "background.js",
|
||||||
"scripts": ["lib/parseuri.js", "lib/misc.js", "compat.js", "background.js"]
|
"type": "module"
|
||||||
},
|
},
|
||||||
|
|
||||||
"options_page": "options.html",
|
"options_page": "options.html",
|
||||||
|
|
||||||
"browser_action": {
|
"action": {
|
||||||
"default_icon": {"32":"icons/gpass_icon_32.png"},
|
"default_icon": {"32":"icons/gpass_icon_32.png"},
|
||||||
"default_title": "Get your password",
|
"default_title": "Get your password",
|
||||||
"default_popup": "popup/popup.html"
|
"default_popup": "popup/popup.html"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"host_permissions": [
|
||||||
|
"<all_urls>"
|
||||||
|
],
|
||||||
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"<all_urls>",
|
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"notifications",
|
"notifications",
|
||||||
"tabs",
|
|
||||||
"storage",
|
"storage",
|
||||||
"clipboardWrite",
|
"clipboardWrite",
|
||||||
"contextMenus"
|
"contextMenus"
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
Copy password into clipboard <input id="clipboard" type="checkbox"/><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>
|
<input id="getButton" type="submit" value="Get"/> <a id="serverLink" href="">Your server</a>
|
||||||
</form>
|
</form>
|
||||||
<script src="misc.js"></script>
|
<script type="module" src="popup.js"></script>
|
||||||
<script src="compat.js"></script>
|
|
||||||
<script src="popup.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2020 Grégory Soutadé
|
Copyright (C) 2020-2022 Grégory Soutadé
|
||||||
|
|
||||||
This file is part of gPass.
|
This file is part of gPass.
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
||||||
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
along with gPass. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {SERVER, browser, notify, debug} from "./misc.js";
|
||||||
|
import {get_preference, send_tab_message} from "./compat.js";
|
||||||
|
|
||||||
var username_filled = false;
|
var username_filled = false;
|
||||||
|
|
||||||
function _server_response(response, tabs, do_submit, force_copy)
|
function _server_response(response, tabs, do_submit, force_copy)
|
||||||
|
@ -29,17 +32,17 @@ function _server_response(response, tabs, do_submit, force_copy)
|
||||||
{
|
{
|
||||||
navigator.clipboard.writeText(response.password).then(function() {
|
navigator.clipboard.writeText(response.password).then(function() {
|
||||||
notify("Password pasted into clipboard", "");
|
notify("Password pasted into clipboard", "");
|
||||||
window.close();
|
window.setTimeout(function() {window.close();}, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill + optional copy */
|
/* Fill + optional copy */
|
||||||
parameters = {
|
var parameters = {
|
||||||
"type":"setPassword",
|
"type":"setPassword",
|
||||||
"password":response.password,
|
"password":response.password,
|
||||||
"submit":do_submit
|
"submit":do_submit,
|
||||||
};
|
};
|
||||||
send_tab_message(tabs[0].id, parameters,
|
send_tab_message(tabs[0].id, parameters,
|
||||||
function(arg)
|
function(arg)
|
||||||
|
@ -49,13 +52,13 @@ function _server_response(response, tabs, do_submit, force_copy)
|
||||||
{
|
{
|
||||||
navigator.clipboard.writeText(response.password).then(function() {
|
navigator.clipboard.writeText(response.password).then(function() {
|
||||||
notify("Password pasted into clipboard", "");
|
notify("Password pasted into clipboard", "");
|
||||||
window.close();
|
window.setTimeout(function() {window.close();}, 2000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
notify("Password filled", "");
|
notify("Password filled", "");
|
||||||
window.close();
|
window.setTimeout(function() {window.close();}, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -91,7 +94,7 @@ function _query_tabs_get_password(tabs)
|
||||||
var logins = new Array();
|
var logins = new Array();
|
||||||
logins.push(username);
|
logins.push(username);
|
||||||
|
|
||||||
parameters = {
|
var parameters = {
|
||||||
type:"password",
|
type:"password",
|
||||||
logins:logins,
|
logins:logins,
|
||||||
domain:domain,
|
domain:domain,
|
||||||
|
@ -115,12 +118,12 @@ function get_password(evt)
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
browser.tabs.query({active:true, currentWindow:true}, _query_tabs_get_password);
|
browser.tabs.query({active:true, currentWindow:true}).then(_query_tabs_get_password);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pform = document.getElementById("passwordForm");
|
var pform = document.getElementById("passwordForm");
|
||||||
|
|
||||||
if (pform != null)
|
if (pform != null)
|
||||||
pform.onsubmit = get_password;
|
pform.onsubmit = get_password;
|
||||||
|
@ -132,7 +135,7 @@ function _query_tabs_init(tabs)
|
||||||
if (tabs.length != 1) return;
|
if (tabs.length != 1) return;
|
||||||
|
|
||||||
/* Fill username */
|
/* Fill username */
|
||||||
parameters = {
|
var parameters = {
|
||||||
"type":"getUsername"
|
"type":"getUsername"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,12 +171,14 @@ function _query_tabs_init(tabs)
|
||||||
browser.runtime.sendMessage(parameters, {},
|
browser.runtime.sendMessage(parameters, {},
|
||||||
function (response)
|
function (response)
|
||||||
{
|
{
|
||||||
url = response.value;
|
if (tabs[0].url === undefined) return true;
|
||||||
|
if (tabs[0].url.startsWith("chrome://newtab/")) tabs[0].url = "";
|
||||||
|
var url = response.value;
|
||||||
url = url.substring(0, url.lastIndexOf('/'));
|
url = url.substring(0, url.lastIndexOf('/'));
|
||||||
url += '?';
|
url += '?';
|
||||||
url += 'url=' + encodeURI(tabs[0].url.split("?")[0]);
|
url += 'url=' + encodeURI(tabs[0].url.split("?")[0]);
|
||||||
url += '&user=' + document.getElementById("gPassUsername").value;
|
url += '&user=' + document.getElementById("gPassUsername").value;
|
||||||
link = document.getElementById("serverLink");
|
var link = document.getElementById("serverLink");
|
||||||
link.href = url;
|
link.href = url;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -182,4 +187,4 @@ function _query_tabs_init(tabs)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.tabs.query({active:true, currentWindow:true}, _query_tabs_init);
|
browser.tabs.query({active:true, currentWindow:true}).then(_query_tabs_init);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user