#include "Swiften/Controllers/ChatControllerBase.h" #include #include #include "Swiften/Client/StanzaChannel.h" #include "Swiften/Base/foreach.h" #include "Swiften/Controllers/ChatWindow.h" #include "Swiften/Controllers/ChatWindowFactory.h" #include "Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h" namespace Swift { ChatControllerBase::ChatControllerBase(StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle) : stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle) { chatWindow_ = chatWindowFactory_->createChatWindow(toJID); chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1)); presenceOracle_->onPresenceChange.connect(boost::bind(&ChatControllerBase::handlePresenceChange, this, _1, _2)); } ChatControllerBase::~ChatControllerBase() { delete chatWindow_; } void ChatControllerBase::setAvailableServerFeatures(boost::shared_ptr info) { if (info->hasFeature(DiscoInfo::SecurityLabels)) { chatWindow_->setSecurityLabelsEnabled(true); chatWindow_->setSecurityLabelsError(); GetSecurityLabelsCatalogRequest* request = new GetSecurityLabelsCatalogRequest(JID(toJID_.toBare()), iqRouter_, Request::AutoDeleteAfterResponse); request->onResponse.connect(boost::bind(&ChatControllerBase::handleSecurityLabelsCatalogResponse, this, _1, _2)); request->send(); labelsEnabled_ = true; } else { chatWindow_->setSecurityLabelsEnabled(false); labelsEnabled_ = false; } } String ChatControllerBase::getStatusChangeString(boost::shared_ptr presence) { String nick = senderDisplayNameFromMessage(presence->getFrom()); if (presence->getType() == Presence::Unavailable) { return nick + " has gone offline."; } else if (presence->getType() == Presence::Available) { StatusShow::Type show = presence->getShow(); if (show == StatusShow::Online || show == StatusShow::FFC) { return nick + " has become available."; } else if (show == StatusShow::Away || show == StatusShow::XA) { return nick + " has gone away."; } else if (show == StatusShow::DND) { return nick + " is now busy."; } } return ""; } void ChatControllerBase::handlePresenceChange(boost::shared_ptr newPresence, boost::shared_ptr previousPresence) { if (!(toJID_.isBare() && newPresence->getFrom().equals(toJID_, JID::WithoutResource)) && newPresence->getFrom() != toJID_) { return; } String newStatusChangeString = getStatusChangeString(newPresence); if (previousPresence.get() == NULL || newStatusChangeString != getStatusChangeString(previousPresence)) { chatWindow_->addSystemMessage(newStatusChangeString); } } void ChatControllerBase::handleAllMessagesRead() { foreach (boost::shared_ptr messageEvent, unreadMessages_) { messageEvent->read(); } unreadMessages_.clear(); chatWindow_->setUnreadMessageCount(0); } void ChatControllerBase::handleSendMessageRequest(const String &body) { if (body.isEmpty()) { return; } boost::shared_ptr message(new Message()); message->setTo(toJID_); message->setType(Swift::Message::Chat); message->setBody(body); boost::optional label; if (labelsEnabled_) { message->addPayload(boost::shared_ptr(new SecurityLabel(chatWindow_->getSelectedSecurityLabel()))); label = boost::optional(chatWindow_->getSelectedSecurityLabel()); } preSendMessageRequest(message); stanzaChannel_->sendMessage(message); postSendMessage(message->getBody()); } void ChatControllerBase::handleSecurityLabelsCatalogResponse(boost::shared_ptr catalog, const boost::optional& error) { if (!error) { if (catalog->getLabels().size() == 0) { chatWindow_->setSecurityLabelsEnabled(false); labelsEnabled_ = false; } else { chatWindow_->setAvailableSecurityLabels(catalog->getLabels()); chatWindow_->setSecurityLabelsEnabled(true); } } else { chatWindow_->setSecurityLabelsError(); } } void ChatControllerBase::showChatWindow() { chatWindow_->show(); } String ChatControllerBase::senderDisplayNameFromMessage(JID from) { return from; } void ChatControllerBase::handleIncomingMessage(boost::shared_ptr messageEvent) { unreadMessages_.push_back(messageEvent); chatWindow_->setUnreadMessageCount(unreadMessages_.size()); boost::shared_ptr message = messageEvent->getStanza(); preHandleIncomingMessage(message); String body = message->getBody(); if (message->isError()) { String errorMessage = getErrorMessage(message->getPayload()); chatWindow_->addErrorMessage(errorMessage); } else { showChatWindow(); boost::shared_ptr label = message->getPayload(); boost::optional maybeLabel = label ? boost::optional(*label) : boost::optional(); JID from = message->getFrom(); chatWindow_->addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), maybeLabel); } } String ChatControllerBase::getErrorMessage(boost::shared_ptr error) { String defaultMessage = "Error sending message"; if (!error->getText().isEmpty()) { return error->getText(); } else { switch (error->getCondition()) { case Error::BadRequest: return defaultMessage; break; case Error::Conflict: return defaultMessage; break; case Error::FeatureNotImplemented: return defaultMessage; break; case Error::Forbidden: return defaultMessage; break; case Error::Gone: return "Recipient can no longer be contacted"; break; case Error::InternalServerError: return "Internal server error"; break; case Error::ItemNotFound: return defaultMessage; break; case Error::JIDMalformed: return defaultMessage; break; case Error::NotAcceptable: return "Message was rejected"; break; case Error::NotAllowed: return defaultMessage; break; case Error::NotAuthorized: return defaultMessage; break; case Error::PaymentRequired: return defaultMessage; break; case Error::RecipientUnavailable: return "Recipient is unavailable."; break; case Error::Redirect: return defaultMessage; break; case Error::RegistrationRequired: return defaultMessage; break; case Error::RemoteServerNotFound: return "Recipient's server not found."; break; case Error::RemoteServerTimeout: return defaultMessage; break; case Error::ResourceConstraint: return defaultMessage; break; case Error::ServiceUnavailable: return defaultMessage; break; case Error::SubscriptionRequired: return defaultMessage; break; case Error::UndefinedCondition: return defaultMessage; break; case Error::UnexpectedRequest: return defaultMessage; break; } } return defaultMessage; } }