From 77b25057d1601ccebd0e9272101d9b445e23dd8f Mon Sep 17 00:00:00 2001 From: Sebastien Helleu Date: Fri, 27 Jul 2012 17:56:55 +0200 Subject: [PATCH] Add SSL support --- src/qweechat/config.py | 1 + src/qweechat/connection.py | 6 ++++++ src/qweechat/network.py | 26 ++++++++++++++++++-------- src/qweechat/qweechat.py | 33 ++++++++++++++++++++------------- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/qweechat/config.py b/src/qweechat/config.py index 120a4bb..31d7355 100644 --- a/src/qweechat/config.py +++ b/src/qweechat/config.py @@ -32,6 +32,7 @@ CONFIG_FILENAME = '%s/qweechat.conf' % CONFIG_DIR CONFIG_DEFAULT_SECTIONS = ('relay', 'look', 'color') CONFIG_DEFAULT_OPTIONS = (('relay.server', ''), ('relay.port', ''), + ('relay.ssl', 'off'), ('relay.password', ''), ('relay.autoconnect', 'off'), ('look.debug', 'off'), diff --git a/src/qweechat/connection.py b/src/qweechat/connection.py index 573038e..9092b1c 100644 --- a/src/qweechat/connection.py +++ b/src/qweechat/connection.py @@ -42,11 +42,17 @@ class ConnectionDialog(QtGui.QDialog): for y, field in enumerate(('server', 'port', 'password')): grid.addWidget(QtGui.QLabel(field.capitalize()), y, 0) lineEdit = QtGui.QLineEdit() + lineEdit.setFixedWidth(200) if field == 'password': lineEdit.setEchoMode(QtGui.QLineEdit.Password) lineEdit.insert(self.values[field]) grid.addWidget(lineEdit, y, 1) self.fields[field] = lineEdit + if field == 'port': + ssl = QtGui.QCheckBox('SSL') + ssl.setChecked(self.values['ssl'] == 'on') + grid.addWidget(ssl, y, 2) + self.fields['ssl'] = ssl self.dialog_buttons = QtGui.QDialogButtonBox() self.dialog_buttons.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) diff --git a/src/qweechat/network.py b/src/qweechat/network.py index 636afcf..e97bb65 100644 --- a/src/qweechat/network.py +++ b/src/qweechat/network.py @@ -49,9 +49,10 @@ class Network(QtCore.QObject): self.status_connected = 'connected' self._server = None self._port = None + self._ssl = None self._password = None self._buffer = QtCore.QByteArray() - self._socket = QtNetwork.QTcpSocket() + self._socket = QtNetwork.QSslSocket() self._socket.connected.connect(self._socket_connected) self._socket.error.connect(self._socket_error) self._socket.readyRead.connect(self._socket_read) @@ -61,7 +62,7 @@ class Network(QtCore.QObject): """Slot: socket connected.""" self.statusChanged.emit(self.status_connected, None) if self._password: - self._socket.write('\n'.join(_PROTO_INIT_CMD + _PROTO_SYNC_CMDS) % {'password': str(self._password)}) + self.send_to_weechat('\n'.join(_PROTO_INIT_CMD + _PROTO_SYNC_CMDS) % {'password': str(self._password)}) def _socket_error(self, error): """Slot: socket error.""" @@ -69,8 +70,7 @@ class Network(QtCore.QObject): def _socket_read(self): """Slot: data available on socket.""" - avail = self._socket.bytesAvailable() - bytes = self._socket.read(avail) + bytes = self._socket.readAll() self._buffer.append(bytes) while len(self._buffer) >= 4: remainder = None @@ -84,6 +84,8 @@ class Network(QtCore.QObject): remainder = self._buffer[length:] self._buffer = self._buffer[0:length] self.messageFromWeechat.emit(self._buffer) + if not self.is_connected(): + return self._buffer.clear() if remainder: self._buffer.append(remainder) @@ -92,30 +94,38 @@ class Network(QtCore.QObject): """Slot: socket disconnected.""" self._server = None self._port = None + self._ssl = None self._password = None self.statusChanged.emit(self.status_disconnected, None) def is_connected(self): return self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState - def connect_weechat(self, server, port, password): + def is_ssl(self): + return self._ssl + + def connect_weechat(self, server, port, ssl, password): self._server = server try: self._port = int(port) except: self._port = 0 + self._ssl = ssl self._password = password if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState: return if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState: self._socket.abort() self._socket.connectToHost(self._server, self._port) + if self._ssl: + self._socket.ignoreSslErrors() + self._socket.startClientEncryption() self.statusChanged.emit(self.status_connecting, None) def disconnect_weechat(self): if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState: if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState: - self._socket.write('quit\n') + self.send_to_weechat('quit\n') self._socket.waitForBytesWritten(1000) else: self.statusChanged.emit(self.status_disconnected, None) @@ -125,10 +135,10 @@ class Network(QtCore.QObject): self._socket.write(str(message)) def desync_weechat(self): - self._socket.write('desync\n') + self.send_to_weechat('desync\n') def sync_weechat(self): - self._socket.write('\n'.join(_PROTO_SYNC_CMDS)) + self.send_to_weechat('\n'.join(_PROTO_SYNC_CMDS)) def status_icon(self, status): icon = {self.status_disconnected: 'dialog-close.png', diff --git a/src/qweechat/qweechat.py b/src/qweechat/qweechat.py index 1680669..265a604 100755 --- a/src/qweechat/qweechat.py +++ b/src/qweechat/qweechat.py @@ -139,6 +139,7 @@ class MainWindow(QtGui.QMainWindow): if self.config.getboolean('relay', 'autoconnect'): self.network.connect_weechat(self.config.get('relay', 'server'), self.config.get('relay', 'port'), + self.config.get('relay', 'ssl') == 'on', self.config.get('relay', 'password')) self.show() @@ -195,7 +196,7 @@ class MainWindow(QtGui.QMainWindow): def open_connection_dialog(self): values = {} - for option in ('server', 'port', 'password'): + for option in ('server', 'port', 'ssl', 'password'): values[option] = self.config.get('relay', option) self.connection_dialog = ConnectionDialog(values, self) self.connection_dialog.dialog_buttons.accepted.connect(self.connect_weechat) @@ -203,6 +204,7 @@ class MainWindow(QtGui.QMainWindow): def connect_weechat(self): self.network.connect_weechat(self.connection_dialog.fields['server'].text(), self.connection_dialog.fields['port'].text(), + self.connection_dialog.fields['ssl'].isChecked(), self.connection_dialog.fields['password'].text()) self.connection_dialog.close() @@ -214,14 +216,15 @@ class MainWindow(QtGui.QMainWindow): def network_status_set(self, status, extra): pal = self.network_status.palette() - if self.network.is_connected(): + if status == self.network.status_connected: pal.setColor(self.network_status.foregroundRole(), QtGui.QColor('green')) else: pal.setColor(self.network_status.foregroundRole(), QtGui.QColor('#aa0000')) + ssl = ' (SSL)' if status != self.network.status_disconnected and self.network.is_ssl() else '' self.network_status.setPalette(pal) icon = self.network.status_icon(status) if icon: - self.network_status.setText(' %s' % (icon, status.capitalize())) + self.network_status.setText(' %s' % (icon, status.capitalize() + ssl)) else: self.network_status.setText(status.capitalize()) if status == self.network.status_disconnected: @@ -236,16 +239,20 @@ class MainWindow(QtGui.QMainWindow): 'message (%d bytes):\n%s' % (len(message), protocol.hex_and_ascii(message, 20)), forcecolor='#008800') - proto = protocol.Protocol() - message = proto.decode(str(message)) - if message.uncompressed: - self.debug_display(0, '==>', - 'message uncompressed (%d bytes):\n%s' - % (message.size_uncompressed, - protocol.hex_and_ascii(message.uncompressed, 20)), - forcecolor='#008800') - self.debug_display(0, '', 'Message: %s' % message) - self.parse_message(message) + try: + proto = protocol.Protocol() + message = proto.decode(str(message)) + if message.uncompressed: + self.debug_display(0, '==>', + 'message uncompressed (%d bytes):\n%s' + % (message.size_uncompressed, + protocol.hex_and_ascii(message.uncompressed, 20)), + forcecolor='#008800') + self.debug_display(0, '', 'Message: %s' % message) + self.parse_message(message) + except: + print("Error while decoding message from WeeChat") + self.network.disconnect_weechat() def parse_message(self, message): if message.msgid.startswith('debug'):