├── .prettierignore ├── test ├── webserver │ ├── test-files │ │ └── tmp │ │ │ ├── äöü.txt │ │ │ ├── existing-file.txt │ │ │ ├── existing_file.txt │ │ │ ├── existing_file - Kopie.txt │ │ │ ├── path with (braces) │ │ │ └── existing_file.txt │ │ │ ├── path with (braces) & ampersand │ │ │ └── existing_file.txt │ │ │ ├── test.html │ │ │ ├── 新年快乐 新年快樂.txt │ │ │ ├── áéíóú.txt │ │ │ ├── áéíóú │ │ │ └── áéíóú.txt │ │ │ └── content │ │ │ ├── pdf-test.pdf │ │ │ └── addon_icon_64x64.png │ ├── start_test_server.cmd │ ├── issue65 │ │ ├── test-files │ │ │ ├── pdf-test.pdf │ │ │ └── addon_icon_64x64.png │ │ └── index.html │ ├── web-howto-Serving Static Files from Node.js.URL │ ├── start_test_server.sh │ ├── issue_ur1 │ │ └── issue.htm │ ├── README.md │ ├── package.json │ ├── issue2 │ │ └── issue.htm │ ├── issue113 │ │ └── index.html │ ├── issue-iframe │ │ └── index.html │ ├── issue53 │ │ └── index.html │ ├── issue106 │ │ └── index.html │ ├── issue84 │ │ └── index.html │ ├── issue16 │ │ └── index.html │ ├── issue183 │ │ └── index.html │ ├── test-server.nodejs.js │ ├── server.js │ ├── issue22 │ │ └── index.html │ ├── index.htm │ ├── std1 │ │ └── issue.htm │ └── issue1 │ │ └── issue.htm ├── test-string-util.js ├── test-index.js ├── test-link-util.js └── test-launch-local-process.js ├── .idea ├── .name ├── copyright │ └── profiles_settings.xml ├── scopes │ └── scope_settings.xml ├── ant.xml ├── encodings.xml ├── vcs.xml ├── mydict │ └── mywords.xml ├── modules.xml ├── misc.xml ├── compiler.xml └── uiDesigner.xml ├── .settings ├── org.eclipse.wst.jsdt.ui.superType.name ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.wst.jsdt.ui.prefs └── .jsdtscope ├── .babelrc ├── .mailmap ├── doc ├── main.md ├── addon_icon_32x32.png ├── addon_icon_64x64.png ├── screenshots │ ├── addon_in_action.png │ ├── addon_context_menu.png │ ├── Screenshot_active_addonbar.png │ └── Screenshot_inactive_addonbar.png ├── Information on addons.mozilla.org.txt └── AboutThisAddon.htm ├── evalpage ├── folder-2.png ├── folder-go.png ├── folder-green.png ├── folder-grey.png └── testpage.htm ├── .prettierrc.yaml ├── .vscode ├── extensions.json └── settings.json ├── make-sourcecode-archive.sh ├── native-host ├── src │ ├── addon_icon_48.ico │ ├── requirements.txt │ ├── local-link-messaging-host.bat │ ├── webextension_local_filesystem_links.json │ ├── webextension_local_filesystem_links_win.json │ ├── install_host.bat │ ├── uninstall_host.bat │ ├── uninstall_host.sh │ ├── get_binary_type.py │ ├── install_host.sh │ ├── subprocess_fix.py │ └── local-link-messaging-host.py ├── build │ ├── windows │ │ ├── vcredist_x86.exe │ │ ├── readme.md │ │ └── InnoSetupScript.iss │ ├── unix │ │ ├── uninstall_host_compiled.sh │ │ ├── bundle.sh │ │ └── install_host_compiled.sh │ └── build.sh ├── requirements.txt ├── package.json └── package-lock.json ├── src ├── assets │ └── img │ │ ├── active_icon_16.png │ │ ├── active_icon_32.png │ │ ├── active_icon_64.png │ │ ├── addon_icon_48.png │ │ ├── addon_icon_96.png │ │ ├── inactive_icon_16.png │ │ ├── inactive_icon_32.png │ │ └── inactive_icon_64.png ├── static │ ├── img │ │ └── code_signing_warning.png │ └── css │ │ └── style.css ├── main.js ├── background.html ├── extension │ ├── options.js │ ├── background │ │ ├── helpers │ │ │ └── whitelist.js │ │ ├── addonbarIcon.js │ │ ├── notify.js │ │ ├── checkInstallation.js │ │ └── EventHandlers.js │ ├── settings.css │ ├── constants.js │ ├── utils │ │ └── os-util.js │ ├── components │ │ ├── Settings.html │ │ └── Settings.js │ └── _locales │ │ ├── ru │ │ └── messages.json │ │ ├── fr │ │ └── messages.json │ │ ├── en │ │ └── messages.json │ │ └── de │ │ └── messages.json ├── options.html ├── app.html ├── installed.js ├── app.css ├── App.js ├── manifest.chrome.json ├── manifest.firefox.json ├── installed.css └── installed.html ├── .env.example ├── index.html ├── reviews ├── 2015-08-01.txt ├── 2012-06-14.txt ├── 2012-05-15.txt ├── 2011-12-30.txt └── 2012-05-29.txt ├── sign-bundle.sh ├── .eslintrc ├── intellij_module └── intellij_module.iml ├── TODO ├── CONTRIBUTORS ├── .gitignore ├── .project ├── .github └── dependabot.yml ├── README.build-from-source.md ├── privacy.md ├── package.json ├── README.md ├── README.dev.md ├── webpack.config.js └── CHANGELOG /.prettierignore: -------------------------------------------------------------------------------- 1 | src/static/**/*.js -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/äöü.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | firefox_addon_local_filesystem_links -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/existing-file.txt: -------------------------------------------------------------------------------- 1 | Hello there! -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/existing_file.txt: -------------------------------------------------------------------------------- 1 | Hello there! -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/existing_file - Kopie.txt: -------------------------------------------------------------------------------- 1 | Hello there! -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/path with (braces)/existing_file.txt: -------------------------------------------------------------------------------- 1 | Hello there! -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | australiensun 2 | australiensun 3 | -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/path with (braces) & ampersand/existing_file.txt: -------------------------------------------------------------------------------- 1 | Hello there! -------------------------------------------------------------------------------- /doc/main.md: -------------------------------------------------------------------------------- 1 | /* 2 | * License: www.mozilla.org/MPL/ 3 | */ 4 | 5 | see AboutThisAddon.htm -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Test page

4 | 5 | -------------------------------------------------------------------------------- /evalpage/folder-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/evalpage/folder-2.png -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # .prettierrc or .prettierrc.yaml 2 | trailingComma: none 3 | tabWidth: 4 4 | semi: true 5 | singleQuote: true -------------------------------------------------------------------------------- /evalpage/folder-go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/evalpage/folder-go.png -------------------------------------------------------------------------------- /doc/addon_icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/addon_icon_32x32.png -------------------------------------------------------------------------------- /doc/addon_icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/addon_icon_64x64.png -------------------------------------------------------------------------------- /evalpage/folder-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/evalpage/folder-green.png -------------------------------------------------------------------------------- /evalpage/folder-grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/evalpage/folder-grey.png -------------------------------------------------------------------------------- /test/webserver/start_test_server.cmd: -------------------------------------------------------------------------------- 1 | set NODEJS="C:\Program Files\nodejs\node.exe" 2 | %NODEJS% test-server.nodejs.js 3 | pause 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "dbaeumer.vscode-eslint" 5 | ] 6 | } -------------------------------------------------------------------------------- /make-sourcecode-archive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OUT=sourcecode-archive.tar.gz 4 | git archive HEAD -1 -o $OUT 5 | 6 | echo $OUT written. 7 | 8 | -------------------------------------------------------------------------------- /native-host/src/addon_icon_48.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/native-host/src/addon_icon_48.ico -------------------------------------------------------------------------------- /src/assets/img/active_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/active_icon_16.png -------------------------------------------------------------------------------- /src/assets/img/active_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/active_icon_32.png -------------------------------------------------------------------------------- /src/assets/img/active_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/active_icon_64.png -------------------------------------------------------------------------------- /src/assets/img/addon_icon_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/addon_icon_48.png -------------------------------------------------------------------------------- /src/assets/img/addon_icon_96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/addon_icon_96.png -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/新年快乐 新年快樂.txt: -------------------------------------------------------------------------------- 1 | https://www.chinahighlights.com/travelguide/special-report/chinese-new-year/happy-new-year-in-chinese.htm -------------------------------------------------------------------------------- /doc/screenshots/addon_in_action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/screenshots/addon_in_action.png -------------------------------------------------------------------------------- /src/assets/img/inactive_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/inactive_icon_16.png -------------------------------------------------------------------------------- /src/assets/img/inactive_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/inactive_icon_32.png -------------------------------------------------------------------------------- /src/assets/img/inactive_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/assets/img/inactive_icon_64.png -------------------------------------------------------------------------------- /doc/screenshots/addon_context_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/screenshots/addon_context_menu.png -------------------------------------------------------------------------------- /src/static/img/code_signing_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/src/static/img/code_signing_warning.png -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/áéíóú.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/test-files/tmp/áéíóú.txt -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /native-host/build/windows/vcredist_x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/native-host/build/windows/vcredist_x86.exe -------------------------------------------------------------------------------- /doc/screenshots/Screenshot_active_addonbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/screenshots/Screenshot_active_addonbar.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.js'; 3 | import './app.css'; 4 | 5 | new Vue({ 6 | el: '#app', 7 | render: h => h(App) 8 | }); 9 | -------------------------------------------------------------------------------- /test/webserver/issue65/test-files/pdf-test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/issue65/test-files/pdf-test.pdf -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/áéíóú/áéíóú.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/test-files/tmp/áéíóú/áéíóú.txt -------------------------------------------------------------------------------- /doc/screenshots/Screenshot_inactive_addonbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/doc/screenshots/Screenshot_inactive_addonbar.png -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | formatter_profile=_Eclipse [built-in] (plus spaces, minus comments) 3 | formatter_settings_version=11 4 | -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/content/pdf-test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/test-files/tmp/content/pdf-test.pdf -------------------------------------------------------------------------------- /test/webserver/web-howto-Serving Static Files from Node.js.URL: -------------------------------------------------------------------------------- 1 | [InternetShortcut] 2 | URL=http://thecodinghumanist.com/blog/archives/2011/5/6/serving-static-files-from-node-js 3 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Set the default 3 | "editor.formatOnSave": false, 4 | // Enable per-language 5 | "[javascript]": { 6 | "editor.formatOnSave": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/webserver/issue65/test-files/addon_icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/issue65/test-files/addon_icon_64x64.png -------------------------------------------------------------------------------- /test/webserver/test-files/tmp/content/addon_icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinstaub/webextension_local_filesystem_links/HEAD/test/webserver/test-files/tmp/content/addon_icon_64x64.png -------------------------------------------------------------------------------- /.idea/ant.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/mydict/mywords.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mozilla 5 | prefs 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /native-host/requirements.txt: -------------------------------------------------------------------------------- 1 | altgraph==0.15 2 | dis3==0.1.2 3 | future==0.16.0 4 | macholib==1.9 5 | pathlib2==2.3.0 6 | pefile==2017.11.5 7 | PyInstaller==3.3.1 8 | pypiwin32==219 9 | scandir==1.6 10 | six==1.11.0 11 | -------------------------------------------------------------------------------- /test/webserver/start_test_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # prepare test data 4 | mkdir -p ~/tmp/content 5 | cp issue65/test-files/* ~/tmp/content 6 | 7 | # start test server 8 | node test-server.nodejs.js 9 | 10 | -------------------------------------------------------------------------------- /src/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Local Filesystem Links 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/extension/options.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Settings from './components/Settings.js'; 3 | import './settings.css'; 4 | 5 | const optionsApp = new Vue({ 6 | el: '#settings', 7 | render(h) { 8 | return h(Settings); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Keys for signing the extension with npm run bundle && npm run sign 2 | # get your keys from https://addons.mozilla.org/de/developers/addon/api/key/ 3 | # (you need to be added as author to the AMO store) 4 | 5 | AMO_JWT_ISSUER=user:12345 6 | AMO_JWT_SECRET= -------------------------------------------------------------------------------- /native-host/src/requirements.txt: -------------------------------------------------------------------------------- 1 | pyparsing==2.2.0 2 | pathlib2==2.3.0 3 | pip-save==0.2.0 4 | packaging==16.8 5 | pygobject==3.26.1 6 | apparmor==2.11.1 7 | pycurl==7.43.0.1 8 | appdirs==1.4.3 9 | cupshelpers==1.0 10 | LibAppArmor==2.11.1 11 | six==1.9.0 12 | pycups==1.9.73 13 | -------------------------------------------------------------------------------- /native-host/src/local-link-messaging-host.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | :: Use of this source code is governed by a BSD-style license that can be 4 | :: found in the LICENSE file. 5 | 6 | python "%~dp0/local-link-messaging-host.py" %* 7 | -------------------------------------------------------------------------------- /test/webserver/issue_ur1/issue.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | chrome-extension-vue 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /native-host/src/webextension_local_filesystem_links.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webextension_local_filesystem_links", 3 | "description": "Local file links Native Messaging API Host", 4 | "path": "HOST_PATH", 5 | "type": "stdio", 6 | "allowed_extensions": [ 7 | "jid1-JAzC7z53jemo5Q@jetpack" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/extension/background/helpers/whitelist.js: -------------------------------------------------------------------------------- 1 | export const prepareWhitelist = whitelist => 2 | whitelist && 3 | whitelist 4 | .split(' ') // spacing char --> later add , and ; 5 | .map(url => { 6 | // remap * to all urls 7 | return url === '*' ? '' : url; 8 | }); 9 | -------------------------------------------------------------------------------- /src/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Local Filesystem Links Options 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /native-host/src/webextension_local_filesystem_links_win.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webextension_local_filesystem_links", 3 | "description": "Local file links Native Messaging API Host", 4 | "path": "local-link-messaging-host.exe", 5 | "type": "stdio", 6 | "allowed_extensions": [ 7 | "jid1-JAzC7z53jemo5Q@jetpack" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/webserver/README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | ======= 3 | - Provides some webpages for interactive testing. 4 | - Webserver run via nodejs 5 | - When using nodeclipse (http://www.nodeclipse.org) 6 | --> Start server by right click on test-server.nodejs.js, Run As (oder Debug as) --> Node Application 7 | - from command line use `npm start` in root folder 8 | ======= 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/test-string-util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * License: www.mozilla.org/MPL/ 3 | */ 4 | "use strict"; 5 | 6 | const stringUtil = require( "../lib/utils/string-util" ); 7 | 8 | exports.test_strEndsWith = function( test ) { 9 | test.assertEqual( stringUtil.strEndsWith( "W:\\", "\\" ), true ); 10 | let s = "W:\\"; 11 | test.assertEqual( s.substr( 0, s.length - 1 ), "W:" ); 12 | }; -------------------------------------------------------------------------------- /reviews/2015-08-01.txt: -------------------------------------------------------------------------------- 1 | Comments: 2 | Your version was rejected because of the following problems: 3 | 4 | 1) New uploads must have a higher version number than the previously uploaded versions otherwise those files do not propagate across our mirror network correctly, and many users will receive the old version, which they will be unable to install due to checksum mismatches. 5 | 6 | 7 | Please fix them and submit again. Thank you. 8 | -------------------------------------------------------------------------------- /sign-bundle.sh: -------------------------------------------------------------------------------- 1 | #!bin/env bash 2 | unlisted=$1 3 | 4 | if [ -f .env ] 5 | then 6 | export $(cat .env | sed 's/#.*//g' | xargs) 7 | fi 8 | 9 | if [[ -n "$unlisted" ]]; then 10 | web-ext sign --api-key "${AMO_JWT_ISSUER}" --api-secret "${AMO_JWT_SECRET}" --source-dir ./dist --channel=unlisted 11 | else 12 | web-ext sign --api-key "${AMO_JWT_ISSUER}" --api-secret "${AMO_JWT_SECRET}" --source-dir ./dist --channel=listed 13 | fi -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | http://www.w3.org/1999/xhtml 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /native-host/src/install_host.bat: -------------------------------------------------------------------------------- 1 | :: Copyright 2014 The Chromium Authors. All rights reserved. 2 | :: Use of this source code is governed by a BSD-style license that can be 3 | :: found in the LICENSE file. 4 | 5 | :: Change HKCU to HKLM if you want to install globally. 6 | :: %~dp0 is the directory containing this bat script and ends with a backslash. 7 | REG ADD "HKCU\Software\Mozilla\NativeMessagingHosts\webextension_local_filesystem_links" /ve /t REG_SZ /d "%~dp0webextension_local_filesystem_links_win.json" /f 8 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |

{{ appName }}

7 | Change settings... 8 |
9 | Show install info 10 | 11 |
12 | 13 |
-------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "prettier" 4 | ], 5 | "parserOptions": { 6 | "ecmaVersion": 6, 7 | "sourceType": "module" 8 | }, 9 | "extends": [], 10 | "env": { 11 | "browser": true, 12 | "node": true 13 | }, 14 | "rules": { 15 | "no-console": "off", 16 | "no-invalid-this": 0, 17 | "new-cap": [0, {"newIsCap": false}] 18 | }, 19 | "globals": { 20 | "jQuery": true, 21 | "browser": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/Information on addons.mozilla.org.txt: -------------------------------------------------------------------------------- 1 | English (US) 2 | Name: Local Filesystem Links 3 | Add-on URL: local-filesystem-links 4 | Summary: Scans for local file system URIs (file:///) on any page. Click on the added icon to open the local link with the system's file browser (e. g. Windows Explorer). Alternatively select any text like the path "C:\tmp\cow 1.txt" and use the context menu. 5 | Tags: file, link, local 6 | Description: see AboutThisAddon.htm (only some html supported) 7 | Homepage: https://github.com/feinstaub/firefox_addon_local_filesystem_links 8 | -------------------------------------------------------------------------------- /native-host/src/uninstall_host.bat: -------------------------------------------------------------------------------- 1 | :: Copyright 2014 The Chromium Authors. All rights reserved. 2 | :: Use of this source code is governed by a BSD-style license that can be 3 | :: found in the LICENSE file. 4 | 5 | :: Deletes the entry created by install_host.bat 6 | REG DELETE "HKCU\Software\Mozilla\NativeMessagingHosts\webextension_local_filesystem_links" /f 7 | :: REG DELETE "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f 8 | :: REG DELETE "HKLM\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f 9 | -------------------------------------------------------------------------------- /test/webserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-webserver-local-link-addon", 3 | "version": "0.0.1", 4 | "description": "Local server for manually testing firefox local link plugin", 5 | "main": "server.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "node server.js", 10 | "copyTestFiles:win32": "xcopy test-files\\tmp\\*.* c:\\tmp\\ /s /e" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "open": "^9.1.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /intellij_module/intellij_module.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/installed.js: -------------------------------------------------------------------------------- 1 | // toggle info field of installer 2 | let toggleBtns = document.getElementsByClassName('toggle'); 3 | 4 | for (var i = 0; i < toggleBtns.length; i++) { 5 | toggleBtns[i].addEventListener('click', toggle); 6 | } 7 | 8 | function toggle(evt) { 9 | evt.preventDefault(); 10 | 11 | var infoEl = document.getElementById( 12 | evt.target.getAttribute('data-target') 13 | ); 14 | 15 | if (infoEl.style.display === 'none' || !infoEl.style.display) { 16 | infoEl.style.display = 'block'; 17 | } else { 18 | infoEl.style.display = 'none'; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODOs 2 | ===== 3 | - [] [IMPROVE]: Settings changes may require a page reload (not immediately applied e.g. changing icon option) 4 | - [] [IMPROVE]: Check UNC root-level support & add SMB support (if possible) 5 | - [] [IMPROVE]: settings page styling (I'd like to use Firefox styling) 6 | - [] [IMPROVE]: executable check for Windows (msi files are also executables) 7 | - [] [IMPROVE]: Check signing issue of native app - installing possible but message shouldn't appear 8 | - [] [IMPROVE]: Add iOS support - virtual machine required 9 | - [] [IMPROVE]: Add unit tests for Javascript & Python 10 | - [] [FEATURE]: Re-add env. var handling -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | If you contributed to firefox_addon_local_filesystem_links 2 | then you may add yourself to the contributors list. 3 | Feel free to use a pseudonym if you like. 4 | 5 | first 6 | author contribution role / contributions 7 | year 8 | ---------------------------------------------------------------------------- 9 | austrALIENsun 2011 project initiator and current maintainer 10 | sweoggy 2015 initial implementation of dynamic link scanning 11 | AWolf81 2016 code refactoring / cleaning / changed dynamic link scanning to jquery-observe 12 | -------------------------------------------------------------------------------- /test/webserver/issue2/issue.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/extension/settings.css: -------------------------------------------------------------------------------- 1 | .aliensun-settings input[type='text'] { 2 | width: 100%; 3 | padding: 5px; 4 | margin-top: 16px; 5 | } 6 | 7 | .aliensun-settings input[type='number'] { 8 | padding: 5px; 9 | margin-top: 16px; 10 | } 11 | 12 | .aliensun-settings input[type='radio'] { 13 | margin-bottom: 6px; 14 | } 15 | .aliensun-settings p { 16 | margin: 0; 17 | } 18 | .aliensun-settings .title { 19 | font-size: 20px; 20 | font-weight: bold; 21 | padding: 6px; 22 | } 23 | .aliensun-settings .description { 24 | font-size: 14px; 25 | } 26 | .aliensun-settings .container { 27 | margin-left: 2%; 28 | padding-top: 8px; 29 | margin-bottom: 16px; 30 | } 31 | -------------------------------------------------------------------------------- /test/webserver/issue113/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Issue 113 - Multiple windows opened 7 | 8 | 9 |

10 | First load: file links are correctly handled.
11 | After click on normal link the file links opens multiple windows. 12 |

13 | 17 | 18 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | .aliensun-wrapper div { 2 | margin: 0; 3 | padding: 10px 5px; 4 | width: 300px; 5 | } 6 | 7 | .aliensun-wrapper h1, 8 | .aliensun-wrapper h2 { 9 | font-weight: normal; 10 | margin: 0; 11 | } 12 | 13 | .aliensun-wrapper h1 { 14 | font-size: 16px; 15 | } 16 | 17 | .aliensun-wrapper a { 18 | color: #42b983; 19 | } 20 | 21 | .aliensun-wrapper img { 22 | text-align: center; 23 | } 24 | 25 | .aliensun-wrapper .col-narrow { 26 | float: left; 27 | width: 25%; 28 | } 29 | 30 | .aliensun-wrapper .col-wide { 31 | float: left; 32 | width: 75%; 33 | padding-left: 15px; 34 | } 35 | 36 | .aliensun-wrapper hr { 37 | border-color: AliceBlue; 38 | } -------------------------------------------------------------------------------- /reviews/2012-06-14.txt: -------------------------------------------------------------------------------- 1 | Your add-on, Local Filesystem Links 0.96, has been fully reviewed by an editor and is now available for download in our gallery at https://addons.mozilla.org/addon/local-filesystem-links/ 2 | 3 | 4 | Reviewer: 5 | Kris Maglione 6 | 7 | Comments: 8 | This version has been approved for the public. Due to caching and mirroring on our site, it can take a few hours before this change is visible, so please be patient. 9 | 10 | However, I have the following issues which should be addressed before your next update: 11 | 12 | 1) Please remove or comment the no longer used code in exports.showPathInWindowsExplorer which searches for the location of Windows Explorer and prepares for nsIProcess. 13 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/extension/background/addonbarIcon.js: -------------------------------------------------------------------------------- 1 | /** Updates the addonbar icon (active/inactive) 2 | * @param {boolean} status True, extension active for current tab else inactive 3 | * @returns {undefined} 4 | */ 5 | export function updateAddonbarIcon(status) { 6 | const filePrefix = status ? 'active' : 'inactive'; 7 | const i18nKey = 'LABEL_ADDONBAR_HOVER_STATE_' + filePrefix; 8 | const statusText = browser.i18n.getMessage(i18nKey); 9 | 10 | // update title 11 | browser.browserAction.setTitle({ 12 | title: browser.i18n.getMessage('LABEL_ADDONBAR_ICON_HOVER', statusText) 13 | }); 14 | 15 | // update icon 16 | browser.browserAction.setIcon({ 17 | path: { 18 | '16': 'img/' + filePrefix + '_icon_16.png', 19 | '32': 'img/' + filePrefix + '_icon_32.png' 20 | } 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import withRender from './app.html'; 2 | 3 | export default withRender({ 4 | name: 'app', 5 | data() { 6 | return { 7 | appName: browser.runtime.getManifest().name 8 | }; 9 | }, 10 | methods: { 11 | displaySettings() { 12 | browser.runtime.openOptionsPage(); 13 | }, 14 | showInstallInfo() { 15 | // console.log('show tab...', browser.runtime.sendMessage); 16 | browser.runtime 17 | .sendMessage({ action: 'showInstallInfoTab' }) 18 | .then(function(response) { 19 | // console.log('showInstallInfo done', response) 20 | }) 21 | .catch(function(err) { 22 | // console.log('error', err); 23 | }); 24 | } 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /native-host/src/uninstall_host.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2013 The Chromium Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | 6 | set -e 7 | 8 | if [ "$(uname -s)" = "Darwin" ]; then 9 | if [ "$(whoami)" = "root" ]; then 10 | TARGET_DIR="/Library/Application Support/Mozilla/NativeMessagingHosts" 11 | else 12 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts" 13 | fi 14 | else 15 | if [ "$(whoami)" = "root" ]; then 16 | TARGET_DIR="/usr/lib/mozilla/native-messaging-hosts" 17 | else 18 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts" 19 | fi 20 | fi 21 | 22 | HOST_NAME="webextension_local_filesystem_links" 23 | rm "$TARGET_DIR/webextension_local_filesystem_links.json" 24 | echo "Native messaging host $HOST_NAME has been uninstalled." 25 | -------------------------------------------------------------------------------- /src/static/css/style.css: -------------------------------------------------------------------------------- 1 | .aliensun-link-icon, .aliensun-link-icon-arrow { 2 | display: inline-table; 3 | padding-left: 0.1em; 4 | } 5 | 6 | .aliensun-link-icon a, .aliensun-link-icon-arrow a { 7 | display: table-cell; 8 | text-decoration: none; 9 | } 10 | 11 | .aliensun-link-icon i, .aliensun-link-icon-arrow i { 12 | color: orange; /*#F3C300;*/ 13 | font-size: 100%; 14 | text-shadow: 0.1em 0.1em 0.1em rgba(150, 150, 150, 1); 15 | vertical-align: -0.2em; /* correction of y-position of icon */ 16 | cursor: pointer; 17 | } 18 | 19 | .aliensun-link-icon i:after { 20 | content: "folder"; 21 | } 22 | 23 | .aliensun-link-icon i:hover:after{ 24 | content: "folder_open"; 25 | } 26 | 27 | .aliensun-link-icon-arrow i:after { 28 | content: "label"; 29 | } 30 | 31 | .aliensun-link-icon-arrow i:hover:after { 32 | content: "label_outline"; 33 | } -------------------------------------------------------------------------------- /src/extension/background/notify.js: -------------------------------------------------------------------------------- 1 | let notifyCount = 0; 2 | const CAKE_INTERVAL = 0.1; 3 | const cakeNotification = 'webextension-local-filesystem-links-notification'; 4 | 5 | function notify(title, message) { 6 | notifyCount++; 7 | const id = `${cakeNotification}-${notifyCount}`; 8 | 9 | // console.log('notify', id, browser.notifications); 10 | browser.notifications 11 | .create(id, { 12 | type: 'basic', 13 | iconUrl: browser.extension.getURL('img/active_icon_64.png'), 14 | title: title || browser.runtime.getManifest().name, 15 | message: message 16 | }) 17 | .then(() => { 18 | // console.log('cake created', arguments); 19 | setTimeout(() => { 20 | // console.log('cake cleared'); 21 | browser.notifications.clear(id); 22 | }, 2000); 23 | }); 24 | } 25 | 26 | export default notify; 27 | -------------------------------------------------------------------------------- /test/webserver/issue-iframe/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test page - iframe issue 6 | 7 | 8 | back
9 |
10 | 12 |

Outside iframe

13 | c:/ 14 |

Reloading of iframe not working properly - same behaviour as in jsfiddle. Not fixed yet

15 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /native-host/build/unix/uninstall_host_compiled.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2013 The Chromium Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | 6 | set -e 7 | 8 | if [ "$(uname -s)" = "Darwin" ]; then 9 | if [ "$(whoami)" = "root" ]; then 10 | TARGET_DIR="/Library/Application Support/Mozilla/NativeMessagingHosts" 11 | else 12 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts" 13 | fi 14 | else 15 | if [ "$(whoami)" = "root" ]; then 16 | TARGET_DIR="/usr/lib/mozilla/native-messaging-hosts" 17 | else 18 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts" 19 | fi 20 | fi 21 | 22 | HOST_NAME="webextension_local_filesystem_links" 23 | rm "$TARGET_DIR/webextension_local_filesystem_links.json" 24 | rm -rf "$TARGET_DIR/local-link-messaging-host" 25 | 26 | echo "Native messaging host $HOST_NAME has been uninstalled." 27 | -------------------------------------------------------------------------------- /src/manifest.chrome.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Local Filesystem Links", 3 | "options_ui": { 4 | "page": "options.html" 5 | }, 6 | "icons": { 7 | "48": "img/addon_icon_48.png", 8 | "96": "img/addon_icon_96.png" 9 | }, 10 | "default_locale": "en", 11 | "background": { 12 | "page": "background.html" 13 | }, 14 | "browser_action": { 15 | "browser_style": true, 16 | "default_icon": { 17 | "16": "img/inactive_icon_16.png", 18 | "32": "img/inactive_icon_32.png" 19 | }, 20 | "default_popup": "index.html" 21 | }, 22 | "manifest_version": 2, 23 | "web_accessible_resources": ["css/*.css"], 24 | "permissions": [ 25 | "", 26 | "file://*/*", 27 | "storage", 28 | "activeTab", 29 | "contextMenus", 30 | "notifications", 31 | "tabs", 32 | "nativeMessaging", 33 | "webNavigation" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /test/test-index.js: -------------------------------------------------------------------------------- 1 | var main = require( "../index" ), 2 | tabs = require( "sdk/tabs" ); 3 | 4 | let { before, after } = require('sdk/test/utils'); 5 | 6 | // todo add pagemod whitelist testing 7 | 8 | // exports.testWhitelist = function( assert, done ) { 9 | // // var options = require( "../lib/common/preferences" ).options; 10 | // // console.log('simplePrefs', options); 11 | // tabs.open( { 12 | // url: 'http://www.google.de', //'http://localhost:3000', 13 | // }, function(tab) { 14 | // tab.on('ready', function() { 15 | // assert.ok( main.isAttached(), "Attached whitelisted" ); 16 | // done(); 17 | // }); 18 | // }); 19 | // }; 20 | 21 | // before(exports, function (name, assert, done) { 22 | // tabs.open( { 23 | // url: 'http://localhost:3000', 24 | // onActivate: function() { 25 | // done(); 26 | // } 27 | 28 | // }); 29 | // }); 30 | 31 | 32 | require( "sdk/test" ).run( exports ); 33 | -------------------------------------------------------------------------------- /native-host/build/unix/bundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # package everything into a tar archive 4 | # (Python included with PyInstaller 5 | # 6 | # MacOS info: 7 | # $ brew install gnu-tar 8 | # --> needed for tar with-out changing transform 9 | 10 | if [ "$(uname -s)" = "Darwin" ]; then 11 | BIN_DIR='bin/mac' 12 | BUNDLE_NAME='mac' 13 | TAR='gtar' 14 | else 15 | BIN_DIR='bin/linux' 16 | BUNDLE_NAME='linux' 17 | TAR='tar' 18 | fi 19 | 20 | echo $BIN_DIR 21 | (cd src; $TAR -cvf "../$BIN_DIR/native-app-bundle-$BUNDLE_NAME.tar" \ 22 | --transform 's,^src,local_filesystem_links_host_app,' \ 23 | webextension_local_filesystem_links.json) 24 | 25 | (cd build/unix; $TAR -rf "../../$BIN_DIR/native-app-bundle-$BUNDLE_NAME.tar" \ 26 | --transform 's,^src,local_filesystem_links_host_app,' \ 27 | uninstall_host_compiled.sh \ 28 | install_host_compiled.sh) 29 | 30 | (cd $BIN_DIR; $TAR -rf "../../$BIN_DIR/native-app-bundle-$BUNDLE_NAME.tar" local-link-messaging-host/. --transform 's,^src,local_filesystem_links_host_app,') -------------------------------------------------------------------------------- /src/extension/constants.js: -------------------------------------------------------------------------------- 1 | // Constants.js 2 | var pkg = require('../../package.json'), 3 | osFileManagerName = require('./utils/os-util').getFileManagerDisplayName; 4 | 5 | export const APP = { 6 | name: pkg.name, 7 | title: pkg.title, 8 | version: pkg.version 9 | }; 10 | 11 | export const MESSAGES = { 12 | FILEMANAGER: osFileManagerName(), 13 | USERMESSAGES: { 14 | tooltips: { 15 | openFolder: browser.i18n.getMessage('TOOLTIP_OPEN_FOLDER'), //'Open folder', // _('TOOLTIP_OPEN_FOLDER'), 16 | linkText: browser.i18n.getMessage('TOOLTIP_OPEN_LINK') //'Open link' // _('TOOLTIP_OPEN_LINK') 17 | } 18 | } 19 | }; 20 | 21 | export const defaultSettings = { 22 | whitelist: '*', 23 | enableExecutables: false, 24 | revealOpenOption: 'O', // default = open link 25 | enableLinkIcons: true, 26 | retriesOnFailure: 1 // default = one retry, error indication delayed by one retry is OK 27 | }; 28 | 29 | export const DELAY_BETWEEN_RETRIES = 100; // ms delay between retries 30 | -------------------------------------------------------------------------------- /native-host/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-messaging-host", 3 | "version": "0.2.2", 4 | "description": "Native messaging host application for local filesystem links webextension.", 5 | "main": "local-link-messaging.py", 6 | "scripts": { 7 | "clean:win32": "rimraf bin/win32 dist", 8 | "clean:unix": "rimraf bin/linux bin/mac dist", 9 | "build:win32": "npm run clean:win32 && npm run createExe:win32 && npm run compileInstaller:win32", 10 | "build:unix": "npm run clean:unix && npm run createExe:unix && npm run bundleInstaller:unix", 11 | "createExe:win32": "sh build/build.sh", 12 | "createExe:unix": "./build/build.sh", 13 | "compileInstaller:win32": "Compil32 /cc \"build/windows/InnoSetupScript.iss\"", 14 | "bundleInstaller:unix": "./build/unix/bundle.sh" 15 | }, 16 | "author": "A. Wolf ", 17 | "license": "GPL-3.0", 18 | "devDependencies": { 19 | "innosetup-compiler": "^5.5.9", 20 | "rimraf": "^2.6.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/webserver/issue53/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Issue 53 - Style improvement 6 | 20 | 21 | 22 |

Add everything style related here (e.g. icon size)

23 |
    24 |
  • c:\ link smallSome text here
  • 25 |
  • c:\ link mediumsome text....
  • 26 |
  • c:\ link normalSome text here
  • 27 |
  • c:\ link largesome text....
  • 28 |

    29 | 30 | 31 | -------------------------------------------------------------------------------- /src/manifest.firefox.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Local Filesystem Links", 3 | "options_ui": { 4 | "page": "options.html" 5 | }, 6 | "applications": { 7 | "gecko": { 8 | "id": "jid1-JAzC7z53jemo5Q@jetpack" 9 | } 10 | }, 11 | "icons": { 12 | "48": "img/addon_icon_48.png", 13 | "96": "img/addon_icon_96.png" 14 | }, 15 | "default_locale": "en", 16 | "background": { 17 | "page": "background.html" 18 | }, 19 | "browser_action": { 20 | "browser_style": true, 21 | "default_icon": { 22 | "16": "img/inactive_icon_16.png", 23 | "32": "img/inactive_icon_32.png" 24 | }, 25 | "default_popup": "index.html" 26 | }, 27 | "manifest_version": 2, 28 | "web_accessible_resources": ["css/*.css"], 29 | "permissions": [ 30 | "", 31 | "file://*/*", 32 | "storage", 33 | "activeTab", 34 | "contextMenus", 35 | "notifications", 36 | "tabs", 37 | "nativeMessaging", 38 | "webNavigation" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore MacOS specific 2 | .DS_Store 3 | 4 | # ignore python binaries 5 | *.pyc 6 | __pycache__ 7 | version.rc 8 | # native host pyinstaller spec - build file 9 | native-host/local-link-messaging-host.spec 10 | 11 | # ignore web-ext bundle 12 | web-ext-artifacts 13 | 14 | # binary folder 15 | bin 16 | 17 | # dist folder 18 | dist 19 | 20 | # Logs 21 | *.log 22 | *.log.* 23 | 24 | # Runtime data 25 | pids 26 | *.pid 27 | *.seed 28 | 29 | # Directory for instrumented libs generated by jscoverage/JSCover 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | coverage 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (http://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directory 42 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 43 | node_modules 44 | 45 | # moz packages 46 | *.xpi 47 | 48 | # misc 49 | .directory 50 | /.idea/workspace.xml 51 | /jid1-JAzC7z53jemo5Q@jetpack-*.xpi 52 | /.kateproject.d/notes.txt 53 | /_pr/ 54 | /_pt/ 55 | /sourcecode-archive.tar.gz 56 | 57 | .env -------------------------------------------------------------------------------- /test/webserver/issue65/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Issue 65 - Direct open option 6 | 7 | 8 |

    open files directly in FF instead of opening in File explorer.

    9 |

    e.g. open image, PDF in browser with right click open in browser

    10 |

    also there is a new option to open link in FF by default

    11 |

    Windows

    12 | 17 |

    Linux

    18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/webserver/issue106/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /reviews/2012-05-15.txt: -------------------------------------------------------------------------------- 1 | Your add-on, Local Filesystem Links 0.9, has been reviewed by an editor and did not meet the criteria for being hosted in our gallery. 2 | 3 | Reviewer: 4 | Kris Maglione 5 | 6 | Comments: 7 | Your version was rejected because of the following problems: 8 | 9 | 1) We can't match your included version of jQuery and jQuery UI to the checksum of any known version. Please include only releases of libraries obtained from official sources in their original, unmodified files. Please note that third party CDNs are not considered official sources for this purpose. In the case of jQuery UI, it's best to include individual files from the development bundle rather than a single, amalgamated script. 10 | 11 | Please also remove the duplicate copies of jQuery and jquery.datatables that you include. 12 | 13 | This version didn't pass full review because of the following issues: 14 | 15 | 1) Your add-on prints quite a lot of debugging information in the Error Console, which is generally not allowed in production add-ons. 16 | 17 | It would also be a good idea to use nsILocalFile.reveal() or .launch() rather than launching explorer.exe directly. 18 | 19 | Please fix them and submit again. Thank you. -------------------------------------------------------------------------------- /src/extension/utils/os-util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * License: www.mozilla.org/MPL/ 3 | * Created by https://github.com/feinstaub/firefox_addon_local_filesystem_links 4 | */ 5 | 'use strict'; 6 | 7 | // var {Cc, Ci} = chrome; //require('chrome'); 8 | 9 | var getOsStringTag = function() { 10 | // https://developer.mozilla.org/en/nsIXULRuntime 11 | // var xulRuntime = Cc['@mozilla.org/xre/app-info;1']. 12 | // getService(Ci.nsIXULRuntime); 13 | 14 | // see https://developer.mozilla.org/en/OS_TARGET 15 | return browser.runtime.getPlatformInfo(function(info) { 16 | // Display host OS in the console 17 | // console.log(info.os); 18 | return info.os; 19 | }); // xulRuntime.OS; 20 | }; 21 | 22 | var retrieveIsWindowsOs = function() { 23 | var osStringTag = getOsStringTag(); 24 | 25 | return osStringTag === 'win'; 26 | }; 27 | const constIsWindowsOs = retrieveIsWindowsOs(); 28 | 29 | var isWindowsOs = function() { 30 | // console.log('isWindowsOs', constIsWindowsOs); 31 | return constIsWindowsOs; 32 | }; 33 | 34 | exports.isWindowsOs = isWindowsOs; 35 | 36 | exports.getFileManagerDisplayName = function() { 37 | if (isWindowsOs()) { 38 | return 'Windows Explorer'; 39 | } else { 40 | return 'default file manager'; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /test/test-link-util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * License: www.mozilla.org/MPL/ 3 | */ 4 | "use strict"; 5 | 6 | const linkUtil = require( "../lib/utils/link-util" ); 7 | 8 | exports.test_stripQuotes = function( test ) { 9 | test.assertEqual( linkUtil.stripQuotes( "aaa" ), "aaa" ); 10 | test.assertEqual( linkUtil.stripQuotes( "\"aaa\"" ), "aaa" ); 11 | 12 | // Test.assertEqual(localProcess.stripQuotes("\"aaa"), "aaa"); // throws error 13 | }; 14 | 15 | exports.test_fixFileLinkStringForWindowsOs = function( test ) { 16 | test.assertEqual( linkUtil.fixFileLinkStringForWindowsOs( "file://W:/" ), "W:\\" ); 17 | test.assertEqual( linkUtil.fixFileLinkStringForWindowsOs( "file:///W:/" ), "W:\\" ); 18 | test.assertEqual( linkUtil.fixFileLinkStringForWindowsOs( "file:///W:/a/bb/ccc" ), "W:\\a\\bb\\ccc" ); 19 | }; 20 | 21 | exports.test_looksLikeLocalFileLink = function( test ) { 22 | test.assertEqual( linkUtil.looksLikeLocalFileLink( "file:///W:/" ), true ); 23 | test.assertEqual( linkUtil.looksLikeLocalFileLink( "file:///W:/asdfasdf asdfasdf" ), true ); 24 | test.assertEqual( linkUtil.looksLikeLocalFileLink( "http://www.google.com" ), false ); 25 | 26 | // test.assertEqual(linkUtil.looksLikeLocalFileLink("file:///AB:/"), false); // TODO 27 | // test.assertEqual(linkUtil.looksLikeLocalFileLink("file:///abc/def"), false); // TODO 28 | }; -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | firefox_addon_local_filesystem_links 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.wst.jsdt.core.jsNature 16 | 17 | 18 | 19 | 1339019242040 20 | 21 | 6 22 | 23 | org.eclipse.ui.ide.multiFilter 24 | 1.0-name-matches-false-false-*~ 25 | 26 | 27 | 28 | 1339019242041 29 | 30 | 10 31 | 32 | org.eclipse.ui.ide.multiFilter 33 | 1.0-name-matches-false-false-_p1 34 | 35 | 36 | 37 | 1339019242042 38 | 39 | 10 40 | 41 | org.eclipse.ui.ide.multiFilter 42 | 1.0-name-matches-false-false-$p1 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" # Location of package manifests 10 | # Raise pull requests for version updates 11 | # to pip against the `develop` branch 12 | target-branch: "develop" 13 | schedule: 14 | interval: "weekly" 15 | labels: 16 | - "npm dependencies (extension)" 17 | - package-ecosystem: "npm" 18 | directory: "/native-host" # Location of package manifests 19 | # Raise pull requests for version updates 20 | # to pip against the `develop` branch 21 | target-branch: "develop" 22 | schedule: 23 | interval: "weekly" 24 | labels: 25 | - "npm dependencies (native app)" 26 | - package-ecosystem: "pip" 27 | directory: "/native-host" # Location of package manifests 28 | # Raise pull requests for version updates 29 | # to pip against the `develop` branch 30 | target-branch: "develop" 31 | schedule: 32 | interval: "weekly" 33 | labels: 34 | - "pip dependencies (native app)" 35 | -------------------------------------------------------------------------------- /test/webserver/issue84/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Issue 84 - European accents 6 | 7 | 8 |

    In version 0.99.46 - European accents can't be opened!

    9 |

    decodeURIComponent is important for direct link click to make these characters work 10 | - side effect env. var not working with it (work-around needed for env. var)

    11 |

    Windows

    12 | c:/tmp/áéíóú.txt
    13 | c:/tmp/áéíóú/áéíóú.txt
    14 |
    15 |

    Test of unicode support Chinese

    16 | c:/tmp/新年快乐 新年快樂.txt Happy New Year on Chinese
    17 |

    Linux

    18 | /~/tmp/áéíóú.txt
    19 | /~/tmp/áéíóú/áéíóú.txt
    20 |

    Test of unicode support Chinese

    21 | /~/tmp/新年快乐 新年快樂.txt Happy New Year on Chinese
    22 | 23 | 24 | -------------------------------------------------------------------------------- /native-host/src/get_binary_type.py: -------------------------------------------------------------------------------- 1 | import struct 2 | 3 | IMAGE_FILE_MACHINE_I386=332 4 | IMAGE_FILE_MACHINE_IA64=512 5 | IMAGE_FILE_MACHINE_AMD64=34404 6 | # source from https://stackoverflow.com/questions/1345632/determine-if-an-executable-or-library-is-32-or-64-bits-on-windows 7 | 8 | # bat & msi not detected --> stick to previous detection method for Win32 9 | def generateReturn(val, text): 10 | res = {} 11 | res["isBinary"] = val 12 | res["readable"] = text 13 | return res 14 | 15 | def GetBinaryType(fileName): 16 | f=open(fileName, "rb") 17 | 18 | s=f.read(2) 19 | if s!="MZ": 20 | return generateReturn(False, "Not an EXE file") 21 | else: 22 | f.seek(60) 23 | s=f.read(4) 24 | header_offset=struct.unpack(" for now just firefox 8 | 9 | set -e 10 | 11 | DIR="$( cd "$( dirname "$0" )" && pwd )" 12 | if [ "$(uname -s)" = "Darwin" ]; then 13 | if [ "$(whoami)" = "root" ]; then 14 | TARGET_DIR="/Library/Application Support/Mozilla/NativeMessagingHosts" 15 | else 16 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts" 17 | fi 18 | else 19 | if [ "$(whoami)" = "root" ]; then 20 | TARGET_DIR="/usr/lib/mozilla/native-messaging-hosts" 21 | else 22 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts" 23 | fi 24 | fi 25 | 26 | HOST_NAME="webextension_local_filesystem_links" 27 | 28 | # Create directory to store native messaging host. 29 | mkdir -p "$TARGET_DIR" 30 | 31 | # Copy native messaging host manifest. 32 | cp "$DIR/$HOST_NAME.json" "$TARGET_DIR" 33 | 34 | # Update host path in the manifest. 35 | HOST_PATH=$DIR/local-link-messaging-host.py 36 | ESCAPED_HOST_PATH=${HOST_PATH////\\/} 37 | sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_NAME.json" 38 | 39 | # Set permissions for the manifest so that all users can read it. 40 | chmod o+r "$TARGET_DIR/$HOST_NAME.json" 41 | 42 | echo "Native messaging host $HOST_NAME has been installed." 43 | -------------------------------------------------------------------------------- /src/installed.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 3 | margin: 0; 4 | background: #f1f4fb; 5 | } 6 | .content-wrap { 7 | max-width: 950px; 8 | margin: 0 auto; 9 | padding: 15px; 10 | } 11 | header { 12 | background: #817f82; 13 | padding: 30px; 14 | } 15 | 16 | h1 { 17 | margin: 0; 18 | padding: 15px; 19 | } 20 | h2 { 21 | padding-top: 15px; 22 | } 23 | 24 | h4 { 25 | margin-bottom: 5px; 26 | } 27 | 28 | .info-container { 29 | display: none; 30 | margin-left: 15px; 31 | background: rgb(235, 243, 255); 32 | } 33 | 34 | .important { 35 | color: rgb(255, 98, 98); 36 | } 37 | 38 | p { 39 | padding: 15px; 40 | margin-top: 0; 41 | } 42 | 43 | li { 44 | padding: 10px; 45 | } 46 | img { 47 | float: left; 48 | padding-right: 15px; 49 | padding-top: 5px; 50 | padding-bottom: 10px; 51 | } 52 | 53 | .app-name { 54 | font-size: 1.4em; 55 | } 56 | 57 | .download-os-container { 58 | display: flex; 59 | flex-wrap: nowrap; 60 | padding: 5px; 61 | } 62 | 63 | .download-os { 64 | display: flex; 65 | width: 100px; 66 | height: 100px; 67 | 68 | justify-content: center; 69 | flex-direction: column; 70 | text-align: center; 71 | } 72 | .download-os-container>a:link { 73 | text-decoration: none; 74 | color: black; 75 | background: rgb(235, 243, 255); 76 | margin: 5px; 77 | } 78 | 79 | .download-os-container>a:hover { 80 | background: lightgray; 81 | } 82 | 83 | .download-os-container>a:visited { 84 | color: black; 85 | } 86 | 87 | .clearfix { 88 | clear: both; 89 | } 90 | -------------------------------------------------------------------------------- /test/webserver/issue16/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Issue 16 - executable links 6 | 7 | 8 |

    Test cases for executable files. (Prevent denial of service attacks)

    9 |

    10 | Additional test open containing folder should always work. 11 |

    12 |

    Windows

    13 |

    14 | file://c:/windows/sysWOW64/cmd.exe (Windows command prompt)
    15 | wordpad.exe (Windows wordpad editor)
    16 | batch file c:/temp/test.bat (Windows batch file)
    17 | installer file c:/temp/node.msi (Windows installer file)
    18 | com file C:/Windows/SysWOW64/tree.com (Windows tree.com)
    19 |

    20 |
    21 |

    Linux

    22 |

    23 | file:///usr/bin/subl (Linux open to sublime editor)
    24 | file:///usr/bin/gnome-terminal (Linux open terminal)
    25 | file:///usr/bin/konsole (Linux open konsole)
    26 | file:///~/bin/sublime_text_3/sublime_text (Linux) 27 |

    28 | 29 | 30 | -------------------------------------------------------------------------------- /src/extension/background/checkInstallation.js: -------------------------------------------------------------------------------- 1 | import notify from './notify'; 2 | 3 | /** Show installation guid tab 4 | * @returns {undefined} 5 | */ 6 | export function showInstallationTab() { 7 | let query = browser.tabs.query({ 8 | currentWindow: true, 9 | url: 'moz-extension://*/installed.html' 10 | }); 11 | 12 | query.then(tabs => { 13 | if (tabs.length > 0) { 14 | browser.tabs.update(tabs[0].id, { 15 | active: true 16 | }); 17 | } else { 18 | browser.tabs.create({ 19 | active: true, 20 | url: '/installed.html' 21 | }); 22 | } 23 | }); 24 | } 25 | /** Check if this is the first run of the extension & show install guide 26 | * @param {object} details info to the current installation reason 27 | * @returns {undefined} 28 | */ 29 | function checkInstallation(details) { 30 | // notify('in func', 'installed'); 31 | if (details.reason == 'install') { 32 | // console.log('This is a first install!'); 33 | // show installation guide 34 | // notify('test', 'first install'); 35 | showInstallationTab(); 36 | } else if (details.reason == 'update') { 37 | // nothing special todo here at the moment. 38 | let thisVersion = browser.runtime.getManifest().version; 39 | 40 | // notify('version', thisVersion); 41 | // console.log('Updated from ' + details.previousVersion + ' to ' + 42 | // thisVersion + '!'); 43 | } 44 | } 45 | 46 | export default checkInstallation; 47 | -------------------------------------------------------------------------------- /test/webserver/issue183/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Issue 183 - Title overwrite 7 | 8 | 9 |

    10 | New functionality, add title only if there is no title available.
    11 | Previous behavior, always overwrite the title. 12 |

    13 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /reviews/2011-12-30.txt: -------------------------------------------------------------------------------- 1 | REVIEW 2 | ------ 3 | Mozilla Add-ons: Local Filesystem Links 0.64 Preliminary Reviewed 4 | [...] 5 | Reviewer: 6 | Kris Maglione 7 | 8 | Comments: 9 | Your preliminary review request has been approved. Due to caching and mirroring on our site, it can take a few hours before your add-on appears public, so please be patient. 10 | 11 | However, I have the following issues which should be addressed before your next update: 12 | 13 | 1) You alter the markup of documents by textually modifying their innerHTML. This causes the entire document to be re-parsed, which aside from the inefficiency has critical drawbacks, including invalidating any JavaScript reference to replaced DOM nodes, clearing any JavaScript properties and event listeners on replaced DOM nodes, re-executing any script tags in the changed markup, and causing said scripts to fail if they rely on document.write. Please create and alter DOM nodes with DOM methods such as createElement and replaceChild, and the textContent rather than innerHTML property. 14 | 15 | 2) Generating script fragments such as event listeners and content scripts from unsanitized string data is error prone and poses a major risk of security vulnerabilities. For more information, please see https://developer.mozilla.org/en/XUL_School/DOM_Building_and_HTML_Insertion#listeners 16 | 17 | Thank you. 18 | [...] 19 | 20 | --------------------------------------------------------------------- 21 | 22 | ACTIONS 23 | ------- 24 | Commented out some code and made comments. 25 | 26 | 27 | OPEN ISSUES 28 | ----------- 29 | Make sure all mentioned issues in the review were addressed. 30 | -------------------------------------------------------------------------------- /native-host/build/unix/install_host_compiled.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2013 The Chromium Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | 6 | # see https://github.com/passff/passff/blob/master/src/host/install_host_app.sh 7 | # for installer for multiple browsers --> for now just firefox 8 | 9 | set -e 10 | 11 | DIR="$( cd "$( dirname "$0" )" && pwd )" 12 | if [ "$(uname -s)" = "Darwin" ]; then 13 | if [ "$(whoami)" = "root" ]; then 14 | TARGET_DIR="/Library/Application Support/Mozilla/NativeMessagingHosts" 15 | else 16 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts" 17 | fi 18 | else 19 | if [ "$(whoami)" = "root" ]; then 20 | TARGET_DIR="/usr/lib/mozilla/native-messaging-hosts" 21 | else 22 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts" 23 | fi 24 | fi 25 | 26 | HOST_NAME="webextension_local_filesystem_links" 27 | 28 | # Create directory to store native messaging host. 29 | mkdir -p "$TARGET_DIR" 30 | 31 | # Copy native messaging host manifest 32 | cp "$DIR/$HOST_NAME.json" "$TARGET_DIR" 33 | 34 | # Copy lib & executable 35 | cp -r "$DIR/local-link-messaging-host" "$TARGET_DIR" 36 | 37 | # Copy uninstall script 38 | cp "$DIR/uninstall_host_compiled.sh" "$TARGET_DIR" 39 | 40 | # Update host path in the manifest. 41 | HOST_PATH=$TARGET_DIR/local-link-messaging-host/local-link-messaging-host 42 | ESCAPED_HOST_PATH=${HOST_PATH////\\/} 43 | sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_NAME.json" 44 | 45 | # Set permissions for the manifest so that all users can read it. 46 | chmod o+r "$TARGET_DIR/$HOST_NAME.json" 47 | 48 | echo "Native messaging host $HOST_NAME has been installed." 49 | -------------------------------------------------------------------------------- /README.build-from-source.md: -------------------------------------------------------------------------------- 1 | Build from source: webextension_local_filesystem_links 2 | ====================================================== 3 | 4 | 1. Extract source code archive 5 | 6 | 2. Install dependencies: 7 | 8 | $ npm install 9 | ... 10 | added 1208 packages in 25.165s 11 | 12 | 3. Generate the production version of the extension in dist folder. 13 | Creates extension from src folder, converts host script to executable and create installer with InnoSetup 14 | (working under windows) 15 | 16 | $ npm run build 17 | ... 18 | DONE Compiled successfully in 4841ms 19 | 20 | 4. Generate the bundle in web-ext-artifacts folder / create the final package 21 | 22 | $ npm run bundle 23 | ... 24 | Your web extension is ready: /home/gregor/dev/src/firefox_addon/sourcecode-archive/web-ext-artifacts/local_filesystem_links-0.99.60.zip 25 | 26 | 5. Manually upload of the zip file here: https://addons.mozilla.org/en-US/developers/addon/local-filesystem-links/versions 27 | - Upload Version -> Select a file... 28 | - Troubleshooting: 29 | - red message: "Version 0.99.58 was uploaded before and deleted". No hint what to do next. 30 | - solution: upload new version 0.99.59 (npm run build, npm run bundle, upload the file) 31 | - Follow the instructions and provide source code 32 | - $ ./make-sourcecode-archive.sh 33 | 34 | Older stuff 35 | ----------- 36 | * One-time: Install [web-ext](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext) with `npm install web-ext`. 37 | * Find API key hiere: See Tools > Manage API Keys (https://addons.mozilla.org/en-US/developers/addon/api/key/) 38 | 39 | $ ./node_modules/web-ext/bin/web-ext sign --api-key=userkey --api-secret=... -s dist 40 | -------------------------------------------------------------------------------- /test/webserver/test-server.nodejs.js: -------------------------------------------------------------------------------- 1 | // 2 | // code by http://thecodinghumanist.com/blog/archives/2011/5/6/serving-static-files-from-node-js 3 | // 4 | // see also http://stackoverflow.com/questions/4720343/loading-basic-html-in-nodejs 5 | // http://stackoverflow.com/questions/6084360/node-js-as-a-simple-web-server 6 | // 7 | // TODO: use readFileSync? 8 | // 9 | 10 | var http = require('http'); 11 | var fs = require('fs'); 12 | var path = require('path'); 13 | 14 | http.createServer(function (request, response) { 15 | 16 | console.log('request starting...'); 17 | 18 | var filePath = '.' + request.url; 19 | if (filePath == './') 20 | filePath = './index.htm'; 21 | 22 | var extname = path.extname(filePath); 23 | var contentType = 'text/html'; 24 | switch (extname) { 25 | case '.js': 26 | contentType = 'text/javascript'; 27 | break; 28 | case '.css': 29 | contentType = 'text/css'; 30 | break; 31 | } 32 | 33 | fs.exists(filePath, function(exists) { 34 | 35 | if (exists) { 36 | fs.readFile(filePath, function(error, content) { 37 | if (error) { 38 | response.writeHead(500); 39 | response.end(); 40 | } 41 | else { 42 | response.writeHead(200, { 'Content-Type': contentType }); 43 | response.end(content, 'utf-8'); 44 | } 45 | }); 46 | } 47 | else { 48 | response.writeHead(404); 49 | response.end(); 50 | } 51 | }); 52 | 53 | }).listen(8125); 54 | 55 | console.log('Server running at http://127.0.0.1:8125/'); -------------------------------------------------------------------------------- /native-host/build/windows/readme.md: -------------------------------------------------------------------------------- 1 | This folder contains information needed for the windows installer. 2 | 3 | ## Files 4 | - InnoSetupScript.iss: Used by [Inno Setup](http://www.jrsoftware.org/) to create the installer. 5 | - vcredist_x86.exe: Needed for PyInstaller to work (unchecked by default because it needs admin rights to install) 6 | Bundled in the setup.exe (can be enabled during installation) 7 | Question: Is it already installed at most users pcs or not? Or is it automatically bundled into pyinstaller bundle? 8 | - Windows SDK for signTool - download [here](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) 9 | (not everything needed but still around 300 MB, most important part is SDK Signing tools) 10 | 11 | ## Useful resources 12 | - Configure py2exe destination [SO question](https://stackoverflow.com/questions/5811960/is-there-a-way-to-specify-the-build-directory-for-py2exe) 13 | 14 | - Configure Registry addition in InnoSetup [SO question](https://stackoverflow.com/questions/13537841/how-to-write-install-path-to-registry-after-install-is-complete-with-inno-setup) 15 | 16 | # Possible improvements to the installer 17 | - Check if vcredist is installed (if not install it) --> probably not that easy as I'd like to start with-out admin rights 18 | Resource for a VC++ check can be found [here](https://stackoverflow.com/questions/11137424/how-to-make-vcredist-x86-reinstall-only-if-not-yet-installed) 19 | 20 | 21 | ## SignTool (not working yet) 22 | Signing is needed to avoid security warning from Windows Defender. 23 | 24 | [step by step guide to sign inno setup installer](https://revolution.screenstepslive.com/s/revolution/m/10695/l/563371-signing-installers-you-create-with-inno-setup) 25 | 26 | Path to signtool at my installation C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86\signtool.exe 27 | -------------------------------------------------------------------------------- /native-host/build/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Detects which OS and if it is Linux then it will detect which Linux 3 | # Distribution. 4 | 5 | OS=`uname -s` 6 | 7 | # VERSION_INFO probably different for Linux 8 | VERSION_INFO="# UTF-8 9 | # 10 | # For more details about fixed file info 'ffi' see: 11 | # http://msdn.microsoft.com/en-us/library/ms646997.aspx 12 | VSVersionInfo( 13 | ffi=FixedFileInfo(" 14 | 15 | if [[ "$OS" =~ ^MSYS.* ]]; then 16 | BIN_DIR="bin/win32"; 17 | elif [[ "$OS" =~ ^Linux.* ]]; then 18 | BIN_DIR="./bin/linux"; 19 | elif [[ "$OS" =~ ^Darwin.* ]]; then 20 | BIN_DIR="./bin/mac" 21 | else 22 | BIN_DIR="./bin/$OS" 23 | fi 24 | 25 | # rmdir -rf BIN_DIR # already removed by npm 26 | echo $BIN_DIR # debugging output 27 | 28 | # Version key/value should be on his own line 29 | PACKAGE_VERSION=$(cat package.json \ 30 | | grep version \ 31 | | head -1 \ 32 | | awk -F: '{ print $2 }' \ 33 | | sed 's/[",]//g') 34 | 35 | echo $PACKAGE_VERSION # return 0.1.0 - debugging output 36 | 37 | # create version file 38 | # filevers=(2, 0, 4, 0), 39 | # prodvers=(2, 0, 4, 0), 40 | #IN="bla@some.com;john@home.com" # e.g. 3.2.1 --> [0] = 3, [1] = 2, [2] = 1 41 | versionArr=${PACKAGE_VERSION//./ } # 42 | 43 | { 44 | printf "$VERSION_INFO\n" 45 | printf " filevers=(%s, %s, %s, 0),\n" ${versionArr[0]} ${versionArr[1]} ${versionArr[2]} 46 | printf " prodvers=(%s, %s, %s, 0),\n" ${versionArr[0]} ${versionArr[1]} ${versionArr[2]} 47 | echo "))" 48 | } >version.rc 49 | 50 | # create folder (-p if it doesn't exist) 51 | mkdir -p $BIN_DIR 52 | 53 | # onefile not working (not correctly bundled) 54 | # --> onedir better (faster start - no extracting to temp. location of python required) 55 | pyinstaller ./src/local-link-messaging-host.py \ 56 | --onedir \ 57 | --distpath=$BIN_DIR \ 58 | --icon ./src/addon_icon_48.ico \ 59 | --workpath=dist \ 60 | --version-file=version.rc 61 | # --log-level=DEBUG 62 | 63 | # remove temporary directory 64 | rm -rf dist 65 | -------------------------------------------------------------------------------- /doc/AboutThisAddon.htm: -------------------------------------------------------------------------------- 1 | Summary 2 | This Firefox extension scans pages for file:/// links and makes it possible to open them with the system's file browser (e. g. Windows Explorer). 3 | 4 | Target Audience 5 | The extensions was created to assist people using local or enterprise intranet sites (e. g. Wikis) 6 | where pages exist that link to files that are located on the local drive or on network shares. 7 | 8 | Details 9 | Currently there are two methods of opening local file system links. 10 | 11 | 1) Automatic file link recognition 12 | An automatic file link recognition scans for hyperlinks with a file:/// prefix. 13 | For each of these hyperlinks a folder icon will be inserted on the right side of the hyperlink. 14 | If you click the icon the local file link is opened with the system's file browser (e. g. Windows Explorer). 15 | In case of a link to a directory, the file browser opens the directory. 16 | In case of a link to a file, the file will be selected (NOT executed) in the file browser. 17 | 18 | 2) Page context menu entry 19 | The extension adds an entry 'Open with Windows Explorer' to the page context menu that works on selected text. 20 | It works as follows: 21 |
      22 |
    • Select a text portion that contains the path to a local file or folder (e. g. C:\Windows).
    • 23 |
    • Right click on the selection and choose 'Open with Windows Explorer' from the context menu.
    • 24 |
    • See the two cases above.
    • 25 |
    26 | 27 | Supported file links 28 |
      29 |
    • Local disk file links like C:\Windows (file:///C:/Windows)
    • 30 |
    • Network share links (UNC paths) like \\server\folder\file.png (file://///server/folder/file.png)
    • 31 |
    • Blanks in the path
    • 32 |
    33 | 34 | Known Issues 35 | Partial incompatibility with Extension Test 2.7.7 36 | The options page of Local Filesystem Links does not work if the add-on Extension Test 2.7.7 is also installed. Reported 2012-06-16 on Firefox 13. 37 | -------------------------------------------------------------------------------- /test/webserver/server.js: -------------------------------------------------------------------------------- 1 | // 2 | // code by http://thecodinghumanist.com/blog/archives/2011/5/6/serving-static-files-from-node-js 3 | // 4 | // see also http://stackoverflow.com/questions/4720343/loading-basic-html-in-nodejs 5 | // http://stackoverflow.com/questions/6084360/node-js-as-a-simple-web-server 6 | // 7 | // TODO: use readFileSync? 8 | // 9 | 10 | import http from 'http'; 11 | import fs from 'fs'; 12 | import path from 'path'; 13 | import open from 'open'; 14 | 15 | var server = http 16 | .createServer(function(request, response) { 17 | console.log('request starting...'); 18 | 19 | var filePath = '.' + request.url; 20 | if (filePath == './') filePath = './index.htm'; 21 | 22 | var extname = path.extname(filePath); 23 | var contentType = 'text/html'; 24 | switch (extname) { 25 | case '.js': 26 | contentType = 'text/javascript'; 27 | break; 28 | case '.css': 29 | contentType = 'text/css'; 30 | break; 31 | } 32 | 33 | fs.exists(filePath, function(exists) { 34 | if (exists) { 35 | fs.readFile(filePath, function(error, content) { 36 | if (error) { 37 | response.writeHead(500); 38 | response.end(); 39 | } else { 40 | response.writeHead(200, { 41 | 'Content-Type': contentType 42 | }); 43 | response.end(content, 'utf-8'); 44 | } 45 | }); 46 | } else { 47 | response.writeHead(404); 48 | response.end(); 49 | } 50 | }); 51 | }) 52 | .listen(3000, 'localhost', function() { 53 | var adrObj = server.address(), 54 | address = [adrObj.address, adrObj.port]; 55 | 56 | console.log('Server running at ' + address.join(':')); 57 | open('http://' + address.join(':')); 58 | }); 59 | -------------------------------------------------------------------------------- /reviews/2012-05-29.txt: -------------------------------------------------------------------------------- 1 | Your add-on, Local Filesystem Links 0.95, has been reviewed by an editor and did not meet the criteria for full review. However, your add-on has been granted preliminary review and is now available for download in our gallery at https://addons.mozilla.org/addon/local-filesystem-links/ 2 | 3 | 4 | 5 | Reviewer: 6 | Kris Maglione 7 | 8 | Comments: 9 | This version didn't pass full review because of the following issues: 10 | 11 | 1) I get the following errors in the Error Console at startup: 12 | 13 | Error: jQuery is not defined 14 | Source file: resource://jid1-jazc7z53jemo5q-at-jetpack/alien-local-filesystem-links/data/js/jquery-ui-1.8.16.custom.min.js 15 | Line: 18 16 | ---------- 17 | Error: jQuery is not defined 18 | Source file: resource://jid1-jazc7z53jemo5q-at-jetpack/alien-local-filesystem-links/data/jsdt/jquery.dataTables.js 19 | Line: 7440 20 | ---------- 21 | Error: unterminated string literal 22 | Source file: resource://jid1-jazc7z53jemo5q-at-jetpack/alien-local-filesystem-links/data/main-wid/main-panel.htm 23 | Line: 57, Column: 96 24 | Source code: 25 | return ' 26 | 27 | It would incidentally be a good idea to ensure that your HTML files are well formed XHTML and change the extensions to .xhtml 28 | 29 | See also https://developer.mozilla.org/en/XUL_School/DOM_Building_and_HTML_Insertion 30 | 31 | You should also remove or disable the unused code in your showPathInWindowsExplorer function. 32 | 33 | You need to correct them to get full approval. Thanks. 34 | 35 | Your add-on will now appear in search results and categories with some limitations. You may re-request full review by addressing the editor's comments and uploading a new version. To learn more about the review process, please visit https://addons.mozilla.org/developers/docs/policies/reviews#selection 36 | 37 | If you have any questions or comments on this review, please reply to this email or join #amo-editors on irc.mozilla.org 38 | -- 39 | Mozilla Add-ons 40 | https://addons.mozilla.org 41 | -------------------------------------------------------------------------------- /privacy.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy for the Local Filesystem Link Extension 2 | 3 | This privacy policy details the data practices of the Local Filesystem Link extension. 4 | 5 | ## 1. Data Collection and Usage 6 | 7 | The Local Filesystem Link extension does not collect, use, or share any personal data from its users. It operates entirely locally on your browser, without communicating with external servers or services. The extension does not gather or store any personally identifiable information or any other type of data from its users. 8 | 9 | ## 2. Permissions 10 | 11 | To facilitate its core functionalities, the extension requires permissions to alter the browser's behavior, enabling it to open local files such as `c:/textfile.txt` or any UNC path from user-whitelisted URLs. Despite necessitating these permissions, the extension doesn’t engage in the collection or transmission of personal data. 12 | 13 | ## 3. User Control 14 | 15 | Users maintain the authority to dictate the URLs where the extension remains active, by leveraging a white-listing feature. This function operates locally and does not involve the transfer or sharing of data with external entities. 16 | 17 | ## 4. Disclosure to Websites 18 | 19 | The extension adds a click handler and an icon next to eligible links, a feature that can be toggled in the extension’s options. Due to this, websites can technically detect the presence of the extension. This addition enhances user interaction without collecting or conveying any personal information to the websites. 20 | 21 | ## 5. Data Security 22 | 23 | Since the extension does not engage in the collection or storage of personal data, it does not incorporate data security measures pertaining to the protection of personal data. 24 | 25 | ## 6. Changes to the Privacy Policy 26 | 27 | We hold the rights to update this privacy policy periodically. Despite the non-involvement in data collection, we may refine this policy to maintain alignment with regulatory requisites and ensure transparency with our users. 28 | 29 | ## Contact Us 30 | 31 | For any queries or clarifications regarding this privacy policy, please reach us at [Github/webextension_local_filesystem_links](https://github.com/feinstaub/webextension_local_filesystem_links). 32 | 33 | By utilizing the Local Filesystem Link extension, you consent to the practices delineated in this privacy policy. 34 | -------------------------------------------------------------------------------- /test/test-launch-local-process.js: -------------------------------------------------------------------------------- 1 | /* 2 | * License: www.mozilla.org/MPL/ 3 | */ 4 | "use strict"; 5 | 6 | // SEE https://addons.mozilla.org/en-US/developers/docs/sdk/1.1/packages/api-utils/docs/unit-test.html 7 | 8 | const { Ci, Cc } = require( "chrome" ); 9 | const localProcess = require( "../lib/launch-local-process" ); 10 | const isWindowsOs = require('../lib/utils/os-util').isWindowsOs; 11 | 12 | var existingFile, notExisting, folderWithSpaceExisting, folderWithSpaceQuotedExisting; 13 | 14 | if (isWindowsOs()) { 15 | existingFile = "C:\\Windows\\explorer.exe"; 16 | notExisting = "C:\\muh.exe"; 17 | folderWithSpaceExisting = "C:\\Windows\\Downloaded Program Files"; 18 | folderWithSpaceQuotedExisting = "\"C:\\Windows\\Downloaded Program Files\""; 19 | } 20 | else { 21 | // console.log('unix system'); 22 | existingFile = "/etc/issue"; 23 | notExisting = "/muh/notfound"; 24 | // todo --> create path at /tmp/ folder 25 | folderWithSpaceExisting = "/tmp/path with spaces"; 26 | folderWithSpaceQuotedExisting = "\"/tmp/path with spaces\""; 27 | 28 | // check if folder is existing --> create it if it's missing 29 | var file = Cc['@mozilla.org/file/local;1']. 30 | createInstance(Ci.nsILocalFile); 31 | file.initWithPath(folderWithSpaceExisting); 32 | if (file && !file.exists()) { 33 | file.create(1, 384); // oct 0600 --> only current user can read/write 34 | } 35 | } 36 | 37 | /*exports.test_getEnvVar = function( test ) { 38 | let v1 = localProcess.getEnvironmentVariable( "WINDIR" ); 39 | test.assertEqual( v1.toUpperCase(), "C:\\WINDOWS" ); 40 | 41 | test.assertRaises( function() { 42 | localProcess.getEnvironmentVariable( "__MUH__" ); 43 | }, 44 | "getEnvironmentVariable: variable does not exist: __MUH__" ); 45 | };*/ 46 | 47 | exports.test_pathExists = function( test ) { 48 | var localFile = Cc[ "@mozilla.org/file/local;1" ] 49 | .createInstance( Ci.nsILocalFile ); 50 | 51 | localFile.initWithPath(existingFile); 52 | test.assertEqual( localProcess.pathExists( localFile ), true ); 53 | 54 | localFile.initWithPath(notExisting); 55 | test.assertEqual( localProcess.pathExists( localFile ), false ); 56 | }; 57 | 58 | exports.test_getNsIFileFromPath = function( test ) { 59 | let nsFile = localProcess.getNsIFileFromPath( existingFile ); 60 | test.assertEqual( nsFile.exists(), true ); 61 | 62 | nsFile = localProcess.getNsIFileFromPath( notExisting ); 63 | test.assertEqual( nsFile.exists(), false ); 64 | 65 | // Folder with space 66 | nsFile = localProcess.getNsIFileFromPath( folderWithSpaceExisting ); 67 | test.assertEqual( nsFile.exists(), true ); 68 | 69 | // With "" 70 | nsFile = localProcess.getNsIFileFromPath( folderWithSpaceQuotedExisting ); 71 | test.assertEqual( nsFile.exists(), true ); 72 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Local Filesystem Links", 3 | "name": "alien-local-filesystem-links", 4 | "version": "0.101.0", 5 | "description": "Scans pages for file:/// links and makes it possible to open them with the system's file browser.", 6 | "main": "index.js", 7 | "author": "austrALIENsun", 8 | "scripts": { 9 | "start": "npm run dev", 10 | "start:web-ext": "wait-on dist/ && web-ext run -s dist/", 11 | "start:web-ext_profile": "wait-on dist/ && web-ext run -s dist/ -p \"firefox_addon\" --keep-profile-changes", 12 | "web-ext": "web-ext run -s dist/", 13 | "bundle": "web-ext build -s dist/ --overwrite-dest", 14 | "sign": "sh ./sign-bundle.sh", 15 | "clean": "rimraf dist", 16 | "dev": "npm-run-all clean --parallel watch start:web-ext", 17 | "watch": "webpack-cli --watch", 18 | "prebuild": "npm run clean", 19 | "build": "cross-env NODE_ENV=production webpack-cli --progress", 20 | "lint": "eslint ./src/**/*.js", 21 | "lint:web-ext": "web-ext lint", 22 | "pretty": "prettier ./src/**/*.js --write" 23 | }, 24 | "husky": { 25 | "hooks": { 26 | "pre-commit": "pretty-quick --staged" 27 | } 28 | }, 29 | "lint-staged": { 30 | "*.js": [ 31 | "npm run lint", 32 | "git add" 33 | ] 34 | }, 35 | "engines": { 36 | "firefox": ">=38.0a1", 37 | "fennec": ">=38.0a1" 38 | }, 39 | "license": "MPL 1.1/GPL 3.0", 40 | "id": "jid1-JAzC7z53jemo5Q@jetpack", 41 | "permissions": { 42 | "multiprocess": true 43 | }, 44 | "dependencies": { 45 | "lodash.debounce": "^4.0.8", 46 | "match-pattern": "0.0.2", 47 | "vue": "^2.5.16", 48 | "webextension-polyfill": "^0.2.1" 49 | }, 50 | "devDependencies": { 51 | "@babel/core": "^7.21.8", 52 | "@babel/preset-env": "^7.21.5", 53 | "ajv": "^8.6.0", 54 | "babel-eslint": "^9.0.0", 55 | "babel-loader": "^8.0.0-beta.6", 56 | "babel-preset-env": "^1.7.0", 57 | "copy-webpack-plugin": "^11.0.0", 58 | "cross-env": "^5.1.5", 59 | "css-loader": "^3.1.0", 60 | "eslint": "^8.41.0", 61 | "eslint-config-prettier": "^6.0.0", 62 | "eslint-plugin-prettier": "^3.1.0", 63 | "file-loader": "^1.1.11", 64 | "friendly-errors-webpack-plugin": "^1.7.0", 65 | "html-webpack-plugin": "^5.5.1", 66 | "husky": "^3.0.2", 67 | "node-process": "^1.0.1", 68 | "npm-run-all": "^4.1.5", 69 | "prettier": "^1.16.4", 70 | "pretty-quick": "^1.11.1", 71 | "request": "^2.88.2", 72 | "rimraf": "^2.6.2", 73 | "style-loader": "^0.21.0", 74 | "vue-template-compiler": "^2.5.16", 75 | "vue-template-loader": "^1.1.0", 76 | "wait-on": "^7.0.1", 77 | "web-ext": "^7.6.2", 78 | "webpack": "^5.84.1", 79 | "webpack-cli": "^5.1.1", 80 | "write-file-webpack-plugin": "^4.3.2" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/webserver/issue22/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Issue 22 - Windows / Linux path variables 6 | 7 | 8 |

    Test if we can open links with environment path variables e.g. %HOMEPATH%

    9 |

    Why are three slashes required file:///%HOMEDRIVE%? With only two it will be relpace to file:///

    10 |

    Probably FF will remove %HOMEDRIVE% because it is not a valid uri.

    11 |

    Info to env. var

    12 |

    Windows list all env. variables with SET command.

    13 |

    Linux list all env. variables with printenv command.

    14 | Windows setting: SET name=c:\
    15 | Linux setting:
    16 | add the following lines to the end of your ~/.bashrc file and re-login into your account (test.txt file in /tmp/test/test.txt):
    17 | export TMPDIR=/tmp
    18 | export TEST=test
    19 | 20 |

    Encoding issue: % in uri is a problem - interference with decodeUriComponent that is required for accents in urls.
    21 | with-out decodeUriComponent the links are working as commented below.
    22 | Temporary work-around manually encoding in links with env. vars required %25 for % for windows and %24 for $ in Linux 23 |

    24 |

    Windows

    25 | 31 |

    Linux

    32 | 38 | 41 | 55 |

    56 | 57 | 58 | -------------------------------------------------------------------------------- /src/extension/components/Settings.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |

    6 | {{whitelistDescription}} 7 |

    8 | 14 |
    15 | 16 | 17 | 18 | 19 |
    20 |

    21 | 27 | {{enableExecutablesDescription}} 30 |

    31 |
    32 | 33 | 34 | 35 | 36 |
    37 |

    38 | 44 | {{enableLinkIconsDescription}} 47 |

    48 |
    49 | 50 | 51 | 52 | 55 |
    56 | 65 | 74 | 86 |

    87 | {{revealOpenOptionDescription}} 88 |

    89 |
    90 | 91 | 92 | 95 |
    96 |

    97 | {{retriesOnFailureDescription}} 98 |

    99 | 105 |
    106 | 107 |

    {{statusMsg}}

    108 | 109 | 110 |
    111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | local-filesystem-links 2 | ====================== 3 | 4 | Overview 5 | -------- 6 | This is the alien-local-filesystem-links extension for Mozilla Firefox. 7 | 8 | It contains: 9 | 10 | * extension source code (src/) 11 | * native app source code (native-host/) 12 | * tests (test/) 13 | * documentation (doc/) 14 | 15 | 16 | Features 17 | -------- 18 | - Adds a click event to every link that is including `file://` or `smb://` in `href` tag. (smb not working yet) 19 | - Shows a link icon close to the link. Icon can be disabled in preferences. 20 | - Dynamic loaded content supported because link events are delegated with `$(document).on(...)` 21 | - Supports links with double and tripple slashes (e.g. file:// or file:///) 22 | - (Not available: Right click context menu that opens a text selection that contains a file link + option to reveal the directory of a directly linked file.) 23 | - Whitelist option to enable local links only at a specific url e.g. `*.trello.com` 24 | - Statusbar icon for displaying if links are active for current tab & for easier access to addon settings 25 | - Option to change the default text link behaviour (open or reveal) 26 | - Localization (current languages German, English, Russian) 27 | 28 | 29 | Screenshots 30 | -------- 31 | ![Addon at local test server](/doc/screenshots/addon_in_action.png) 32 | ![Context menu](/doc/screenshots/addon_context_menu.png) 33 | 34 | 35 | License 36 | ------- 37 | * GPLv3 or later 38 | * www.mozilla.org/MPL/ v2 or later 39 | 40 | 41 | Start developing 42 | ---------------- 43 | See README.dev.md 44 | 45 | 46 | Donations 47 | --------- 48 | If you like the extension and you want to support the development - please consider to donate. Any donations are greatly appreciated. 49 | 50 | * AWolf81 - current main developer: 51 | * [Paypal.me to AWolf81](https://www.paypal.me/awlf81) (coding contributions) 52 | * What are we doing with the donations? 53 | * Buy a code signing certificate (needed for Windows) cost around 100 USD 54 | * Incentive / motivation - this helps to stay motivated. 55 | 56 | * Feinstaub - original author and addon management: 57 | * No direct donations possible yet (waiting for something private and decentrally organized like [GNU Taler](https://taler.net/en)) 58 | * [Some people do not use Paypal](https://github.com/feinstaub/webextension_local_filesystem_links/issues/98#issuecomment-357984115), maybe because of https://de.wikipedia.org/wiki/PayPal#Kritik 59 | * Any donation that supports a Free Software community helps to maintain a technical and social environment where the development of software like this addon are possible. If you have no idea which community you would like to support, I recommend these organisations: 60 | * **KDE**: https://www.kde.org/community/donations/others.php 61 | * Vision: ["A world in which everyone has control over their digital life and enjoys freedom and privacy."](https://dot.kde.org/2016/04/05/kde-presents-its-vision-future) 62 | * [supports Bitpay](https://bitpay.com/990273/donate) 63 | * **Free Software Foundation**: https://www.fsf.org/about/ways-to-donate 64 | * **Software Freedom Conservancy**: https://sfconservancy.org/donate 65 | * ["helps promote, improve, develop, and defend Free, Libre, and Open Source Software (FLOSS) projects"](https://sfconservancy.org/about/) 66 | * **Mozilla**: https://donate.mozilla.org/de/ 67 | * For Germany, there are related organisations which help Free Software indirectly by supporting the underlying values: 68 | * **DigitalCourage**: https://digitalcourage.de/ueber-uns 69 | * "Digitalcourage arbeitet für eine lebenswerte Welt im digitalen Zeitalter." 70 | * "setzt sich seit 1987 für Grundrechte und Datenschutz ein" 71 | * **Forum InformatikerInnen für Frieden und gesellschaftliche Verantwortung e.V.**: https://www.fiff.de 72 | * "FIfF wurde 1984 [...] aus einer historischen Situation heraus gegründet, als es galt, das Schweigen einer Zunft zu brechen, die so maßgeblich an der Entwicklung automatisierter und informatisierter Kriegsführung beteiligt war." 73 | -------------------------------------------------------------------------------- /native-host/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-messaging-host", 3 | "version": "0.2.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "balanced-match": { 8 | "version": "1.0.0", 9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 11 | "dev": true 12 | }, 13 | "brace-expansion": { 14 | "version": "1.1.8", 15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 16 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 17 | "dev": true, 18 | "requires": { 19 | "balanced-match": "1.0.0", 20 | "concat-map": "0.0.1" 21 | } 22 | }, 23 | "concat-map": { 24 | "version": "0.0.1", 25 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 26 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 27 | "dev": true 28 | }, 29 | "fs.realpath": { 30 | "version": "1.0.0", 31 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 32 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 33 | "dev": true 34 | }, 35 | "glob": { 36 | "version": "7.1.2", 37 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 38 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 39 | "dev": true, 40 | "requires": { 41 | "fs.realpath": "1.0.0", 42 | "inflight": "1.0.6", 43 | "inherits": "2.0.3", 44 | "minimatch": "3.0.4", 45 | "once": "1.4.0", 46 | "path-is-absolute": "1.0.1" 47 | } 48 | }, 49 | "inflight": { 50 | "version": "1.0.6", 51 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 52 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 53 | "dev": true, 54 | "requires": { 55 | "once": "1.4.0", 56 | "wrappy": "1.0.2" 57 | } 58 | }, 59 | "inherits": { 60 | "version": "2.0.3", 61 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 62 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 63 | "dev": true 64 | }, 65 | "innosetup-compiler": { 66 | "version": "5.5.9", 67 | "resolved": "https://registry.npmjs.org/innosetup-compiler/-/innosetup-compiler-5.5.9.tgz", 68 | "integrity": "sha1-//VhobtJzl07Ez7ot4i1qGj17iE=", 69 | "dev": true 70 | }, 71 | "minimatch": { 72 | "version": "3.0.4", 73 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 74 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 75 | "dev": true, 76 | "requires": { 77 | "brace-expansion": "1.1.8" 78 | } 79 | }, 80 | "once": { 81 | "version": "1.4.0", 82 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 83 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 84 | "dev": true, 85 | "requires": { 86 | "wrappy": "1.0.2" 87 | } 88 | }, 89 | "path-is-absolute": { 90 | "version": "1.0.1", 91 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 92 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 93 | "dev": true 94 | }, 95 | "rimraf": { 96 | "version": "2.6.2", 97 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 98 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 99 | "dev": true, 100 | "requires": { 101 | "glob": "7.1.2" 102 | } 103 | }, 104 | "wrappy": { 105 | "version": "1.0.2", 106 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 107 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 108 | "dev": true 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /test/webserver/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | firefox_addon_local_filesystem_links Test Pages 6 | 7 | 8 |

    firefox_addon_local_filesystem_links Test pages

    9 |

    Here you can find pages where you can verify features.

    10 | 11 |

    12 | NOTE: These test pages should be served by a webserver and 13 | not just double-clicked and opened locally. Otherwise the link 14 | recognition fails and Firefox opens the file links (which it does 15 | not if the page is served by a webserver; thats what the add-on is 16 | for). 17 |

    18 | 19 |

    Page list

    20 | 21 |

    Standard test cases 1

    22 | 23 |

    24 | Issue User Review 1 Comma in path 25 | (user review) 29 |

    30 | 31 |

    32 | Issue 1 - Dynamic content (github) 36 |

    37 | 38 |

    39 | Issue 2 - Blanks in path (github) 43 |

    44 | 45 |

    46 | Issue 16 - security improvement (Issue 16) 50 |

    51 | 52 |

    53 | Issue 22 - Windows / Linux env. path varibales 56 | (Issue 22) 60 |

    61 | 62 |

    63 | Issue 53 - style improvement (Issue 53) 67 |

    68 | 69 |

    70 | Issue 65 - Direct open as option 71 | (Issue 65) 75 |

    76 | 77 |

    78 | Issue 74 - icons added to hidden links 81 | (Issue 74) 85 |

    86 | 87 |

    88 | Issue 84 - european accents (Issue 84) 92 |

    93 | 94 |

    95 | Issue Iframe - re-loading issue (like at jsfiddle) 98 |

    99 |

    100 | Issue 106 - address in link e.g. 192.168.2.x 103 |

    104 |

    105 | Issue 113 - Multiple windows opened 108 |

    109 |

    110 | Issue 183 - Don't overwrite title attribute 113 |

    114 | 115 | 116 | -------------------------------------------------------------------------------- /README.dev.md: -------------------------------------------------------------------------------- 1 | # local-filesystem-links DEVELOPMENT 2 | 3 | jsfiddle for some whitelist testing: http://jsfiddle.net/awolf2904/tefcs74q/ 4 | 5 | # Building for production 6 | 7 | see README.build-from-source.md 8 | 9 | # Extension testing in browser 10 | 11 | ## Install native app 12 | 13 | Go to `native-host\src\` and run `install_host`. This will register the native app in your system. 14 | 15 | ## Starting dev script 16 | 17 | Run `npm run dev` will start webpack to build the extension. It will also watch for changes to the source files and once `dist` folder is ready it starts Firefox with the extension. 18 | 19 | ## Manually starting 20 | 21 | Run `npm run build`, open Firefox and enter about:debugging in url bar and load `dist\manifest.json` Extension. 22 | 23 | ## With Web-ext CLI 24 | 25 | Install [web-ext](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext) with `npm install --global web-ext`. 26 | 27 | And run `web-ext run` in `dist` folder to start FF nightly with the Extension temporarily enabled. 28 | 29 | # Usage 30 | 31 | First run `npm install`. 32 | 33 | ## Start dev server 34 | 35 | `npm run dev` starts the development build for FF and watches source directory for changes. 36 | 37 | ## Start firefox with webextension loaded 38 | 39 | `npm start` to start web-ext start with dist folder. It will load the extension in Firefox. 40 | 41 | Based on https://www.npmjs.com/package/web-ext 42 | 43 | ## Linting 44 | 45 | `npm run lint` will lint your files with eslint. But it's recommended to use VS code prettier plugin, so your code is pretty after hitting save. 46 | 47 | `npm run lint:webext` will lint the extension with web-ext linter. 48 | 49 | # Testing 50 | 51 | ## Manual tests 52 | 53 | The web server is available in `test/webserver` and it can be started with `npm start` in the mentioned directory. Then run `npm run dev` in project root and open `localhost:3000` to do manual tests. 54 | 55 | We need node to create a webserver because we cannot test properly with local websites. 56 | 57 | ## Unit tests 58 | 59 | -- Not available -- 60 | The old jpm unit tests are not working, so we have to convert them so we can run them with the web extension. 61 | 62 | The following repo is going in the right direction https://github.com/Standard8/example-webextension and it's using Karma as test runner. 63 | 64 | ## CODING STYLE 65 | 66 | We follow w3schools.com's style guide and coding conventions, see http://www.w3schools.com/js/js_conventions.asp. 67 | 68 | Additionally all pages are coded in order to conform with strict mode, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode. 69 | 70 | ## DOCUMENTATION 71 | 72 | We use JSDoc for documentation, see http://code.google.com/p/jsdoc-toolkit/wiki/DocExamples 73 | 74 | ## WEB SERVER 75 | 76 | Used to verify some features, nodejs is required. See readme in \test\README.md for more information. 77 | 78 | Webserver can be started by executing: \test\webserver\start_test_server.cmd 79 | 80 | - Q: Why don't we use local html files? 81 | - A: Because they are treated differently (compared to remotely served files) by Firefox 82 | 83 | ## IDE HINTS 84 | 85 | IntelliJ IDEA Community Edition 11 86 | http://stackoverflow.com/questions/1147336/how-to-get-intellij-idea-to-display-directories 87 | 88 | 1. Start IntelliJ IDEA Community Edition 11.0 89 | 2. File --> Open Project... --> Select folder firefox_addon_local_filesystem_links 90 | (where this README.dev.txt resides) 91 | opt: 3) Project settings --> Spelling --> Custom dict --> ... 92 | 93 | ## SIGNING (only users with AMO dev. account) 94 | 95 | Copy `.env.example` to `.env` and replace the entries with your AMO account details. 96 | 97 | Run `npm run build` and then `npm run sign`. 98 | Please check version in `package.json` before signing as it will upload the new version to AMO. AMO will refuse the update if the version already exists. 99 | 100 | If you'd like to sign with-out AMO upload (e.g. a signed test version), run `npm run sign unlisted` and download the signed version from https://addons.mozilla.org/de/developers/addon/local-filesystem-links 101 | 102 | Manual installation is then possible with `about:addons`. Version names like `0.0.1pre` are not working at the moment (April 2020). Not sure why? Simply use a regular version to distribute a test version. 103 | -------------------------------------------------------------------------------- /src/extension/components/Settings.js: -------------------------------------------------------------------------------- 1 | import debounce from 'lodash.debounce'; 2 | import { defaultSettings } from '../constants'; 3 | import withRender from './Settings.html'; 4 | 5 | const DEBOUNCE_TIME = 500; // delay saving by 500ms (reduce saving as you type) 6 | const STATUS_TIME = 2000; // flash duration 7 | 8 | export default withRender({ 9 | data() { 10 | const getI18n = browser.i18n.getMessage; 11 | return { 12 | whitelistTitle: getI18n('whitelist_title'), 13 | whitelistDescription: getI18n('whitelist_description'), 14 | enableExecutablesTitle: getI18n('enableExecutables_title'), 15 | enableExecutablesDescription: getI18n( 16 | 'enableExecutables_description' 17 | ), 18 | enableLinkIconsTitle: getI18n('enableLinkIcons_title'), 19 | enableLinkIconsDescription: getI18n('enableLinkIcons_description'), 20 | revealOpenOptionTitle: getI18n('revealOpenOption_title'), 21 | revealOpenOptionDescription: getI18n( 22 | 'revealOpenOption_description' 23 | ), 24 | revealOpenOptionTexts: { 25 | o: getI18n('revealOpenOption_options_Open'), 26 | r: getI18n('revealOpenOption_options_Reveal'), 27 | d: getI18n('revealOpenOption_options_Direct') 28 | }, 29 | retriesOnFailureTitle: getI18n('retries_on_failure_title'), 30 | retriesOnFailureDescription: getI18n( 31 | 'retries_on_failure_description' 32 | ), 33 | settings: defaultSettings, 34 | statusMsg: undefined, 35 | loaded: false 36 | }; 37 | }, 38 | created() { 39 | this.load(); 40 | }, 41 | watch: { 42 | settings: { 43 | handler(val, old) { 44 | this.updateSetting(); 45 | }, 46 | deep: true 47 | } 48 | }, 49 | methods: { 50 | updateSetting: debounce(function() { 51 | this.save(); 52 | }, DEBOUNCE_TIME), 53 | 54 | getObj(obj) { 55 | return JSON.parse(JSON.stringify(obj)); // remove reactive getters/setters 56 | }, 57 | 58 | save() { 59 | const settings = this.getObj(this.settings); 60 | 61 | browser.storage.local 62 | .set(settings) 63 | .then(() => { 64 | // Update status to let user know options were saved. 65 | // console.log('saved!', browser.storage.local); 66 | this.statusMsg = 'Options saved.'; 67 | let updateActionObj = Object.assign( 68 | {}, 69 | { 70 | action: 'updateContentPages' 71 | }, 72 | settings 73 | ); 74 | 75 | // browser.runtime.sendMessage(updateActionObj); 76 | 77 | setTimeout(() => { 78 | this.statusMsg = ''; 79 | }, STATUS_TIME); 80 | }) 81 | .catch(err => { 82 | this.statusMsg = err; 83 | }); 84 | }, 85 | toggleExecutables() { 86 | this.settings.enableExecutables = !this.settings.enableExecutables; 87 | }, 88 | toggleLinkIcon() { 89 | this.settings.enableLinkIcons = !this.settings.enableLinkIcons; 90 | }, 91 | load() { 92 | // return {colorSettings: defaultColor}; 93 | // Use default value color = 'red' and likesColor = true. 94 | // chrome.storage.local.get(defaultColor, 95 | // console.log('load defaults', defaultSettings, this.getObj(defaultSettings)) 96 | browser.storage.local 97 | .get(this.getObj(defaultSettings)) 98 | .then(items => { 99 | // console.log('loaded', items); 100 | // alert(JSON.stringify(items)) 101 | this.settings = items || defaultSettings; 102 | this.loaded = true; 103 | }) 104 | .catch(err => { 105 | this.statusMsg = `Error: ${err}`; 106 | }); 107 | } 108 | } 109 | }); 110 | -------------------------------------------------------------------------------- /src/extension/_locales/ru/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "whitelist_title": { 3 | "message": "URL-адреса, добавленные в White List, будут кликабельными", 4 | "description": "Settings title for whitelist" 5 | }, 6 | "whitelist_description": { 7 | "message": "По-умолчанию кликабельны все ссылки, которые распознает дополнение, но вы можете добавить нераспознанные URL-адреса вручную, разделяя их пробелом. Допускается использование подстановочных знаков, например, *://*.trello.com/*", 8 | "description": "Settings description for whitelist" 9 | }, 10 | "enableExecutables_title": { 11 | "message": "Разрешить ссылки на исполняемые файлы", 12 | "description": "Settings title for enable of executable files" 13 | }, 14 | "enableExecutables_description": { 15 | "message": "Если включить эту опцию, URL-адреса на исполняемые файлы станут кликабельными. Будьте осторожны, это не всегда безопасно!", 16 | "description": "Settings description for executable files" 17 | }, 18 | "enableLinkIcons_title": { 19 | "message": "Отображать иконки возле ссылок", 20 | "description": "Settings title for enable link icons" 21 | }, 22 | "enableLinkIcons_description": { 23 | "message": "Если включить эту опцию, то напротив каждой локальной ссылки будет отображаться иконка", 24 | "description": "Settings description for link icons" 25 | }, 26 | "revealOpenOption_title": { 27 | "message": "Default link text click behaviour", 28 | "description": "Settings title for default link click behaviour" 29 | }, 30 | "revealOpenOption_description": { 31 | "message": " Changes the default click behaviour of file-links. Default = direct file link open.", 32 | "description": "Settings description for default click behaviour" 33 | }, 34 | "revealOpenOption_options_Open": { 35 | "message": "Open link directly", 36 | "description": "Setting open link directly" 37 | }, 38 | "revealOpenOption_options_Reveal": { 39 | "message": "Reveal link (open containing folder)", 40 | "description": "Setting reveal link" 41 | }, 42 | "revealOpenOption_options_Direct": { 43 | "message": "Open link directly in browser", 44 | "description": "Setting direct open" 45 | }, 46 | "ERROR_EXECTUBALES_NOT_ENABLED": { 47 | "message": "Открытие исполняемых файлов отключено в настройках дополнения. Пожалуйста, включите эту опцию и попробуйте снова.", 48 | "description": "Error message EXE not enabled" 49 | }, 50 | "ERROR_BAD_LINK": { 51 | "message": "Невозможно открыть файл $URL$", 52 | "description": "Error message bad link", 53 | "placeholders": { 54 | "url" : { 55 | "content" : "$1", 56 | "example" : "file://" 57 | } 58 | } 59 | }, 60 | "INFO_CONFIG_CHANGED_SMB": { 61 | "message": "Заработали ссылки на SMB-ресурсы!", 62 | "description": "Info message SMB configured (not used yet)" 63 | }, 64 | "LABEL_CONTEXT_MENU_OPEN_LINK": { 65 | "message": "Открыть ссылку", 66 | "description": "Label text open link" 67 | }, 68 | "LABEL_CONTEXT_MENU_OPEN_CONTAINING": { 69 | "message": "Открыть содержащую папку", 70 | "description": "Label text open containing folder" 71 | }, 72 | "LABEL_CONTEXT_MENU_OPEN_DIRECT": { 73 | "message": "Open in browser", 74 | "description": "Label text open in browser" 75 | }, 76 | 77 | "LABEL_CONTEXT_SUB_SELECTION_TITLE": { 78 | "message": "Открыть выбранное", 79 | "description": "Label text selection in context menu" 80 | }, 81 | 82 | "LABEL_CONTEXT_SUB_LINK_TITLE": { 83 | "message": "Link addon", 84 | "description": "Label text context menu item" 85 | }, 86 | 87 | "LABEL_ADDONBAR_ICON_HOVER": { 88 | "message": "Локальные ссылки $ACTIVE$ в текущей вкладке.", 89 | "description": "Status icon hover text", 90 | "placeholders": { 91 | "active" : { 92 | "content" : "$1", 93 | "example" : "active" 94 | } 95 | } 96 | }, 97 | 98 | "LABEL_ADDONBAR_HOVER_STATE_active": { 99 | "message": "включены", 100 | "description": "Status text active hover" 101 | }, 102 | "LABEL_ADDONBAR_HOVER_STATE_inactive": { 103 | "message": "выключены", 104 | "description": "Status text inactive hover" 105 | }, 106 | 107 | "TOOLTIP_OPEN_FOLDER": { 108 | "message": "Открыть папку", 109 | "description": "Tooltip text open folder" 110 | }, 111 | "TOOLTIP_OPEN_LINK": { 112 | "message": "Перейти по ссылке", 113 | "description": "Tooltip text open link" 114 | }, 115 | "TOOLTIP_OPEN_IN_BROWSER": { 116 | "message": "Open link in browser", 117 | "description": "Tooltip text open in browser" 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /test/webserver/std1/issue.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 43 | 44 | 45 | 46 |

    47 |

    48 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /evalpage/testpage.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
    96 |

    THIS IS THE TEMPLATE

    97 | [new] 98 |
    99 |
    100 | 101 | 102 | 103 | 104 |
    105 | 106 |

    No Frills is not possible in Confluence

    107 | 108 | 109 |

    C-Link with / []

    110 | 111 |

    C-Link with \ (file:// as is)

    112 | 113 |

    C-Link with \ (as is)

    114 | 115 |

    C-Link 3 slashes

    116 | 117 |

    C-Link 2 slashes

    118 | 119 |

    Wikipedia

    120 | 121 |

    C-Link with spaces %20

    122 | 123 |

    C-Link 5 slashes - network drive

    124 | 125 | 126 |

    "C:\Windows\Downloaded Program Files\desktop.ini"

    127 | 128 |

    "C:\Windows\Downloaded Program Files\"

    129 | 130 |

    "C:\Windows\Downloaded Program Files"

    131 | 132 |

    C:\Windows

    133 | 134 |

    "C:\Windows"

    135 | 136 |

    After this the stuff should be inserted:

    137 | 138 | 139 | 140 | 148 | 149 | -------------------------------------------------------------------------------- /src/extension/_locales/fr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "whitelist_title": { 3 | "message": "Activer l'addon de lien de fichier pour les URLs en liste blanche", 4 | "description": "Paramètres titre de la liste blanche" 5 | }, 6 | "whitelist_description": { 7 | "message": "Toutes les URL qui sont ajoutées à la liste blanche activeront les liens de fichiers locaux si vous naviguez vers cette adresse. * activera tout. Vide désactivera tout. Les URL multiples sont séparées par des espaces. Les caractères génériques sont autorisés, par exemple *://*.trello.com/*.", 8 | "description": "Description des paramètres de la liste blanche" 9 | }, 10 | "enableExecutables_title": { 11 | "message": "Activer les liens vers les fichiers exécutables locaux", 12 | "description": "Titre des paramètres pour l'activation des fichiers exécutables" 13 | }, 14 | "enableExecutables_description": { 15 | "message": "Si cette option est activée, n'importe quel fichier de programme peut être lancé par l'addon. (Attention ! Un site malveillant pourrait l'utiliser pour une attaque par déni de service (DDOS) !", 16 | "description": "Description des paramètres pour les fichiers exécutables" 17 | }, 18 | "enableLinkIcons_title": { 19 | "message": "Activer les icônes de lien", 20 | "description": "Titre des paramètres pour les icônes d'activation des liens" 21 | }, 22 | "enableLinkIcons_description": { 23 | "message": "Si cette case est cochée, un lien sera ajouté à chaque lien local.", 24 | "description": "Description des paramètres pour les icônes de lien" 25 | }, 26 | "revealOpenOption_title": { 27 | "message": "Comportement par défaut des clics de texte de lien par défaut", 28 | "description": "Paramètres titre pour le comportement de clic de lien par défaut" 29 | }, 30 | "revealOpenOption_description": { 31 | "message": "Modifie le comportement de clic par défaut des liens de fichier. Par défaut = lien de fichier direct ouvert.", 32 | "description": "Description des paramètres pour le comportement de clic par défaut" 33 | }, 34 | "revealOpenOption_options_Open": { 35 | "message": "Ouvrir le lien directement", 36 | "description": "Mise en place d'un lien ouvert directement" 37 | }, 38 | "revealOpenOption_options_Reveal": { 39 | "message": "Révéler le lien (ouvrir le dossier contenant le dossier)", 40 | "description": "Réglage du lien de révélation" 41 | }, 42 | "revealOpenOption_options_Direct": { 43 | "message": "Ouvrir le lien directement dans le navigateur", 44 | "description": "Réglage d'ouverture directe" 45 | }, 46 | "ERROR_EXECTUBALES_NOT_ENABLED": { 47 | "message": "Vous essayez d'ouvrir un fichier exécutable. Veuillez vérifier les paramètres de l'addon pour activer les fichiers exécutables et réessayer.", 48 | "description": "Message d'erreur EXE non activé" 49 | }, 50 | "ERROR_BAD_LINK": { 51 | "message": "Impossible d'ouvrir le fichier $URL$$.", 52 | "description": "Message d'erreur mauvais lien", 53 | "placeholders": { 54 | "url" : { 55 | "content" : "$1", 56 | "example" : "fichier://" 57 | } 58 | } 59 | }, 60 | "INFO_CONFIG_CHANGED_SMB": { 61 | "message": "Configuration modifiée ! Les liens SMB sont maintenant activés", 62 | "description": "Message d'information SMB configuré (pas encore utilisé)" 63 | }, 64 | "LABEL_CONTEXT_MENU_OPEN_LINK": { 65 | "message": "Ouvrir le lien", 66 | "description": "Texte de l'étiquette Ouvrir le lien" 67 | }, 68 | "LABEL_CONTEXT_MENU_OPEN_CONTAINING": { 69 | "message": "Ouvrir le dossier contenant", 70 | "description": "Texte d'étiquette ouvert contenant un dossier" 71 | }, 72 | "LABEL_CONTEXT_MENU_OPEN_DIRECT": { 73 | "message": "Ouvrir dans le navigateur", 74 | "description": "Texte d'étiquette ouvert dans le navigateur" 75 | }, 76 | 77 | "LABEL_CONTEXT_SUB_SELECTION_TITLE": { 78 | "message": "Sélection de l'addon de lien", 79 | "description": "Sélection du texte de l'étiquette dans le menu contextuel" 80 | }, 81 | 82 | "LABEL_CONTEXT_SUB_LINK_TITLE": { 83 | "message": "Ajout de lien", 84 | "description": "Elément de menu contextuel du texte de l'étiquette" 85 | }, 86 | 87 | "LABEL_ADDONBAR_ICON_HOVER": { 88 | "message": "Ajout de lien local (onglet courant : $ACTIVE$)", 89 | "description": "Icône d'état au survol du texte", 90 | "placeholders": { 91 | "active" : { 92 | "content" : "$1", 93 | "example" : "activé" 94 | } 95 | } 96 | }, 97 | 98 | "LABEL_ADDONBAR_HOVER_STATE_active": { 99 | "message": "activé", 100 | "description": "Survol de texte en état actif" 101 | }, 102 | "LABEL_ADDONBAR_HOVER_STATE_inactive": { 103 | "message": "inactif", 104 | "description": "Survol de Texte en état inactif" 105 | }, 106 | 107 | "TOOLTIP_OPEN_FOLDER": { 108 | "message": "Ouvrir dossier", 109 | "description": "Dossier ouvert du texte de l'info-bulle" 110 | }, 111 | "TOOLTIP_OPEN_LINK": { 112 | "message": "Ouvrir lien", 113 | "description": "Texte d'info-bulle lien ouvert" 114 | }, 115 | "TOOLTIP_OPEN_IN_BROWSER": { 116 | "message": "Ouvrir le lien dans le navigateur", 117 | "description": "Texte d'info-bulle ouvert dans le navigateur" 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/installed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Successfully installed - Local Filesystem Links 6 | 7 | 8 | 9 |
    10 |
    11 |

    Thank you for installing

    12 | 13 |

    Local Filesystem Links Extension

    14 |
    15 |
    16 |
    17 |

    Important! Next steps required for the extension to work

    18 |
      19 |
    1. Download and install the native application for your system.
      20 | 37 |
    2. 38 |
    3. 39 | Check and modify whitelist settings by clicking at the addon icon in addon bar and select "Change settings...". 40 | By default all pages are allowed but it's recommended to limit the pages where the addon can add the local link behaviour. 41 |
    4. 42 |
    5. 43 | Test the addon at your pages or at this Jsfiddle. 44 |
    6. 45 |
    46 |
    47 |

    Donations

    48 |

    If you like the extension and you want to support the development - please consider to donate. Any donations are greatly appreciated.

    49 | Ways to donate 50 |
    51 |

    Additional information

    52 |

    Why do I get a warning that my computer was protected by Windows? Show answer

    53 |
    54 |

    55 | This warning shouldn't happend anymore because the installer is signed now. If you're getting this warning please report it so we can check the certificate.
    56 | You can install the app if you're clicking on show more information and afterwards click on the new button "run anyway".
    57 | Below you see that message in Windows 10: 58 | 59 |

    60 |

    61 | If you're concerned about security then you can do the following to be sure that everything is as usual: 62 |

    66 |

    67 |
    68 |

    Why do I need to install a program? Show answer

    69 |
    70 |

    71 | In previous versions of Firefox (before FF 57) it was possible to access the 72 | local filesystem with the browser API. That's not supported anymore and it 73 | is similar to other browsers (e.g. Chrome has also this restriction). 74 |

    75 |

    76 | To make this extension possible we need a way to interact with the file system again. 77 | This is possible with a native application that communicates with the browser with an API. It's called native messaging. 78 | The application will use the system file explorer (e.g. on Windows - it's Windows Explorer) 79 | to open the application in your linked application. 80 |

    81 |
    82 |

    Whitelist needs to be according to new schema e.g. *://*.jsfiddle.net/*

    83 |

    The new format is <scheme>://<host><path> (wildcard char * is possible)
    84 | A single * will be replaced with <all_urls> by the extension. 85 | Please have a look at the following docs. for more details about match patterns 86 |

    87 |

    How can I whitelist a server with a port e.g. servername:8080?

    88 |

    Just add it with-out the port and it will be correctly handled. e.g. http://servername/*

    89 |
    90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/extension/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "whitelist_title": { 3 | "message": "Enable file link addon for whitelisted URLs", 4 | "description": "Settings title for whitelist" 5 | }, 6 | "whitelist_description": { 7 | "message": "Any URLs that are added to the whitelist will enable local file links if you're browsing to that address. * will enable all. Empty will disable all. Multiple URLs are space separated. Wildcards are allowed e.g. *://*.trello.com/*", 8 | "description": "Settings description for whitelist" 9 | }, 10 | "enableExecutables_title": { 11 | "message": "Enable links to local executable files", 12 | "description": "Settings title for enable of executable files" 13 | }, 14 | "enableExecutables_description": { 15 | "message": "If enabled any progam file can be launched by the addon. (Attention! A malicious site could use this for denial-of-service attack!)", 16 | "description": "Settings description for executable files" 17 | }, 18 | "enableLinkIcons_title": { 19 | "message": "Enable link icons", 20 | "description": "Settings title for enable link icons" 21 | }, 22 | "enableLinkIcons_description": { 23 | "message": "If checked there will be a link added to every local link", 24 | "description": "Settings description for link icons" 25 | }, 26 | "revealOpenOption_title": { 27 | "message": "Default link text click behaviour", 28 | "description": "Settings title for default link click behaviour" 29 | }, 30 | "revealOpenOption_description": { 31 | "message": "Changes the default click behaviour of file-links. Default = direct file link open.", 32 | "description": "Settings description for default click behaviour" 33 | }, 34 | "revealOpenOption_options_Open": { 35 | "message": "Open link directly", 36 | "description": "Setting open link directly" 37 | }, 38 | "revealOpenOption_options_Reveal": { 39 | "message": "Reveal link (open containing folder)", 40 | "description": "Setting reveal link" 41 | }, 42 | "revealOpenOption_options_Direct": { 43 | "message": "Open link directly in browser", 44 | "description": "Setting direct open" 45 | }, 46 | "retries_on_failure_title": { 47 | "message": "Retries on failure", 48 | "description": "Settings title for retries on failure" 49 | }, 50 | "retries_on_failure_description": { 51 | "message": "The number of retries to open a file before an error will be displayed (e.g. file not found will be indicated after all retries failed)", 52 | "description": "Settings description for retries on failure" 53 | }, 54 | "ERROR_EXECTUBALES_NOT_ENABLED": { 55 | "message": "You're trying to open an executable file. Please check addon settings to enable executable files and try again.", 56 | "description": "Error message EXE not enabled" 57 | }, 58 | "ERROR_BAD_LINK": { 59 | "message": "Couldn't open file $URL$", 60 | "description": "Error message bad link", 61 | "placeholders": { 62 | "url": { 63 | "content": "$1", 64 | "example": "file://" 65 | } 66 | } 67 | }, 68 | "INFO_CONFIG_CHANGED_SMB": { 69 | "message": "Configuration changed! SMB links now enabled", 70 | "description": "Info message SMB configured (not used yet)" 71 | }, 72 | "LABEL_CONTEXT_MENU_OPEN_LINK": { 73 | "message": "Open link", 74 | "description": "Label text open link" 75 | }, 76 | "LABEL_CONTEXT_MENU_OPEN_CONTAINING": { 77 | "message": "Open containing folder", 78 | "description": "Label text open containing folder" 79 | }, 80 | "LABEL_CONTEXT_MENU_OPEN_DIRECT": { 81 | "message": "Open in browser", 82 | "description": "Label text open in browser" 83 | }, 84 | 85 | "LABEL_CONTEXT_SUB_SELECTION_TITLE": { 86 | "message": "Link addon selection", 87 | "description": "Label text selection in context menu" 88 | }, 89 | 90 | "LABEL_CONTEXT_SUB_LINK_TITLE": { 91 | "message": "Link addon", 92 | "description": "Label text context menu item" 93 | }, 94 | 95 | "LABEL_ADDONBAR_ICON_HOVER": { 96 | "message": "Local link addon (current tab: $ACTIVE$)", 97 | "description": "Status icon hover text", 98 | "placeholders": { 99 | "active": { 100 | "content": "$1", 101 | "example": "active" 102 | } 103 | } 104 | }, 105 | 106 | "LABEL_ADDONBAR_HOVER_STATE_active": { 107 | "message": "active", 108 | "description": "Status text active hover" 109 | }, 110 | "LABEL_ADDONBAR_HOVER_STATE_inactive": { 111 | "message": "inactive", 112 | "description": "Status text inactive hover" 113 | }, 114 | 115 | "TOOLTIP_OPEN_FOLDER": { 116 | "message": "Open folder", 117 | "description": "Tooltip text open folder" 118 | }, 119 | "TOOLTIP_OPEN_LINK": { 120 | "message": "Open link", 121 | "description": "Tooltip text open link" 122 | }, 123 | "TOOLTIP_OPEN_IN_BROWSER": { 124 | "message": "Open link in browser", 125 | "description": "Tooltip text open in browser" 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /test/webserver/issue1/issue.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | local_filesystem_links / Test Page / dynamic 6 | 7 | 71 | 72 | 73 | The source of this html page was copied from 74 | here. 75 |
    76 | 90 |
    91 |
    94 |
    95 |
    96 |
    98 |
    101 | Change a 102 | link with js and check if the file link icon button updates
    103 |
    104 | 105 | 106 | -------------------------------------------------------------------------------- /src/extension/_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "whitelist_title": { 3 | "message": "Aktiviert das File link Addon für URLs in der White-list", 4 | "description": "Settings title for whitelist" 5 | }, 6 | "whitelist_description": { 7 | "message": "Jede URL, die in der White-list aufgeführt ist, aktiviert Links zu lokalen Dateien auf Webseiten mit diesen Adressen. * lässt jede Url zu. Leer lässt keine Url zu. Mehrere URLs werden mit Leerzeichen getrennt. Wildcards sind zuläassig z.B. *://*.trello.com/*", 8 | "description": "Settings description for whitelist" 9 | }, 10 | "enableExecutables_title": { 11 | "message": "Aktiviert Links zu lokalen ausführbaren Dateien", 12 | "description": "Settings title for enable of executable files" 13 | }, 14 | "enableExecutables_description": { 15 | "message": "Wenn aktiviert, kann jedes Programm vom Addon gestartet werden. (Achtung! Eine Seite von einem Betrüger könnte das für einen Denial-Of-Service-Angriff verwenden.)", 16 | "description": "Settings description for executable files" 17 | }, 18 | "enableLinkIcons_title": { 19 | "message": "Aktiviert Link icons", 20 | "description": "Settings title for enable link icons" 21 | }, 22 | "enableLinkIcons_description": { 23 | "message": "Wenn aktiviert, wird ein Link-Icon jedem lokalen File-Link hinzugefügt.", 24 | "description": "Settings description for link icons" 25 | }, 26 | "revealOpenOption_title": { 27 | "message": "Standard Link-Text Klick Verhalten", 28 | "description": "Settings title for default link click behaviour" 29 | }, 30 | "revealOpenOption_description": { 31 | "message": "Verändert das Standard Verhalten bei einem Klick auf einen File-link. Default = Link direkt öffnen.", 32 | "description": "Settings description for default click behaviour" 33 | }, 34 | "revealOpenOption_options_Open": { 35 | "message": "Link direkt öffnen", 36 | "description": "Setting open link directly" 37 | }, 38 | "revealOpenOption_options_Reveal": { 39 | "message": "Beinhaltenden Ordner öffnen", 40 | "description": "Setting reveal link" 41 | }, 42 | "revealOpenOption_options_Direct": { 43 | "message": "Link direkt im Browser öffnen", 44 | "description": "Setting direct open" 45 | }, 46 | "retries_on_failure_title": { 47 | "message": "Wiederholungen bei Fehlern", 48 | "description": "Settings title for retries on failure" 49 | }, 50 | "retries_on_failure_description": { 51 | "message": "Die Anzahl an Versuchen bevor ein Fehler angezeigt wird (z.B. wird der Fehler \"Konnte Datei nicht öffnen\" erst angezeigt wenn alle Versuche fehlgeschlagen sind)", 52 | "description": "Settings description for retries on failure" 53 | }, 54 | "ERROR_EXECTUBALES_NOT_ENABLED": { 55 | "message": "Sie versuchen ein ausführbare Datei zu starten. Bitte prüfen Sie die Addon Einstellungen und aktivieren Sie ausführbare Dateien und versuchen Sie es erneut.", 56 | "description": "Error message EXE not enabled" 57 | }, 58 | "ERROR_BAD_LINK": { 59 | "message": "Konnte Datei nicht öffnen $URL$", 60 | "description": "Error message bad link", 61 | "placeholders": { 62 | "url": { 63 | "content": "$1", 64 | "example": "file://" 65 | } 66 | } 67 | }, 68 | "INFO_CONFIG_CHANGED_SMB": { 69 | "message": "Konfiguration geändert! SMB links sind jetzt aktiviert.", 70 | "description": "Info message SMB configured (not used yet)" 71 | }, 72 | "LABEL_CONTEXT_MENU_OPEN_LINK": { 73 | "message": "Öffne Link", 74 | "description": "Label text open link" 75 | }, 76 | "LABEL_CONTEXT_MENU_OPEN_CONTAINING": { 77 | "message": "Öffne beinhaltendes Verzeichnis", 78 | "description": "Label text open containing folder" 79 | }, 80 | "LABEL_CONTEXT_MENU_OPEN_DIRECT": { 81 | "message": "Öffne im Browser", 82 | "description": "Label text open in browser" 83 | }, 84 | 85 | "LABEL_CONTEXT_SUB_SELECTION_TITLE": { 86 | "message": "Link addon Markierung", 87 | "description": "Label text selection in context menu" 88 | }, 89 | 90 | "LABEL_CONTEXT_SUB_LINK_TITLE": { 91 | "message": "Link addon", 92 | "description": "Label text context menu item" 93 | }, 94 | 95 | "LABEL_ADDONBAR_ICON_HOVER": { 96 | "message": "Local link addon (aktuelles Tab: $ACTIVE$)", 97 | "description": "Status icon hover text", 98 | "placeholders": { 99 | "active": { 100 | "content": "$1", 101 | "example": "active" 102 | } 103 | } 104 | }, 105 | 106 | "LABEL_ADDONBAR_HOVER_STATE_active": { 107 | "message": "aktiv", 108 | "description": "Status text active hover" 109 | }, 110 | "LABEL_ADDONBAR_HOVER_STATE_inactive": { 111 | "message": "inaktiv", 112 | "description": "Status text inactive hover" 113 | }, 114 | 115 | "TOOLTIP_OPEN_FOLDER": { 116 | "message": "Öffne Verzeichnis", 117 | "description": "Tooltip text open folder" 118 | }, 119 | "TOOLTIP_OPEN_LINK": { 120 | "message": "Öffne Link", 121 | "description": "Tooltip text open link" 122 | }, 123 | "TOOLTIP_OPEN_IN_BROWSER": { 124 | "message": "Öffne Link im Browser", 125 | "description": "Tooltip text open in browser" 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('webpack').Configuration} */ 2 | const path = require('path'); 3 | const webpack = require('webpack'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 6 | const WriteFilePlugin = require('write-file-webpack-plugin'); 7 | const FriendlyErrors = require('friendly-errors-webpack-plugin'); 8 | 9 | // var FF = process.env.BROWSER === 'Firefox'; // needed for custom stuff in manifest for Firefox 10 | 11 | const manifestFiles = { 12 | firefox: 'manifest.firefox.json', 13 | chrome: 'manifest.chrome.json' 14 | }; 15 | 16 | const manifestFileName = manifestFiles[process.env.BROWSER || 'firefox']; // default to firefox 17 | 18 | module.exports = { 19 | entry: { 20 | app: './src/main.js', 21 | background: './src/extension/background/index.js', 22 | options: './src/extension/options.js', 23 | content: './src/extension/content.js' 24 | }, 25 | output: { 26 | path: path.resolve(__dirname, './dist'), 27 | filename: '[name].js' 28 | }, 29 | mode: 'none', 30 | module: { 31 | rules: [ 32 | { 33 | test: /\.js$/, 34 | loader: 'babel-loader', 35 | exclude: /node_modules/ 36 | }, 37 | { 38 | test: /\.html$/, 39 | loader: 'vue-template-loader', 40 | // We don't want to pass `src/index.html` file to this loader. 41 | exclude: /(index|options|background).html/ 42 | }, 43 | { 44 | test: /\.css$/, 45 | use: ['style-loader', 'css-loader'] 46 | }, 47 | { 48 | test: /\.(png|jpg|gif|svg)$/, 49 | loader: 'file-loader', 50 | options: { 51 | name: '[name].[ext]?[hash]' 52 | } 53 | } 54 | ] 55 | }, 56 | resolve: { 57 | alias: { 58 | vue$: 'vue/dist/vue.esm.js' 59 | } 60 | }, 61 | devServer: { 62 | historyApiFallback: true, 63 | noInfo: true, 64 | writeToDisk: true 65 | }, 66 | performance: { 67 | hints: false 68 | }, 69 | devtool: 'source-map', 70 | plugins: [ 71 | // new webpack.optimize.OccurrenceOrderPlugin(), 72 | // We're using process (polyfill for webpack 5 needed) 73 | new webpack.ProvidePlugin({ 74 | process: 'process/browser' 75 | }), 76 | new CopyWebpackPlugin({ 77 | patterns: [ 78 | { 79 | // copy locale 80 | from: 'src/extension/_locales', 81 | to: '_locales' 82 | }, 83 | { 84 | from: 'src/static' 85 | }, 86 | { 87 | from: 'src/assets' 88 | }, 89 | { 90 | from: 'src/installed.*', 91 | to: '[name][ext]' 92 | }, 93 | // {output}/file.txt 94 | { 95 | from: `src/${manifestFileName}`, 96 | to: 'manifest.json', 97 | transform: function(content, path) { 98 | // add description & version from package.json 99 | // let json = JSON.parse(content.toString('utf8')); 100 | 101 | // if (FF) { 102 | // Object.assign(json, manifestAdditionsFF); 103 | // } 104 | 105 | return JSON.stringify( 106 | Object.assign( 107 | {}, 108 | JSON.parse(content.toString('utf8')), 109 | { 110 | description: 111 | process.env.npm_package_description, 112 | version: 113 | process.env.npm_package_version || 114 | '0.0.1' 115 | } 116 | ), 117 | null, 118 | 2 119 | ); 120 | } 121 | } 122 | ] 123 | }), 124 | // https://github.com/ampedandwired/html-webpack-plugin 125 | new HtmlWebpackPlugin({ 126 | filename: 'index.html', 127 | template: 'index.html', 128 | // chunksSortMode: 'none', 129 | chunks: ['app'], // , 'webpack-manifest'], 130 | inject: true 131 | }), 132 | new HtmlWebpackPlugin({ 133 | template: path.join(__dirname, 'src', 'background.html'), 134 | filename: 'background.html', 135 | // chunksSortMode: 'none', 136 | chunks: ['background'] 137 | }), 138 | new HtmlWebpackPlugin({ 139 | template: path.join(__dirname, 'src', 'options.html'), 140 | filename: 'options.html', 141 | chunksSortMode: 'none', 142 | chunks: ['options'] 143 | }), 144 | new WriteFilePlugin(), 145 | new FriendlyErrors() 146 | ] 147 | }; 148 | 149 | if (process.env.NODE_ENV === 'production') { 150 | module.exports.devtool = 'nosources-source-map'; 151 | // http://vue-loader.vuejs.org/en/workflow/production.html 152 | module.exports.plugins = (module.exports.plugins || []).concat([ 153 | new webpack.DefinePlugin({ 154 | 'process.env': { 155 | NODE_ENV: '"production"' 156 | } 157 | }) 158 | ]); 159 | } 160 | -------------------------------------------------------------------------------- /src/extension/background/EventHandlers.js: -------------------------------------------------------------------------------- 1 | import * as CONSTANTS from '../constants'; 2 | import { showInstallationTab } from './checkInstallation'; 3 | import notify from './notify'; 4 | import { prepareWhitelist } from './helpers/whitelist'; 5 | 6 | const { defaultSettings, DELAY_BETWEEN_RETRIES } = CONSTANTS; 7 | 8 | /** Event handler methods of the extension */ 9 | export class ExtensionEventHandlers { 10 | /** Initialize EventHandler 11 | * @param {object} settings reference to app settings. 12 | */ 13 | constructor(settings) { 14 | this.settings = settings; 15 | this.retriesOnFailure = 0; 16 | } 17 | 18 | /** Global Error handler 19 | * @param {object} err error object 20 | * @returns {undefined} 21 | */ 22 | static onError(err) { 23 | // console.log('error handler:', err.name, err.message, err.stack, 24 | // err.lineNumber); // todo - check that really the connection to the native app isn't open 25 | const nativeAppNotInstalled = err.message.includes('disconnected port') 26 | ? ' Please check that you have installed the native app. ' + 27 | 'See installation guide in addon-bar ' + 28 | 'menu.' 29 | : ''; 30 | 31 | // console.log('error', err); 32 | notify(err.name, err.message + '.' + nativeAppNotInstalled); 33 | } 34 | 35 | /** 36 | * Send native message with retries 37 | * @param {object} request 38 | * @param {string} uri 39 | */ 40 | static sendNativeMessage(request, uri, handler) { 41 | browser.runtime 42 | .sendNativeMessage( 43 | // direct sending --> opens port to native app 44 | 'webextension_local_filesystem_links', 45 | { 46 | url: uri, 47 | reveal: request.reveal, 48 | exeAllowed: handler.settings.enableExecutables 49 | } 50 | ) 51 | .then(function(response) { 52 | // console.log('received response', response); 53 | if (response && response.error) { 54 | if ( 55 | handler.retriesOnFailure >= 56 | handler.settings.retriesOnFailure 57 | ) { 58 | const msg = browser.i18n.getMessage( 59 | response.error, 60 | window.decodeURI(response.url) 61 | ); 62 | 63 | notify('Error', msg); // only NotFound error at the moment 64 | } else { 65 | setTimeout(() => { 66 | ExtensionEventHandlers.sendNativeMessage( 67 | request, 68 | uri, 69 | handler 70 | ); 71 | handler.retriesOnFailure++; 72 | }, DELAY_BETWEEN_RETRIES); 73 | } 74 | } 75 | }) 76 | .catch(err => { 77 | const nativeAppNotInstalled = err.message.includes( 78 | 'disconnected port' 79 | ) 80 | ? ' Please check that you have installed ' + 81 | 'the native app. ' + 82 | 'See installation guide in addon-bar ' + 83 | 'menu.' 84 | : ''; 85 | 86 | // console.log('error', err); 87 | notify(err.name, err.message + '.' + nativeAppNotInstalled); 88 | }); //ExtensionEventHandlers.onError(err)); 89 | } 90 | 91 | /** 92 | * Handler for content script messages 93 | * @param {object} request information about the request (e.g. action) 94 | * @param {object} sender sender info 95 | * @param {callback} sendResponse sends response to content script. 96 | * @returns {undefined} 97 | */ 98 | onMessage(request, sender, sendResponse) { 99 | switch (request.action) { 100 | case 'showInstallInfoTab': 101 | showInstallationTab(); 102 | break; 103 | case 'open': 104 | var uri = request.url; 105 | console.log('opening', uri); 106 | 107 | if (request.directOpen) { 108 | // setting commented at the moment --> re-add later 109 | browser.tabs.create({ 110 | active: true, 111 | url: window.decodeURI(uri) // illegal URL --> not priveleged to add file:// - fix later 112 | }); 113 | } else { 114 | this.retriesOnFailure = 0; // reset failure count 115 | ExtensionEventHandlers.sendNativeMessage( 116 | request, 117 | uri, 118 | this 119 | ); 120 | } 121 | break; 122 | default: 123 | } 124 | } 125 | 126 | /** Handler for app settingss loaded 127 | * @param {object} settings reference to settings of extension 128 | * @param {function} callback do somehing with the loaded settings 129 | * @returns {undefined} 130 | */ 131 | onSettingsLoaded(settings, callback) { 132 | const loadedSettings = Object.assign({}, defaultSettings, settings); 133 | const whitelist = loadedSettings.whitelist.trim() 134 | ? prepareWhitelist(loadedSettings.whitelist.trim()) 135 | : []; 136 | // const whitelist = ['*']; //['http://127.0.0.1:3000/*', '*://*.localhost/*', '*://*.google.de/*', '*://*.trello.com/*']; 137 | 138 | callback(loadedSettings, whitelist); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /native-host/src/subprocess_fix.py: -------------------------------------------------------------------------------- 1 | ## issue: https://bugs.python.org/issue19264 2 | import os 3 | import ctypes 4 | import subprocess 5 | import _subprocess 6 | from ctypes import byref, windll, c_char_p, c_wchar_p, c_void_p, \ 7 | Structure, sizeof, c_wchar, WinError 8 | from ctypes.wintypes import BYTE, WORD, LPWSTR, BOOL, DWORD, LPVOID, \ 9 | HANDLE 10 | 11 | 12 | ## 13 | ## Types 14 | ## 15 | 16 | CREATE_UNICODE_ENVIRONMENT = 0x00000400 17 | LPCTSTR = c_char_p 18 | LPTSTR = c_wchar_p 19 | LPSECURITY_ATTRIBUTES = c_void_p 20 | LPBYTE = ctypes.POINTER(BYTE) 21 | 22 | class STARTUPINFOW(Structure): 23 | _fields_ = [ 24 | ("cb", DWORD), ("lpReserved", LPWSTR), 25 | ("lpDesktop", LPWSTR), ("lpTitle", LPWSTR), 26 | ("dwX", DWORD), ("dwY", DWORD), 27 | ("dwXSize", DWORD), ("dwYSize", DWORD), 28 | ("dwXCountChars", DWORD), ("dwYCountChars", DWORD), 29 | ("dwFillAtrribute", DWORD), ("dwFlags", DWORD), 30 | ("wShowWindow", WORD), ("cbReserved2", WORD), 31 | ("lpReserved2", LPBYTE), ("hStdInput", HANDLE), 32 | ("hStdOutput", HANDLE), ("hStdError", HANDLE), 33 | ] 34 | 35 | LPSTARTUPINFOW = ctypes.POINTER(STARTUPINFOW) 36 | 37 | 38 | class PROCESS_INFORMATION(Structure): 39 | _fields_ = [ 40 | ("hProcess", HANDLE), ("hThread", HANDLE), 41 | ("dwProcessId", DWORD), ("dwThreadId", DWORD), 42 | ] 43 | 44 | LPPROCESS_INFORMATION = ctypes.POINTER(PROCESS_INFORMATION) 45 | 46 | 47 | class DUMMY_HANDLE(ctypes.c_void_p): 48 | 49 | def __init__(self, *a, **kw): 50 | super(DUMMY_HANDLE, self).__init__(*a, **kw) 51 | self.closed = False 52 | 53 | def Close(self): 54 | if not self.closed: 55 | windll.kernel32.CloseHandle(self) 56 | self.closed = True 57 | 58 | def __int__(self): 59 | return self.value 60 | 61 | 62 | CreateProcessW = windll.kernel32.CreateProcessW 63 | CreateProcessW.argtypes = [ 64 | LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, 65 | LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, 66 | LPSTARTUPINFOW, LPPROCESS_INFORMATION, 67 | ] 68 | CreateProcessW.restype = BOOL 69 | 70 | 71 | ## 72 | ## Patched functions/classes 73 | ## 74 | 75 | def CreateProcess(executable, args, _p_attr, _t_attr, 76 | inherit_handles, creation_flags, env, cwd, 77 | startup_info): 78 | """Create a process supporting unicode executable and args for win32 79 | 80 | Python implementation of CreateProcess using CreateProcessW for Win32 81 | 82 | """ 83 | 84 | si = STARTUPINFOW( 85 | dwFlags=startup_info.dwFlags, 86 | wShowWindow=startup_info.wShowWindow, 87 | cb=sizeof(STARTUPINFOW), 88 | ## XXXvlab: not sure of the casting here to ints. 89 | hStdInput=int(startup_info.hStdInput), 90 | hStdOutput=int(startup_info.hStdOutput), 91 | hStdError=int(startup_info.hStdError), 92 | ) 93 | 94 | wenv = None 95 | if env is not None: 96 | ## LPCWSTR seems to be c_wchar_p, so let's say CWSTR is c_wchar 97 | env = (unicode("").join([ 98 | unicode("%s=%s\0") % (k, v) 99 | for k, v in env.items()])) + unicode("\0") 100 | wenv = (c_wchar * len(env))() 101 | wenv.value = env 102 | 103 | pi = PROCESS_INFORMATION() 104 | creation_flags |= CREATE_UNICODE_ENVIRONMENT 105 | 106 | if CreateProcessW(executable, args, None, None, 107 | inherit_handles, creation_flags, 108 | wenv, cwd, byref(si), byref(pi)): 109 | return (DUMMY_HANDLE(pi.hProcess), DUMMY_HANDLE(pi.hThread), 110 | pi.dwProcessId, pi.dwThreadId) 111 | raise WinError() 112 | 113 | 114 | class Popen(subprocess.Popen): 115 | """This superseeds Popen and corrects a bug in cPython 2.7 implem""" 116 | 117 | def _execute_child(self, args, executable, preexec_fn, close_fds, 118 | cwd, env, universal_newlines, 119 | startupinfo, creationflags, shell, to_close, 120 | p2cread, p2cwrite, 121 | c2pread, c2pwrite, 122 | errread, errwrite): 123 | """Code from part of _execute_child from Python 2.7 (9fbb65e) 124 | 125 | There are only 2 little changes concerning the construction of 126 | the the final string in shell mode: we preempt the creation of 127 | the command string when shell is True, because original function 128 | will try to encode unicode args which we want to avoid to be able to 129 | sending it as-is to ``CreateProcess``. 130 | 131 | """ 132 | if not isinstance(args, subprocess.types.StringTypes): 133 | args = subprocess.list2cmdline(args) 134 | 135 | if startupinfo is None: 136 | startupinfo = subprocess.STARTUPINFO() 137 | if shell: 138 | startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW 139 | startupinfo.wShowWindow = _subprocess.SW_HIDE 140 | comspec = os.environ.get("COMSPEC", unicode("cmd.exe")) 141 | args = unicode('{} /c "{}"').format(comspec, args) 142 | if (_subprocess.GetVersion() >= 0x80000000 or 143 | os.path.basename(comspec).lower() == "command.com"): 144 | w9xpopen = self._find_w9xpopen() 145 | args = unicode('"%s" %s') % (w9xpopen, args) 146 | creationflags |= _subprocess.CREATE_NEW_CONSOLE 147 | 148 | super(Popen, self)._execute_child(args, executable, 149 | preexec_fn, close_fds, cwd, env, universal_newlines, 150 | startupinfo, creationflags, False, to_close, p2cread, 151 | p2cwrite, c2pread, c2pwrite, errread, errwrite) 152 | 153 | _subprocess.CreateProcess = CreateProcess 154 | -------------------------------------------------------------------------------- /native-host/build/windows/InnoSetupScript.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | [Setup] 5 | ; NOTE: The value of AppId uniquely identifies this application. 6 | ; Do not use the same AppId value in installers for other applications. 7 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 8 | 9 | SignTool=signtool 10 | #define AppVersion GetFileVersion("D:\github\webextension_local_filesystem_links\native-host\bin\win32\local-link-messaging-host\local-link-messaging-host.exe") 11 | #define AppName "Local file links Native Messaging API Host" 12 | 13 | AppId={{318A38DD-A431-42F0-BBAB-58C330AC545F} 14 | AppName={#AppName} v{#AppVersion} 15 | AppVerName={#AppName} {#AppVersion} 16 | VersionInfoVersion={#AppVersion} 17 | AppVersion={#AppVersion} 18 | ;AppVerName=Local file links Native Messaging API Host 19 | AppPublisher=feinstaub/webextension_local_filesystem_links 20 | AppPublisherURL=https://github.com/feinstaub/webextension_local_filesystem_links 21 | AppSupportURL=https://github.com/feinstaub/webextension_local_filesystem_links 22 | AppUpdatesURL=https://github.com/feinstaub/webextension_local_filesystem_links 23 | DefaultDirName={%USERPROFILE}\{#AppName} 24 | DisableDirPage=yes 25 | DefaultGroupName=Local file links Native Messaging API Host 26 | DisableProgramGroupPage=yes 27 | OutputDir=D:\github\webextension_local_filesystem_links\native-host\bin\win32 28 | OutputBaseFilename=native-app-setup 29 | Compression=lzma 30 | UninstallDisplayIcon=D:\github\webextension_local_filesystem_links\native-host\src\addon_icon_48.ico 31 | SetupIconFile=D:\github\webextension_local_filesystem_links\native-host\src\addon_icon_48.ico 32 | SolidCompression=yes 33 | PrivilegesRequired=lowest 34 | 35 | [Tasks] 36 | Name: Visualc; Description: Install Visual C++ re-distributable (required for the app - install if not already available); Flags: unchecked 37 | 38 | [Languages] 39 | Name: "english"; MessagesFile: "compiler:Default.isl" 40 | 41 | [Files] 42 | Source: "D:\github\webextension_local_filesystem_links\native-host\bin\win32\local-link-messaging-host\*"; DestDir: "{app}" 43 | Source: "D:\github\webextension_local_filesystem_links\native-host\src\webextension_local_filesystem_links_win.json"; DestDir: "{app}"; Flags: ignoreversion 44 | Source: "D:\github\webextension_local_filesystem_links\native-host\build\windows\vcredist_x86.exe"; DestDir: "{app}"; AfterInstall: RunOtherInstaller; Tasks: Visualc; Flags: ignoreversion 45 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 46 | 47 | [Icons] 48 | ; Name: "{group}\Local file links Native Messaging API Host"; Filename: "{app}\local-link-messaging-host.exe" 49 | 50 | [Registry] 51 | Root: HKLM; Subkey: "Software\Mozilla\NativeMessagingHosts\webextension_local_filesystem_links"; ValueType: string; ValueName: ""; ValueData: "{app}\webextension_local_filesystem_links_win.json"; Flags: uninsdeletekey; Check: not IsWin64 and isElevated 52 | Root: HKLM64; Subkey: "Software\Mozilla\NativeMessagingHosts\webextension_local_filesystem_links"; ValueType: string; ValueName: ""; ValueData: "{app}\webextension_local_filesystem_links_win.json"; Flags: uninsdeletekey; Check: IsWin64 and IsElevated 53 | Root: HKCU; Subkey: "Software\Mozilla\NativeMessagingHosts\webextension_local_filesystem_links"; ValueType: string; ValueName: ""; ValueData: "{app}\webextension_local_filesystem_links_win.json"; Flags: uninsdeletekey; Check: not IsElevated; 54 | 55 | [Code] 56 | var 57 | Page: TInputOptionWizardPage; 58 | InstallationOnlyMe: Boolean; 59 | 60 | procedure InitializeWizard; 61 | begin 62 | // Create the page 63 | Page := CreateInputOptionPage(wpWelcome, 64 | 'Installation type', 'Install for all users or only current user?', 65 | 'By selecting "All users" it will install the native app to program folder which requires elevated rights.', 66 | True, False); 67 | 68 | // Add items 69 | Page.Add('Only current user'); 70 | Page.Add('All users'); 71 | 72 | 73 | // Set initial values (default to current unser) 74 | Page.Values[0] := True; 75 | end; 76 | 77 | // check if elevated 78 | function IsElevated: Boolean; 79 | begin 80 | Result := IsAdminLoggedOn or IsPowerUserLoggedOn; 81 | end; 82 | 83 | procedure ExitProcess(uExitCode: UINT); 84 | external 'ExitProcess@kernel32.dll stdcall'; 85 | function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string; 86 | lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle; 87 | external 'ShellExecuteW@shell32.dll stdcall'; 88 | 89 | // elevate installer 90 | // code from here https://stackoverflow.com/questions/21556853/make-inno-setup-installer-request-privileges-elevation-only-when-needed 91 | // --> slightly modified 92 | // NOT working and not used - at the moment just an info that admin rights are required to install for all users. 93 | function Elevate: Boolean; 94 | var 95 | I: Integer; 96 | RetVal: Integer; 97 | Params: string; 98 | S: string; 99 | begin 100 | { Collect current instance parameters } 101 | for I := 1 to ParamCount do 102 | begin 103 | S := ParamStr(I); 104 | { Unique log file name for the elevated instance } 105 | if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then 106 | begin 107 | S := S + '-elevated'; 108 | end; 109 | { Do not pass our /SL5 switch } 110 | if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then 111 | begin 112 | Params := Params + AddQuotes(S) + ' '; 113 | end; 114 | end; 115 | 116 | { ... and add selected language } 117 | // Params := Params + '/LANG=' + ActiveLanguage; 118 | 119 | //Log(Format('Elevating setup with parameters [%s]', [Params])); 120 | Log(ExpandConstant('{srcexe}')); 121 | //RetVal := ShellExecute(0, 'runas', ExpandConstant('{srcexe}'), Params, '', SW_SHOW); 122 | RetVal := ShellExecute(WizardForm.handle, 'runas', ExpandConstant('{srcexe}'), '', '', SW_SHOW); 123 | Log(Format('Running elevated setup returned [%d]', [RetVal])); 124 | Result := (RetVal > 32); 125 | { if elevated executing of this setup succeeded, then... } 126 | if Result then 127 | begin 128 | Log('Elevation succeeded'); 129 | { exit this non-elevated setup instance } 130 | ExitProcess(0); 131 | end 132 | else 133 | begin 134 | Log(Format('Elevation failed [%s]', [SysErrorMessage(RetVal)])); 135 | end; 136 | end; 137 | 138 | function NextButtonClick(CurPageID: Integer): Boolean; 139 | var dest: String; 140 | var res: Boolean; 141 | begin 142 | 143 | res := True 144 | Log('NextButtonClick(' + IntToStr(CurPageID) + ') called'); 145 | if (CurPageID = 100) then 146 | begin 147 | // Read values into variables 148 | InstallationOnlyMe := Page.Values[0]; 149 | if InstallationOnlyMe then 150 | dest := ExpandConstant('{%USERPROFILE}\{#AppName}'); 151 | 152 | if not InstallationOnlyMe or (isElevated and WizardSilent) then 153 | // selected all user or running silently with elevated right 154 | dest := ExpandConstant('{pf}\{#AppName}'); 155 | //if IsElevated = False then 156 | // elevate 157 | //end; 158 | //WriteRegKey 159 | 160 | //test := IsElevated 161 | // todo --> request elevated rights for pf 162 | WizardForm.DirEdit.Text := dest; 163 | if IsElevated or InstallationOnlyMe then 164 | res := True 165 | else 166 | begin 167 | MsgBox('Administrator privileges required to install for all users. Please restart setup with the correct rights or install for current user.',mbError, MB_OK) 168 | res := False 169 | end; 170 | end; 171 | Result := res 172 | end; 173 | 174 | // check HKCU for onlyMe or HKLM for allUsers 175 | function CheckKeyLocation() : Boolean; 176 | //var 177 | // Version: TWindowsVersion; 178 | begin 179 | Result := InstallationOnlyMe; 180 | end; 181 | 182 | procedure RunOtherInstaller; 183 | 184 | var 185 | ResultCode: Integer; 186 | 187 | begin 188 | if not ShellExec('runas', ExpandConstant('{app}\vcredist_x86.exe'), '', '', SW_SHOW, 189 | ewWaitUntilTerminated, ResultCode) 190 | then 191 | MsgBox('Other installer failed to run!' + #13#10 + 192 | SysErrorMessage(ResultCode), mbError, MB_OK); 193 | end; 194 | 195 | -------------------------------------------------------------------------------- /native-host/src/local-link-messaging-host.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2012 The Chromium Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | 7 | # A native messaging host. 8 | 9 | import struct 10 | import sys 11 | import json 12 | import urllib 13 | import subprocess 14 | from subprocess import PIPE 15 | import os 16 | import re 17 | from pathlib2 import Path 18 | 19 | currentOS = sys.platform 20 | 21 | fileExplorers = { 22 | "win32": { 23 | "open": r'cmd /c', 24 | "reveal": { 25 | "cmd": r'cmd /c explorer', 26 | "arg": r'/select,' 27 | } 28 | }, 29 | "linux": [{ 30 | # Ubunutu 31 | "open": r'xdg-open', 32 | "reveal": { 33 | "cmd": r'nautilus', # not perfect to use directly nautilus but xdg-open is not supporting select option 34 | "arg": r'--select ' 35 | } 36 | }, 37 | { 38 | # Open SUSE 39 | "open": r'xdg-open', 40 | "reveal": { 41 | "cmd": r'dolphin', 42 | "arg": r'--select ' 43 | } 44 | }], 45 | "mac": { 46 | "open": r'open', 47 | "reveal": { 48 | "cmd": r'open', 49 | "arg": r'--reveal ' 50 | } 51 | } 52 | } 53 | 54 | fileExplorer = fileExplorers['linux'][1] # default to linux 55 | 56 | # On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY 57 | # to avoid unwanted modifications of the input/output streams. 58 | if currentOS == "win32": 59 | # import win32api # if active state python is installed or install pywin32 package seperately 60 | import os, msvcrt 61 | import sys 62 | # from get_binary_type import GetBinaryType 63 | import pywintypes 64 | import win32api 65 | from subprocess_fix import Popen 66 | 67 | msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) 68 | msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) 69 | 70 | fileExplorer = fileExplorers['win32'] 71 | 72 | def is_exe(fpath): 73 | # just msi files are still executed - com, exe, bat files are blocked 74 | # send_message('{"debug": "hello"}') 75 | # helpful resource http://timgolden.me.uk/python/win32_how_do_i/tell-if-a-file-is-executable.html 76 | try: 77 | # print "Looking at", filePath 78 | r, executable = win32api.FindExecutable(fpath) 79 | executable = win32api.GetLongPathName(executable).lower() 80 | except pywintypes.error: 81 | # print "Neither executable nor document" # e.g. just a path 82 | return False 83 | else: 84 | return executable == fpath.lower() 85 | else: 86 | from subprocess import Popen 87 | 88 | # helper to check if cmd exists (e.g. Nautilus or Dolphin) 89 | def cmd_exists(cmd): 90 | return subprocess.call("type " + cmd, shell=True, 91 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0 92 | 93 | # Helper for checking if file is exec. returns file if executable (for unix) 94 | def is_exe(fpath): 95 | return os.path.exists(fpath) and os.access(fpath, os.X_OK) and os.path.isfile(fpath) 96 | 97 | if sys.platform.startswith('linux'): 98 | fileExplorer = fileExplorers['linux'] 99 | 100 | if cmd_exists(fileExplorer[0]['reveal']['cmd']): 101 | fileExplorer = fileExplorer[0] 102 | elif cmd_exists(fileExplorer[1]['reveal']['cmd']): 103 | fileExplorer = fileExplorer[1] 104 | else: 105 | # no match fallback to default -- just reveal not working 106 | fileExplorer = fileExplorer[0] 107 | elif sys.platform == 'darwin': 108 | fileExplorer = fileExplorers['mac'] 109 | #send_message(u'{"debug os": "%s"}' % sys.platform) #urllib.quote(pathStr.encode('utf-8'))) 110 | 111 | 112 | # Helper function that sends a message to the webapp. 113 | def send_message(message): 114 | # Write message size. 115 | sys.stdout.write(struct.pack('I', len(message))) 116 | # Write the message itself. 117 | sys.stdout.write(message) 118 | sys.stdout.flush() 119 | 120 | def preparePath(pathStr): 121 | # replace backslashes to slashes 122 | pathStr = re.sub(r'\\', r'/', pathStr) 123 | # send_message('{"debug prepare": "%s"}' % pathStr.encode('utf-8')) 124 | 125 | if currentOS == "win32": 126 | # add feature to allow 4 slashes too for UNC network addresses 127 | regex = r'\bfile:(\/\/){2}\b'; 128 | 129 | #4 slashes? add another one to have 5 slashes 130 | if re.match(regex, pathStr): 131 | pathStr = re.sub("(%s)" % regex, r'\1/', pathStr) 132 | 133 | # pathStr = re.sub(r'file:[\/]{2,3}', '', pathStr) # remove file:// (also any leading / needs to be removed in windows) 134 | pathStr = re.sub(r'[a-z]*:[\/]{2,3}', '', pathStr) # remove file:// (also any leading / needs to be removed in windows) 135 | else: 136 | pathStr = re.sub(r'[a-z]*:[\/]{2}', '', pathStr) # remove file:// 137 | 138 | # pathStr = urllib.unquote(pathStr).decode('utf8') # why was this here? 139 | if sys.platform.startswith('linux') or sys.platform == 'darwin': 140 | # hack to have ~ path working in Linux & mac os 141 | # one or two slashes before ~ // stop at first / after ~ 142 | # unixPath = unixPath.replace(/(\/){1,2}~\//, '~/'); # code from previous addon 143 | pathStr = re.sub(r'[/]{1,2}~/', '~/', pathStr) 144 | pathStr = os.path.expanduser(pathStr) # expand ~ to home/username 145 | 146 | pathStr = os.path.normpath(pathStr) # normalize slashes ----- not working? 147 | return pathStr 148 | 149 | # Helper for check if path or file exists 150 | def checkPath(pathStr): 151 | pathStr = preparePath(pathStr) 152 | path_to_open = Path(pathStr) 153 | # send_message(u'{"debug before match": "%s"}' % urllib.quote(pathStr)) 154 | # send_message(u'{"debug match": "%s"}' % pathStr.startswith('//')) 155 | if currentOS == 'win32' and os.path.exists(pathStr) is False: 156 | # and url.startswith('//') would be good to test but it wasn't working --> re-check later 157 | # windows and two slashes --> UNC link detected (special check required because os.path.exists fails on //servername/) 158 | p = Popen(["net", "view", pathStr], shell=True, 159 | stdin=PIPE, stdout=PIPE, stderr=PIPE) 160 | out, err = p.communicate() 161 | 162 | validUNC = False if err else True 163 | else: 164 | validUNC = False 165 | 166 | return os.path.exists(pathStr) or validUNC 167 | 168 | def getFilePath(program, exeAllowed): 169 | filePath = preparePath(program) 170 | 171 | if is_exe(filePath) is True and exeAllowed is False: 172 | send_message('{"error": "ERROR_EXECTUBALES_NOT_ENABLED"}') 173 | return None 174 | else: 175 | return filePath 176 | 177 | def createResponse(): 178 | send_message('{"error": %s}' % "null") 179 | 180 | def openFile(command): 181 | # command = u"explorer c:\\tmp\\áéíóú.txt" 182 | # send_message(r'{"debug openfile": "%s"}' % urllib.quote(command.encode('utf-8'))) 183 | p = Popen(command, shell=True, 184 | stdin=PIPE, stdout=PIPE, stderr=PIPE) 185 | out, err = p.communicate() 186 | 187 | # Thread that reads messages from the webapp. 188 | def read_thread_func(queue): 189 | message_number = 0 190 | while 1: 191 | # Read the message length (first 4 bytes). 192 | text_length_bytes = sys.stdin.read(4) 193 | 194 | if len(text_length_bytes) == 0: 195 | sys.exit(0) 196 | 197 | # Unpack message length as 4 byte integer. 198 | text_length = struct.unpack("i", text_length_bytes)[0] 199 | 200 | # Read the text (JSON object) of the message. 201 | text = sys.stdin.read(text_length).decode('utf-8') 202 | 203 | data = json.loads(text) 204 | 205 | fileStr = data['url'] 206 | reveal = data['reveal'] 207 | 208 | exeAllowed = data['exeAllowed'] 209 | # send_message(u"{\"debug\": \"%s\"}" % urllib.quote(fileStr.encode('utf-8'))) 210 | if (checkPath(fileStr)): 211 | result = getFilePath(fileStr, exeAllowed) 212 | if (reveal): 213 | openFile(fileExplorer['reveal']['cmd'] + ' ' + fileExplorer['reveal']['arg'] + "\"%s\"" % result) 214 | else: 215 | if result is not None: 216 | openFile(u"%s \"%s\"" % (fileExplorer['open'], result)) 217 | else: 218 | send_message('{"error": %s }' % "EXE_ACCESS_DENIED") # todo pass error from getFilePath 219 | else: 220 | # send_message(u"{\"debug not found\": \"%s\"}" % urllib.quote(fileStr.encode('utf-8'))) 221 | if (reveal): 222 | result = getFilePath(fileStr, exeAllowed) 223 | revealPath = os.path.dirname(result) 224 | openFile(fileExplorer['open'] + " \"%s\"" % revealPath) 225 | else: 226 | send_message('{"error": "%s", "url": "%s"}' % ("ERROR_BAD_LINK", fileStr)) 227 | 228 | createResponse() # default response 229 | sys.exit(0) 230 | 231 | def Main(): 232 | read_thread_func(None) 233 | sys.exit(0) 234 | 235 | if __name__ == '__main__': 236 | Main() 237 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Changelog for Local Filesystem Links 2 | ==================================== 3 | v0.101.0 4 | ------- 5 | * FIX: Multiple windows issue 125 6 | * IMPROVED: Title handling issue 183 7 | * FIX: Web-ext and all dependencies mentioned by dependabot (reconfigured dependabot from master to develop as target for easier workflow in the future) 8 | 9 | v0.100.2 10 | ------- 11 | * IMPROVED: Fix Issue 161 12 | - Added retry on failure option (default one retry - max. delay of error display 100ms + default opening time) 13 | 14 | v0.99.64 15 | -------- 16 | * FIX: Issue 125 17 | - Added dynamic link handling & debounced link click event handler (reduce the risk of firing multiple events) 18 | 19 | v0.99.62 20 | -------- 21 | * FIX: Issue 127 cont.: 22 | - Updated dependencies 23 | - Modified webpack config for new webpack-click 24 | - Removed vue-loader (*.vue) and changed to vue-template-loader 25 | - Tested build with Ubuntu, Windows and Debian OpenSUSE Tumbleweed - three identical bundles (Note: Changed Windows to checkout LF instead of CRLF.) 26 | 27 | v0.99.61 28 | -------- 29 | * FIX: Issue 127 - Changed css scoping of Vue files because of an AMO review issue. IDs of scopes are not identical - build not reproducible. Removed scoping && added css classes manually. 30 | 31 | v0.99.60 32 | -------- 33 | * removed source maps & minification - fixed issue #126 34 | * changed to jquery 3.x - fixed issue #123 35 | * New package with build from source instructions for Mozilla review 36 | 37 | v0.99.59 38 | -------- 39 | * Added MacOS support (SMB support still in progress) 40 | * Added info to post-install page for white-listing with ports as mentioned in issue #115 / #118. 41 | * IMPROVED: Content script injection to avoid multiple opened files (fixes issue #108 & #113) 42 | * Disabled dynamically added link icons - performance issues at some pages (will be re-added later, see issue #109) 43 | * FIX: Issue 92 - XML files are not handled by the extension so the XML viewer is working as expected. 44 | 45 | v0.99.57 46 | -------- 47 | **Available Features** 48 | First compatible version with webextension stlye that's required for FF >= 57. A large re-write of the background scripts and a new native app (currently supporting Linux & Windows - iOS planned) was necessary. 49 | * Native app for link opening (wasn't required in previous versions - currently supported OS are **Windows & Linux**) - requires manual installation (download link see post-installation page of the extension) 50 | * Link opening & revealing (same as before) 51 | * White-list urls (match pattern slightly different - see info in post-install guide) 52 | * Prevention of executable link execution (some improvements for Windows req. - .msi files can be opened) 53 | * Activity indication with addonbar icon 54 | * Addon-bar menu for faster access to settings 55 | * Settings page (almost as before) 56 | * UNC links are supported e.g. //servename/directory (SMB protocoll still not implemented but should be possible now) - root directory issue still present as reported in issue #90. More investigation required.) 57 | 58 | ** Missing features (added in future release) ** 59 | * [MISSING]: Native app support for MacOS (extension not usable at MacOS with-out the app - probably easy to implement but I don't have access to a test setup with that OS. Still trying to install OSx in VM ware.) 60 | * [MISSING]: Right click context menu 61 | * [MISSING]: Link text selection open via context menu 62 | * [MISSING]: In browser opening option (e.g. show supported types directly in Firefox like images, PDFs,...) 63 | 64 | v0.99.47 65 | -------- 66 | * FIX: Issue #84 - Accents are working now. Re-added decodeURIComponent. Changed env. var handling (improve later) 67 | * IMPROVED: 68 | Performance improvement, Issue #74, now 800 or more local file links in a page are supported - 69 | Links are still added to invisible links because handling of later addition seems too complicated. 70 | * NEW: Direct open in browser 71 | Files like jpg, txt, pdf, etc. can be directly opened in browser - accessible with context menu or 72 | by default link behaviour change 73 | * NEW: Environment path variables are supported e.g. %HOMEDRIVE% for Windows and $HOME$ for Linux - 74 | Note: Links with env. var needs to use %25 for % and %24 for $ in href attr. (will be improved later) 75 | e.g. for Windows %HOMEPATH%/ 76 | 77 | v0.99.46 78 | -------- 79 | * IMPROVED: Better link scanning with jQuery Observe 80 | Trello links are working now. See issue #56 81 | * FIX: Path handling with-out NS_ERROR_FILE_UNRECOGNIZED_PATH in console 82 | * FIX: Non standard backslash links are working now. See issue #57 83 | * FIX: Added directory check - fix for false executable notification #72 84 | * CHECKED: Addon is multi-process compatible, see issue #48 85 | * SECURITY: Added option to enable links to executable files (default is disabled) 86 | See issue #16 87 | * TECH: Added code linting (using eslint with google style) - runs with gulp or gulp lint or npm run lint 88 | * CHANGE: New icon style with scaling to text - see issue #53 / #63 89 | * FEATURE: Environment path variables are now possible - see issue #22 90 | * FEATURE: Added Addonbar icon for easier access to config & to visualize if current tab is whitelisted 91 | * FEATURE: Added localization (languages English, German & Russian) 92 | Russian translation contributed by lmaodzedun 93 | * FEATURE: New option to change default text link click behaviour (open/reveal) 94 | 95 | 96 | v0.99.42 97 | -------- 98 | * CLEANUP: remove jquery and other useless files, cleanup code 99 | * Major cleanup and rewrite by AWolf81 100 | * FEATURE: Click the hyperlink text as opposed to clicking the icon, #11 101 | * FEATURE: Optionally hide the icons, #36 102 | * FEATURE: Have both: "Open containing folder" and "Open file" #32 103 | 104 | 105 | v0.99.38 106 | -------- 107 | * FIX: "no longer works with Firefox 39 or later" 108 | https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/37 109 | * NEW: "Automatically react on DOM changes" 110 | The folder icon is now added even if the page is updated via Javascript 111 | https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/24 112 | * CHANGE: The toolbar icon does not work anymore (technical issue, might be fixed later). 113 | This means the custom Options page (not the one reachable from the addons page) 114 | cannot be shown anymore. 115 | https://github.com/feinstaub/firefox_addon_local_filesystem_links/commit/bdef48140cc2a5106a4f9302fe9fdd733a8c743c 116 | Thanks to sweoggy for contributing. 117 | 118 | 119 | v0.99.37 (since v0.99.25) 120 | ------------------------ 121 | * CHANGE: Open links in default program instead of file explorer #16 122 | https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/16 123 | Initial patch provided by EnriqueSoria 124 | * CHANGE: Open folders directly instead of just selecting it 125 | * CHANGE: Linux: support file:/// (with only 3 instead of 4 slashes) 126 | https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/31 127 | * NEW: README.md gives more detailed instructions of how to dev this addon 128 | * TECH: upgrade to sdk-1.17 and fix deprecations 129 | 130 | 131 | v0.99.25 (since v0.99.22) 132 | ------------------------ 133 | * NEW: add option to Add-on preferences to exclude user-defined URLs from hyperlink scanning 134 | (https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/4) 135 | * FIX: display version 136 | (https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/9) 137 | 138 | 139 | v0.99.22 (since v0.98) 140 | --------------------- 141 | * FIX: No icon if page is served from local drive (https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/15) 142 | * NEW: Show addon version in toolbarpanel (https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/9) 143 | * TECH: upgrade to sdk-1.14 144 | 145 | 146 | v0.981 (since v0.98) 147 | ------------------- 148 | * Add a button "Rescan" to the toolbar panel that rescans a page and 149 | finds hyperlinks that were added dynamically. 150 | 151 | 152 | v0.98 (since v0.97) 153 | ------------------ 154 | * Upgrade to jetpack-sdk-1.10 155 | * Fix issue #8: Page layout is shaky. (https://github.com/feinstaub/firefox_addon_local_filesystem_links/issues/8) 156 | * Update documentation 157 | * Fix issue #5: "Prevent Reloading of Page" when working with Plone. 158 | 159 | 160 | v0.97 (since v0.96) 161 | ----------------- 162 | * add support for Linux 163 | 164 | 165 | v0.8 (since v0.64) 166 | ----------------- 167 | * NEW: Add Options page with basic options 168 | * Several minor fixes 169 | * Fix issue#2 "Blanks in path" 170 | * EXPERIMENTAL: grid for options 171 | 172 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | --------------------------------------------------------------------------------