Merge pull request #1357 from coffeedogs/final_code_quality_2

Changes based on style and lint checks. (final_code_quality_2)
This commit is contained in:
coffeedogs 2018-10-31 17:09:58 +00:00 committed by GitHub
commit 44f5e03774
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 34 deletions

View File

@ -1,14 +1,26 @@
#!/usr/bin/python2.7 #!/usr/bin/python2.7
"""
src/settingsmixin.py
====================
"""
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
class SettingsMixin(object): class SettingsMixin(object):
"""Mixin for adding geometry and state saving between restarts."""
def warnIfNoObjectName(self): def warnIfNoObjectName(self):
"""
Handle objects which don't have a name. Currently it ignores them. Objects without a name can't have their
state/geometry saved as they don't have an identifier.
"""
if self.objectName() == "": if self.objectName() == "":
# TODO: logger # .. todo:: logger
pass pass
def writeState(self, source): def writeState(self, source):
"""Save object state (e.g. relative position of a splitter)"""
self.warnIfNoObjectName() self.warnIfNoObjectName()
settings = QtCore.QSettings() settings = QtCore.QSettings()
settings.beginGroup(self.objectName()) settings.beginGroup(self.objectName())
@ -16,6 +28,7 @@ class SettingsMixin(object):
settings.endGroup() settings.endGroup()
def writeGeometry(self, source): def writeGeometry(self, source):
"""Save object geometry (e.g. window size and position)"""
self.warnIfNoObjectName() self.warnIfNoObjectName()
settings = QtCore.QSettings() settings = QtCore.QSettings()
settings.beginGroup(self.objectName()) settings.beginGroup(self.objectName())
@ -23,57 +36,73 @@ class SettingsMixin(object):
settings.endGroup() settings.endGroup()
def readGeometry(self, target): def readGeometry(self, target):
"""Load object geometry"""
self.warnIfNoObjectName() self.warnIfNoObjectName()
settings = QtCore.QSettings() settings = QtCore.QSettings()
try: try:
geom = settings.value("/".join([str(self.objectName()), "geometry"])) geom = settings.value("/".join([str(self.objectName()), "geometry"]))
target.restoreGeometry(geom.toByteArray() if hasattr(geom, 'toByteArray') else geom) target.restoreGeometry(geom.toByteArray() if hasattr(geom, 'toByteArray') else geom)
except Exception as e: except Exception:
pass pass
def readState(self, target): def readState(self, target):
"""Load object state"""
self.warnIfNoObjectName() self.warnIfNoObjectName()
settings = QtCore.QSettings() settings = QtCore.QSettings()
try: try:
state = settings.value("/".join([str(self.objectName()), "state"])) state = settings.value("/".join([str(self.objectName()), "state"]))
target.restoreState(state.toByteArray() if hasattr(state, 'toByteArray') else state) target.restoreState(state.toByteArray() if hasattr(state, 'toByteArray') else state)
except Exception as e: except Exception:
pass pass
class SMainWindow(QtGui.QMainWindow, SettingsMixin): class SMainWindow(QtGui.QMainWindow, SettingsMixin):
"""Main window with Settings functionality."""
def loadSettings(self): def loadSettings(self):
"""Load main window settings."""
self.readGeometry(self) self.readGeometry(self)
self.readState(self) self.readState(self)
def saveSettings(self): def saveSettings(self):
"""Save main window settings"""
self.writeState(self) self.writeState(self)
self.writeGeometry(self) self.writeGeometry(self)
class STableWidget(QtGui.QTableWidget, SettingsMixin): class STableWidget(QtGui.QTableWidget, SettingsMixin):
"""Table widget with Settings functionality"""
# pylint: disable=too-many-ancestors
def loadSettings(self): def loadSettings(self):
"""Load table settings."""
self.readState(self.horizontalHeader()) self.readState(self.horizontalHeader())
def saveSettings(self): def saveSettings(self):
"""Save table settings."""
self.writeState(self.horizontalHeader()) self.writeState(self.horizontalHeader())
class SSplitter(QtGui.QSplitter, SettingsMixin): class SSplitter(QtGui.QSplitter, SettingsMixin):
"""Splitter with Settings functionality."""
def loadSettings(self): def loadSettings(self):
"""Load splitter settings"""
self.readState(self) self.readState(self)
def saveSettings(self): def saveSettings(self):
"""Save splitter settings."""
self.writeState(self) self.writeState(self)
class STreeWidget(QtGui.QTreeWidget, SettingsMixin): class STreeWidget(QtGui.QTreeWidget, SettingsMixin):
"""Tree widget with settings functionality."""
# pylint: disable=too-many-ancestors
def loadSettings(self): def loadSettings(self):
#recurse children """Load tree settings."""
#self.readState(self) # recurse children
# self.readState(self)
pass pass
def saveSettings(self): def saveSettings(self):
#recurse children """Save tree settings"""
#self.writeState(self) # recurse children
# self.writeState(self)
pass pass

View File

@ -1,36 +1,48 @@
"""
src/network/socks5.py
=====================
"""
# pylint: disable=attribute-defined-outside-init
import socket import socket
import struct import struct
from proxy import Proxy, ProxyError, GeneralProxyError from proxy import GeneralProxyError, Proxy, ProxyError
class Socks5AuthError(ProxyError): class Socks5AuthError(ProxyError):
"""Thrown when the socks5 protocol encounters an authentication error"""
errorCodes = ("Succeeded", errorCodes = ("Succeeded",
"Authentication is required", "Authentication is required",
"All offered authentication methods were rejected", "All offered authentication methods were rejected",
"Unknown username or invalid password", "Unknown username or invalid password",
"Unknown error") "Unknown error")
class Socks5Error(ProxyError): class Socks5Error(ProxyError):
"""Thrown when socks5 protocol encounters an error"""
errorCodes = ("Succeeded", errorCodes = ("Succeeded",
"General SOCKS server failure", "General SOCKS server failure",
"Connection not allowed by ruleset", "Connection not allowed by ruleset",
"Network unreachable", "Network unreachable",
"Host unreachable", "Host unreachable",
"Connection refused", "Connection refused",
"TTL expired", "TTL expired",
"Command not supported", "Command not supported",
"Address type not supported", "Address type not supported",
"Unknown error") "Unknown error")
class Socks5(Proxy): class Socks5(Proxy):
"""A socks5 proxy base class"""
def __init__(self, address=None): def __init__(self, address=None):
Proxy.__init__(self, address) Proxy.__init__(self, address)
self.ipaddr = None self.ipaddr = None
self.destport = address[1] self.destport = address[1]
def state_init(self): def state_init(self):
"""Protocol initialisation (before connection is established)"""
if self._auth: if self._auth:
self.append_write_buf(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) self.append_write_buf(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02))
else: else:
@ -39,6 +51,7 @@ class Socks5(Proxy):
return True return True
def state_auth_1(self): def state_auth_1(self):
"""Perform authentication if peer is requesting it."""
ret = struct.unpack('BB', self.read_buf[:2]) ret = struct.unpack('BB', self.read_buf[:2])
if ret[0] != 5: if ret[0] != 5:
# general error # general error
@ -48,9 +61,9 @@ class Socks5(Proxy):
self.set_state("auth_done", length=2) self.set_state("auth_done", length=2)
elif ret[1] == 2: elif ret[1] == 2:
# username/password # username/password
self.append_write_buf(struct.pack('BB', 1, len(self._auth[0])) + \ self.append_write_buf(struct.pack('BB', 1, len(self._auth[0])) +
self._auth[0] + struct.pack('B', len(self._auth[1])) + \ self._auth[0] + struct.pack('B', len(self._auth[1])) +
self._auth[1]) self._auth[1])
self.set_state("auth_needed", length=2, expectBytes=2) self.set_state("auth_needed", length=2, expectBytes=2)
else: else:
if ret[1] == 0xff: if ret[1] == 0xff:
@ -62,6 +75,7 @@ class Socks5(Proxy):
return True return True
def state_auth_needed(self): def state_auth_needed(self):
"""Handle response to authentication attempt"""
ret = struct.unpack('BB', self.read_buf[0:2]) ret = struct.unpack('BB', self.read_buf[0:2])
if ret[0] != 1: if ret[0] != 1:
# general error # general error
@ -74,6 +88,7 @@ class Socks5(Proxy):
return True return True
def state_pre_connect(self): def state_pre_connect(self):
"""Handle feedback from socks5 while it is connecting on our behalf."""
# Get the response # Get the response
if self.read_buf[0:1] != chr(0x05).encode(): if self.read_buf[0:1] != chr(0x05).encode():
self.close() self.close()
@ -81,7 +96,7 @@ class Socks5(Proxy):
elif self.read_buf[1:2] != chr(0x00).encode(): elif self.read_buf[1:2] != chr(0x00).encode():
# Connection failed # Connection failed
self.close() self.close()
if ord(self.read_buf[1:2])<=8: if ord(self.read_buf[1:2]) <= 8:
raise Socks5Error(ord(self.read_buf[1:2])) raise Socks5Error(ord(self.read_buf[1:2]))
else: else:
raise Socks5Error(9) raise Socks5Error(9)
@ -96,21 +111,31 @@ class Socks5(Proxy):
return True return True
def state_proxy_addr_1(self): def state_proxy_addr_1(self):
"""Handle IPv4 address returned for peer"""
self.boundaddr = self.read_buf[0:4] self.boundaddr = self.read_buf[0:4]
self.set_state("proxy_port", length=4, expectBytes=2) self.set_state("proxy_port", length=4, expectBytes=2)
return True return True
def state_proxy_addr_2_1(self): def state_proxy_addr_2_1(self):
"""
Handle other addresses than IPv4 returned for peer (e.g. IPv6, onion, ...). This is part 1 which retrieves the
length of the data.
"""
self.address_length = ord(self.read_buf[0:1]) self.address_length = ord(self.read_buf[0:1])
self.set_state("proxy_addr_2_2", length=1, expectBytes=self.address_length) self.set_state("proxy_addr_2_2", length=1, expectBytes=self.address_length)
return True return True
def state_proxy_addr_2_2(self): def state_proxy_addr_2_2(self):
"""
Handle other addresses than IPv4 returned for peer (e.g. IPv6, onion, ...). This is part 2 which retrieves the
data.
"""
self.boundaddr = self.read_buf[0:self.address_length] self.boundaddr = self.read_buf[0:self.address_length]
self.set_state("proxy_port", length=self.address_length, expectBytes=2) self.set_state("proxy_port", length=self.address_length, expectBytes=2)
return True return True
def state_proxy_port(self): def state_proxy_port(self):
"""Handle peer's port being returned."""
self.boundport = struct.unpack(">H", self.read_buf[0:2])[0] self.boundport = struct.unpack(">H", self.read_buf[0:2])[0]
self.__proxysockname = (self.boundaddr, self.boundport) self.__proxysockname = (self.boundaddr, self.boundport)
if self.ipaddr is not None: if self.ipaddr is not None:
@ -121,14 +146,17 @@ class Socks5(Proxy):
return True return True
def proxy_sock_name(self): def proxy_sock_name(self):
"""Handle return value when using SOCKS5 for DNS resolving instead of connecting."""
return socket.inet_ntoa(self.__proxysockname[0]) return socket.inet_ntoa(self.__proxysockname[0])
class Socks5Connection(Socks5): class Socks5Connection(Socks5):
"""Child socks5 class used for making outbound connections."""
def __init__(self, address): def __init__(self, address):
Socks5.__init__(self, address=address) Socks5.__init__(self, address=address)
def state_auth_done(self): def state_auth_done(self):
"""Request connection to be made"""
# Now we can request the actual connection # Now we can request the actual connection
self.append_write_buf(struct.pack('BBB', 0x05, 0x01, 0x00)) self.append_write_buf(struct.pack('BBB', 0x05, 0x01, 0x00))
# If the given destination address is an IP address, we'll # If the given destination address is an IP address, we'll
@ -138,10 +166,12 @@ class Socks5Connection(Socks5):
self.append_write_buf(chr(0x01).encode() + self.ipaddr) self.append_write_buf(chr(0x01).encode() + self.ipaddr)
except socket.error: except socket.error:
# Well it's not an IP number, so it's probably a DNS name. # Well it's not an IP number, so it's probably a DNS name.
if Proxy._remote_dns: if Proxy._remote_dns: # pylint: disable=protected-access
# Resolve remotely # Resolve remotely
self.ipaddr = None self.ipaddr = None
self.append_write_buf(chr(0x03).encode() + chr(len(self.destination[0])).encode() + self.destination[0]) self.append_write_buf(chr(0x03).encode() +
chr(len(self.destination[0])).encode() +
self.destination[0])
else: else:
# Resolve locally # Resolve locally
self.ipaddr = socket.inet_aton(socket.gethostbyname(self.destination[0])) self.ipaddr = socket.inet_aton(socket.gethostbyname(self.destination[0]))
@ -151,6 +181,7 @@ class Socks5Connection(Socks5):
return True return True
def state_pre_connect(self): def state_pre_connect(self):
"""Tell socks5 to initiate a connection"""
try: try:
return Socks5.state_pre_connect(self) return Socks5.state_pre_connect(self)
except Socks5Error as e: except Socks5Error as e:
@ -159,12 +190,14 @@ class Socks5Connection(Socks5):
class Socks5Resolver(Socks5): class Socks5Resolver(Socks5):
"""DNS resolver class using socks5"""
def __init__(self, host): def __init__(self, host):
self.host = host self.host = host
self.port = 8444 self.port = 8444
Socks5.__init__(self, address=(self.host, self.port)) Socks5.__init__(self, address=(self.host, self.port))
def state_auth_done(self): def state_auth_done(self):
"""Perform resolving"""
# Now we can request the actual connection # Now we can request the actual connection
self.append_write_buf(struct.pack('BBB', 0x05, 0xF0, 0x00)) self.append_write_buf(struct.pack('BBB', 0x05, 0xF0, 0x00))
self.append_write_buf(chr(0x03).encode() + chr(len(self.host)).encode() + str(self.host)) self.append_write_buf(chr(0x03).encode() + chr(len(self.host)).encode() + str(self.host))
@ -173,4 +206,8 @@ class Socks5Resolver(Socks5):
return True return True
def resolved(self): def resolved(self):
"""
Resolving is done, process the return value. To use this within PyBitmessage, a callback needs to be
implemented which hasn't been done yet.
"""
print "Resolved %s as %s" % (self.host, self.proxy_sock_name()) print "Resolved %s as %s" % (self.host, self.proxy_sock_name())