diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2015-09-09 19:00:56 +0200 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2015-09-09 19:02:23 +0200 |
| commit | 8a6d4b06f2291c363f3dea17837ed20893852453 (patch) | |
| tree | c091375499e35eaa1810586454e0834c06e6c9b2 /libcommuni/src/core/ircconnection.cpp | |
| parent | f554a27046f203e56a07baaf214d90834942e3f5 (diff) | |
| download | manager-8a6d4b06f2291c363f3dea17837ed20893852453.tar.gz manager-8a6d4b06f2291c363f3dea17837ed20893852453.zip | |
Cleanup repo with some directories
Diffstat (limited to 'libcommuni/src/core/ircconnection.cpp')
| -rw-r--r-- | libcommuni/src/core/ircconnection.cpp | 1508 |
1 files changed, 0 insertions, 1508 deletions
diff --git a/libcommuni/src/core/ircconnection.cpp b/libcommuni/src/core/ircconnection.cpp deleted file mode 100644 index 837aa16..0000000 --- a/libcommuni/src/core/ircconnection.cpp +++ /dev/null @@ -1,1508 +0,0 @@ -/* - Copyright (C) 2008-2014 The Communi Project - - You may use this file under the terms of BSD license as follows: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "ircconnection.h" -#include "ircconnection_p.h" -#include "ircnetwork_p.h" -#include "ircprotocol.h" -#include "ircnetwork.h" -#include "irccommand.h" -#include "ircmessage.h" -#include "ircfilter.h" -#include "irc.h" -#include <QLocale> -#include <QDateTime> -#include <QTcpSocket> -#include <QTextCodec> -#include <QStringList> -#include <QMetaObject> -#include <QMetaMethod> -#include <QMetaEnum> -#ifndef QT_NO_OPENSSL -#include <QSslSocket> -#include <QSslError> -#endif // QT_NO_OPENSSL -#include <QDataStream> -#include <QVariantMap> - -IRC_BEGIN_NAMESPACE - -/*! - \file ircconnection.h - \brief \#include <IrcConnection> - */ - -/*! - \class IrcConnection ircconnection.h IrcConnection - \ingroup core - \brief Provides means to establish a connection to an IRC server. - - \section connection-management Connection management - - Before \ref open() "opening" a connection, it must be first initialized - with \ref host, \ref userName, \ref nickName and \ref realName. - - The connection status may be queried at any time via status(). Also - \ref active "isActive()" and \ref connected "isConnected()" are provided - for convenience. In addition to the \ref status "statusChanged()" signal, - the most important statuses are informed via the following convenience - signals: - \li connecting() - - The connection is being established. - \li \ref connected "connected()" - - The IRC connection has been established, and the server is ready to receive commands. - \li disconnected() - - The connection has been lost. - - \section receiving-messages Receiving messages - - Whenever a message is received from the server, the messageReceived() - signal is emitted. Also message type specific signals are provided - for convenience. See messageReceived() and IrcMessage and its - subclasses for more details. - - \section sending-commands Sending commands - - Sending commands to a server is most conveniently done by creating - them via the various static \ref IrcCommand "IrcCommand::createXxx()" - methods and passing them to sendCommand(). Also sendData() is provided - for more low-level access. See IrcCommand for more details. - - \section example Example - - \code - IrcConnection* connection = new IrcConnection(this); - connect(connection, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*))); - connection->setHost("irc.server.com"); - connection->setUserName("me"); - connection->setNickName("myself"); - connection->setRealName("And I"); - connection->sendCommand(IrcCommand::createJoin("#mine")); - connection->open(); - \endcode - - \sa IrcNetwork, IrcMessage, IrcCommand - */ - -/*! - \enum IrcConnection::Status - This enum describes the connection status. - */ - -/*! - \var IrcConnection::Inactive - \brief The connection is inactive. - */ - -/*! - \var IrcConnection::Waiting - \brief The connection is waiting for a reconnect. - */ - -/*! - \var IrcConnection::Connecting - \brief The connection is being established. - */ - -/*! - \var IrcConnection::Connected - \brief The connection has been established. - */ - -/*! - \var IrcConnection::Closing - \brief The connection is being closed. - */ - -/*! - \var IrcConnection::Closed - \brief The connection has been closed. - */ - -/*! - \var IrcConnection::Error - \brief The connection has encountered an error. - */ - -/*! - \fn void IrcConnection::connecting() - - This signal is emitted when the connection is being established. - - The underlying \ref socket has connected, but the IRC handshake is - not yet finished and the server is not yet ready to receive commands. - */ - -/*! - \fn void IrcConnection::nickNameRequired(const QString& reserved, QString* alternate) - - This signal is emitted when the requested nick name is \a reserved - and an \a alternate nick name should be provided. - - An alternate nick name may be set via the provided argument, by changing - the \ref nickName property, or by sending a nick command directly. - - \sa IrcCommand::createNick(), Irc::ERR_NICKNAMEINUSE, Irc::ERR_NICKCOLLISION - */ - -/*! - \fn void IrcConnection::channelKeyRequired(const QString& channel, QString* key) - - This signal is emitted when joining a \a channel requires a \a key. - The key may be set via the provided argument, or by sending a new - join command directly. - - \sa IrcCommand::createJoin(), Irc::ERR_BADCHANNELKEY - */ - -/*! - \fn void IrcConnection::disconnected() - - This signal is emitted when the connection has been lost. - */ - -/*! - \fn void IrcConnection::socketError(QAbstractSocket::SocketError error) - - This signal is emitted when a \ref socket \a error occurs. - - \sa QAbstractSocket::error() - */ - -/*! - \fn void IrcConnection::socketStateChanged(QAbstractSocket::SocketState state) - - This signal is emitted when the \a state of the underlying \ref socket changes. - - \sa QAbstractSocket::stateChanged() - */ - -/*! - \since 3.2 - \fn void IrcConnection::secureError() - - This signal is emitted when SSL socket error occurs. - - Either QSslSocket::sslErrors() was emitted, or the remote host closed - the connection without QSslSocket::sslErrors() being emitted meaning - that the server is not SSL-enabled. - */ - -/*! - \fn void IrcConnection::messageReceived(IrcMessage* message) - - This signal is emitted when a \a message is received. - - In addition, message type specific signals are provided for convenience: - \li void <b>capabilityMessageReceived</b>(\ref IrcCapabilityMessage* message) - \li void <b>errorMessageReceived</b>(\ref IrcErrorMessage* message) - \li void <b>inviteMessageReceived</b>(\ref IrcInviteMessage* message) - \li void <b>joinMessageReceived</b>(\ref IrcJoinMessage* message) - \li void <b>kickMessageReceived</b>(\ref IrcKickMessage* message) - \li void <b>modeMessageReceived</b>(\ref IrcModeMessage* message) - \li void <b>namesMessageReceived</b>(\ref IrcNamesMessage* message) - \li void <b>nickMessageReceived</b>(\ref IrcNickMessage* message) - \li void <b>noticeMessageReceived</b>(\ref IrcNoticeMessage* message) - \li void <b>numericMessageReceived</b>(\ref IrcNumericMessage* message) - \li void <b>motdMessageReceived</b>(\ref IrcMotdMessage* message) - \li void <b>partMessageReceived</b>(\ref IrcPartMessage* message) - \li void <b>pingMessageReceived</b>(\ref IrcPingMessage* message) - \li void <b>pongMessageReceived</b>(\ref IrcPongMessage* message) - \li void <b>privateMessageReceived</b>(\ref IrcPrivateMessage* message) - \li void <b>quitMessageReceived</b>(\ref IrcQuitMessage* message) - \li void <b>topicMessageReceived</b>(\ref IrcTopicMessage* message) - */ - -#ifndef IRC_DOXYGEN -template<typename T> -static void irc_debug(IrcConnection* connection, const char* msg, const T& arg) -{ - static bool dbg = qgetenv("IRC_DEBUG").toInt(); - if (dbg) { - const QString desc = QString::fromLatin1("IrcConnection(%1)").arg(connection->displayName()); - qDebug() << qPrintable(desc) << msg << arg; - } -} - -IrcConnectionPrivate::IrcConnectionPrivate() : - q_ptr(0), - encoding("ISO-8859-15"), - network(0), - protocol(0), - socket(0), - host(), - port(6667), - userName(), - nickName(), - realName(), - enabled(true), - status(IrcConnection::Inactive), - sslErrors(false), - closed(false) -{ -} - -void IrcConnectionPrivate::init(IrcConnection* connection) -{ - q_ptr = connection; - network = IrcNetworkPrivate::create(connection); - connection->setSocket(new QTcpSocket(connection)); - connection->setProtocol(new IrcProtocol(connection)); - QObject::connect(&reconnecter, SIGNAL(timeout()), connection, SLOT(_irc_reconnect())); -} - -void IrcConnectionPrivate::_irc_connected() -{ - Q_Q(IrcConnection); - closed = false; - sslErrors = false; - emit q->connecting(); - if (q->isSecure()) - QMetaObject::invokeMethod(socket, "startClientEncryption"); - protocol->open(); -} - -void IrcConnectionPrivate::_irc_disconnected() -{ - Q_Q(IrcConnection); - protocol->close(); - emit q->disconnected(); - if (enabled && !sslErrors && (status != IrcConnection::Closed || !closed) && !reconnecter.isActive() && reconnecter.interval() > 0) { - reconnecter.start(); - setStatus(IrcConnection::Waiting); - } -} - -void IrcConnectionPrivate::_irc_error(QAbstractSocket::SocketError error) -{ - Q_Q(IrcConnection); - if (!closed && !sslErrors && error == QAbstractSocket::RemoteHostClosedError && q->isSecure()) { - irc_debug(q, "SSL error:", "no SSL available"); - setStatus(IrcConnection::Error); - sslErrors = true; - emit q->secureError(); - } else if (!closed || (error != QAbstractSocket::RemoteHostClosedError && error != QAbstractSocket::UnknownSocketError)) { - irc_debug(q, "socket error:", error); - emit q->socketError(error); - setStatus(IrcConnection::Error); - } -} - -void IrcConnectionPrivate::_irc_sslErrors() -{ - Q_Q(IrcConnection); - QStringList errors; -#ifndef QT_NO_OPENSSL - QSslSocket* ssl = qobject_cast<QSslSocket*>(socket); - if (ssl) { - foreach (const QSslError& error, ssl->sslErrors()) - errors += error.errorString(); - } -#endif - irc_debug(q, "SSL handshake errors:", errors); - sslErrors = true; - emit q->secureError(); -} - -void IrcConnectionPrivate::_irc_state(QAbstractSocket::SocketState state) -{ - Q_Q(IrcConnection); - switch (state) { - case QAbstractSocket::UnconnectedState: - if (closed) - setStatus(IrcConnection::Closed); - break; - case QAbstractSocket::ClosingState: - if (status != IrcConnection::Error) - setStatus(IrcConnection::Closing); - break; - case QAbstractSocket::HostLookupState: - case QAbstractSocket::ConnectingState: - case QAbstractSocket::ConnectedState: - default: - setStatus(IrcConnection::Connecting); - break; - } - emit q->socketStateChanged(state); -} - -void IrcConnectionPrivate::_irc_reconnect() -{ - Q_Q(IrcConnection); - if (!q->isActive()) { - reconnecter.stop(); - q->open(); - } -} - -void IrcConnectionPrivate::_irc_readData() -{ - protocol->read(); -} - -void IrcConnectionPrivate::_irc_filterDestroyed(QObject* filter) -{ - messageFilters.removeAll(filter); - commandFilters.removeAll(filter); -} - -void IrcConnectionPrivate::setNick(const QString& nick) -{ - Q_Q(IrcConnection); - if (nickName != nick) { - nickName = nick; - emit q->nickNameChanged(nick); - } -} - -void IrcConnectionPrivate::setStatus(IrcConnection::Status value) -{ - Q_Q(IrcConnection); - if (status != value) { - const bool wasConnected = q->isConnected(); - status = value; - emit q->statusChanged(value); - - if (!wasConnected && q->isConnected()) { - emit q->connected(); - foreach (IrcCommand* cmd, pendingCommands) - q->sendCommand(cmd); - pendingCommands.clear(); - } - irc_debug(q, "status:", status); - } -} - -void IrcConnectionPrivate::setInfo(const QHash<QString, QString>& info) -{ - Q_Q(IrcConnection); - const QString oldName = q->displayName(); - IrcNetworkPrivate* priv = IrcNetworkPrivate::get(network); - priv->setInfo(info); - const QString newName = q->displayName(); - if (oldName != newName) - emit q->displayNameChanged(newName); -} - -void IrcConnectionPrivate::receiveMessage(IrcMessage* msg) -{ - Q_Q(IrcConnection); - bool filtered = false; - for (int i = messageFilters.count() - 1; !filtered && i >= 0; --i) { - IrcMessageFilter* filter = qobject_cast<IrcMessageFilter*>(messageFilters.at(i)); - if (filter) - filtered |= filter->messageFilter(msg); - } - - if (!filtered) { - emit q->messageReceived(msg); - - switch (msg->type()) { - case IrcMessage::Nick: - emit q->nickMessageReceived(static_cast<IrcNickMessage*>(msg)); - break; - case IrcMessage::Quit: - emit q->quitMessageReceived(static_cast<IrcQuitMessage*>(msg)); - break; - case IrcMessage::Join: - emit q->joinMessageReceived(static_cast<IrcJoinMessage*>(msg)); - break; - case IrcMessage::Part: - emit q->partMessageReceived(static_cast<IrcPartMessage*>(msg)); - break; - case IrcMessage::Topic: - emit q->topicMessageReceived(static_cast<IrcTopicMessage*>(msg)); - break; - case IrcMessage::WhoReply: - emit q->whoReplyMessageReceived(static_cast<IrcWhoReplyMessage*>(msg)); - break; - case IrcMessage::Invite: - emit q->inviteMessageReceived(static_cast<IrcInviteMessage*>(msg)); - break; - case IrcMessage::Kick: - emit q->kickMessageReceived(static_cast<IrcKickMessage*>(msg)); - break; - case IrcMessage::Mode: - emit q->modeMessageReceived(static_cast<IrcModeMessage*>(msg)); - break; - case IrcMessage::Private: - emit q->privateMessageReceived(static_cast<IrcPrivateMessage*>(msg)); - break; - case IrcMessage::Notice: - emit q->noticeMessageReceived(static_cast<IrcNoticeMessage*>(msg)); - break; - case IrcMessage::Ping: - emit q->pingMessageReceived(static_cast<IrcPingMessage*>(msg)); - break; - case IrcMessage::Pong: - emit q->pongMessageReceived(static_cast<IrcPongMessage*>(msg)); - break; - case IrcMessage::Error: - emit q->errorMessageReceived(static_cast<IrcErrorMessage*>(msg)); - break; - case IrcMessage::Numeric: - emit q->numericMessageReceived(static_cast<IrcNumericMessage*>(msg)); - break; - case IrcMessage::Capability: - emit q->capabilityMessageReceived(static_cast<IrcCapabilityMessage*>(msg)); - break; - case IrcMessage::Motd: - emit q->motdMessageReceived(static_cast<IrcMotdMessage*>(msg)); - break; - case IrcMessage::Names: - emit q->namesMessageReceived(static_cast<IrcNamesMessage*>(msg)); - break; - case IrcMessage::Unknown: - default: - break; - } - } - msg->deleteLater(); -} - -IrcCommand* IrcConnectionPrivate::createCtcpReply(IrcPrivateMessage* request) -{ - Q_Q(IrcConnection); - IrcCommand* reply = 0; - const QMetaObject* metaObject = q->metaObject(); - int idx = metaObject->indexOfMethod("createCtcpReply(QVariant)"); - if (idx != -1) { - // QML: QVariant createCtcpReply(QVariant) - QVariant ret; - QMetaMethod method = metaObject->method(idx); - method.invoke(q, Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, QVariant::fromValue(request))); - reply = ret.value<IrcCommand*>(); - } else { - // C++: IrcCommand* createCtcpReply(IrcPrivateMessage*) - idx = metaObject->indexOfMethod("createCtcpReply(IrcPrivateMessage*)"); - QMetaMethod method = metaObject->method(idx); - method.invoke(q, Q_RETURN_ARG(IrcCommand*, reply), Q_ARG(IrcPrivateMessage*, request)); - } - return reply; -} -#endif // IRC_DOXYGEN - -/*! - Constructs a new IRC connection with \a parent. - */ -IrcConnection::IrcConnection(QObject* parent) : QObject(parent), d_ptr(new IrcConnectionPrivate) -{ - Q_D(IrcConnection); - d->init(this); -} - -/*! - Constructs a new IRC connection with \a host and \a parent. - */ -IrcConnection::IrcConnection(const QString& host, QObject* parent) : QObject(parent), d_ptr(new IrcConnectionPrivate) -{ - Q_D(IrcConnection); - d->init(this); - setHost(host); -} - -/*! - Destructs the IRC connection. - */ -IrcConnection::~IrcConnection() -{ - close(); - emit destroyed(this); -} - -/*! - This property holds the FALLBACK encoding for received messages. - - The fallback encoding is used when the message is detected not - to be valid \c UTF-8 and the consequent auto-detection of message - encoding fails. See QTextCodec::availableCodecs() for the list of - supported encodings. - - The default value is \c ISO-8859-15. - - \par Access functions: - \li QByteArray <b>encoding</b>() const - \li void <b>setEncoding</b>(const QByteArray& encoding) - - \sa QTextCodec::availableCodecs(), QTextCodec::codecForLocale() - */ -QByteArray IrcConnection::encoding() const -{ - Q_D(const IrcConnection); - return d->encoding; -} - -void IrcConnection::setEncoding(const QByteArray& encoding) -{ - Q_D(IrcConnection); - extern bool irc_is_supported_encoding(const QByteArray& encoding); // ircmessagedecoder.cpp - if (!irc_is_supported_encoding(encoding)) { - qWarning() << "IrcConnection::setEncoding(): unsupported encoding" << encoding; - return; - } - d->encoding = encoding; -} - -/*! - This property holds the server host. - - \par Access functions: - \li QString <b>host</b>() const - \li void <b>setHost</b>(const QString& host) - - \par Notifier signal: - \li void <b>hostChanged</b>(const QString& host) - */ -QString IrcConnection::host() const -{ - Q_D(const IrcConnection); - return d->host; -} - -void IrcConnection::setHost(const QString& host) -{ - Q_D(IrcConnection); - if (d->host != host) { - if (isActive()) - qWarning("IrcConnection::setHost() has no effect until re-connect"); - const QString oldName = displayName(); - d->host = host; - emit hostChanged(host); - const QString newName = displayName(); - if (oldName != newName) - emit displayNameChanged(newName); - } -} - -/*! - This property holds the server port. - - The default value is \c 6667. - - \par Access functions: - \li int <b>port</b>() const - \li void <b>setPort</b>(int port) - - \par Notifier signal: - \li void <b>portChanged</b>(int port) - */ -int IrcConnection::port() const -{ - Q_D(const IrcConnection); - return d->port; -} - -void IrcConnection::setPort(int port) -{ - Q_D(IrcConnection); - if (d->port != port) { - if (isActive()) - qWarning("IrcConnection::setPort() has no effect until re-connect"); - d->port = port; - emit portChanged(port); - } -} - -/*! - This property holds the user name. - - \note Changing the user name has no effect until the connection is re-established. - - \par Access functions: - \li QString <b>userName</b>() const - \li void <b>setUserName</b>(const QString& name) - - \par Notifier signal: - \li void <b>userNameChanged</b>(const QString& name) - */ -QString IrcConnection::userName() const -{ - Q_D(const IrcConnection); - return d->userName; -} - -void IrcConnection::setUserName(const QString& name) -{ - Q_D(IrcConnection); - QString user = name.split(" ", QString::SkipEmptyParts).value(0).trimmed(); - if (d->userName != user) { - if (isActive()) - qWarning("IrcConnection::setUserName() has no effect until re-connect"); - d->userName = user; - emit userNameChanged(user); - } -} - -/*! - This property holds the nick name. - - \par Access functions: - \li QString <b>nickName</b>() const - \li void <b>setNickName</b>(const QString& name) - - \par Notifier signal: - \li void <b>nickNameChanged</b>(const QString& name) - */ -QString IrcConnection::nickName() const -{ - Q_D(const IrcConnection); - return d->nickName; -} - -void IrcConnection::setNickName(const QString& name) -{ - Q_D(IrcConnection); - QString nick = name.split(" ", QString::SkipEmptyParts).value(0).trimmed(); - if (d->nickName != nick) { - if (isActive()) - sendCommand(IrcCommand::createNick(nick)); - else - d->setNick(nick); - } -} - -/*! - This property holds the real name. - - \note Changing the real name has no effect until the connection is re-established. - - \par Access functions: - \li QString <b>realName</b>() const - \li void <b>setRealName</b>(const QString& name) - - \par Notifier signal: - \li void <b>realNameChanged</b>(const QString& name) - */ -QString IrcConnection::realName() const -{ - Q_D(const IrcConnection); - return d->realName; -} - -void IrcConnection::setRealName(const QString& name) -{ - Q_D(IrcConnection); - if (d->realName != name) { - if (isActive()) - qWarning("IrcConnection::setRealName() has no effect until re-connect"); - d->realName = name; - emit realNameChanged(name); - } -} - -/*! - This property holds the password. - - \par Access functions: - \li QString <b>password</b>() const - \li void <b>setPassword</b>(const QString& password) - - \par Notifier signal: - \li void <b>passwordChanged</b>(const QString& password) - */ -QString IrcConnection::password() const -{ - Q_D(const IrcConnection); - return d->password; -} - -void IrcConnection::setPassword(const QString& password) -{ - Q_D(IrcConnection); - if (d->password != password) { - if (isActive()) - qWarning("IrcConnection::setPassword() has no effect until re-connect"); - d->password = password; - emit passwordChanged(password); - } -} - -/*! - This property holds the display name. - - Unless explicitly set, display name resolves to IrcNetwork::name - or IrcConnection::host while the former is not known. - - \par Access functions: - \li QString <b>displayName</b>() const - \li void <b>setDisplayName</b>(const QString& name) - - \par Notifier signal: - \li void <b>displayNameChanged</b>(const QString& name) - */ -QString IrcConnection::displayName() const -{ - Q_D(const IrcConnection); - QString name = d->displayName; - if (name.isEmpty()) - name = d->network->name(); - if (name.isEmpty()) - name = d->host; - return name; -} - -void IrcConnection::setDisplayName(const QString& name) -{ - Q_D(IrcConnection); - if (d->displayName != name) { - d->displayName = name; - emit displayNameChanged(name); - } -} - -/*! - \since 3.1 - - This property holds arbitrary user data. - - \par Access functions: - \li QVariantMap <b>userData</b>() const - \li void <b>setUserData</b>(const QVariantMap& data) - - \par Notifier signal: - \li void <b>userDataChanged</b>(const QVariantMap& data) - */ -QVariantMap IrcConnection::userData() const -{ - Q_D(const IrcConnection); - return d->userData; -} - -void IrcConnection::setUserData(const QVariantMap& data) -{ - Q_D(IrcConnection); - if (d->userData != data) { - d->userData = data; - emit userDataChanged(data); - } -} - -/*! - \property Status IrcConnection::status - This property holds the connection status. - - \par Access function: - \li Status <b>status</b>() const - - \par Notifier signal: - \li void <b>statusChanged</b>(Status status) - */ -IrcConnection::Status IrcConnection::status() const -{ - Q_D(const IrcConnection); - return d->status; -} - -/*! - \property bool IrcConnection::active - This property holds whether the connection is active. - - The connection is considered active when its either connecting, connected or closing. - - \par Access function: - \li bool <b>isActive</b>() const - */ -bool IrcConnection::isActive() const -{ - Q_D(const IrcConnection); - return d->status == Connecting || d->status == Connected || d->status == Closing; -} - -/*! - \property bool IrcConnection::connected - This property holds whether the connection has been established. - - The connection has been established when the welcome message - has been received and the server is ready to receive commands. - - \sa Irc::RPL_WELCOME - - \par Access function: - \li bool <b>isConnected</b>() const - - \par Notifier signal: - \li void <b>connected</b>() - */ -bool IrcConnection::isConnected() const -{ - Q_D(const IrcConnection); - return d->status == Connected; -} - -/*! - \property bool IrcConnection::enabled - This property holds whether the connection is enabled. - - The default value is \c true. - - When set to \c false, a disabled connection does nothing when open() is called. - - \par Access functions: - \li bool <b>isEnabled</b>() const - \li void <b>setEnabled</b>(bool enabled) [slot] - \li void <b>setDisabled</b>(bool disabled) [slot] - - \par Notifier signal: - \li void <b>enabledChanged</b>(bool enabled) - */ -bool IrcConnection::isEnabled() const -{ - Q_D(const IrcConnection); - return d->enabled; -} - -void IrcConnection::setEnabled(bool enabled) -{ - Q_D(IrcConnection); - if (d->enabled != enabled) { - d->enabled = enabled; - emit enabledChanged(enabled); - } -} - -void IrcConnection::setDisabled(bool disabled) -{ - setEnabled(!disabled); -} - -/*! - \property int IrcConnection::reconnectDelay - This property holds the reconnect delay in seconds. - - A positive (greater than zero) value enables automatic reconnect. - When the connection is lost due to a socket error, IrcConnection - will automatically attempt to reconnect after the specified delay. - - The default value is \c 0 (automatic reconnect disabled). - - \par Access functions: - \li int <b>reconnectDelay</b>() const - \li void <b>setReconnectDelay</b>(int seconds) - - \par Notifier signal: - \li void <b>reconnectDelayChanged</b>(int seconds) - */ -int IrcConnection::reconnectDelay() const -{ - Q_D(const IrcConnection); - return d->reconnecter.interval() / 1000; -} - -void IrcConnection::setReconnectDelay(int seconds) -{ - Q_D(IrcConnection); - const int interval = qMax(0, seconds) * 1000; - if (d->reconnecter.interval() != interval) { - d->reconnecter.setInterval(interval); - emit reconnectDelayChanged(interval); - } -} - -/*! - This property holds the socket. The default value is an instance of QTcpSocket. - - The previously set socket is deleted if its parent is \c this. - - \note IrcConnection supports QSslSocket in the way that it automatically - calls QSslSocket::startClientEncryption() while connecting. - - \par Access functions: - \li \ref QAbstractSocket* <b>socket</b>() const - \li void <b>setSocket</b>(\ref QAbstractSocket* socket) - - \sa IrcConnection::secure - */ -QAbstractSocket* IrcConnection::socket() const -{ - Q_D(const IrcConnection); - return d->socket; -} - -void IrcConnection::setSocket(QAbstractSocket* socket) -{ - Q_D(IrcConnection); - if (d->socket != socket) { - if (d->socket) { - d->socket->disconnect(this); - if (d->socket->parent() == this) - d->socket->deleteLater(); - } - - d->socket = socket; - if (socket) { - connect(socket, SIGNAL(connected()), this, SLOT(_irc_connected())); - connect(socket, SIGNAL(disconnected()), this, SLOT(_irc_disconnected())); - connect(socket, SIGNAL(readyRead()), this, SLOT(_irc_readData())); - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_irc_error(QAbstractSocket::SocketError))); - connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(_irc_state(QAbstractSocket::SocketState))); - if (isSecure()) - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(_irc_sslErrors())); - } - } -} - -/*! - \property bool IrcConnection::secure - This property holds whether the socket is an SSL socket. - - This property is provided for convenience. Calling - \code - connection->setSecure(true); - \endcode - - is equivalent to: - - \code - QSslSocket* socket = new QSslSocket(socket); - socket->setPeerVerifyMode(QSslSocket::QueryPeer); - connection->setSocket(socket); - \endcode - - \note IrcConnection does not handle SSL errors, see - QSslSocket::sslErrors() for more details on the subject. - - \par Access functions: - \li bool <b>isSecure</b>() const - \li void <b>setSecure</b>(bool secure) - - \par Notifier signal: - \li void <b>secureChanged</b>(bool secure) - - \sa secureSupported, IrcConnection::socket - */ -bool IrcConnection::isSecure() const -{ -#ifdef QT_NO_OPENSSL - return false; -#else - return qobject_cast<QSslSocket*>(socket()); -#endif // QT_NO_OPENSSL -} - -void IrcConnection::setSecure(bool secure) -{ -#ifdef QT_NO_OPENSSL - if (secure) { - qWarning("IrcConnection::setSecure(): the Qt build does not support SSL"); - return; - } -#else - if (secure && !QSslSocket::supportsSsl()) { - qWarning("IrcConnection::setSecure(): the platform does not support SSL - try installing OpenSSL"); - return; - } - - QSslSocket* sslSocket = qobject_cast<QSslSocket*>(socket()); - if (secure && !sslSocket) { - sslSocket = new QSslSocket(this); - sslSocket->setPeerVerifyMode(QSslSocket::QueryPeer); - setSocket(sslSocket); - emit secureChanged(true); - } else if (!secure && sslSocket) { - setSocket(new QTcpSocket(this)); - emit secureChanged(false); - } -#endif // !QT_NO_OPENSSL -} - -/*! - \since 3.2 - \property bool IrcConnection::secureSupported - This property holds whether SSL is supported. - - The value may be \c false for the following reasons: - \li Qt was built without SSL support (\c QT_NO_SSL is defined), or - \li The platform does not support SSL (QSslSocket::supportsSsl() returns \c false). - - \par Access function: - \li static bool <b>isSecureSupported</b>() - - \sa secure, QSslSocket::supportsSsl() - */ - -bool IrcConnection::isSecureSupported() -{ -#ifdef QT_NO_OPENSSL - return false; -#else - return QSslSocket::supportsSsl(); -#endif -} - -/*! - This property holds the used SASL (Simple Authentication and Security Layer) mechanism. - - \par Access functions: - \li QString <b>saslMechanism</b>() const - \li void <b>setSaslMechanism</b>(const QString& mechanism) - - \par Notifier signal: - \li void <b>saslMechanismChanged</b>(const QString& mechanism) - - \sa supportedSaslMechanisms - */ -QString IrcConnection::saslMechanism() const -{ - Q_D(const IrcConnection); - return d->saslMechanism; -} - -void IrcConnection::setSaslMechanism(const QString& mechanism) -{ - Q_D(IrcConnection); - if (!mechanism.isEmpty() && !supportedSaslMechanisms().contains(mechanism.toUpper())) { - qWarning("IrcConnection::setSaslMechanism(): unsupported mechanism: '%s'", qPrintable(mechanism)); - return; - } - if (d->saslMechanism != mechanism) { - if (isActive()) - qWarning("IrcConnection::setSaslMechanism() has no effect until re-connect"); - d->saslMechanism = mechanism.toUpper(); - emit saslMechanismChanged(mechanism); - } -} - -/*! - This property holds the list of supported SASL (Simple Authentication and Security Layer) mechanisms. - - \par Access function: - \li static QStringList <b>supportedSaslMechanisms</b>() - - \sa saslMechanism - */ -QStringList IrcConnection::supportedSaslMechanisms() -{ - return QStringList() << QLatin1String("PLAIN"); -} - -/*! - This property holds the network information. - - \par Access function: - \li IrcNetwork* <b>network</b>() const - */ -IrcNetwork* IrcConnection::network() const -{ - Q_D(const IrcConnection); - return d->network; -} - -/*! - Opens a connection to the server. - - The function does nothing when the connection is already \ref active - or explicitly \ref enabled "disabled". - - \note The function merely outputs a warnings and returns immediately if - either \ref host, \ref userName, \ref nickName or \ref realName is empty. - */ -void IrcConnection::open() -{ - Q_D(IrcConnection); - if (d->host.isEmpty()) { - qWarning("IrcConnection::open(): host is empty!"); - return; - } - if (d->userName.isEmpty()) { - qWarning("IrcConnection::open(): userName is empty!"); - return; - } - if (d->nickName.isEmpty()) { - qWarning("IrcConnection::open(): nickName is empty!"); - return; - } - if (d->realName.isEmpty()) { - qWarning("IrcConnection::open(): realName is empty!"); - return; - } - if (d->enabled && d->socket && !isActive()) - d->socket->connectToHost(d->host, d->port); -} - -/*! - Immediately closes the connection to the server. - - Calling close() makes the connection close immediately and thus might lead to - "remote host closed the connection". In order to quit gracefully, call quit() - first. This function attempts to flush the underlying socket, but this does - not guarantee that the server ever receives the QUIT command if the connection - is closed immediately after sending the command. In order to ensure a graceful - quit, let the server handle closing the connection. - - C++ example: - \code - connection->quit(reason); - QTimer::singleShot(timeout, connection, SLOT(deleteLater())); - \endcode - - QML example: - \code - connection.quit(reason); - connection.destroy(timeout); - \endcode - - \sa quit() - */ -void IrcConnection::close() -{ - Q_D(IrcConnection); - if (d->socket) { - d->closed = true; - d->socket->flush(); - d->socket->abort(); - d->socket->disconnectFromHost(); - if (d->socket->state() == QAbstractSocket::UnconnectedState) - d->setStatus(Closed); - d->reconnecter.stop(); - } -} - -/*! - Sends a quit command with an optionally specified \a reason. - - This method is provided for convenience. It is equal to: - \code - IrcCommand* command = IrcCommand::createQuit(reason); - connection->sendCommand(command); - \endcode - - \sa IrcCommand::createQuit() - */ -void IrcConnection::quit(const QString& reason) -{ - sendCommand(IrcCommand::createQuit(reason)); -} - -/*! - Sends a \a command to the server. - - If the connection is not active, the \a command is queued and sent - later when the connection has been established. - - \note If the command has a valid parent, it is an indication that - the caller of this method is be responsible for freeing the command. - If the command does not have a valid parent (like the commands - created via various IrcCommand::createXxx() methods) the connection - will take ownership of the command and delete it once it has been - sent. Thus, the command must have been allocated on the heap and - it is not safe to access the command after it has been sent. - - \sa sendData() - */ -bool IrcConnection::sendCommand(IrcCommand* command) -{ - Q_D(IrcConnection); - bool res = false; - if (command) { - bool filtered = false; - for (int i = d->commandFilters.count() - 1; !filtered && i >= 0; --i) { - QObject* filter = d->commandFilters.at(i); - IrcCommandFilter* commandFilter = qobject_cast<IrcCommandFilter*>(filter); - if (commandFilter && !d->activeCommandFilters.contains(filter)) { - d->activeCommandFilters.push(filter); - filtered |= commandFilter->commandFilter(command); - d->activeCommandFilters.pop(); - } - } - if (filtered) - return false; - - if (isActive()) { - QTextCodec* codec = QTextCodec::codecForName(command->encoding()); - Q_ASSERT(codec); - res = sendData(codec->fromUnicode(command->toString())); - if (!command->parent()) - command->deleteLater(); - } else { - Q_D(IrcConnection); - d->pendingCommands += command; - } - } - return res; -} - -/*! - Sends raw \a data to the server. - - \sa sendCommand() - */ -bool IrcConnection::sendData(const QByteArray& data) -{ - Q_D(IrcConnection); - if (d->socket) { - static bool dbg = qgetenv("IRC_DEBUG").toInt(); - if (dbg) qDebug() << "->" << data; - if (!d->closed && data.length() >= 4) { - const QByteArray cmd = data.left(5).toUpper(); - if (cmd.startsWith("QUIT") && (data.length() == 4 || QChar(data.at(4)).isSpace())) - d->closed = true; - } - return d->protocol->write(data); - } - return false; -} - -/*! - Sends raw \a message to the server using UTF-8 encoding. - - \sa sendData(), sendCommand() - */ -bool IrcConnection::sendRaw(const QString& message) -{ - return sendData(message.toUtf8()); -} - -/*! - Installs a message \a filter on the connection. The \a filter must implement the IrcMessageFilter interface. - - A message filter receives all messages that are sent to the connection. The filter - receives messages via the \ref IrcMessageFilter::messageFilter() "messageFilter()" - function. The function must return \c true if the message should be filtered, - (i.e. stopped); otherwise it must return \c false. - - If multiple message filters are installed on the same connection, the filter - that was installed last is activated first. - - \sa removeMessageFilter() - */ -void IrcConnection::installMessageFilter(QObject* filter) -{ - Q_D(IrcConnection); - IrcMessageFilter* msgFilter = qobject_cast<IrcMessageFilter*>(filter); - if (msgFilter) { - d->messageFilters += filter; - connect(filter, SIGNAL(destroyed(QObject*)), this, SLOT(_irc_filterDestroyed(QObject*)), Qt::UniqueConnection); - } -} - -/*! - Removes a message \a filter from the connection. - - The request is ignored if such message filter has not been installed. - All message filters for a connection are automatically removed - when the connection is destroyed. - - \sa installMessageFilter() - */ -void IrcConnection::removeMessageFilter(QObject* filter) -{ - Q_D(IrcConnection); - IrcMessageFilter* msgFilter = qobject_cast<IrcMessageFilter*>(filter); - if (msgFilter) { - d->messageFilters.removeAll(filter); - disconnect(filter, SIGNAL(destroyed(QObject*)), this, SLOT(_irc_filterDestroyed(QObject*))); - } -} - -/*! - Installs a command \a filter on the connection. The \a filter must implement the IrcCommandFilter interface. - - A command filter receives all commands that are sent from the connection. The filter - receives commands via the \ref IrcCommandFilter::commandFilter() "commandFilter()" - function. The function must return \c true if the command should be filtered, - (i.e. stopped); otherwise it must return \c false. - - If multiple command filters are installed on the same connection, the filter - that was installed last is activated first. - - \sa removeCommandFilter() - */ -void IrcConnection::installCommandFilter(QObject* filter) -{ - Q_D(IrcConnection); - IrcCommandFilter* cmdFilter = qobject_cast<IrcCommandFilter*>(filter); - if (cmdFilter) { - d->commandFilters += filter; - connect(filter, SIGNAL(destroyed(QObject*)), this, SLOT(_irc_filterDestroyed(QObject*)), Qt::UniqueConnection); - } -} - -/*! - Removes a command \a filter from the connection. - - The request is ignored if such command filter has not been installed. - All command filters for a connection are automatically removed when - the connection is destroyed. - - \sa installCommandFilter() - */ -void IrcConnection::removeCommandFilter(QObject* filter) -{ - Q_D(IrcConnection); - IrcCommandFilter* cmdFilter = qobject_cast<IrcCommandFilter*>(filter); - if (cmdFilter) { - d->commandFilters.removeAll(filter); - disconnect(filter, SIGNAL(destroyed(QObject*)), this, SLOT(_irc_filterDestroyed(QObject*))); - } -} - -/*! - \since 3.1 - - Saves the state of the connection. The \a version number is stored as part of the state data. - - To restore the saved state, pass the return value and \a version number to restoreState(). - */ -QByteArray IrcConnection::saveState(int version) const -{ - QVariantMap args; - args.insert("version", version); - args.insert("host", host()); - args.insert("port", port()); - args.insert("userName", userName()); - args.insert("nickName", nickName()); - args.insert("realName", realName()); - args.insert("password", password()); - args.insert("displayName", displayName()); - args.insert("userData", userData()); - args.insert("encoding", encoding()); - args.insert("enabled", isEnabled()); - args.insert("reconnectDelay", reconnectDelay()); - args.insert("secure", isSecure()); - args.insert("saslMechanism", saslMechanism()); - - QByteArray state; - QDataStream out(&state, QIODevice::WriteOnly); - out << args; - return state; -} - -/*! - \since 3.1 - - Restores the \a state of the connection. The \a version number is compared with that stored in \a state. - If they do not match, the connection state is left unchanged, and this function returns \c false; otherwise, - the state is restored, and \c true is returned. - - \sa saveState() - */ -bool IrcConnection::restoreState(const QByteArray& state, int version) -{ - if (isActive()) - return false; - - QVariantMap args; - QDataStream in(state); - in >> args; - if (in.status() != QDataStream::Ok || args.value("version", -1).toInt() != version) - return false; - - setHost(args.value("host", host()).toString()); - setPort(args.value("port", port()).toInt()); - setUserName(args.value("userName", userName()).toString()); - setNickName(args.value("nickName", nickName()).toString()); - setRealName(args.value("realName", realName()).toString()); - setPassword(args.value("password", password()).toString()); - setDisplayName(args.value("displayName").toString()); - setUserData(args.value("userData", userData()).toMap()); - setEncoding(args.value("encoding", encoding()).toByteArray()); - setEnabled(args.value("enabled", isEnabled()).toBool()); - setReconnectDelay(args.value("reconnectDelay", reconnectDelay()).toInt()); - setSecure(args.value("secure", isSecure()).toBool()); - setSaslMechanism(args.value("saslMechanism", saslMechanism()).toString()); - return true; -} - -/*! - Creates a reply command for the CTCP \a request. - - The default implementation handles the following CTCP requests: CLIENTINFO, PING, SOURCE, TIME and VERSION. - - Reimplement this function in order to alter or omit the default replies. - */ -IrcCommand* IrcConnection::createCtcpReply(IrcPrivateMessage* request) const -{ - QString reply; - QString type = request->content().split(" ", QString::SkipEmptyParts).value(0).toUpper(); - if (type == "PING") - reply = request->content(); - else if (type == "TIME") - reply = QLatin1String("TIME ") + QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat); - else if (type == "VERSION") - reply = QLatin1String("VERSION Using libcommuni ") + Irc::version() + QLatin1String(" - http://communi.github.com"); - else if (type == "SOURCE") - reply = QLatin1String("SOURCE http://communi.github.com"); - else if (type == "CLIENTINFO") - reply = QLatin1String("CLIENTINFO PING SOURCE TIME VERSION"); - if (!reply.isEmpty()) - return IrcCommand::createCtcpReply(request->nick(), reply); - return 0; -} - -/*! - \since 3.2 - - This property holds the protocol. - - The previously set protocol is deleted if its parent is \c this. - - \par Access functions: - \li \ref IrcProtocol* <b>protocol</b>() const - \li void <b>setProtocol</b>(\ref IrcProtocol* protocol) - */ -IrcProtocol* IrcConnection::protocol() const -{ - Q_D(const IrcConnection); - return d->protocol; -} - -void IrcConnection::setProtocol(IrcProtocol* proto) -{ - Q_D(IrcConnection); - if (d->protocol != proto) { - if (d->protocol && d->protocol->parent() == this) - delete d->protocol; - d->protocol = proto; - } -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug debug, IrcConnection::Status status) -{ - const int index = IrcConnection::staticMetaObject.indexOfEnumerator("Status"); - QMetaEnum enumerator = IrcConnection::staticMetaObject.enumerator(index); - const char* key = enumerator.valueToKey(status); - debug << (key ? key : "Unknown"); - return debug; -} - -QDebug operator<<(QDebug debug, const IrcConnection* connection) -{ - if (!connection) - return debug << "IrcConnection(0x0) "; - debug.nospace() << connection->metaObject()->className() << '(' << (void*) connection; - if (!connection->displayName().isEmpty()) - debug.nospace() << ", " << qPrintable(connection->displayName()); - debug.nospace() << ')'; - return debug.space(); -} -#endif // QT_NO_DEBUG_STREAM - -#include "moc_ircconnection.cpp" - -IRC_END_NAMESPACE |
