From 3d50e6e9e2b53b5fcde3d952ea5a54997b6f9feb Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 13 Oct 2017 11:20:20 +0200 Subject: [PATCH] Handle From and To headers in CPIM messages. --- src/chat/chat-message/chat-message-p.h | 7 ++ src/chat/chat-message/chat-message.cpp | 65 ++++++++++--------- src/chat/chat-message/chat-message.h | 1 + src/chat/chat-room/chat-room.cpp | 1 + .../modifier/cpim-chat-message-modifier.cpp | 54 ++++++++++++++- .../modifier/cpim-chat-message-modifier.h | 3 + 6 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index e62bff099..40f7ea492 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -55,6 +55,11 @@ public: // ----------------------------------------------------------------------------- + void setApplyModifiers (bool value) { applyModifiers = value; } + + const Address &getCpimFromAddress () const { return cpimFrom; } + void setCpimFromAddress (const Address &addr); + void setDirection (ChatMessage::Direction dir); void setState(ChatMessage::State state); @@ -124,6 +129,7 @@ private: unsigned int storageId = 0; Address from; Address to; + Address cpimFrom; time_t time = 0; std::string id; std::string appData; @@ -143,6 +149,7 @@ private: SalCustomHeader *salCustomHeaders = NULL; unsigned long backgroundTaskId; unsigned char currentSendStep = Step::None; + bool applyModifiers = true; // Cache for returned values, used for compatibility with previous C API ContentType cContentType; std::string cText; diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index d8f94593b..bec65cd75 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -60,6 +60,11 @@ void ChatMessagePrivate::setChatRoom (shared_ptr cr) { chatRoom = cr; } +void ChatMessagePrivate::setCpimFromAddress (const Address &addr) { + cpimFrom = addr; + cpimFrom.clean(); +} + void ChatMessagePrivate::setDirection (ChatMessage::Direction dir) { direction = dir; } @@ -1132,41 +1137,43 @@ void ChatMessagePrivate::send() { } //End of TODO Remove - if ((currentSendStep & ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) { - lInfo() << "Multipart step already done, skipping"; - } else { - if (contents.size() > 1) { - MultipartChatMessageModifier mcmm; - mcmm.encode(q->getSharedFromThis(), errorCode); + if (applyModifiers) { + if ((currentSendStep & ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) { + lInfo() << "Multipart step already done, skipping"; + } else { + if (contents.size() > 1) { + MultipartChatMessageModifier mcmm; + mcmm.encode(q->getSharedFromThis(), errorCode); + } + currentSendStep |= ChatMessagePrivate::Step::Multipart; } - currentSendStep |= ChatMessagePrivate::Step::Multipart; - } - if ((currentSendStep & ChatMessagePrivate::Step::Encryption) == ChatMessagePrivate::Step::Encryption) { - lInfo() << "Encryption step already done, skipping"; - } else { - EncryptionChatMessageModifier ecmm; - ChatMessageModifier::Result result = ecmm.encode(q->getSharedFromThis(), errorCode); - if (result == ChatMessageModifier::Result::Error) { - sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", errorCode, "Unable to encrypt IM", nullptr); - q->updateState(ChatMessage::State::NotDelivered); - q->store(); - return; - } else if (result == ChatMessageModifier::Result::Suspended) { + if ((currentSendStep & ChatMessagePrivate::Step::Encryption) == ChatMessagePrivate::Step::Encryption) { + lInfo() << "Encryption step already done, skipping"; + } else { + EncryptionChatMessageModifier ecmm; + ChatMessageModifier::Result result = ecmm.encode(q->getSharedFromThis(), errorCode); + if (result == ChatMessageModifier::Result::Error) { + sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", errorCode, "Unable to encrypt IM", nullptr); + q->updateState(ChatMessage::State::NotDelivered); + q->store(); + return; + } else if (result == ChatMessageModifier::Result::Suspended) { + currentSendStep |= ChatMessagePrivate::Step::Encryption; + return; + } currentSendStep |= ChatMessagePrivate::Step::Encryption; - return; } - currentSendStep |= ChatMessagePrivate::Step::Encryption; - } - if ((currentSendStep & ChatMessagePrivate::Step::Cpim) == ChatMessagePrivate::Step::Cpim) { - lInfo() << "Cpim step already done, skipping"; - } else { - if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) { - CpimChatMessageModifier ccmm; - ccmm.encode(q->getSharedFromThis(), errorCode); + if ((currentSendStep & ChatMessagePrivate::Step::Cpim) == ChatMessagePrivate::Step::Cpim) { + lInfo() << "Cpim step already done, skipping"; + } else { + if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) { + CpimChatMessageModifier ccmm; + ccmm.encode(q->getSharedFromThis(), errorCode); + } + currentSendStep |= ChatMessagePrivate::Step::Cpim; } - currentSendStep |= ChatMessagePrivate::Step::Cpim; } // --------------------------------------- diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index 7a5504860..d4be49592 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -39,6 +39,7 @@ class ChatMessagePrivate; class LINPHONE_PUBLIC ChatMessage : public Object { friend class ChatRoom; friend class ChatRoomPrivate; + friend class CpimChatMessageModifier; friend class RealTimeTextChatRoomPrivate; public: diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index c980b6566..50dc7d370 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -557,6 +557,7 @@ shared_ptr ChatRoom::createMessage () { shared_ptr chatMessage = ObjectFactory::create(getSharedFromThis()); chatMessage->setToAddress(d->peerAddress); chatMessage->setFromAddress(Address(linphone_core_get_identity(d->core))); + chatMessage->getPrivate()->setCpimFromAddress(chatMessage->getFromAddress()); chatMessage->getPrivate()->setTime(ms_time(0)); return chatMessage; } diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index af0b0568d..e7e04d870 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -18,7 +18,7 @@ */ #include "address/address.h" -#include "chat/chat-message/chat-message.h" +#include "chat/chat-message/chat-message-p.h" #include "chat/cpim/cpim.h" #include "content/content-type.h" #include "content/content.h" @@ -36,9 +36,16 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetPrivate()->getCpimFromAddress())); + cpimMessage.addMessageHeader(cpimFromHeader); + Cpim::ToHeader cpimToHeader; + cpimToHeader.setValue(cpimAddressAsString(message->getToAddress())); + cpimMessage.addMessageHeader(cpimToHeader); + Content content; if (!message->getInternalContent().isEmpty()) { // Another ChatMessageModifier was called before this one, we apply our changes on the private content @@ -93,11 +100,52 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptrgetContentHeaders()->front()->getValue())); + bool contentTypeFound = false; + Cpim::Message::HeaderList l = cpimMessage->getContentHeaders(); + if (l) { + for (const auto &header : *l.get()) { + if (header->getName() == "Content-Type") { + contentTypeFound = true; + newContent.setContentType(ContentType(header->getValue())); + break; + } + } + } + if (!contentTypeFound) { + lError() << "[CPIM] No Content-type for the content of the message"; + errorCode = 500; + return ChatMessageModifier::Result::Error; + } newContent.setBody(cpimMessage->getContent()); + + Address cpimFromAddress; + Address cpimToAddress; + l = cpimMessage->getMessageHeaders(); + if (l) { + for (const auto &header : *l.get()) { + if (header->getName() == "From") + cpimFromAddress = Address(header->getValue()); + else if (header->getName() == "To") + cpimToAddress = Address(header->getValue()); + } + } + + // Modify the initial message since there was no error message->setInternalContent(newContent); + if (cpimFromAddress.isValid()) + message->getPrivate()->setCpimFromAddress(cpimFromAddress); + if (cpimToAddress.isValid()) + message->setToAddress(cpimToAddress); return ChatMessageModifier::Result::Done; } +string CpimChatMessageModifier::cpimAddressAsString (const Address &addr) const { + ostringstream os; + if (!addr.getDisplayName().empty()) + os << addr.getDisplayName() << " "; + os << "<" << addr.asStringUriOnly() << ">"; + return os.str(); +} + LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/cpim-chat-message-modifier.h b/src/chat/modifier/cpim-chat-message-modifier.h index 7cb94c705..2b7488518 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.h +++ b/src/chat/modifier/cpim-chat-message-modifier.h @@ -32,6 +32,9 @@ public: Result encode (const std::shared_ptr &message, int &errorCode) override; Result decode (const std::shared_ptr &message, int &errorCode) override; + +private: + std::string cpimAddressAsString (const Address &addr) const; }; LINPHONE_END_NAMESPACE