Changes based on style and lint checks. (final_code_quality_2)

This commit is contained in:
coffeedogs 2018-10-04 15:11:56 +01:00
parent 283154e508
commit 10128b7560
No known key found for this signature in database
GPG Key ID: 9D818C503D0B7E70
2 changed files with 100 additions and 34 deletions

View File

@ -1,79 +1,108 @@
#!/usr/bin/python2.7
"""
src/settingsmixin.py
====================
"""
from PyQt4 import QtCore, QtGui
class SettingsMixin(object):
"""Mixin for adding geometry and state saving between restarts."""
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() == "":
# TODO: logger
# .. todo:: logger
pass
def writeState(self, source):
"""Save object state (e.g. relative position of a splitter)"""
self.warnIfNoObjectName()
settings = QtCore.QSettings()
settings.beginGroup(self.objectName())
settings.setValue("state", source.saveState())
settings.endGroup()
def writeGeometry(self, source):
"""Save object geometry (e.g. window size and position)"""
self.warnIfNoObjectName()
settings = QtCore.QSettings()
settings.beginGroup(self.objectName())
settings.setValue("geometry", source.saveGeometry())
settings.endGroup()
def readGeometry(self, target):
"""Load object geometry"""
self.warnIfNoObjectName()
settings = QtCore.QSettings()
try:
geom = settings.value("/".join([str(self.objectName()), "geometry"]))
target.restoreGeometry(geom.toByteArray() if hasattr(geom, 'toByteArray') else geom)
except Exception as e:
except Exception:
pass
def readState(self, target):
"""Load object state"""
self.warnIfNoObjectName()
settings = QtCore.QSettings()
try:
state = settings.value("/".join([str(self.objectName()), "state"]))
target.restoreState(state.toByteArray() if hasattr(state, 'toByteArray') else state)
except Exception as e:
except Exception:
pass
class SMainWindow(QtGui.QMainWindow, SettingsMixin):
"""Main window with Settings functionality."""
def loadSettings(self):
"""Load main window settings."""
self.readGeometry(self)
self.readState(self)
def saveSettings(self):
"""Save main window settings"""
self.writeState(self)
self.writeGeometry(self)
class STableWidget(QtGui.QTableWidget, SettingsMixin):
"""Table widget with Settings functionality"""
# pylint: disable=too-many-ancestors
def loadSettings(self):
"""Load table settings."""
self.readState(self.horizontalHeader())
def saveSettings(self):
"""Save table settings."""
self.writeState(self.horizontalHeader())
class SSplitter(QtGui.QSplitter, SettingsMixin):
"""Splitter with Settings functionality."""
def loadSettings(self):
"""Load splitter settings"""
self.readState(self)
def saveSettings(self):
"""Save splitter settings."""
self.writeState(self)
class STreeWidget(QtGui.QTreeWidget, SettingsMixin):
"""Tree widget with settings functionality."""
# pylint: disable=too-many-ancestors
def loadSettings(self):
#recurse children
#self.readState(self)
"""Load tree settings."""
# recurse children
# self.readState(self)
pass
def saveSettings(self):
#recurse children
#self.writeState(self)
"""Save tree settings"""
# recurse children
# self.writeState(self)
pass

View File

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