Skip to content
Snippets Groups Projects
Commit cf9c4c30 authored by David Byers's avatar David Byers
Browse files

Added support for copying the original URL. New icon. Code cleanup.

parent 3dde3ac7
No related branches found
No related tags found
No related merge requests found
Pipeline #31644 passed
extension/assets/shield.png

692 B

browser.messageDisplayScripts.register({
css: [{
file: "/style.css",
}],
js: [{
file: "/content.js",
}],
});
browser.messageDisplayScripts.register({
css: [
{file: "/style.css"}
],
js: [
{file: "/common.js"},
{file: "/content.js"}
],
});
browser.menus.create({
id: "liu-safelinks-copy",
title: "Copy original link",
contexts: ["link"],
visible: true,
targetUrlPatterns: ["*://*.safelinks.protection.outlook.com/*"],
});
browser.menus.onClicked.addListener((info, tab) => {
if (info.menuItemId == "liu-safelinks-copy") {
navigator.clipboard.writeText(untangleLink(info.linkUrl));
}
});
const safelinksRegexp = new RegExp(
'https?://[^.]+[.]safelinks[.]protection[.]outlook[.]com/[?]url=([^&]+)&.*',
'gi'
);
function untangleLink(link) {
return link.replaceAll(
safelinksRegexp, (match, url) => {
try {
return decodeURIComponent(url);
}
catch (e) {
console.log(e);
return url;
}
});
}
function isTangledLink(link) {
return link.match(safelinksRegexp);
}
// Modify the displayed message to clarify where safelinks are
// inserted and to show the actual link targets.
const safelinksRegexp = new RegExp(
'https?://[^.]+[.]safelinks[.]protection[.]outlook[.]com/[?]url=([^&]+)&.*',
'gi'
);
function getTextNodes(elem) {
var result = [];
if (elem) {
for (var nodes = elem.childNodes, i = nodes.length; i--;) {
let node = nodes[i];
let nodeType = node.nodeType;
if (nodeType == Node.TEXT_NODE) {
result.push(node);
}
else if (nodeType == Node.ELEMENT_NODE
|| nodeType == Node.DOCUMENT_NODE
|| nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
result = result.concat(getTextNodes(node));
}
}
}
return result;
}
for (const link of document.links) {
let display = link.innerHTML;
// Mangle the link text
for (const node of getTextNodes(link)) {
node.textContent = node.textContent.replaceAll(
safelinksRegexp, (match, url) => {
try {
return decodeURIComponent(url);
}
catch (e) {
return url;
}
});
}
// Generate the tooltip and set link class
for (const match of link.href.matchAll(safelinksRegexp)) {
link.classList.add('liu_safelinks_link');
let tooltiptext = match[1];
let tooltip = document.createElement('span');
tooltip.classList.add('liu_safelinks_tooltip');
try {
tooltiptext = decodeURIComponent(tooltiptext);
}
catch (e) {
}
tooltip.textContent = tooltiptext;
link.appendChild(tooltip);
break;
}
}
// Modify the displayed message to clarify where safelinks are
// inserted and to show the actual link targets.
function getTextNodes(elem) {
var result = [];
if (elem) {
for (var nodes = elem.childNodes, i = nodes.length; i--;) {
let node = nodes[i];
let nodeType = node.nodeType;
if (nodeType == Node.TEXT_NODE) {
result.push(node);
}
else if (nodeType == Node.ELEMENT_NODE
|| nodeType == Node.DOCUMENT_NODE
|| nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
result = result.concat(getTextNodes(node));
}
}
}
return result;
}
for (const link of document.links) {
// Mangle the link text
for (const node of getTextNodes(link)) {
node.textContent = untangleLink(node.textContent);
}
// Generate the tooltip and set link class
if (isTangledLink(link.href)) {
let tooltiptext = untangleLink(link.href);
let tooltip = document.createElement('span');
tooltip.classList.add('liu_safelinks_tooltip');
tooltip.textContent = tooltiptext;
link.classList.add('liu_safelinks_link');
link.prepend(tooltip);
}
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><linearGradient id="0" gradientUnits="userSpaceOnUse" y1="227.63" x2="0" y2="171.63"><stop stop-color="#2fae61"/><stop offset="1" stop-color="#4bdf88"/></linearGradient></defs><g transform="matrix(.92857 0 0 .92857-676.99-152.79)"><path d="m789.32 182.93c-.017-1.302-1.019-2.377-2.315-2.496-10.772-1.01-19.563-6.764-22.461-8.87-.606-.442-1.426-.442-2.032 0-2.893 2.106-11.683 7.863-22.456 8.87-1.296.119-2.293 1.194-2.315 2.496-.13 8.497 1.234 37.34 25.14 43.762.425.113.872.113 1.296 0 23.905-6.413 25.27-35.27 25.14-43.762" fill="url(#0)"/><path d="m773.85 193.97l-1.89-1.89c-.259-.259-.574-.389-.945-.389-.371 0-.686.13-.945.389l-9.116 9.13-4.085-4.099c-.259-.259-.574-.389-.945-.389-.371 0-.686.13-.945.389l-1.89 1.89c-.259.259-.389.574-.389.945 0 .37.13.686.389.945l5.03 5.03 1.89 1.89c.259.259.574.389.945.389.37 0 .685-.13.945-.389l1.89-1.89 10.06-10.06c.259-.259.389-.574.389-.945 0-.37-.13-.685-.389-.945" fill="#fff" fill-opacity=".851"/></g></svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.46 283.46" style="enable-background:new 0 0 283.46 283.46;" xml:space="preserve">
<style type="text/css">
.st0{fill:#231F20;}
.st1{fill:none;stroke:#231F20;stroke-width:36;stroke-linecap:round;stroke-miterlimit:10;}
.st2{fill:#ED1C24;}
.st3{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M209.46,74v135.46H74V74H209.46 M283.46,0H0v283.46h283.46V0L283.46,0z"/>
</g>
<path class="st1" d="M15.14,199.56"/>
<path class="st1" d="M15.14,216.86"/>
<g>
<polygon class="st2" points="97.71,88.66 150.06,36.3 99.24,-14.5 297.96,-14.5 297.96,184.2 246.66,132.89 194.3,185.25 "/>
<path class="st3" d="M283.46,0v149.2l-36.81-36.81l-52.36,52.36l-76.09-76.09l52.36-52.36L134.26,0H283.46 M312.46-29h-29H134.26
H64.23l49.52,49.51l15.8,15.79L97.71,68.15L77.2,88.66l20.51,20.51l76.09,76.09l20.51,20.51l20.51-20.51l31.85-31.85l16.3,16.3
l49.51,49.51V149.2V0V-29L312.46-29z"/>
</g>
</svg>
{
"manifest_version": 2,
"name": "Safelinks Cleaner",
"description": "Clean up display of Microsoft Advanced Threat Protection Safe Links",
"version": "1.0",
"author": "David Byers",
"homepage_url": "https://gitlab.liu.se/davby02/safelinkscleaner/",
"icons": {
"48": "icon.svg",
"96": "icon.svg",
"144": "icon.svg",
"192": "icon.svg"
},
"applications": {
"gecko": {
"id": "safelinkscleaner@it.liu.se",
"strict_min_version": "78.4"
}
},
"background": {
"scripts": [
"background.js"
]
},
"permissions": [
"messagesModify"
],
"web_accessible_resources": [
"assets/*.png"
]
}
{
"manifest_version": 2,
"name": "Safelinks Cleaner",
"description": "Clean up display of Microsoft Advanced Threat Protection Safe Links",
"version": "1.0",
"author": "David Byers",
"homepage_url": "https://gitlab.liu.se/davby02/safelinkscleaner/",
"icons": {
"48": "icon.svg",
"96": "icon.svg",
"144": "icon.svg",
"192": "icon.svg"
},
"applications": {
"gecko": {
"id": "safelinkscleaner@it.liu.se",
"strict_min_version": "78.4"
}
},
"background": {
"scripts": [
"common.js",
"background.js"
]
},
"permissions": [
"messagesModify",
"clipboardWrite",
"menus"
],
"web_accessible_resources": [
"assets/*.png"
]
}
a:hover .liu_safelinks_tooltip {
display: block;
}
.liu_safelinks_tooltip {
display: none;
background: #fffff0 url(assets/shield.png) no-repeat 3px;
background-size: 14px 14px;
color: black;
padding: 3px 3px 4px 22px;
position: absolute;
z-index: 1000;
border: 1px solid black;
-webkit-box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
-moz-box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
font: 14px sans-serif;
}
a:hover .liu_safelinks_tooltip {
display: block;
}
.liu_safelinks_tooltip {
display: none;
background: #fffff0 url(assets/shield.png) no-repeat 3px;
background-size: 14px 14px;
color: black;
padding: 3px 3px 4px 22px;
position: absolute;
z-index: 1000;
border: 1px solid black;
-webkit-box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
-moz-box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
box-shadow: 0px 0px 6px 1px rgba(0,0,0,0.5);
font: 14px sans-serif;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment