This shows you the differences between two versions of the page.
Next revision Both sides next revision | |||
coding:utilities [2008/07/31 12:38] 127.0.0.1 external edit |
coding:utilities [2011/03/01 16:19] robm Added IE2FF, which intercepts Internet Explorer invocations and forwards them (over TCP/IP) to another browser, e.g. Firefox. Useful when using WinXP via a VM at work. |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Utilities ====== | ====== Utilities ====== | ||
A collection of scripts and the like which I have come to rely on. | A collection of scripts and the like which I have come to rely on. | ||
+ | |||
+ | ====== IE2FF ====== | ||
+ | <code python> | ||
+ | # | ||
+ | """ | ||
+ | URL-click forwarder (Windows -> Linux). | ||
+ | |||
+ | This script catches URL clicks (actually iexplore.exe invokations) and | ||
+ | forwards them over TCP/IP to a Linux machine which launches them in the | ||
+ | default browser (e.g. Firefox). | ||
+ | |||
+ | This was written so that clicking a URL in, say, MS Outlook in a WinXP VM | ||
+ | would open the page in the host Linux' | ||
+ | that via VMwareOpenHose.exe, | ||
+ | that, so this was written.) | ||
+ | |||
+ | WINDOWS-SIDE INSTALLATION | ||
+ | ========================= | ||
+ | |||
+ | 1. Update paths in IE2FF.reg as appropriate | ||
+ | 2. Install IE2FF.reg (e.g. ``regedit IE2FF.reg``) | ||
+ | |||
+ | LINUX-SIDE INSTALLATION | ||
+ | ======================= | ||
+ | |||
+ | 1. Run the script without arguments | ||
+ | |||
+ | TODO: Use Python-Win32 modules to implement a Win32 DDE server to catch | ||
+ | special invocations, | ||
+ | |||
+ | TCP/IP PROTOCOL | ||
+ | =============== | ||
+ | |||
+ | The protocol uses endpoint readiness to signal when processing has been | ||
+ | completed. This relies on the behaviour of ``recv()``, which blocks until data | ||
+ | is available (returns a non-empty string) or the local READ endpoint has been | ||
+ | closed by the remote end (returns an empty string). | ||
+ | |||
+ | 1. Client: | ||
+ | |||
+ | a. Connects to server | ||
+ | b. Transmits URL data as ASCII-encoded text | ||
+ | c. Closes WRITE end-point | ||
+ | d. Starts spinning on recv() | ||
+ | |||
+ | 2. Server: | ||
+ | |||
+ | a. Waits for a connection | ||
+ | b. Spins on recv() until it returns an empty string | ||
+ | c. Closes WRITE end-point | ||
+ | d. Spins on recv() | ||
+ | e. Closes connection | ||
+ | |||
+ | 3. Client: | ||
+ | |||
+ | a. Finishes spinning on recv() | ||
+ | b. Closes connection. | ||
+ | """ | ||
+ | __docformat__ = " | ||
+ | |||
+ | giPORT = 43233 # That's IE2FF in T9 (predictive text, as on a phone) | ||
+ | giHOST = " | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def regedit(rRegistryFragment): | ||
+ | import os | ||
+ | import tempfile | ||
+ | |||
+ | import subprocess as sp | ||
+ | |||
+ | assert os.name == " | ||
+ | |||
+ | rRegistryFragment = os.linesep.join( rRegistryFragment.splitlines() ) | ||
+ | |||
+ | rTF = tempfile.mktemp() | ||
+ | |||
+ | try: | ||
+ | with file(rTF, " | ||
+ | sTF.write( rRegistryFragment.encode(" | ||
+ | sTF.flush() | ||
+ | |||
+ | # Seems we must close the file or regedit cannot read it. Go figure. | ||
+ | |||
+ | sPH = sp.Popen([ | ||
+ | " | ||
+ | "/ | ||
+ | sTF.name]) | ||
+ | |||
+ | iRetVal = sPH.wait() | ||
+ | |||
+ | finally: | ||
+ | if os.path.exists(rTF): | ||
+ | os.unlink(rTF) | ||
+ | |||
+ | return iRetVal == 0 | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def install(): | ||
+ | import os | ||
+ | import sys | ||
+ | from textwrap import dedent | ||
+ | |||
+ | # Note that backslashes have to be escaped, and double-escaped between a | ||
+ | # drive letter and a path. | ||
+ | |||
+ | rRegistryFragment = dedent(R""" | ||
+ | Windows Registry Editor Version 5.00 | ||
+ | |||
+ | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\iexplore.exe] | ||
+ | " | ||
+ | |||
+ | """ | ||
+ | (os.path.abspath( sys.executable ) | ||
+ | .replace(": | ||
+ | .replace(" | ||
+ | |||
+ | (os.path.abspath( install.func_code.co_filename ) | ||
+ | .replace(": | ||
+ | .replace(" | ||
+ | ) | ||
+ | |||
+ | if regedit(rRegistryFragment): | ||
+ | print " | ||
+ | else: | ||
+ | print " | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def uninstall(): | ||
+ | from textwrap import dedent | ||
+ | |||
+ | # Note that backslashes have to be escaped, and double-escaped between a | ||
+ | # drive letter and a path. | ||
+ | |||
+ | rRegistryFragment = dedent(R""" | ||
+ | Windows Registry Editor Version 5.00 | ||
+ | |||
+ | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\iexplore.exe] | ||
+ | |||
+ | """ | ||
+ | |||
+ | if regedit(rRegistryFragment): | ||
+ | print " | ||
+ | else: | ||
+ | print " | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def server(): | ||
+ | """ | ||
+ | Launch URLs sent via TCP/IP using ``gnome-open``. | ||
+ | """ | ||
+ | import socket | ||
+ | import subprocess as sp | ||
+ | |||
+ | sSock = socket.socket() | ||
+ | sSock.bind( ("", | ||
+ | sSock.listen(1) | ||
+ | |||
+ | print " | ||
+ | |||
+ | while True: | ||
+ | sConn, tAddr = sSock.accept() | ||
+ | |||
+ | rMessage = "" | ||
+ | while True: | ||
+ | rData = sConn.recv(1024) | ||
+ | if rData == "": | ||
+ | break | ||
+ | rMessage += rData | ||
+ | |||
+ | sConn.shutdown( socket.SHUT_WR ) # Indicate finished | ||
+ | |||
+ | # Spin until remote side is also finished | ||
+ | while sConn.recv(1024) != "": | ||
+ | pass | ||
+ | |||
+ | sConn.close() | ||
+ | |||
+ | print rMessage | ||
+ | |||
+ | sPH = sp.Popen([ | ||
+ | " | ||
+ | rMessage]) | ||
+ | |||
+ | sPH.wait() | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def client(): | ||
+ | R""" | ||
+ | ``sys.argv`` should look like so: | ||
+ | |||
+ | 0. ``H: | ||
+ | 1. ``C: | ||
+ | 2. May be absent. If present, should be one of: | ||
+ | |||
+ | a. ``-nofile``, | ||
+ | b. ``http:// | ||
+ | """ | ||
+ | import sys | ||
+ | |||
+ | if len(sys.argv) < 3 or sys.argv[2] == " | ||
+ | # TODO: Implement fallback behaviour (start local browser?) | ||
+ | return | ||
+ | |||
+ | rMessage = sys.argv[2] | ||
+ | |||
+ | import socket | ||
+ | import subprocess as sp | ||
+ | |||
+ | sConn = socket.socket() | ||
+ | sConn.connect( (giHOST, giPORT) ) | ||
+ | sConn.sendall( rMessage ) | ||
+ | sConn.shutdown( socket.SHUT_WR ) # Indicate finished | ||
+ | |||
+ | # Spin until remote side is also finished | ||
+ | while sConn.recv(1024) != "": | ||
+ | pass | ||
+ | |||
+ | sConn.close() | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | def main(): | ||
+ | import platform | ||
+ | from optparse import OptionParser | ||
+ | |||
+ | sParser = OptionParser( | ||
+ | description=" | ||
+ | x.strip() for x in | ||
+ | """ | ||
+ | This script catches URL clicks (actually iexplore.exe | ||
+ | invocations) on a Windows machine and forwards them over | ||
+ | TCP/IP to a Linux machine (also running this script) which | ||
+ | launches them in the default browser (e.g. Firefox). | ||
+ | """ | ||
+ | ) | ||
+ | ) | ||
+ | |||
+ | sParser.add_option( | ||
+ | " | ||
+ | action=" | ||
+ | dest=" | ||
+ | help=" | ||
+ | " | ||
+ | default=False) | ||
+ | |||
+ | sParser.add_option( | ||
+ | " | ||
+ | action=" | ||
+ | dest=" | ||
+ | help=" | ||
+ | " | ||
+ | default=False) | ||
+ | |||
+ | # Parse command line | ||
+ | sOptions, lArgs = sParser.parse_args() | ||
+ | |||
+ | if sOptions.yInstall: | ||
+ | install() | ||
+ | |||
+ | if sOptions.yUninstall: | ||
+ | uninstall() | ||
+ | |||
+ | if platform.system() == " | ||
+ | server() | ||
+ | else: | ||
+ | client() | ||
+ | |||
+ | # ----------------------------------------------------------------------------- | ||
+ | if __name__ == " | ||
+ | main() | ||
+ | </ | ||
+ | |||
===== BASH shell ===== | ===== BASH shell ===== |