diff --git a/gitso/trunk/ArgsParser.py b/gitso/trunk/ArgsParser.py index e96eca7..8e7c402 100644 --- a/gitso/trunk/ArgsParser.py +++ b/gitso/trunk/ArgsParser.py @@ -43,7 +43,7 @@ class ArgsParser: self.paths['mode'] = '' self.paths['low-colors'] = False - if sys.platform.find('linux') != -1: + if re.match('(?:open|free|net)bsd|linux',sys.platform): self.paths['main'] = os.path.join(sys.path[0], '..', 'share', 'gitso') self.paths['copyright'] = os.path.join(sys.path[0], '..', 'share', 'doc', 'gitso', 'COPYING') elif sys.platform == "darwin": diff --git a/gitso/trunk/ConnectionWindow.py b/gitso/trunk/ConnectionWindow.py index 39ba8e4..b0eba76 100644 --- a/gitso/trunk/ConnectionWindow.py +++ b/gitso/trunk/ConnectionWindow.py @@ -50,7 +50,7 @@ class ConnectionWindow(wx.Frame): # Disable until 0.7 release self.enablePMP = False - if sys.platform.find('linux') != -1: + if re.match('(?:open|free|net)bsd|linux',sys.platform): width = 165 height = 350 xval1 = 155 @@ -88,7 +88,7 @@ class ConnectionWindow(wx.Frame): self.Bind(wx.EVT_RADIOBUTTON, self.RadioToggle, id=self.rb2.GetId()) # checkbox for natpmp - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.enablePMP: self.cb1 = wx.CheckBox(self, -1, 'Use NAT-PMP', (130, 48)) self.cb1.Enable(False) @@ -135,7 +135,7 @@ class ConnectionWindow(wx.Frame): menuBar.Append(fileMenu, "&File") menuBar.Append(editMenu, "&Edit") - if sys.platform.find('linux') != -1 or sys.platform == 'win32': + if re.match('(?:open|free|net)bsd|linux',sys.platform) or sys.platform == 'win32': menuBar.Append(helpMenu, "&Help") self.SetMenuBar(menuBar) @@ -174,14 +174,14 @@ class ConnectionWindow(wx.Frame): self.ToggleValue = 0 self.hostField.Enable(True) self.cb2.Enable(False) - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.enablePMP: self.cb1.Enable(False) else: self.ToggleValue = 1 self.hostField.Enable(False) self.cb2.Enable(True) - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.enablePMP: self.cb1.Enable(True) diff --git a/gitso/trunk/GitsoThread.py b/gitso/trunk/GitsoThread.py index 8d9eeae..0a65d7c 100755 --- a/gitso/trunk/GitsoThread.py +++ b/gitso/trunk/GitsoThread.py @@ -27,7 +27,7 @@ import threading, time import os, sys, signal, os.path import Processes -if sys.platform == 'darwin' or sys.platform.find('linux') != -1: +if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): import NATPMP class GitsoThread(threading.Thread): @@ -59,7 +59,7 @@ class GitsoThread(threading.Thread): self.error = True else: # Give Support - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.window.enablePMP: self.window.cb1.Enable(False) if self.window.cb1.GetValue() == True: @@ -99,7 +99,7 @@ class GitsoThread(threading.Thread): @author: Aaron Gerber """ - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.window.enablePMP: if self.window.rb1.GetValue() == False: #give support if self.window.cb1.GetValue() == True: @@ -122,7 +122,7 @@ class GitsoThread(threading.Thread): connection = [] listen = [] - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.host <> "": connection = os.popen('LANG=C netstat -an | grep 5500 | grep ESTABLISHED').readlines() else: @@ -149,7 +149,7 @@ class GitsoThread(threading.Thread): @author: Dennis Koot """ - if sys.platform == 'darwin' or sys.platform.find('linux') != -1: + if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform): if self.window.enablePMP: if action == 'request': lifetime = 3600 diff --git a/gitso/trunk/NATPMP.py b/gitso/trunk/NATPMP.py index 7012987..479272c 100644 --- a/gitso/trunk/NATPMP.py +++ b/gitso/trunk/NATPMP.py @@ -15,16 +15,19 @@ For more information on NAT-PMP, see the NAT-PMP draft specification: http://files.dns-sd.org/draft-cheshire-nat-pmp.txt Requires Python 2.3 or later. -Tested on Python 2.3, 2.4, 2.5 against Apple AirPort Express. +Tested on Python 2.5, 2.6 against Apple AirPort Express. +0.2.2 - changed gateway autodetect, per github issue #1. thanks to jirib +0.2 - changed useException to use_exception, responseDataClass to response_data_class parameters in function calls for consistency +0.1 - repackaged via setuptools. Fixed major bug in gateway detection. Experimental gateway detection support for Windows 7. Python 2.6 testing. 0.0.1.2 - NT autodetection code. Thanks to roee shlomo for the gateway detection regex! 0.0.1.1 - Removed broken mutex code 0.0.1 - Initial release """ -__version__ = "0.0.1.2" -__license__ = """Copyright (c) 2008, Yiming Liu, All rights reserved. +__version__ = "0.2" +__license__ = """Copyright (c) 2008-2010, Yiming Liu, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -49,9 +52,9 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.""" -__author__ = "Yiming Liu " +__author__ = "Yiming Liu " -import struct, socket, select, time +import struct, socket, select, time, platform import sys, os, re NATPMP_PORT = 5351 @@ -199,19 +202,18 @@ def get_gateway_addr(): It does not guarantee correct results. This function requires the presence of - netstat on the path on POSIX and NT. It requires ip on - Linux. + netstat on the path on POSIX and NT. """ addr = "" shell_command = 'netstat -rn' if os.name == "posix": - pattern = re.compile('default\s+([\w.:]+)\s+\w') - if "linux" in sys.platform: - shell_command = "ip route show" - pattern = re.compile('default via\s+([\w.:]+)\s+\w') + pattern = re.compile('(?:default|0\.0\.0\.0|::/0)\s+([\w\.:]+)\s+.*UG') elif os.name == "nt": - pattern = re.compile(".*?Default Gateway:[ ]+(.*?)\n") - system_out = os.popen(shell_command, 'r').read() # TODO: this could be a security issue + if platform.version().startswith("6.1"): + pattern = re.compile(".*?0.0.0.0[ ]+0.0.0.0[ ]+(.*?)[ ]+?.*?\n") + else: + pattern = re.compile(".*?Default Gateway:[ ]+(.*?)\n") + system_out = os.popen(shell_command, 'r').read() if not system_out: raise NATPMPNetworkError(NATPMP_GATEWAY_CANNOT_FIND, error_str(NATPMP_GATEWAY_CANNOT_FIND)) match = pattern.search(system_out) @@ -243,7 +245,7 @@ def get_gateway_socket(gateway): response_socket.connect((gateway, NATPMP_PORT)) return response_socket -def get_public_address(gateway_ip=get_gateway_addr(), retry=9): +def get_public_address(gateway_ip=None, retry=9): """A high-level function that returns the public interface IP of the current host by querying the NAT-PMP gateway. IP is returned as string. @@ -255,9 +257,11 @@ def get_public_address(gateway_ip=get_gateway_addr(), retry=9): retry - the number of times to retry the request if unsuccessful. Defaults to 9 as per specification. """ + if gateway_ip == None: + gateway_ip = get_gateway_addr() addr = None addr_request = PublicAddressRequest() - addr_response = send_request_with_retry(gateway_ip, addr_request, responseDataClass=PublicAddressResponse, retry=retry) + addr_response = send_request_with_retry(gateway_ip, addr_request, response_data_class=PublicAddressResponse, retry=retry) if addr_response.result != 0: #sys.stderr.write("NAT-PMP error %d: %s\n" % (addr_response.result, error_str(addr_response.result))) #sys.stderr.flush() @@ -265,7 +269,7 @@ def get_public_address(gateway_ip=get_gateway_addr(), retry=9): addr = addr_response.ip return addr -def map_tcp_port(public_port, private_port, lifetime=3600, gateway_ip=get_gateway_addr(), retry=9, useException=True): +def map_tcp_port(public_port, private_port, lifetime=3600, gateway_ip=None, retry=9, use_exception=True): """A high-level wrapper to map_port() that requests a mapping for a public TCP port on the NAT to a private TCP port on this host. Returns the complete response on success. @@ -279,12 +283,12 @@ def map_tcp_port(public_port, private_port, lifetime=3600, gateway_ip=get_gatewa get_gateway_addr() retry - the number of times to retry the request if unsuccessful. Defaults to 9 as per specification. - useException - throw an exception if an error result is + use_exception - throw an exception if an error result is received from the gateway. Defaults to True. """ - return map_port(NATPMP_PROTOCOL_TCP, public_port, private_port, lifetime, gateway_ip=gateway_ip, retry=retry, useException=useException) + return map_port(NATPMP_PROTOCOL_TCP, public_port, private_port, lifetime, gateway_ip=gateway_ip, retry=retry, use_exception=use_exception) -def map_udp_port(public_port, private_port, lifetime=3600, gateway_ip=get_gateway_addr(), retry=9, useException=True): +def map_udp_port(public_port, private_port, lifetime=3600, gateway_ip=None, retry=9, use_exception=True): """A high-level wrapper to map_port() that requests a mapping for a public UDP port on the NAT to a private UDP port on this host. Returns the complete response on success. @@ -298,12 +302,12 @@ def map_udp_port(public_port, private_port, lifetime=3600, gateway_ip=get_gatewa get_gateway_addr() retry - the number of times to retry the request if unsuccessful. Defaults to 9 as per specification. - useException - throw an exception if an error result is + use_exception - throw an exception if an error result is received from the gateway. Defaults to True. """ - return map_port(NATPMP_PROTOCOL_UDP, public_port, private_port, lifetime, gateway_ip=gateway_ip, retry=retry, useException=useException) + return map_port(NATPMP_PROTOCOL_UDP, public_port, private_port, lifetime, gateway_ip=gateway_ip, retry=retry, use_exception=use_exception) -def map_port(protocol, public_port, private_port, lifetime=3600, gateway_ip=get_gateway_addr(), retry=9, useException=True): +def map_port(protocol, public_port, private_port, lifetime=3600, gateway_ip=None, retry=9, use_exception=True): """A function to map public_port to private_port of protocol. Returns the complete response on success. @@ -317,15 +321,17 @@ def map_port(protocol, public_port, private_port, lifetime=3600, gateway_ip=get_ get_gateway_addr() retry - the number of times to retry the request if unsuccessful. Defaults to 9 as per specification. - useException - throw an exception if an error result + use_exception - throw an exception if an error result is received from the gateway. Defaults to True. """ if protocol not in [NATPMP_PROTOCOL_UDP, NATPMP_PROTOCOL_TCP]: raise ValueError("Must be either NATPMP_PROTOCOL_UDP or NATPMP_PROTOCOL_TCP") + if gateway_ip == None: + gateway_ip = get_gateway_addr() response = None port_mapping_request = PortMapRequest(protocol, private_port, public_port, lifetime) - port_mapping_response = send_request_with_retry(gateway_ip, port_mapping_request, responseDataClass=PortMapResponse, retry=retry) - if port_mapping_response.result != 0 and useException: + port_mapping_response = send_request_with_retry(gateway_ip, port_mapping_request, response_data_class=PortMapResponse, retry=retry) + if port_mapping_response.result != 0 and use_exception: raise NATPMPResultError(port_mapping_response.result, error_str(port_mapping_response.result), port_mapping_response) return port_mapping_response @@ -342,7 +348,7 @@ def read_response(gateway_socket, timeout, responseSize=16): data,source_addr = resp_socket.recvfrom(responseSize) return data,source_addr -def send_request_with_retry(gateway_ip, request, responseDataClass=None, retry=9): +def send_request_with_retry(gateway_ip, request, response_data_class=None, retry=9): gateway_socket = get_gateway_socket(gateway_ip) n = 1 data = "" @@ -354,8 +360,8 @@ def send_request_with_retry(gateway_ip, request, responseDataClass=None, retry=9 n += 1 if n >= retry and not data: raise NATPMPUnsupportedError(NATPMP_GATEWAY_NO_SUPPORT, error_str(NATPMP_GATEWAY_NO_SUPPORT)) - if data and responseDataClass: - data = responseDataClass(data) + if data and response_data_class: + data = response_data_class(data) return data diff --git a/gitso/trunk/Processes.py b/gitso/trunk/Processes.py index 2ee9a9a..aa9aba0 100644 --- a/gitso/trunk/Processes.py +++ b/gitso/trunk/Processes.py @@ -35,7 +35,7 @@ class Processes: def getSupport(self, host): if sys.platform == 'darwin': self.returnPID = os.spawnl(os.P_NOWAIT, '%sOSXvnc/OSXvnc-server' % self.paths['resources'], '%sOSXvnc/OSXvnc-server' % self.paths['resources'], '-connectHost', '%s' % host) - elif sys.platform.find('linux') != -1: + elif re.match('(?:open|free|net)bsd|linux',sys.platform): # We should include future versions with options for speed. #self.returnPID = os.spawnlp(os.P_NOWAIT, 'x11vnc', 'x11vnc','-nopw','-ncache','20','-solid','black','-connect','%s' % host) @@ -59,7 +59,7 @@ class Processes: if sys.platform == 'darwin': vncviewer = '%scotvnc.app/Contents/MacOS/cotvnc' % self.paths['resources'] self.returnPID = os.spawnlp(os.P_NOWAIT, vncviewer, vncviewer, '--listen') - elif sys.platform.find('linux') != -1: + elif re.match('(?:open|free|net)bsd|linux',sys.platform): # These are the options for low-res connections. # In the future, I'd like to support cross-platform low-res options. @@ -93,11 +93,11 @@ class Processes: handle = win32api.OpenProcess(PROCESS_TERMINATE, False, self.returnPID.pid) win32api.TerminateProcess(handle, -1) win32api.CloseHandle(handle) - elif sys.platform.find('linux') != -1: + elif re.match('(?:open|free|net)bsd|linux',sys.platform): # New processes are created when you made connections. So if you kill self.returnPID, # you're just killing the dispatch process, not the one actually doing business... - os.spawnlp(os.P_NOWAIT, 'killall', 'killall', 'vncviewer') - os.spawnlp(os.P_NOWAIT, 'killall', 'killall', 'x11vnc') + os.spawnlp(os.P_NOWAIT, 'pkill', 'pkill', '-f', 'vncviewer') + os.spawnlp(os.P_NOWAIT, 'pkill', 'pkill', '-f', 'x11vnc') else: os.kill(self.returnPID, signal.SIGKILL) self.returnPID = 0