summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp6
-rw-r--r--Swift/Controllers/Chat/ChatController.h1
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h1
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp63
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h3
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp110
-rw-r--r--Swift/Controllers/MainController.cpp22
-rw-r--r--Swift/Controllers/MainController.h2
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h24
-rw-r--r--Swiften/Elements/DiscoInfo.cpp1
-rw-r--r--Swiften/Elements/DiscoInfo.h1
-rw-r--r--Swiften/Elements/Forwarded.h6
-rw-r--r--Swiften/Queries/Requests/EnableCarbonsRequest.h28
13 files changed, 241 insertions, 27 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index b8bf4c3..e36728a 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -312,6 +312,12 @@ void ChatController::handleUIEvent(std::shared_ptr<UIEvent> event) {
}
}
+void ChatController::handleIncomingOwnMessage(std::shared_ptr<Message> message) {
+ if (!message->getBody().get_value_or("").empty()) {
+ postSendMessage(message->getBody().get_value_or(""), message);
+ handleStanzaAcked(message);
+ }
+}
void ChatController::postSendMessage(const std::string& body, std::shared_ptr<Stanza> sentStanza) {
std::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 206ee71..99f8e23 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -40,6 +40,7 @@ namespace Swift {
virtual void handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state);
virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/) SWIFTEN_OVERRIDE;
virtual ChatWindow* detachChatWindow() SWIFTEN_OVERRIDE;
+ virtual void handleIncomingOwnMessage(std::shared_ptr<Message> message) SWIFTEN_OVERRIDE;
protected:
virtual void cancelReplaces() SWIFTEN_OVERRIDE;
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index b97d7af..4255c19 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -54,6 +54,7 @@ namespace Swift {
void activateChatWindow();
bool hasOpenWindow() const;
virtual void setAvailableServerFeatures(std::shared_ptr<DiscoInfo> info);
+ virtual void handleIncomingOwnMessage(std::shared_ptr<Message> /*message*/) {}
void handleIncomingMessage(std::shared_ptr<MessageEvent> message);
std::string addMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time);
void replaceMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& id, const boost::posix_time::ptime& time);
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index e8b85c4..f3bb8d3 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -24,9 +24,12 @@
#include <Swiften/Client/NickResolver.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Disco/DiscoServiceWalker.h>
+#include <Swiften/Elements/CarbonsReceived.h>
+#include <Swiften/Elements/CarbonsSent.h>
#include <Swiften/Elements/ChatState.h>
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
+#include <Swiften/Elements/Forwarded.h>
#include <Swiften/Elements/MUCInvitationPayload.h>
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/MUC/MUCBookmarkManager.h>
@@ -333,7 +336,7 @@ void ChatsManager::loadRecents() {
return;
}
- foreach(ChatListWindow::Chat chat, recentChats) {
+ for (auto chat : recentChats) {
chat.statusType = StatusShow::None;
chat = updateChatStatusAndAvatarHelper(chat);
prependRecent(chat);
@@ -865,13 +868,49 @@ void ChatsManager::handleUserNicknameChanged(MUCController* mucController, const
}
}
-void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> message) {
- JID jid = message->getFrom();
+bool ChatsManager::messageCausesSessionBinding(std::shared_ptr<Message> message) {
+ bool causesRebind = false;
+ ChatState::ref chatState = message->getPayload<ChatState>();
+ if (!message->getBody().get_value_or("").empty() || (chatState && chatState->getChatState() == ChatState::Composing)) {
+ causesRebind = true;
+ }
+ return causesRebind;
+}
+
+void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> incomingMessage) {
+ std::shared_ptr<Message> message = incomingMessage;
+ if (message->getFrom().toBare() == jid_.toBare()) {
+ CarbonsReceived::ref carbonsReceived;
+ CarbonsSent::ref carbonsSent;
+ Forwarded::ref forwarded;
+ Message::ref forwardedMessage;
+ if ((carbonsReceived = incomingMessage->getPayload<CarbonsReceived>()) &&
+ (forwarded = carbonsReceived->getForwarded()) &&
+ (forwardedMessage = std::dynamic_pointer_cast<Message>(forwarded->getStanza()))) {
+ message = forwardedMessage;
+ }
+ else if ((carbonsSent = incomingMessage->getPayload<CarbonsSent>()) &&
+ (forwarded = carbonsSent->getForwarded()) &&
+ (forwardedMessage = std::dynamic_pointer_cast<Message>(forwarded->getStanza()))) {
+ JID toJID = forwardedMessage->getTo();
+
+ ChatController* controller = getChatControllerOrCreate(toJID);
+ if (controller) {
+ controller->handleIncomingOwnMessage(forwardedMessage);
+ }
+ else {
+ SWIFT_LOG(error) << "Carbons message ignored." << std::endl;
+ }
+ return;
+ }
+ }
+ JID fromJID = message->getFrom();
+
std::shared_ptr<MessageEvent> event(new MessageEvent(message));
bool isInvite = !!message->getPayload<MUCInvitationPayload>();
bool isMediatedInvite = (message->getPayload<MUCUserPayload>() && message->getPayload<MUCUserPayload>()->getInvite());
if (isMediatedInvite) {
- jid = (*message->getPayload<MUCUserPayload>()->getInvite()).from;
+ fromJID = (*message->getPayload<MUCUserPayload>()->getInvite()).from;
}
if (!event->isReadable() && !message->getPayload<ChatState>() && !message->getPayload<DeliveryReceipt>() && !message->getPayload<DeliveryReceiptRequest>() && !isInvite && !isMediatedInvite && !message->hasSubject()) {
return;
@@ -879,7 +918,7 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> message) {
// Try to deliver it to a MUC
if (message->getType() == Message::Groupchat || message->getType() == Message::Error /*|| (isInvite && message->getType() == Message::Normal)*/) {
- std::map<JID, MUCController*>::iterator i = mucControllers_.find(jid.toBare());
+ std::map<JID, MUCController*>::iterator i = mucControllers_.find(fromJID.toBare());
if (i != mucControllers_.end()) {
i->second->handleIncomingMessage(event);
return;
@@ -895,10 +934,10 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> message) {
if (invite && autoAcceptMUCInviteDecider_->isAutoAcceptedInvite(message->getFrom(), invite)) {
if (invite->getIsContinuation()) {
// check for existing chat controller for the from JID
- ChatController* controller = getChatControllerIfExists(jid);
+ ChatController* controller = getChatControllerIfExists(fromJID);
if (controller) {
ChatWindow* window = controller->detachChatWindow();
- chatControllers_.erase(jid);
+ chatControllers_.erase(fromJID);
delete controller;
handleJoinMUCRequest(invite->getJID(), boost::optional<std::string>(), boost::optional<std::string>(), false, false, true, window);
return;
@@ -914,18 +953,12 @@ void ChatsManager::handleIncomingMessage(std::shared_ptr<Message> message) {
/* Only route such messages if a window exists, don't open new windows for them.*/
// Do not bind a controller to a full JID, for delivery receipts or chat state notifications.
- bool bindControllerToJID = false;
- ChatState::ref chatState = message->getPayload<ChatState>();
- if (!message->getBody().get_value_or("").empty() || (chatState && chatState->getChatState() == ChatState::Composing)) {
- bindControllerToJID = true;
- }
-
- ChatController* controller = getChatControllerIfExists(jid, bindControllerToJID);
+ ChatController* controller = getChatControllerIfExists(fromJID, messageCausesSessionBinding(message));
if (controller) {
controller->handleIncomingMessage(event);
}
} else {
- getChatControllerOrCreate(jid)->handleIncomingMessage(event);
+ getChatControllerOrCreate(fromJID)->handleIncomingMessage(event);
}
}
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index da85949..593624d 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -67,7 +67,7 @@ namespace Swift {
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
void setServerDiscoInfo(std::shared_ptr<DiscoInfo> info);
- void handleIncomingMessage(std::shared_ptr<Message> message);
+ void handleIncomingMessage(std::shared_ptr<Message> incomingMessage);
std::vector<ChatListWindow::Chat> getRecentChats() const;
virtual std::vector<Contact::ref> getContacts(bool withMUCNicks);
@@ -105,6 +105,7 @@ namespace Swift {
void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);
void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);
boost::optional<ChatListWindow::Chat> removeExistingChat(const ChatListWindow::Chat& chat);
+ bool messageCausesSessionBinding(std::shared_ptr<Message> message);
void cleanupPrivateMessageRecents();
void appendRecent(const ChatListWindow::Chat& chat);
void prependRecent(const ChatListWindow::Chat& chat);
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index f3908d6..e45bcae 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -23,8 +23,11 @@
#include <Swiften/Crypto/CryptoProvider.h>
#include <Swiften/Crypto/PlatformCryptoProvider.h>
#include <Swiften/Disco/DummyEntityCapsProvider.h>
+#include <Swiften/Elements/CarbonsReceived.h>
+#include <Swiften/Elements/CarbonsSent.h>
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
+#include <Swiften/Elements/Forwarded.h>
#include <Swiften/Elements/MUCInvitationPayload.h>
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h>
@@ -80,11 +83,18 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testChatControllerFullJIDBindingOnTypingAndNotActive);
CPPUNIT_TEST(testChatControllerPMPresenceHandling);
CPPUNIT_TEST(testLocalMUCServiceDiscoveryResetOnDisconnect);
+ CPPUNIT_TEST(testPresenceChangeDoesNotReplaceMUCInvite);
+
+ // Highlighting tests
CPPUNIT_TEST(testChatControllerHighlightingNotificationTesting);
CPPUNIT_TEST(testChatControllerHighlightingNotificationDeduplicateSounds);
CPPUNIT_TEST(testChatControllerMeMessageHandling);
CPPUNIT_TEST(testChatControllerMeMessageHandlingInMUC);
- CPPUNIT_TEST(testPresenceChangeDoesNotReplaceMUCInvite);
+
+ // Carbons tests
+ CPPUNIT_TEST(testCarbonsForwardedIncomingMessageToSecondResource);
+ CPPUNIT_TEST(testCarbonsForwardedOutgoingMessageFromSecondResource);
+
CPPUNIT_TEST_SUITE_END();
public:
@@ -921,6 +931,104 @@ public:
CPPUNIT_ASSERT_EQUAL(std::string("testling@test.com has gone offline."), MockChatWindow::bodyFromMessage(window->lastAddedPresence_));
}
+ template <typename CarbonsType>
+ Message::ref createCarbonsMessage(std::shared_ptr<CarbonsType> carbons, std::shared_ptr<Message> forwardedMessage) {
+ auto messageWrapper = std::make_shared<Message>();
+ messageWrapper->setFrom(jid_.toBare());
+ messageWrapper->setTo(jid_);
+ messageWrapper->setType(Message::Chat);
+
+ messageWrapper->addPayload(carbons);
+ auto forwarded = std::make_shared<Forwarded>();
+ carbons->setForwarded(forwarded);
+ forwarded->setStanza(forwardedMessage);
+ return messageWrapper;
+ }
+
+ void testCarbonsForwardedIncomingMessageToSecondResource() {
+ JID messageJID("testling@test.com/resource1");
+ JID jid2 = jid_.toBare().withResource("someOtherResource");
+
+ MockChatWindow* window = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
+
+ std::shared_ptr<Message> message(new Message());
+ message->setFrom(messageJID);
+ std::string body("This is a legible message. >HEH@)oeueu");
+ message->setBody(body);
+ manager_->handleIncomingMessage(message);
+ CPPUNIT_ASSERT_EQUAL(body, MockChatWindow::bodyFromMessage(window->lastAddedMessage_));
+
+ // incoming carbons message from another resource
+ {
+ auto originalMessage = std::make_shared<Message>();
+ originalMessage->setFrom(messageJID);
+ originalMessage->setTo(jid2);
+ originalMessage->setType(Message::Chat);
+ std::string forwardedBody = "Some further text.";
+ originalMessage->setBody(forwardedBody);
+
+ auto messageWrapper = createCarbonsMessage(std::make_shared<CarbonsReceived>(), originalMessage);
+
+ manager_->handleIncomingMessage(messageWrapper);
+
+ CPPUNIT_ASSERT_EQUAL(forwardedBody, MockChatWindow::bodyFromMessage(window->lastAddedMessage_));
+ CPPUNIT_ASSERT_EQUAL(false, window->lastAddedMessageSenderIsSelf_);
+ }
+ }
+
+ void testCarbonsForwardedOutgoingMessageFromSecondResource() {
+ JID messageJID("testling@test.com/resource1");
+ JID jid2 = jid_.toBare().withResource("someOtherResource");
+
+ MockChatWindow* window = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
+
+ std::shared_ptr<Message> message(new Message());
+ message->setFrom(messageJID);
+ std::string body("This is a legible message. >HEH@)oeueu");
+ message->setBody(body);
+ manager_->handleIncomingMessage(message);
+ CPPUNIT_ASSERT_EQUAL(body, MockChatWindow::bodyFromMessage(window->lastAddedMessage_));
+
+ // incoming carbons message from another resource
+ {
+ auto originalMessage = std::make_shared<Message>();
+ originalMessage->setFrom(jid2);
+ originalMessage->setTo(messageJID);
+ originalMessage->setType(Message::Chat);
+ originalMessage->setID("abcdefg123456");
+ std::string forwardedBody = "Some text my other resource sent.";
+ originalMessage->setBody(forwardedBody);
+ originalMessage->addPayload(std::make_shared<DeliveryReceiptRequest>());
+
+ auto messageWrapper = createCarbonsMessage(std::make_shared<CarbonsSent>(), originalMessage);
+
+ manager_->handleIncomingMessage(messageWrapper);
+
+ CPPUNIT_ASSERT_EQUAL(forwardedBody, MockChatWindow::bodyFromMessage(window->lastAddedMessage_));
+ CPPUNIT_ASSERT_EQUAL(true, window->lastAddedMessageSenderIsSelf_);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), window->receiptChanges_.size());
+ CPPUNIT_ASSERT_EQUAL(ChatWindow::ReceiptRequested, window->receiptChanges_[0].second);
+ }
+
+ // incoming carbons message for the received delivery receipt to the other resource
+ {
+ auto originalMessage = std::make_shared<Message>();
+ originalMessage->setFrom(messageJID);
+ originalMessage->setTo(jid2);
+ originalMessage->setType(Message::Chat);
+ originalMessage->addPayload(std::make_shared<DeliveryReceipt>("abcdefg123456"));
+
+ auto messageWrapper = createCarbonsMessage(std::make_shared<CarbonsReceived>(), originalMessage);
+
+ manager_->handleIncomingMessage(messageWrapper);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), window->receiptChanges_.size());
+ CPPUNIT_ASSERT_EQUAL(ChatWindow::ReceiptReceived, window->receiptChanges_[1].second);
+ }
+ }
+
private:
std::shared_ptr<Message> makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) {
std::shared_ptr<Message> message = std::make_shared<Message>();
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index eebac37..a9d3f5c 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -7,13 +7,13 @@
#include <Swift/Controllers/MainController.h>
#include <cstdlib>
+#include <memory>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
-#include <memory>
-#include <memory>
#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Base/Log.h>
#include <Swiften/Base/String.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Base/format.h>
@@ -35,6 +35,7 @@
#include <Swiften/Network/NetworkFactories.h>
#include <Swiften/Network/TimerFactory.h>
#include <Swiften/Presence/PresenceSender.h>
+#include <Swiften/Queries/Requests/EnableCarbonsRequest.h>
#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/StringCodecs/Hexify.h>
#include <Swiften/VCards/GetVCardRequest.h>
@@ -802,9 +803,26 @@ void MainController::handleServerDiscoInfoResponse(std::shared_ptr<DiscoInfo> in
rosterController_->getWindow()->setBlockingCommandAvailable(true);
rosterController_->initBlockingCommand();
}
+ if (info->hasFeature(DiscoInfo::MessageCarbonsFeature)) {
+ enableMessageCarbons();
+ }
}
}
+void MainController::enableMessageCarbons() {
+ auto enableCarbonsRequest = EnableCarbonsRequest::create(client_->getIQRouter());
+ enableCarbonsRequestHandlerConnection_ = enableCarbonsRequest->onResponse.connect([&](Payload::ref /*payload*/, ErrorPayload::ref error) {
+ if (error) {
+ SWIFT_LOG(warning) << "Failed to enable carbons." << std::endl;
+ }
+ else {
+ SWIFT_LOG(debug) << "Successfully enabled carbons." << std::endl;
+ }
+ enableCarbonsRequestHandlerConnection_.disconnect();
+ });
+ enableCarbonsRequest->send();
+}
+
void MainController::handleVCardReceived(const JID& jid, VCard::ref vCard) {
if (!jid.equals(jid_, JID::WithoutResource) || !vCard) {
return;
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 5000d51..4f691ee 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -122,6 +122,7 @@ namespace Swift {
void setReconnectTimer();
void resetPendingReconnects();
void resetCurrentError();
+ void enableMessageCarbons();
void performLoginFromCachedCredentials();
void reconnectAfterError();
@@ -195,5 +196,6 @@ namespace Swift {
HighlightManager* highlightManager_;
HighlightEditorController* highlightEditorController_;
std::map<std::string, std::string> emoticons_;
+ boost::signals2::connection enableCarbonsRequestHandlerConnection_;
};
}
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 4f874e1..d7942ff 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -7,8 +7,7 @@
#pragma once
#include <memory>
-
-#include <Swiften/Base/foreach.h>
+#include <string>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
@@ -18,13 +17,17 @@ namespace Swift {
MockChatWindow() : labelsEnabled_(false), impromptuMUCSupported_(false) {}
virtual ~MockChatWindow();
- virtual std::string addMessage(const ChatMessage& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, std::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) {
+ virtual std::string addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) {
lastAddedMessage_ = message;
+ lastAddedMessageSenderName_ = senderName;
+ lastAddedMessageSenderIsSelf_ = senderIsSelf;
return "id";
}
- virtual std::string addAction(const ChatMessage& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, std::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) {
+ virtual std::string addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) {
lastAddedAction_ = message;
+ lastAddedActionSenderName_ = senderName;
+ lastAddedActionSenderIsSelf_ = senderIsSelf;
return "id";
}
@@ -52,7 +55,9 @@ namespace Swift {
virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { }
virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { }
- virtual void setMessageReceiptState(const std::string &/* id */, ReceiptState /* state */) { }
+ virtual void setMessageReceiptState(const std::string & id, ReceiptState state) {
+ receiptChanges_.emplace_back(id, state);
+ }
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {}
virtual void setName(const std::string& name) {name_ = name;}
@@ -101,7 +106,7 @@ namespace Swift {
std::string body;
std::shared_ptr<ChatTextMessagePart> text;
std::shared_ptr<ChatHighlightingMessagePart> highlight;
- foreach (std::shared_ptr<ChatMessagePart> part, message.getParts()) {
+ for (auto &&part : message.getParts()) {
if ((text = std::dynamic_pointer_cast<ChatTextMessagePart>(part))) {
body += text->text;
}
@@ -114,11 +119,17 @@ namespace Swift {
void resetLastMessages() {
lastAddedMessage_ = lastAddedAction_ = lastAddedPresence_ = lastReplacedMessage_ = lastAddedSystemMessage_ = lastReplacedSystemMessage_ = ChatMessage();
+ lastAddedMessageSenderName_ = lastAddedActionSenderName_ = "";
+ lastAddedMessageSenderIsSelf_ = lastAddedActionSenderIsSelf_ = false;
}
std::string name_;
ChatMessage lastAddedMessage_;
+ std::string lastAddedMessageSenderName_;
+ bool lastAddedMessageSenderIsSelf_;
ChatMessage lastAddedAction_;
+ std::string lastAddedActionSenderName_;
+ bool lastAddedActionSenderIsSelf_;
ChatMessage lastAddedPresence_;
ChatMessage lastReplacedMessage_;
ChatMessage lastAddedSystemMessage_;
@@ -129,6 +140,7 @@ namespace Swift {
bool impromptuMUCSupported_;
SecurityLabelsCatalog::Item label_;
Roster* roster_;
+ std::vector<std::pair<std::string, ReceiptState>> receiptChanges_;
};
}
diff --git a/Swiften/Elements/DiscoInfo.cpp b/Swiften/Elements/DiscoInfo.cpp
index 29676b5..51a4450 100644
--- a/Swiften/Elements/DiscoInfo.cpp
+++ b/Swiften/Elements/DiscoInfo.cpp
@@ -24,6 +24,7 @@ const std::string DiscoInfo::Bytestream = std::string("http://jabber.org/protoco
const std::string DiscoInfo::MessageDeliveryReceiptsFeature = std::string("urn:xmpp:receipts");
const std::string DiscoInfo::WhiteboardFeature = std::string("http://swift.im/whiteboard");
const std::string DiscoInfo::BlockingCommandFeature = std::string("urn:xmpp:blocking");
+const std::string DiscoInfo::MessageCarbonsFeature = std::string("urn:xmpp:carbons:2");
bool DiscoInfo::Identity::operator<(const Identity& other) const {
if (category_ == other.category_) {
diff --git a/Swiften/Elements/DiscoInfo.h b/Swiften/Elements/DiscoInfo.h
index 6ce3fbb..ebc598c 100644
--- a/Swiften/Elements/DiscoInfo.h
+++ b/Swiften/Elements/DiscoInfo.h
@@ -35,6 +35,7 @@ namespace Swift {
static const std::string MessageDeliveryReceiptsFeature;
static const std::string WhiteboardFeature;
static const std::string BlockingCommandFeature;
+ static const std::string MessageCarbonsFeature;
class Identity {
public:
diff --git a/Swiften/Elements/Forwarded.h b/Swiften/Elements/Forwarded.h
index 1a31b89..a7eb492 100644
--- a/Swiften/Elements/Forwarded.h
+++ b/Swiften/Elements/Forwarded.h
@@ -6,8 +6,7 @@
#pragma once
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/optional.hpp>
+#include <memory>
#include <Swiften/Base/API.h>
#include <Swiften/Elements/Payload.h>
@@ -18,6 +17,9 @@ namespace Swift {
class SWIFTEN_API Forwarded : public Payload {
public:
+ typedef std::shared_ptr<Forwarded> ref;
+
+ public:
virtual ~Forwarded();
void setDelay(std::shared_ptr<Delay> delay) { delay_ = delay; }
diff --git a/Swiften/Queries/Requests/EnableCarbonsRequest.h b/Swiften/Queries/Requests/EnableCarbonsRequest.h
new file mode 100644
index 0000000..7762e68
--- /dev/null
+++ b/Swiften/Queries/Requests/EnableCarbonsRequest.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Elements/CarbonsEnable.h>
+#include <Swiften/Queries/GenericRequest.h>
+
+namespace Swift {
+ class SWIFTEN_API EnableCarbonsRequest : public GenericRequest<CarbonsEnable> {
+ public:
+ typedef std::shared_ptr<EnableCarbonsRequest> ref;
+
+ static ref create(IQRouter* router) {
+ return ref(new EnableCarbonsRequest(router));
+ }
+
+ private:
+ EnableCarbonsRequest(IQRouter* router) : GenericRequest<CarbonsEnable>(IQ::Set, JID(), std::make_shared<CarbonsEnable>(), router) {
+ }
+ };
+}