├── webextension ├── options.css ├── popup.css ├── manifest.json ├── popup.html ├── options.html ├── README.md ├── lib.js ├── options.js ├── popup.js ├── yourls.svg ├── yourls-tight.svg ├── background.js └── LICENSE ├── legacy ├── skin │ ├── favicon.gif │ ├── favicon-failed.gif │ ├── favicon-success.gif │ └── skin.css ├── locale │ └── en-US │ │ └── translations.dtd ├── chrome.manifest ├── defaults │ └── preferences │ │ └── prefs.js ├── install.rdf ├── chrome │ └── content │ │ ├── browser.xul │ │ ├── options.xul │ │ └── yourlsshortener.js ├── README.md └── LICENSE ├── README.md └── LICENSE /webextension/options.css: -------------------------------------------------------------------------------- 1 | #message { 2 | margin-top: 20px; 3 | } 4 | -------------------------------------------------------------------------------- /legacy/skin/favicon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binfalse/YOURLS-FirefoxExtension/HEAD/legacy/skin/favicon.gif -------------------------------------------------------------------------------- /legacy/skin/favicon-failed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binfalse/YOURLS-FirefoxExtension/HEAD/legacy/skin/favicon-failed.gif -------------------------------------------------------------------------------- /legacy/skin/favicon-success.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binfalse/YOURLS-FirefoxExtension/HEAD/legacy/skin/favicon-success.gif -------------------------------------------------------------------------------- /legacy/locale/en-US/translations.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /legacy/skin/skin.css: -------------------------------------------------------------------------------- 1 | #yourls-shortener-toolbar-button, #yourls-shortener-context { 2 | list-style-image: url("chrome://yourls-shortener/skin/favicon.gif"); 3 | } 4 | #yourls-shortener-status-bar-icon { 5 | margin: 0 2px; 6 | } -------------------------------------------------------------------------------- /webextension/popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 20px; 3 | } 4 | .display_table { 5 | width: 100%; 6 | border: 0px; 7 | } 8 | #keyword, #result_url { 9 | min-width: 200px; 10 | } 11 | #message { 12 | color: red; 13 | margin-top: 10px; 14 | } 15 | #headlineicon { 16 | height: .8em; 17 | } 18 | button { 19 | margin-right: 5px; 20 | margin-top: 10px; 21 | } 22 | -------------------------------------------------------------------------------- /legacy/chrome.manifest: -------------------------------------------------------------------------------- 1 | content yourls-shortener chrome/content/ 2 | content yourls-shortener chrome/content/ contentaccessible=yes 3 | overlay chrome://browser/content/browser.xul chrome://yourls-shortener/content/browser.xul 4 | locale yourls-shortener en-US locale/en-US/ 5 | skin yourls-shortener classic/1.0 skin/ 6 | style chrome://global/content/customizeToolbar.xul chrome://yourls-shortener/skin/skin.css -------------------------------------------------------------------------------- /legacy/defaults/preferences/prefs.js: -------------------------------------------------------------------------------- 1 | pref("extensions.yourls-shortener.api", "http://yoursite/"); 2 | pref("extensions.yourls-shortener.signature", "123456"); 3 | pref("extensions.yourls-shortener.askforkey", false); 4 | pref("extensions.yourls-shortener.maxwait", 4); 5 | pref("extensions.yourls-shortener.showprompt", true); 6 | pref("extensions.yourls-shortener.copyclipboard", true); 7 | pref("extensions.yourls-shortener.changeicons", true); -------------------------------------------------------------------------------- /legacy/install.rdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | yourls-shortener@binfalse.de 5 | YOURLS shortener 6 | 1.6 7 | 2 8 | Martin Scharm 9 | Shorten URLs with your own YOURLS instance 10 | http://binfalse.de/ 11 | chrome://yourls-shortener/content/options.xul 12 | chrome://yourls-shortener/skin/favicon.gif 13 | 14 | 15 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 16 | 3.0 17 | 22.* 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /webextension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "YOURLS WebExtension", 4 | "version": "2.5.2", 5 | "description": "Shorten URLs with your own YOURLS instance", 6 | "homepage_url": "https://binfalse.de/software/browser-extensions/yourls-firefox-webextension/", 7 | "applications": { 8 | "gecko": { 9 | "id": "yourls-shortener@binfalse.de", 10 | "strict_min_version": "57.0" 11 | } 12 | }, 13 | "icons": { 14 | "48": "yourls.svg", 15 | "96": "yourls.svg" 16 | }, 17 | "permissions": [ 18 | "activeTab", 19 | "storage", 20 | "clipboardWrite", 21 | "contextMenus", 22 | "http://*/*", 23 | "https://*/*" 24 | ], 25 | "background": { 26 | "scripts": ["background.js"] 27 | }, 28 | "options_ui": { 29 | "browser_style": true, 30 | "page": "options.html" 31 | }, 32 | "browser_action": { 33 | "browser_style": true, 34 | "default_icon": "yourls.svg", 35 | "default_title": "YOURLS", 36 | "default_popup": "popup.html" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YOURLS shortener for Firefox 2 | 3 | ![YOURLS shortener for Firefox](https://binfalse.de/assets/media/pics/2017/yourls-firefox/yourls.svg) 4 | 5 | This is an extension for the Firefox browser to shorten URLs using YOURLS. 6 | 7 | The original version is available in the [legacy](legacy/) directory. It was initially developed in 2011. However, the techniques back then are no longer supported by Firefox. 8 | 9 | A new version of the extension is available in the [webextension](webextension/) directory. 10 | It was rewritten in 2017. 11 | 12 | Many thanks to @xppppp, @yfdyh000, @joshp23, @wilcochris, @tessus, and @airtonzanon for their contributions! 13 | 14 | Find more information about the extension 15 | 16 | * [in the extensions directory](webextension/) 17 | * [at the extensions web site](https://binfalse.de/software/browser-extensions/yourls-firefox-webextension/) 18 | * [at Mozilla's add-on platform](https://addons.mozilla.org/en-US/firefox/addon/yourls-shortener/) 19 | 20 | ![Shorten URLs using YOURLS and this webextension](https://binfalse.de/assets/media/pics/2017/yourls-firefox/popup.png) 21 | -------------------------------------------------------------------------------- /webextension/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Shorten URL with YOURLS

9 | 10 | 11 | 14 | 16 | 17 | 18 | 21 | 25 | 26 | 27 | 30 | 34 | 35 |
12 | Source URL: 13 | 15 |
19 | Keyword: 20 | 22 | 23 | 24 |
28 | Short URL: 29 | 31 | 32 | 33 |
36 |
37 | 38 |
39 |
40 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /legacy/chrome/content/browser.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /webextension/README.md: -------------------------------------------------------------------------------- 1 | # YOURLS Firefox extension 2 | 3 | This is an extension for Mozilla's Firefox to interact with the open source [URL shortener Yourls](http://yourls.org/). 4 | This page is just a stub and just contains a few screenshots. You will find [more information on the plugin's website](https://binfalse.de/software/browser-extensions/yourls-firefox-webextension/) and at [Mozilla's add-on platform](https://addons.mozilla.org/en-US/firefox/addon/yourls-shortener/). 5 | 6 | ## Key features 7 | 8 | * passwordless authentication 9 | * provide a keyword for the short URL 10 | * selected text on the web page to use it as keyword 11 | * automatically copy the resulting short URL to your clipboard 12 | 13 | 14 | ## Required Permissions 15 | 16 | * *Access data for all web sites:* The extension needs access to the current website to get the URL and potentially selected text (for keyword suggestions), and the extension needs to access any other URL to communicated with private YOURLS instances. 17 | * *Input data to the clipboard:* The extension is able to copy the shortened URL to clipboard (can be configured in the extension's preferences) 18 | 19 | ## UI Integration 20 | 21 | ### A toolbar button to shorten the current web page 22 | 23 | ![toolbar button of the YOURLS shortener](https://binfalse.de/assets/media/pics/2017/yourls-firefox/popup-border.png) 24 | 25 | ### Selected text automatically becomes a keyword 26 | 27 | ![select text for the YOURLS shortener](https://binfalse.de/assets/media/pics/2017/yourls-firefox/selection-border.png) 28 | 29 | ### Shorten link targets 30 | 31 | ![shorten link targets using the YOURLS shortener](https://binfalse.de/assets/media/pics/2017/yourls-firefox/link-border.png) 32 | 33 | 34 | ## Preferences 35 | 36 | ![Preferences of the YOURLS shortener](https://binfalse.de/assets/media/pics/2017/yourls-firefox/preferences-border.png) 37 | 38 | 39 | ## License 40 | 41 | Copyright 2011-2017 Martin Scharm 42 | 43 | This program is free software: you can redistribute it and/or modify 44 | it under the terms of the GNU General Public License as published by 45 | the Free Software Foundation, either version 3 of the License, or 46 | (at your option) any later version. 47 | 48 | This program is distributed in the hope that it will be useful, 49 | but WITHOUT ANY WARRANTY; without even the implied warranty of 50 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51 | GNU General Public License for more details. 52 | 53 | You should have received a copy of the GNU General Public License 54 | along with this program. If not, see . 55 | 56 | 57 | -------------------------------------------------------------------------------- /webextension/lib.js: -------------------------------------------------------------------------------- 1 | // create a proper DOM link 2 | function createLink (url, text) { 3 | if (!text) 4 | text = url; 5 | 6 | var a = document.createElement ('a'); 7 | a.appendChild (document.createTextNode (text)); 8 | a.title = text; 9 | a.href = url; 10 | return a; 11 | } 12 | 13 | // inject supplemental information into a DOM element 14 | // this will create proper links for recognised and allowed link contents 15 | function injectSupplemental (node, supp) { 16 | while (node.firstChild) 17 | node.removeChild(node.firstChild); 18 | 19 | if (!supp.text) 20 | return; 21 | 22 | if (supp.links && supp.links.length > 0) { 23 | var text = [supp.text]; 24 | for (var i = 0; i < supp.links.length; i++) { 25 | for (var j = 0; j < text.length; j++) { 26 | var idx = text[j].indexOf (supp.links[i]); 27 | if (idx >= 0) { 28 | text.splice (j, 1, text[j].substring (0, idx), text[j].substring (idx, idx + supp.links[i].length), text[j].substring (idx + supp.links[i].length)); 29 | j = j + 1; 30 | } 31 | } 32 | } 33 | 34 | var found = false; 35 | for (var j = 0; j < text.length; j++) { 36 | found = false; 37 | for (var i = 0; i < supp.links.length; i++) { 38 | if (text[j].indexOf (supp.links[i]) === 0 && text[j].length == supp.links[i].length){ 39 | if (text[j].indexOf ("extension's settings") === 0) { 40 | var settingslink = createLink ("", text[j]); 41 | settingslink.addEventListener( 42 | 'click', 43 | function(se) { 44 | browser.runtime.openOptionsPage(); 45 | } 46 | ); 47 | node.appendChild (settingslink); 48 | } else { 49 | node.appendChild (createLink (text[j])); 50 | } 51 | found = true; 52 | } 53 | } 54 | if (!found) 55 | node.appendChild (document.createTextNode (text[j])); 56 | } 57 | 58 | } else { 59 | node.appendChild (document.createTextNode (supp.text)); 60 | } 61 | 62 | } 63 | 64 | // returns server url including tailing slash 65 | function sanitiseApiUrl (url) { 66 | 67 | // strip common postfixes from the server url 68 | var endStripper = [ 69 | 'yourls-api.php', 70 | 'admin/tools.php', 71 | 'admin/index.php', 72 | 'admin/plugins.php', 73 | 'admin/', 74 | 'admin', 75 | 'readme.html', 76 | ]; 77 | 78 | for (var i = 0; i < endStripper.length; i++) 79 | if (url.endsWith (endStripper[i])) 80 | url = url.substr (0, url.length - endStripper[i].length); 81 | 82 | if (url.substr(-1) != '/') 83 | url += '/'; 84 | 85 | return url; 86 | } 87 | 88 | 89 | var communicationErrorMsg = { 90 | text: "This seems like a serious bug!? Could you please file a bug report at https://github.com/binfalse/YOURLS-FirefoxExtension/issues/new and explain what you did? This would help improving the add-on.", 91 | links: ["https://github.com/binfalse/YOURLS-FirefoxExtension/issues/new"] 92 | }; 93 | -------------------------------------------------------------------------------- /webextension/options.js: -------------------------------------------------------------------------------- 1 | (function _yourlsOptions () { 2 | 3 | var loadOptions = function(e) { 4 | browser.storage.local.get().then(function _gotOptions(result) { 5 | document.querySelector('#api').value = result.api || ''; 6 | document.querySelector('#signature').value = result.signature || ''; 7 | document.querySelector('#maxwait').value = result.maxwait || '4'; 8 | document.querySelector('#keyword').checked = result.keyword || false; 9 | document.querySelector('#copy').checked = result.copy || false; 10 | }, function _err () { 11 | document.querySelector('#message').textContent = 'Could not load settings.'; 12 | } 13 | ); 14 | }; 15 | var buttonClick = function(e) { 16 | if (e && e.target) { 17 | e.preventDefault(); 18 | 19 | var msg_title = document.querySelector('#message_title'); 20 | var msg_supp = document.querySelector('#message_supp'); 21 | msg_title.textContent = ""; 22 | while (msg_supp.firstChild) 23 | msg_supp.removeChild(msg_supp.firstChild); 24 | 25 | if (document.querySelector('#api').value.length && 26 | document.querySelector('#signature').value.length) { 27 | 28 | var settings = {}; 29 | ['api', 'signature', 'maxwait'].forEach(function(sKey) { 30 | settings[sKey] = document.querySelector('#'+sKey).value.trim (); 31 | }); 32 | settings['keyword'] = document.querySelector('#keyword').checked; 33 | settings['copy'] = document.querySelector('#copy').checked; 34 | 35 | settings['maxwait'] = parseInt(settings['maxwait']); 36 | if (!settings['maxwait'] || settings['maxwait'] < 1) { 37 | settings['maxwait'] = 5; 38 | } 39 | document.querySelector('#maxwait').value = settings['maxwait']; 40 | 41 | settings['api'] = sanitiseApiUrl (settings['api']); 42 | document.querySelector('#api').value = settings['api']; 43 | 44 | document.querySelector('#signature').value = settings['signature']; 45 | 46 | browser.runtime.sendMessage({method: "version", settings: settings}, function (response) 47 | { 48 | if (!response.error) { 49 | msg_title.textContent = "Success!"; 50 | if (settings['api'].indexOf ("https://") != 0) { 51 | msg_supp.textContent = "You're connected to a YOURLS version " + response.url + ". WARNING: As you are not using HTTPS, we are submitting all requests in plain text over the network - including your signature! Please consider to secure your YOURLS instance with proper encryption."; 52 | } else { 53 | msg_supp.textContent = "You're connected to a YOURLS version " + response.url; 54 | } 55 | } else { 56 | msg_title.textContent = response.error; 57 | if (response.supp) { 58 | injectSupplemental (msg_supp, response.supp); 59 | } 60 | } 61 | }, function (error) { 62 | msg_title.textContent = "Communication error within the extension!"; 63 | injectSupplemental (msg_supp, communicationErrorMsg); 64 | }); 65 | 66 | } else { 67 | msg_title.textContent = 'Please provide a proper API URL and your signature.'; 68 | msg_supp.textContent = 'The Server URL is the URL to the YOURLS web interface. The signature can be obtained from the "Tools" page of the YOURLS web interface.'; 69 | } 70 | } 71 | }; 72 | document.addEventListener('DOMContentLoaded', loadOptions); 73 | document.getElementById('button').addEventListener('click', buttonClick); 74 | })(); 75 | 76 | -------------------------------------------------------------------------------- /legacy/chrome/content/options.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |