From 813ab614ebdcdadf79af64a9dbde9c12cc3644da Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 11:48:40 +0200 Subject: [PATCH] Use Header class instead of pair in Content + improved tester --- coreapi/bellesip_sal/sal_impl.c | 4 ++ src/c-wrapper/api/c-content.cpp | 15 +++-- src/c-wrapper/internal/c-sal.h | 1 + .../multipart-chat-message-modifier.cpp | 5 +- src/content/content-manager.cpp | 8 +-- src/content/content-p.h | 4 +- src/content/content-type.cpp | 3 +- src/content/content.cpp | 18 ++++-- src/content/content.h | 6 +- src/content/header/header-p.h | 2 + src/content/header/header.cpp | 62 ++++++++++++++++++- src/content/header/header.h | 19 +++++- tester/content-manager-tester.cpp | 26 +++++--- 13 files changed, 140 insertions(+), 33 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 771155918..bdf3683dd 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -446,3 +446,7 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con } return NULL; } + +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler) { + return belle_sip_body_handler_get_headers(BELLE_SIP_BODY_HANDLER(body_handler)); +} diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 2b68cbbde..580c78ca3 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -25,6 +25,7 @@ #include "content/content.h" #include "content/content-type.h" #include "content/header/header-param.h" +#include "content/header/header.h" #include "content/content-manager.h" #include "content/file-content.h" #include "content/file-transfer-content.h" @@ -259,6 +260,13 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * belle_sip_free(body); } + belle_sip_list_t *headers = (belle_sip_list_t *)sal_body_handler_get_headers(body_handler); + while (headers) { + belle_sip_header_t *cHeader = BELLE_SIP_HEADER(headers->data); + LinphonePrivate::Header header = LinphonePrivate::Header(belle_sip_header_get_name(cHeader), belle_sip_header_get_unparsed_value(cHeader)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->addHeader(header); + headers = headers->next; + } if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); } @@ -307,12 +315,7 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { } for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { - belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER( - belle_sip_header_create( - header.first.c_str(), - header.second.c_str() - ) - ); + belle_sip_header_t *additionalHeader = belle_sip_header_parse(header.asString().c_str()); belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), additionalHeader); } diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index ebf373229..f34c4ee5f 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -650,6 +650,7 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i 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); +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler); /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 13041bdb4..8ed8312d9 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -22,6 +22,7 @@ #include "chat/chat-message/chat-message.h" #include "content/content-type.h" +#include "content/header/header.h" #include "content/content-manager.h" #include "content/file-transfer-content.h" @@ -55,8 +56,8 @@ ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_p content->setContentType(c.getContentType()); content->setContentDisposition(c.getContentDisposition()); content->setContentEncoding(c.getContentEncoding()); - for (const pair &pair : c.getHeaders()) { - content->addHeader(pair.first, pair.second); + for (const Header &header : c.getHeaders()) { + content->addHeader(header); } content->setBodyFromUtf8(c.getBodyAsUtf8String()); } else { diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index cbecfaa83..ff341bcf2 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -29,14 +29,14 @@ // ============================================================================= -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - namespace { constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; } +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + // ----------------------------------------------------------------------------- list ContentManager::multipartToContentList (const Content &content) { diff --git a/src/content/content-p.h b/src/content/content-p.h index 167712313..9dc4e1d31 100644 --- a/src/content/content-p.h +++ b/src/content/content-p.h @@ -29,13 +29,15 @@ LINPHONE_BEGIN_NAMESPACE +class Header; + class ContentPrivate : public ClonableObjectPrivate { private: std::vector body; ContentType contentType; ContentDisposition contentDisposition; std::string contentEncoding; - std::list> headers; + std::list
headers; L_DECLARE_PUBLIC(Content); }; diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 4f357f3ee..35391783b 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -179,8 +179,7 @@ string ContentType::asString () const { L_D(); if (isValid()) { string asString = d->type + "/" + d->subType; - for (auto it = std::begin(getParameters()); it!=std::end(getParameters()); ++it) { - HeaderParam param = *it; + for (const auto ¶m : getParameters()) { asString += param.asString(); } return asString; diff --git a/src/content/content.cpp b/src/content/content.cpp index f27e731d6..91761e268 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -25,6 +25,7 @@ #include "content-p.h" #include "content-type.h" +#include "header/header.h" // ============================================================================= @@ -197,10 +198,17 @@ bool Content::isFileTransfer () const { void Content::addHeader (const string &headerName, const string &headerValue) { L_D(); removeHeader(headerName); - d->headers.push_back(make_pair(headerName, headerValue)); + Header header = Header(headerName, headerValue); + d->headers.push_back(header); } -const list> &Content::getHeaders () const { +void Content::addHeader (const Header &header) { + L_D(); + removeHeader(header.getName()); + d->headers.push_back(header); +} + +const list
&Content::getHeaders () const { L_D(); return d->headers; } @@ -212,10 +220,10 @@ void Content::removeHeader (const string &headerName) { d->headers.remove(*it); } -list>::const_iterator Content::findHeader (const string &headerName) const { +list
::const_iterator Content::findHeader (const string &headerName) const { L_D(); - return findIf(d->headers, [&headerName](const pair &pair) { - return pair.first == headerName; + return findIf(d->headers, [&headerName](const Header &header) { + return header.getName() == headerName; }); } diff --git a/src/content/content.h b/src/content/content.h index 94d832643..50066133f 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -35,6 +35,7 @@ LINPHONE_BEGIN_NAMESPACE class ContentDisposition; class ContentType; class ContentPrivate; +class Header; class LINPHONE_PUBLIC Content : public ClonableObject, public AppDataContainer { public: @@ -76,10 +77,11 @@ public: virtual bool isFile () const; virtual bool isFileTransfer () const; - const std::list> &getHeaders () const; + const std::list
&getHeaders () const; void addHeader (const std::string &headerName, const std::string &headerValue); + void addHeader (const Header &header); void removeHeader (const std::string &headerName); - std::list>::const_iterator findHeader (const std::string &headerName) const; + std::list
::const_iterator findHeader (const std::string &headerName) const; protected: explicit Content (ContentPrivate &p); diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h index 3af1e3688..fd4663efe 100644 --- a/src/content/header/header-p.h +++ b/src/content/header/header-p.h @@ -32,6 +32,8 @@ LINPHONE_BEGIN_NAMESPACE class HeaderPrivate : public ClonableObjectPrivate { private: + std::string name; + std::string value; std::list parameters; L_DECLARE_PUBLIC(Header); }; diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 0c8017e60..561b7ce05 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -35,14 +35,64 @@ Header::Header(HeaderPrivate &p) : ClonableObject(p) { } -void Header::cleanParameters() { +Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { + setName(name); + setValue(value); +} + +Header::Header (const string &name, const string &value, const list ¶ms) : Header(name, value) { + addParameters(params); +} + +Header::Header (const Header &other) : Header(other.getName(), other.getValue(), other.getParameters()) {} + +Header &Header::operator= (const Header &other) { + if (this != &other) { + setName(other.getName()); + setValue(other.getValue()); + cleanParameters(); + addParameters(other.getParameters()); + } + + return *this; +} + +bool Header::operator== (const Header &other) const { + return getName() == other.getName() && + getValue() == other.getValue(); +} + +bool Header::operator!= (const Header &other) const { + return !(*this == other); +} + +void Header::setName (const string &name) { + L_D(); + d->name = name; +} + +string Header::getName () const { + L_D(); + return d->name; +} + +void Header::setValue (const string &value) { + L_D(); + d->value = value; +} + +string Header::getValue () const { + L_D(); + return d->value; +} + +void Header::cleanParameters () { L_D(); d->parameters.clear(); } const std::list &Header::getParameters () const { L_D(); - return d->parameters; } @@ -90,4 +140,12 @@ const HeaderParam &Header::getParameter (const std::string ¶mName) const { return Utils::getEmptyConstRefObject(); } +string Header::asString () const { + string asString = getName() + ":" + getValue(); + for (const auto ¶m : getParameters()) { + asString += param.asString(); + } + return asString; +} + LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h index 822839516..a0b8083fe 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -33,7 +33,22 @@ class HeaderParam; class LINPHONE_PUBLIC Header : public ClonableObject { public: - void cleanParameters(); + Header (const std::string &name, const std::string &value); + Header (const std::string &name, const std::string &value, const std::list ¶ms); + Header (const Header &other); + + Header &operator= (const Header &other); + + bool operator== (const Header &other) const; + bool operator!= (const Header &other) const; + + void setName (const std::string &name); + std::string getName () const; + + void setValue (const std::string &value); + std::string getValue () const; + + void cleanParameters (); const std::list &getParameters () const; void addParameter (const std::string ¶mName, const std::string ¶mValue); void addParameter (const HeaderParam ¶m); @@ -43,6 +58,8 @@ public: std::list::const_iterator findParameter (const std::string ¶mName) const; const HeaderParam &getParameter (const std::string ¶mName) const; + std::string asString () const; + protected: explicit Header (HeaderPrivate &p); diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index 296231086..24c4817d5 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -61,6 +61,7 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ +"Content-Encoding: b64\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -78,6 +79,7 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ +"Content-Id: toto;param1=value1;param2;param3=value3\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -98,8 +100,8 @@ static const char* source_multipart = \ static const char* generated_multipart = \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:582" \ +"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:582\r\n\r\n" \ "" \ "" \ " " \ @@ -113,8 +115,8 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:561" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ "" \ "" \ " " \ @@ -131,8 +133,9 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:561" \ +"Content-Encoding:b64\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ "" \ "" \ " " \ @@ -149,8 +152,9 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:546" \ +"Content-Id:toto;param1=value1;param2;param3=value3\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:546\r\n\r\n" \ "" \ "" \ " " \ @@ -326,8 +330,14 @@ void list_to_multipart () { content2.setContentType(contentType); Content content3; content3.setBody(part3); + content3.addHeader("Content-Encoding", "b64"); content3.setContentType(contentType); Content content4; + Header header = Header("Content-Id", "toto"); + header.addParameter("param1", "value1"); + header.addParameter("param2", ""); + header.addParameter("param3", "value3"); + content4.addHeader(header); content4.setBody(part4); content4.setContentType(contentType); list contents = {&content1, &content2, &content3, &content4};