This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
coding:utilities [2008/07/31 12:38] 127.0.0.1 external edit |
coding:utilities [2011/03/02 13:40] (current) robm IE2FF comments fix |
||
|---|---|---|---|
| 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 VMwareOpenHost.exe, | ||
| + | that, so this was written.) | ||
| + | |||
| + | WINDOWS-SIDE INSTALLATION | ||
| + | ========================= | ||
| + | |||
| + | 1. Change ``giHOST`` to match your server-side hostname | ||
| + | 2. Call this script with --install | ||
| + | |||
| + | 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 ===== | ||