[WebUI] Log correct http address if listening on IPv6

This commit is contained in:
bendikro 2016-04-29 22:42:34 +02:00 committed by Calum Lind
commit 0edebda1c7
5 changed files with 88 additions and 30 deletions

View file

@ -11,8 +11,10 @@
* geoip-database (optional) * geoip-database (optional)
* setproctitle (optional) * setproctitle (optional)
* pillow (optional) * pillow (optional)
* py2-ipaddress (optional, required for Windows IPv6)
* rencode >= 1.0.2 (optional), python port bundled. * rencode >= 1.0.2 (optional), python port bundled.
=== Gtk UI === === Gtk UI ===
* pygtk >= 2.16 * pygtk >= 2.16
* librsvg * librsvg

View file

@ -721,44 +721,84 @@ def free_space(path):
def is_ip(ip): def is_ip(ip):
""" """A test to see if 'ip' is a valid IPv4 or IPv6 address.
A simple test to see if 'ip' is valid
:param ip: the ip to check Args:
:type ip: string ip (str): The IP to test.
:returns: True or False
:rtype: bool
:Example: Returns:
bool: Whether IP is valid is not.
>>> is_ip('127.0.0.1') Examples:
True >>> is_ip("192.0.2.0")
True
>>> is_ip("2001:db8::")
True
""" """
return is_ipv4(ip) or is_ipv6(ip)
def is_ipv4(ip):
"""A test to see if 'ip' is a valid IPv4 address.
Args:
ip (str): The IP to test.
Returns:
bool: Whether IP is valid is not.
Examples:
>>> is_ipv4("192.0.2.0")
True
"""
import socket import socket
# first we test ipv4
try: try:
if windows_check(): if windows_check():
if socket.inet_aton(ip): return socket.inet_aton(ip)
return True
else: else:
if socket.inet_pton(socket.AF_INET, ip): return socket.inet_pton(socket.AF_INET, ip)
return True
except socket.error:
if not socket.has_ipv6:
return False
# now test ipv6
try:
if windows_check():
log.warning('ipv6 check unavailable on windows')
return True
else:
if socket.inet_pton(socket.AF_INET6, ip):
return True
except socket.error: except socket.error:
return False return False
def is_ipv6(ip):
"""A test to see if 'ip' is a valid IPv6 address.
Args:
ip (str): The IP to test.
Returns:
bool: Whether IP is valid is not.
Examples:
>>> is_ipv6("2001:db8::")
True
"""
try:
import ipaddress
except ImportError:
import socket
try:
return socket.inet_pton(socket.AF_INET6, ip)
except (socket.error, AttributeError):
if windows_check():
log.warning('Unable to verify IPv6 Address on Windows.')
return True
else:
try:
return ipaddress.IPv6Address(ip)
except ipaddress.AddressValueError:
pass
return False
def decode_string(s, encoding='utf8'): def decode_string(s, encoding='utf8'):
""" """
Decodes a string and return unicode. If it cannot decode using Decodes a string and return unicode. If it cannot decode using

View file

@ -68,8 +68,18 @@ class CommonTestCase(unittest.TestCase):
self.failUnless(get_path_size('non-existant.file') == -1) self.failUnless(get_path_size('non-existant.file') == -1)
def test_is_ip(self): def test_is_ip(self):
self.failUnless(is_ip('127.0.0.1')) self.failUnless(is_ip('192.0.2.0'))
self.failIf(is_ip('127..0.0')) self.failIf(is_ip('192..0.0'))
self.failUnless(is_ip('2001:db8::'))
self.failIf(is_ip('2001:db8:'))
def test_is_ipv4(self):
self.failUnless(is_ip('192.0.2.0'))
self.failIf(is_ip('192..0.0'))
def test_is_ipv6(self):
self.failUnless(is_ip('2001:db8::'))
self.failIf(is_ip('2001:db8:'))
def test_version_split(self): def test_version_split(self):
self.failUnless(VersionSplit('1.2.2') == VersionSplit('1.2.2')) self.failUnless(VersionSplit('1.2.2') == VersionSplit('1.2.2'))

View file

@ -21,6 +21,7 @@ from twisted.internet.ssl import SSL, Certificate, CertificateOptions, KeyPair
from twisted.web import http, resource, server, static from twisted.web import http, resource, server, static
from deluge import common, component, configmanager from deluge import common, component, configmanager
from deluge.common import is_ipv6
from deluge.core.rpcserver import check_ssl_keys from deluge.core.rpcserver import check_ssl_keys
from deluge.ui.tracker_icons import TrackerIcons from deluge.ui.tracker_icons import TrackerIcons
from deluge.ui.util import lang from deluge.ui.util import lang
@ -568,7 +569,7 @@ class DelugeWeb(component.Component):
self.base = self.config['base'] self.base = self.config['base']
if options: if options:
self.interface = options.interface if options.interface else self.interface self.interface = options.interface if options.interface is not None else self.interface
self.port = options.port if options.port else self.port self.port = options.port if options.port else self.port
self.base = options.base if options.base else self.base self.base = options.base if options.base else self.base
if options.ssl: if options.ssl:
@ -635,7 +636,9 @@ class DelugeWeb(component.Component):
def start_normal(self): def start_normal(self):
self.socket = reactor.listenTCP(self.port, self.site, interface=self.interface) self.socket = reactor.listenTCP(self.port, self.site, interface=self.interface)
log.info('Serving at http://%s:%s%s', self.interface, self.port, self.base) ip = self.socket.getHost().host
ip = '[%s]' % ip if is_ipv6(ip) else ip
log.info('Serving at http://%s:%s%s', ip, self.port, self.base)
def start_ssl(self): def start_ssl(self):
check_ssl_keys() check_ssl_keys()
@ -649,7 +652,9 @@ class DelugeWeb(component.Component):
options.getContext().set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) options.getContext().set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface)
log.info('Serving at https://%s:%s%s', self.interface, self.port, self.base) ip = self.socket.getHost().host
ip = '[%s]' % ip if is_ipv6(ip) else ip
log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
def stop(self): def stop(self):
log.info('Shutting down webserver') log.info('Shutting down webserver')

View file

@ -31,6 +31,7 @@ deps =
mock mock
slimit slimit
pillow pillow
py2-ipaddress
whitelist_externals = py.test whitelist_externals = py.test
commands = {envpython} setup.py test commands = {envpython} setup.py test