Add SSL support

This commit is contained in:
Sebastien Helleu 2012-07-27 17:56:55 +02:00
parent f8bbe7b6c1
commit 77b25057d1
4 changed files with 45 additions and 21 deletions

View file

@ -32,6 +32,7 @@ CONFIG_FILENAME = '%s/qweechat.conf' % CONFIG_DIR
CONFIG_DEFAULT_SECTIONS = ('relay', 'look', 'color') CONFIG_DEFAULT_SECTIONS = ('relay', 'look', 'color')
CONFIG_DEFAULT_OPTIONS = (('relay.server', ''), CONFIG_DEFAULT_OPTIONS = (('relay.server', ''),
('relay.port', ''), ('relay.port', ''),
('relay.ssl', 'off'),
('relay.password', ''), ('relay.password', ''),
('relay.autoconnect', 'off'), ('relay.autoconnect', 'off'),
('look.debug', 'off'), ('look.debug', 'off'),

View file

@ -42,11 +42,17 @@ class ConnectionDialog(QtGui.QDialog):
for y, field in enumerate(('server', 'port', 'password')): for y, field in enumerate(('server', 'port', 'password')):
grid.addWidget(QtGui.QLabel(field.capitalize()), y, 0) grid.addWidget(QtGui.QLabel(field.capitalize()), y, 0)
lineEdit = QtGui.QLineEdit() lineEdit = QtGui.QLineEdit()
lineEdit.setFixedWidth(200)
if field == 'password': if field == 'password':
lineEdit.setEchoMode(QtGui.QLineEdit.Password) lineEdit.setEchoMode(QtGui.QLineEdit.Password)
lineEdit.insert(self.values[field]) lineEdit.insert(self.values[field])
grid.addWidget(lineEdit, y, 1) grid.addWidget(lineEdit, y, 1)
self.fields[field] = lineEdit 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 = QtGui.QDialogButtonBox()
self.dialog_buttons.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self.dialog_buttons.setStandardButtons(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)

View file

@ -49,9 +49,10 @@ class Network(QtCore.QObject):
self.status_connected = 'connected' self.status_connected = 'connected'
self._server = None self._server = None
self._port = None self._port = None
self._ssl = None
self._password = None self._password = None
self._buffer = QtCore.QByteArray() self._buffer = QtCore.QByteArray()
self._socket = QtNetwork.QTcpSocket() self._socket = QtNetwork.QSslSocket()
self._socket.connected.connect(self._socket_connected) self._socket.connected.connect(self._socket_connected)
self._socket.error.connect(self._socket_error) self._socket.error.connect(self._socket_error)
self._socket.readyRead.connect(self._socket_read) self._socket.readyRead.connect(self._socket_read)
@ -61,7 +62,7 @@ class Network(QtCore.QObject):
"""Slot: socket connected.""" """Slot: socket connected."""
self.statusChanged.emit(self.status_connected, None) self.statusChanged.emit(self.status_connected, None)
if self._password: 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): def _socket_error(self, error):
"""Slot: socket error.""" """Slot: socket error."""
@ -69,8 +70,7 @@ class Network(QtCore.QObject):
def _socket_read(self): def _socket_read(self):
"""Slot: data available on socket.""" """Slot: data available on socket."""
avail = self._socket.bytesAvailable() bytes = self._socket.readAll()
bytes = self._socket.read(avail)
self._buffer.append(bytes) self._buffer.append(bytes)
while len(self._buffer) >= 4: while len(self._buffer) >= 4:
remainder = None remainder = None
@ -84,6 +84,8 @@ class Network(QtCore.QObject):
remainder = self._buffer[length:] remainder = self._buffer[length:]
self._buffer = self._buffer[0:length] self._buffer = self._buffer[0:length]
self.messageFromWeechat.emit(self._buffer) self.messageFromWeechat.emit(self._buffer)
if not self.is_connected():
return
self._buffer.clear() self._buffer.clear()
if remainder: if remainder:
self._buffer.append(remainder) self._buffer.append(remainder)
@ -92,30 +94,38 @@ class Network(QtCore.QObject):
"""Slot: socket disconnected.""" """Slot: socket disconnected."""
self._server = None self._server = None
self._port = None self._port = None
self._ssl = None
self._password = None self._password = None
self.statusChanged.emit(self.status_disconnected, None) self.statusChanged.emit(self.status_disconnected, None)
def is_connected(self): def is_connected(self):
return self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState 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 self._server = server
try: try:
self._port = int(port) self._port = int(port)
except: except:
self._port = 0 self._port = 0
self._ssl = ssl
self._password = password self._password = password
if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState: if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
return return
if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState: if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
self._socket.abort() self._socket.abort()
self._socket.connectToHost(self._server, self._port) self._socket.connectToHost(self._server, self._port)
if self._ssl:
self._socket.ignoreSslErrors()
self._socket.startClientEncryption()
self.statusChanged.emit(self.status_connecting, None) self.statusChanged.emit(self.status_connecting, None)
def disconnect_weechat(self): def disconnect_weechat(self):
if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState: if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState: if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
self._socket.write('quit\n') self.send_to_weechat('quit\n')
self._socket.waitForBytesWritten(1000) self._socket.waitForBytesWritten(1000)
else: else:
self.statusChanged.emit(self.status_disconnected, None) self.statusChanged.emit(self.status_disconnected, None)
@ -125,10 +135,10 @@ class Network(QtCore.QObject):
self._socket.write(str(message)) self._socket.write(str(message))
def desync_weechat(self): def desync_weechat(self):
self._socket.write('desync\n') self.send_to_weechat('desync\n')
def sync_weechat(self): 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): def status_icon(self, status):
icon = {self.status_disconnected: 'dialog-close.png', icon = {self.status_disconnected: 'dialog-close.png',

View file

@ -139,6 +139,7 @@ class MainWindow(QtGui.QMainWindow):
if self.config.getboolean('relay', 'autoconnect'): if self.config.getboolean('relay', 'autoconnect'):
self.network.connect_weechat(self.config.get('relay', 'server'), self.network.connect_weechat(self.config.get('relay', 'server'),
self.config.get('relay', 'port'), self.config.get('relay', 'port'),
self.config.get('relay', 'ssl') == 'on',
self.config.get('relay', 'password')) self.config.get('relay', 'password'))
self.show() self.show()
@ -195,7 +196,7 @@ class MainWindow(QtGui.QMainWindow):
def open_connection_dialog(self): def open_connection_dialog(self):
values = {} values = {}
for option in ('server', 'port', 'password'): for option in ('server', 'port', 'ssl', 'password'):
values[option] = self.config.get('relay', option) values[option] = self.config.get('relay', option)
self.connection_dialog = ConnectionDialog(values, self) self.connection_dialog = ConnectionDialog(values, self)
self.connection_dialog.dialog_buttons.accepted.connect(self.connect_weechat) self.connection_dialog.dialog_buttons.accepted.connect(self.connect_weechat)
@ -203,6 +204,7 @@ class MainWindow(QtGui.QMainWindow):
def connect_weechat(self): def connect_weechat(self):
self.network.connect_weechat(self.connection_dialog.fields['server'].text(), self.network.connect_weechat(self.connection_dialog.fields['server'].text(),
self.connection_dialog.fields['port'].text(), self.connection_dialog.fields['port'].text(),
self.connection_dialog.fields['ssl'].isChecked(),
self.connection_dialog.fields['password'].text()) self.connection_dialog.fields['password'].text())
self.connection_dialog.close() self.connection_dialog.close()
@ -214,14 +216,15 @@ class MainWindow(QtGui.QMainWindow):
def network_status_set(self, status, extra): def network_status_set(self, status, extra):
pal = self.network_status.palette() 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')) pal.setColor(self.network_status.foregroundRole(), QtGui.QColor('green'))
else: else:
pal.setColor(self.network_status.foregroundRole(), QtGui.QColor('#aa0000')) 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) self.network_status.setPalette(pal)
icon = self.network.status_icon(status) icon = self.network.status_icon(status)
if icon: if icon:
self.network_status.setText('<img src="data/icons/%s"> %s' % (icon, status.capitalize())) self.network_status.setText('<img src="data/icons/%s"> %s' % (icon, status.capitalize() + ssl))
else: else:
self.network_status.setText(status.capitalize()) self.network_status.setText(status.capitalize())
if status == self.network.status_disconnected: if status == self.network.status_disconnected:
@ -236,16 +239,20 @@ class MainWindow(QtGui.QMainWindow):
'message (%d bytes):\n%s' 'message (%d bytes):\n%s'
% (len(message), protocol.hex_and_ascii(message, 20)), % (len(message), protocol.hex_and_ascii(message, 20)),
forcecolor='#008800') forcecolor='#008800')
proto = protocol.Protocol() try:
message = proto.decode(str(message)) proto = protocol.Protocol()
if message.uncompressed: message = proto.decode(str(message))
self.debug_display(0, '==>', if message.uncompressed:
'message uncompressed (%d bytes):\n%s' self.debug_display(0, '==>',
% (message.size_uncompressed, 'message uncompressed (%d bytes):\n%s'
protocol.hex_and_ascii(message.uncompressed, 20)), % (message.size_uncompressed,
forcecolor='#008800') protocol.hex_and_ascii(message.uncompressed, 20)),
self.debug_display(0, '', 'Message: %s' % message) forcecolor='#008800')
self.parse_message(message) 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): def parse_message(self, message):
if message.msgid.startswith('debug'): if message.msgid.startswith('debug'):