include(CheckFunctionExists)
include(CheckIncludeFile)
-# cmake 2.6.2 is required for KDE >=4.2 and should be widespread enough now
# For building against Qt5, we check for an even newer cmake version below!
-cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
+cmake_minimum_required(VERSION 2.8.1 FATAL_ERROR)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
if(APPLE)
option(DEPLOY "Mac OS X only! Adds required libs to bundle resources and create a dmg. Note: requires Qt to be built with 10.4u SDK" OFF)
+ option(WITH_NOTIFICATION_CENTER "Enable OS X Notification Center support" ON)
endif(APPLE)
# Default to embedding data in the static case
set(INDICATEQT_LIBRARIES "")
endif(WITH_LIBINDICATE AND NOT WITH_QT5)
+ # Setup OS X notification center support
+ if(WITH_NOTIFICATION_CENTER AND APPLE)
+ set(HAVE_NOTIFICATION_CENTER true)
+ add_definitions(-DHAVE_NOTIFICATION_CENTER)
+ set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES}
+ /System/Library/Frameworks/Foundation.framework
+ )
+ endif()
+
endif(BUILD_GUI)
# Core-only deps
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
<key>NSHumanReadableCopyright</key>
<string>© 2005-2012, Quassel IRC Team</string>
</dict>
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "clientsettings.h"
#include "coreaccountmodel.h"
#include "identity.h"
+#include "internalpeer.h"
#include "network.h"
#include "networkmodel.h"
#include "quassel.h"
#include "signalproxy.h"
#include "util.h"
+#include "protocols/legacy/legacypeer.h"
+
CoreConnection::CoreConnection(CoreAccountModel *model, QObject *parent)
: QObject(parent),
_model(model),
- _blockSize(0),
_state(Disconnected),
_wantReconnect(false),
_progressMinimum(0),
_progressMaximum(-1),
_progressValue(-1),
_wasReconnect(false),
- _requestedDisconnect(false)
+ _requestedDisconnect(false),
+ _resetting(false)
{
qRegisterMetaType<ConnectionState>("CoreConnection::ConnectionState");
}
void CoreConnection::reconnectTimeout()
{
- if (!_socket) {
+ if (!_peer) {
CoreConnectionSettings s;
if (_wantReconnect && s.autoReconnect()) {
#ifdef HAVE_KDE
bool CoreConnection::isEncrypted() const
{
-#ifndef HAVE_SSL
- return false;
-#else
- QSslSocket *sock = qobject_cast<QSslSocket *>(_socket);
- return isConnected() && sock && sock->isEncrypted();
-#endif
+ return _peer && _peer->isSecure();
}
return false;
if (currentAccount().isInternal())
return true;
- if (_socket->peerAddress().isInSubnet(QHostAddress::LocalHost, 0x00ffffff))
+ if (_peer->isLocal())
return true;
return false;
void CoreConnection::coreSocketError(QAbstractSocket::SocketError)
{
- qDebug() << "coreSocketError" << _socket << _socket->errorString();
disconnectFromCore(_socket->errorString(), true);
}
void CoreConnection::coreSocketDisconnected()
{
- // qDebug() << Q_FUNC_INFO;
_wasReconnect = !_requestedDisconnect;
resetConnection(true);
// FIXME handle disconnects gracefully
}
-void CoreConnection::coreHasData()
+// note: this still expects the legacy protocol
+// note²: after cleaning this up, we can probably get rid of _socket altogether
+void CoreConnection::coreHasData(const QVariant &item)
{
- QVariant item;
- while (SignalProxy::readDataFromDevice(_socket, _blockSize, item)) {
- QVariantMap msg = item.toMap();
- if (!msg.contains("MsgType")) {
- // This core is way too old and does not even speak our init protocol...
- emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
- disconnectFromCore(QString(), false);
- return;
- }
- if (msg["MsgType"] == "ClientInitAck") {
- clientInitAck(msg);
- }
- else if (msg["MsgType"] == "ClientInitReject") {
- emit connectionErrorPopup(msg["Error"].toString());
- disconnectFromCore(QString(), false);
- return;
- }
- else if (msg["MsgType"] == "CoreSetupAck") {
- emit coreSetupSuccess();
- }
- else if (msg["MsgType"] == "CoreSetupReject") {
- emit coreSetupFailed(msg["Error"].toString());
- }
- else if (msg["MsgType"] == "ClientLoginReject") {
- loginFailed(msg["Error"].toString());
- }
- else if (msg["MsgType"] == "ClientLoginAck") {
- loginSuccess();
- }
- else if (msg["MsgType"] == "SessionInit") {
- // that's it, let's hand over to the signal proxy
- // if the socket is an orphan, the signalProxy adopts it.
- // -> we don't need to care about it anymore
- _socket->setParent(0);
- Client::signalProxy()->addPeer(_socket);
-
- sessionStateReceived(msg["SessionState"].toMap());
- break; // this is definitively the last message we process here!
- }
- else {
- disconnectFromCore(tr("Invalid data received from core"), false);
- return;
- }
+ QVariantMap msg = item.toMap();
+ if (!msg.contains("MsgType")) {
+ // This core is way too old and does not even speak our init protocol...
+ emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
+ disconnectFromCore(QString(), false);
+ return;
+ }
+ if (msg["MsgType"] == "ClientInitAck") {
+ clientInitAck(msg);
+ }
+ else if (msg["MsgType"] == "ClientInitReject") {
+ emit connectionErrorPopup(msg["Error"].toString());
+ disconnectFromCore(QString(), false);
+ return;
+ }
+ else if (msg["MsgType"] == "CoreSetupAck") {
+ emit coreSetupSuccess();
+ }
+ else if (msg["MsgType"] == "CoreSetupReject") {
+ emit coreSetupFailed(msg["Error"].toString());
+ }
+ else if (msg["MsgType"] == "ClientLoginReject") {
+ loginFailed(msg["Error"].toString());
}
- if (_blockSize > 0) {
- updateProgress(_socket->bytesAvailable(), _blockSize);
+ else if (msg["MsgType"] == "ClientLoginAck") {
+ loginSuccess();
+ }
+ else if (msg["MsgType"] == "SessionInit") {
+ // that's it, let's hand over to the signal proxy
+ // if the connection is an orphan, the signalProxy adopts it.
+ // -> we don't need to care about it anymore
+
+ disconnect(_peer, 0, this, 0);
+
+ _peer->setParent(0);
+ Client::signalProxy()->addPeer(_peer);
+
+ sessionStateReceived(msg["SessionState"].toMap());
+ }
+ else {
+ disconnectFromCore(tr("Invalid data received from core"), false);
+ return;
}
}
void CoreConnection::disconnectFromCore()
{
- _requestedDisconnect = true;
- disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect
+ if (_socket) {
+ _requestedDisconnect = true;
+ disconnectFromCore(QString(), false); // requested disconnect, so don't try to reconnect
+ }
}
_wasReconnect = wantReconnect; // store if disconnect was requested
+ resetConnection(wantReconnect);
+
if (errorString.isEmpty())
emit connectionError(tr("Disconnected"));
else
emit connectionError(errorString);
-
- Client::signalProxy()->removeAllPeers();
- resetConnection(wantReconnect);
}
void CoreConnection::resetConnection(bool wantReconnect)
{
+ if (_resetting)
+ return;
+ _resetting = true;
+
_wantReconnect = wantReconnect;
- if (_socket) {
+ if (_peer) {
+ disconnect(_socket, 0, this, 0);
+ disconnect(_peer, 0, this, 0);
+ _peer->close();
+
+ if (_peer->parent() == this)
+ _peer->deleteLater(); // if it's not us, it belongs to the sigproxy which will delete it
+ _socket = 0; // socket is owned and will be deleted by RemoteConnection
+ _peer = 0;
+ }
+ else if (_socket) {
disconnect(_socket, 0, this, 0);
_socket->deleteLater();
_socket = 0;
}
+
_requestedDisconnect = false;
- _blockSize = 0;
_coreMsgBuffer.clear();
-
_netsToSync.clear();
_numNetsToSync = 0;
if (wantReconnect && s.autoReconnect()) {
_reconnectTimer.start();
}
+
+ _resetting = false;
}
return;
}
emit startInternalCore();
- emit connectToInternalCore(Client::instance()->signalProxy());
+
+ InternalPeer *peer = new InternalPeer();
+ Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership
+ emit connectToInternalCore(peer);
+
return;
}
Q_ASSERT(!_socket);
#ifdef HAVE_SSL
- QSslSocket *sock = new QSslSocket(Client::instance());
+ QSslSocket *sock = new QSslSocket(this);
// make sure the warning is shown if we happen to connect without SSL support later
s.setAccountValue("ShowNoClientSslWarning", true);
#else
s.setAccountValue("ShowNoClientSslWarning", false);
}
}
- QTcpSocket *sock = new QTcpSocket(Client::instance());
+ QTcpSocket *sock = new QTcpSocket(this);
#endif
#ifndef QT_NO_NETWORKPROXY
#endif
_socket = sock;
- connect(sock, SIGNAL(readyRead()), SLOT(coreHasData()));
connect(sock, SIGNAL(connected()), SLOT(coreSocketConnected()));
connect(sock, SIGNAL(disconnected()), SLOT(coreSocketDisconnected()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(coreSocketError(QAbstractSocket::SocketError)));
void CoreConnection::coreSocketConnected()
{
+ // Create the connection which will handle the incoming data
+ Q_ASSERT(!_peer);
+ _peer = new LegacyPeer(_socket, this);
+ connect(_peer, SIGNAL(dataReceived(QVariant)), SLOT(coreHasData(QVariant)));
+ connect(_peer, SIGNAL(transferProgress(int,int)), SLOT(updateProgress(int,int)));
+
// Phase One: Send client info and wait for core info
emit connectionMsg(tr("Synchronizing to core..."));
clientInit["UseCompression"] = false;
#endif
- SignalProxy::writeDataToDevice(_socket, clientInit);
+ qobject_cast<RemotePeer *>(_peer)->writeSocketData(clientInit);
}
clientLogin["MsgType"] = "ClientLogin";
clientLogin["User"] = currentAccount().user();
clientLogin["Password"] = currentAccount().password();
- SignalProxy::writeDataToDevice(_socket, clientLogin);
+ qobject_cast<RemotePeer*>(_peer)->writeSocketData(clientLogin);
}
{
updateProgress(100, 100);
- // rest of communication happens through SignalProxy...
- disconnect(_socket, SIGNAL(readyRead()), this, 0);
- disconnect(_socket, SIGNAL(connected()), this, 0);
-
syncToCore(state);
}
QVariantMap setup;
setup["MsgType"] = "CoreSetupData";
setup["SetupData"] = setupData;
- SignalProxy::writeDataToDevice(_socket, setup);
+ qobject_cast<RemotePeer *>(_peer)->writeSocketData(setup);
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#endif
#include "coreaccount.h"
+#include "remotepeer.h"
#include "types.h"
class CoreAccountModel;
+class InternalPeer;
class Network;
class SignalProxy;
void init();
- inline bool isConnected() const;
- inline ConnectionState state() const;
- inline CoreAccount currentAccount() const;
+ bool isConnected() const;
+ ConnectionState state() const;
+ CoreAccount currentAccount() const;
bool isEncrypted() const;
bool isLocalConnection() const;
- inline int progressMinimum() const;
- inline int progressMaximum() const;
- inline int progressValue() const;
- inline QString progressText() const;
+ int progressMinimum() const;
+ int progressMaximum() const;
+ int progressValue() const;
+ QString progressText() const;
//! Check if we consider the last connect as reconnect
- inline bool wasReconnect() const { return _wasReconnect; }
+ bool wasReconnect() const { return _wasReconnect; }
#ifdef HAVE_SSL
- inline const QSslSocket *sslSocket() const;
+ const QSslSocket *sslSocket() const;
#endif
public slots:
void coreSetupFailed(const QString &error);
void startInternalCore();
- void connectToInternalCore(SignalProxy *proxy);
+ void connectToInternalCore(InternalPeer *connection);
// These signals MUST be handled synchronously!
void userAuthenticationRequired(CoreAccount *, bool *valid, const QString &errorMessage = QString());
void socketStateChanged(QAbstractSocket::SocketState);
void coreSocketError(QAbstractSocket::SocketError);
- void coreHasData();
+ void coreHasData(const QVariant &item);
void coreSocketConnected();
void coreSocketDisconnected();
CoreAccount _account;
QVariantMap _coreMsgBuffer;
- QPointer<QAbstractSocket> _socket;
- quint32 _blockSize;
+ QPointer<QTcpSocket> _socket;
+ QPointer<SignalProxy::AbstractPeer> _peer;
ConnectionState _state;
QTimer _reconnectTimer;
QString _coreInfoString(const QVariantMap &);
bool _wasReconnect;
bool _requestedDisconnect;
+ bool _resetting;
inline CoreAccountModel *accountModel() const;
Q_DECLARE_METATYPE(CoreConnection::ConnectionState)
// Inlines
-int CoreConnection::progressMinimum() const { return _progressMinimum; }
-int CoreConnection::progressMaximum() const { return _progressMaximum; }
-int CoreConnection::progressValue() const { return _progressValue; }
-QString CoreConnection::progressText() const { return _progressText; }
+inline int CoreConnection::progressMinimum() const { return _progressMinimum; }
+inline int CoreConnection::progressMaximum() const { return _progressMaximum; }
+inline int CoreConnection::progressValue() const { return _progressValue; }
+inline QString CoreConnection::progressText() const { return _progressText; }
-CoreConnection::ConnectionState CoreConnection::state() const { return _state; }
-bool CoreConnection::isConnected() const { return state() >= Connected; }
-CoreAccount CoreConnection::currentAccount() const { return _account; }
-CoreAccountModel *CoreConnection::accountModel() const { return _model; }
+inline CoreConnection::ConnectionState CoreConnection::state() const { return _state; }
+inline bool CoreConnection::isConnected() const { return state() >= Connected; }
+inline CoreAccount CoreConnection::currentAccount() const { return _account; }
+inline CoreAccountModel *CoreConnection::accountModel() const { return _model; }
#ifdef HAVE_SSL
-const QSslSocket *CoreConnection::sslSocket() const { return qobject_cast<QSslSocket *>(_socket); }
+inline const QSslSocket *CoreConnection::sslSocket() const { return qobject_cast<QSslSocket *>(_socket); }
#endif
#endif
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
eventmanager.cpp
identity.cpp
ignorelistmanager.cpp
+ internalpeer.cpp
ircchannel.cpp
ircevent.cpp
irclisthelper.cpp
networkconfig.cpp
networkevent.cpp
quassel.cpp
+ remotepeer.cpp
settings.cpp
signalproxy.cpp
syncableobject.cpp
- util.cpp)
+ util.cpp
+
+ protocols/legacy/legacypeer.cpp
+)
set(MOC_HDRS
aliasmanager.h
eventmanager.h
identity.h
ignorelistmanager.h
+ internalpeer.h
ircchannel.h
irclisthelper.h
ircuser.h
network.h
networkconfig.h
+ remotepeer.h
settings.h
signalproxy.h
- syncableobject.h)
+ syncableobject.h
+
+ protocols/legacy/legacypeer.h
+)
set(HEADERS ${MOC_HDRS}
abstractcliparser.h
networkevent.h
logger.h
message.h
+ protocol.h
types.h
util.h)
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
IrcEventPrivmsg,
IrcEventQuit,
IrcEventTopic,
+ IrcEventWallops,
IrcEventRawPrivmsg, ///< Undecoded privmsg (still needs CTCP parsing)
IrcEventRawNotice, ///< Undecoded notice (still needs CTCP parsing)
IrcEventUnknown, ///< Unknown non-numeric cmd
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <QCoreApplication>
+#include <QThread>
+
+#include "internalpeer.h"
+
+using namespace Protocol;
+
+template<class T>
+class PeerMessageEvent : public QEvent
+{
+public:
+ PeerMessageEvent(InternalPeer *sender, InternalPeer::EventType eventType, const T &message)
+ : QEvent(QEvent::Type(eventType)), sender(sender), message(message) {}
+ InternalPeer *sender;
+ T message;
+};
+
+
+InternalPeer::InternalPeer(QObject *parent)
+ : SignalProxy::AbstractPeer(parent),
+ _proxy(0),
+ _peer(0),
+ _isOpen(true)
+{
+
+}
+
+
+InternalPeer::~InternalPeer()
+{
+ if (_isOpen)
+ emit disconnected();
+}
+
+
+QString InternalPeer::description() const
+{
+ return tr("internal connection");
+}
+
+
+bool InternalPeer::isOpen() const
+{
+ return true;
+}
+
+
+bool InternalPeer::isSecure() const
+{
+ return true;
+}
+
+
+bool InternalPeer::isLocal() const
+{
+ return true;
+}
+
+
+void InternalPeer::close(const QString &reason)
+{
+ // FIXME
+ Q_UNUSED(reason)
+ qWarning() << "closing not implemented!";
+}
+
+
+int InternalPeer::lag() const
+{
+ return 0;
+}
+
+
+void InternalPeer::setSignalProxy(::SignalProxy *proxy)
+{
+ if (!proxy && _proxy) {
+ _proxy = 0;
+ if (_isOpen) {
+ _isOpen = false;
+ emit disconnected();
+ }
+ return;
+ }
+
+ if (proxy && !_proxy) {
+ _proxy = proxy;
+ return;
+ }
+
+ qWarning() << Q_FUNC_INFO << "Changing the SignalProxy is not supported!";
+}
+
+
+void InternalPeer::setPeer(InternalPeer *peer)
+{
+ if (_peer) {
+ qWarning() << Q_FUNC_INFO << "Peer already set, ignoring!";
+ return;
+ }
+ _peer = peer;
+ connect(peer, SIGNAL(disconnected()), SLOT(peerDisconnected()));
+}
+
+
+void InternalPeer::peerDisconnected()
+{
+ disconnect(_peer, 0, this, 0);
+ _peer = 0;
+ if (_isOpen) {
+ _isOpen = false;
+ emit disconnected();
+ }
+}
+
+
+void InternalPeer::dispatch(const SyncMessage &msg)
+{
+ dispatch(SyncMessageEvent, msg);
+}
+
+
+void InternalPeer::dispatch(const RpcCall &msg)
+{
+ dispatch(RpcCallEvent, msg);
+}
+
+
+void InternalPeer::dispatch(const InitRequest &msg)
+{
+ dispatch(InitRequestEvent, msg);
+}
+
+
+void InternalPeer::dispatch(const InitData &msg)
+{
+ dispatch(InitDataEvent, msg);
+}
+
+
+template<class T>
+void InternalPeer::dispatch(EventType eventType, const T &msg)
+{
+ if (!_peer) {
+ qWarning() << Q_FUNC_INFO << "Cannot dispatch a message without a peer!";
+ return;
+ }
+
+ if(QThread::currentThread() == _peer->thread())
+ _peer->handle(msg);
+ else
+ QCoreApplication::postEvent(_peer, new PeerMessageEvent<T>(this, eventType, msg));
+}
+
+
+template<class T>
+void InternalPeer::handle(const T &msg)
+{
+ if (!_proxy) {
+ qWarning() << Q_FUNC_INFO << "Cannot handle a message without having a signal proxy set!";
+ return;
+ }
+
+ _proxy->handle(this, msg);
+}
+
+
+void InternalPeer::customEvent(QEvent *event)
+{
+ switch ((int)event->type()) {
+ case SyncMessageEvent: {
+ PeerMessageEvent<SyncMessage> *e = static_cast<PeerMessageEvent<SyncMessage> *>(event);
+ handle(e->message);
+ break;
+ }
+ case RpcCallEvent: {
+ PeerMessageEvent<RpcCall> *e = static_cast<PeerMessageEvent<RpcCall> *>(event);
+ handle(e->message);
+ break;
+ }
+ case InitRequestEvent: {
+ PeerMessageEvent<InitRequest> *e = static_cast<PeerMessageEvent<InitRequest> *>(event);
+ handle(e->message);
+ break;
+ }
+ case InitDataEvent: {
+ PeerMessageEvent<InitData> *e = static_cast<PeerMessageEvent<InitData> *>(event);
+ handle(e->message);
+ break;
+ }
+
+ default:
+ qWarning() << Q_FUNC_INFO << "Received unknown custom event:" << event->type();
+ return;
+ }
+
+ event->accept();
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INTERNALPEER_H
+#define INTERNALPEER_H
+
+#include <QTcpSocket>
+
+#include "protocol.h"
+#include "signalproxy.h"
+
+class QEvent;
+
+class InternalPeer : public SignalProxy::AbstractPeer
+{
+ Q_OBJECT
+
+public:
+ enum EventType {
+ SyncMessageEvent = QEvent::User,
+ RpcCallEvent,
+ InitRequestEvent,
+ InitDataEvent
+ };
+
+ InternalPeer(QObject *parent = 0);
+ virtual ~InternalPeer();
+
+ QString description() const;
+
+ SignalProxy *signalProxy() const;
+ void setSignalProxy(SignalProxy *proxy);
+
+ InternalPeer *peer() const;
+ void setPeer(InternalPeer *peer);
+
+ bool isOpen() const;
+ bool isSecure() const;
+ bool isLocal() const;
+
+ int lag() const;
+
+ void dispatch(const Protocol::SyncMessage &msg);
+ void dispatch(const Protocol::RpcCall &msg);
+ void dispatch(const Protocol::InitRequest &msg);
+ void dispatch(const Protocol::InitData &msg);
+
+public slots:
+ void close(const QString &reason = QString());
+
+signals:
+
+ void disconnected();
+ void error(QAbstractSocket::SocketError);
+
+protected:
+ void customEvent(QEvent *event);
+
+private slots:
+ void peerDisconnected();
+
+private:
+ template<class T>
+ void dispatch(EventType eventType, const T &msg);
+
+ template<class T>
+ void handle(const T &msg);
+
+private:
+ SignalProxy *_proxy;
+ InternalPeer *_peer;
+ bool _isOpen;
+};
+
+
+#endif
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
_autoWhoEnabled(true),
_autoWhoInterval(90),
_autoWhoNickLimit(200),
- _autoWhoDelay(5)
+ _autoWhoDelay(5),
+ _standardCtcp(false)
{
}
SYNC(ARG(delay))
emit autoWhoDelaySet(delay);
}
+
+
+void NetworkConfig::setStandardCtcp(bool enabled)
+{
+ if (_standardCtcp == enabled)
+ return;
+
+ _standardCtcp = enabled;
+ SYNC(ARG(enabled))
+ emit standardCtcpSet(enabled);
+}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
Q_PROPERTY(int autoWhoInterval READ autoWhoInterval WRITE setAutoWhoInterval)
Q_PROPERTY(int autoWhoNickLimit READ autoWhoNickLimit WRITE setAutoWhoNickLimit)
Q_PROPERTY(int autoWhoDelay READ autoWhoDelay WRITE setAutoWhoDelay)
+ Q_PROPERTY(bool standardCtcp READ standardCtcp WRITE setStandardCtcp)
public :
NetworkConfig(const QString &objectName = "GlobalNetworkConfig", QObject *parent = 0);
void setAutoWhoDelay(int);
virtual inline void requestSetAutoWhoDelay(int i) { REQUEST(ARG(i)) }
+ inline bool standardCtcp() const { return _standardCtcp; }
+ void setStandardCtcp(bool);
+ virtual inline void requestSetStandardCtcp(bool b) { REQUEST(ARG(b)) }
+
signals:
void pingTimeoutEnabledSet(bool);
void pingIntervalSet(int);
void autoWhoIntervalSet(int);
// void autoWhoNickLimitSet(int);
void autoWhoDelaySet(int);
+ void standardCtcpSet(bool);
// void setPingTimeoutEnabledRequested(bool);
// void setPingIntervalRequested(int);
int _autoWhoInterval;
int _autoWhoNickLimit;
int _autoWhoDelay;
+
+ bool _standardCtcp;
};
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef PROTOCOL_H_
+#define PROTOCOL_H_
+
+#include <QByteArray>
+#include <QDateTime>
+#include <QVariantList>
+
+namespace Protocol {
+
+/*** handled by SignalProxy ***/
+
+class SyncMessage
+{
+public:
+ inline SyncMessage(const QByteArray &className, const QString &objectName, const QByteArray &slotName, const QVariantList ¶ms)
+ : _className(className), _objectName(objectName), _slotName(slotName), _params(params) {}
+
+ inline QByteArray className() const { return _className; }
+ inline QString objectName() const { return _objectName; }
+ inline QByteArray slotName() const { return _slotName; }
+
+ inline QVariantList params() const { return _params; }
+
+private:
+ QByteArray _className;
+ QString _objectName;
+ QByteArray _slotName;
+ QVariantList _params;
+};
+
+
+class RpcCall
+{
+public:
+ inline RpcCall(const QByteArray &slotName, const QVariantList ¶ms)
+ : _slotName(slotName), _params(params) {}
+
+ inline QByteArray slotName() const { return _slotName; }
+ inline QVariantList params() const { return _params; }
+
+private:
+ QByteArray _slotName;
+ QVariantList _params;
+};
+
+
+class InitRequest
+{
+public:
+ inline InitRequest(const QByteArray &className, const QString &objectName)
+ : _className(className), _objectName(objectName) {}
+
+ inline QByteArray className() const { return _className; }
+ inline QString objectName() const { return _objectName; }
+
+private:
+ QByteArray _className;
+ QString _objectName;
+};
+
+
+class InitData
+{
+public:
+ inline InitData(const QByteArray &className, const QString &objectName, const QVariantMap &initData)
+ : _className(className), _objectName(objectName), _initData(initData) {}
+
+ inline QByteArray className() const { return _className; }
+ inline QString objectName() const { return _objectName; }
+
+ inline QVariantMap initData() const { return _initData; }
+
+private:
+ QByteArray _className;
+ QString _objectName;
+ QVariantMap _initData;
+};
+
+
+/*** handled by RemoteConnection ***/
+
+class HeartBeat
+{
+public:
+ inline HeartBeat(const QDateTime ×tamp) : _timestamp(timestamp) {}
+
+ inline QDateTime timestamp() const { return _timestamp; }
+
+private:
+ QDateTime _timestamp;
+};
+
+
+class HeartBeatReply
+{
+public:
+ inline HeartBeatReply(const QDateTime ×tamp) : _timestamp(timestamp) {}
+
+ inline QDateTime timestamp() const { return _timestamp; }
+
+private:
+ QDateTime _timestamp;
+};
+
+
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "legacypeer.h"
+
+using namespace Protocol;
+
+LegacyPeer::LegacyPeer(QTcpSocket *socket, QObject *parent)
+ : RemotePeer(socket, parent),
+ _blockSize(0),
+ _useCompression(false)
+{
+ _stream.setDevice(socket);
+ _stream.setVersion(QDataStream::Qt_4_2);
+
+ connect(socket, SIGNAL(readyRead()), SLOT(socketDataAvailable()));
+}
+
+
+void LegacyPeer::setSignalProxy(::SignalProxy *proxy)
+{
+ RemotePeer::setSignalProxy(proxy);
+
+ if (proxy) {
+ // enable compression now if requested - the initial handshake is uncompressed in the legacy protocol!
+ _useCompression = socket()->property("UseCompression").toBool();
+ }
+
+}
+
+
+void LegacyPeer::socketDataAvailable()
+{
+ QVariant item;
+ while (readSocketData(item)) {
+ // if no sigproxy is set, we're in handshake mode and let the data be handled elsewhere
+ if (!signalProxy())
+ emit dataReceived(item);
+ else
+ handlePackedFunc(item);
+ }
+}
+
+
+bool LegacyPeer::readSocketData(QVariant &item)
+{
+ if (_blockSize == 0) {
+ if (socket()->bytesAvailable() < 4)
+ return false;
+ _stream >> _blockSize;
+ }
+
+ if (_blockSize > 1 << 22) {
+ close("Peer tried to send package larger than max package size!");
+ return false;
+ }
+
+ if (_blockSize == 0) {
+ close("Peer tried to send 0 byte package!");
+ return false;
+ }
+
+ if (socket()->bytesAvailable() < _blockSize) {
+ emit transferProgress(socket()->bytesAvailable(), _blockSize);
+ return false;
+ }
+
+ emit transferProgress(_blockSize, _blockSize);
+
+ _blockSize = 0;
+
+ if (_useCompression) {
+ QByteArray rawItem;
+ _stream >> rawItem;
+
+ int nbytes = rawItem.size();
+ if (nbytes <= 4) {
+ const char *data = rawItem.constData();
+ if (nbytes < 4 || (data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 0)) {
+ close("Peer sent corrupted compressed data!");
+ return false;
+ }
+ }
+
+ rawItem = qUncompress(rawItem);
+
+ QDataStream itemStream(&rawItem, QIODevice::ReadOnly);
+ itemStream.setVersion(QDataStream::Qt_4_2);
+ itemStream >> item;
+ }
+ else {
+ _stream >> item;
+ }
+
+ if (!item.isValid()) {
+ close("Peer sent corrupt data: unable to load QVariant!");
+ return false;
+ }
+
+ return true;
+}
+
+
+void LegacyPeer::writeSocketData(const QVariant &item)
+{
+ if (!socket()->isOpen()) {
+ qWarning() << Q_FUNC_INFO << "Can't write to a closed socket!";
+ return;
+ }
+
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_2);
+
+ if (_useCompression) {
+ QByteArray rawItem;
+ QDataStream itemStream(&rawItem, QIODevice::WriteOnly);
+ itemStream.setVersion(QDataStream::Qt_4_2);
+ itemStream << item;
+
+ rawItem = qCompress(rawItem);
+
+ out << rawItem;
+ }
+ else {
+ out << item;
+ }
+
+ _stream << block; // also writes the length as part of the serialization format
+}
+
+
+void LegacyPeer::handlePackedFunc(const QVariant &packedFunc)
+{
+ QVariantList params(packedFunc.toList());
+
+ if (params.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Received incompatible data:" << packedFunc;
+ return;
+ }
+
+ RequestType requestType = (RequestType)params.takeFirst().value<int>();
+ switch (requestType) {
+ case Sync: {
+ if (params.count() < 3) {
+ qWarning() << Q_FUNC_INFO << "Received invalid sync call:" << params;
+ return;
+ }
+ QByteArray className = params.takeFirst().toByteArray();
+ QString objectName = params.takeFirst().toString();
+ QByteArray slotName = params.takeFirst().toByteArray();
+ handle(Protocol::SyncMessage(className, objectName, slotName, params));
+ break;
+ }
+ case RpcCall: {
+ if (params.empty()) {
+ qWarning() << Q_FUNC_INFO << "Received empty RPC call!";
+ return;
+ }
+ QByteArray slotName = params.takeFirst().toByteArray();
+ handle(Protocol::RpcCall(slotName, params));
+ break;
+ }
+ case InitRequest: {
+ if (params.count() != 2) {
+ qWarning() << Q_FUNC_INFO << "Received invalid InitRequest:" << params;
+ return;
+ }
+ QByteArray className = params[0].toByteArray();
+ QString objectName = params[1].toString();
+ handle(Protocol::InitRequest(className, objectName));
+ break;
+ }
+ case InitData: {
+ if (params.count() != 3) {
+ qWarning() << Q_FUNC_INFO << "Received invalid InitData:" << params;
+ return;
+ }
+ QByteArray className = params[0].toByteArray();
+ QString objectName = params[1].toString();
+ QVariantMap initData = params[2].toMap();
+ handle(Protocol::InitData(className, objectName, initData));
+ break;
+ }
+ case HeartBeat: {
+ if (params.count() != 1) {
+ qWarning() << Q_FUNC_INFO << "Received invalid HeartBeat:" << params;
+ return;
+ }
+ // The legacy protocol would only send a QTime, no QDateTime
+ // so we assume it's sent today, which works in exactly the same cases as it did in the old implementation
+ QDateTime dateTime = QDateTime::currentDateTimeUtc();
+ dateTime.setTime(params[0].toTime());
+ handle(Protocol::HeartBeat(dateTime));
+ break;
+ }
+ case HeartBeatReply: {
+ if (params.count() != 1) {
+ qWarning() << Q_FUNC_INFO << "Received invalid HeartBeat:" << params;
+ return;
+ }
+ // The legacy protocol would only send a QTime, no QDateTime
+ // so we assume it's sent today, which works in exactly the same cases as it did in the old implementation
+ QDateTime dateTime = QDateTime::currentDateTimeUtc();
+ dateTime.setTime(params[0].toTime());
+ handle(Protocol::HeartBeatReply(dateTime));
+ break;
+ }
+
+ }
+}
+
+
+void LegacyPeer::dispatch(const Protocol::SyncMessage &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)Sync << msg.className() << msg.objectName() << msg.slotName() << msg.params());
+}
+
+
+void LegacyPeer::dispatch(const Protocol::RpcCall &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)RpcCall << msg.slotName() << msg.params());
+}
+
+
+void LegacyPeer::dispatch(const Protocol::InitRequest &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)InitRequest << msg.className() << msg.objectName());
+}
+
+
+void LegacyPeer::dispatch(const Protocol::InitData &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)InitData << msg.className() << msg.objectName() << msg.initData());
+}
+
+
+void LegacyPeer::dispatch(const Protocol::HeartBeat &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)HeartBeat << msg.timestamp().time());
+}
+
+
+void LegacyPeer::dispatch(const Protocol::HeartBeatReply &msg)
+{
+ dispatchPackedFunc(QVariantList() << (qint16)HeartBeatReply << msg.timestamp().time());
+}
+
+
+void LegacyPeer::dispatchPackedFunc(const QVariantList &packedFunc)
+{
+ writeSocketData(QVariant(packedFunc));
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef LEGACYPEER_H
+#define LEGACYPEER_H
+
+#include <QDataStream>
+
+#include "../../remotepeer.h"
+
+class QDataStream;
+
+class LegacyPeer : public RemotePeer
+{
+ Q_OBJECT
+
+public:
+ enum RequestType {
+ Sync = 1,
+ RpcCall,
+ InitRequest,
+ InitData,
+ HeartBeat,
+ HeartBeatReply
+ };
+
+ LegacyPeer(QTcpSocket *socket, QObject *parent = 0);
+ ~LegacyPeer() {}
+
+ void setSignalProxy(SignalProxy *proxy);
+
+ void dispatch(const Protocol::SyncMessage &msg);
+ void dispatch(const Protocol::RpcCall &msg);
+ void dispatch(const Protocol::InitRequest &msg);
+ void dispatch(const Protocol::InitData &msg);
+
+ void dispatch(const Protocol::HeartBeat &msg);
+ void dispatch(const Protocol::HeartBeatReply &msg);
+
+ // FIXME: this is only used for the auth phase and should be replaced by something more generic
+ void writeSocketData(const QVariant &item);
+
+private slots:
+ void socketDataAvailable();
+
+private:
+ bool readSocketData(QVariant &item);
+ void handlePackedFunc(const QVariant &packedFunc);
+ void dispatchPackedFunc(const QVariantList &packedFunc);
+
+ QDataStream _stream;
+ qint32 _blockSize;
+ bool _useCompression;
+};
+
+#endif
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "bufferinfo.h"
#include "types.h"
#include "syncableobject.h"
+#include "logger.h"
Quassel::BuildInfo Quassel::_buildInfo;
AbstractCliParser *Quassel::_cliParser = 0;
quasselTranslator->setObjectName("QuasselTr");
qApp->installTranslator(quasselTranslator);
- QLocale::setDefault(locale);
+#if QT_VERSION >= 0x040800
+ bool success = qtTranslator->load(locale, QString("qt_%1"), translationDirPath());
+ if (!success)
+ qtTranslator->load(locale, QString("qt_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
+ quasselTranslator->load(locale, QString(""), translationDirPath());
+#else
+ QString localeName = locale.name();
+
+ // if the user did not specify a language in the settings, the system locale
+ // is used, but Qt < 4.8 does not respect language settings. This bit is
+ // based on QLocale::uiLanguages() as in Qt 4.8.3
+ if (locale == QLocale::system()) {
+ // FIXME: does it make sense to set the locale to the system locale?
+ QLocale::setDefault(locale);
+ QVariant res = QSystemLocale().query(QSystemLocale::UILanguages, QVariant());
+ if (!res.isNull()) {
+ QString newName = res.toStringList()[0];
+ if (!newName.isEmpty()) {
+ localeName = newName.replace('-', "_"); // silly Qt.
+ }
+ }
+ }
- bool success = qtTranslator->load(QString("qt_%1").arg(locale.name()), translationDirPath());
+ bool success = qtTranslator->load(QString("qt_%1").arg(localeName), translationDirPath());
if (!success)
- qtTranslator->load(QString("qt_%1").arg(locale.name()), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
- quasselTranslator->load(QString("%1").arg(locale.name()), translationDirPath());
+ qtTranslator->load(QString("qt_%1").arg(localeName), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
+ quasselTranslator->load(QString("%1").arg(localeName), translationDirPath());
+#endif
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
enum Feature {
SynchronizedMarkerLine = 0x0001,
SaslAuthentication = 0x0002,
+ SaslExternal = 0x0004,
- NumFeatures = 0x0002
+ NumFeatures = 0x0004
};
Q_DECLARE_FLAGS(Features, Feature);
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <QHostAddress>
+#include <QTimer>
+
+#ifdef HAVE_SSL
+# include <QSslSocket>
+#endif
+
+#include "remotepeer.h"
+
+using namespace Protocol;
+
+RemotePeer::RemotePeer(QTcpSocket *socket, QObject *parent)
+ : SignalProxy::AbstractPeer(parent),
+ _socket(socket),
+ _signalProxy(0),
+ _heartBeatTimer(new QTimer(this)),
+ _heartBeatCount(0),
+ _lag(0)
+{
+ socket->setParent(this);
+ connect(socket, SIGNAL(disconnected()), SIGNAL(disconnected()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError)));
+
+#ifdef HAVE_SSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
+ if (sslSocket)
+ connect(sslSocket, SIGNAL(encrypted()), SIGNAL(secureStateChanged()));
+#endif
+
+ connect(_heartBeatTimer, SIGNAL(timeout()), SLOT(sendHeartBeat()));
+}
+
+
+QString RemotePeer::description() const
+{
+ if (socket())
+ return socket()->peerAddress().toString();
+
+ return QString();
+}
+
+
+::SignalProxy *RemotePeer::signalProxy() const
+{
+ return _signalProxy;
+}
+
+
+void RemotePeer::setSignalProxy(::SignalProxy *proxy)
+{
+ if (proxy == _signalProxy)
+ return;
+
+ if (!proxy) {
+ _heartBeatTimer->stop();
+ disconnect(signalProxy(), 0, this, 0);
+ _signalProxy = 0;
+ if (isOpen())
+ close();
+ }
+ else {
+ if (signalProxy()) {
+ qWarning() << Q_FUNC_INFO << "Setting another SignalProxy not supported, ignoring!";
+ return;
+ }
+ _signalProxy = proxy;
+ connect(proxy, SIGNAL(heartBeatIntervalChanged(int)), SLOT(changeHeartBeatInterval(int)));
+ _heartBeatTimer->setInterval(proxy->heartBeatInterval() * 1000);
+ _heartBeatTimer->start();
+ }
+}
+
+
+void RemotePeer::changeHeartBeatInterval(int secs)
+{
+ if(secs <= 0)
+ _heartBeatTimer->stop();
+ else {
+ _heartBeatTimer->setInterval(secs * 1000);
+ _heartBeatTimer->start();
+ }
+}
+
+
+int RemotePeer::lag() const
+{
+ return _lag;
+}
+
+
+QTcpSocket *RemotePeer::socket() const
+{
+ return _socket;
+}
+
+
+bool RemotePeer::isSecure() const
+{
+ if (socket()) {
+ if (isLocal())
+ return true;
+#ifdef HAVE_SSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
+ if (sslSocket && sslSocket->isEncrypted())
+ return true;
+#endif
+ }
+ return false;
+}
+
+
+bool RemotePeer::isLocal() const
+{
+ if (socket()) {
+ if (socket()->peerAddress() == QHostAddress::LocalHost || socket()->peerAddress() == QHostAddress::LocalHostIPv6)
+ return true;
+ }
+ return false;
+}
+
+
+bool RemotePeer::isOpen() const
+{
+ return socket() && socket()->state() == QTcpSocket::ConnectedState;
+}
+
+
+void RemotePeer::close(const QString &reason)
+{
+ if (!reason.isEmpty()) {
+ qWarning() << "Disconnecting:" << reason;
+ }
+
+ if (socket() && socket()->state() != QTcpSocket::UnconnectedState) {
+ socket()->disconnectFromHost();
+ }
+}
+
+
+void RemotePeer::handle(const HeartBeat &heartBeat)
+{
+ dispatch(HeartBeatReply(heartBeat.timestamp()));
+}
+
+
+void RemotePeer::handle(const HeartBeatReply &heartBeatReply)
+{
+ _heartBeatCount = 0;
+#if QT_VERSION < 0x040700
+ emit lagUpdated(heartBeatReply.timestamp().time().msecsTo(QTime::currentTime()) / 2);
+#else
+ emit lagUpdated(heartBeatReply.timestamp().msecsTo(QDateTime::currentDateTime()) / 2);
+#endif
+}
+
+
+void RemotePeer::sendHeartBeat()
+{
+ if (signalProxy()->maxHeartBeatCount() > 0 && _heartBeatCount >= signalProxy()->maxHeartBeatCount()) {
+ qWarning() << "Disconnecting peer:" << description()
+ << "(didn't receive a heartbeat for over" << _heartBeatCount *_heartBeatTimer->interval() / 1000 << "seconds)";
+ socket()->close();
+ _heartBeatTimer->stop();
+ return;
+ }
+
+ if (_heartBeatCount > 0) {
+ _lag = _heartBeatCount * _heartBeatTimer->interval();
+ emit lagUpdated(_lag);
+ }
+
+ dispatch(HeartBeat(QDateTime::currentDateTime()));
+ ++_heartBeatCount;
+}
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2013 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef REMOTEPEER_H
+#define REMOTEPEER_H
+
+#include <QDateTime>
+#include <QTcpSocket>
+
+#include "protocol.h"
+#include "signalproxy.h"
+
+class QTimer;
+
+class RemotePeer : public SignalProxy::AbstractPeer
+{
+ Q_OBJECT
+
+public:
+ RemotePeer(QTcpSocket *socket, QObject *parent = 0);
+ virtual ~RemotePeer() {};
+
+ void setSignalProxy(SignalProxy *proxy);
+
+ QString description() const;
+
+ bool isOpen() const;
+ bool isSecure() const;
+ bool isLocal() const;
+
+ int lag() const;
+
+ bool compressionEnabled() const;
+ void setCompressionEnabled(bool enabled);
+
+ QTcpSocket *socket() const;
+
+ // this is only used for the auth phase and should be replaced by something more generic
+ virtual void writeSocketData(const QVariant &item) = 0;
+
+public slots:
+ void close(const QString &reason = QString());
+
+signals:
+ // this is only used for the auth phase and should be replaced by something more generic
+ void dataReceived(const QVariant &item);
+
+ void disconnected();
+ void error(QAbstractSocket::SocketError);
+
+ void transferProgress(int current, int max);
+
+protected:
+ SignalProxy *signalProxy() const;
+
+ template<class T>
+ void handle(const T &protoMessage);
+
+ // These protocol messages get handled internally and won't reach SignalProxy
+ void handle(const Protocol::HeartBeat &heartBeat);
+ void handle(const Protocol::HeartBeatReply &heartBeatReply);
+ virtual void dispatch(const Protocol::HeartBeat &msg) = 0;
+ virtual void dispatch(const Protocol::HeartBeatReply &msg) = 0;
+
+private slots:
+ void sendHeartBeat();
+ void changeHeartBeatInterval(int secs);
+
+private:
+ QTcpSocket *_socket;
+ SignalProxy *_signalProxy;
+ QTimer *_heartBeatTimer;
+ int _heartBeatCount;
+ int _lag;
+};
+
+// Template methods we need in the header
+template<class T> inline
+void RemotePeer::handle(const T &protoMessage)
+{
+ if (!signalProxy()) {
+ qWarning() << Q_FUNC_INFO << "Cannot handle messages without a SignalProxy!";
+ return;
+ }
+
+ // _heartBeatCount = 0;
+
+ signalProxy()->handle(this, protoMessage);
+}
+
+
+#endif
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include <QEvent>
#include <QCoreApplication>
+#include "protocol.h"
#include "syncableobject.h"
#include "util.h"
-// ==================================================
-// PeerSignalEvent
-// ==================================================
-class PeerSignalEvent : public QEvent
-{
-public:
- PeerSignalEvent(SignalProxy *sender, SignalProxy::RequestType requestType, const QVariantList ¶ms) : QEvent(QEvent::Type(SignalProxy::PeerSignal)), sender(sender), requestType(requestType), params(params) {}
- SignalProxy *sender;
- SignalProxy::RequestType requestType;
- QVariantList params;
-};
-
+using namespace Protocol;
class RemovePeerEvent : public QEvent
{
public:
- RemovePeerEvent(QObject *peer) : QEvent(QEvent::Type(SignalProxy::RemovePeer)), peer(peer) {}
- QObject *peer;
+ RemovePeerEvent(SignalProxy::AbstractPeer *peer) : QEvent(QEvent::Type(SignalProxy::RemovePeerEvent)), peer(peer) {}
+ SignalProxy::AbstractPeer *peer;
};
const Signal &signal = _slots[_id];
QVariantList params;
- params << signal.signature;
const QList<int> &argTypes = eMeta->argTypes(signal.signalId);
for (int i = 0; i < argTypes.size(); i++) {
params << QVariant(argTypes[i], _a[i+1]);
}
- proxy()->dispatchSignal(SignalProxy::RpcCall, params);
+ proxy()->dispatch(RpcCall(signal.signature, params));
}
_id -= _slots.count();
}
}
-// ==================================================
-// Peers
-// ==================================================
-void SignalProxy::IODevicePeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms)
-{
- QVariantList packedFunc;
- packedFunc << (qint16)requestType
- << params;
- dispatchPackedFunc(QVariant(packedFunc));
-}
-
-
-bool SignalProxy::IODevicePeer::isSecure() const
-{
-#ifdef HAVE_SSL
- QSslSocket *sslSocket = qobject_cast<QSslSocket *>(_device);
- if (sslSocket)
- return sslSocket->isEncrypted() || sslSocket->localAddress() == QHostAddress::LocalHost || sslSocket->localAddress() == QHostAddress::LocalHostIPv6;
-#endif
-
- QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(_device);
- if (socket)
- return socket->localAddress() == QHostAddress::LocalHost || socket->localAddress() == QHostAddress::LocalHostIPv6;
-
- return false;
-}
-
-
-QString SignalProxy::IODevicePeer::address() const
-{
- QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(_device);
- if (socket)
- return socket->peerAddress().toString();
- else
- return QString();
-}
-
-
-void SignalProxy::SignalProxyPeer::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms)
-{
- Qt::ConnectionType type = QThread::currentThread() == receiver->thread()
- ? Qt::DirectConnection
- : Qt::QueuedConnection;
-
- if (type == Qt::DirectConnection) {
- receiver->receivePeerSignal(sender, requestType, params);
- }
- else {
- QCoreApplication::postEvent(receiver, new PeerSignalEvent(sender, requestType, params));
- }
-}
-
-
// ==================================================
// SignalProxy
// ==================================================
}
-SignalProxy::SignalProxy(ProxyMode mode, QIODevice *device, QObject *parent)
- : QObject(parent)
-{
- setProxyMode(mode);
- addPeer(device);
- init();
-}
-
-
SignalProxy::~SignalProxy()
{
QHash<QByteArray, ObjectId>::iterator classIter = _syncSlave.begin();
void SignalProxy::setProxyMode(ProxyMode mode)
{
- PeerHash::iterator peer = _peers.begin();
- while (peer != _peers.end()) {
- if ((*peer)->type() != AbstractPeer::IODevicePeer) {
- IODevicePeer *ioPeer = static_cast<IODevicePeer *>(*peer);
- if (ioPeer->isOpen()) {
- qWarning() << "SignalProxy: Cannot change proxy mode while connected";
- return;
- }
- }
- if ((*peer)->type() != AbstractPeer::SignalProxyPeer) {
- qWarning() << "SignalProxy: Cannot change proxy mode while connected to another internal SignalProxy";
- return;
- }
- peer++;
+ if (_peers.count()) {
+ qWarning() << Q_FUNC_INFO << "Cannot change proxy mode while connected";
+ return;
}
_proxyMode = mode;
_heartBeatInterval = 0;
_maxHeartBeatCount = 0;
_signalRelay = new SignalRelay(this);
- connect(&_heartBeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartBeat()));
setHeartBeatInterval(30);
setMaxHeartBeatCount(2);
- _heartBeatTimer.start();
_secure = false;
updateSecureState();
}
void SignalProxy::initClient()
{
- attachSlot("__objectRenamed__", this, SLOT(objectRenamed(QByteArray, QString, QString)));
-}
-
-
-bool SignalProxy::addPeer(QIODevice *iodev)
-{
- if (!iodev)
- return false;
-
- if (_peers.contains(iodev))
- return true;
-
- if (proxyMode() == Client && !_peers.isEmpty()) {
- qWarning("SignalProxy: only one peer allowed in client mode!");
- return false;
- }
-
- if (!iodev->isOpen()) {
- qWarning("SignalProxy::addPeer(QIODevice *iodev): iodev needs to be open!");
- return false;
- }
-
- connect(iodev, SIGNAL(disconnected()), this, SLOT(removePeerBySender()));
- connect(iodev, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
-
-#ifdef HAVE_SSL
- QSslSocket *sslSocket = qobject_cast<QSslSocket *>(iodev);
- if (sslSocket) {
- connect(iodev, SIGNAL(encrypted()), this, SLOT(updateSecureState()));
- }
-#endif
-
- if (!iodev->parent())
- iodev->setParent(this);
-
- _peers[iodev] = new IODevicePeer(iodev, iodev->property("UseCompression").toBool());
-
- if (_peers.count() == 1)
- emit connected();
-
- updateSecureState();
- return true;
+ attachSlot("__objectRenamed__", this, SLOT(objectRenamed(QByteArray,QString,QString)));
}
void SignalProxy::setHeartBeatInterval(int secs)
{
- if (secs != _heartBeatInterval) {
+ if (_heartBeatInterval != secs) {
_heartBeatInterval = secs;
- _heartBeatTimer.setInterval(secs * 1000);
+ emit heartBeatIntervalChanged(secs);
}
}
void SignalProxy::setMaxHeartBeatCount(int max)
{
- _maxHeartBeatCount = max;
+ if (_maxHeartBeatCount != max) {
+ _maxHeartBeatCount = max;
+ emit maxHeartBeatCountChanged(max);
+ }
}
-bool SignalProxy::addPeer(SignalProxy *proxy)
+bool SignalProxy::addPeer(AbstractPeer *peer)
{
- if (!proxy)
+ if (!peer)
return false;
- if (proxyMode() == proxy->proxyMode()) {
- qWarning() << "SignalProxy::addPeer(): adding a SignalProxy as peer requires one proxy to be server and one client!";
+ if (_peers.contains(peer))
+ return true;
+
+ if (!peer->isOpen()) {
+ qWarning("SignalProxy: peer needs to be open!");
return false;
}
- if (_peers.contains(proxy)) {
- return true;
+ if (proxyMode() == Client) {
+ if (!_peers.isEmpty()) {
+ qWarning("SignalProxy: only one peer allowed in client mode!");
+ return false;
+ }
+ connect(peer, SIGNAL(lagUpdated(int)), SIGNAL(lagUpdated(int)));
}
- if (proxyMode() == Client && !_peers.isEmpty()) {
- qWarning("SignalProxy: only one peer allowed in client mode!");
- return false;
- }
+ connect(peer, SIGNAL(disconnected()), SLOT(removePeerBySender()));
+ connect(peer, SIGNAL(secureStateChanged(bool)), SLOT(updateSecureState()));
+
+ if (!peer->parent())
+ peer->setParent(this);
- _peers[proxy] = new SignalProxyPeer(this, proxy);
- proxy->addPeer(this);
+ _peers.insert(peer);
+
+ peer->setSignalProxy(this);
if (_peers.count() == 1)
emit connected();
{
Q_ASSERT(proxyMode() == Server || _peers.count() <= 1);
// wee need to copy that list since we modify it in the loop
- QList<QObject *> peers = _peers.keys();
- foreach(QObject *peer, peers) {
+ QSet<AbstractPeer *> peers = _peers;
+ foreach(AbstractPeer *peer, peers) {
removePeer(peer);
}
}
-void SignalProxy::removePeer(QObject *dev)
+void SignalProxy::removePeer(AbstractPeer *peer)
{
+ if (!peer) {
+ qWarning() << Q_FUNC_INFO << "Trying to remove a null peer!";
+ return;
+ }
+
if (_peers.isEmpty()) {
qWarning() << "SignalProxy::removePeer(): No peers in use!";
return;
}
- Q_ASSERT(dev);
- if (!_peers.contains(dev)) {
- qWarning() << "SignalProxy: unknown Peer" << dev;
+ if (!_peers.contains(peer)) {
+ qWarning() << "SignalProxy: unknown Peer" << peer;
return;
}
- AbstractPeer *peer = _peers[dev];
- _peers.remove(dev);
-
- disconnect(dev, 0, this, 0);
- if (peer->type() == AbstractPeer::IODevicePeer)
- emit peerRemoved(static_cast<QIODevice *>(dev));
-
- if (peer->type() == AbstractPeer::SignalProxyPeer) {
- SignalProxy *proxy = static_cast<SignalProxy *>(dev);
- if (proxy->_peers.contains(this))
- proxy->removePeer(this);
- }
+ disconnect(peer, 0, this, 0);
+ peer->setSignalProxy(0);
- if (dev->parent() == this)
- dev->deleteLater();
+ _peers.remove(peer);
+ emit peerRemoved(peer);
- delete peer;
+ if (peer->parent() == this)
+ peer->deleteLater();
updateSecureState();
void SignalProxy::removePeerBySender()
{
- removePeer(sender());
+ removePeer(qobject_cast<SignalProxy::AbstractPeer *>(sender()));
}
const QByteArray className(meta->className());
objectRenamed(className, newname, oldname);
- QVariantList params;
- params << "__objectRenamed__" << className << newname << oldname;
- dispatchSignal(RpcCall, params);
+ dispatch(RpcCall("__objectRenamed__", QVariantList() << className << newname << oldname));
}
}
-void SignalProxy::dispatchSignal(const RequestType &requestType, const QVariantList ¶ms)
+template<class T>
+void SignalProxy::dispatch(const T &protoMessage)
{
- QVariant packedFunc(QVariantList() << (qint16)requestType << params);
- PeerHash::iterator peer = _peers.begin();
- while (peer != _peers.end()) {
- switch ((*peer)->type()) {
- case AbstractPeer::IODevicePeer:
- {
- IODevicePeer *ioPeer = static_cast<IODevicePeer *>(*peer);
- if (ioPeer->isOpen())
- ioPeer->dispatchPackedFunc(packedFunc);
- else
- QCoreApplication::postEvent(this, new RemovePeerEvent(peer.key()));
- }
- break;
- case AbstractPeer::SignalProxyPeer:
- (*peer)->dispatchSignal(requestType, params);
- break;
- default:
- Q_ASSERT(false); // there shouldn't be any peers with wrong / unknown type
- }
- peer++;
- }
-}
-
-
-void SignalProxy::receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc)
-{
- QVariantList params(packedFunc.toList());
-
- if (params.isEmpty()) {
- qWarning() << "SignalProxy::receivePeerSignal(): received incompatible Data:" << packedFunc;
- return;
- }
-
- RequestType requestType = (RequestType)params.takeFirst().value<int>();
- receivePeerSignal(sender, requestType, params);
-}
-
-
-void SignalProxy::receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms)
-{
- switch (requestType) {
- // list all RequestTypes that shouldnot trigger a heartbeat counter reset here
- case HeartBeatReply:
- break;
- default:
- if (sender->type() == AbstractPeer::IODevicePeer) {
- IODevicePeer *ioPeer = static_cast<IODevicePeer *>(sender);
- ioPeer->sentHeartBeats = 0;
- }
- }
-
- // qDebug() << "SignalProxy::receivePeerSignal)" << requestType << params;
- switch (requestType) {
- case RpcCall:
- if (params.empty())
- qWarning() << "SignalProxy::receivePeerSignal(): received empty RPC-Call";
+ foreach (AbstractPeer *peer, _peers) {
+ if (peer->isOpen())
+ peer->dispatch(protoMessage);
else
- handleSignal(params);
- //handleSignal(params.takeFirst().toByteArray(), params);
- break;
-
- case Sync:
- handleSync(sender, params);
- break;
-
- case InitRequest:
- handleInitRequest(sender, params);
- break;
-
- case InitData:
- handleInitData(sender, params);
- break;
-
- case HeartBeat:
- receiveHeartBeat(sender, params);
- break;
-
- case HeartBeatReply:
- receiveHeartBeatReply(sender, params);
- break;
-
- default:
- qWarning() << "SignalProxy::receivePeerSignal(): received undefined CallType" << requestType << params;
- }
-}
-
-
-void SignalProxy::receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms)
-{
- if (!_peers.contains(sender)) {
- // we output only the pointer value. otherwise Qt would try to pretty print. As the object might already been destroyed, this is not a good idea.
- qWarning() << "SignalProxy::receivePeerSignal(): received Signal from unknown Proxy" << reinterpret_cast<void *>(sender);
- return;
+ QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
}
- receivePeerSignal(_peers[sender], requestType, params);
}
-void SignalProxy::handleSync(AbstractPeer *sender, QVariantList params)
+void SignalProxy::handle(SignalProxy::AbstractPeer *peer, const SyncMessage &syncMessage)
{
- if (params.count() < 3) {
- qWarning() << "received invalid Sync call" << params;
- return;
- }
-
- QByteArray className = params.takeFirst().toByteArray();
- QString objectName = params.takeFirst().toString();
- QByteArray slot = params.takeFirst().toByteArray();
-
- if (!_syncSlave.contains(className) || !_syncSlave[className].contains(objectName)) {
- qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName)
- << params;
+ if (!_syncSlave.contains(syncMessage.className()) || !_syncSlave[syncMessage.className()].contains(syncMessage.objectName())) {
+ qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
+ << syncMessage.params();
return;
}
- SyncableObject *receiver = _syncSlave[className][objectName];
+ SyncableObject *receiver = _syncSlave[syncMessage.className()][syncMessage.objectName()];
ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
- if (!eMeta->slotMap().contains(slot)) {
- qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(QString(className)).arg(QString(slot)).arg(objectName)
- << params;
+ if (!eMeta->slotMap().contains(syncMessage.slotName())) {
+ qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
+ << syncMessage.params();
return;
}
- int slotId = eMeta->slotMap()[slot];
+ int slotId = eMeta->slotMap()[syncMessage.slotName()];
if (proxyMode() != eMeta->receiverMode(slotId)) {
qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed. Wrong ProxyMode!", eMeta->methodName(slotId).constData());
return;
}
QVariant returnValue((QVariant::Type)eMeta->returnType(slotId));
- if (!invokeSlot(receiver, slotId, params, returnValue)) {
+ if (!invokeSlot(receiver, slotId, syncMessage.params(), returnValue)) {
qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", eMeta->methodName(slotId).constData());
return;
}
if (returnValue.type() != QVariant::Invalid && eMeta->receiveMap().contains(slotId)) {
int receiverId = eMeta->receiveMap()[slotId];
QVariantList returnParams;
- returnParams << className
- << objectName
- << eMeta->methodName(receiverId);
- //QByteArray(receiver->metaObject()->method(receiverId).signature());
if (eMeta->argTypes(receiverId).count() > 1)
- returnParams << params;
+ returnParams << syncMessage.params();
returnParams << returnValue;
- sender->dispatchSignal(Sync, returnParams);
+ peer->dispatch(SyncMessage(syncMessage.className(), syncMessage.objectName(), eMeta->methodName(receiverId), returnParams));
}
// send emit update signal
}
-void SignalProxy::handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms)
+void SignalProxy::handle(SignalProxy::AbstractPeer *peer, const InitRequest &initRequest)
{
- if (params.count() != 2) {
- qWarning() << "SignalProxy::handleInitRequest() received initRequest with invalid param Count:"
- << params;
- return;
- }
-
- QByteArray className(params[0].toByteArray());
- QString objectName(params[1].toString());
-
- if (!_syncSlave.contains(className)) {
+ if (!_syncSlave.contains(initRequest.className())) {
qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Class:"
- << className;
+ << initRequest.className();
return;
}
- if (!_syncSlave[className].contains(objectName)) {
+ if (!_syncSlave[initRequest.className()].contains(initRequest.objectName())) {
qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Object:"
- << className << objectName;
+ << initRequest.className() << initRequest.objectName();
return;
}
- SyncableObject *obj = _syncSlave[className][objectName];
-
- QVariantList params_;
- params_ << className
- << objectName
- << initData(obj);
-
- sender->dispatchSignal(InitData, params_);
+ SyncableObject *obj = _syncSlave[initRequest.className()][initRequest.objectName()];
+ peer->dispatch(InitData(initRequest.className(), initRequest.objectName(), initData(obj)));
}
-void SignalProxy::handleInitData(AbstractPeer *sender, const QVariantList ¶ms)
+void SignalProxy::handle(SignalProxy::AbstractPeer *peer, const InitData &initData)
{
- Q_UNUSED(sender)
- if (params.count() != 3) {
- qWarning() << "SignalProxy::handleInitData() received initData with invalid param Count:"
- << params;
- return;
- }
-
- QByteArray className(params[0].toByteArray());
- QString objectName(params[1].toString());
- QVariantMap propertyMap(params[2].toMap());
+ Q_UNUSED(peer)
- if (!_syncSlave.contains(className)) {
+ if (!_syncSlave.contains(initData.className())) {
qWarning() << "SignalProxy::handleInitData() received initData for unregistered Class:"
- << className;
+ << initData.className();
return;
}
- if (!_syncSlave[className].contains(objectName)) {
+ if (!_syncSlave[initData.className()].contains(initData.objectName())) {
qWarning() << "SignalProxy::handleInitData() received initData for unregistered Object:"
- << className << objectName;
+ << initData.className() << initData.objectName();
return;
}
- SyncableObject *obj = _syncSlave[className][objectName];
- setInitData(obj, propertyMap);
+ SyncableObject *obj = _syncSlave[initData.className()][initData.objectName()];
+ setInitData(obj, initData.initData());
}
-//void SignalProxy::handleSignal(const QByteArray &funcName, const QVariantList ¶ms) {
-void SignalProxy::handleSignal(const QVariantList &data)
+void SignalProxy::handle(SignalProxy::AbstractPeer *peer, const RpcCall &rpcCall)
{
- QVariantList params = data;
- QByteArray funcName = params.takeFirst().toByteArray();
+ Q_UNUSED(peer)
QObject *receiver;
int methodId;
- SlotHash::const_iterator slot = _attachedSlots.constFind(funcName);
- while (slot != _attachedSlots.constEnd() && slot.key() == funcName) {
+ SlotHash::const_iterator slot = _attachedSlots.constFind(rpcCall.slotName());
+ while (slot != _attachedSlots.constEnd() && slot.key() == rpcCall.slotName()) {
receiver = (*slot).first;
methodId = (*slot).second;
- if (!invokeSlot(receiver, methodId, params)) {
+ if (!invokeSlot(receiver, methodId, rpcCall.params())) {
ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
qWarning("SignalProxy::handleSignal(): invokeMethod for \"%s\" failed ", eMeta->methodName(methodId).constData());
}
- slot++;
+ ++slot;
}
}
}
-void SignalProxy::dataAvailable()
-{
- // yet again. it's a private slot. no need for checks.
- QIODevice *ioDev = qobject_cast<QIODevice *>(sender());
- Q_ASSERT(_peers.contains(ioDev) && _peers[ioDev]->type() == AbstractPeer::IODevicePeer);
- IODevicePeer *peer = static_cast<IODevicePeer *>(_peers[ioDev]);
- QVariant var;
- while (peer->readData(var))
- receivePackedFunc(peer, var);
-}
-
-
-void SignalProxy::writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed)
-{
- QAbstractSocket *sock = qobject_cast<QAbstractSocket *>(dev);
- if (!dev->isOpen() || (sock && sock->state() != QAbstractSocket::ConnectedState)) {
- qWarning("SignalProxy: Can't call write on a closed device");
- return;
- }
-
- QByteArray block;
- QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_2);
- out << (quint32)0;
-
- if (compressed) {
- QByteArray rawItem;
- QDataStream itemStream(&rawItem, QIODevice::WriteOnly);
-
- itemStream.setVersion(QDataStream::Qt_4_2);
- itemStream << item;
-
- rawItem = qCompress(rawItem);
-
- out << rawItem;
- }
- else {
- out << item;
- }
-
- out.device()->seek(0);
- out << (quint32)(block.size() - sizeof(quint32));
-
- dev->write(block);
-}
-
-
-bool SignalProxy::readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed)
-{
- if (!dev)
- return false;
-
- QDataStream in(dev);
- in.setVersion(QDataStream::Qt_4_2);
-
- if (blockSize == 0) {
- if (dev->bytesAvailable() < (int)sizeof(quint32)) return false;
- in >> blockSize;
- }
-
- if (blockSize > 1 << 22) {
- disconnectDevice(dev, tr("Peer tried to send package larger than max package size!"));
- return false;
- }
-
- if (blockSize == 0) {
- disconnectDevice(dev, tr("Peer tried to send 0 byte package!"));
- return false;
- }
-
- if (dev->bytesAvailable() < blockSize)
- return false;
-
- blockSize = 0;
-
- if (compressed) {
- QByteArray rawItem;
- in >> rawItem;
-
- int nbytes = rawItem.size();
- if (nbytes <= 4) {
- const char *data = rawItem.constData();
- if (nbytes < 4 || (data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 0)) {
- disconnectDevice(dev, tr("Peer sent corrupted compressed data!"));
- return false;
- }
- }
-
- rawItem = qUncompress(rawItem);
-
- QDataStream itemStream(&rawItem, QIODevice::ReadOnly);
- itemStream.setVersion(QDataStream::Qt_4_2);
- itemStream >> item;
- }
- else {
- in >> item;
- }
-
- if (!item.isValid()) {
- disconnectDevice(dev, tr("Peer sent corrupt data: unable to load QVariant!"));
- return false;
- }
-
- return true;
-}
-
-
void SignalProxy::requestInit(SyncableObject *obj)
{
if (proxyMode() == Server || obj->isInitialized())
return;
- QVariantList params;
- params << obj->syncMetaObject()->className()
- << obj->objectName();
- dispatchSignal(InitRequest, params);
+ dispatch(InitRequest(obj->syncMetaObject()->className(), obj->objectName()));
}
}
-void SignalProxy::sendHeartBeat()
-{
- QVariantList heartBeatParams;
- heartBeatParams << QTime::currentTime();
- QList<IODevicePeer *> toClose;
-
- PeerHash::iterator peer = _peers.begin();
- while (peer != _peers.end()) {
- if ((*peer)->type() == AbstractPeer::IODevicePeer) {
- IODevicePeer *ioPeer = static_cast<IODevicePeer *>(*peer);
- ioPeer->dispatchSignal(SignalProxy::HeartBeat, heartBeatParams);
- if (ioPeer->sentHeartBeats > 0) {
- updateLag(ioPeer, ioPeer->sentHeartBeats * _heartBeatTimer.interval());
- }
- if (maxHeartBeatCount() >= 0 && ioPeer->sentHeartBeats >= maxHeartBeatCount())
- toClose.append(ioPeer);
- else
- ioPeer->sentHeartBeats++;
- }
- ++peer;
- }
-
- foreach(IODevicePeer *ioPeer, toClose) {
- qWarning() << "SignalProxy: Disconnecting peer:" << ioPeer->address()
- << "(didn't receive a heartbeat for over" << ioPeer->sentHeartBeats *_heartBeatTimer.interval() / 1000 << "seconds)";
- ioPeer->close();
- }
-}
-
-
-void SignalProxy::receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms)
-{
- peer->dispatchSignal(SignalProxy::HeartBeatReply, params);
-}
-
-
-void SignalProxy::receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms)
-{
- if (peer->type() != AbstractPeer::IODevicePeer) {
- qWarning() << "SignalProxy::receiveHeartBeatReply: received heart beat from a non IODevicePeer!";
- return;
- }
-
- IODevicePeer *ioPeer = static_cast<IODevicePeer *>(peer);
- ioPeer->sentHeartBeats = 0;
-
- if (params.isEmpty()) {
- qWarning() << "SignalProxy: received heart beat reply with less params then sent from:" << ioPeer->address();
- return;
- }
-
- QTime sendTime = params[0].value<QTime>();
- updateLag(ioPeer, sendTime.msecsTo(QTime::currentTime()) / 2);
-}
-
-
void SignalProxy::customEvent(QEvent *event)
{
- switch (+event->type()) {
- case PeerSignal:
- {
- PeerSignalEvent *e = static_cast<PeerSignalEvent *>(event);
- receivePeerSignal(e->sender, e->requestType, e->params);
- }
+ switch ((int)event->type()) {
+ case RemovePeerEvent: {
+ ::RemovePeerEvent *e = static_cast< ::RemovePeerEvent *>(event);
+ removePeer(e->peer);
event->accept();
break;
- case RemovePeer:
- {
- RemovePeerEvent *e = static_cast<RemovePeerEvent *>(event);
- removePeer(e->peer);
}
- event->accept();
+
default:
+ qWarning() << Q_FUNC_INFO << "Received unknown custom event:" << event->type();
return;
}
}
ExtendedMetaObject *eMeta = extendedMetaObject(obj);
QVariantList params;
- params << eMeta->metaObject()->className()
- << obj->objectName()
- << QByteArray(funcname);
const QList<int> &argTypes = eMeta->argTypes(eMeta->methodId(QByteArray(funcname)));
params << QVariant(argTypes[i], va_arg(ap, void *));
}
- dispatchSignal(Sync, params);
+ dispatch(SyncMessage(eMeta->metaObject()->className(), obj->objectName(), QByteArray(funcname), params));
}
}
-void SignalProxy::updateLag(IODevicePeer *peer, int lag)
-{
- peer->lag = lag;
- if (proxyMode() == Client) {
- emit lagUpdated(lag);
- }
-}
-
-
void SignalProxy::dumpProxyStats()
{
QString mode;
bool wasSecure = _secure;
_secure = !_peers.isEmpty();
- PeerHash::const_iterator peerIter;
- for (peerIter = _peers.constBegin(); peerIter != _peers.constEnd(); peerIter++) {
- _secure &= (*peerIter)->isSecure();
+ foreach (const AbstractPeer *peer, _peers) {
+ _secure &= peer->isSecure();
}
if (wasSecure != _secure)
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#ifndef SIGNALPROXY_H
#define SIGNALPROXY_H
+#include <QAbstractSocket>
#include <QEvent>
#include <QList>
#include <QHash>
#include <QVariant>
#include <QVariantMap>
#include <QPair>
+#include <QSet>
#include <QString>
#include <QByteArray>
#include <QTimer>
+#include "protocol.h"
+
class SyncableObject;
struct QMetaObject;
+
class SignalProxy : public QObject
{
Q_OBJECT
- class AbstractPeer;
- class IODevicePeer;
- class SignalProxyPeer;
-
class SignalRelay;
public:
+ class AbstractPeer;
+
enum ProxyMode {
Server,
Client
};
- enum RequestType {
- Sync = 1,
- RpcCall,
- InitRequest,
- InitData,
- HeartBeat,
- HeartBeatReply
- };
-
- enum ClientConnectionType {
- SignalProxyConnection,
- IODeviceConnection
- };
-
- enum CustomEvents {
- PeerSignal = QEvent::User,
- RemovePeer
+ enum EventType {
+ RemovePeerEvent = QEvent::User
};
SignalProxy(QObject *parent);
SignalProxy(ProxyMode mode, QObject *parent);
- SignalProxy(ProxyMode mode, QIODevice *device, QObject *parent);
virtual ~SignalProxy();
void setProxyMode(ProxyMode mode);
void setMaxHeartBeatCount(int max);
inline int maxHeartBeatCount() const { return _maxHeartBeatCount; }
- bool addPeer(QIODevice *iodev);
- bool addPeer(SignalProxy *proxy);
- void removePeer(QObject *peer);
- void removeAllPeers();
+ bool addPeer(AbstractPeer *peer);
bool attachSignal(QObject *sender, const char *signal, const QByteArray &sigName = QByteArray());
bool attachSlot(const QByteArray &sigName, QObject *recv, const char *slot);
void synchronize(SyncableObject *obj);
void stopSynchronize(SyncableObject *obj);
- //! Writes a QVariant to a device.
- /** The data item is prefixed with the resulting blocksize,
- * so the corresponding function readDataFromDevice() can check if enough data is available
- * at the device to reread the item.
- */
- static void writeDataToDevice(QIODevice *dev, const QVariant &item, bool compressed = false);
-
- //! Reads a data item from a device that has been written by writeDataToDevice().
- /** If not enough data bytes are available, the function returns false and the QVariant reference
- * remains untouched.
- */
- static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item, bool compressed = false);
-
class ExtendedMetaObject;
ExtendedMetaObject *extendedMetaObject(const QMetaObject *meta) const;
ExtendedMetaObject *createExtendedMetaObject(const QMetaObject *meta, bool checkConflicts = false);
bool isSecure() const { return _secure; }
void dumpProxyStats();
+ void dumpSyncMap(SyncableObject *object);
+ inline int peerCount() const { return _peers.size(); }
public slots:
void detachObject(QObject *obj);
void renameObject(const SyncableObject *obj, const QString &newname, const QString &oldname);
private slots:
- void dataAvailable();
void removePeerBySender();
void objectRenamed(const QByteArray &classname, const QString &newname, const QString &oldname);
- void sendHeartBeat();
- void receiveHeartBeat(AbstractPeer *peer, const QVariantList ¶ms);
- void receiveHeartBeatReply(AbstractPeer *peer, const QVariantList ¶ms);
-
void updateSecureState();
signals:
- void peerRemoved(QIODevice *dev);
+ void peerRemoved(SignalProxy::AbstractPeer *peer);
void connected();
void disconnected();
void objectInitialized(SyncableObject *);
+ void heartBeatIntervalChanged(int secs);
+ void maxHeartBeatCountChanged(int max);
void lagUpdated(int lag);
- void securityChanged(bool);
void secureStateChanged(bool);
private:
+ template<class T>
+ class PeerMessageEvent;
+
void init();
void initServer();
void initClient();
static const QMetaObject *metaObject(const QObject *obj);
- void dispatchSignal(QIODevice *receiver, const RequestType &requestType, const QVariantList ¶ms);
- void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms);
+ void removePeer(AbstractPeer *peer);
+ void removeAllPeers();
+
+ template<class T>
+ void dispatch(const T &protoMessage);
- void receivePackedFunc(AbstractPeer *sender, const QVariant &packedFunc);
- void receivePeerSignal(AbstractPeer *sender, const RequestType &requestType, const QVariantList ¶ms);
- void receivePeerSignal(SignalProxy *sender, const RequestType &requestType, const QVariantList ¶ms);
- void handleSync(AbstractPeer *sender, QVariantList params);
- void handleInitRequest(AbstractPeer *sender, const QVariantList ¶ms);
- void handleInitData(AbstractPeer *sender, const QVariantList ¶ms);
- void handleSignal(const QVariantList &data);
+ void handle(AbstractPeer *peer, const Protocol::SyncMessage &syncMessage);
+ void handle(AbstractPeer *peer, const Protocol::RpcCall &rpcCall);
+ void handle(AbstractPeer *peer, const Protocol::InitRequest &initRequest);
+ void handle(AbstractPeer *peer, const Protocol::InitData &initData);
bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue);
bool invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms = QVariantList());
QVariantMap initData(SyncableObject *obj) const;
void setInitData(SyncableObject *obj, const QVariantMap &properties);
- void updateLag(IODevicePeer *peer, int lag);
-
-public:
- void dumpSyncMap(SyncableObject *object);
- inline int peerCount() const { return _peers.size(); }
-
-private:
static void disconnectDevice(QIODevice *dev, const QString &reason = QString());
- // a Hash of the actual used communication object to it's corresponding peer
- // currently a communication object can either be an arbitrary QIODevice or another SignalProxy
- typedef QHash<QObject *, AbstractPeer *> PeerHash;
- PeerHash _peers;
+ QSet<AbstractPeer *> _peers;
// containg a list of argtypes for fast access
QHash<const QMetaObject *, ExtendedMetaObject *> _extendedMetaObjects;
QHash<QByteArray, ObjectId> _syncSlave;
ProxyMode _proxyMode;
- QTimer _heartBeatTimer;
int _heartBeatInterval;
int _maxHeartBeatCount;
friend class SignalRelay;
friend class SyncableObject;
+ friend class InternalPeer;
+ friend class RemotePeer;
};
{
class MethodDescriptor
{
-public:
+ public:
MethodDescriptor(const QMetaMethod &method);
MethodDescriptor() : _returnType(-1), _minArgCount(-1), _receiverMode(SignalProxy::Client) {}
inline int minArgCount() const { return _minArgCount; }
inline SignalProxy::ProxyMode receiverMode() const { return _receiverMode; }
-private:
+ private:
QByteArray _methodName;
QList<int> _argTypes;
int _returnType;
// ==================================================
-// Peers
+// AbstractPeer
// ==================================================
-class SignalProxy::AbstractPeer
+class SignalProxy::AbstractPeer : public QObject
{
+ Q_OBJECT
+
public:
- enum PeerType {
- NotAPeer = 0,
- IODevicePeer = 1,
- SignalProxyPeer = 2
- };
- AbstractPeer() : _type(NotAPeer) {}
- AbstractPeer(PeerType type) : _type(type) {}
- virtual ~AbstractPeer() {}
- inline PeerType type() const { return _type; }
- virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms) = 0;
+ AbstractPeer(QObject *parent = 0) : QObject(parent) {}
+
+ virtual QString description() const = 0;
+
+ virtual void setSignalProxy(SignalProxy *proxy) = 0;
+
+ virtual bool isOpen() const = 0;
virtual bool isSecure() const = 0;
-private:
- PeerType _type;
-};
+ virtual bool isLocal() const = 0;
+ virtual QString errorString() const { return QString(); }
-class SignalProxy::IODevicePeer : public SignalProxy::AbstractPeer
-{
-public:
- IODevicePeer(QIODevice *device, bool compress) : AbstractPeer(AbstractPeer::IODevicePeer), _device(device), byteCount(0), usesCompression(compress), sentHeartBeats(0), lag(0) {}
- virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms);
- virtual bool isSecure() const;
- inline void dispatchPackedFunc(const QVariant &packedFunc) { SignalProxy::writeDataToDevice(_device, packedFunc, usesCompression); }
- QString address() const;
- inline bool isOpen() const { return _device->isOpen(); }
- inline void close() const { _device->close(); }
- inline bool readData(QVariant &item) { return SignalProxy::readDataFromDevice(_device, byteCount, item, usesCompression); }
-private:
- QIODevice *_device;
- quint32 byteCount;
- bool usesCompression;
-public:
- int sentHeartBeats;
- int lag;
-};
+ virtual int lag() const = 0;
+public slots:
+ virtual void dispatch(const Protocol::SyncMessage &msg) = 0;
+ virtual void dispatch(const Protocol::RpcCall &msg) = 0;
+ virtual void dispatch(const Protocol::InitRequest &msg) = 0;
+ virtual void dispatch(const Protocol::InitData &msg) = 0;
-class SignalProxy::SignalProxyPeer : public SignalProxy::AbstractPeer
-{
-public:
- SignalProxyPeer(SignalProxy *sender, SignalProxy *receiver) : AbstractPeer(AbstractPeer::SignalProxyPeer), sender(sender), receiver(receiver) {}
- virtual void dispatchSignal(const RequestType &requestType, const QVariantList ¶ms);
- virtual inline bool isSecure() const { return true; }
-private:
- SignalProxy *sender;
- SignalProxy *receiver;
-};
+ virtual void close(const QString &reason = QString()) = 0;
+signals:
+ void disconnected();
+ void error(QAbstractSocket::SocketError);
+ void secureStateChanged(bool secure = true);
+ void lagUpdated(int msecs);
+};
#endif
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "core.h"
#include "coresession.h"
#include "coresettings.h"
+#include "internalpeer.h"
#include "postgresqlstorage.h"
#include "quassel.h"
-#include "signalproxy.h"
#include "sqlitestorage.h"
#include "network.h"
#include "logger.h"
#include "util.h"
+#include "protocols/legacy/legacypeer.h"
+
// migration related
#include <QFile>
#ifdef Q_OS_WIN32
class AddClientEvent : public QEvent
{
public:
- AddClientEvent(QTcpSocket *socket, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), socket(socket), userId(uid) {}
- QTcpSocket *socket;
+ AddClientEvent(RemotePeer *p, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), peer(p), userId(uid) {}
+ RemotePeer *peer;
UserId userId;
};
Core::~Core()
{
- foreach(QTcpSocket *socket, blocksizes.keys()) {
- socket->disconnectFromHost(); // disconnect non authed clients
+ foreach(RemotePeer *peer, clientInfo.keys()) {
+ peer->close(); // disconnect non authed clients
}
qDeleteAll(sessions);
qDeleteAll(_storageBackends);
Q_ASSERT(server);
while (server->hasPendingConnections()) {
QTcpSocket *socket = server->nextPendingConnection();
- connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
- connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
- connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
+ RemotePeer *peer = new LegacyPeer(socket, this);
+
+ connect(peer, SIGNAL(disconnected()), SLOT(clientDisconnected()));
+ connect(peer, SIGNAL(dataReceived(QVariant)), SLOT(processClientMessage(QVariant)));
+ connect(peer, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
- QVariantMap clientInfo;
- blocksizes.insert(socket, (quint32)0);
+ clientInfo.insert(peer, QVariantMap());
quInfo() << qPrintable(tr("Client connected from")) << qPrintable(socket->peerAddress().toString());
if (!_configured) {
}
-void Core::clientHasData()
+void Core::processClientMessage(const QVariant &data)
{
- QTcpSocket *socket = dynamic_cast<QTcpSocket *>(sender());
- Q_ASSERT(socket && blocksizes.contains(socket));
- QVariant item;
- while (SignalProxy::readDataFromDevice(socket, blocksizes[socket], item)) {
- QVariantMap msg = item.toMap();
- processClientMessage(socket, msg);
- if (!blocksizes.contains(socket)) break; // this socket is no longer ours to handle!
+ RemotePeer *peer = qobject_cast<RemotePeer *>(sender());
+ if (!peer) {
+ qWarning() << Q_FUNC_INFO << "Message not sent by RemoteConnection!";
+ return;
}
-}
-
-void Core::processClientMessage(QTcpSocket *socket, const QVariantMap &msg)
-{
+ QVariantMap msg = data.toMap();
if (!msg.contains("MsgType")) {
// Client is way too old, does not even use the current init format
qWarning() << qPrintable(tr("Antique client trying to connect... refusing."));
- socket->close();
+ peer->close();
return;
}
+
// OK, so we have at least an init message format we can understand
if (msg["MsgType"] == "ClientInit") {
QVariantMap reply;
reply["Error"] = tr("<b>Your Quassel Client is too old!</b><br>"
"This core needs at least client/core protocol version %1.<br>"
"Please consider upgrading your client.").arg(Quassel::buildInfo().coreNeedsProtocol);
- SignalProxy::writeDataToDevice(socket, reply);
- qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("too old, rejecting."));
- socket->close(); return;
+ peer->writeSocketData(reply);
+ qWarning() << qPrintable(tr("Client")) << peer->description() << qPrintable(tr("too old, rejecting."));
+ peer->close();
+ return;
}
reply["ProtocolVersion"] = Quassel::buildInfo().protocolVersion;
#ifdef HAVE_SSL
SslServer *sslServer = qobject_cast<SslServer *>(&_server);
- QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
- bool supportSsl = (bool)sslServer && (bool)sslSocket && sslServer->isCertValid();
+ QSslSocket *sslSocket = qobject_cast<QSslSocket *>(peer->socket());
+ bool supportSsl = sslServer && sslSocket && sslServer->isCertValid();
#else
bool supportSsl = false;
#endif
else {
reply["Configured"] = true;
}
- clientInfo[socket] = msg; // store for future reference
+ clientInfo[peer] = msg; // store for future reference
reply["MsgType"] = "ClientInitAck";
- SignalProxy::writeDataToDevice(socket, reply);
- socket->flush(); // ensure that the write cache is flushed before we switch to ssl
+ peer->writeSocketData(reply);
+ peer->socket()->flush(); // ensure that the write cache is flushed before we switch to ssl
#ifdef HAVE_SSL
// after we told the client that we are ssl capable we switch to ssl mode
if (supportSsl && msg["UseSsl"].toBool()) {
- qDebug() << qPrintable(tr("Starting TLS for Client:")) << qPrintable(socket->peerAddress().toString());
- connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
+ qDebug() << qPrintable(tr("Starting TLS for Client:")) << peer->description();
+ connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), SLOT(sslErrors(const QList<QSslError> &)));
sslSocket->startServerEncryption();
}
#endif
#ifndef QT_NO_COMPRESS
if (supportsCompression && msg["UseCompression"].toBool()) {
- socket->setProperty("UseCompression", true);
- qDebug() << "Using compression for Client:" << qPrintable(socket->peerAddress().toString());
+ peer->socket()->setProperty("UseCompression", true);
+ qDebug() << "Using compression for Client:" << qPrintable(peer->socket()->peerAddress().toString());
}
#endif
}
else {
// for the rest, we need an initialized connection
- if (!clientInfo.contains(socket)) {
+ if (!clientInfo.contains(peer)) {
QVariantMap reply;
reply["MsgType"] = "ClientLoginReject";
reply["Error"] = tr("<b>Client not initialized!</b><br>You need to send an init message before trying to login.");
- SignalProxy::writeDataToDevice(socket, reply);
- qWarning() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting."));
- socket->close(); return;
+ peer->writeSocketData(reply);
+ qWarning() << qPrintable(tr("Client")) << qPrintable(peer->socket()->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting."));
+ peer->close(); return;
}
if (msg["MsgType"] == "CoreSetupData") {
QVariantMap reply;
else {
reply["MsgType"] = "CoreSetupAck";
}
- SignalProxy::writeDataToDevice(socket, reply);
+ peer->writeSocketData(reply);
}
else if (msg["MsgType"] == "ClientLogin") {
QVariantMap reply;
if (uid == 0) {
reply["MsgType"] = "ClientLoginReject";
reply["Error"] = tr("<b>Invalid username or password!</b><br>The username/password combination you supplied could not be found in the database.");
- SignalProxy::writeDataToDevice(socket, reply);
+ peer->writeSocketData(reply);
return;
}
reply["MsgType"] = "ClientLoginAck";
- SignalProxy::writeDataToDevice(socket, reply);
- quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("initialized and authenticated successfully as \"%1\" (UserId: %2).").arg(msg["User"].toString()).arg(uid.toInt()));
- setupClientSession(socket, uid);
+ peer->writeSocketData(reply);
+ quInfo() << qPrintable(tr("Client")) << qPrintable(peer->socket()->peerAddress().toString()) << qPrintable(tr("initialized and authenticated successfully as \"%1\" (UserId: %2).").arg(msg["User"].toString()).arg(uid.toInt()));
+ setupClientSession(peer, uid);
}
}
}
// Potentially called during the initialization phase (before handing the connection off to the session)
void Core::clientDisconnected()
{
- QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
- if (socket) {
- // here it's safe to call methods on socket!
- quInfo() << qPrintable(tr("Non-authed client disconnected.")) << qPrintable(socket->peerAddress().toString());
- blocksizes.remove(socket);
- clientInfo.remove(socket);
- socket->deleteLater();
- }
- else {
- // we have to crawl through the hashes and see if we find a victim to remove
- qDebug() << qPrintable(tr("Non-authed client disconnected. (socket allready destroyed)"));
+ RemotePeer *peer = qobject_cast<RemotePeer *>(sender());
+ Q_ASSERT(peer);
- // DO NOT CALL ANY METHODS ON socket!!
- socket = static_cast<QTcpSocket *>(sender());
-
- QHash<QTcpSocket *, quint32>::iterator blockSizeIter = blocksizes.begin();
- while (blockSizeIter != blocksizes.end()) {
- if (blockSizeIter.key() == socket) {
- blockSizeIter = blocksizes.erase(blockSizeIter);
- }
- else {
- blockSizeIter++;
- }
- }
-
- QHash<QTcpSocket *, QVariantMap>::iterator clientInfoIter = clientInfo.begin();
- while (clientInfoIter != clientInfo.end()) {
- if (clientInfoIter.key() == socket) {
- clientInfoIter = clientInfo.erase(clientInfoIter);
- }
- else {
- clientInfoIter++;
- }
- }
- }
+ quInfo() << qPrintable(tr("Non-authed client disconnected.")) << qPrintable(peer->socket()->peerAddress().toString());
+ clientInfo.remove(peer);
+ peer->deleteLater();
// make server listen again if still not configured
if (!_configured) {
}
-void Core::setupClientSession(QTcpSocket *socket, UserId uid)
+void Core::setupClientSession(RemotePeer *peer, UserId uid)
{
// From now on everything is handled by the client session
- disconnect(socket, 0, this, 0);
- socket->flush();
- blocksizes.remove(socket);
- clientInfo.remove(socket);
+ disconnect(peer, 0, this, 0);
+ peer->socket()->flush();
+ clientInfo.remove(peer);
// Find or create session for validated user
SessionThread *session;
else {
session = createSession(uid);
if (!session) {
- qWarning() << qPrintable(tr("Could not initialize session for client:")) << qPrintable(socket->peerAddress().toString());
- socket->close();
+ qWarning() << qPrintable(tr("Could not initialize session for client:")) << qPrintable(peer->socket()->peerAddress().toString());
+ peer->close();
return;
}
}
// as we are currently handling an event triggered by incoming data on this socket
// it is unsafe to directly move the socket to the client thread.
- QCoreApplication::postEvent(this, new AddClientEvent(socket, uid));
+ QCoreApplication::postEvent(this, new AddClientEvent(peer, uid));
}
{
if (event->type() == AddClientEventId) {
AddClientEvent *addClientEvent = static_cast<AddClientEvent *>(event);
- addClientHelper(addClientEvent->socket, addClientEvent->userId);
+ addClientHelper(addClientEvent->peer, addClientEvent->userId);
return;
}
}
-void Core::addClientHelper(QTcpSocket *socket, UserId uid)
+void Core::addClientHelper(RemotePeer *peer, UserId uid)
{
// Find or create session for validated user
if (!sessions.contains(uid)) {
- qWarning() << qPrintable(tr("Could not find a session for client:")) << qPrintable(socket->peerAddress().toString());
- socket->close();
+ qWarning() << qPrintable(tr("Could not find a session for client:")) << qPrintable(peer->socket()->peerAddress().toString());
+ peer->close();
return;
}
SessionThread *session = sessions[uid];
- session->addClient(socket);
+ session->addClient(peer);
}
-void Core::setupInternalClientSession(SignalProxy *proxy)
+void Core::setupInternalClientSession(InternalPeer *clientPeer)
{
if (!_configured) {
stopListening();
return;
}
+ InternalPeer *corePeer = new InternalPeer(this);
+ corePeer->setPeer(clientPeer);
+ clientPeer->setPeer(corePeer);
+
// Find or create session for validated user
- SessionThread *sess;
+ SessionThread *sessionThread;
if (sessions.contains(uid))
- sess = sessions[uid];
+ sessionThread = sessions[uid];
else
- sess = createSession(uid);
- sess->addClient(proxy);
+ sessionThread = createSession(uid);
+
+ sessionThread->addClient(corePeer);
}
void Core::socketError(QAbstractSocket::SocketError err)
{
- QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(sender());
- if (socket && err != QAbstractSocket::RemoteHostClosedError)
- qWarning() << "Core::socketError()" << socket << err << socket->errorString();
+ RemotePeer *peer = qobject_cast<RemotePeer *>(sender());
+ if (peer && err != QAbstractSocket::RemoteHostClosedError)
+ qWarning() << "Core::socketError()" << peer->socket() << err << peer->socket()->errorString();
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "types.h"
class CoreSession;
+class RemotePeer;
+struct NetworkInfo;
class SessionThread;
class SignalProxy;
-struct NetworkInfo;
class AbstractSqlMigrationReader;
class AbstractSqlMigrationWriter;
/** \note This method is threadsafe.
*/
void syncStorage();
- void setupInternalClientSession(SignalProxy *proxy);
+ void setupInternalClientSession(InternalPeer *clientConnection);
signals:
//! Sent when a BufferInfo is updated in storage.
bool startListening();
void stopListening(const QString &msg = QString());
void incomingConnection();
- void clientHasData();
void clientDisconnected();
bool initStorage(const QString &backend, QVariantMap settings, bool setup = false);
#endif
void socketError(QAbstractSocket::SocketError);
+ void processClientMessage(const QVariant &data);
+
private:
Core();
~Core();
static Core *instanceptr;
SessionThread *createSession(UserId userId, bool restoreState = false);
- void setupClientSession(QTcpSocket *socket, UserId uid);
- void addClientHelper(QTcpSocket *socket, UserId uid);
- void processClientMessage(QTcpSocket *socket, const QVariantMap &msg);
+ void setupClientSession(RemotePeer *peer, UserId uid);
+ void addClientHelper(RemotePeer *peer, UserId uid);
//void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
QString setupCoreForInternalUsage();
QString setupCore(QVariantMap setupData);
OidentdConfigGenerator *_oidentdConfigGenerator;
- QHash<QTcpSocket *, quint32> blocksizes;
- QHash<QTcpSocket *, QVariantMap> clientInfo;
+ QHash<RemotePeer *, QVariantMap> clientInfo;
QHash<QString, Storage *> _storageBackends;
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
void CoreNetwork::socketHasData()
{
while (socket.canReadLine()) {
- QByteArray s = socket.readLine().trimmed();
+ QByteArray s = socket.readLine();
+ s.chop(2);
NetworkDataEvent *event = new NetworkDataEvent(EventManager::NetworkIncoming, this, s);
#if QT_VERSION >= 0x040700
event->setTimestamp(QDateTime::currentDateTimeUtc());
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
virtual inline void requestSetAutoWhoInterval(int interval) { setAutoWhoInterval(interval); }
virtual inline void requestSetAutoWhoNickLimit(int nickLimit) { setAutoWhoNickLimit(nickLimit); }
virtual inline void requestSetAutoWhoDelay(int delay) { setAutoWhoDelay(delay); }
+ virtual inline void requestSetStandardCtcp(bool enabled) { setStandardCtcp(enabled); }
};
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "coreusersettings.h"
#include "ctcpparser.h"
#include "eventstringifier.h"
+#include "internalpeer.h"
#include "ircchannel.h"
#include "ircparser.h"
#include "ircuser.h"
#include "logger.h"
#include "messageevent.h"
-#include "signalproxy.h"
#include "storage.h"
#include "util.h"
+#include "protocols/legacy/legacypeer.h"
+
class ProcessMessagesEvent : public QEvent
{
public:
CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent)
: QObject(parent),
_user(uid),
- _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
+ _signalProxy(new SignalProxy(SignalProxy::Server, this)),
_aliasManager(this),
_bufferSyncer(new CoreBufferSyncer(this)),
_backlogManager(new CoreBacklogManager(this)),
p->setHeartBeatInterval(30);
p->setMaxHeartBeatCount(60); // 30 mins until we throw a dead socket out
- connect(p, SIGNAL(peerRemoved(QIODevice *)), this, SLOT(removeClient(QIODevice *)));
+ connect(p, SIGNAL(peerRemoved(SignalProxy::AbstractPeer*)), SLOT(removeClient(SignalProxy::AbstractPeer*)));
- connect(p, SIGNAL(connected()), this, SLOT(clientsConnected()));
- connect(p, SIGNAL(disconnected()), this, SLOT(clientsDisconnected()));
+ connect(p, SIGNAL(connected()), SLOT(clientsConnected()));
+ connect(p, SIGNAL(disconnected()), SLOT(clientsDisconnected()));
p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
p->attachSignal(this, SIGNAL(displayMsg(Message)));
}
-void CoreSession::addClient(QIODevice *device)
+void CoreSession::addClient(RemotePeer *peer)
{
- if (!device) {
- qCritical() << "Invoking CoreSession::addClient with a QObject that is not a QIODevice!";
- }
- else {
- // if the socket is an orphan, the signalProxy adopts it.
- // -> we don't need to care about it anymore
- device->setParent(0);
- signalProxy()->addPeer(device);
- QVariantMap reply;
- reply["MsgType"] = "SessionInit";
- reply["SessionState"] = sessionState();
- SignalProxy::writeDataToDevice(device, reply);
- }
+ QVariantMap reply;
+ reply["MsgType"] = "SessionInit";
+ reply["SessionState"] = sessionState();
+ peer->writeSocketData(reply);
+ signalProxy()->addPeer(peer);
}
-void CoreSession::addClient(SignalProxy *proxy)
+void CoreSession::addClient(InternalPeer *peer)
{
- signalProxy()->addPeer(proxy);
+ signalProxy()->addPeer(peer);
emit sessionState(sessionState());
}
-void CoreSession::removeClient(QIODevice *iodev)
+void CoreSession::removeClient(SignalProxy::AbstractPeer *peer)
{
- QTcpSocket *socket = qobject_cast<QTcpSocket *>(iodev);
- if (socket)
- quInfo() << qPrintable(tr("Client")) << qPrintable(socket->peerAddress().toString()) << qPrintable(tr("disconnected (UserId: %1).").arg(user().toInt()));
+ RemotePeer *p = qobject_cast<RemotePeer *>(peer);
+ if (p)
+ quInfo() << qPrintable(tr("Client")) << p->description() << qPrintable(tr("disconnected (UserId: %1).").arg(user().toInt()));
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "corealiasmanager.h"
#include "coreignorelistmanager.h"
#include "message.h"
+#include "signalproxy.h"
#include "storage.h"
class CoreBacklogManager;
class CtcpParser;
class EventManager;
class EventStringifier;
+class InternalPeer;
class IrcParser;
class MessageEvent;
class NetworkConnection;
-class SignalProxy;
+class RemotePeer;
struct NetworkInfo;
void restoreSessionState();
public slots:
- void addClient(QIODevice *device);
- void addClient(SignalProxy *proxy);
+ void addClient(RemotePeer *peer);
+ void addClient(InternalPeer *peer);
void msgFromClient(BufferInfo, QString message);
virtual void customEvent(QEvent *event);
private slots:
- void removeClient(QIODevice *dev);
+ void removeClient(SignalProxy::AbstractPeer *peer);
void recvStatusMsgFromServer(QString msg);
void recvMessageFromServer(NetworkId networkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None);
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
CoreNetwork *net = coreNetwork(e);
- QString construct = net->saslAccount();
- construct.append(QChar(QChar::Null));
- construct.append(net->saslAccount());
- construct.append(QChar(QChar::Null));
- construct.append(net->saslPassword());
- QByteArray saslData = QByteArray(construct.toAscii().toBase64());
- saslData.prepend("AUTHENTICATE ");
- net->putRawLine(saslData);
+#ifdef HAVE_SSL
+ if (net->identityPtr()->sslCert().isNull()) {
+#endif
+ QString construct = net->saslAccount();
+ construct.append(QChar(QChar::Null));
+ construct.append(net->saslAccount());
+ construct.append(QChar(QChar::Null));
+ construct.append(net->saslPassword());
+ QByteArray saslData = QByteArray(construct.toAscii().toBase64());
+ saslData.prepend("AUTHENTICATE ");
+ net->putRawLine(saslData);
+#ifdef HAVE_SSL
+ } else {
+ net->putRawLine("AUTHENTICATE +");
+ }
+#endif
}
// additional CAP messages (ls, multi-prefix, et cetera).
if (e->params().count() == 3) {
- if (e->params().at(2) == "sasl") {
+ if (e->params().at(2).startsWith("sasl")) { // Freenode (at least) sends "sasl " with a trailing space for some reason!
// FIXME use event
- coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later
+ // if the current identity has a cert set, use SASL EXTERNAL
+#ifdef HAVE_SSL
+ if (!coreNetwork(e)->identityPtr()->sslCert().isNull()) {
+ coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE EXTERNAL"));
+ } else {
+#endif
+ // Only working with PLAIN atm, blowfish later
+ coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN"));
+#ifdef HAVE_SSL
+ }
+#endif
}
}
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "ctcpparser.h"
+#include "corenetworkconfig.h"
#include "coresession.h"
#include "ctcpevent.h"
#include "messageevent.h"
_ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r');
_ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
- QByteArray XQUOTE = QByteArray("\134");
- _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
- _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
+ setStandardCtcp(_coreSession->networkConfig()->standardCtcp());
+ connect(_coreSession->networkConfig(), SIGNAL(standardCtcpSet(bool)), this, SLOT(setStandardCtcp(bool)));
connect(this, SIGNAL(newEvent(Event *)), _coreSession->eventManager(), SLOT(postEvent(Event *)));
}
+void CtcpParser::setStandardCtcp(bool enabled)
+{
+ QByteArray XQUOTE = QByteArray("\134");
+ if (enabled)
+ _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
+ else
+ _ctcpXDelimDequoteHash.remove(XQUOTE + XQUOTE);
+ _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
+}
+
+
void CtcpParser::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
const QString &target, Message::Flags msgFlags)
{
void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype)
{
- QByteArray ctcp;
-
//lowlevel message dequote
QByteArray dequotedMessage = lowLevelDequote(e->rawMessage());
? Message::Redirected
: Message::None;
+ if (coreSession()->networkConfig()->standardCtcp())
+ parseStandard(e, messagetype, dequotedMessage, ctcptype, flags);
+ else
+ parseSimple(e, messagetype, dequotedMessage, ctcptype, flags);
+}
+
+
+// only accept CTCPs in their simplest form, i.e. one ctcp, from start to
+// end, no text around it; not as per the 'specs', but makes people happier
+void CtcpParser::parseSimple(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags)
+{
+ if (dequotedMessage.count(XDELIM) != 2 || dequotedMessage[0] != '\001' || dequotedMessage[dequotedMessage.count() -1] != '\001') {
+ displayMsg(e, messagetype, targetDecode(e, dequotedMessage), e->prefix(), e->target(), flags);
+ } else {
+ int spacePos = -1;
+ QString ctcpcmd, ctcpparam;
+
+ QByteArray ctcp = xdelimDequote(dequotedMessage.mid(1, dequotedMessage.count() - 2));
+ spacePos = ctcp.indexOf(' ');
+ if (spacePos != -1) {
+ ctcpcmd = targetDecode(e, ctcp.left(spacePos));
+ ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1));
+ } else {
+ ctcpcmd = targetDecode(e, ctcp);
+ ctcpparam = QString();
+ }
+ ctcpcmd = ctcpcmd.toUpper();
+
+ // we don't want to block /me messages by the CTCP ignore list
+ if (ctcpcmd == QLatin1String("ACTION") || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) {
+ QUuid uuid = QUuid::createUuid();
+ _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix())));
+ CtcpEvent *event = new CtcpEvent(EventManager::CtcpEvent, e->network(), e->prefix(), e->target(),
+ ctcptype, ctcpcmd, ctcpparam, e->timestamp(), uuid);
+ emit newEvent(event);
+ CtcpEvent *flushEvent = new CtcpEvent(EventManager::CtcpEventFlush, e->network(), e->prefix(), e->target(),
+ ctcptype, "INVALID", QString(), e->timestamp(), uuid);
+ emit newEvent(flushEvent);
+ }
+ }
+}
+
+
+void CtcpParser::parseStandard(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags)
+{
+ QByteArray ctcp;
+
QList<CtcpEvent *> ctcpEvents;
QUuid uuid; // needed to group all replies together
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "corenetwork.h"
#include "eventmanager.h"
#include "ircevent.h"
+#include "ctcpevent.h"
class CoreSession;
class CtcpEvent;
Message::Flags msgFlags = Message::None);
void parse(IrcEventRawMessage *event, Message::Type msgType);
+ void parseSimple(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags);
+ void parseStandard(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags);
QByteArray lowLevelQuote(const QByteArray &);
QByteArray lowLevelDequote(const QByteArray &);
QByteArray pack(const QByteArray &ctcpTag, const QByteArray &message);
void packedReply(CoreNetwork *network, const QString &bufname, const QList<QByteArray> &replies);
+private slots:
+ void setStandardCtcp(bool enabled);
+
private:
inline QString targetDecode(IrcEventRawMessage *e, const QByteArray &msg) { return coreNetwork(e)->userDecode(e->target(), msg); }
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
.arg(e->nick(), e->params().at(0), e->params().at(1)), QString(), e->params().at(0));
}
+void EventStringifier::processIrcEventWallops(IrcEvent *e)
+{
+ displayMsg(e, Message::Server, tr("[Operwall] %1: %2").arg(e->nick(), e->params().join(" ")));
+}
+
/* RPL_ISUPPORT */
void EventStringifier::processIrcEvent005(IrcEvent *e)
if (e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation
QDateTime loginTime = QDateTime::fromTime_t(e->params()[2].toInt());
- displayMsg(e, Message::Server, tr("[Whois] %1 is logged in since %2").arg(e->params()[0], loginTime.toString()));
+ displayMsg(e, Message::Server, tr("[Whois] %1 is logged in since %2")
+ .arg(e->params()[0], QLocale().toString(loginTime, QLocale().dateTimeFormat())));
}
+ QDateTime idlingSince = e->timestamp().toLocalTime().addSecs(-idleSecs);
displayMsg(e, Message::Server, tr("[Whois] %1 is idling for %2 (since %3)")
- .arg(e->params()[0], secondsToString(idleSecs), e->timestamp().toLocalTime().addSecs(-idleSecs).toString()));
+ .arg(e->params()[0], secondsToString(idleSecs),
+ QLocale().toString(idlingSince, QLocale().dateTimeFormat())));
}
return;
}
QDateTime time = QDateTime::fromTime_t(unixtime);
- displayMsg(e, Message::Topic, tr("Channel %1 created on %2").arg(channel, time.toString()), QString(), channel);
+ displayMsg(e, Message::Topic, tr("Channel %1 created on %2")
+ .arg(channel, QLocale().toString(time, QLocale().dateTimeFormat())),
+ QString(), channel);
}
return;
QString channel = e->params().first();
+ QDateTime topicSetTime = QDateTime::fromTime_t(e->params()[2].toInt());
displayMsg(e, Message::Topic, tr("Topic set by %1 on %2")
- .arg(e->params()[1], QDateTime::fromTime_t(e->params()[2].toInt()).toString()), QString(), channel);
+ .arg(e->params()[1],
+ QLocale().toString(topicSetTime, QLocale().dateTimeFormat())), QString(), channel);
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
Q_INVOKABLE void processIrcEventPong(IrcEvent *event);
Q_INVOKABLE void processIrcEventQuit(IrcEvent *event);
Q_INVOKABLE void processIrcEventTopic(IrcEvent *event);
+ Q_INVOKABLE void processIrcEventWallops(IrcEvent *event);
Q_INVOKABLE void processIrcEvent005(IrcEvent *event); // RPL_ISUPPORT
Q_INVOKABLE void processIrcEvent301(IrcEvent *event); // RPL_AWAY
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
out << data;
QSqlDatabase db = logDb();
- QSqlQuery query(db);
- query.prepare(queryString("insert_user_setting"));
- query.bindValue(":userid", userId.toInt());
- query.bindValue(":settingname", settingName);
- query.bindValue(":settingvalue", rawData);
- safeExec(query);
+ QSqlQuery selectQuery(db);
+ selectQuery.prepare(queryString("select_user_setting"));
+ selectQuery.bindValue(":userid", userId.toInt());
+ selectQuery.bindValue(":settingname", settingName);
+ safeExec(selectQuery);
- if (query.lastError().isValid()) {
- QSqlQuery updateQuery(db);
- updateQuery.prepare(queryString("update_user_setting"));
- updateQuery.bindValue(":userid", userId.toInt());
- updateQuery.bindValue(":settingname", settingName);
- updateQuery.bindValue(":settingvalue", rawData);
- safeExec(updateQuery);
+ QString setQueryString;
+ if (!selectQuery.first()) {
+ setQueryString = queryString("insert_user_setting");
+ }
+ else {
+ setQueryString = queryString("update_user_setting");
}
+
+ QSqlQuery setQuery(db);
+ setQuery.prepare(setQueryString);
+ setQuery.bindValue(":userid", userId.toInt());
+ setQuery.bindValue(":settingname", settingName);
+ setQuery.bindValue(":settingvalue", rawData);
+ safeExec(setQuery);
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#include <QMutexLocker>
-
+#include "core.h"
+#include "coresession.h"
+#include "internalpeer.h"
+#include "remotepeer.h"
#include "sessionthread.h"
#include "signalproxy.h"
-#include "coresession.h"
-#include "core.h"
SessionThread::SessionThread(UserId uid, bool restoreState, QObject *parent)
: QThread(parent),
}
+// this and the following related methods are executed in the Core thread!
void SessionThread::addClient(QObject *peer)
{
if (isSessionInitialized()) {
void SessionThread::addClientToSession(QObject *peer)
{
- QIODevice *socket = qobject_cast<QIODevice *>(peer);
- if (socket) {
- addRemoteClientToSession(socket);
+ RemotePeer *remote = qobject_cast<RemotePeer *>(peer);
+ if (remote) {
+ addRemoteClientToSession(remote);
return;
}
- SignalProxy *proxy = qobject_cast<SignalProxy *>(peer);
- if (proxy) {
- addInternalClientToSession(proxy);
+ InternalPeer *internal = qobject_cast<InternalPeer *>(peer);
+ if (internal) {
+ addInternalClientToSession(internal);
return;
}
- qWarning() << "SessionThread::addClient() received neither QIODevice nor SignalProxy as peer!" << peer;
+ qWarning() << "SessionThread::addClient() received invalid peer!" << peer;
}
-void SessionThread::addRemoteClientToSession(QIODevice *socket)
+void SessionThread::addRemoteClientToSession(RemotePeer *remotePeer)
{
- socket->setParent(0);
- socket->moveToThread(session()->thread());
- emit addRemoteClient(socket);
+ remotePeer->setParent(0);
+ remotePeer->moveToThread(session()->thread());
+ emit addRemoteClient(remotePeer);
}
-void SessionThread::addInternalClientToSession(SignalProxy *proxy)
+void SessionThread::addInternalClientToSession(InternalPeer *internalPeer)
{
- emit addInternalClient(proxy);
+ internalPeer->setParent(0);
+ internalPeer->moveToThread(session()->thread());
+ emit addInternalClient(internalPeer);
}
void SessionThread::run()
{
_session = new CoreSession(user(), _restoreState);
- connect(this, SIGNAL(addRemoteClient(QIODevice *)), _session, SLOT(addClient(QIODevice *)));
- connect(this, SIGNAL(addInternalClient(SignalProxy *)), _session, SLOT(addClient(SignalProxy *)));
- connect(_session, SIGNAL(sessionState(const QVariant &)), Core::instance(), SIGNAL(sessionState(const QVariant &)));
+ connect(this, SIGNAL(addRemoteClient(RemotePeer*)), _session, SLOT(addClient(RemotePeer*)));
+ connect(this, SIGNAL(addInternalClient(InternalPeer*)), _session, SLOT(addClient(InternalPeer*)));
+ connect(_session, SIGNAL(sessionState(QVariant)), Core::instance(), SIGNAL(sessionState(QVariant)));
emit initialized();
exec();
delete _session;
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "types.h"
class CoreSession;
+class InternalPeer;
+class RemotePeer;
class QIODevice;
-class SignalProxy;
class SessionThread : public QThread
{
void initialized();
void shutdown();
- void addRemoteClient(QIODevice *);
- void addInternalClient(SignalProxy *);
+ void addRemoteClient(RemotePeer *peer);
+ void addInternalClient(InternalPeer *peer);
private:
CoreSession *_session;
bool isSessionInitialized();
void addClientToSession(QObject *peer);
- void addRemoteClientToSession(QIODevice *socket);
- void addInternalClientToSession(SignalProxy *proxy);
+ void addRemoteClientToSession(RemotePeer *remotePeer);
+ void addInternalClientToSession(InternalPeer *internalPeer);
};
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
include_directories(${INDICATEQT_INCLUDE_DIRS})
endif(INDICATEQT_FOUND)
+if(HAVE_NOTIFICATION_CENTER)
+ set(SOURCES ${SOURCES} osxnotificationbackend.mm)
+ set(MOC_HDRS ${MOC_HDRS} osxnotificationbackend.h)
+endif()
+
foreach(FORM ${FORMS})
set(FORMPATH ${FORMPATH} ui/${FORM})
endforeach(FORM ${FORMS})
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
{
QString res;
res = tr("<b>A modern, distributed IRC Client</b><br><br>"
- "©2005-2012 by the Quassel Project<br>"
+ "©2005-2013 by the Quassel Project<br>"
"<a href=\"http://quassel-irc.org\">http://quassel-irc.org</a><br>"
"<a href=\"irc://irc.freenode.net/quassel\">#quassel</a> on <a href=\"http://www.freenode.net\">Freenode</a><br><br>"
"Quassel IRC is dual-licensed under <a href=\"http://www.gnu.org/licenses/gpl-2.0.txt\">GPLv2</a> and "
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "indicatornotificationbackend.h"
#endif
+#ifdef HAVE_NOTIFICATION_CENTER
+ #include "osxnotificationbackend.h"
+#endif
+
#include "settingspages/aliasessettingspage.h"
#include "settingspages/appearancesettingspage.h"
#include "settingspages/backlogsettingspage.h"
QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this));
#endif
+#ifdef HAVE_NOTIFICATION_CENTER
+ QtUi::registerNotificationBackend(new OSXNotificationBackend(this));
+#endif
+
// we assume that at this point, all configurable actions are defined!
QtUi::loadShortcuts();
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "core.h"
#include "qtui.h"
+class InternalPeer;
+
MonolithicApplication::MonolithicApplication(int &argc, char **argv)
: QtUiApplication(argc, argv),
_internalInitDone(false)
connect(Client::coreConnection(), SIGNAL(startInternalCore()), SLOT(startInternalCore()));
+ // FIXME what's this for?
if (isOptionSet("port")) {
startInternalCore();
}
}
Core *core = Core::instance();
CoreConnection *connection = Client::coreConnection();
- connect(connection, SIGNAL(connectToInternalCore(SignalProxy *)), core, SLOT(setupInternalClientSession(SignalProxy *)));
- connect(core, SIGNAL(sessionState(const QVariant &)), connection, SLOT(internalSessionStateReceived(const QVariant &)));
+ connect(connection, SIGNAL(connectToInternalCore(InternalPeer*)), core, SLOT(setupInternalClientSession(InternalPeer*)));
+ connect(core, SIGNAL(sessionState(QVariant)), connection, SLOT(internalSessionStateReceived(QVariant)));
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2012 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef OSXNOTIFICATIONBACKEND_H_
+#define OSXNOTIFICATIONBACKEND_H_
+
+#include "abstractnotificationbackend.h"
+#include "settingspage.h"
+
+class OSXNotificationBackend : public AbstractNotificationBackend
+{
+ Q_OBJECT
+
+public:
+ OSXNotificationBackend(QObject *parent = 0);
+
+ void notify(const Notification &);
+ void close(uint notificationId);
+ virtual SettingsPage *createConfigWidget() const;
+
+private slots:
+ void enabledChanged(const QVariant &value);
+
+private:
+ class ConfigWidget;
+
+ bool _enabled;
+};
+
+class OSXNotificationBackend::ConfigWidget : public SettingsPage
+{
+ Q_OBJECT
+
+public:
+ ConfigWidget(QWidget *parent = 0);
+ void save();
+ void load();
+ bool hasDefaults() const;
+ void defaults();
+
+private slots:
+ void widgetChanged();
+
+private:
+ QCheckBox *_enabledBox;
+ bool _enabled;
+};
+
+#endif // OSXNOTIFICATIONBACKEND_H_
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2012 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "clientsettings.h"
+#include "osxnotificationbackend.h"
+
+#include <QCheckBox>
+#include <QHBoxLayout>
+
+#import <Foundation/NSUserNotification.h>
+
+namespace {
+
+void SendNotificationCenterMessage(NSString* title, NSString* subtitle) {
+ NSUserNotificationCenter* center =
+ [NSUserNotificationCenter defaultUserNotificationCenter];
+ NSUserNotification* notification =
+ [[NSUserNotification alloc] init];
+
+ [notification setTitle: title];
+ [notification setSubtitle: subtitle];
+
+ [center deliverNotification: notification];
+
+ [notification release];
+}
+
+}
+
+OSXNotificationBackend::OSXNotificationBackend(QObject *parent)
+ : AbstractNotificationBackend(parent),
+ _enabled(true)
+{
+ NotificationSettings notificationSettings;
+ notificationSettings.initAndNotify("OSXNotification/Enabled", this, SLOT(enabledChanged(QVariant)), true);
+}
+
+void OSXNotificationBackend::enabledChanged(const QVariant &value)
+{
+ _enabled = value.toBool();
+}
+
+void OSXNotificationBackend::notify(const Notification ¬ification)
+{
+ if (!_enabled)
+ {
+ return;
+ }
+
+ NSString* message = [[NSString alloc] initWithUTF8String:notification.sender.toUtf8().constData()];
+ NSString* summary = [[NSString alloc] initWithUTF8String:notification.message.toUtf8().constData()];
+
+ SendNotificationCenterMessage(message, summary);
+
+ [message release];
+ [summary release];
+}
+
+void OSXNotificationBackend::close(uint notificationId)
+{
+}
+
+SettingsPage *OSXNotificationBackend::createConfigWidget() const
+{
+ return new ConfigWidget();
+}
+
+OSXNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent)
+ : SettingsPage("Internal", "OSXNotification", parent)
+{
+ _enabledBox = new QCheckBox(tr("Show OS X notifications"));
+ connect(_enabledBox, SIGNAL(toggled(bool)), this, SLOT(widgetChanged()));
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->addWidget(_enabledBox);
+}
+
+void OSXNotificationBackend::ConfigWidget::widgetChanged()
+{
+ bool changed = (_enabled != _enabledBox->isChecked());
+ if (changed != hasChanged())
+ setChangedState(changed);
+}
+
+bool OSXNotificationBackend::ConfigWidget::hasDefaults() const
+{
+ return true;
+}
+
+void OSXNotificationBackend::ConfigWidget::defaults()
+{
+ _enabledBox->setChecked(true);
+ widgetChanged();
+}
+
+void OSXNotificationBackend::ConfigWidget::load()
+{
+ NotificationSettings s;
+ _enabled = s.value("OSXNotification/Enabled", false).toBool();
+ _enabledBox->setChecked(_enabled);
+ setChangedState(false);
+}
+
+
+void OSXNotificationBackend::ConfigWidget::save()
+{
+ NotificationSettings s;
+ s.setValue("OSXNotification/Enabled", _enabledBox->isChecked());
+ load();
+}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include <QFileDialog>
-#include <phonon/mediaobject.h>
+#include <Phonon/MediaObject>
+#include <Phonon/BackendCapabilities>
#include "phononnotificationbackend.h"
: AbstractNotificationBackend(parent),
_media(0)
{
+ _audioAvailable = !Phonon::BackendCapabilities::availableAudioOutputDevices().isEmpty();
NotificationSettings notificationSettings;
_enabled = notificationSettings.value("Phonon/Enabled", true).toBool();
createMediaObject(notificationSettings.value("Phonon/AudioFile", QString()).toString());
void PhononNotificationBackend::notify(const Notification ¬ification)
{
- if (_enabled && _media && (notification.type == Highlight || notification.type == PrivMsg)) {
- _media->stop();
- _media->play();
+ if (_enabled && (notification.type == Highlight || notification.type == PrivMsg)) {
+ if (_audioAvailable) {
+ _media->stop();
+ _media->play();
+ }
+ else
+ QApplication::beep();
}
}
return;
}
- _media = Phonon::createPlayer(Phonon::NotificationCategory,
- Phonon::MediaSource(file));
+ _media = Phonon::createPlayer(Phonon::NotificationCategory, Phonon::MediaSource(file));
}
audioPreview(0)
{
ui.setupUi(this);
+ _audioAvailable = !Phonon::BackendCapabilities::availableAudioOutputDevices().isEmpty();
ui.enabled->setIcon(SmallIcon("media-playback-start"));
ui.play->setIcon(SmallIcon("media-playback-start"));
ui.open->setIcon(SmallIcon("document-open"));
void PhononNotificationBackend::ConfigWidget::widgetChanged()
{
- ui.play->setEnabled(ui.enabled->isChecked() && !ui.filename->text().isEmpty());
+ if (! _audioAvailable) {
+ ui.play->setEnabled(ui.enabled->isChecked());
+ ui.open->setEnabled(false);
+ ui.filename->setEnabled(false);
+ ui.filename->setText(QString());
+ }
+ else {
+ ui.play->setEnabled(ui.enabled->isChecked() && !ui.filename->text().isEmpty());
- bool changed = (enabled != ui.enabled->isChecked()
- || filename != ui.filename->text());
+ bool changed = (enabled != ui.enabled->isChecked() || filename != ui.filename->text());
- if (changed != hasChanged()) setChangedState(changed);
+ if (changed != hasChanged())
+ setChangedState(changed);
+ }
}
void PhononNotificationBackend::ConfigWidget::on_play_clicked()
{
- if (!ui.filename->text().isEmpty()) {
- if (audioPreview)
- delete audioPreview;
+ if (_audioAvailable) {
+ if (!ui.filename->text().isEmpty()) {
+ if (audioPreview)
+ delete audioPreview;
- audioPreview = Phonon::createPlayer(Phonon::NotificationCategory,
- Phonon::MediaSource(ui.filename->text()));
- audioPreview->play();
+ audioPreview = Phonon::createPlayer(Phonon::NotificationCategory, Phonon::MediaSource(ui.filename->text()));
+ audioPreview->play();
+ }
}
+ else
+ QApplication::beep();
}
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
class ConfigWidget;
bool _enabled;
+ bool _audioAvailable;
Phonon::MediaObject *_media;
};
Ui::PhononNotificationConfigWidget ui;
bool enabled;
+ bool _audioAvailable;
QString filename;
Phonon::MediaObject *audioPreview;
};
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
return config->autoWhoNickLimit();
if (widgetName == "autoWhoDelay")
return config->autoWhoDelay();
+ if (widgetName == "standardCtcp")
+ return config->standardCtcp();
return SettingsPage::loadAutoWidgetValue(widgetName);
}
config->requestSetAutoWhoNickLimit(value.toInt());
else if (widgetName == "autoWhoDelay")
config->requestSetAutoWhoDelay(value.toInt());
+ else if (widgetName == "standardCtcp")
+ config->requestSetStandardCtcp(value.toBool());
else
SettingsPage::saveAutoWidgetValue(widgetName, value);
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
</layout>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="standardCtcp">
+ <property name="text">
+ <string>Enable standard-compliant CTCP behavior</string>
+ </property>
+ <property name="settingsKey" stdset="0">
+ <string notr="true" />
+ </property>
+ </widget>
+ </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
void IdentityEditWidget::saveToIdentity(CertIdentity *id)
{
+ QRegExp linebreaks = QRegExp("[\\r\\n]");
id->setRealName(ui.realName->text());
QStringList nicks;
for (int i = 0; i < ui.nicknameList->count(); i++) {
id->setNicks(nicks);
id->setAwayNick(ui.awayNick->text());
id->setAwayNickEnabled(true);
- id->setAwayReason(ui.awayReason->text());
+ id->setAwayReason(ui.awayReason->text().remove(linebreaks));
id->setAwayReasonEnabled(true);
id->setAutoAwayEnabled(ui.autoAwayEnabled->isChecked());
id->setAutoAwayTime(ui.autoAwayTime->value());
- id->setAutoAwayReason(ui.autoAwayReason->text());
+ id->setAutoAwayReason(ui.autoAwayReason->text().remove(linebreaks));
id->setAutoAwayReasonEnabled(ui.autoAwayReasonEnabled->isChecked());
id->setDetachAwayEnabled(ui.detachAwayEnabled->isChecked());
- id->setDetachAwayReason(ui.detachAwayReason->text());
+ id->setDetachAwayReason(ui.detachAwayReason->text().remove(linebreaks));
id->setDetachAwayReasonEnabled(true);
id->setIdent(ui.ident->text());
- id->setKickReason(ui.kickReason->text());
- id->setPartReason(ui.partReason->text());
- id->setQuitReason(ui.quitReason->text());
+ id->setKickReason(ui.kickReason->text().remove(linebreaks));
+ id->setPartReason(ui.partReason->text().remove(linebreaks));
+ id->setQuitReason(ui.quitReason->text().remove(linebreaks));
#ifdef HAVE_SSL
id->setSslKey(QSslKey(ui.keyTypeLabel->property("sslKey").toByteArray(), (QSsl::KeyAlgorithm)(ui.keyTypeLabel->property("sslKeyType").toInt())));
id->setSslCert(QSslCertificate(ui.certOrgLabel->property("sslCert").toByteArray()));
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This class has been inspired by KDE's KKeySequenceWidget and uses *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This class has been inspired by KDE's KKeySequenceWidget and uses *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
NetworksSettingsPage::NetworksSettingsPage(QWidget *parent)
: SettingsPage(tr("IRC"), tr("Networks"), parent)
+#ifdef HAVE_SSL
+ , _cid(0)
+#endif
{
ui.setupUi(this);
// hide SASL options for older cores
if (!(Client::coreFeatures() & Quassel::SaslAuthentication))
ui.sasl->hide();
+ if (!(Client::coreFeatures() & Quassel::SaslExternal))
+ ui.saslExtInfo->hide();
+#ifndef HAVE_SSL
+ ui.saslExtInfo->hide();
+#endif
// set up icons
ui.renameNetwork->setIcon(SmallIcon("edit-rename"));
_ignoreWidgetChanges = true;
if (id != 0) {
NetworkInfo info = networkInfos[id];
+
+#ifdef HAVE_SSL
+ // this is only needed when the core supports SASL EXTERNAL
+ if (Client::coreFeatures() & Quassel::SaslExternal) {
+ if (_cid) {
+ disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated()));
+ delete _cid;
+ }
+ _cid = new CertIdentity(*Client::identity(info.identity), this);
+ _cid->enableEditSsl(true);
+ connect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated()));
+ }
+#endif
+
ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt()));
ui.serverList->clear();
foreach(Network::Server server, info.serverList) {
}
else {
// just clear widgets
+#ifdef HAVE_SSL
+ if (_cid) {
+ disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated()));
+ delete _cid;
+ }
+#endif
ui.identityList->setCurrentIndex(-1);
ui.serverList->clear();
ui.performEdit->clear();
}
+#ifdef HAVE_SSL
+void NetworksSettingsPage::sslUpdated()
+{
+ if (_cid && !_cid->sslKey().isNull()) {
+ ui.saslAccount->setDisabled(true);
+ ui.saslAccountLabel->setDisabled(true);
+ ui.saslPassword->setDisabled(true);
+ ui.saslPasswordLabel->setDisabled(true);
+ ui.saslExtInfo->setHidden(false);
+ } else {
+ ui.saslAccount->setDisabled(false);
+ ui.saslAccountLabel->setDisabled(false);
+ ui.saslPassword->setDisabled(false);
+ ui.saslPasswordLabel->setDisabled(false);
+ ui.saslExtInfo->setHidden(true);
+ }
+}
+#endif
+
+
/*** Network list ***/
void NetworksSettingsPage::on_networkList_itemSelectionChanged()
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "network.h"
#include "settingspage.h"
+#include "clientidentity.h"
#include "ui_networkssettingspage.h"
#include "ui_networkadddlg.h"
void clientIdentityRemoved(IdentityId);
void clientIdentityUpdated();
+#ifdef HAVE_SSL
+ void sslUpdated();
+#endif
+
void on_networkList_itemSelectionChanged();
void on_addNetwork_clicked();
void on_deleteNetwork_clicked();
NetworkId currentId;
QHash<NetworkId, NetworkInfo> networkInfos;
bool _ignoreWidgetChanges;
+#ifdef HAVE_SSL
+ CertIdentity *_cid;
+#endif
QPixmap connectedIcon, connectingIcon, disconnectedIcon;
<rect>
<x>0</x>
<y>0</y>
- <width>515</width>
- <height>503</height>
+ <width>510</width>
+ <height>505</height>
</rect>
</property>
<property name="windowTitle">
</widget>
</item>
<item row="1" column="0">
- <widget class="QLabel" name="label_11">
+ <widget class="QLabel" name="saslPasswordLabel">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
- <widget class="QLabel" name="label_10">
+ <widget class="QLabel" name="saslAccountLabel">
<property name="enabled">
<bool>true</bool>
</property>
</layout>
</widget>
</item>
+ <item>
+ <widget class="QLabel" name="saslExtInfo">
+ <property name="text">
+ <string><html><head/><body><p><span style=" font-weight:600;">Note:</span> because the identity has an ssl certificate set, SASL EXTERNAL will be used.</p></body></html></string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This contains code from KStatusNotifierItem, part of the KDE libs *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This contains code from KStatusNotifierItem, part of the KDE libs *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This contains code from KStatusNotifierItem, part of the KDE libs *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* Based in part on KDE's kiconloader.h *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
QString UiStyle::mircToInternal(const QString &mirc_)
{
- QString mirc = mirc_;
- mirc.replace('%', "%%"); // escape % just to be sure
- mirc.replace('\t', " "); // tabs break layout, also this is italics in Konversation
- mirc.replace('\x02', "%B");
- mirc.replace('\x0f', "%O");
- mirc.replace('\x12', "%R");
- mirc.replace('\x16', "%R");
- mirc.replace('\x1d', "%S");
- mirc.replace('\x1f', "%U");
+ QString mirc;
+ mirc.reserve(mirc_.size());
+ foreach (const QChar &c, mirc_) {
+ if ((c < '\x20' || c == '\x7f') && c != '\x03') {
+ switch (c.unicode()) {
+ case '\x02':
+ mirc += "%B";
+ break;
+ case '\x0f':
+ mirc += "%O";
+ break;
+ case '\x12':
+ case '\x16':
+ mirc += "%R";
+ break;
+ case '\x1d':
+ mirc += "%S";
+ break;
+ case '\x1f':
+ mirc += "%U";
+ break;
+ case '\x7f':
+ mirc += QChar(0x2421);
+ break;
+ default:
+ mirc += QChar(0x2400 + c.unicode());
+ }
+ } else {
+ if (c == '\t') {
+ mirc += " ";
+ continue;
+ }
+ if (c == '%')
+ mirc += c;
+ mirc += c;
+ }
+ }
// Now we bring the color codes (\x03) in a sane format that can be parsed more easily later.
// %Dcfxx is foreground, %Dcbxx is background color, where xx is a 2 digit dec number denoting the color code.
//: Error Message
t = tr("%1").arg(txt); break;
case Message::DayChange:
+ {
//: Day Change Message
- t = tr("{Day changed to %1}").arg(timestamp().toString());
+ t = tr("{Day changed to %1}").arg(QLocale().toString(timestamp(), QLocale().dateFormat()));
+ }
break;
case Message::Topic:
//: Topic Message
/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2013 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *