summaryrefslogtreecommitdiffstats
path: root/deluge/common.py
diff options
context:
space:
mode:
authortbkizle <tbkizle@gmail.com>2020-02-13 00:13:44 -0500
committerCalum Lind <calumlind+deluge@gmail.com>2022-01-30 16:13:27 +0000
commit540d557cb2163c41af894ee252cc677d01887376 (patch)
tree1e03424802944dde5d6cab4f2278173d39fff9ec /deluge/common.py
parentd8acadb085a8f20bce15193c4b6e946199ab263d (diff)
downloaddeluge-540d557cb2163c41af894ee252cc677d01887376.tar.gz
deluge-540d557cb2163c41af894ee252cc677d01887376.tar.bz2
deluge-540d557cb2163c41af894ee252cc677d01887376.zip
[Common] Add is_interface to validate network interfaces
Libtorrent now supports interface names instead of just IP address so add new common functions to validate user input. * Added is_interface that will verify if a libtorrent interface of name or IP address. * Added is_interface_name to verify that the name supplied is a valid network interface name in the operating system. On Windows sock.if_nameindex() is only supported on 3.8+ and does not return a uuid (required by libtorrent) so use ifaddr package. Using git commit version for ifaddr due to adapter name decode bug in v0.1.7. On other OSes attempt to use stdlib and fallback to ifaddr if installed otherwiser return True. * Added tests for is_interface & is_interface_name * Updated UIs with change from address to interface * Updated is_ipv6 and is_ipv4 to used inet_pton; now supported on Windows. Ref: https://github.com/pydron/ifaddr/pull/32 Closes: https://github.com/deluge-torrent/deluge/pull/338
Diffstat (limited to 'deluge/common.py')
-rw-r--r--deluge/common.py92
1 files changed, 73 insertions, 19 deletions
diff --git a/deluge/common.py b/deluge/common.py
index da056d484..82adb0715 100644
--- a/deluge/common.py
+++ b/deluge/common.py
@@ -17,6 +17,7 @@ import numbers
import os
import platform
import re
+import socket
import subprocess
import sys
import tarfile
@@ -44,6 +45,11 @@ if platform.system() in ('Windows', 'Microsoft'):
os.environ['SSL_CERT_FILE'] = where()
+try:
+ import ifaddr
+except ImportError:
+ ifaddr = None
+
if platform.system() not in ('Windows', 'Microsoft', 'Darwin'):
# gi makes dbus available on Window but don't import it as unused.
@@ -900,6 +906,29 @@ def free_space(path):
return disk_data.f_bavail * block_size
+def is_interface(interface):
+ """Check if interface is a valid IP or network adapter.
+
+ Args:
+ interface (str): The IP or interface name to test.
+
+ Returns:
+ bool: Whether interface is valid is not.
+
+ Examples:
+ Windows:
+ >>> is_interface('{7A30AE62-23ZA-3744-Z844-A5B042524871}')
+ >>> is_interface('127.0.0.1')
+ True
+ Linux:
+ >>> is_interface('lo')
+ >>> is_interface('127.0.0.1')
+ True
+
+ """
+ return is_ip(interface) or is_interface_name(interface)
+
+
def is_ip(ip):
"""A test to see if 'ip' is a valid IPv4 or IPv6 address.
@@ -935,15 +964,12 @@ def is_ipv4(ip):
"""
- import socket
-
try:
- if windows_check():
- return socket.inet_aton(ip)
- else:
- return socket.inet_pton(socket.AF_INET, ip)
+ socket.inet_pton(socket.AF_INET, ip)
except OSError:
return False
+ else:
+ return True
def is_ipv6(ip):
@@ -962,23 +988,51 @@ def is_ipv6(ip):
"""
try:
- import ipaddress
- except ImportError:
- import socket
-
- try:
- return socket.inet_pton(socket.AF_INET6, ip)
- except (OSError, AttributeError):
- if windows_check():
- log.warning('Unable to verify IPv6 Address on Windows.')
- return True
+ socket.inet_pton(socket.AF_INET6, ip)
+ except OSError:
+ return False
else:
+ return True
+
+
+def is_interface_name(name):
+ """Returns True if an interface name exists.
+
+ Args:
+ name (str): The Interface to test. eg. eth0 linux. GUID on Windows.
+
+ Returns:
+ bool: Whether name is valid or not.
+
+ Examples:
+ >>> is_interface_name("eth0")
+ True
+ >>> is_interface_name("{7A30AE62-23ZA-3744-Z844-A5B042524871}")
+ True
+
+ """
+
+ if not windows_check():
try:
- return ipaddress.IPv6Address(decode_bytes(ip))
- except ipaddress.AddressValueError:
+ socket.if_nametoindex(name)
+ except OSError:
pass
+ else:
+ return True
+
+ if ifaddr:
+ try:
+ adapters = ifaddr.get_adapters()
+ except OSError:
+ return True
+ else:
+ return any([name == a.name for a in adapters])
+
+ if windows_check():
+ regex = '^{[0-9A-Z]{8}-([0-9A-Z]{4}-){3}[0-9A-Z]{12}}$'
+ return bool(re.search(regex, str(name)))
- return False
+ return True
def decode_bytes(byte_str, encoding='utf8'):