| |
@@ -2,6 +2,7 @@
|
| |
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
|
| |
* *
|
| |
* Copyright (C) 2017 Nathan Nichols, Loic J. Duros, Nik Nyby
|
| |
+ * Copyright (C) 2018 Giorgio Maone
|
| |
*
|
| |
* This file is part of GNU LibreJS.
|
| |
*
|
| |
@@ -23,8 +24,12 @@
|
| |
// - open the manifest.json
|
| |
// - add a comma after the closing bracket of the key "background"
|
| |
// - Copy and paste this after it:
|
| |
- /*
|
| |
- "content_scripts": [{"matches": ["<all_urls>"],"js": ["contact_finder.js"]}]
|
| |
+ /*
|
| |
+ "content_scripts": [{
|
| |
+ "matches": ["<all_urls>"],
|
| |
+ "js": ["/content/contactFinder.js"],
|
| |
+ "css": ["/content/contactFinder.css"]
|
| |
+ }]
|
| |
*/
|
| |
// Now, the contact finder will load on every page and you can test it where ever you want.
|
| |
|
| |
@@ -34,7 +39,13 @@
|
| |
//Copyright (C) 2011, 2012, 2014 Loic J. Duros
|
| |
//Copyright (C) 2014, 2015 Nik Nyby
|
| |
|
| |
- console.log("contact_finder.js");
|
| |
+ function debug(format, ...args) {
|
| |
+ console.debug(`LibreJS - ${format}`, ...args);
|
| |
+ }
|
| |
+
|
| |
+ var myPort;
|
| |
+
|
| |
+ debug("Injecting contact finder in %s", document.URL);
|
| |
|
| |
// email address regexp
|
| |
var reEmail = /^mailto\:(admin|feedback|webmaster|info|contact|support|comments|team|help)\@[a-z0-9.\-]+\.[a-z]{2,4}$/i;
|
| |
@@ -121,33 +132,14 @@
|
| |
var prefs;
|
| |
|
| |
/**
|
| |
- *
|
| |
- * Creates a transparent floating button from a name string and a callback
|
| |
- *
|
| |
- *
|
| |
- */
|
| |
- function new_debug_button(name_text,callback){
|
| |
- if(document.getElementById("abc123_main_div") !== null){
|
| |
- document.getElementById("abc123_main_div").remove();
|
| |
- }
|
| |
- console.log("adding button");
|
| |
- if(document.getElementById("abc123_main_div") === null){
|
| |
- var to_insert = '<div style="opacity: 0.5; font-size: small; z-index: 2147483647; position: fixed; right: 1%; top: 4%;" id="abc123_main_div"></div>';
|
| |
- document.body.insertAdjacentHTML('afterbegin', to_insert);
|
| |
- }
|
| |
- var button_html = '<input id="abc123_button_complain" value="' + name_text +'" type="button"></input><br>';
|
| |
- document.getElementById("abc123_main_div").insertAdjacentHTML('afterbegin', button_html); document.getElementById("abc123_button_complain").addEventListener("click",callback);
|
| |
-
|
| |
- }
|
| |
- /**
|
| |
* returns input with all elements not of type string removed
|
| |
*/
|
| |
function remove_not_str(a){
|
| |
- var new_a = [];
|
| |
+ var new_a = [];
|
| |
for(var i in a){
|
| |
if(typeof(a[i]) == "string"){
|
| |
new_a.push(a[i])
|
| |
- }
|
| |
+ }
|
| |
}
|
| |
return new_a;
|
| |
}
|
| |
@@ -157,7 +149,7 @@
|
| |
* Will return either the first regex match from the selected certainty level or all regexes that
|
| |
* match on that certainty level.
|
| |
*
|
| |
- * certainty_lvl can be "certain" > "probable" > "uncertain"
|
| |
+ * certainty_lvl can be "certain" > "probable" > "uncertain"
|
| |
*/
|
| |
function attempt(certainty_lvl, first=true){
|
| |
// There needs to be some kind of max so that people can't troll by for example leaving a comment with a bunch of emails
|
| |
@@ -165,8 +157,8 @@
|
| |
var fail_flag = true;
|
| |
var flag;
|
| |
var matches = [];
|
| |
- var result = [];
|
| |
- var str_under_test = "";
|
| |
+ var result = [];
|
| |
+ var str_under_test = "";
|
| |
for(var i in document.links){
|
| |
if( typeof(document.links[i].innerText) != "string" || typeof(document.links[i].href) != "string"){
|
| |
continue;
|
| |
@@ -176,10 +168,10 @@
|
| |
for(var j in contactStr){
|
| |
for(var k in contactStr[j][certainty_lvl]){
|
| |
if(flag){
|
| |
- result = [];
|
| |
+ result = [];
|
| |
result = str_under_test.match(new RegExp(contactStr[j][certainty_lvl][k],"g"));
|
| |
result = remove_not_str(result);
|
| |
- if(result !== undefined && typeof(result[0]) == "string" ){
|
| |
+ if(result !== undefined && typeof(result[0]) == "string" ){
|
| |
if(first){
|
| |
return {"fail":false,"result":document.links[i]};
|
| |
} else{
|
| |
@@ -197,7 +189,7 @@
|
| |
}
|
| |
|
| |
/**
|
| |
- * "LibreJS detects contact pages, email addresses that are likely to be owned by the
|
| |
+ * "LibreJS detects contact pages, email addresses that are likely to be owned by the
|
| |
* maintainer of the site, Twitter and identi.ca links, and phone numbers."
|
| |
*/
|
| |
function find_contacts(){
|
| |
@@ -207,19 +199,19 @@
|
| |
var identi = [];
|
| |
var contact_pages = [];
|
| |
var res = attempt("certain");
|
| |
- var flag = true;
|
| |
+ var flag = true;
|
| |
var type = "";
|
| |
if(res["fail"] == false){
|
| |
type = "certain";
|
| |
res = res["result"];
|
| |
- flag = false;
|
| |
+ flag = false;
|
| |
}
|
| |
if(flag){
|
| |
res = attempt("probable");
|
| |
if(res["fail"] == false){
|
| |
type = "probable";
|
| |
res = res["result"];
|
| |
- flag = false;
|
| |
+ flag = false;
|
| |
}
|
| |
}
|
| |
if(flag){
|
| |
@@ -227,7 +219,7 @@
|
| |
if(res["fail"] == false){
|
| |
type = "uncertain";
|
| |
res = res["result"];
|
| |
- flag = false;
|
| |
+ flag = false;
|
| |
}
|
| |
}
|
| |
if(flag){
|
| |
@@ -235,63 +227,102 @@
|
| |
}
|
| |
return [type,res];
|
| |
}
|
| |
- // need to have this so the handler doesn't take too long
|
| |
- function handler(){
|
| |
- var res = find_contacts();
|
| |
- if(document.getElementById("librejs_contactfinder") != null){
|
| |
- document.getElementById("librejs_contactfinder").remove();
|
| |
- }
|
| |
- var to_insert;
|
| |
- if("fail" in res){
|
| |
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
|
| |
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
|
| |
- ' id="librejs_contactfinder">'+
|
| |
- "Contact finder failed.";
|
| |
- } else{
|
| |
- if(typeof(res[1]) == "string"){
|
| |
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
|
| |
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
|
| |
- ' id="librejs_contactfinder"><b>Result:</b><br>'+
|
| |
- res[0] + ": " + '<a href="' + res[1] + '>'+res[1]+'</a>';
|
| |
- }
|
| |
- if(typeof(res[1]) == "object"){
|
| |
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
|
| |
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
|
| |
- ' id="librejs_contactfinder"><b>Result:</b><br>'+
|
| |
- res[0]+": "+res[1].outerHTML;
|
| |
|
| |
- }
|
| |
- }
|
| |
|
| |
- var email = document.documentElement.innerText.match(email_regex);
|
| |
- if(email != null){
|
| |
- var max_i = 0;
|
| |
- if(email.length >= 10){
|
| |
- max_i = 10;
|
| |
- } else{
|
| |
- max_i = email.length;
|
| |
- }
|
| |
- for(var i = 0; i < max_i; i++){
|
| |
- var mailto = "mailto:"+email[i]+"?subject="+encodeURI(prefs["pref_subject"])+"&body="+encodeURI(prefs["pref_body"]);
|
| |
- to_insert += '<br>' + 'Possible email: <a href="' + mailto + '">'+email[i]+'</a>';
|
| |
- }
|
| |
- }
|
| |
+ function createWidget(id, tag, parent = document.body) {
|
| |
+ let widget = document.getElementById(id);
|
| |
+ if (widget) widget.remove();
|
| |
+ widget = parent.appendChild(document.createElement(tag));
|
| |
+ widget.id = id;
|
| |
+ return widget;
|
| |
+ }
|
| |
|
| |
- to_insert += '</div>';
|
| |
+ /**
|
| |
+ *
|
| |
+ * Creates the contact finder / complain UI as a semi-transparent overlay
|
| |
+ *
|
| |
+ */
|
| |
|
| |
- setTimeout(function(){document.getElementById("librejs_contactfinder").remove()}, 7500);
|
| |
- document.body.insertAdjacentHTML("afterbegin",to_insert);
|
| |
- return 0;
|
| |
+ function main() {
|
| |
+ let overlay = createWidget("_LibreJS_overlay", "div");
|
| |
+ let frame = createWidget("_LibreJS_frame", "iframe");
|
| |
|
| |
- }
|
| |
+ let close = () => {
|
| |
+ frame.remove();
|
| |
+ overlay.remove();
|
| |
+ };
|
| |
|
| |
- function main(){
|
| |
- new_debug_button("Complain to website",handler);
|
| |
- }
|
| |
+ let closeListener = e => {
|
| |
+ let t = e.currentTarget;
|
| |
+ if (t.href) { // link navigation
|
| |
+ if (t.href !== document.URL) {
|
| |
+ if (t.href.includes("#")) {
|
| |
+ window.addEventListener("hashchange", close);
|
| |
+ }
|
| |
+ return;
|
| |
+ }
|
| |
+ }
|
| |
+ close();
|
| |
+ };
|
| |
+ let makeCloser = clickable => clickable.addEventListener("click", closeListener);
|
| |
+
|
| |
+ makeCloser(overlay);
|
| |
+
|
| |
+ let initFrame = () => {
|
| |
+ debug("initFrame");
|
| |
+ let res = find_contacts();
|
| |
+ let contentDoc = frame.contentWindow.document;
|
| |
+ let {body} = contentDoc;
|
| |
+ body.id = "_LibreJS_dialog";
|
| |
+ body.innerHTML = `<h1>LibreJS Complaint</h1><button class='close'>x</button>`;
|
| |
+ contentDoc.documentElement.appendChild(contentDoc.createElement("base")).target = "_top";
|
| |
+ let content = body.appendChild(contentDoc.createElement("div"));
|
| |
+ content.id = "content";
|
| |
+ let addHTML = s => content.insertAdjacentHTML("beforeend", s);
|
| |
+ if ("fail" in res) {
|
| |
+ content.classList.toggle("_LibreJS_fail", true)
|
| |
+ addHTML("<div>Could not guess any contact page for this site.</div>");
|
| |
+ } else {
|
| |
+ addHTML("<h3>Contact info guessed for this site</h3>");
|
| |
+ if(typeof(res[1]) === "string") {
|
| |
+ let a = contentDoc.createElement("a");
|
| |
+ a.href = a.textContent = res[1];
|
| |
+ content.appendChild(a);
|
| |
+ } else if (typeof(res[1]) === "object"){
|
| |
+ addHTML(`${res[0]}: ${res[1].outerHTML}`);
|
| |
+ }
|
| |
+ }
|
| |
|
| |
- var myPort = browser.runtime.connect({name:"contact_finder"});
|
| |
+ let emails = document.documentElement.textContent.match(email_regex);
|
| |
+ if (emails && (emails = Array.filter(emails, e => !!e)).length) {
|
| |
+ addHTML("<h5>Possible email addresses:</h5>");
|
| |
+ let list = contentDoc.createElement("ul");
|
| |
+ for (let i = 0, max = Math.min(emails.length, 10); i < max; i++) {
|
| |
+ let recipient = emails[i];
|
| |
+ let a = contentDoc.createElement("a");
|
| |
+ a.href = `mailto:${recipient}?subject${
|
| |
+ encodeURIComponent(prefs["pref_subject"])
|
| |
+ }&body=${
|
| |
+ encodeURIComponent(prefs["pref_body"])
|
| |
+ }`;
|
| |
+ a.textContent = recipient;
|
| |
+ list.appendChild(contentDoc.createElement("li")).appendChild(a);
|
| |
+ }
|
| |
+ content.appendChild(list);
|
| |
+ }
|
| |
+ Array.forEach(contentDoc.querySelectorAll(".close, a"), makeCloser);
|
| |
+ debug("frame initialized");
|
| |
+ }
|
| |
+
|
| |
+
|
| |
+
|
| |
+ frame.addEventListener("load", e => {
|
| |
+ debug("frame loaded");
|
| |
+ myPort = browser.runtime.connect({name: "contact_finder"}).onMessage.addListener(m => {
|
| |
+ prefs = m;
|
| |
+ initFrame();
|
| |
+ });
|
| |
+ });
|
| |
+ }
|
| |
|
| |
- myPort.onMessage.addListener(function(m) {
|
| |
- prefs = m;
|
| |
- main();
|
| |
- });
|
| |
+ main();
|
| |
Notice: since it could not be developed without compiling against latest Acorn, this PR includes and supersedes PR #19, whose branch has been merged while the work was in progress.
Here we refactored the complaint UI to use a separate CSS, safer and faster HTML building and less clicks to be operated (by removing the intermediate "Complain to website" tab/button and going straight to the floating panel).
Nevertheless we kept around a branch preserving the "Complain to website" side tab/button, just in case there's a rationale to reintroduce it.