2013-02-13 08:06:05 +01:00
|
|
|
/**
|
|
|
|
* XMPP - libpurple transport
|
2011-11-24 19:07:21 +01:00
|
|
|
*
|
2013-02-13 08:06:05 +01:00
|
|
|
* Copyright (C) 2013, Jan Kaluza <hanzz.k@gmail.com>
|
|
|
|
*
|
|
|
|
* 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) any later version.
|
|
|
|
*
|
|
|
|
* 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 02111-1301 USA
|
2011-11-24 19:07:21 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "session.h"
|
|
|
|
#include <QtCore>
|
|
|
|
#include <iostream>
|
|
|
|
#include <IrcCommand>
|
|
|
|
#include <IrcMessage>
|
2016-02-28 11:42:05 +01:00
|
|
|
#include <IrcUser>
|
|
|
|
#include <IrcChannel>
|
2013-02-17 09:41:20 +01:00
|
|
|
#include "backports.h"
|
2011-11-24 19:07:21 +01:00
|
|
|
|
2012-10-04 08:48:14 +02:00
|
|
|
#include "ircnetworkplugin.h"
|
|
|
|
|
2012-03-27 13:40:33 +02:00
|
|
|
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
|
|
|
|
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
|
|
|
|
|
2015-11-18 14:05:57 +01:00
|
|
|
#include "transport/Logging.h"
|
2011-11-24 19:07:21 +01:00
|
|
|
|
2015-11-11 08:01:19 +01:00
|
|
|
DEFINE_LOGGER(logger, "IRCConnection");
|
2011-11-24 19:07:21 +01:00
|
|
|
|
2015-11-11 08:01:19 +01:00
|
|
|
MyIrcSession::MyIrcSession(const std::string &user, IRCNetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcConnection(parent)
|
2011-11-24 19:07:21 +01:00
|
|
|
{
|
2015-12-17 15:08:37 +01:00
|
|
|
m_np = np;
|
|
|
|
m_user = user;
|
|
|
|
m_suffix = suffix;
|
2011-12-09 15:13:58 +01:00
|
|
|
m_connected = false;
|
2011-11-24 19:07:21 +01:00
|
|
|
rooms = 0;
|
2016-02-28 11:42:05 +01:00
|
|
|
m_bufferModel = NULL;
|
2015-12-17 15:08:37 +01:00
|
|
|
|
2011-11-24 19:07:21 +01:00
|
|
|
connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
|
2012-10-04 08:48:14 +02:00
|
|
|
connect(this, SIGNAL(socketError(QAbstractSocket::SocketError)), SLOT(on_socketError(QAbstractSocket::SocketError)));
|
2011-11-24 19:07:21 +01:00
|
|
|
connect(this, SIGNAL(connected()), SLOT(on_connected()));
|
2012-12-04 19:21:59 +01:00
|
|
|
|
|
|
|
m_awayTimer = new QTimer(this);
|
|
|
|
connect(m_awayTimer, SIGNAL(timeout()), this, SLOT(awayTimeout()));
|
2016-02-28 11:42:05 +01:00
|
|
|
m_awayTimer->start(1 * 1000);
|
2012-12-04 19:21:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MyIrcSession::~MyIrcSession() {
|
|
|
|
delete m_awayTimer;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
void MyIrcSession::createBufferModel() {
|
|
|
|
m_bufferModel = new IrcBufferModel(this);
|
|
|
|
connect(m_bufferModel, SIGNAL(added(IrcBuffer*)), this, SLOT(onBufferAdded(IrcBuffer*)));
|
|
|
|
connect(m_bufferModel, SIGNAL(removed(IrcBuffer*)), this, SLOT(onBufferRemoved(IrcBuffer*)));
|
|
|
|
|
|
|
|
// keep the command parser aware of the context
|
|
|
|
// connect(m_bufferModel, SIGNAL(channelsChanged(QStringList)), parser, SLOT(setChannels(QStringList)));
|
|
|
|
|
|
|
|
// create a server buffer for non-targeted messages...
|
|
|
|
IrcBuffer* serverBuffer = m_bufferModel->add(host());
|
|
|
|
// ...and connect it to IrcBufferModel::messageIgnored()
|
|
|
|
// TODO: Make this configurable, so users can show the MOTD and other stuff as in normal
|
|
|
|
// IRC client.
|
|
|
|
connect(m_bufferModel, SIGNAL(messageIgnored(IrcMessage*)), serverBuffer, SLOT(receiveMessage(IrcMessage*)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onBufferAdded(IrcBuffer* buffer) {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": Created IrcBuffer " << TO_UTF8(buffer->name()));
|
|
|
|
|
|
|
|
connect(buffer, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*)));
|
|
|
|
|
|
|
|
if (buffer->isChannel()) {
|
|
|
|
QVariantMap userData;
|
2016-02-28 14:48:24 +01:00
|
|
|
userData["awayCycle"] = boost::lexical_cast<int>(CONFIG_STRING_DEFAULTED(m_np->getConfig(), "service.irc_away_timeout", "60")) + m_userModels.size();
|
2016-02-28 11:42:05 +01:00
|
|
|
userData["awayTick"] = 0;
|
|
|
|
buffer->setUserData(userData);
|
|
|
|
}
|
|
|
|
|
|
|
|
// create a model for buffer users
|
|
|
|
IrcUserModel* userModel = new IrcUserModel(buffer);
|
|
|
|
connect(userModel, SIGNAL(added(IrcUser*)), this, SLOT(onIrcUserAdded(IrcUser*)));
|
|
|
|
connect(userModel, SIGNAL(removed(IrcUser*)), this, SLOT(onIrcUserRemoved(IrcUser*)));
|
|
|
|
m_userModels.insert(buffer, userModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onBufferRemoved(IrcBuffer* buffer) {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": Removed IrcBuffer " << TO_UTF8(buffer->name()));
|
|
|
|
// the buffer specific models and documents are no longer needed
|
|
|
|
delete m_userModels.take(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyIrcSession::hasIrcUser(const std::string &channel_, const std::string &name) {
|
|
|
|
std::string channel = channel_;
|
|
|
|
if (channel[0] != '#') {
|
|
|
|
channel = "#" + channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
IrcBuffer *buffer = m_bufferModel->find(FROM_UTF8(channel));
|
|
|
|
if (!buffer) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": Cannot find IrcBuffer '" << channel << "'");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
IrcUserModel *userModel = m_userModels.value(buffer);
|
|
|
|
if (!userModel) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << channel);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return userModel->contains(FROM_UTF8(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::sendUserToFrontend(IrcUser *user, pbnetwork::StatusType statusType, const std::string &statusMessage, const std::string &newNick) {
|
|
|
|
std::string target = "#" + TO_UTF8(user->channel()->name().toLower()) + m_suffix;
|
|
|
|
int op = user->mode() == "o";
|
|
|
|
|
|
|
|
if (statusType != pbnetwork::STATUS_NONE) {
|
|
|
|
if (user->isAway()) {
|
|
|
|
statusType = pbnetwork::STATUS_AWAY;
|
|
|
|
}
|
|
|
|
if (newNick.empty()) {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": IrcUser connected: " << target << "/" << TO_UTF8(user->name()));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": IrcUser changed nickname: " << target << "/" << TO_UTF8(user->name()) << ", newNick=" << newNick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": IrcUser disconnected: " << target << "/" << TO_UTF8(user->name()));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_np->handleParticipantChanged(m_user, TO_UTF8(user->name()), target, op, statusType, statusMessage, newNick);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onIrcUserChanged(bool dummy) {
|
|
|
|
IrcUser *user = dynamic_cast<IrcUser *>(QObject::sender());
|
|
|
|
if (!user) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": IrcUser " << TO_UTF8(user->name()) << " changed.");
|
|
|
|
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onIrcUserChanged(const QString &) {
|
|
|
|
onIrcUserChanged(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onIrcUserAdded(IrcUser *user) {
|
|
|
|
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
|
|
|
connect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
|
|
|
|
connect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::onIrcUserRemoved(IrcUser *user) {
|
|
|
|
sendUserToFrontend(user, pbnetwork::STATUS_NONE);
|
|
|
|
disconnect(user, SIGNAL(modeChanged(const QString&)), this, SLOT(onIrcUserChanged(const QString&)));
|
|
|
|
disconnect(user, SIGNAL(awayChanged(bool)), this, SLOT(onIrcUserChanged(bool)));
|
|
|
|
}
|
|
|
|
|
2011-11-24 19:07:21 +01:00
|
|
|
void MyIrcSession::on_connected() {
|
2011-12-09 15:13:58 +01:00
|
|
|
m_connected = true;
|
2015-12-17 15:08:37 +01:00
|
|
|
if (m_suffix.empty()) {
|
|
|
|
m_np->handleConnected(m_user);
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (getIdentify().find(" ") != std::string::npos) {
|
|
|
|
std::string to = getIdentify().substr(0, getIdentify().find(" "));
|
|
|
|
std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
|
2015-12-17 15:08:37 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": Sending IDENTIFY message to " << to);
|
2012-03-27 13:40:33 +02:00
|
|
|
sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-17 10:07:56 +01:00
|
|
|
void MyIrcSession::addPM(const std::string &name, const std::string &room) {
|
2015-12-17 15:08:37 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": Adding PM conversation " << name << " " << room);
|
2015-12-17 10:07:56 +01:00
|
|
|
m_pms[name] = room;
|
|
|
|
}
|
|
|
|
|
2012-10-04 08:48:14 +02:00
|
|
|
void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) {
|
2013-02-12 09:30:24 +01:00
|
|
|
std::string reason;
|
|
|
|
switch(error) {
|
|
|
|
case QAbstractSocket::ConnectionRefusedError: reason = "The connection was refused by the peer (or timed out)."; break;
|
|
|
|
case QAbstractSocket::RemoteHostClosedError: reason = "The remote host closed the connection."; break;
|
|
|
|
case QAbstractSocket::HostNotFoundError: reason = "The host address was not found."; break;
|
|
|
|
case QAbstractSocket::SocketAccessError: reason = "The socket operation failed because the application lacked the required privileges."; break;
|
|
|
|
case QAbstractSocket::SocketResourceError: reason = "The local system ran out of resources."; break;
|
|
|
|
case QAbstractSocket::SocketTimeoutError: reason = "The socket operation timed out."; break;
|
|
|
|
case QAbstractSocket::DatagramTooLargeError: reason = "The datagram was larger than the operating system's limit."; break;
|
|
|
|
case QAbstractSocket::NetworkError: reason = "An error occurred with the network."; break;
|
|
|
|
case QAbstractSocket::SslHandshakeFailedError: reason = "The SSL/TLS handshake failed, so the connection was closed"; break;
|
|
|
|
case QAbstractSocket::UnknownSocketError: reason = "An unidentified error occurred."; break;
|
|
|
|
default: reason= "Unknown error."; break;
|
|
|
|
};
|
|
|
|
|
2015-12-17 15:08:37 +01:00
|
|
|
if (!m_suffix.empty()) {
|
2016-02-28 11:42:05 +01:00
|
|
|
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
if (!buffer->isChannel()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_ROOM_NOT_FOUND, pbnetwork::STATUS_NONE, reason);
|
2013-02-12 09:30:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-12-17 15:08:37 +01:00
|
|
|
m_np->handleDisconnected(m_user, 0, reason);
|
|
|
|
m_np->tryNextServer();
|
2013-02-12 09:30:24 +01:00
|
|
|
}
|
2016-02-28 14:43:59 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": Disconnected from IRC network: " << reason);
|
2013-02-12 09:30:24 +01:00
|
|
|
m_connected = false;
|
2012-10-04 08:48:14 +02:00
|
|
|
}
|
|
|
|
|
2011-11-24 19:07:21 +01:00
|
|
|
void MyIrcSession::on_disconnected() {
|
2015-12-17 15:08:37 +01:00
|
|
|
if (m_suffix.empty()) {
|
|
|
|
m_np->handleDisconnected(m_user, 0, "");
|
|
|
|
m_np->tryNextServer();
|
2012-10-04 08:48:14 +02:00
|
|
|
}
|
2011-12-09 15:13:58 +01:00
|
|
|
m_connected = false;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
void MyIrcSession::correctNickname(std::string &nick) {
|
|
|
|
if (nick.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(nick.at(0)) {
|
|
|
|
case '@':
|
|
|
|
case '+':
|
|
|
|
case '~':
|
|
|
|
case '&':
|
|
|
|
case '%':
|
|
|
|
nick.erase(0, 1);
|
|
|
|
break;
|
|
|
|
default: break;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, std::string &nick) {
|
|
|
|
correctNickname(nick);
|
|
|
|
IrcUserModel *userModel = m_userModels.value(buffer);
|
|
|
|
if (!userModel) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return userModel->find(FROM_UTF8(nick));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, IrcMessage *message) {
|
|
|
|
std::string nick = TO_UTF8(message->nick());
|
|
|
|
return getIrcUser(buffer, nick);
|
|
|
|
}
|
2011-11-24 19:07:21 +01:00
|
|
|
|
|
|
|
void MyIrcSession::on_parted(IrcMessage *message) {
|
2016-02-28 11:42:05 +01:00
|
|
|
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
|
|
|
|
// part/quit message. We should use this method instead and write version
|
|
|
|
// of sendUserToFrontend which takes nickname instead of IrcUser just for
|
|
|
|
// part/quit messages.
|
|
|
|
// IrcPartMessage *m = (IrcPartMessage *) message;
|
|
|
|
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
|
|
|
// IrcUser *user = getIrcUser(buffer, message);
|
|
|
|
// if (!user) {
|
|
|
|
// LOG4CXX_ERROR(logger, m_user << ": Part: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::on_quit(IrcMessage *message) {
|
2016-02-28 11:42:05 +01:00
|
|
|
// TODO: We currently use onIrcUserRemoved, but this does not allow sending
|
|
|
|
// part/quit message. We should use this method instead and write version
|
|
|
|
// of sendUserToFrontend which takes nickname instead of IrcUser just for
|
|
|
|
// part/quit messages.
|
|
|
|
// IrcQuitMessage *m = (IrcQuitMessage *) message;
|
|
|
|
// IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
|
|
|
// IrcUser *user = getIrcUser(buffer, message);
|
|
|
|
// if (!user) {
|
|
|
|
// LOG4CXX_ERROR(logger, m_user << ": Quit: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// sendUserToFrontend(user, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::on_nickChanged(IrcMessage *message) {
|
|
|
|
IrcNickMessage *m = (IrcNickMessage *) message;
|
2016-02-28 11:42:05 +01:00
|
|
|
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
|
|
|
IrcUser *user = getIrcUser(buffer, message);
|
|
|
|
if (!user) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": NickChanged: IrcUser " << TO_UTF8(message->nick()) << " not in channel " << TO_UTF8(buffer->name()));
|
2011-11-24 19:07:21 +01:00
|
|
|
return;
|
2013-02-13 07:59:40 +01:00
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->newNick()));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::on_topicChanged(IrcMessage *message) {
|
|
|
|
IrcTopicMessage *m = (IrcTopicMessage *) message;
|
|
|
|
|
2015-11-11 08:01:19 +01:00
|
|
|
std::string nickname = TO_UTF8(m->nick());
|
2012-12-04 18:36:41 +01:00
|
|
|
correctNickname(nickname);
|
2011-11-24 19:07:21 +01:00
|
|
|
|
2015-12-17 15:08:37 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
|
|
|
|
m_np->handleSubject(m_user, TO_UTF8(m->channel().toLower()) + m_suffix, TO_UTF8(m->topic()), nickname);
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2015-12-17 17:42:15 +01:00
|
|
|
void MyIrcSession::sendWhoisCommand(const std::string &channel, const std::string &to) {
|
|
|
|
m_whois[to] = channel;
|
|
|
|
sendCommand(IrcCommand::createWhois(FROM_UTF8(to)));
|
|
|
|
}
|
2011-11-24 19:07:21 +01:00
|
|
|
|
2015-12-17 17:42:15 +01:00
|
|
|
void MyIrcSession::on_whoisMessageReceived(IrcMessage *message) {
|
|
|
|
IrcWhoisMessage *m = (IrcWhoisMessage *) message;
|
|
|
|
std::string nickname = TO_UTF8(m->nick());
|
|
|
|
if (m_whois.find(nickname) == m_whois.end()) {
|
|
|
|
LOG4CXX_INFO(logger, "Whois response received with unexpected nickname " << nickname);
|
|
|
|
return;
|
2012-10-10 13:26:27 +02:00
|
|
|
}
|
2015-12-17 17:42:15 +01:00
|
|
|
|
|
|
|
std::string msg = "";
|
|
|
|
msg += nickname + " is connected to " + TO_UTF8(m->server()) + " (" + TO_UTF8(m->realName()) + ")\n";
|
|
|
|
msg += nickname + " is a user on channels: " + TO_UTF8(m->channels().join(", "));
|
|
|
|
|
|
|
|
sendMessageToFrontend(m_whois[nickname], "whois", msg);
|
|
|
|
m_whois.erase(nickname);
|
|
|
|
}
|
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
void MyIrcSession::on_namesMessageReceived(IrcMessage *message) {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": NAMES received");
|
|
|
|
IrcBuffer *buffer = dynamic_cast<IrcBuffer *>(QObject::sender());
|
|
|
|
IrcUserModel *userModel = m_userModels.value(buffer);
|
|
|
|
if (!userModel) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (IrcUser *user, userModel->users()) {
|
|
|
|
sendUserToFrontend(user, pbnetwork::STATUS_ONLINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG4CXX_INFO(logger, m_user << "Asking /who for channel " << TO_UTF8(buffer->name()));
|
|
|
|
sendCommand(IrcCommand::createWho(buffer->name()));
|
|
|
|
}
|
|
|
|
|
2015-12-17 17:42:15 +01:00
|
|
|
void MyIrcSession::sendMessageToFrontend(const std::string &channel, const std::string &nick, const std::string &msg) {
|
2013-02-17 09:41:20 +01:00
|
|
|
QString html = "";//msg;
|
2015-12-17 17:42:15 +01:00
|
|
|
// CommuniBackport::toPlainText(msg);
|
2013-02-17 09:41:20 +01:00
|
|
|
|
|
|
|
// TODO: Communi produces invalid html now...
|
|
|
|
// if (html == msg) {
|
|
|
|
// html = "";
|
|
|
|
// }
|
|
|
|
// else {
|
|
|
|
// html = IrcUtil::messageToHtml(html);
|
|
|
|
// }
|
2012-10-10 13:26:27 +02:00
|
|
|
|
2015-12-17 17:42:15 +01:00
|
|
|
std::string nickname = nick;
|
|
|
|
if (channel.find("#") == 0) {
|
2012-12-04 18:36:41 +01:00
|
|
|
correctNickname(nickname);
|
2015-12-17 17:42:15 +01:00
|
|
|
m_np->handleMessage(m_user, channel + m_suffix, msg, nickname, TO_UTF8(html));
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
else {
|
2012-12-04 18:36:41 +01:00
|
|
|
correctNickname(nickname);
|
2013-02-11 20:44:28 +01:00
|
|
|
if (m_pms.find(nickname) != m_pms.end()) {
|
2015-12-17 10:07:56 +01:00
|
|
|
std::string room = m_pms[nickname].substr(0, m_pms[nickname].find("/"));
|
|
|
|
room = room.substr(0, room.find("@"));
|
2016-02-28 11:42:05 +01:00
|
|
|
if (hasIrcUser(room, nickname)) {
|
2015-12-17 17:42:15 +01:00
|
|
|
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
|
2013-02-11 20:44:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
2015-12-17 15:08:37 +01:00
|
|
|
nickname = nickname + m_suffix;
|
2013-02-11 20:44:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-02-28 11:42:05 +01:00
|
|
|
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
std::string room = "#" + TO_UTF8(buffer->name());
|
|
|
|
IrcUserModel *userModel = m_userModels.value(buffer);
|
|
|
|
if (!userModel) {
|
|
|
|
LOG4CXX_ERROR(logger, m_user << ": Cannot find UserModel for IrcBuffer " << TO_UTF8(buffer->name()));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!userModel->contains(FROM_UTF8(nickname))) {
|
2015-12-17 15:08:37 +01:00
|
|
|
continue;
|
|
|
|
}
|
2016-02-28 11:42:05 +01:00
|
|
|
|
|
|
|
addPM(nickname, room + "/" + nickname);
|
|
|
|
m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true);
|
2015-12-17 15:08:37 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nickname = nickname + m_suffix;
|
2013-02-11 20:44:28 +01:00
|
|
|
}
|
|
|
|
|
2015-12-17 17:42:15 +01:00
|
|
|
m_np->handleMessage(m_user, nickname, msg, "", TO_UTF8(html));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::on_messageReceived(IrcMessage *message) {
|
|
|
|
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
|
|
|
|
if (m->isRequest()) {
|
|
|
|
QString request = m->content().split(" ", QString::SkipEmptyParts).value(0).toUpper();
|
|
|
|
if (request == "PING" || request == "TIME" || request == "VERSION") {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": " << TO_UTF8(request) << " received and has been answered");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string msg = TO_UTF8(m->content());
|
|
|
|
if (m->isAction()) {
|
|
|
|
msg = "/me " + msg;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
2015-12-17 17:42:15 +01:00
|
|
|
|
|
|
|
std::string target = TO_UTF8(m->target().toLower());
|
|
|
|
std::string nickname = TO_UTF8(m->nick());
|
|
|
|
sendMessageToFrontend(target, nickname, msg);
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
2011-12-09 15:13:58 +01:00
|
|
|
QString channel;
|
|
|
|
QStringList members;
|
2012-11-27 12:51:19 +01:00
|
|
|
std::string nick;
|
2011-12-09 15:13:58 +01:00
|
|
|
|
2011-11-24 19:07:21 +01:00
|
|
|
IrcNumericMessage *m = (IrcNumericMessage *) message;
|
2012-12-13 22:08:34 +01:00
|
|
|
QStringList parameters = m->parameters();
|
2011-11-24 19:07:21 +01:00
|
|
|
switch (m->code()) {
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::RPL_TOPIC:
|
2012-12-13 22:08:34 +01:00
|
|
|
m_topicData = TO_UTF8(parameters[2]);
|
2011-11-24 19:07:21 +01:00
|
|
|
break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::RPL_TOPICWHOTIME:
|
2012-12-13 22:08:34 +01:00
|
|
|
nick = TO_UTF8(parameters[2]);
|
2012-11-27 12:51:19 +01:00
|
|
|
if (nick.find("!") != std::string::npos) {
|
|
|
|
nick = nick.substr(0, nick.find("!"));
|
|
|
|
}
|
|
|
|
if (nick.find("/") != std::string::npos) {
|
|
|
|
nick = nick.substr(0, nick.find("/"));
|
|
|
|
}
|
2015-12-17 15:08:37 +01:00
|
|
|
m_np->handleSubject(m_user, TO_UTF8(parameters[1].toLower()) + m_suffix, m_topicData, nick);
|
2011-11-24 19:07:21 +01:00
|
|
|
break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::ERR_NOSUCHNICK:
|
|
|
|
case Irc::ERR_NOSUCHSERVER:
|
2015-12-17 18:25:26 +01:00
|
|
|
nick = TO_UTF8(parameters[1]);
|
|
|
|
if (m_whois.find(nick) != m_whois.end()) {
|
|
|
|
sendMessageToFrontend(m_whois[nick], "whois", nick + ": No such client");
|
|
|
|
m_whois.erase(nick);
|
|
|
|
}
|
|
|
|
break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::ERR_ERRONEUSNICKNAME:
|
2015-12-17 15:08:37 +01:00
|
|
|
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
|
2011-12-09 15:13:58 +01:00
|
|
|
break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::ERR_NICKNAMEINUSE:
|
2016-02-28 14:43:59 +01:00
|
|
|
case Irc::ERR_NICKCOLLISION:
|
2016-02-28 11:42:05 +01:00
|
|
|
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
if (!buffer->isChannel()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_np->handleRoomNicknameChanged(m_user, TO_UTF8(buffer->title()) + m_suffix, TO_UTF8(nickName() + "_"));
|
|
|
|
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, 0, pbnetwork::STATUS_ONLINE, "", TO_UTF8(nickName() + "_"));
|
2013-01-25 12:47:41 +01:00
|
|
|
}
|
2016-02-26 06:57:02 +01:00
|
|
|
setNickName(nickName() + "_");
|
|
|
|
open();
|
|
|
|
// for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
|
|
|
|
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), it->second->getChannel() + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
|
|
|
|
// }
|
|
|
|
// if (m_suffix.empty()) {
|
|
|
|
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname is already in use");
|
|
|
|
// }
|
2013-01-24 08:35:24 +01:00
|
|
|
break;
|
2016-02-28 14:43:59 +01:00
|
|
|
// foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
// if (!buffer->isChannel()) {
|
|
|
|
// continue;
|
|
|
|
// }
|
|
|
|
// m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT);
|
|
|
|
// }
|
|
|
|
// m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname collision KILL");
|
|
|
|
// break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case Irc::ERR_PASSWDMISMATCH:
|
|
|
|
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
if (!buffer->isChannel()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_np->handleParticipantChanged(m_user, TO_UTF8(nickName()), TO_UTF8(buffer->title()) + m_suffix, pbnetwork::PARTICIPANT_FLAG_NOT_AUTHORIZED);
|
2013-01-24 08:35:24 +01:00
|
|
|
}
|
2015-12-17 15:08:37 +01:00
|
|
|
if (m_suffix.empty()) {
|
|
|
|
m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Password incorrect");
|
2013-01-25 12:47:41 +01:00
|
|
|
}
|
2012-10-18 09:04:20 +02:00
|
|
|
case 321:
|
|
|
|
m_rooms.clear();
|
|
|
|
m_names.clear();
|
|
|
|
break;
|
|
|
|
case 322:
|
2012-12-13 22:08:34 +01:00
|
|
|
m_rooms.push_back(TO_UTF8(parameters[1]));
|
|
|
|
m_names.push_back(TO_UTF8(parameters[1]));
|
2012-10-18 09:04:20 +02:00
|
|
|
break;
|
|
|
|
case 323:
|
2015-12-17 15:08:37 +01:00
|
|
|
m_np->handleRoomList("", m_rooms, m_names);
|
2012-10-18 09:04:20 +02:00
|
|
|
break;
|
2011-12-09 15:13:58 +01:00
|
|
|
default:
|
|
|
|
break;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2013-01-24 08:35:24 +01:00
|
|
|
if (m->code() >= 400 && m->code() < 500) {
|
2015-12-17 15:08:37 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": Error message received: " << message->toData().data());
|
2013-01-24 08:35:24 +01:00
|
|
|
}
|
2016-02-28 14:43:59 +01:00
|
|
|
else {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": Numeric message received: " << message->toData().data());
|
|
|
|
}
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
|
2012-12-04 19:21:59 +01:00
|
|
|
void MyIrcSession::awayTimeout() {
|
2016-02-28 11:42:05 +01:00
|
|
|
foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
|
|
|
|
if (!buffer->isChannel()) {
|
|
|
|
continue;
|
2012-12-04 19:21:59 +01:00
|
|
|
}
|
2016-02-28 11:42:05 +01:00
|
|
|
|
|
|
|
QVariantMap userData = buffer->userData();
|
|
|
|
int awayCycle = userData["awayCycle"].toInt();
|
|
|
|
int awayTick = userData["awayTick"].toInt();
|
|
|
|
|
|
|
|
if (awayTick == awayCycle) {
|
|
|
|
LOG4CXX_INFO(logger, m_user << ": The time has come. Asking /who " << TO_UTF8(buffer->title()) << " again to get current away states.");
|
|
|
|
sendCommand(IrcCommand::createWho(buffer->title()));
|
|
|
|
awayTick = 0;
|
|
|
|
}
|
|
|
|
awayTick++;
|
|
|
|
|
|
|
|
userData["awayCycle"] = awayCycle;
|
|
|
|
userData["awayTick"] = awayTick;
|
|
|
|
buffer->setUserData(userData);
|
2012-12-04 19:21:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-27 14:17:15 +01:00
|
|
|
void MyIrcSession::on_noticeMessageReceived(IrcMessage *message) {
|
|
|
|
IrcNoticeMessage *m = (IrcNoticeMessage *) message;
|
2015-12-17 15:08:37 +01:00
|
|
|
LOG4CXX_INFO(logger, m_user << ": NOTICE " << TO_UTF8(m->content()));
|
2013-02-27 15:47:56 +01:00
|
|
|
|
2016-02-28 11:42:05 +01:00
|
|
|
std::string msg = TO_UTF8(m->content());
|
2013-02-27 15:47:56 +01:00
|
|
|
std::string target = TO_UTF8(m->target().toLower());
|
2016-02-28 11:42:05 +01:00
|
|
|
std::string nickname = TO_UTF8(m->nick());
|
|
|
|
sendMessageToFrontend(target, nickname, msg);
|
2013-02-27 14:17:15 +01:00
|
|
|
}
|
|
|
|
|
2011-11-24 19:07:21 +01:00
|
|
|
void MyIrcSession::onMessageReceived(IrcMessage *message) {
|
|
|
|
switch (message->type()) {
|
|
|
|
case IrcMessage::Part:
|
|
|
|
on_parted(message);
|
|
|
|
break;
|
|
|
|
case IrcMessage::Quit:
|
|
|
|
on_quit(message);
|
|
|
|
break;
|
|
|
|
case IrcMessage::Nick:
|
|
|
|
on_nickChanged(message);
|
|
|
|
break;
|
|
|
|
case IrcMessage::Topic:
|
|
|
|
on_topicChanged(message);
|
|
|
|
break;
|
|
|
|
case IrcMessage::Private:
|
|
|
|
on_messageReceived(message);
|
|
|
|
break;
|
|
|
|
case IrcMessage::Numeric:
|
|
|
|
on_numericMessageReceived(message);
|
|
|
|
break;
|
2013-02-27 14:17:15 +01:00
|
|
|
case IrcMessage::Notice:
|
|
|
|
on_noticeMessageReceived(message);
|
|
|
|
break;
|
2015-12-17 17:42:15 +01:00
|
|
|
case IrcMessage::Whois:
|
|
|
|
on_whoisMessageReceived(message);
|
|
|
|
break;
|
2016-02-28 11:42:05 +01:00
|
|
|
case IrcMessage::Names:
|
|
|
|
on_namesMessageReceived(message);
|
|
|
|
break;
|
2011-12-09 16:31:48 +01:00
|
|
|
default:break;
|
2011-11-24 19:07:21 +01:00
|
|
|
}
|
|
|
|
}
|