1#!/usr/bin/env python 2from __future__ import print_function 3 4import os 5import sys 6import json 7import struct 8import subprocess 9 10VERSION = '7.1b2' 11 12try: 13 sys.stdin.buffer 14 15 # Python 3.x version 16 # Read a message from stdin and decode it. 17 def getMessage(): 18 rawLength = sys.stdin.buffer.read(4) 19 if len(rawLength) == 0: 20 sys.exit(0) 21 messageLength = struct.unpack('@I', rawLength)[0] 22 message = sys.stdin.buffer.read(messageLength).decode('utf-8') 23 return json.loads(message) 24 25 # Send an encoded message to stdout 26 def sendMessage(messageContent): 27 encodedContent = json.dumps(messageContent).encode('utf-8') 28 encodedLength = struct.pack('@I', len(encodedContent)) 29 30 sys.stdout.buffer.write(encodedLength) 31 sys.stdout.buffer.write(encodedContent) 32 sys.stdout.buffer.flush() 33 34except AttributeError: 35 # Python 2.x version (if sys.stdin.buffer is not defined) 36 # Read a message from stdin and decode it. 37 def getMessage(): 38 rawLength = sys.stdin.read(4) 39 if len(rawLength) == 0: 40 sys.exit(0) 41 messageLength = struct.unpack('@I', rawLength)[0] 42 message = sys.stdin.read(messageLength) 43 return json.loads(message) 44 45 # Send an encoded message to stdout 46 def sendMessage(messageContent): 47 encodedContent = json.dumps(messageContent) 48 encodedLength = struct.pack('@I', len(encodedContent)) 49 50 sys.stdout.write(encodedLength) 51 sys.stdout.write(encodedContent) 52 sys.stdout.flush() 53 54 55def install(): 56 home_path = os.getenv('HOME') 57 58 manifest = { 59 'name': 'open_with', 60 'description': 'Open With native host', 61 'path': os.path.realpath(__file__), 62 'type': 'stdio', 63 } 64 locations = { 65 'chrome': os.path.join(home_path, '.config', 'google-chrome', 'NativeMessagingHosts'), 66 'chromium': os.path.join(home_path, '.config', 'chromium', 'NativeMessagingHosts'), 67 'firefox': os.path.join(home_path, '.mozilla', 'native-messaging-hosts'), 68 } 69 filename = 'open_with.json' 70 71 for browser, location in locations.items(): 72 if os.path.exists(os.path.dirname(location)): 73 if not os.path.exists(location): 74 os.mkdir(location) 75 76 browser_manifest = manifest.copy() 77 if browser == 'firefox': 78 browser_manifest['allowed_extensions'] = ['openwith@darktrojan.net'] 79 else: 80 browser_manifest['allowed_origins'] = [ 81 'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/', # Chrome 82 'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/', # Opera 83 ] 84 85 with open(os.path.join(location, filename), 'w') as file: 86 file.write( 87 json.dumps(browser_manifest, indent=2, separators=(',', ': '), sort_keys=True).replace(' ', '\t') + '\n' 88 ) 89 90 91def _read_desktop_file(path): 92 with open(path, 'r') as desktop_file: 93 current_section = None 94 name = None 95 command = None 96 for line in desktop_file: 97 if line[0] == '[': 98 current_section = line[1:-2] 99 if current_section != 'Desktop Entry':100 continue101102 if line.startswith('Name='):103 name = line[5:].strip()104 elif line.startswith('Exec='):105 command = line[5:].strip()106107 return {108 'name': name,109 'command': command110 }111112113def find_browsers():114 apps = [115 'Chrome',116 'Chromium',117 'chromium-browser',118 'firefox',119 'Firefox',120 'Google Chrome',121 'google-chrome',122 'opera',123 'Opera',124 'SeaMonkey',125 'seamonkey',126 ]127 paths = [128 os.path.join(os.getenv('HOME'), '.local/share/applications'),129 '/usr/local/share/applications',130 '/usr/share/applications'131 ]132 suffix = '.desktop'133134 results = []135 for p in paths:136 for a in apps:137 fp = os.path.join(p, a) + suffix138 if os.path.exists(fp):139 results.append(_read_desktop_file(fp))140 return results141142143def listen():144 receivedMessage = getMessage()145 if receivedMessage == 'ping':146 sendMessage({147 'version': VERSION,148 'file': os.path.realpath(__file__)149 })150 elif receivedMessage == 'find':151 sendMessage(find_browsers())152 else:153 for k, v in os.environ.items():154 if k.startswith('MOZ_'):155 try:156 os.unsetenv(k)157 except:158 os.environ[k] = ''159160 devnull = open(os.devnull, 'w')161 subprocess.Popen(receivedMessage, stdout=devnull, stderr=devnull)162 sendMessage(None)163164165if __name__ == '__main__':166 if len(sys.argv) == 2:167 if sys.argv[1] == 'install':168 install()169 sys.exit(0)170 elif sys.argv[1] == 'find_browsers':171 print(find_browsers())172 sys.exit(0)173174 allowed_extensions = [175 'openwith@darktrojan.net',176 'chrome-extension://cogjlncmljjnjpbgppagklanlcbchlno/',177 'chrome-extension://fbmcaggceafhobjkhnaakhgfmdaadhhg/',178 ]179 for ae in allowed_extensions:180 if ae in sys.argv:181 listen()182 sys.exit(0)183184 print('Open With native helper, version %s.' % VERSION)