diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a73468af..fad0f570e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,6 +48,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES chat/is-composing.h chat/modifier/chat-message-modifier.h chat/modifier/cpim-chat-message-modifier.h + chat/modifier/encryption-chat-message-modifier.h chat/modifier/multipart-chat-message-modifier.h chat/real-time-text-chat-room-p.h chat/real-time-text-chat-room.h @@ -129,6 +130,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES chat/imdn.cpp chat/is-composing.cpp chat/modifier/cpim-chat-message-modifier.cpp + chat/modifier/encryption-chat-message-modifier.cpp chat/modifier/multipart-chat-message-modifier.cpp chat/real-time-text-chat-room.cpp conference/conference.cpp diff --git a/src/chat/chat-message-p.h b/src/chat/chat-message-p.h index f461d5c26..7fc20f851 100644 --- a/src/chat/chat-message-p.h +++ b/src/chat/chat-message-p.h @@ -29,6 +29,7 @@ LINPHONE_BEGIN_NAMESPACE class ChatMessagePrivate : public ObjectPrivate { friend class CpimChatMessageModifier; + friend class EncryptionChatMessageModifier; friend class MultipartChatMessageModifier; public: @@ -98,6 +99,7 @@ public: void sendImdn(ImdnType imdnType, LinphoneReason reason); + LinphoneReason receive(); void send(); private: @@ -143,6 +145,8 @@ private: int startHttpTransfer(std::string url, std::string action, belle_http_request_listener_callbacks_t *cbs); void releaseHttpRequest(); + + std::shared_ptr getPublicSharedPtr(); // ----------------------------------------------------------------------------- diff --git a/src/chat/chat-message.cpp b/src/chat/chat-message.cpp index d854e9b48..d06008c2f 100644 --- a/src/chat/chat-message.cpp +++ b/src/chat/chat-message.cpp @@ -29,9 +29,11 @@ #include "content/content.h" #include "chat-room-p.h" #include "real-time-text-chat-room.h" -#include "modifier/multipart-chat-message-modifier.h" #include "modifier/cpim-chat-message-modifier.h" +#include "modifier/encryption-chat-message-modifier.h" +#include "modifier/multipart-chat-message-modifier.h" +#include "logger/logger.h" #include "ortp/b64.h" // ============================================================================= @@ -53,6 +55,11 @@ ChatMessagePrivate::~ChatMessagePrivate () {} // ----------------------------------------------------------------------------- +shared_ptr ChatMessagePrivate::getPublicSharedPtr() { + L_Q(); + return q->getSharedPtr(); +} + void ChatMessagePrivate::setChatRoom (shared_ptr cr) { chatRoom = cr; } @@ -887,6 +894,59 @@ void ChatMessagePrivate::releaseHttpRequest() { } } +LinphoneReason ChatMessagePrivate::receive() { + L_Q(); + + LinphoneReason reason = LinphoneReasonNone; + bool store = false; + + // --------------------------------------- + // Start of message modification + // --------------------------------------- + + EncryptionChatMessageModifier ecmm; + int retval = 0; + retval = ecmm.decode(this); + if (retval > 0) { + /* Unable to decrypt message */ + chatRoom->getPrivate()->notifyUndecryptableMessageReceived(getPublicSharedPtr()); + reason = linphone_error_code_to_reason(retval); + q->sendDeliveryNotification(reason); + /* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */ + reason = LinphoneReasonNone; + goto end; + } + + // --------------------------------------- + // End of message modification + // --------------------------------------- + + if ((retval <= 0) && (linphone_core_is_content_type_supported(chatRoom->getCore(), getContentType().c_str()) == FALSE)) { + retval = 415; + lError() << "Unsupported MESSAGE (content-type " << getContentType() << " not recognized)"; + } + + if (retval > 0) { + reason = linphone_error_code_to_reason(retval); + q->sendDeliveryNotification(reason); + goto end; + } + + if (ContentType::isFileTransfer(getContentType())) { + create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(L_GET_C_BACK_PTR(getPublicSharedPtr())); + store = true; + } else if (ContentType::isText(getContentType())) { + store = true; + } + + if (store) { + q->store(); + } + +end: + return reason; +} + void ChatMessagePrivate::send() { L_Q(); SalOp *op = salOp; @@ -941,19 +1001,14 @@ void ChatMessagePrivate::send() { if (!getContentType().empty()) { clearTextContentType = getContentType(); } - - int retval = -1; - LinphoneImEncryptionEngine *imee = chatRoom->getCore()->im_encryption_engine; - if (imee) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); - if (cbProcessOutgoingMessage) { - retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(chatRoom), L_GET_C_BACK_PTR(q->getSharedPtr())); - if (retval == 0) { - isSecured = true; - } - } + + if (contents.size() > 1) { + MultipartChatMessageModifier mcmm; + mcmm.encode(this); } + + EncryptionChatMessageModifier ecmm; + int retval = ecmm.encode(this); if (retval > 0) { sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr); @@ -962,11 +1017,6 @@ void ChatMessagePrivate::send() { return; } - if (contents.size() > 1) { - MultipartChatMessageModifier mcmm; - mcmm.encode(this); - } - if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) { CpimChatMessageModifier ccmm; ccmm.encode(this); diff --git a/src/chat/chat-room-p.h b/src/chat/chat-room-p.h index 02d6e802c..4bcd6792a 100644 --- a/src/chat/chat-room-p.h +++ b/src/chat/chat-room-p.h @@ -35,6 +35,7 @@ LINPHONE_BEGIN_NAMESPACE class ChatRoomPrivate : public ObjectPrivate, public IsComposingListener { + friend class ChatMessagePrivate; public: ChatRoomPrivate (LinphoneCore *core); virtual ~ChatRoomPrivate (); diff --git a/src/chat/chat-room.cpp b/src/chat/chat-room.cpp index 4a99b6a79..ad33f152c 100644 --- a/src/chat/chat-room.cpp +++ b/src/chat/chat-room.cpp @@ -416,57 +416,20 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa if (salMsg->url) msg->setExternalBodyUrl(salMsg->url); - int retval = -1; - LinphoneImEncryptionEngine *imee = core->im_encryption_engine; - if (imee) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = linphone_im_encryption_engine_cbs_get_process_incoming_message(imeeCbs); - if (cbProcessIncomingMessage) { - retval = cbProcessIncomingMessage(imee, L_GET_C_BACK_PTR(q), L_GET_C_BACK_PTR(msg)); - if (retval == 0) { - msg->setIsSecured(true); - } else if (retval > 0) { - /* Unable to decrypt message */ - notifyUndecryptableMessageReceived(msg); - reason = linphone_error_code_to_reason(retval); - msg->sendDeliveryNotification(reason); - /* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */ - reason = LinphoneReasonNone; - goto end; - } - } - } + reason = msg->getPrivate()->receive(); - if ((retval <= 0) && (linphone_core_is_content_type_supported(core, msg->getPrivate()->getContentType().c_str()) == FALSE)) { - retval = 415; - lError() << "Unsupported MESSAGE (content-type " << msg->getPrivate()->getContentType() << " not recognized)"; - } - - if (retval > 0) { - reason = linphone_error_code_to_reason(retval); - msg->sendDeliveryNotification(reason); - goto end; - } - - if (ContentType::isFileTransfer(msg->getPrivate()->getContentType())) { - create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(L_GET_C_BACK_PTR(msg)); - msg->setIsToBeStored(true); - } else if (ContentType::isImIsComposing(msg->getPrivate()->getContentType())) { + if (ContentType::isImIsComposing(msg->getPrivate()->getContentType())) { isComposingReceived(msg->getPrivate()->getText()); - msg->setIsToBeStored(false); increaseMsgCount = FALSE; if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) { goto end; } } else if (ContentType::isImdn(msg->getPrivate()->getContentType())) { imdnReceived(msg->getPrivate()->getText()); - msg->setIsToBeStored(false); increaseMsgCount = FALSE; if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) { goto end; } - } else if (ContentType::isText(msg->getPrivate()->getContentType())) { - msg->setIsToBeStored(true); } if (increaseMsgCount) { @@ -482,10 +445,6 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa chatMessageReceived(msg); - if (msg->isToBeStored()) { - msg->store(); - } - pendingMessage = nullptr; end: @@ -751,7 +710,7 @@ void ChatRoom::markAsRead () { sqlite3_free(buf); if (d->pendingMessage) { - d->pendingMessage->getPrivate()->setState(ChatMessage::State::Displayed); + d->pendingMessage->updateState(ChatMessage::State::Displayed); d->pendingMessage->sendDisplayNotification(); } diff --git a/src/chat/modifier/chat-message-modifier.h b/src/chat/modifier/chat-message-modifier.h index 0f4071df8..ed4741de4 100644 --- a/src/chat/modifier/chat-message-modifier.h +++ b/src/chat/modifier/chat-message-modifier.h @@ -20,7 +20,6 @@ #define _CHAT_MESSAGE_MODIFIER_H_ #include "linphone/utils/general.h" - #include "private.h" // ============================================================================= @@ -33,8 +32,8 @@ class ChatMessageModifier { public: virtual ~ChatMessageModifier () = default; - virtual void encode (ChatMessagePrivate *messagePrivate) = 0; - virtual void decode (ChatMessagePrivate *messagePrivate) = 0; + virtual int encode (ChatMessagePrivate *messagePrivate) = 0; + virtual int decode (ChatMessagePrivate *messagePrivate) = 0; }; LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 33c2dba62..65cb25e1e 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -30,7 +30,7 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -void CpimChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { +int CpimChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { Cpim::Message message; Cpim::GenericHeader cpimContentTypeHeader; cpimContentTypeHeader.setName("Content-Type"); @@ -68,9 +68,10 @@ void CpimChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { newContent->setBody(message.asString()); messagePrivate->internalContent = newContent; } + return 0; } -void CpimChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { +int CpimChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { shared_ptr content; if (messagePrivate->internalContent) { content = messagePrivate->internalContent; @@ -94,6 +95,7 @@ void CpimChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { } else { //TODO } + return 0; } LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/cpim-chat-message-modifier.h b/src/chat/modifier/cpim-chat-message-modifier.h index 9d5696bb0..550887808 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.h +++ b/src/chat/modifier/cpim-chat-message-modifier.h @@ -29,8 +29,8 @@ class CpimChatMessageModifier : public ChatMessageModifier { public: CpimChatMessageModifier () = default; - void encode (ChatMessagePrivate *messagePrivate) override; - void decode (ChatMessagePrivate *messagePrivate) override; + int encode (ChatMessagePrivate *messagePrivate) override; + int decode (ChatMessagePrivate *messagePrivate) override; }; LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/encryption-chat-message-modifier.cpp b/src/chat/modifier/encryption-chat-message-modifier.cpp new file mode 100644 index 000000000..0949724b4 --- /dev/null +++ b/src/chat/modifier/encryption-chat-message-modifier.cpp @@ -0,0 +1,68 @@ +/* + * encryption-chat-message-modifier.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "encryption-chat-message-modifier.h" + +#include "object/object-p.h" +#include "c-wrapper/c-wrapper.h" + +#include "content/content-type.h" +#include "content/content.h" +#include "address/address.h" +#include "chat/chat-room.h" +#include "chat/chat-message-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +int EncryptionChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { + int retval = -1; + LinphoneImEncryptionEngine *imee = messagePrivate->chatRoom->getCore()->im_encryption_engine; + if (imee) { + LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); + if (cbProcessOutgoingMessage) { + retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(messagePrivate->chatRoom), L_GET_C_BACK_PTR(messagePrivate->getPublicSharedPtr())); + if (retval == 0) { + messagePrivate->isSecured = true; + } + } + } + return retval; +} + +int EncryptionChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { + int retval = -1; + LinphoneImEncryptionEngine *imee = messagePrivate->chatRoom->getCore()->im_encryption_engine; + if (imee) { + LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = linphone_im_encryption_engine_cbs_get_process_incoming_message(imeeCbs); + if (cbProcessIncomingMessage) { + retval = cbProcessIncomingMessage(imee, L_GET_C_BACK_PTR(messagePrivate->chatRoom), L_GET_C_BACK_PTR(messagePrivate->getPublicSharedPtr())); + if (retval == 0) { + messagePrivate->isSecured = true; + } + } + } + return retval; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/encryption-chat-message-modifier.h b/src/chat/modifier/encryption-chat-message-modifier.h new file mode 100644 index 000000000..8389236a0 --- /dev/null +++ b/src/chat/modifier/encryption-chat-message-modifier.h @@ -0,0 +1,38 @@ +/* + * encryption-chat-message-modifier.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ +#define _ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ + +#include "chat-message-modifier.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class EncryptionChatMessageModifier : public ChatMessageModifier { +public: + EncryptionChatMessageModifier () = default; + + int encode (ChatMessagePrivate *messagePrivate) override; + int decode (ChatMessagePrivate *messagePrivate) override; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index c3c8299ca..cdad3fc02 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -26,14 +26,16 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -void MultipartChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { +int MultipartChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { if (messagePrivate->contents.size() > 1) { //TODO } + return 0; } -void MultipartChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { +int MultipartChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { //TODO + return 0; } LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/multipart-chat-message-modifier.h b/src/chat/modifier/multipart-chat-message-modifier.h index 17361d3d6..23b8dbe79 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.h +++ b/src/chat/modifier/multipart-chat-message-modifier.h @@ -29,8 +29,8 @@ class MultipartChatMessageModifier : public ChatMessageModifier { public: MultipartChatMessageModifier () = default; - void encode (ChatMessagePrivate *message) override; - void decode (ChatMessagePrivate *message) override; + int encode (ChatMessagePrivate *message) override; + int decode (ChatMessagePrivate *message) override; }; LINPHONE_END_NAMESPACE