Add Content-Disposition header for IMDN messages.

This commit is contained in:
Ghislain MARY 2018-04-12 11:02:31 +02:00
parent 5ab6c928f2
commit 94e53a4e22
12 changed files with 71 additions and 40 deletions

View file

@ -26,8 +26,8 @@
#include "chat/chat-room/chat-room-id.h"
#include "chat/modifier/file-transfer-chat-message-modifier.h"
#include "chat/notification/imdn.h"
#include "content/content-type.h"
#include "content/content.h"
#include "content/content-type.h"
#include "content/file-content.h"
#include "content/file-transfer-content.h"
#include "db/main-db.h"

View file

@ -33,17 +33,15 @@
#include "chat/chat-room/real-time-text-chat-room.h"
#include "chat/modifier/cpim-chat-message-modifier.h"
#include "chat/modifier/encryption-chat-message-modifier.h"
#include "chat/modifier/file-transfer-chat-message-modifier.h"
#include "chat/modifier/multipart-chat-message-modifier.h"
#include "chat/notification/imdn.h"
#include "conference/participant.h"
#include "conference/participant-imdn-state.h"
#include "content/file-content.h"
#include "content/content-disposition.h"
#include "content/header/header-param.h"
#include "content/content.h"
#include "core/core.h"
#include "core/core-p.h"
#include "logger/logger.h"
#include "chat/notification/imdn.h"
#include "sip-tools/sip-headers.h"
#include "ortp/b64.h"
@ -462,6 +460,7 @@ void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) {
shared_ptr<ChatMessage> msg = q->getChatRoom()->createChatMessage();
Content *content = new Content();
content->setContentDisposition(ContentDisposition::Notification);
content->setContentType(ContentType::Imdn);
content->setBody(Imdn::createXml(imdnId, time, imdnType, reason));
msg->addContent(content);
@ -773,13 +772,16 @@ void ChatMessagePrivate::send () {
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
if (!externalBodyUrl.empty()) {
char *content_type = ms_strdup_printf("message/external-body;access-type=URL;URL=\"%s\"", externalBodyUrl.c_str());
msgOp->send_message(content_type, NULL);
ms_free(content_type);
} else if (internalContent.getContentType().isValid()) {
msgOp->send_message(internalContent.getContentType().asString().c_str(), internalContent.getBodyAsUtf8String().c_str());
Content content;
ContentType contentType(ContentType::ExternalBody);
contentType.addParameter("access-type", "URL");
contentType.addParameter("URL", "\"" + externalBodyUrl + "\"");
content.setContentType(contentType);
msgOp->sendMessage(content);
} else {
msgOp->send_message(ContentType::PlainText.asString().c_str(), internalContent.getBodyAsUtf8String().c_str());
if (!internalContent.getContentType().isValid())
internalContent.setContentType(ContentType::PlainText);
msgOp->sendMessage(internalContent);
}
// Restore FileContents and remove FileTransferContents

View file

@ -69,7 +69,7 @@ public:
private:
struct Message {
Message (const std::string &from, const ContentType &contentType, const std::string &text, const SalCustomHeader *salCustomHeaders)
: fromAddr(from)
: fromAddr(from)
{
content.setContentType(contentType);
if (!text.empty())

View file

@ -20,8 +20,9 @@
#include "address/address.h"
#include "chat/chat-message/chat-message-p.h"
#include "chat/cpim/cpim.h"
#include "content/content-type.h"
#include "content/content.h"
#include "content/content-disposition.h"
#include "content/content-type.h"
#include "logger/logger.h"
#include "cpim-chat-message-modifier.h"
@ -59,6 +60,12 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr<Ch
content = message->getContents().front();
}
if (content->getContentDisposition().isValid()) {
Cpim::GenericHeader contentDispositionHeader;
contentDispositionHeader.setName("Content-Disposition");
contentDispositionHeader.setValue(content->getContentDisposition().asString());
cpimMessage.addContentHeader(contentDispositionHeader);
}
Cpim::GenericHeader contentTypeHeader;
contentTypeHeader.setName("Content-Type");
contentTypeHeader.setValue(content->getContentType().asString());
@ -100,10 +107,11 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptr<Ch
Cpim::Message::HeaderList l = cpimMessage->getContentHeaders();
if (l) {
for (const auto &header : *l.get()) {
if (header->getName() == "Content-Type") {
if (header->getName() == "Content-Disposition") {
newContent.setContentDisposition(ContentDisposition(header->getValue()));
} else if (header->getName() == "Content-Type") {
contentTypeFound = true;
newContent.setContentType(ContentType(header->getValue()));
break;
}
}
}

View file

@ -38,6 +38,7 @@ public:
// -----------------------------------------------------------------------------
const ContentDisposition ContentDisposition::Notification("notification");
const ContentDisposition ContentDisposition::RecipientList("recipient-list");
const ContentDisposition ContentDisposition::RecipientListHistory("recipient-list-history; handling=optional");

View file

@ -52,6 +52,7 @@ public:
std::string asString () const;
static const ContentDisposition Notification;
static const ContentDisposition RecipientList;
static const ContentDisposition RecipientListHistory;

View file

@ -1530,10 +1530,11 @@ void SalCallOp::process_notify(const belle_sip_request_event_t *event, belle_sip
}
}
int SalCallOp::send_message(const char* content_type, const char *msg) {
if (!this->dialog) return -1;
belle_sip_request_t* req=belle_sip_dialog_create_queued_request(this->dialog,"MESSAGE");
prepare_message_request(req, content_type, msg);
int SalCallOp::sendMessage (const Content &content) {
if (!this->dialog)
return -1;
belle_sip_request_t *req = belle_sip_dialog_create_queued_request(this->dialog, "MESSAGE");
prepareMessageRequest(req, content);
return send_request(req);
}

View file

@ -66,7 +66,7 @@ public:
void set_sdp_handling(SalOpSDPHandling handling);
// Implementation of SalMessageOpInterface
int send_message(const char* content_type, const char *msg) override;
int sendMessage (const Content &content) override;
int reply(SalReason reason) override {return SalOp::reply_message(reason);}
private:

View file

@ -20,17 +20,49 @@
#ifndef _L_SAL_MESSAGE_OP_INTERFACE_H_
#define _L_SAL_MESSAGE_OP_INTERFACE_H_
#include <ctime>
#include "content/content.h"
#include "content/content-type.h"
LINPHONE_BEGIN_NAMESPACE
class SalMessageOpInterface {
public:
virtual ~SalMessageOpInterface() = default;
virtual int send_message(const char* content_type, const char *msg) = 0;
virtual int sendMessage (const Content &content) = 0;
virtual int reply(SalReason reason) = 0;
protected:
void prepare_message_request(belle_sip_request_t *req, const char* content_type, const char *msg);
void prepareMessageRequest (belle_sip_request_t *req, const Content &content) {
time_t curtime = std::time(nullptr);
belle_sip_message_add_header(
BELLE_SIP_MESSAGE(req),
BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))
);
const ContentType &contentType = content.getContentType();
std::string contentTypeStr = std::string(BELLE_SIP_CONTENT_TYPE ": ") + contentType.asString();
belle_sip_message_add_header(
BELLE_SIP_MESSAGE(req),
BELLE_SIP_HEADER(belle_sip_header_content_type_parse(contentTypeStr.c_str()))
);
if (content.isEmpty()) {
belle_sip_message_add_header(
BELLE_SIP_MESSAGE(req),
BELLE_SIP_HEADER(belle_sip_header_content_length_create(0))
);
} else {
std::string body = content.getBodyAsUtf8String();
size_t contentLength = body.size();
belle_sip_message_add_header(
BELLE_SIP_MESSAGE(req),
BELLE_SIP_HEADER(belle_sip_header_content_length_create(contentLength))
);
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), body.c_str(), contentLength);
}
}
};
LINPHONE_END_NAMESPACE

View file

@ -77,27 +77,13 @@ void SalMessageOp::fill_cbs() {
this->type=Type::Message;
}
void SalMessageOpInterface::prepare_message_request(belle_sip_request_t *req, const char* content_type, const char *msg) {
char content_type_raw[256];
size_t content_length = msg?strlen(msg):0;
time_t curtime = ms_time(NULL);
snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
if (msg){
/*don't call set_body() with null argument because it resets content type and content length*/
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), msg, content_length);
}
}
int SalMessageOp::send_message(const char* content_type, const char *msg) {
int SalMessageOp::sendMessage (const Content &content) {
fill_cbs();
this->dir = Dir::Outgoing;
belle_sip_request_t *req = build_request("MESSAGE");
if (!req)
return -1;
prepare_message_request(req, content_type, msg);
prepareMessageRequest(req, content);
return send_request(req);
}

View file

@ -29,7 +29,7 @@ class SalMessageOp: public SalOp, public SalMessageOpInterface {
public:
SalMessageOp(Sal *sal): SalOp(sal) {}
int send_message(const char* content_type, const char *msg) override;
int sendMessage (const Content &content) override;
int reply(SalReason reason) override {return SalOp::reply_message(reason);}
private:

View file

@ -1040,7 +1040,7 @@ void SalOp::process_incoming_message(const belle_sip_request_event_t *event) {
salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/
((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/
}
salmsg.message_id=message_id;
salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL);
this->root->callbacks.message_received(this,&salmsg);