diff -Nru sshuttle-0.53/client.py sshuttle-0.54/client.py --- sshuttle-0.53/client.py 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/client.py 2011-05-31 04:42:48.000000000 +0000 @@ -175,6 +175,65 @@ raise Fatal('cleanup: %r returned %d' % (self.argv, rv)) +def onaccept(listener, mux, handlers): + global _extra_fd + try: + sock,srcip = listener.accept() + except socket.error, e: + if e.args[0] in [errno.EMFILE, errno.ENFILE]: + debug1('Rejected incoming connection: too many open files!\n') + # free up an fd so we can eat the connection + os.close(_extra_fd) + try: + sock,srcip = listener.accept() + sock.close() + finally: + _extra_fd = os.open('/dev/null', os.O_RDONLY) + return + else: + raise + dstip = original_dst(sock) + debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1], + dstip[0],dstip[1])) + if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]): + debug1("-- ignored: that's my address!\n") + sock.close() + return + chan = mux.next_channel() + if not chan: + log('warning: too many open channels. Discarded connection.\n') + sock.close() + return + mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip) + outwrap = MuxWrapper(mux, chan) + handlers.append(Proxy(SockWrapper(sock, sock), outwrap)) + + +dnsreqs = {} +def dns_done(chan, data): + peer,sock,timeout = dnsreqs.get(chan) or (None,None,None) + debug3('dns_done: channel=%r peer=%r\n' % (chan, peer)) + if peer: + del dnsreqs[chan] + debug3('doing sendto %r\n' % (peer,)) + sock.sendto(data, peer) + + +def ondns(listener, mux, handlers): + pkt,peer = listener.recvfrom(4096) + now = time.time() + if pkt: + debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt))) + chan = mux.next_channel() + dnsreqs[chan] = peer,listener,now+30 + mux.send(chan, ssnet.CMD_DNS_REQ, pkt) + mux.channels[chan] = lambda cmd,data: dns_done(chan,data) + for chan,(peer,sock,timeout) in dnsreqs.items(): + if timeout < now: + del dnsreqs[chan] + debug3('Remaining DNS requests: %d\n' % len(dnsreqs)) + + def _main(listener, fw, ssh_cmd, remotename, python, latency_control, dnslistener, seed_hosts, auto_nets, syslog, daemon): @@ -255,63 +314,10 @@ fw.sethostip(name, ip) mux.got_host_list = onhostlist - def onaccept(): - global _extra_fd - try: - sock,srcip = listener.accept() - except socket.error, e: - if e.args[0] in [errno.EMFILE, errno.ENFILE]: - debug1('Rejected incoming connection: too many open files!\n') - # free up an fd so we can eat the connection - os.close(_extra_fd) - try: - sock,srcip = listener.accept() - sock.close() - finally: - _extra_fd = os.open('/dev/null', os.O_RDONLY) - return - else: - raise - dstip = original_dst(sock) - debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1], - dstip[0],dstip[1])) - if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]): - debug1("-- ignored: that's my address!\n") - sock.close() - return - chan = mux.next_channel() - if not chan: - log('warning: too many open channels. Discarded connection.\n') - sock.close() - return - mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip) - outwrap = MuxWrapper(mux, chan) - handlers.append(Proxy(SockWrapper(sock, sock), outwrap)) - handlers.append(Handler([listener], onaccept)) - - dnsreqs = {} - def dns_done(chan, data): - peer,timeout = dnsreqs.get(chan) or (None,None) - debug3('dns_done: channel=%r peer=%r\n' % (chan, peer)) - if peer: - del dnsreqs[chan] - debug3('doing sendto %r\n' % (peer,)) - dnslistener.sendto(data, peer) - def ondns(): - pkt,peer = dnslistener.recvfrom(4096) - now = time.time() - if pkt: - debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt))) - chan = mux.next_channel() - dnsreqs[chan] = peer,now+30 - mux.send(chan, ssnet.CMD_DNS_REQ, pkt) - mux.channels[chan] = lambda cmd,data: dns_done(chan,data) - for chan,(peer,timeout) in dnsreqs.items(): - if timeout < now: - del dnsreqs[chan] - debug3('Remaining DNS requests: %d\n' % len(dnsreqs)) + handlers.append(Handler([listener], lambda: onaccept(listener, mux, handlers))) + if dnslistener: - handlers.append(Handler([dnslistener], ondns)) + handlers.append(Handler([dnslistener], lambda: ondns(dnslistener, mux, handlers))) if seed_hosts != None: debug1('seed_hosts: %r\n' % seed_hosts) diff -Nru sshuttle-0.53/debian/changelog sshuttle-0.54/debian/changelog --- sshuttle-0.53/debian/changelog 2011-06-08 22:03:56.000000000 +0000 +++ sshuttle-0.54/debian/changelog 2011-08-08 18:21:38.000000000 +0000 @@ -1,3 +1,14 @@ +sshuttle (0.54-1) unstable; urgency=low + + * New upstream release. + * Add myself as co-maintainer. + * Remove unnecessary README.source. + * Document the fact that manpage.diff patch was forwarded to upstream. + * Wrap long lines of README.Debian. + * Remove unused patches. + + -- Miguel Landaeta Sun, 24 Jul 2011 21:25:25 +0200 + sshuttle (0.53-0.1) unstable; urgency=low * Non-maintainer upload. diff -Nru sshuttle-0.53/debian/control sshuttle-0.54/debian/control --- sshuttle-0.53/debian/control 2011-06-08 22:03:42.000000000 +0000 +++ sshuttle-0.54/debian/control 2011-06-12 21:36:18.000000000 +0000 @@ -2,6 +2,7 @@ Section: net Priority: extra Maintainer: Javier Fernandez-Sanguino Pen~a +Uploaders: Miguel Landaeta Build-Depends: debhelper (>= 7.0.50~), pandoc, python (>= 2.6.6-3~) Standards-Version: 3.9.2 X-Python-Version: >= 2.4 diff -Nru sshuttle-0.53/debian/patches/debian-changes-0.42-2 sshuttle-0.54/debian/patches/debian-changes-0.42-2 --- sshuttle-0.53/debian/patches/debian-changes-0.42-2 2011-06-08 21:59:27.000000000 +0000 +++ sshuttle-0.54/debian/patches/debian-changes-0.42-2 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -Description: Upstream changes introduced in version 0.42-2 - - Add an 'install' target to the Makefile - -Author: Javier Fernandez-Sanguino Pen~a -Forwarded: no -Origin: vendor - ---- a/Makefile -+++ b/Makefile -@@ -1,3 +1,13 @@ -+# -+# Makefile for sshuttle -+ -+SSHUTTLE_DIR=/usr/lib/sshuttle -+BIN_DIR=/usr/sbin/ -+ -+SSHUTTLE_MAIN=main.py -+SSHUTTLE_SCRIPTS=assembler.py firewall.py hostwatch.py options.py ssh.py \ -+ client.py helpers.py server.py ssnet.py -+ - PANDOC:=$(shell \ - if pandoc /dev/null; then \ - echo pandoc; \ -@@ -15,5 +25,16 @@ - %.8: %.md - $(PANDOC) -s -r markdown -w man -o $@ $< - -+install: install-compat -+ [ -d "$(PREFIX)$(SSHUTTLE_DIR)" ] || mkdir -p $(PREFIX)$(SSHUTTLE_DIR) -+ install -m755 $(SSHUTTLE_MAIN) $(PREFIX)$(SSHUTTLE_DIR) -+ install -m644 $(SSHUTTLE_SCRIPTS) $(PREFIX)$(SSHUTTLE_DIR) -+ [ -d "$(PREFIX)$(BIN_DIR)" ] || mkdir -p $(PREFIX)$(BIN_DIR) -+ ( cd $(PREFIX)$(BIN_DIR) && ln -s $(SSHUTTLE_DIR)/$(SSHUTTLE_MAIN) sshuttle ) -+ -+install-compat: -+ [ -d "$(PREFIX)$(SSHUTTLE_DIR)/compat" ] || mkdir -p $(PREFIX)$(SSHUTTLE_DIR)/compat -+ install -m644 compat/*.py $(PREFIX)$(SSHUTTLE_DIR)/compat -+ - clean: - rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc diff -Nru sshuttle-0.53/debian/patches/debian-changes-0.43a-1 sshuttle-0.54/debian/patches/debian-changes-0.43a-1 --- sshuttle-0.53/debian/patches/debian-changes-0.43a-1 2011-06-08 21:59:27.000000000 +0000 +++ sshuttle-0.54/debian/patches/debian-changes-0.43a-1 1970-01-01 00:00:00.000000000 +0000 @@ -1,269 +0,0 @@ -Description: Upstream changes introduced in version 0.43a-1 - This patch has been created by dpkg-source during the package build. - Here's the last changelog entry, hopefully it gives details on why - those changes were made: - . - sshuttle (0.43a-1) unstable; urgency=low - . - * New upstream version with patches from GIT - - Fixes file descriptors leak after a long run (Closes: 607067) - - Clear up upstream patches and sync (Closes: 607069) - * debian/patches: - - Remove debian-changes-0.42-1 - - Refresh debian-changes-0.42-2 - - Add debian-changes-0.43a-1: changes introduced in the GIT repository after the - 0.43a release - . - The person named in the Author field signed this changelog entry. -Author: Javier Fernandez-Sanguino Pen~a -Bug-Debian: http://bugs.debian.org/607067 -Bug-Debian: http://bugs.debian.org/607069 - ---- -The information above should follow the Patch Tagging Guidelines, please -checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here -are templates for supplementary fields that you might want to add: - -Origin: , -Bug: -Bug-Debian: http://bugs.debian.org/ -Bug-Ubuntu: https://launchpad.net/bugs/ -Forwarded: -Reviewed-By: -Last-Update: - ---- sshuttle-0.43a.orig/main.py -+++ sshuttle-0.43a/main.py -@@ -56,8 +56,8 @@ python= specify the name/path of the pyt - r,remote= ssh hostname (and optional username) of remote sshuttle server - x,exclude= exclude this subnet (can be used more than once) - v,verbose increase debug message verbosity --e,ssh-cmd= the command to use to connect to the remote [ssh] - seed-hosts= with -H, use these hostnames for initial scan (comma-separated) -+noserver don't use a separate server process (mostly for debugging) - server (internal use only) - firewall (internal use only) - hostwatch (internal use only) -@@ -98,9 +98,9 @@ try: - else: - sh = None - sys.exit(client.main(parse_ipport(opt.listen or '0.0.0.0:0'), -- opt.ssh_cmd, -+ not opt.noserver, - remotename, -- opt.python, -+ (opt.python or "python"), - sh, - opt.auto_nets, - parse_subnets(includes), ---- sshuttle-0.43a.orig/README.md -+++ sshuttle-0.43a/README.md -@@ -54,14 +54,8 @@ This is how you use it: - - - ./sshuttle -r username@sshserver 0.0.0.0/0 -vv - --(You may be prompted for one or more passwords; first, the --local password to become root using either sudo or su, and --then the remote ssh password. Or you might have sudo and ssh set --up to not require passwords, in which case you won't be --prompted at all.) -- - That's it! Now your local machine can access the remote network as if you --were right there. And if your "client" machine is a router, everyone on -+were right there! And if your "client" machine is a router, everyone on - your local network can make connections to your remote network. - - You don't need to install sshuttle on the remote server; ---- sshuttle-0.43a.orig/ssh.py -+++ sshuttle-0.43a/ssh.py -@@ -21,35 +21,17 @@ def empackage(z, filename): - return '%s\n%d\n%s' % (basename,len(content), content) - - --def connect(ssh_cmd, rhostport, python): -+def connect(rhostport, python): - main_exe = sys.argv[0] -+ l = (rhostport or '').split(':', 1) -+ rhost = l[0] - portl = [] -- -- rhostIsIPv6 = False -- if (rhostport or '').count(':') > 1: -- rhostIsIPv6 = True -- if rhostport.count(']') or rhostport.count('['): -- result = rhostport.split(']') -- rhost = result[0].strip('[') -- if len(result) > 1: -- result[1] = result[1].strip(':') -- if result[1] is not '': -- portl = ['-p', str(int(result[1]))] -- else: # can't disambiguate IPv6 colons and a port number. pass the hostname through. -- rhost = rhostport -- else: # IPv4 -- l = (rhostport or '').split(':', 1) -- rhost = l[0] -- if len(l) > 1: -- portl = ['-p', str(int(l[1]))] -+ if len(l) > 1: -+ portl = ['-p', str(int(l[1]))] - - if rhost == '-': - rhost = None - -- ipv6flag = [] -- if rhostIsIPv6: -- ipv6flag = ['-6'] -- - z = zlib.compressobj(1) - content = readfile('assembler.py') - content2 = (empackage(z, 'helpers.py') + -@@ -71,14 +53,7 @@ def connect(ssh_cmd, rhostport, python): - if not rhost: - argv = [python, '-c', pyscript] - else: -- if ssh_cmd: -- sshl = ssh_cmd.split(' ') -- else: -- sshl = ['ssh'] -- argv = (sshl + -- portl + -- ipv6flag + -- [rhost, '--', "'%s' -c '%s'" % (python, pyscript)]) -+ argv = ['ssh'] + portl + [rhost, '--', "'%s' -c '%s'" % (python, pyscript)] - (s1,s2) = socket.socketpair() - def setup(): - # runs in the child process ---- sshuttle-0.43a.orig/client.py -+++ sshuttle-0.43a/client.py -@@ -31,7 +31,7 @@ class FirewallClient: - ['-v'] * (helpers.verbose or 0) + - ['--firewall', str(port)]) - argv_tries = [ -- ['sudo', '-p', '[local sudo] Password: '] + argvbase, -+ ['sudo'] + argvbase, - ['su', '-c', ' '.join(argvbase)], - argvbase - ] -@@ -45,12 +45,8 @@ class FirewallClient: - # run in the child process - s2.close() - e = None -- if os.getuid() == 0: -- argv_tries = argv_tries[-1:] # last entry only - for argv in argv_tries: - try: -- if argv[0] == 'su': -- sys.stderr.write('[local su] ') - self.p = ssubprocess.Popen(argv, stdout=s1, preexec_fn=setup) - e = None - break -@@ -98,34 +94,35 @@ class FirewallClient: - raise Fatal('cleanup: %r returned %d' % (self.argv, rv)) - - --def _main(listener, fw, ssh_cmd, remotename, python, seed_hosts, auto_nets): -+def _main(listener, fw, use_server, remotename, python, seed_hosts, auto_nets): - handlers = [] -- if helpers.verbose >= 1: -- helpers.logprefix = 'c : ' -- else: -- helpers.logprefix = 'client: ' -- debug1('connecting to server...\n') -- try: -- (serverproc, serversock) = ssh.connect(ssh_cmd, remotename, python) -- except socket.error, e: -- if e.errno == errno.EPIPE: -- raise Fatal("failed to establish ssh session") -+ if use_server: -+ if helpers.verbose >= 1: -+ helpers.logprefix = 'c : ' - else: -- raise -- mux = Mux(serversock, serversock) -- handlers.append(mux) -+ helpers.logprefix = 'client: ' -+ debug1('connecting to server...\n') -+ try: -+ (serverproc, serversock) = ssh.connect(remotename, python) -+ except socket.error, e: -+ if e.errno == errno.EPIPE: -+ raise Fatal("failed to establish ssh session") -+ else: -+ raise -+ mux = Mux(serversock, serversock) -+ handlers.append(mux) - -- expected = 'SSHUTTLE0001' -- initstring = serversock.recv(len(expected)) -- -- rv = serverproc.poll() -- if rv: -- raise Fatal('server died with error code %d' % rv) -+ expected = 'SSHUTTLE0001' -+ initstring = serversock.recv(len(expected)) - -- if initstring != expected: -- raise Fatal('expected server init string %r; got %r' -- % (expected, initstring)) -- debug1('connected.\n') -+ rv = serverproc.poll() -+ if rv: -+ raise Fatal('server died with error code %d' % rv) -+ -+ if initstring != expected: -+ raise Fatal('expected server init string %r; got %r' -+ % (expected, initstring)) -+ debug1('connected.\n') - - def onroutes(routestr): - if auto_nets: -@@ -161,9 +158,12 @@ def _main(listener, fw, ssh_cmd, remoten - debug1("-- ignored: that's my address!\n") - sock.close() - return -- chan = mux.next_channel() -- mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip) -- outwrap = MuxWrapper(mux, chan) -+ if use_server: -+ chan = mux.next_channel() -+ mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip) -+ outwrap = MuxWrapper(mux, chan) -+ else: -+ outwrap = ssnet.connect_dst(dstip[0], dstip[1]) - handlers.append(Proxy(SockWrapper(sock, sock), outwrap)) - handlers.append(Handler([listener], onaccept)) - -@@ -172,16 +172,18 @@ def _main(listener, fw, ssh_cmd, remoten - mux.send(0, ssnet.CMD_HOST_REQ, '\n'.join(seed_hosts)) - - while 1: -- rv = serverproc.poll() -- if rv: -- raise Fatal('server died with error code %d' % rv) -+ if use_server: -+ rv = serverproc.poll() -+ if rv: -+ raise Fatal('server died with error code %d' % rv) - - ssnet.runonce(handlers, mux) -- mux.callback() -- mux.check_fullness() -+ if use_server: -+ mux.callback() -+ mux.check_fullness() - - --def main(listenip, ssh_cmd, remotename, python, seed_hosts, auto_nets, -+def main(listenip, use_server, remotename, python, seed_hosts, auto_nets, - subnets_include, subnets_exclude): - debug1('Starting sshuttle proxy.\n') - listener = socket.socket() -@@ -212,7 +214,7 @@ def main(listenip, ssh_cmd, remotename, - fw = FirewallClient(listenip[1], subnets_include, subnets_exclude) - - try: -- return _main(listener, fw, ssh_cmd, remotename, -+ return _main(listener, fw, use_server, remotename, - python, seed_hosts, auto_nets) - finally: - fw.done() diff -Nru sshuttle-0.53/debian/patches/manpage.diff sshuttle-0.54/debian/patches/manpage.diff --- sshuttle-0.53/debian/patches/manpage.diff 2011-06-08 22:03:42.000000000 +0000 +++ sshuttle-0.54/debian/patches/manpage.diff 2011-08-08 18:16:21.000000000 +0000 @@ -1,6 +1,6 @@ Description: Document missing option in sshuttle manpage Author: Miguel Landaeta -Forwarded: no +Forwarded: https://github.com/apenwarr/sshuttle/pull/11 Last-Update: 2011-04-04 --- sshuttle-0.52.orig/sshuttle.md diff -Nru sshuttle-0.53/debian/patches/series sshuttle-0.54/debian/patches/series --- sshuttle-0.53/debian/patches/series 2011-06-08 22:12:17.000000000 +0000 +++ sshuttle-0.54/debian/patches/series 2011-08-08 18:16:21.000000000 +0000 @@ -1,3 +1 @@ -#debian-changes-0.42-2 -#debian-changes-0.43a-1 manpage.diff diff -Nru sshuttle-0.53/debian/README.Debian sshuttle-0.54/debian/README.Debian --- sshuttle-0.53/debian/README.Debian 2011-06-08 21:59:27.000000000 +0000 +++ sshuttle-0.54/debian/README.Debian 2011-08-08 18:16:21.000000000 +0000 @@ -2,8 +2,9 @@ ------------------- The sshuttle package in Debian does not provide, on purpose, any -init.d service to start up a VPN tunnel. Users of sshuttle ,(with administrative -privileges in the local system) have to manually startup sshuttle. +init.d service to start up a VPN tunnel. Users of sshuttle +(with administrative privileges in the local system) have to +manually startup sshuttle. -- Javier Fernandez-Sanguino Wed, 27 Oct 2010 03:01:24 +0200 diff -Nru sshuttle-0.53/debian/README.source sshuttle-0.54/debian/README.source --- sshuttle-0.53/debian/README.source 2011-06-08 21:59:27.000000000 +0000 +++ sshuttle-0.54/debian/README.source 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -sshuttle for Debian -------------------- - - - - - - diff -Nru sshuttle-0.53/helpers.py sshuttle-0.54/helpers.py --- sshuttle-0.53/helpers.py 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/helpers.py 2011-05-31 04:42:48.000000000 +0000 @@ -1,4 +1,4 @@ -import sys, os, socket +import sys, os, socket, errno logprefix = '' verbose = 0 diff -Nru sshuttle-0.53/README.md sshuttle-0.54/README.md --- sshuttle-0.53/README.md 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/README.md 2011-05-31 04:42:48.000000000 +0000 @@ -72,7 +72,7 @@ - If you would also like your DNS queries to be proxied through the DNS server of the server you are connect to: - ./sshuttle --dns -rvv username@sshserver 0/0 + ./sshuttle --dns -vvr username@sshserver 0/0 The above is probably what you want to use to prevent local network attacks such as Firesheep and friends. diff -Nru sshuttle-0.53/ssnet.py sshuttle-0.54/ssnet.py --- sshuttle-0.53/ssnet.py 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/ssnet.py 2011-05-31 04:42:48.000000000 +0000 @@ -152,6 +152,17 @@ debug3('%r: fixed connect result: %s\n' % (self, e)) if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]: pass # not connected yet + elif e.args[0] == 0: + # connected successfully (weird Linux bug?) + # Sometimes Linux seems to return EINVAL when it isn't + # invalid. This *may* be caused by a race condition + # between connect() and getsockopt(SO_ERROR) (ie. it + # finishes connecting in between the two, so there is no + # longer an error). However, I'm not sure of that. + # + # I did get at least one report that the problem went away + # when we added this, however. + self.connect_to = None elif e.args[0] == errno.EISCONN: # connected successfully (BSD) self.connect_to = None diff -Nru sshuttle-0.53/ui-macos/bits/runpython.do sshuttle-0.54/ui-macos/bits/runpython.do --- sshuttle-0.53/ui-macos/bits/runpython.do 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/ui-macos/bits/runpython.do 2011-05-31 04:42:48.000000000 +0000 @@ -1,9 +1,14 @@ exec >&2 redo-ifchange runpython.c ARCHES="" +printf "Platforms: " for d in /usr/libexec/gcc/darwin/*; do - ARCHES="$ARCHES -arch $(basename $d)" + PLAT=$(basename "$d") + [ "$PLAT" != "ppc64" ] || continue # fails for some reason on my Mac + ARCHES="$ARCHES -arch $PLAT" + printf "$PLAT " done +printf "\n" gcc $ARCHES \ -Wall -o $3 runpython.c \ -I/usr/include/python2.5 \ diff -Nru sshuttle-0.53/ui-macos/models.py sshuttle-0.54/ui-macos/models.py --- sshuttle-0.53/ui-macos/models.py 2011-05-03 21:19:45.000000000 +0000 +++ sshuttle-0.54/ui-macos/models.py 2011-05-31 04:42:48.000000000 +0000 @@ -3,6 +3,7 @@ configchange_callback = setconnect_callback = None +objc_validator = objc.signature('@@:N^@o^@') def config_changed(): @@ -39,7 +40,7 @@ def setSubnet_(self, v): self._k_subnet = v config_changed() - @objc.accessor + @objc_validator def validateSubnet_error_(self, value, error): #print 'validateSubnet!' return True, _validate_ip(value), error @@ -49,7 +50,7 @@ def setWidth_(self, v): self._k_width = v config_changed() - @objc.accessor + @objc_validator def validateWidth_error_(self, value, error): #print 'validateWidth!' return True, _validate_width(value), error @@ -118,7 +119,7 @@ self._k_host = v self.setTitle_(None) config_changed() - @objc.accessor + @objc_validator def validateHost_error_(self, value, error): #print 'validatehost! %r %r %r' % (self, value, error) while value.startswith('-'):