#!/usr/bin/env python from __future__ import print_function import os import sys import json import struct import subprocess VERSION = '7.1b2' try: sys.stdin.buffer # Python 3.x version # Read a message from stdin and decode it. def getMessage(): rawLength = sys.stdin.buffer.read(4) if len(rawLength) == 0: sys.exit(0) messageLength = struct.unpack('@I', rawLength)[0] message = sys.stdin.buffer.read(messageLength).decode('utf-8') return json.loads(message) # Send an encoded message to stdout def sendMessage(messageContent): encodedContent = json.dumps(messageContent).encode('utf-8') encodedLength = struct.pack('@I', len(encodedContent)) sys.stdout.buffer.write(encodedLength) sys.stdout.buffer.write(encodedContent) sys.stdout.buffer.flush() except AttributeError: # Python 2.x version (if sys.stdin.buffer is not defined) # Read a message from stdin and decode it. def getMessage(): rawLength = sys.stdin.read(4) if len(rawLength) == 0: sys.exit(0) messageLength = struct.unpack('@I', rawLength)[0] message = sys.stdin.read(messageLength) return json.loads(message) # Send an encoded message to stdout def sendMessage(messageContent): encodedContent = json.dumps(messageContent) encodedLength = struct.pack('@I', len(encodedContent)) sys.stdout.write(encodedLength) sys.stdout.write(encodedContent) sys.stdout.flush() def install(): home_path = os.getenv('HOME') manifest = { 'name': 'open_with', 'description': 'Open With native host', 'path': os.path.realpath(__file__), 'type': 'stdio', } locations = { 'chrome': os.path.join(home_path, '.config', 'google-chrome', 'NativeMessagingHosts'), 'chromium': os.path.join(home_path, '.config', 'chromium', 'NativeMessagingHosts'), 'firefox': os.path.join(home_path, '.mozilla', 'native-messaging-hosts'), } filename = 'open_with.json' for browser, location in locations.items(): if os.path.exists(os.path.dirname(location)): if not os.path.exists(location): os.mkdir(location) browser_manifest = manifest.copy() if browser == 'firefox': browser_manifest['allowed_extensions'] = ['openwith@darktrojan.net'] else: browser_manifest['allowed_origins'] = [ 'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', # Chrome 'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', # Opera ] with open(os.path.join(location, filename), 'w') as file: file.write( json.dumps(browser_manifest, indent=2, separators=(',', ': '), sort_keys=True).replace(' ', '\t') + '\n' ) def _read_desktop_file(path): with open(path, 'r') as desktop_file: current_section = None name = None command = None for line in desktop_file: if line[0] == '[': current_section = line[1:-2] if current_section != 'Desktop Entry': continue if line.startswith('Name='): name = line[5:].strip() elif line.startswith('Exec='): command = line[5:].strip() return { 'name': name, 'command': command } def find_browsers(): apps = [ 'Chrome', 'Chromium', 'chromium-browser', 'firefox', 'Firefox', 'Google Chrome', 'google-chrome', 'opera', 'Opera', 'SeaMonkey', 'seamonkey', ] paths = [ os.path.join(os.getenv('HOME'), '.local/share/applications'), '/usr/local/share/applications', '/usr/share/applications' ] suffix = '.desktop' results = [] for p in paths: for a in apps: fp = os.path.join(p, a) + suffix if os.path.exists(fp): results.append(_read_desktop_file(fp)) return results def listen(): receivedMessage = getMessage() if receivedMessage == 'ping': sendMessage({ 'version': VERSION, 'file': os.path.realpath(__file__) }) elif receivedMessage == 'find': sendMessage(find_browsers()) else: for k, v in os.environ.items(): if k.startswith('MOZ_'): try: os.unsetenv(k) except: os.environ[k] = '' devnull = open(os.devnull, 'w') subprocess.Popen(receivedMessage, stdout=devnull, stderr=devnull) sendMessage(None) if __name__ == '__main__': if len(sys.argv) == 2: if sys.argv[1] == 'install': install() sys.exit(0) elif sys.argv[1] == 'find_browsers': print(find_browsers()) sys.exit(0) allowed_extensions = [ 'openwith@darktrojan.net', 'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', 'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', ] for ae in allowed_extensions: if ae in sys.argv: listen() sys.exit(0) print('Open With native helper, version %s.' % VERSION)