mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-03 11:49:31 +00:00
Clean code related to multiparts' Contents
This commit is contained in:
parent
ba1d6bc8b0
commit
0dfd57b505
7 changed files with 65 additions and 151 deletions
|
|
@ -419,6 +419,11 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i
|
|||
return (SalBodyHandler *)belle_sip_list_nth_data(l, idx);
|
||||
}
|
||||
|
||||
const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler) {
|
||||
if (!sal_body_handler_is_multipart(body_handler)) return NULL;
|
||||
return belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
|
||||
}
|
||||
|
||||
SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) {
|
||||
const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
|
||||
for (; l != NULL; l = l->next) {
|
||||
|
|
|
|||
|
|
@ -647,6 +647,7 @@ size_t sal_body_handler_get_size(const SalBodyHandler *body_handler);
|
|||
void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size);
|
||||
bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler);
|
||||
SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx);
|
||||
const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler);
|
||||
SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value);
|
||||
const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,14 +20,10 @@
|
|||
// TODO: Remove me later.
|
||||
#include "private.h"
|
||||
|
||||
#include "address/address.h"
|
||||
#include "chat/chat-message/chat-message.h"
|
||||
#include "chat/chat-room/chat-room.h"
|
||||
#include "content/content-type.h"
|
||||
#include "content/header-param.h"
|
||||
#include "content/content-manager.h"
|
||||
#include "content/file-transfer-content.h"
|
||||
#include "logger/logger.h"
|
||||
#include "core/core.h"
|
||||
|
||||
#include "multipart-chat-message-modifier.h"
|
||||
|
||||
|
|
@ -44,85 +40,30 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode (
|
|||
if (message->getContents().size() <= 1)
|
||||
return ChatMessageModifier::Result::Skipped;
|
||||
|
||||
LinphoneCore *lc = message->getChatRoom()->getCore()->getCCore();
|
||||
char tmp[64];
|
||||
lc->sal->create_uuid(tmp, sizeof(tmp));
|
||||
string boundary = tmp;
|
||||
stringstream multipartMessage;
|
||||
|
||||
multipartMessage << "--" << boundary;
|
||||
for (Content *content : message->getContents()) {
|
||||
multipartMessage << "\r\n";
|
||||
multipartMessage << "Content-Type: " << content->getContentType().asString() << "\r\n\r\n";
|
||||
multipartMessage << content->getBodyAsString() << "\r\n\r\n";
|
||||
multipartMessage << "--" << boundary;
|
||||
}
|
||||
multipartMessage << "--";
|
||||
|
||||
Content newContent;
|
||||
ContentType newContentType(ContentType::Multipart);
|
||||
newContentType.addParameter("boundary", boundary);
|
||||
newContent.setContentType(newContentType);
|
||||
newContent.setBody(multipartMessage.str());
|
||||
message->setInternalContent(newContent);
|
||||
Content content = ContentManager::contentListToMultipart(message->getContents());
|
||||
message->setInternalContent(content);
|
||||
|
||||
return ChatMessageModifier::Result::Done;
|
||||
}
|
||||
|
||||
ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr<ChatMessage> &message, int &errorCode) {
|
||||
if (message->getInternalContent().getContentType().getType() == "multipart") {
|
||||
string boundary = message->getInternalContent().getContentType().getParameter("boundary").getValue();
|
||||
if (boundary.empty()) {
|
||||
lError() << "Boundary parameter of content-type not found: " << message->getInternalContent().getContentType().asString();
|
||||
return ChatMessageModifier::Result::Error;
|
||||
}
|
||||
|
||||
boundary = "--" + boundary;
|
||||
lInfo() << "Multipart boundary is " << boundary;
|
||||
|
||||
const vector<char> body = message->getInternalContent().getBody();
|
||||
string contentsString(body.begin(), body.end());
|
||||
|
||||
size_t pos = contentsString.find(boundary);
|
||||
if (pos == string::npos) {
|
||||
lError() << "Boundary not found in body !";
|
||||
return ChatMessageModifier::Result::Error;
|
||||
}
|
||||
|
||||
size_t start = pos + boundary.length() + 2; // 2 is the size of \r\n
|
||||
size_t end;
|
||||
do {
|
||||
end = contentsString.find(boundary, start);
|
||||
if (end != string::npos) {
|
||||
string contentString = contentsString.substr(start, end - start);
|
||||
|
||||
size_t contentTypePos = contentString.find(": ") + 2; // 2 is the size of :
|
||||
size_t endOfLinePos = contentString.find("\r\n");
|
||||
if (contentTypePos >= endOfLinePos) {
|
||||
lError() << "Content should start by a 'Content-Type: ' line !";
|
||||
continue;
|
||||
if (message->getInternalContent().getContentType().isMultipart()) {
|
||||
for (Content &c : ContentManager::multipartToContentList(message->getInternalContent())) {
|
||||
Content *content;
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
content = new FileTransferContent();
|
||||
content->setContentType(c.getContentType());
|
||||
content->setContentDisposition(c.getContentDisposition());
|
||||
content->setContentEncoding(c.getContentEncoding());
|
||||
for (const pair<string, string> &pair : c.getHeaders()) {
|
||||
content->addHeader(pair.first, pair.second);
|
||||
}
|
||||
string contentTypeString = contentString.substr(contentTypePos, endOfLinePos - contentTypePos);
|
||||
ContentType contentType(contentTypeString);
|
||||
|
||||
endOfLinePos += 4; // 4 is two time the size of \r\n
|
||||
string contentBody = contentString.substr(endOfLinePos, contentString.length() - (endOfLinePos + 4)); // 4 is two time the size of \r\n
|
||||
|
||||
Content *content;
|
||||
if (contentType == ContentType::FileTransfer) {
|
||||
content = new FileTransferContent();
|
||||
} else {
|
||||
content = new Content();
|
||||
}
|
||||
content->setContentType(contentType);
|
||||
content->setBody(contentBody);
|
||||
message->addContent(content);
|
||||
|
||||
lInfo() << "Parsed and added content with type " << contentType.asString();
|
||||
content->setBodyFromUtf8(c.getBodyAsUtf8String());
|
||||
} else {
|
||||
content = new Content(c);
|
||||
}
|
||||
start = end + boundary.length() + 2; // 2 is the size of \r\n
|
||||
} while (end != string::npos);
|
||||
|
||||
message->addContent(content);
|
||||
}
|
||||
return ChatMessageModifier::Result::Done;
|
||||
}
|
||||
return ChatMessageModifier::Result::Skipped;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId)
|
|||
static_cast<unsigned int>(notifyId)
|
||||
);
|
||||
|
||||
list<Content> contents;
|
||||
list<Content *> contents;
|
||||
for (const auto &eventLog : events) {
|
||||
Content content;
|
||||
content.setContentType(ContentType("application","conference-info"));
|
||||
|
|
@ -181,7 +181,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId)
|
|||
continue;
|
||||
}
|
||||
content.setBody(body);
|
||||
contents.push_back(content);
|
||||
contents.push_back(&content);
|
||||
}
|
||||
|
||||
if (contents.empty())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
#include <belle-sip/belle-sip.h>
|
||||
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
|
||||
#include "linphone/api/c-content.h"
|
||||
|
||||
#include "content-manager.h"
|
||||
#include "content-type.h"
|
||||
#include "content/content.h"
|
||||
|
|
@ -36,86 +40,47 @@ namespace {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
list<Content> ContentManager::multipartToContentList (const Content &content) {
|
||||
const string body = content.getBodyAsString();
|
||||
belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new_from_buffer(
|
||||
body.c_str(), body.length(), MultipartBoundary
|
||||
);
|
||||
belle_sip_object_ref(mpbh);
|
||||
LinphoneContent *cContent = L_GET_C_BACK_PTR(&content);
|
||||
SalBodyHandler *sbh = sal_body_handler_ref(sal_body_handler_from_content(cContent));
|
||||
|
||||
list<Content> contents;
|
||||
for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) {
|
||||
belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data);
|
||||
Content content;
|
||||
|
||||
for (const belle_sip_list_t *it = belle_sip_body_handler_get_headers(part); it; it = it->next) {
|
||||
belle_sip_header_t *header = BELLE_SIP_HEADER(it->data);
|
||||
if (strcasecmp("Content-Type", belle_sip_header_get_name(header)) == 0) {
|
||||
belle_sip_header_content_type_t * partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header);
|
||||
content.setContentType(ContentType(
|
||||
belle_sip_header_content_type_get_type(partContentType),
|
||||
belle_sip_header_content_type_get_subtype(partContentType)
|
||||
));
|
||||
} else {
|
||||
content.addHeader(belle_sip_header_get_name(header), belle_sip_header_get_unparsed_value(header));
|
||||
}
|
||||
}
|
||||
|
||||
content.setBody(static_cast<const char *>(
|
||||
belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part))
|
||||
));
|
||||
|
||||
contents.push_back(move(content));
|
||||
for (const belle_sip_list_t *parts = sal_body_handler_get_parts(sbh); parts; parts = parts->next) {
|
||||
SalBodyHandler *part = (SalBodyHandler *)parts->data;
|
||||
LinphoneContent *cContent = linphone_content_from_sal_body_handler(part);
|
||||
Content *cppContent = L_GET_CPP_PTR_FROM_C_OBJECT(cContent);
|
||||
contents.push_back(*cppContent);
|
||||
linphone_content_unref(cContent);
|
||||
}
|
||||
|
||||
belle_sip_object_unref(mpbh);
|
||||
sal_body_handler_unref(sbh);
|
||||
linphone_content_unref(cContent);
|
||||
return contents;
|
||||
}
|
||||
|
||||
Content ContentManager::contentListToMultipart (const list<Content> &contents) {
|
||||
Content ContentManager::contentListToMultipart (const list<Content *> &contents) {
|
||||
belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new(
|
||||
nullptr, nullptr, nullptr, MultipartBoundary
|
||||
);
|
||||
belle_sip_object_ref(mpbh);
|
||||
mpbh = (belle_sip_multipart_body_handler_t *)belle_sip_object_ref(mpbh);
|
||||
|
||||
for (const auto &content : contents) {
|
||||
const ContentType &contentType = content.getContentType();
|
||||
belle_sip_header_t *cContentType = BELLE_SIP_HEADER(
|
||||
belle_sip_header_content_type_create(
|
||||
contentType.getType().c_str(),
|
||||
string(contentType.getSubType() + "; charset=\"UTF-8\"").c_str()
|
||||
)
|
||||
);
|
||||
|
||||
const string body = content.getBodyAsString();
|
||||
belle_sip_memory_body_handler_t *mbh = belle_sip_memory_body_handler_new_copy_from_buffer(
|
||||
body.c_str(), body.length(), nullptr, nullptr
|
||||
);
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), cContentType);
|
||||
|
||||
for (const auto &header : content.getHeaders()) {
|
||||
belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER(
|
||||
belle_sip_header_create(
|
||||
header.first.c_str(),
|
||||
header.second.c_str()
|
||||
)
|
||||
);
|
||||
belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), additionalHeader);
|
||||
}
|
||||
|
||||
belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(mbh));
|
||||
for (Content *content : contents) {
|
||||
LinphoneContent *cContent = L_GET_C_BACK_PTR(content);
|
||||
SalBodyHandler *sbh = sal_body_handler_from_content(cContent);
|
||||
belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(sbh));
|
||||
linphone_content_unref(cContent);
|
||||
}
|
||||
|
||||
char *desc = belle_sip_object_to_string(mpbh);
|
||||
Content content;
|
||||
content.setBody(desc);
|
||||
belle_sip_free(desc);
|
||||
SalBodyHandler *sbh = (SalBodyHandler *)mpbh;
|
||||
sal_body_handler_set_type(sbh, ContentType::Multipart.getType().c_str());
|
||||
sal_body_handler_set_subtype(sbh, ContentType::Multipart.getSubType().c_str());
|
||||
sal_body_handler_set_content_type_parameter(sbh, "boundary", MultipartBoundary);
|
||||
LinphoneContent *cContent = linphone_content_from_sal_body_handler(sbh);
|
||||
Content *content = L_GET_CPP_PTR_FROM_C_OBJECT(cContent);
|
||||
Content returnContent = *content;
|
||||
linphone_content_unref(cContent);
|
||||
belle_sip_object_unref(mpbh);
|
||||
|
||||
ContentType contentType = ContentType::Multipart;
|
||||
contentType.addParameter("boundary", string(MultipartBoundary));
|
||||
content.setContentType(contentType);
|
||||
|
||||
return content;
|
||||
return returnContent;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class Content;
|
|||
|
||||
namespace ContentManager {
|
||||
std::list<Content> multipartToContentList (const Content &content);
|
||||
Content contentListToMultipart (const std::list<Content> &contents);
|
||||
Content contentListToMultipart (const std::list<Content *> &contents);
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -234,26 +234,28 @@ void multipart_to_list () {
|
|||
generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\r'), generatedStr4.end());
|
||||
generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\n'), generatedStr4.end());
|
||||
ms_message("\n\n----- Generated part 4 -----");
|
||||
ms_message("%s", generatedStr3.c_str());
|
||||
ms_message("%s", generatedStr4.c_str());
|
||||
ms_message("\n\n----- Original part 4 -----");
|
||||
ms_message("%s", originalStr4.c_str());
|
||||
BC_ASSERT_TRUE(originalStr4 == generatedStr4);
|
||||
}
|
||||
|
||||
void list_to_multipart () {
|
||||
ContentType contentType = ContentType("application", "rlmi+xml");
|
||||
contentType.addParameter("charset", "\"UTF-8\"");
|
||||
Content content1;
|
||||
content1.setBody(part1);
|
||||
content1.setContentType(ContentType("application", "rlmi+xml"));
|
||||
content1.setContentType(contentType);
|
||||
Content content2;
|
||||
content2.setBody(part2);
|
||||
content2.setContentType(ContentType("application", "pidf+xml"));
|
||||
content2.setContentType(contentType);
|
||||
Content content3;
|
||||
content3.setBody(part3);
|
||||
content3.setContentType(ContentType("application", "pidf+xml"));
|
||||
content3.setContentType(contentType);
|
||||
Content content4;
|
||||
content4.setBody(part4);
|
||||
content4.setContentType(ContentType("application", "pidf+xml"));
|
||||
list<Content> contents = {content1, content2, content3, content4};
|
||||
content4.setContentType(contentType);
|
||||
list<Content *> contents = {&content1, &content2, &content3, &content4};
|
||||
|
||||
Content multipartContent = ContentManager::contentListToMultipart(contents);
|
||||
string originalStr(multipart);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue