Changeset - 61e7cfaa7f98
[Not reviewed]
0 2 0
Jan Kaluza - 10 years ago 2016-02-28 14:43:59
jkaluza@redhat.com
Libcommuni treat ERR_NICKNAME colision the same way as ERR_NICKNAMEINUSE
2 files changed with 17 insertions and 9 deletions:
0 comments (0 inline, 0 general)
backends/libcommuni/session.cpp
Show inline comments
 
@@ -171,96 +171,97 @@ void MyIrcSession::onIrcUserRemoved(IrcUser *user) {
 

	
 
void MyIrcSession::on_connected() {
 
	m_connected = true;
 
	if (m_suffix.empty()) {
 
		m_np->handleConnected(m_user);
 
	}
 

	
 
	if (getIdentify().find(" ") != std::string::npos) {
 
		std::string to = getIdentify().substr(0, getIdentify().find(" "));
 
		std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
 
		LOG4CXX_INFO(logger, m_user << ": Sending IDENTIFY message to " << to);
 
		sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
 
	}
 
}
 

	
 
void MyIrcSession::addPM(const std::string &name, const std::string &room) {
 
	LOG4CXX_INFO(logger, m_user << ": Adding PM conversation " << name << " " << room);
 
	m_pms[name] = room;
 
}
 

	
 
void MyIrcSession::on_socketError(QAbstractSocket::SocketError error) {
 
	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;
 
	};
 

	
 
	if (!m_suffix.empty()) {
 
		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);
 
		}
 
	}
 
	else {
 
		m_np->handleDisconnected(m_user, 0, reason);
 
		m_np->tryNextServer();
 
	}
 
	LOG4CXX_INFO(logger, m_user << ": Disconnected from IRC network: " << reason);
 
	m_connected = false;
 
}
 

	
 
void MyIrcSession::on_disconnected() {
 
	if (m_suffix.empty()) {
 
		m_np->handleDisconnected(m_user, 0, "");
 
		m_np->tryNextServer();
 
	}
 
	m_connected = false;
 
}
 

	
 
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;
 
	}
 
}
 

	
 
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));
 
}
 

	
 
IrcUser *MyIrcSession::getIrcUser(IrcBuffer *buffer, IrcMessage *message) {
 
	std::string nick = TO_UTF8(message->nick());
 
	return getIrcUser(buffer, nick);
 
}
 

	
 
void MyIrcSession::on_parted(IrcMessage *message) {
 
	// 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
 
@@ -415,149 +416,152 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) {
 
			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;
 
	}
 

	
 
	std::string target = TO_UTF8(m->target().toLower());
 
	std::string nickname = TO_UTF8(m->nick());
 
	sendMessageToFrontend(target, nickname, msg);
 
}
 

	
 
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
 
	QString channel;
 
	QStringList members;
 
	std::string nick;
 

	
 
	IrcNumericMessage *m = (IrcNumericMessage *) message;
 
	QStringList parameters = m->parameters();
 
	switch (m->code()) {
 
		case Irc::RPL_TOPIC:
 
			m_topicData = TO_UTF8(parameters[2]);
 
			break;
 
		case Irc::RPL_TOPICWHOTIME:
 
			nick = TO_UTF8(parameters[2]);
 
			if (nick.find("!") != std::string::npos) {
 
				nick = nick.substr(0, nick.find("!"));
 
			}
 
			if (nick.find("/") != std::string::npos) {
 
				nick = nick.substr(0, nick.find("/"));
 
			}
 
			m_np->handleSubject(m_user, TO_UTF8(parameters[1].toLower()) + m_suffix, m_topicData, nick);
 
			break;
 
		case Irc::ERR_NOSUCHNICK:
 
		case Irc::ERR_NOSUCHSERVER:
 
			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;
 
		case Irc::ERR_ERRONEUSNICKNAME:
 
			m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
 
			break;
 
		case Irc::ERR_NICKNAMEINUSE:
 
		case Irc::ERR_NICKCOLLISION:
 
			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() + "_"));
 
			}
 
			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");
 
// 			}
 
			break;
 
		case Irc::ERR_NICKCOLLISION:
 
			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;
 
// 			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;
 
		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);
 
			}
 
			if (m_suffix.empty()) {
 
				m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Password incorrect");
 
			}
 
		case 321:
 
			m_rooms.clear();
 
			m_names.clear();
 
			break;
 
		case 322:
 
			m_rooms.push_back(TO_UTF8(parameters[1]));
 
			m_names.push_back(TO_UTF8(parameters[1]));
 
			break;
 
		case 323:
 
			m_np->handleRoomList("", m_rooms, m_names);
 
			break;
 
		default:
 
			break;
 
	}
 

	
 
	if (m->code() >= 400 && m->code() < 500) {
 
		LOG4CXX_INFO(logger, m_user << ": Error message received: " << message->toData().data());
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, m_user << ": Numeric message received: " << message->toData().data());
 
	}
 
}
 

	
 
void MyIrcSession::awayTimeout() {
 
	foreach (IrcBuffer *buffer, m_bufferModel->buffers()) {
 
		if (!buffer->isChannel()) {
 
			continue;
 
		}
 

	
 
		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);
 
	}
 
}
 

	
 
void MyIrcSession::on_noticeMessageReceived(IrcMessage *message) {
 
	IrcNoticeMessage *m = (IrcNoticeMessage *) message;
 
	LOG4CXX_INFO(logger, m_user << ": NOTICE " << TO_UTF8(m->content()));
 

	
 
	std::string msg = TO_UTF8(m->content());
 
	std::string target = TO_UTF8(m->target().toLower());
 
	std::string nickname = TO_UTF8(m->nick());
 
	sendMessageToFrontend(target, nickname, msg);
 
}
 

	
 
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);
libtransport/Conversation.cpp
Show inline comments
 
@@ -278,162 +278,166 @@ void Conversation::sendCachedMessages(const Swift::JID &to) {
 
		}
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(*it);
 
	}
 

	
 
	if (m_subject) {
 
		if (to.isValid()) {
 
			m_subject->setTo(to);
 
		}
 
		else {
 
			m_subject->setTo(m_jid.toBare());
 
		}
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
	}
 

	
 
	m_cachedMessages.clear();
 
}
 

	
 
Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash) {
 
	std::string nickname = nick;
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	std::string legacyName = m_legacyName;
 
	if (m_muc) {
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 
	}
 
	presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
	presence->setType(Swift::Presence::Available);
 

	
 
	if (!statusMessage.empty())
 
		presence->setStatus(statusMessage);
 

	
 
	Swift::StatusShow s((Swift::StatusShow::Type) status);
 

	
 
	if (s.getType() == Swift::StatusShow::None) {
 
		presence->setType(Swift::Presence::Unavailable);
 
	}
 

	
 
	presence->setShow(s.getType());
 

	
 
	Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
	if (m_nickname == nickname) {
 
		if (flag & PARTICIPANT_FLAG_CONFLICT) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::Conflict)));
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Generating error presence: PARTICIPANT_FLAG_CONFLICT");
 
			return presence;
 
		}
 
		else if (flag & PARTICIPANT_FLAG_NOT_AUTHORIZED) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::NotAuthorized, Swift::ErrorPayload::Auth, statusMessage)));
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Generating error presence: PARTICIPANT_FLAG_NOT_AUTHORIZED");
 
			return presence;
 
		}
 
		else if (flag & PARTICIPANT_FLAG_ROOM_NOT_FOUD) {
 
			delete p;
 
			presence->setType(Swift::Presence::Error);
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::MUCPayload()));
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::ErrorPayload(Swift::ErrorPayload::ItemNotFound, Swift::ErrorPayload::Cancel, statusMessage)));
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Generating error presence: PARTICIPANT_FLAG_ROOM_NOT_FOUND");
 
			return presence;
 
		}
 
		else {
 
			Swift::MUCUserPayload::StatusCode c;
 
			c.code = 110;
 
			p->addStatusCode(c);
 
			if (m_nicknameChanged) {
 
				Swift::MUCUserPayload::StatusCode c;
 
				c.code = 210;
 
				p->addStatusCode(c);
 
				m_nicknameChanged = false;
 
			}
 
			m_sentInitialPresence = true;
 
		}
 
	}
 

	
 

	
 
	Swift::MUCItem item;
 
	
 
	item.affiliation = Swift::MUCOccupant::Member;
 
	item.role = Swift::MUCOccupant::Participant;
 

	
 
	if (flag & PARTICIPANT_FLAG_MODERATOR) {
 
		item.affiliation = Swift::MUCOccupant::Admin;
 
		item.role = Swift::MUCOccupant::Moderator;
 
	}
 

	
 
	if (!newname.empty()) {
 
		item.nick = newname;
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 303;
 
		p->addStatusCode(c);
 
		presence->setType(Swift::Presence::Unavailable);
 
	}
 

	
 
	if (!iconhash.empty()) {
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate (iconhash)));
 
	}
 
	
 
	p->addItem(item);
 
	presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
	return presence;
 
}
 

	
 

	
 
void Conversation::setNickname(const std::string &nickname) {
 
	if (!nickname.empty() && m_nickname != nickname) {
 
		m_nicknameChanged = true;
 
	}
 
	m_nickname = nickname;
 
}
 

	
 
void Conversation::handleRawPresence(Swift::Presence::ref presence) {
 
	// TODO: Detect nickname change.
 
	m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	m_participants[presence->getFrom().getResource()].presence = presence;
 
}
 

	
 
void Conversation::removeJID(const Swift::JID &jid) {
 
	if (m_muc) {
 
		Swift::Presence::ref presence = generatePresence(m_nickname, 0, Swift::StatusShow::None, "");
 
		presence->setTo(jid);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	}
 
	m_jids.remove(jid);
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash, const std::string &alias) {
 
	Swift::Presence::ref presence = generatePresence(alias.empty() ? nick : alias, flag, status, statusMessage, newname, iconhash);
 

	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
 
		m_participants.erase(nick);
 
	}
 
	else {
 
		m_participants[nick].presence = presence;
 
		m_participants[nick].alias = alias;
 
	}
 

	
 
	BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
		presence->setTo(jid);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	}
 
	if (!newname.empty()) {
 
		handleParticipantChanged(newname, flag, status, statusMessage, "", iconhash);
 
	}
 

	
 
	if (m_sentInitialPresence && !m_sentInitialSubject && m_subject) {
 
		m_sentInitialSubject = true;
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
	}
 

	
 
	// We send error presences only to inform user that he is disconnected
 
	// from the room. This code must be extended in case we start sending error
 
	// presences in other situations.
 
	if (presence->getType() == Swift::Presence::Error) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Leaving the conversation " << m_legacyName << " because of error.");
 
		m_conversationManager->getUser()->leaveRoom(m_legacyName);
 
	}
 
}
 

	
 
}
0 comments (0 inline, 0 general)