summaryrefslogtreecommitdiffstats
path: root/libcommuni/src/core/ircprotocol.cpp
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2015-09-09 19:00:56 +0200
committerMarkus Mittendrein <git@maxmitti.tk>2015-09-09 19:02:23 +0200
commit8a6d4b06f2291c363f3dea17837ed20893852453 (patch)
treec091375499e35eaa1810586454e0834c06e6c9b2 /libcommuni/src/core/ircprotocol.cpp
parentf554a27046f203e56a07baaf214d90834942e3f5 (diff)
downloadmanager-8a6d4b06f2291c363f3dea17837ed20893852453.tar.gz
manager-8a6d4b06f2291c363f3dea17837ed20893852453.zip
Cleanup repo with some directories
Diffstat (limited to 'libcommuni/src/core/ircprotocol.cpp')
-rw-r--r--libcommuni/src/core/ircprotocol.cpp480
1 files changed, 0 insertions, 480 deletions
diff --git a/libcommuni/src/core/ircprotocol.cpp b/libcommuni/src/core/ircprotocol.cpp
deleted file mode 100644
index 9d42126..0000000
--- a/libcommuni/src/core/ircprotocol.cpp
+++ /dev/null
@@ -1,480 +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 "ircprotocol.h"
-#include "ircconnection_p.h"
-#include "ircmessagebuilder_p.h"
-#include "ircnetwork_p.h"
-#include "ircconnection.h"
-#include "ircmessage.h"
-#include "irccommand.h"
-#include "irc.h"
-#include <QDebug>
-
-IRC_BEGIN_NAMESPACE
-
-/*!
- \file ircprotocol.h
- \brief \#include &lt;IrcProtocol&gt;
- */
-
-/*!
- \since 3.2
- \class IrcProtocol ircprotocol.h IrcProtocol
- \ingroup core
- \brief Implements the IRC protocol and provides means for implementing support for custom protocols.
-
- \sa IrcConnection::protocol
- */
-
-#ifndef IRC_DOXYGEN
-class IrcProtocolPrivate
-{
- Q_DECLARE_PUBLIC(IrcProtocol)
-
-public:
- IrcProtocolPrivate();
-
- void authenticate(bool secure);
-
- void readLines(const QByteArray& delimiter);
- void processLine(const QByteArray& line);
-
- void handleNumericMessage(IrcNumericMessage* msg);
- void handlePrivateMessage(IrcPrivateMessage* msg);
- void handleCapabilityMessage(IrcCapabilityMessage* msg);
-
- void _irc_pauseHandshake();
- void _irc_resumeHandshake();
-
- IrcProtocol* q_ptr;
- IrcConnection* connection;
- IrcMessageBuilder* builder;
- QHash<QString, QString> info;
- QByteArray buffer;
- bool resumed;
- bool authed;
-};
-
-IrcProtocolPrivate::IrcProtocolPrivate() : q_ptr(0), connection(0), builder(0), resumed(false), authed(false)
-{
-}
-
-void IrcProtocolPrivate::authenticate(bool secure)
-{
- const QString password = connection->password();
- if (!password.isEmpty()) {
- if (secure) {
- const QByteArray userName = connection->userName().toUtf8();
- const QByteArray data = userName + '\0' + userName + '\0' + password.toUtf8();
- authed = connection->sendData("AUTHENTICATE " + data.toBase64());
- } else {
- authed = connection->sendRaw(QString("PASS %1").arg(password));
- }
- }
-}
-
-void IrcProtocolPrivate::readLines(const QByteArray& delimiter)
-{
- int i = -1;
- while ((i = buffer.indexOf(delimiter)) != -1) {
- QByteArray line = buffer.left(i).trimmed();
- buffer = buffer.mid(i + delimiter.length());
- if (!line.isEmpty())
- processLine(line);
- }
-}
-
-void IrcProtocolPrivate::processLine(const QByteArray& line)
-{
- Q_Q(IrcProtocol);
- static bool dbg = qgetenv("IRC_DEBUG").toInt();
- if (dbg) qDebug() << line;
-
- if (line.startsWith("AUTHENTICATE") && !connection->saslMechanism().isEmpty()) {
- const QList<QByteArray> args = line.split(' ');
- if (args.count() == 2 && args.at(1) == "+")
- authenticate(true);
- if (!connection->isConnected())
- QMetaObject::invokeMethod(q, "_irc_resumeHandshake", Qt::QueuedConnection);
- return;
- }
-
- IrcMessage* msg = IrcMessage::fromData(line, connection);
- if (msg) {
- msg->setEncoding(connection->encoding());
-
- switch (msg->type()) {
- case IrcMessage::Capability:
- handleCapabilityMessage(static_cast<IrcCapabilityMessage*>(msg));
- break;
- case IrcMessage::Nick:
- if (msg->flags() & IrcMessage::Own)
- q->setNickName(static_cast<IrcNickMessage*>(msg)->newNick());
- break;
- case IrcMessage::Numeric:
- handleNumericMessage(static_cast<IrcNumericMessage*>(msg));
- break;
- case IrcMessage::Ping:
- connection->sendRaw("PONG " + static_cast<IrcPingMessage*>(msg)->argument());
- break;
- case IrcMessage::Private:
- handlePrivateMessage(static_cast<IrcPrivateMessage*>(msg));
- break;
- default:
- break;
- }
- q->receiveMessage(msg);
- }
-}
-
-void IrcProtocolPrivate::handleNumericMessage(IrcNumericMessage* msg)
-{
- Q_Q(IrcProtocol);
- switch (msg->code()) {
- case Irc::RPL_WELCOME:
- q->setNickName(msg->parameters().value(0));
- q->setStatus(IrcConnection::Connected);
- break;
- case Irc::RPL_ISUPPORT: {
- foreach (const QString& param, msg->parameters().mid(1)) {
- QStringList keyValue = param.split("=", QString::SkipEmptyParts);
- info.insert(keyValue.value(0), keyValue.value(1));
- }
- break;
- }
- case Irc::ERR_NOMOTD:
- case Irc::RPL_MOTDSTART:
- q->setInfo(info);
- break;
- case Irc::ERR_NICKNAMEINUSE:
- case Irc::ERR_NICKCOLLISION: {
- QString alternate = connection->nickName();
- emit connection->nickNameReserved(&alternate);
- if (!alternate.isEmpty() && alternate != connection->nickName()) {
- connection->setNickName(alternate);
- } else {
- emit connection->nickNameRequired(msg->parameters().value(1), &alternate);
- if (!alternate.isEmpty() && alternate != connection->nickName())
- connection->setNickName(alternate);
- }
- break;
- }
- case Irc::ERR_BADCHANNELKEY: {
- QString key;
- QString channel = msg->parameters().value(1);
- emit connection->channelKeyRequired(channel, &key);
- if (!key.isEmpty())
- connection->sendCommand(IrcCommand::createJoin(channel, key));
- break;
- }
- default:
- break;
- }
-}
-
-void IrcProtocolPrivate::handlePrivateMessage(IrcPrivateMessage* msg)
-{
- if (msg->isRequest()) {
- IrcCommand* reply = IrcConnectionPrivate::get(connection)->createCtcpReply(msg);
- if (reply)
- connection->sendCommand(reply);
- }
-}
-
-static void handleCapability(QSet<QString>* caps, const QString& cap)
-{
- Q_ASSERT(caps);
- // sticky modifier (once the cap is enabled, it cannot be disabled)
- QLatin1Char stickyMod('=');
- // ack modifier (the cap must be acked by the client to fully enable/disable)
- QLatin1Char ackMod('~');
- // disable modifier (the cap should be disabled)
- QLatin1Char disMod('-');
-
- QString name = cap;
- while (name.startsWith(stickyMod) || name.startsWith(ackMod))
- name.remove(0, 1);
-
- if (name.startsWith(disMod))
- caps->remove(name.mid(1));
- else
- caps->insert(name);
-}
-
-void IrcProtocolPrivate::handleCapabilityMessage(IrcCapabilityMessage* msg)
-{
- Q_Q(IrcProtocol);
- const bool connected = connection->isConnected();
- const QString subCommand = msg->subCommand();
- if (subCommand == "LS") {
- QSet<QString> availableCaps = connection->network()->availableCapabilities().toSet();
- foreach (const QString& cap, msg->capabilities())
- handleCapability(&availableCaps, cap);
- q->setAvailableCapabilities(availableCaps);
-
- if (!connected) {
- QMetaObject::invokeMethod(connection->network(), "requestingCapabilities");
- QStringList requestedCaps = connection->network()->requestedCapabilities();
- const QStringList params = msg->parameters();
- if (params.value(params.count() - 1) != QLatin1String("*")) {
- if (!connection->saslMechanism().isEmpty() && availableCaps.contains(QLatin1String("sasl")))
- requestedCaps += QLatin1String("sasl");
- }
- if (!requestedCaps.isEmpty())
- connection->sendRaw("CAP REQ :" + requestedCaps.join(" "));
- else
- QMetaObject::invokeMethod(q, "_irc_resumeHandshake", Qt::QueuedConnection);
- }
- } else if (subCommand == "ACK" || subCommand == "NAK") {
- bool auth = false;
- if (subCommand == "ACK") {
- QSet<QString> activeCaps = connection->network()->activeCapabilities().toSet();
- foreach (const QString& cap, msg->capabilities()) {
- handleCapability(&activeCaps, cap);
- if (cap == "sasl" && !connection->saslMechanism().isEmpty() && !connection->password().isEmpty())
- auth = connection->sendRaw("AUTHENTICATE " + connection->saslMechanism());
- }
- q->setActiveCapabilities(activeCaps);
- }
-
- if (!connected && !auth)
- QMetaObject::invokeMethod(q, "_irc_resumeHandshake", Qt::QueuedConnection);
- }
-}
-
-void IrcProtocolPrivate::_irc_pauseHandshake()
-{
- // Send CAP LS first; if the server understands it this will
- // temporarily pause the handshake until CAP END is sent, so we
- // know whether the server supports the CAP extension.
- connection->sendData("CAP LS");
- resumed = false;
- authed = false;
-}
-
-void IrcProtocolPrivate::_irc_resumeHandshake()
-{
- if (!resumed && !connection->isConnected()) {
- if (!authed && !connection->saslMechanism().isEmpty() && !connection->password().isEmpty())
- authenticate(false);
- connection->sendData("CAP END");
- }
- resumed = true;
-}
-#endif // IRC_DOXYGEN
-
-/*!
- Constructs a new IRC protocol for \a connection.
- */
-IrcProtocol::IrcProtocol(IrcConnection* connection) : QObject(connection), d_ptr(new IrcProtocolPrivate)
-{
- Q_D(IrcProtocol);
- d->q_ptr = this;
- d->connection = connection;
- d->builder = new IrcMessageBuilder(connection);
- connect(d->builder, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(receiveMessage(IrcMessage*)));
-}
-
-/*!
- Destructs the IRC protocol.
- */
-IrcProtocol::~IrcProtocol()
-{
- Q_D(IrcProtocol);
- delete d->builder;
-}
-
-/*!
- This property holds the connection.
-
- \par Access function:
- \li \ref IrcConnection* <b>connection</b>() const
- */
-IrcConnection* IrcProtocol::connection() const
-{
- Q_D(const IrcProtocol);
- return d->connection;
-}
-
-/*!
- This property holds the socket.
-
- \par Access functions:
- \li \ref QAbstractSocket* <b>socket</b>() const
- */
-QAbstractSocket* IrcProtocol::socket() const
-{
- Q_D(const IrcProtocol);
- return d->connection->socket();
-}
-
-/*!
- This method is called when the connection has been established.
-
- The default implementation sends the \c NICK, \c USER and \c PASSWORD commands as defined in
- <a href="http://tools.ietf.org/html/rfc1459">RFC 1459</a>.
-
- Furthermore, it sends a <tt>CAP LS</tt> command as specified in
- <a href="http://tools.ietf.org/html/draft-mitchell-irc-capabilities-01">IRC Client Capabilities Extension</a>.
- */
-void IrcProtocol::open()
-{
- Q_D(IrcProtocol);
- d->_irc_pauseHandshake();
-
- if (d->connection->saslMechanism().isEmpty() && !d->connection->password().isEmpty())
- d->authenticate(false);
-
- d->connection->sendRaw(QString("NICK %1").arg(d->connection->nickName()));
- d->connection->sendRaw(QString("USER %1 hostname servername :%2").arg(d->connection->userName(), d->connection->realName()));
-}
-
-/*!
- This method is called when the connection has been lost.
- */
-void IrcProtocol::close()
-{
-}
-
-/*!
- This method is called when the \ref socket has new data available for read.
-
- The default implementation reads lines as specified in
- <a href="http://tools.ietf.org/html/rfc1459">RFC 1459</a>.
-
- \sa socket
- */
-void IrcProtocol::read()
-{
- Q_D(IrcProtocol);
- d->buffer += socket()->readAll();
- // try reading RFC compliant message lines first
- d->readLines("\r\n");
- // fall back to RFC incompliant lines...
- d->readLines("\n");
-}
-
-/*!
- This method is called when raw \a data should be written to the \ref socket.
-
- The default implementation writes the data and appends \c "\r\n" as specified in
- <a href="http://tools.ietf.org/html/rfc1459">RFC 1459</a>.
-
- \sa socket
- */
-bool IrcProtocol::write(const QByteArray& data)
-{
- return socket()->write(data + QByteArray("\r\n")) != -1;
-}
-
-/*!
- This method should be called by the protocol implementation
- to make the underlying IRC connection receive a \a message.
-
- \sa IrcConnection::messageReceived()
- */
-void IrcProtocol::receiveMessage(IrcMessage* message)
-{
- Q_D(IrcProtocol);
- IrcConnectionPrivate* priv = IrcConnectionPrivate::get(d->connection);
- priv->receiveMessage(message);
- if (message->type() == IrcMessage::Numeric)
- d->builder->processMessage(static_cast<IrcNumericMessage*>(message));
-}
-
-/*!
- This method should be called by the protocol implementation to
- notify the underlying IRC connection about a nick \a name change.
-
- \sa IrcConnection::nickName
- */
-void IrcProtocol::setNickName(const QString& name)
-{
- Q_D(IrcProtocol);
- IrcConnectionPrivate* priv = IrcConnectionPrivate::get(d->connection);
- priv->setNick(name);
-}
-
-/*!
- This method should be called by the protocol implementation
- to notify the underlying IRC connection about a \a status change.
-
- \sa IrcConnection::status
- */
-void IrcProtocol::setStatus(IrcConnection::Status status)
-{
- Q_D(IrcProtocol);
- IrcConnectionPrivate* priv = IrcConnectionPrivate::get(d->connection);
- priv->setStatus(status);
-}
-
-/*!
- This method should be called by the protocol implementation
- to initialize the underlying IRC network connection \a info.
-
- \sa IrcNetwork::initialized
- */
-void IrcProtocol::setInfo(const QHash<QString, QString>& info)
-{
- Q_D(IrcProtocol);
- if (!info.isEmpty()) {
- IrcConnectionPrivate* priv = IrcConnectionPrivate::get(d->connection);
- priv->setInfo(info);
- }
-}
-
-/*!
- This method should be called by the protocol implementation to notify
- the underlying IRC network about a change in available \a capabilities.
-
- \sa IrcNetwork::availableCapabilities
- */
-void IrcProtocol::setAvailableCapabilities(const QSet<QString>& capabilities)
-{
- Q_D(IrcProtocol);
- IrcNetworkPrivate* priv = IrcNetworkPrivate::get(d->connection->network());
- priv->setAvailableCapabilities(capabilities);
-}
-
-/*!
- This method should be called by the protocol implementation to notify
- the underlying IRC network about a change in active \a capabilities.
-
- \sa IrcNetwork::activeCapabilities
- */
-void IrcProtocol::setActiveCapabilities(const QSet<QString>& capabilities)
-{
- Q_D(IrcProtocol);
- IrcNetworkPrivate* priv = IrcNetworkPrivate::get(d->connection->network());
- priv->setActiveCapabilities(capabilities);
-}
-
-#include "moc_ircprotocol.cpp"
-
-IRC_END_NAMESPACE