diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 2effcf5ec..85e13205c 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -64,6 +64,7 @@ set(LINPHONE_SOURCE_FILES_C carddav.c chat.c contactprovider.c + content.c dial_plan.c dict.c ec-calibrator.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index c2b2ee53b..4e63d8879 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -39,6 +39,7 @@ liblinphone_la_SOURCES=\ chat_file_transfer.c \ conference.cc conference_private.h \ contactprovider.c contact_providers_priv.h \ + content.c \ dial_plan.c \ dict.c \ ec-calibrator.c \ diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index bdf3683dd..ad11525fb 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -348,29 +348,6 @@ void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subt belle_sip_header_content_type_set_subtype(content_type, subtype); } -const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - return belle_sip_parameters_get_parameter_names(BELLE_SIP_PARAMETERS(content_type)); - } - return NULL; -} - -const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - return belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type), name); - } - return NULL; -} - -void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(content_type), paramName, paramValue); - } -} - const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); if (content_encoding != NULL) { @@ -419,11 +396,6 @@ 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) { @@ -446,7 +418,3 @@ 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/coreapi/callbacks.c b/coreapi/callbacks.c index 126cb41d2..da809bc05 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -17,15 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #include "c-wrapper/internal/c-sal.h" #include "sal/call-op.h" #include "sal/message-op.h" #include "sal/refer-op.h" -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/utils/utils.h" - #include "private.h" #include "mediastreamer2/mediastream.h" #include "linphone/lpconfig.h" diff --git a/coreapi/content.c b/coreapi/content.c new file mode 100644 index 000000000..8d20964bd --- /dev/null +++ b/coreapi/content.c @@ -0,0 +1,243 @@ +/* +linphone +Copyright (C) 2010-2014 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 2 +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + +static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { + if (content->body_handler != NULL) { + sal_body_handler_unref(content->body_handler); + content->body_handler = NULL; + } + content->body_handler = sal_body_handler_ref(body_handler); +} + +static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { + LinphoneContent *content = belle_sip_object_new(LinphoneContent); + belle_sip_object_ref(content); + content->owned_fields = TRUE; + content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ + if (body_handler == NULL) { + linphone_content_set_sal_body_handler(content, sal_body_handler_new()); + } else { + linphone_content_set_sal_body_handler(content, body_handler); + } + return content; +} + +static void linphone_content_destroy(LinphoneContent *content) { + if (content->owned_fields == TRUE) { + if (content->body_handler) sal_body_handler_unref(content->body_handler); + if (content->name) belle_sip_free(content->name); + if (content->key) belle_sip_free(content->key); + /* note : crypto context is allocated/destroyed by the encryption function */ + } +} + +static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { + obj->owned_fields = TRUE; + linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); + if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { + linphone_content_set_type(obj, linphone_content_get_type(ref)); + linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); + } + if (linphone_content_get_encoding(ref) != NULL) { + linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + } + linphone_content_set_name(obj, linphone_content_get_name(ref)); + linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); + if (linphone_content_get_buffer(ref) != NULL) { + linphone_content_set_buffer(obj, linphone_content_get_buffer(ref), linphone_content_get_size(ref)); + } else { + linphone_content_set_size(obj, linphone_content_get_size(ref)); + } +} + + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneContent); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneContent, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_content_destroy, + (belle_sip_object_clone_t)linphone_content_clone, + NULL, // marshal + TRUE +); + + +LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { + return linphone_content_new(); +} + +LinphoneContent * linphone_content_ref(LinphoneContent *content) { + belle_sip_object_ref(content); + return content; +} + +void linphone_content_unref(LinphoneContent *content) { + belle_sip_object_unref(content); +} + +void *linphone_content_get_user_data(const LinphoneContent *content) { + return content->user_data; +} + +void linphone_content_set_user_data(LinphoneContent *content, void *ud) { + content->user_data = ud; +} + +const char * linphone_content_get_type(const LinphoneContent *content) { + return sal_body_handler_get_type(content->body_handler); +} + +void linphone_content_set_type(LinphoneContent *content, const char *type) { + sal_body_handler_set_type(content->body_handler, type); +} + +const char * linphone_content_get_subtype(const LinphoneContent *content) { + return sal_body_handler_get_subtype(content->body_handler); +} + +void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { + sal_body_handler_set_subtype(content->body_handler, subtype); +} + +uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { + return (uint8_t *)sal_body_handler_get_data(content->body_handler); +} + +void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { + void *data; + sal_body_handler_set_size(content->body_handler, size); + data = belle_sip_malloc(size + 1); + memcpy(data, buffer, size); + ((char *)data)[size] = '\0'; + sal_body_handler_set_data(content->body_handler, data); +} + +const char * linphone_content_get_string_buffer(const LinphoneContent *content) { + return (const char *)linphone_content_get_buffer(content); +} + +void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { + sal_body_handler_set_size(content->body_handler, strlen(buffer)); + sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); +} + +size_t linphone_content_get_size(const LinphoneContent *content) { + return sal_body_handler_get_size(content->body_handler); +} + +void linphone_content_set_size(LinphoneContent *content, size_t size) { + sal_body_handler_set_size(content->body_handler, size); +} + +const char * linphone_content_get_encoding(const LinphoneContent *content) { + return sal_body_handler_get_encoding(content->body_handler); +} + +void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { + sal_body_handler_set_encoding(content->body_handler, encoding); +} + +const char * linphone_content_get_name(const LinphoneContent *content) { + return content->name; +} + +void linphone_content_set_name(LinphoneContent *content, const char *name) { + if (content->name != NULL) { + belle_sip_free(content->name); + content->name = NULL; + } + if (name != NULL) { + content->name = belle_sip_strdup(name); + } +} + +size_t linphone_content_get_key_size(const LinphoneContent *content) { + return content->keyLength; +} + +const char * linphone_content_get_key(const LinphoneContent *content) { + return content->key; +} + +void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { + if (content->key != NULL) { + belle_sip_free(content->key); + content->key = NULL; + } + if (key != NULL) { + content->key = reinterpret_cast(belle_sip_malloc(keyLength + 1)); + memcpy(content->key, key, keyLength); + content->key[keyLength] = '\0'; + content->keyLength = keyLength; + } +} + +/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ +void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { + return &(content->cryptoContext); +} + +bool_t linphone_content_is_multipart(const LinphoneContent *content) { + return sal_body_handler_is_multipart(content->body_handler); +} + +LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_get_part(content->body_handler, idx); + return linphone_content_from_sal_body_handler(part_body_handler); +} + +LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); + return linphone_content_from_sal_body_handler(part_body_handler); +} + +const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { + return sal_body_handler_get_header(content->body_handler, header_name); +} + + +LinphoneContent * linphone_content_new(void) { + return linphone_content_new_with_body_handler(NULL); +} + +LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { + return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); +} + +LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { + if (body_handler) { + return linphone_content_new_with_body_handler(body_handler); + } + return NULL; +} + +SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { + if (content == NULL) return NULL; + return content->body_handler; +} diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 6f196721e..5e9ca2abf 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "c-wrapper/c-wrapper.h" @@ -962,7 +961,7 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin const char *subtype = linphone_content_get_subtype(body); if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) { - ms_warning("multipart presence notified but it is not 'multipart/related', instead is '%s/%s'", type, subtype); + ms_warning("multipart presence notified but it is not 'multipart/related'"); return; } diff --git a/coreapi/info.c b/coreapi/info.c index f68bb4522..5b12089bb 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -23,7 +23,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" diff --git a/coreapi/lime.c b/coreapi/lime.c index cdf697b95..4270f9d2a 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" - #include "lime.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -421,8 +419,6 @@ int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, ch int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { bctbx_aes_gcm_context_t *gcmContext; - if (key == NULL) return -1; - if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ /* key contains 192bits of key || 64 bits of Initialisation Vector, no additional data */ gcmContext = bctbx_aes_gcm_context_new(key, 24, NULL, 0, key+24, 8, BCTBX_GCM_DECRYPT); @@ -791,8 +787,8 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; /* check if we have a xml/cipher message to be decrypted */ - if (linphone_chat_message_get_content_type(msg) && - (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || + if (linphone_chat_message_get_content_type(msg) && + (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0)) { errcode = 0; int retval; @@ -897,7 +893,6 @@ int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEn LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); if (!content) return -1; - if (!linphone_content_get_key(content)) { linphone_content_unref(content); return -1; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4a052feca..b0a4347fe 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -18,12 +18,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" #include "linphone/core.h" +#include "linphone/sipsetup.h" #include "linphone/lpconfig.h" #include "linphone/logging.h" -#include "linphone/sipsetup.h" - #include "private.h" #include "logging-private.h" #include "quality_reporting.h" diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 6b6486ab8..3bcfc4d78 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -449,6 +449,17 @@ struct _EchoTester { unsigned int rate; }; +struct _LinphoneContent { + belle_sip_object_t base; + void *user_data; + SalBodyHandler *body_handler; + char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ + char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ + size_t keyLength; /**< Length of key in bytes */ + void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ + bool_t owned_fields; +}; + BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneContent); struct _LinphoneBuffer { diff --git a/coreapi/proxy.c b/coreapi/proxy.c index b797e1d0b..03213da1e 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -25,7 +25,6 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/sipsetup.h" - #include "mediastreamer2/mediastream.h" #include "enum.h" diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index a20b03b8e..571a8faa0 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -21,9 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif -#include "linphone/api/c-content.h" #include "linphone/core.h" - #include "private.h" #include "c-wrapper/internal/c-sal.h" #include "sal/sal.h" diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 04aee8ddd..2e09af5eb 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -33,6 +33,7 @@ set(ROOT_HEADER_FILES chat.h conference.h contactprovider.h + content.h core_utils.h core.h defs.h @@ -84,7 +85,6 @@ set(C_API_HEADER_FILES c-chat-message.h c-chat-room-cbs.h c-chat-room.h - c-content.h c-dial-plan.h c-event-log.h c-magic-search.h diff --git a/include/linphone/Makefile.am b/include/linphone/Makefile.am index 56c2c3dda..dc9488e0b 100644 --- a/include/linphone/Makefile.am +++ b/include/linphone/Makefile.am @@ -14,6 +14,7 @@ linphone_include_HEADERS=\ chat.h \ conference.h \ contactprovider.h \ + content.h \ core.h \ core_utils.h \ defs.h \ diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h index 7044bed6a..039b55246 100644 --- a/include/linphone/api/c-api.h +++ b/include/linphone/api/c-api.h @@ -23,15 +23,14 @@ #include "linphone/utils/general.h" #include "linphone/api/c-address.h" +#include "linphone/api/c-call.h" #include "linphone/api/c-call-cbs.h" #include "linphone/api/c-call-stats.h" -#include "linphone/api/c-call.h" #include "linphone/api/c-callbacks.h" -#include "linphone/api/c-chat-message-cbs.h" #include "linphone/api/c-chat-message.h" -#include "linphone/api/c-chat-room-cbs.h" +#include "linphone/api/c-chat-message-cbs.h" #include "linphone/api/c-chat-room.h" -#include "linphone/api/c-content.h" +#include "linphone/api/c-chat-room-cbs.h" #include "linphone/api/c-dial-plan.h" #include "linphone/api/c-event-log.h" #include "linphone/api/c-participant.h" diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index 312a6fc6f..41f3c669e 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -90,7 +90,7 @@ LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(Linphon * @param initial_content #LinphoneContent initial content. #LinphoneCoreVTable.file_transfer_send is invoked later to notify file transfer progress and collect next chunk of the message if LinphoneContent.data is NULL. * @return a new #LinphoneChatMessage */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent* initial_content); +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent* initial_content); /** * get peer address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom diff --git a/include/linphone/api/c-types.h b/include/linphone/api/c-types.h index b4f629101..f587b77f8 100644 --- a/include/linphone/api/c-types.h +++ b/include/linphone/api/c-types.h @@ -162,12 +162,6 @@ typedef struct _LinphoneMagicSearch LinphoneMagicSearch; **/ typedef struct _LinphoneParticipant LinphoneParticipant; -/** - * The LinphoneContent object holds data that can be embedded in a signaling message. - * @ingroup misc -**/ -typedef struct _LinphoneContent LinphoneContent; - /** * The LinphoneSearchResult object represents a result of a search * @ingroup misc diff --git a/include/linphone/api/c-content.h b/include/linphone/content.h similarity index 83% rename from include/linphone/api/c-content.h rename to include/linphone/content.h index 5cdd27663..78ebc3114 100644 --- a/include/linphone/api/c-content.h +++ b/include/linphone/content.h @@ -1,32 +1,33 @@ /* - * c-content.h - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ +content.h +Copyright (C) 2010-2014 Belledonne Communications SARL -#ifndef _L_C_CONTENT_H_ -#define _L_C_CONTENT_H_ +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 2 +of the License, or (at your option) any later version. -#include "linphone/api/c-types.h" +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef LINPHONE_CONTENT_H_ +#define LINPHONE_CONTENT_H_ + + +#include "linphone/types.h" -// ============================================================================= #ifdef __cplusplus - extern "C" { -#endif // ifdef __cplusplus +extern "C" { +#endif + /** * @addtogroup misc @@ -88,14 +89,6 @@ LINPHONE_PUBLIC const char * linphone_content_get_subtype(const LinphoneContent */ LINPHONE_PUBLIC void linphone_content_set_subtype(LinphoneContent *content, const char *subtype); -/** - * Adds a parameter to the ContentType header. - * @param[in] content LinphoneContent object. - * @param[in] name the name of the parameter to add. - * @param[in] value the value of the parameter to add. - */ -LINPHONE_PUBLIC void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value); - /** * Get the content data buffer, usually a string. * @param[in] content LinphoneContent object. @@ -225,8 +218,9 @@ LINPHONE_PUBLIC void linphone_content_set_key(LinphoneContent *content, const ch * @} */ -#ifdef __cplusplus - } -#endif // ifdef __cplusplus -#endif // ifndef _L_C_CONTENT_H_ \ No newline at end of file +#ifdef __cplusplus +} +#endif + +#endif /* LINPHONE_CONTENT_H_ */ diff --git a/include/linphone/core.h b/include/linphone/core.h index ff15192e9..ded8e3949 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -42,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/call_stats.h" #include "linphone/chat.h" #include "linphone/conference.h" +#include "linphone/content.h" #include "linphone/dictionary.h" #include "linphone/error_info.h" #include "linphone/event.h" diff --git a/include/linphone/types.h b/include/linphone/types.h index 32384b498..9a8ba46c9 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -367,6 +367,12 @@ typedef unsigned int LinphoneContactSearchID; */ LINPHONE_DEPRECATED typedef LinphoneContactSearchID ContactSearchID; +/** + * The LinphoneContent object holds data that can be embedded in a signaling message. + * @ingroup misc +**/ +typedef struct _LinphoneContent LinphoneContent; + /** * Linphone core main object created by function linphone_core_new() . * @ingroup initializing diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7c47abf8..ca182139f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,9 +99,6 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES content/content.h content/file-content.h content/file-transfer-content.h - content/header/header.h - content/header/header-p.h - content/header/header-param.h core/core-accessor.h core/core-listener.h core/core-p.h @@ -176,7 +173,6 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES c-wrapper/api/c-chat-room-cbs.cpp c-wrapper/api/c-chat-room.cpp c-wrapper/api/c-core.cpp - c-wrapper/api/c-content.cpp c-wrapper/api/c-dial-plan.cpp c-wrapper/api/c-event-log.cpp c-wrapper/api/c-magic-search.cpp @@ -226,8 +222,6 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES content/content.cpp content/file-content.cpp content/file-transfer-content.cpp - content/header/header.cpp - content/header/header-param.cpp core/core-accessor.cpp core/core-call.cpp core/core-chat-room.cpp diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 76916ca2b..a616a9659 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -18,7 +18,6 @@ */ #include "linphone/api/c-chat-message.h" -#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "linphone/wrapper_utils.h" @@ -229,7 +228,7 @@ void linphone_chat_message_add_text_content(LinphoneChatMessage *msg, const char LinphonePrivate::ContentType contentType = LinphonePrivate::ContentType::PlainText; content->setContentType(contentType); content->setBody(L_C_TO_STRING(c_content)); - L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(content); + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(*content); } bool_t linphone_chat_message_has_text_content(const LinphoneChatMessage *msg) { @@ -295,9 +294,7 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { } LinphoneContent *linphone_chat_message_get_file_transfer_information(LinphoneChatMessage *msg) { - const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); - if (content) return L_GET_C_BACK_PTR(content); - return NULL; + return L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); } // ============================================================================= diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index b8fa75567..e549964e0 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -355,8 +355,8 @@ const bctbx_list_t *linphone_chat_room_get_composing_addresses (LinphoneChatRoom return cr->composingAddresses; } -LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent *initial_content) { - shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(L_GET_CPP_PTR_FROM_C_OBJECT(initial_content)); +LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(initial_content); LinphoneChatMessage *object = L_INIT(ChatMessage); L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); return object; diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp deleted file mode 100644 index 580c78ca3..000000000 --- a/src/c-wrapper/api/c-content.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * c-content.cpp - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "linphone/api/c-content.h" -#include "linphone/wrapper_utils.h" - -#include "c-wrapper/c-wrapper.h" - -#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" - -// ============================================================================= - -using namespace std; - -L_DECLARE_C_CLONABLE_OBJECT_IMPL(Content, - void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ - mutable char *name; - mutable char *type; - mutable char *subtype; - mutable char *body; - mutable size_t size; - mutable char *encoding; - mutable char *key; -) - -// ============================================================================= -// Reference and user data handling functions. -// ============================================================================= - -LinphoneContent * linphone_content_ref(LinphoneContent *content) { - belle_sip_object_ref(content); - return content; -} - -void linphone_content_unref(LinphoneContent *content) { - belle_sip_object_unref(content); -} - -void *linphone_content_get_user_data(const LinphoneContent *content) { - return L_GET_USER_DATA_FROM_C_OBJECT(content); -} - -void linphone_content_set_user_data(LinphoneContent *content, void *ud) { - return L_SET_USER_DATA_FROM_C_OBJECT(content, ud); -} - -// ============================================================================= - -const char * linphone_content_get_type(const LinphoneContent *content) { - if (content->type) ms_free(content->type); - content->type = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType())); - return content->type; -} - -void linphone_content_set_type(LinphoneContent *content, const char *type) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.setType(L_C_TO_STRING(type)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -const char * linphone_content_get_subtype(const LinphoneContent *content) { - if (content->subtype) ms_free(content->subtype); - content->subtype = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType())); - return content->subtype; -} - -void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.setSubType(L_C_TO_STRING(subtype)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.addParameter(L_C_TO_STRING(name), L_C_TO_STRING(value)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return (uint8_t *)linphone_content_get_string_buffer(content); -} - -void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(buffer, size); -} - -const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - if (content->body) ms_free(content->body); - content->body = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - return content->body; -} - -void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBodyFromUtf8(L_C_TO_STRING(buffer)); -} - -size_t linphone_content_get_size(const LinphoneContent *content) { - size_t size = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getSize(); - if (size == 0) { - size = content->size; - } - return size; -} - -void linphone_content_set_size(LinphoneContent *content, size_t size) { - content->size = size; -} - -const char * linphone_content_get_encoding(const LinphoneContent *content) { - return content->encoding; -} - -void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - if (content->encoding) ms_free(content->encoding); - content->encoding = ms_strdup(encoding); -} - -const char * linphone_content_get_name(const LinphoneContent *content) { - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - const LinphonePrivate::FileContent *fc = static_cast(c); - if (content->name) ms_free(content->name); - content->name = ms_strdup(L_STRING_TO_C(fc->getFileName())); - } else if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - if (content->name) ms_free(content->name); - content->name = ms_strdup(L_STRING_TO_C(ftc->getFileName())); - } - return content->name; -} - -void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->name) ms_free(content->name); - - LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - LinphonePrivate::FileContent *fc = static_cast(c); - fc->setFileName(L_C_TO_STRING(name)); - } else if (c->isFileTransfer()) { - LinphonePrivate::FileTransferContent *ftc = static_cast(c); - ftc->setFileName(L_C_TO_STRING(name)); - } - - content->name = ms_strdup(name); -} - -bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart(); -} - -LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { - SalBodyHandler *part_body_handler; - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - if (!sal_body_handler_is_multipart(body_handler)) { - sal_body_handler_unref(body_handler); - return NULL; - } - part_body_handler = sal_body_handler_get_part(body_handler, idx); - LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); - sal_body_handler_unref(body_handler); - return result; -} - -LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { - SalBodyHandler *part_body_handler; - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - if (!sal_body_handler_is_multipart(body_handler)) { - sal_body_handler_unref(body_handler); - return NULL; - } - part_body_handler = sal_body_handler_find_part_by_header(body_handler, header_name, header_value); - LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); - sal_body_handler_unref(body_handler); - return result; -} - -const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - const char *header = sal_body_handler_get_header(body_handler, header_name); - sal_body_handler_unref(body_handler); - return header; -} - -const char *linphone_content_get_key(const LinphoneContent *content) { - if (content->key) ms_free(content->key); - - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - content->key = ms_strdup(ftc->getFileKeyAsString()); - } - - return content->key; -} - -size_t linphone_content_get_key_size(const LinphoneContent *content) { - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - return ftc->getFileKeySize(); - } - return 0; -} - -void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - LinphonePrivate::FileTransferContent *ftc = static_cast(c); - ftc->setFileKey(key, keyLength); - } -} - -// ============================================================================= -// Private functions. -// ============================================================================= - -static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { - LinphoneContent *content = L_INIT(Content); - content->cryptoContext = NULL; - LinphonePrivate::Content *c = new LinphonePrivate::Content(); - L_SET_CPP_PTR_FROM_C_OBJECT(content, c); - - if (body_handler != NULL) { - linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); - linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); - for (const belle_sip_list_t *params = sal_body_handler_get_content_type_parameters_names(body_handler); params; params = params->next) { - const char *paramName = (const char *)(params->data); - const char *paramValue = sal_body_handler_get_content_type_parameter(body_handler, paramName); - linphone_content_add_content_type_parameter(content, paramName, paramValue); - } - - if (!linphone_content_is_multipart(content)) { - linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); - } else { - belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); - char *body = belle_sip_object_to_string(mpbh); - linphone_content_set_string_buffer(content, body); - 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)); - } - - return content; -} - -LinphoneContent * linphone_content_new(void) { - return linphone_content_new_with_body_handler(NULL); -} - -LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return (LinphoneContent *)(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); -} - -LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { - return linphone_content_new(); -} - -/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ -void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->cryptoContext); -} - -LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { - if (body_handler) { - return linphone_content_new_with_body_handler(body_handler); - } - return NULL; -} - -SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { - if (content == NULL) return NULL; - - SalBodyHandler *body_handler; - LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - - if (contentType.isMultipart()) { - size_t size = linphone_content_get_size(content); - char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - const char *boundary = L_STRING_TO_C(contentType.getParameter("boundary").getValue()); - belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); - body_handler = (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(bh); - } else { - body_handler = sal_body_handler_new(); - sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); - } - - for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { - 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); - } - - sal_body_handler_set_type(body_handler, contentType.getType().c_str()); - sal_body_handler_set_subtype(body_handler, contentType.getSubType().c_str()); - sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); - for (const auto ¶m : contentType.getParameters()) { - sal_body_handler_set_content_type_parameter(body_handler, param.getName().c_str(), param.getValue().c_str()); - } - if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); - - return body_handler; -} diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index c6382b809..e0109ce7c 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -37,7 +37,6 @@ F(ChatMessage, ChatMessage) \ F(AbstractChatRoom, ChatRoom) \ F(Core, Core) \ - F(Content, Content) \ F(DialPlan, DialPlan) \ F(EventLog, EventLog) \ F(MagicSearch, MagicSearch) \ @@ -86,6 +85,7 @@ BELLE_SIP_TYPE_ID(LinphoneConferenceParams), BELLE_SIP_TYPE_ID(LinphoneConfig), BELLE_SIP_TYPE_ID(LinphoneContactProvider), BELLE_SIP_TYPE_ID(LinphoneContactSearch), +BELLE_SIP_TYPE_ID(LinphoneContent), BELLE_SIP_TYPE_ID(LinphoneCoreCbs), BELLE_SIP_TYPE_ID(LinphoneErrorInfo), BELLE_SIP_TYPE_ID(LinphoneEvent), diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index f34c4ee5f..4aeca0042 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -636,9 +636,6 @@ const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); -const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler); -const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name); -void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue); const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); void * sal_body_handler_get_data(const SalBodyHandler *body_handler); @@ -647,10 +644,8 @@ 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); -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/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index 0e17afc88..4c957ed71 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -137,11 +137,11 @@ public: bool hasFileTransferContent () const; const Content* getFileTransferContent () const; - const Content* getFileTransferInformation () const; - void setFileTransferInformation (Content *content); + LinphoneContent *getFileTransferInformation () const; + void setFileTransferInformation (const LinphoneContent *content); - void addContent (Content *content); - void removeContent (Content *content); + void addContent (Content &content); + void removeContent (const Content &content); bool downloadFile (); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 81efcd2ec..0fcde7521 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -19,7 +19,6 @@ #include "object/object-p.h" -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/utils/utils.h" @@ -37,7 +36,6 @@ #include "chat/modifier/multipart-chat-message-modifier.h" #include "conference/participant.h" #include "content/file-content.h" -#include "content/header/header-param.h" #include "content/content.h" #include "core/core.h" #include "core/core-p.h" @@ -241,8 +239,8 @@ const Content* ChatMessagePrivate::getTextContent() const { } bool ChatMessagePrivate::hasFileTransferContent() const { - for (const Content *c : contents) { - if (c->isFileTransfer()) { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::FileTransfer) { return true; } } @@ -250,8 +248,8 @@ bool ChatMessagePrivate::hasFileTransferContent() const { } const Content* ChatMessagePrivate::getFileTransferContent() const { - for (const Content *c : contents) { - if (c->isFileTransfer()) { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::FileTransfer) { return c; } } @@ -376,54 +374,51 @@ void ChatMessagePrivate::setText (const string &text) { } } -const Content *ChatMessagePrivate::getFileTransferInformation () const { +LinphoneContent *ChatMessagePrivate::getFileTransferInformation () const { if (hasFileTransferContent()) { - return getFileTransferContent(); + return getFileTransferContent()->toLinphoneContent(); } for (const Content *c : getContents()) { if (c->isFile()) { FileContent *fileContent = (FileContent *)c; - return fileContent; + return fileContent->toLinphoneContent(); } } return nullptr; } -void ChatMessagePrivate::setFileTransferInformation (Content *content) { +void ChatMessagePrivate::setFileTransferInformation (const LinphoneContent *c_content) { L_Q(); - if (content->isFile()) { - q->addContent(content); - } else { - // This scenario is more likely to happen because the caller is using the C API - LinphoneContent *c_content = L_GET_C_BACK_PTR(content); - FileContent *fileContent = new FileContent(); - fileContent->setContentType(content->getContentType()); - fileContent->setFileSize(linphone_content_get_size(c_content)); // This information is only available from C Content if it was created from C API - fileContent->setFileName(linphone_content_get_name(c_content)); // This information is only available from C Content if it was created from C API - if (!content->isEmpty()) { - fileContent->setBody(content->getBody()); - } - q->addContent(fileContent); + // Create a FileContent, it will create the FileTransferContent at upload time + FileContent *fileContent = new FileContent(); + ContentType contentType(linphone_content_get_type(c_content), linphone_content_get_subtype(c_content)); + fileContent->setContentType(contentType); + fileContent->setFileSize(linphone_content_get_size(c_content)); + fileContent->setFileName(linphone_content_get_name(c_content)); + if (linphone_content_get_string_buffer(c_content)) { + fileContent->setBody(linphone_content_get_string_buffer(c_content)); } + + q->addContent(*fileContent); } bool ChatMessagePrivate::downloadFile () { L_Q(); for (auto &content : getContents()) - if (content->isFileTransfer()) - return q->downloadFile(static_cast(content)); + if (content->getContentType() == ContentType::FileTransfer) + return q->downloadFile(*static_cast(content)); return false; } -void ChatMessagePrivate::addContent (Content *content) { - getContents().push_back(content); +void ChatMessagePrivate::addContent (Content &content) { + getContents().push_back(&content); } -void ChatMessagePrivate::removeContent (Content *content) { - getContents().remove(content); +void ChatMessagePrivate::removeContent (const Content &content) { + getContents().remove(&const_cast(content)); } void ChatMessagePrivate::loadFileTransferUrlFromBodyToContent() { @@ -458,7 +453,7 @@ void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) { Content *content = new Content(); content->setContentType(ContentType::Imdn); content->setBody(Imdn::createXml(imdnId, time, imdnType, reason)); - msg->addContent(content); + msg->addContent(*content); if (reason != LinphoneReasonNone) msg->getPrivate()->setEncryptionPrevented(true); @@ -475,7 +470,7 @@ static void forceUtf8Content (Content &content) { if (contentType != ContentType::PlainText) return; - string charset = contentType.getParameter("charset").getValue(); + string charset = contentType.getParameter(); if (charset.empty()) return; @@ -494,7 +489,7 @@ static void forceUtf8Content (Content &content) { if (!utf8Body.empty()) { // TODO: use move operator if possible in the future! content.setBodyFromUtf8(utf8Body); - contentType.addParameter("charset", "UTF-8"); + contentType.setParameter(string(contentType.getParameter()).replace(begin, end - begin, "UTF-8")); content.setContentType(contentType); } } @@ -606,7 +601,7 @@ LinphoneReason ChatMessagePrivate::receive () { foundSupportContentType = true; break; } else - lError() << "Unsupported content-type: " << c->getContentType(); + lError() << "Unsupported content-type: " << c->getContentType().asString(); } if (!foundSupportContentType) { @@ -765,7 +760,7 @@ void ChatMessagePrivate::send () { auto msgOp = dynamic_cast(op); if (!externalBodyUrl.empty()) { - char *content_type = ms_strdup_printf("message/external-body;access-type=URL;URL=\"%s\"", externalBodyUrl.c_str()); + 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()) { @@ -778,10 +773,10 @@ void ChatMessagePrivate::send () { list::iterator it = contents.begin(); while (it != contents.end()) { Content *content = *it; - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent *)content; it = contents.erase(it); - addContent(fileTransferContent->getFileContent()); + addContent(*fileTransferContent->getFileContent()); delete fileTransferContent; } else { it++; @@ -1019,13 +1014,13 @@ const list &ChatMessage::getContents () const { return d->getContents(); } -void ChatMessage::addContent (Content *content) { +void ChatMessage::addContent (Content &content) { L_D(); if (!d->isReadOnly) d->addContent(content); } -void ChatMessage::removeContent (Content *content) { +void ChatMessage::removeContent (const Content &content) { L_D(); if (!d->isReadOnly) d->removeContent(content); @@ -1095,9 +1090,9 @@ void ChatMessage::sendDisplayNotification () { d->sendImdn(Imdn::Type::Display, LinphoneReasonNone); } -bool ChatMessage::downloadFile(FileTransferContent *fileTransferContent) { +bool ChatMessage::downloadFile(FileTransferContent &fileTransferContent) { L_D(); - return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), fileTransferContent); + return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), &fileTransferContent); } bool ChatMessage::isFileTransferInProgress() { diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index ea1cffedd..2b53bda7d 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -95,8 +95,8 @@ public: void setToBeStored (bool value); const std::list &getContents () const; - void addContent (Content *content); - void removeContent (Content *content); + void addContent (Content &content); + void removeContent (const Content &content); const Content &getInternalContent () const; void setInternalContent (const Content &content); @@ -106,7 +106,7 @@ public: void addCustomHeader (const std::string &headerName, const std::string &headerValue); void removeCustomHeader (const std::string &headerName); - bool downloadFile (FileTransferContent *content); + bool downloadFile (FileTransferContent &content); bool isFileTransferInProgress(); private: diff --git a/src/chat/chat-room/abstract-chat-room.h b/src/chat/chat-room/abstract-chat-room.h index 8a259466f..9662f89b9 100644 --- a/src/chat/chat-room/abstract-chat-room.h +++ b/src/chat/chat-room/abstract-chat-room.h @@ -89,7 +89,8 @@ public: virtual std::shared_ptr createChatMessage () = 0; virtual std::shared_ptr createChatMessage (const std::string &text) = 0; - virtual std::shared_ptr createFileTransferMessage (Content *initialContent) = 0; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + virtual std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) = 0; virtual std::shared_ptr findChatMessage (const std::string &messageId) const = 0; virtual std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index b0b86553f..28106b50d 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -86,7 +86,7 @@ void ChatRoomPrivate::sendIsComposingNotification () { shared_ptr chatMessage = createChatMessage(ChatMessage::Direction::Outgoing); chatMessage->setToBeStored(false); - chatMessage->addContent(content); + chatMessage->addContent(*content); chatMessage->getPrivate()->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent); chatMessage->getPrivate()->addSalCustomHeader("Expires", "0"); @@ -414,11 +414,11 @@ shared_ptr ChatRoom::createChatMessage (const string &text) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody(text); - chatMessage->addContent(content); + chatMessage->addContent(*content); return chatMessage; } -shared_ptr ChatRoom::createFileTransferMessage (Content *initialContent) { +shared_ptr ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { shared_ptr chatMessage = createChatMessage(); chatMessage->getPrivate()->setFileTransferInformation(initialContent); return chatMessage; diff --git a/src/chat/chat-room/chat-room.h b/src/chat/chat-room/chat-room.h index c63e70c7d..40cad5ae3 100644 --- a/src/chat/chat-room/chat-room.h +++ b/src/chat/chat-room/chat-room.h @@ -65,7 +65,8 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - std::shared_ptr createFileTransferMessage (Content *initialContent) override; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/proxy-chat-room.cpp b/src/chat/chat-room/proxy-chat-room.cpp index 2e64bae01..6ddcb4f74 100644 --- a/src/chat/chat-room/proxy-chat-room.cpp +++ b/src/chat/chat-room/proxy-chat-room.cpp @@ -173,7 +173,7 @@ shared_ptr ProxyChatRoom::createChatMessage (const string &text) { return d->chatRoom->createChatMessage(text); } -shared_ptr ProxyChatRoom::createFileTransferMessage (Content *initialContent) { +shared_ptr ProxyChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { L_D(); return d->chatRoom->createFileTransferMessage(initialContent); } diff --git a/src/chat/chat-room/proxy-chat-room.h b/src/chat/chat-room/proxy-chat-room.h index 68ff37e5c..5e4c68d11 100644 --- a/src/chat/chat-room/proxy-chat-room.h +++ b/src/chat/chat-room/proxy-chat-room.h @@ -66,7 +66,8 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - std::shared_ptr createFileTransferMessage (Content *initialContent) override; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 123ef6c66..84753f4ef 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -149,11 +149,9 @@ string Cpim::Message::asString () const { string output; // TODO: Remove cpimHeaders - if (d->cpimHeaders->size() > 0) { - for (const auto &cpimHeader : *d->cpimHeaders) - output += cpimHeader->asString(); - output += "\r\n"; - } + for (const auto &cpimHeader : *d->cpimHeaders) + output += cpimHeader->asString(); + output += "\r\n"; // TODO Remove cpimHeaders if (d->messageHeaders->size() > 0) { diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 03c35fed0..8958c0f82 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -98,7 +98,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptrgetContents().front(); if (content->getContentType() != ContentType::Cpim) { - lError() << "[CPIM] Message is not CPIM but " << content->getContentType(); + lError() << "[CPIM] Message is not CPIM but " << content->getContentType().asString(); return ChatMessageModifier::Result::Skipped; } diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 6bebbfa0b..d9d0767b2 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -17,17 +17,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" - -#include "address/address.h" -#include "bctoolbox/crypto.h" #include "c-wrapper/c-wrapper.h" +#include "address/address.h" #include "chat/chat-message/chat-message-p.h" -#include "chat/chat-room/chat-room-p.h" #include "content/content-type.h" #include "content/content.h" +#include "chat/chat-room/chat-room-p.h" #include "core/core.h" #include "logger/logger.h" +#include "bctoolbox/crypto.h" #include "file-transfer-chat-message-modifier.h" @@ -109,7 +107,7 @@ void FileTransferChatMessageModifier::fileTransferOnProgress ( LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)) { linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)(msg, content, offset, total); } else { @@ -159,7 +157,7 @@ int FileTransferChatMessageModifier::onSendBody ( LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(cbs); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (file_transfer_send_cb) { LinphoneBuffer *lb = file_transfer_send_cb(msg, content, offset, *size); if (lb) { @@ -255,6 +253,12 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } // shall we encrypt the file if (is_file_encryption_enabled && message->getChatRoom()) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = + linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); + if (generate_file_transfer_key_cb) { + generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); + } // temporary storage for the Content-disposition header value : use a generic filename to not leak it // Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg // sended to the @@ -297,31 +301,9 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); if (body && strlen(body) > 0) { FileTransferContent *fileTransferContent = new FileTransferContent(); - fileTransferContent->setContentType(ContentType::FileTransfer); - - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); - bool_t is_file_encryption_enabled = FALSE; - if (imee && message->getChatRoom()) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = - linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs); - if (is_encryption_enabled_for_file_transfer_cb) { - is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom())); - } - } - if (is_file_encryption_enabled && message->getChatRoom()) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = - linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); - if (generate_file_transfer_key_cb) { - generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); - } - } - // if we have an encryption key for the file, we must insert it into the msg and restore the correct filename - const char *content_key = fileTransferContent->getFileKeyAsString(); - size_t content_key_size = fileTransferContent->getFileKey().size(); - if (content_key_size > 0) { + string content_key = currentFileContentToTransfer->getFileKey(); + if (!content_key.empty()) { // parse the msg body xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); @@ -334,15 +316,16 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); // this is the node we are looking for : add a file-key children node if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { + size_t content_key_size = content_key.length(); // need to parse the children node to update the file-name one xmlNodePtr fileInfoNodeChildren = cur->xmlChildrenNode; // convert key to base64 size_t b64Size; - bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key, content_key_size); + bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); unsigned char *keyb64 = (unsigned char *)ms_malloc0(b64Size + 1); int xmlStringLength; - bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key, content_key_size); + bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); keyb64[b64Size] = '\0'; // libxml need a null terminated string // add the node containing the key to the file-info node @@ -378,10 +361,11 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } FileContent *fileContent = currentFileContentToTransfer; + fileTransferContent->setContentType(ContentType::FileTransfer); fileTransferContent->setFileContent(fileContent); - message->getPrivate()->removeContent(fileContent); - message->getPrivate()->addContent(fileTransferContent); + message->getPrivate()->removeContent(*fileContent); + message->getPrivate()->addContent(*fileTransferContent); message->getPrivate()->setState(ChatMessage::State::FileTransferDone); releaseHttpRequest(); @@ -575,13 +559,13 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode (const share fileTransferContent->setContentType(internalContent.getContentType()); fileTransferContent->setBody(internalContent.getBody()); fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); - message->addContent(fileTransferContent); + message->addContent(*fileTransferContent); return ChatMessageModifier::Result::Done; } for (Content *content : message->getContents()) { - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent *)content; fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); } } @@ -650,7 +634,8 @@ static void createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferC uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); // decode the key into local key buffer bctbx_base64_decode(keyBuffer, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); - fileTransferContent->setFileKey((const char *)keyBuffer, keyLength); + string key = string((const char *)keyBuffer); + fileContent->setFileKey(key); // duplicate key value into the linphone content private structure xmlFree(keyb64); free(keyBuffer); @@ -714,7 +699,7 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); @@ -755,7 +740,7 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new(); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); @@ -771,12 +756,12 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (retval <= 0 && message->getState() != ChatMessage::State::FileTransferError) { // Remove the FileTransferContent from the message and store the FileContent FileContent *fileContent = currentFileContentToTransfer; - message->getPrivate()->addContent(fileContent); + message->getPrivate()->addContent(*fileContent); for (Content *content : message->getContents()) { - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent*)content; if (fileTransferContent->getFileContent() == fileContent) { - message->getPrivate()->removeContent(content); + message->getPrivate()->removeContent(*content); delete fileTransferContent; break; } @@ -829,7 +814,7 @@ void FileTransferChatMessageModifier::processResponseHeadersFromGetFile (const b } else { lWarning() << "No file transfer information for msg [" << this << "]: creating..."; FileContent *content = createFileTransferInformationFromHeaders(response); - message->addContent(content); + message->addContent(*content); } size_t body_size = 0; diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 8ed8312d9..243cb32e1 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -20,11 +20,13 @@ // 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/header.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" @@ -41,30 +43,90 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode ( if (message->getContents().size() <= 1) return ChatMessageModifier::Result::Skipped; - Content content = ContentManager::contentListToMultipart(message->getContents()); - message->setInternalContent(content); + 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.setParameter("boundary=" + boundary); + newContent.setContentType(newContentType); + newContent.setBody(multipartMessage.str()); + message->setInternalContent(newContent); return ChatMessageModifier::Result::Done; } ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { - 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 Header &header : c.getHeaders()) { - content->addHeader(header); - } - content->setBodyFromUtf8(c.getBodyAsUtf8String()); - } else { - content = new Content(c); - } - message->addContent(content); + if (message->getInternalContent().getContentType().getType() == "multipart") { + string boundary = message->getInternalContent().getContentType().getParameter(); + if (boundary.empty()) { + lError() << "Boundary parameter of content-type not found: " << message->getInternalContent().getContentType().asString(); + return ChatMessageModifier::Result::Error; } + + size_t pos = boundary.find("="); + if (pos == string::npos) { + lError() << "Parameter seems invalid: " << boundary; + return ChatMessageModifier::Result::Error; + } + boundary = "--" + boundary.substr(pos + 1); + lInfo() << "Multipart boundary is " << boundary; + + const vector body = message->getInternalContent().getBody(); + string contentsString(body.begin(), body.end()); + + 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; + } + 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(); + } + start = end + boundary.length() + 2; // 2 is the size of \r\n + } while (end != string::npos); + return ChatMessageModifier::Result::Done; } return ChatMessageModifier::Result::Skipped; diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp index 8f56e74e5..9847a93e9 100644 --- a/src/conference/handlers/local-conference-event-handler.cpp +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -19,7 +19,6 @@ #include -#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "conference/local-conference.h" @@ -107,7 +106,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) static_cast(notifyId) ); - list contents; + list contents; for (const auto &eventLog : events) { Content content; content.setContentType(ContentType("application","conference-info")); @@ -181,7 +180,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) continue; } content.setBody(body); - contents.push_back(&content); + contents.push_back(content); } if (contents.empty()) diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index ea125826e..668f0df33 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -19,18 +19,19 @@ #include -#include "linphone/api/c-content.h" -#include "linphone/core.h" +#include "c-wrapper/c-wrapper.h" #include "address/address-p.h" -#include "c-wrapper/c-wrapper.h" #include "call/call-p.h" #include "conference/params/call-session-params-p.h" #include "conference/session/call-session-p.h" #include "conference/session/call-session.h" #include "core/core-p.h" + #include "logger/logger.h" +#include "linphone/core.h" + #include "private.h" using namespace std; diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index ff341bcf2..94ee69ce9 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -19,68 +19,101 @@ #include -#include "c-wrapper/c-wrapper.h" - -#include "linphone/api/c-content.h" - #include "content-manager.h" #include "content-type.h" #include "content/content.h" // ============================================================================= -namespace { - constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; -} - using namespace std; LINPHONE_BEGIN_NAMESPACE +namespace { + constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; +} + // ----------------------------------------------------------------------------- list ContentManager::multipartToContentList (const Content &content) { - LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); - SalBodyHandler *sbh = sal_body_handler_ref(sal_body_handler_from_content(cContent)); + 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); list contents; - 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); + 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); + belle_sip_header_content_type_t *partContentType = nullptr; + 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) { + partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header); + break; + } + } + + Content content; + content.setBody(static_cast( + belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)) + )); + content.setContentType(ContentType( + belle_sip_header_content_type_get_type(partContentType), + belle_sip_header_content_type_get_subtype(partContentType) + )); + contents.push_back(move(content)); } - sal_body_handler_unref(sbh); - linphone_content_unref(cContent); + belle_sip_object_unref(mpbh); return contents; } -Content ContentManager::contentListToMultipart (const list &contents) { +Content ContentManager::contentListToMultipart (const list &contents) { belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new( nullptr, nullptr, nullptr, MultipartBoundary ); - mpbh = (belle_sip_multipart_body_handler_t *)belle_sip_object_ref(mpbh); + belle_sip_object_ref(mpbh); - 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); + 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)); } - 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); + char *desc = belle_sip_object_to_string(mpbh); + Content content; + content.setBody(desc); + belle_sip_free(desc); belle_sip_object_unref(mpbh); - return returnContent; + ContentType contentType = ContentType::Multipart; + contentType.setParameter("boundary=" + string(MultipartBoundary)); + content.setContentType(contentType); + + return content; } LINPHONE_END_NAMESPACE diff --git a/src/content/content-manager.h b/src/content/content-manager.h index 4d19076f0..8251d3c3b 100644 --- a/src/content/content-manager.h +++ b/src/content/content-manager.h @@ -32,7 +32,7 @@ class Content; namespace ContentManager { std::list multipartToContentList (const Content &content); - Content contentListToMultipart (const std::list &contents); + Content contentListToMultipart (const std::list &contents); } LINPHONE_END_NAMESPACE diff --git a/src/content/content-p.h b/src/content/content-p.h index 9dc4e1d31..167712313 100644 --- a/src/content/content-p.h +++ b/src/content/content-p.h @@ -29,15 +29,13 @@ 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 7aee05247..78c356af6 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -20,8 +20,7 @@ #include "linphone/utils/utils.h" #include "content-type.h" -#include "header/header-p.h" -#include "header/header-param.h" +#include "object/clonable-object-p.h" // ============================================================================= @@ -31,10 +30,11 @@ LINPHONE_BEGIN_NAMESPACE // ----------------------------------------------------------------------------- -class ContentTypePrivate : public HeaderPrivate { +class ContentTypePrivate : public ClonableObjectPrivate { public: string type; string subType; + string parameter; }; // ----------------------------------------------------------------------------- @@ -52,7 +52,7 @@ const ContentType ContentType::Sdp("application/sdp"); // ----------------------------------------------------------------------------- -ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { +ContentType::ContentType (const string &contentType) : ClonableObject(*new ContentTypePrivate) { L_D(); size_t pos = contentType.find('/'); @@ -68,23 +68,11 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr d->type.clear(); } - if (posParam != string::npos) { - string params = contentType.substr(posParam + 1); - string token; - do { - posParam = params.find(";"); - if (posParam == string::npos) { - token = params; - } else { - token = params.substr(0, posParam); - } - addParameter(HeaderParam(token)); - params.erase(0, posParam + 1); - } while (posParam != std::string::npos); - } + if (posParam != string::npos) + setParameter(Utils::trim(contentType.substr(posParam + 1))); } -ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { +ContentType::ContentType (const string &type, const string &subType) : ClonableObject(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) @@ -94,35 +82,22 @@ ContentType::ContentType (const string &type, const string &subType) : Header(*n ContentType::ContentType ( const string &type, const string &subType, - const HeaderParam ¶meter -) : Header(*new ContentTypePrivate) { + const string ¶meter +) : ClonableObject(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) d->type.clear(); - addParameter(parameter); + setParameter(parameter); } -ContentType::ContentType ( - const string &type, - const string &subType, - const std::list ¶meters -) : Header(*new ContentTypePrivate) { - L_D(); - - if (setType(type) && !setSubType(subType)) - d->type.clear(); - addParameters(parameters); -} - -ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameters()) {} +ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameter()) {} ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { setType(other.getType()); setSubType(other.getSubType()); - cleanParameters(); - addParameters(other.getParameters()); + setParameter(other.getParameter()); } return *this; @@ -130,7 +105,8 @@ ContentType &ContentType::operator= (const ContentType &other) { bool ContentType::operator== (const ContentType &other) const { return getType() == other.getType() && - getSubType() == other.getSubType(); + getSubType() == other.getSubType() && + getParameter() == other.getParameter(); } bool ContentType::operator!= (const ContentType &other) const { @@ -146,7 +122,6 @@ bool ContentType::setType (const string &type) { L_D(); if (type.find('/') == string::npos) { d->type = Utils::stringToLower(type); - setValue(d->type + "/" + d->subType); return true; } return false; @@ -161,12 +136,21 @@ bool ContentType::setSubType (const string &subType) { L_D(); if (subType.find('/') == string::npos) { d->subType = Utils::stringToLower(subType); - setValue(d->type + "/" + d->subType); return true; } return false; } +const string &ContentType::getParameter () const { + L_D(); + return d->parameter; +} + +void ContentType::setParameter (const string ¶meter) { + L_D(); + d->parameter = parameter; +} + bool ContentType::isEmpty () const { L_D(); return d->type.empty() && d->subType.empty(); @@ -177,10 +161,18 @@ bool ContentType::isValid () const { return !d->type.empty() && !d->subType.empty(); } -bool ContentType::isMultipart() const { - return getType() == "multipart"; +string ContentType::asString () const { + L_D(); + if (isValid()) { + string asString = d->type + "/" + d->subType; + if (!d->parameter.empty()) + asString += "; " + d->parameter; + return asString; + } + return ""; } + bool ContentType::isFile () const { // TODO Remove when not needed anymore in step 2.1 of maindb return isFile(*this); diff --git a/src/content/content-type.h b/src/content/content-type.h index c9aa7af77..b13063115 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -21,21 +21,18 @@ #define _L_CONTENT_TYPE_H_ #include "object/clonable-object.h" -#include "header/header.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE class ContentTypePrivate; -class HeaderParam; -class LINPHONE_PUBLIC ContentType : public Header { +class LINPHONE_PUBLIC ContentType : public ClonableObject { public: explicit ContentType (const std::string &contentType = ""); ContentType (const std::string &type, const std::string &subType); - ContentType (const std::string &type, const std::string &subType, const HeaderParam ¶meter); - ContentType (const std::string &type, const std::string &subType, const std::list ¶meters); + ContentType (const std::string &type, const std::string &subType, const std::string ¶meter); ContentType (const ContentType &other); ContentType &operator= (const ContentType &other); @@ -58,7 +55,10 @@ public: const std::string &getSubType () const; bool setSubType (const std::string &subType); - bool isMultipart() const; + const std::string &getParameter () const; + void setParameter (const std::string ¶meter); + + std::string asString () const; static bool isFile (const ContentType &contentType); diff --git a/src/content/content.cpp b/src/content/content.cpp index ad74de27f..aa30503d4 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -25,7 +25,6 @@ #include "content-p.h" #include "content-type.h" -#include "header/header.h" // ============================================================================= @@ -191,37 +190,17 @@ bool Content::isFile () const { return false; } -bool Content::isFileTransfer () const { - return false; -} - void Content::addHeader (const string &headerName, const string &headerValue) { L_D(); removeHeader(headerName); - Header header = Header(headerName, headerValue); - d->headers.push_back(header); + d->headers.push_back(make_pair(headerName, headerValue)); } -void Content::addHeader (const Header &header) { - L_D(); - removeHeader(header.getName()); - d->headers.push_back(header); -} - -const list
&Content::getHeaders () const { +const list> &Content::getHeaders () const { L_D(); return d->headers; } -const Header &Content::getHeader (const string &headerName) const { - L_D(); - list
::const_iterator it = findHeader(headerName); - if (it != d->headers.cend()) { - return *it; - } - return Utils::getEmptyConstRefObject
(); -} - void Content::removeHeader (const string &headerName) { L_D(); auto it = findHeader(headerName); @@ -229,11 +208,18 @@ 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 Header &header) { - return header.getName() == headerName; + return findIf(d->headers, [&headerName](const pair &pair) { + return pair.first == headerName; }); } +LinphoneContent *Content::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + return content; +} + LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h index 3c29d3a1a..c570670c5 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -35,7 +35,6 @@ LINPHONE_BEGIN_NAMESPACE class ContentDisposition; class ContentType; class ContentPrivate; -class Header; class LINPHONE_PUBLIC Content : public ClonableObject, public AppDataContainer { public: @@ -75,14 +74,14 @@ public: bool isEmpty () const; virtual bool isFile () const; - virtual bool isFileTransfer () const; - const std::list
&getHeaders () const; - const Header &getHeader (const std::string &headerName) 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; + + // TODO: Remove me later. + virtual LinphoneContent *toLinphoneContent () const; protected: explicit Content (ContentPrivate &p); diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp index b4a0ef0fb..851d935d3 100644 --- a/src/content/file-content.cpp +++ b/src/content/file-content.cpp @@ -36,6 +36,7 @@ public: string fileName; string filePath; size_t fileSize = 0; + string fileKey; }; // ----------------------------------------------------------------------------- @@ -47,6 +48,7 @@ FileContent::FileContent (const FileContent &other) : Content(*new FileContentPr d->fileName = other.getFileName(); d->filePath = other.getFilePath(); d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); } FileContent::FileContent (FileContent &&other) : Content(*new FileContentPrivate) { @@ -54,14 +56,18 @@ FileContent::FileContent (FileContent &&other) : Content(*new FileContentPrivate d->fileName = move(other.getPrivate()->fileName); d->filePath = move(other.getPrivate()->filePath); d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); } FileContent &FileContent::operator= (const FileContent &other) { L_D(); + if (this != &other) { Content::operator=(other); d->fileName = other.getFileName(); d->filePath = other.getFilePath(); d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); + } return *this; } @@ -72,6 +78,7 @@ FileContent &FileContent::operator= (FileContent &&other) { d->fileName = move(other.getPrivate()->fileName); d->filePath = move(other.getPrivate()->filePath); d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); return *this; } @@ -80,7 +87,8 @@ bool FileContent::operator== (const FileContent &other) const { return Content::operator==(other) && d->fileName == other.getFileName() && d->filePath == other.getFilePath() && - d->fileSize == other.getFileSize(); + d->fileSize == other.getFileSize() && + d->fileKey == other.getFileKey(); } void FileContent::setFileSize (size_t size) { @@ -113,12 +121,28 @@ const string &FileContent::getFilePath () const { return d->filePath; } +void FileContent::setFileKey (const string &key) { + L_D(); + d->fileKey = key; +} + +const string &FileContent::getFileKey () const { + L_D(); + return d->fileKey; +} + bool FileContent::isFile () const { return true; } -bool FileContent::isFileTransfer () const { - return false; +LinphoneContent *FileContent::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + linphone_content_set_name(content, getFileName().c_str()); + linphone_content_set_size(content, getFileSize()); + linphone_content_set_key(content, getFileKey().c_str(), getFileKey().size()); + return content; } LINPHONE_END_NAMESPACE diff --git a/src/content/file-content.h b/src/content/file-content.h index 081a5898a..645fc6312 100644 --- a/src/content/file-content.h +++ b/src/content/file-content.h @@ -48,8 +48,13 @@ public: void setFilePath (const std::string &path); const std::string &getFilePath () const; + void setFileKey (const std::string &key); + const std::string &getFileKey () const; + bool isFile () const override; - bool isFileTransfer () const override; + + // TODO: Remove me later. + LinphoneContent *toLinphoneContent () const override; private: L_DECLARE_PRIVATE(FileContent); diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index e2fe5ab4f..4bc5ed691 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -38,7 +38,6 @@ public: string filePath; FileContent *fileContent = nullptr; size_t fileSize = 0; - std::vector fileKey; }; // ----------------------------------------------------------------------------- @@ -52,7 +51,6 @@ FileTransferContent::FileTransferContent (const FileTransferContent &other) : Co d->filePath = other.getFilePath(); d->fileContent = other.getFileContent(); d->fileSize = other.getFileSize(); - d->fileKey = other.getFileKey(); } FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content(*new FileTransferContentPrivate) { @@ -62,7 +60,6 @@ FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content d->filePath = move(other.getPrivate()->filePath); d->fileContent = move(other.getPrivate()->fileContent); d->fileSize = move(other.getPrivate()->fileSize); - d->fileKey = move(other.getPrivate()->fileKey); } FileTransferContent &FileTransferContent::operator= (const FileTransferContent &other) { @@ -74,7 +71,6 @@ FileTransferContent &FileTransferContent::operator= (const FileTransferContent & d->filePath = other.getFilePath(); d->fileContent = other.getFileContent(); d->fileSize = other.getFileSize(); - d->fileKey = other.getFileKey(); } return *this; @@ -88,8 +84,6 @@ FileTransferContent &FileTransferContent::operator= (FileTransferContent &&other d->filePath = move(other.getPrivate()->filePath); d->fileContent = move(other.getPrivate()->fileContent); d->fileSize = move(other.getPrivate()->fileSize); - d->fileKey = move(other.getPrivate()->fileKey); - return *this; } @@ -152,32 +146,17 @@ size_t FileTransferContent::getFileSize () const { return d->fileSize; } -void FileTransferContent::setFileKey (const char *key, size_t size) { - L_D(); - d->fileKey = vector(key, key + size); -} - -const vector &FileTransferContent::getFileKey () const { - L_D(); - return d->fileKey; -} - -const char *FileTransferContent::getFileKeyAsString() const { - L_D(); - return d->fileKey.data(); -} - -size_t FileTransferContent::getFileKeySize() const { - L_D(); - return d->fileKey.size(); +LinphoneContent *FileTransferContent::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + linphone_content_set_name(content, getFileName().c_str()); + linphone_content_set_size(content, getFileSize()); + return content; } bool FileTransferContent::isFile () const { return false; } -bool FileTransferContent::isFileTransfer () const { - return true; -} - LINPHONE_END_NAMESPACE diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index 1904e11c5..59b4cc125 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -20,8 +20,6 @@ #ifndef _L_FILE_TRANSFER_CONTENT_H_ #define _L_FILE_TRANSFER_CONTENT_H_ -#include - #include "content.h" // ============================================================================= @@ -57,13 +55,10 @@ public: void setFileSize (size_t size); size_t getFileSize () const; - void setFileKey (const char *key, size_t size); - const std::vector &getFileKey () const; - const char *getFileKeyAsString () const; - size_t getFileKeySize() const; - bool isFile () const override; - bool isFileTransfer () const override; + + // TODO: Remove me later. + LinphoneContent *toLinphoneContent () const override; private: L_DECLARE_PRIVATE(FileTransferContent); diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h deleted file mode 100644 index fd4663efe..000000000 --- a/src/content/header/header-p.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * header-p.h - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_P_H_ -#define _L_HEADER_P_H_ - -#include - -#include "object/clonable-object-p.h" - -#include "header.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderPrivate : public ClonableObjectPrivate { -private: - std::string name; - std::string value; - std::list parameters; - L_DECLARE_PUBLIC(Header); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_P_H_ \ No newline at end of file diff --git a/src/content/header/header-param.cpp b/src/content/header/header-param.cpp deleted file mode 100644 index 9605a2f84..000000000 --- a/src/content/header/header-param.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * header-param.cpp - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "linphone/utils/utils.h" - -#include "header-param.h" -#include "object/clonable-object-p.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -class HeaderParamPrivate : public ClonableObjectPrivate { -public: - string name; - string value; -}; - -// ----------------------------------------------------------------------------- - -HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParamPrivate) { - size_t pos = param.find("="); - size_t end = param.length(); - - if (pos == string::npos) { - setName(param); - } else { - setName(param.substr(0, pos)); - setValue(param.substr(pos + 1, end - (pos + 1))); - } -} - -HeaderParam::HeaderParam (const string &name, const string &value) : ClonableObject(*new HeaderParamPrivate) { - setName(name); - setValue(value); -} - -HeaderParam::HeaderParam (const HeaderParam &other) : HeaderParam(other.getName(), other.getValue()) {} - -HeaderParam &HeaderParam::operator= (const HeaderParam &other) { - if (this != &other) { - setName(other.getName()); - setValue(other.getValue()); - } - - return *this; -} - -bool HeaderParam::operator== (const HeaderParam &other) const { - return getName() == other.getName() && - getValue() == other.getValue(); -} - -bool HeaderParam::operator!= (const HeaderParam &other) const { - return !(*this == other); -} - -const string &HeaderParam::getName () const { - L_D(); - return d->name; -} - -bool HeaderParam::setName (const string &name) { - L_D(); - d->name = name; - return true; -} - -const string &HeaderParam::getValue () const { - L_D(); - return d->value; -} - -bool HeaderParam::setValue (const string &value) { - L_D(); - d->value = value; - return true; -} - -string HeaderParam::asString () const { - L_D(); - string asString = ";" + d->name; - if (!d->value.empty()) - asString += "=" + d->value; - return asString; -} - -LINPHONE_END_NAMESPACE diff --git a/src/content/header/header-param.h b/src/content/header/header-param.h deleted file mode 100644 index a9471b486..000000000 --- a/src/content/header/header-param.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * header-param.h - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_PARAM_H_ -#define _L_HEADER_PARAM_H_ - -#include "object/clonable-object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderParamPrivate; - -class LINPHONE_PUBLIC HeaderParam : public ClonableObject { -public: - explicit HeaderParam (const std::string &header = ""); - HeaderParam (const std::string &name, const std::string &value); - HeaderParam (const HeaderParam &other); - - HeaderParam &operator= (const HeaderParam &other); - - bool operator== (const HeaderParam &other) const; - bool operator!= (const HeaderParam &other) const; - - // Delete these operators to prevent putting complicated content-type strings - // in the code. Instead define static const HeaderParam objects below. - bool operator== (const std::string &other) const = delete; - bool operator!= (const std::string &other) const = delete; - - const std::string &getName () const; - bool setName (const std::string &name); - - const std::string &getValue () const; - bool setValue (const std::string &value); - - std::string asString () const; - -private: - L_DECLARE_PRIVATE(HeaderParam); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_PARAM_H_ diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp deleted file mode 100644 index 5924cdf5b..000000000 --- a/src/content/header/header.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * header.cpp - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "linphone/utils/utils.h" -#include "linphone/utils/algorithm.h" - -#include "header-p.h" -#include "header-param.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -Header::Header(HeaderPrivate &p) : ClonableObject(p) {} - -Header::Header() : ClonableObject(*new HeaderPrivate) {} - -Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { - setName(name); - - size_t posParam = value.find(";"); - if (posParam == string::npos) { - setValue(value); - return; - } - - string parsedValue = value.substr(0, posParam); - string params = value.substr(posParam + 1); - string token; - do { - posParam = params.find(";"); - if (posParam == string::npos) { - token = params; - } else { - token = params.substr(0, posParam); - } - addParameter(HeaderParam(token)); - params.erase(0, posParam + 1); - } while (posParam != std::string::npos); - - setValue(parsedValue); -} - -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 list &Header::getParameters () const { - L_D(); - return d->parameters; -} - -void Header::addParameter (const string ¶mName, const string ¶mValue) { - addParameter(HeaderParam(paramName, paramValue)); -} - -void Header::addParameter (const HeaderParam ¶m) { - L_D(); - removeParameter(param); - d->parameters.push_back(param); -} - -void Header::addParameters(const list ¶ms) { - for (auto it = std::begin(params); it!=std::end(params); ++it) { - HeaderParam param = *it; - addParameter(param.getName(), param.getValue()); - } -} - -void Header::removeParameter (const string ¶mName) { - L_D(); - auto it = findParameter(paramName); - if (it != d->parameters.cend()) - d->parameters.remove(*it); -} - -void Header::removeParameter (const HeaderParam ¶m) { - removeParameter(param.getName()); -} - -list::const_iterator Header::findParameter (const string ¶mName) const { - L_D(); - return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { - return param.getName() == paramName; - }); -} - -const HeaderParam &Header::getParameter (const string ¶mName) const { - L_D(); - list::const_iterator it = findParameter(paramName); - if (it != d->parameters.cend()) { - return *it; - } - return Utils::getEmptyConstRefObject(); -} - -string Header::asString () const { - stringstream asString; - if (!getName().empty()) { - asString << getName() << ":"; - } - asString << getValue(); - for (const auto ¶m : getParameters()) { - asString << param.asString(); - } - return asString.str(); -} - -ostream &operator<<(ostream& stream, const Header& header) { - stream << header.asString(); - return stream; -} - -LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h deleted file mode 100644 index 583572523..000000000 --- a/src/content/header/header.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * header.h - * Copyright (C) 2010-2018 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_H_ -#define _L_HEADER_H_ - -#include - -#include "object/clonable-object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderPrivate; -class HeaderParam; - -class LINPHONE_PUBLIC Header : public ClonableObject { -public: - Header (); - 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); - void addParameters(const std::list ¶ms); - void removeParameter (const std::string ¶mName); - void removeParameter (const HeaderParam ¶m); - std::list::const_iterator findParameter (const std::string ¶mName) const; - const HeaderParam &getParameter (const std::string ¶mName) const; - - std::string asString () const; - friend std::ostream &operator<<(std::ostream&, const Header&); - -protected: - explicit Header (HeaderPrivate &p); - -private: - L_DECLARE_PRIVATE(Header); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_H_ diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index ac26bff98..e6cfd375d 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -2226,7 +2226,7 @@ void MainDb::loadChatMessageContents (const shared_ptr &chatMessage string data; fetchContentAppData(session, *content, contentId, data); } - chatMessage->addContent(content); + chatMessage->addContent(*content); } // 2 - Load external body url from body into FileTransferContent if needed. diff --git a/src/sal/op.cpp b/src/sal/op.cpp index 497a7a99b..e5e211f3b 100644 --- a/src/sal/op.cpp +++ b/src/sal/op.cpp @@ -1029,18 +1029,12 @@ void SalOp::process_incoming_message(const belle_sip_request_event_t *event) { /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; salmsg.url=NULL; - - char buffer[1024]; - size_t offset = 0; - belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buffer, 1024, &offset); - buffer[offset] = '\0'; - salmsg.content_type = ms_strdup_printf("%s/%s%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), buffer); + salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); 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); diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index e07217934..b14e28572 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -199,7 +199,7 @@ set(SOURCE_FILES_C set(SOURCE_FILES_CXX clonable-object-tester.cpp conference-event-tester.cpp - contents-tester.cpp + content-manager-tester.cpp cpim-tester.cpp main-db-tester.cpp multipart-tester.cpp diff --git a/tester/contents-tester.cpp b/tester/content-manager-tester.cpp similarity index 62% rename from tester/contents-tester.cpp rename to tester/content-manager-tester.cpp index 99ecee08d..e21cc6399 100644 --- a/tester/contents-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -21,15 +21,13 @@ #include "content/content-manager.h" #include "content/content-type.h" #include "content/content.h" -#include "content/header/header-param.h" #include "liblinphone_tester.h" #include "tester_utils.h" -#include "logger/logger.h" using namespace LinphonePrivate; using namespace std; -static const char* source_multipart = \ +static const char* multipart = \ "-----------------------------14737809831466499882746641449\r\n" \ "Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ @@ -62,7 +60,6 @@ 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" \ "" \ "" \ @@ -80,7 +77,6 @@ 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" \ "" \ "" \ @@ -99,80 +95,6 @@ static const char* source_multipart = \ "" \ "-----------------------------14737809831466499882746641449--\r\n"; -static const char* generated_multipart = \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:582\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:561\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Encoding:b64\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:561\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"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" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:someone@sip.linphone.org" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449--\r\n"; - static const char* part1 = \ "" \ "" \ @@ -240,7 +162,7 @@ static const char* part4 = \ void multipart_to_list () { Content multipartContent; - multipartContent.setBody(source_multipart); + multipartContent.setBody(multipart); multipartContent.setContentType(ContentType("multipart", "related")); list contents = ContentManager::multipartToContentList(multipartContent); @@ -298,7 +220,6 @@ void multipart_to_list () { ms_message("\n\n----- Original part 3 -----"); ms_message("%s", originalStr3.c_str()); BC_ASSERT_TRUE(originalStr3 == generatedStr3); - BC_ASSERT_TRUE(content3.getHeader("Content-Encoding").getValue() == "b64"); Content content4 = contents.front(); contents.pop_front(); @@ -313,43 +234,29 @@ 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", generatedStr4.c_str()); + ms_message("%s", generatedStr3.c_str()); ms_message("\n\n----- Original part 4 -----"); ms_message("%s", originalStr4.c_str()); BC_ASSERT_TRUE(originalStr4 == generatedStr4); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getValue() == "toto"); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param1").getValue() == "value1"); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param2").getValue().empty()); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param3").getValue() == "value3"); } void list_to_multipart () { - ContentType contentType = ContentType("application", "rlmi+xml"); - contentType.addParameter("charset", "\"UTF-8\""); Content content1; content1.setBody(part1); - content1.setContentType(contentType); - contentType = ContentType("application", "pidf+xml"); - contentType.addParameter("charset", "\"UTF-8\""); + content1.setContentType(ContentType("application", "rlmi+xml")); Content content2; content2.setBody(part2); - content2.setContentType(contentType); + content2.setContentType(ContentType("application", "pidf+xml")); Content content3; content3.setBody(part3); - content3.addHeader("Content-Encoding", "b64"); - content3.setContentType(contentType); + content3.setContentType(ContentType("application", "pidf+xml")); 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}; + content4.setContentType(ContentType("application", "pidf+xml")); + list contents = {content1, content2, content3, content4}; Content multipartContent = ContentManager::contentListToMultipart(contents); - string originalStr(generated_multipart); + string originalStr(multipart); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), ' '), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\t'), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\r'), originalStr.end()); @@ -369,67 +276,16 @@ void list_to_multipart () { BC_ASSERT_TRUE(originalStr == generatedStr); } -static void content_type_parsing(void) { - string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; - ContentType contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("message", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("external-body", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("URL", contentType.getParameter("access-type").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\"", contentType.getParameter("URL").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_EQUAL(2, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); - - type = "multipart/mixed;boundary=-----------------------------14737809831466499882746641450"; - contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("multipart", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("mixed", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("-----------------------------14737809831466499882746641450", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("access-type").getValue().c_str()); - BC_ASSERT_EQUAL(1, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); - - type = "plain/text"; - contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("plain", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("text", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_EQUAL(0, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); -} - -static void content_header_parsing(void) { - string value = "toto;param1=value1;param2;param3=value3"; - Header header = Header("Content-Id", value); - BC_ASSERT_TRUE(header.getValue() == "toto"); - BC_ASSERT_TRUE(header.getParameter("param1").getValue() == "value1"); - BC_ASSERT_TRUE(header.getParameter("param2").getValue().empty()); - BC_ASSERT_TRUE(header.getParameter("param3").getValue() == "value3"); - BC_ASSERT_EQUAL(3, header.getParameters().size(), int, "%d"); - BC_ASSERT_STRING_EQUAL("", header.getParameter("encoding").getValue().c_str()); - - value = "b64"; - header = Header("Content-Encoding", value); - BC_ASSERT_TRUE(header.getValue() == value); - BC_ASSERT_EQUAL(0, header.getParameters().size(), int, "%d"); - BC_ASSERT_STRING_EQUAL("", header.getParameter("access-type").getValue().c_str()); -} - -test_t contents_tests[] = { +test_t content_manager_tests[] = { TEST_NO_TAG("Multipart to list", multipart_to_list), - TEST_NO_TAG("List to multipart", list_to_multipart), - TEST_NO_TAG("Content type parsing", content_type_parsing), - TEST_NO_TAG("Content header parsing", content_header_parsing) + TEST_NO_TAG("List to multipart", list_to_multipart) }; -test_suite_t contents_test_suite = { - "Contents", +test_suite_t content_manager_test_suite = { + "Content manager", nullptr, nullptr, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(contents_tests) / sizeof(contents_tests[0]), contents_tests + sizeof(content_manager_tests) / sizeof(content_manager_tests[0]), content_manager_tests }; diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 66cc661d8..e803ae33a 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -423,12 +423,12 @@ static void cpim_chat_message_modifier_base(bool_t use_multipart) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody("Hello Part 2"); - marieMessage->addContent(content); + marieMessage->addContent(*content); } marieMessage->send(); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_TRUE(marieMessage->getInternalContent().getContentType().isEmpty()); // Internal content is cleaned after message is sent or received + BC_ASSERT_STRING_EQUAL(marieMessage->getInternalContent().getContentType().asString().c_str(), ""); // Internal content is cleaned after message is sent or received BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); if (pauline->stat.last_received_chat_message != NULL) { diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 66ae0f165..2119f3500 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -41,7 +41,7 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * if (!BC_ASSERT_PTR_NOT_NULL(content)) return; if (!linphone_content_is_multipart(content) && (!ua || !strstr(ua, "flexisip"))) { /*disable check for full presence server support*/ /*hack to disable content checking for list notify */ - BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),notify_content); + BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); } mgr=get_manager(lc); mgr->stat.number_of_NotifyReceived++; diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index c96be9ed4..9824c2084 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -45,7 +45,7 @@ extern test_suite_t call_video_test_suite; extern test_suite_t clonable_object_test_suite; extern test_suite_t conference_event_test_suite; extern test_suite_t conference_test_suite; -extern test_suite_t contents_test_suite; +extern test_suite_t content_manager_test_suite; extern test_suite_t cpim_test_suite; extern test_suite_t dtmf_test_suite; extern test_suite_t event_test_suite; diff --git a/tester/message_tester.c b/tester/message_tester.c index 8922adf20..396f4b9c4 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -2294,19 +2294,15 @@ void text_message_with_custom_content_type_and_lime(void) { static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { - ms_debug("IM encryption process incoming message with content type %s", linphone_chat_message_get_content_type(msg)); if (linphone_chat_message_get_content_type(msg)) { if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) { size_t b64Size = 0; unsigned char *output; - const char *data = linphone_chat_message_get_text(msg); - ms_debug("IM encryption process incoming message crypted message is %s", data); - bctbx_base64_decode(NULL, &b64Size, (unsigned char *)data, strlen(data)); + bctbx_base64_decode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); output = (unsigned char *)ms_malloc(b64Size+1), - bctbx_base64_decode(output, &b64Size, (unsigned char *)data, strlen(data)); + bctbx_base64_decode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); output[b64Size] = '\0'; linphone_chat_message_set_text(msg, (char *)output); - ms_debug("IM encryption process incoming message decrypted message is %s", output); ms_free(output); linphone_chat_message_set_content_type(msg, "text/plain"); return 0; diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp index c94dc9a2e..3fdd9073a 100644 --- a/tester/multipart-tester.cpp +++ b/tester/multipart-tester.cpp @@ -53,13 +53,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType(ContentType("video/mkv")); content->setFilePath(send_filepath); content->setFileName("sintel_trailer_opus_h264.mkv"); - marieMessage->addContent(content); + marieMessage->addContent(*content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello part 1"); - marieMessage->addContent(content); + content->setBody("Hello Part 1"); + marieMessage->addContent(*content); } if (second_file_transfer) { @@ -68,13 +68,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType(ContentType("file/vcf")); content->setFilePath(send_filepath); content->setFileName("vcards.vcf"); - marieMessage->addContent(content); + marieMessage->addContent(*content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello part 2"); - marieMessage->addContent(content); + content->setBody("Hello Part 2"); + marieMessage->addContent(*content); } linphone_core_set_file_transfer_server(marie->lc,"https://www.linphone.org:444/lft.php"); @@ -82,20 +82,7 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); - - if (first_file_transfer || second_file_transfer) { - LinphoneContent *content = linphone_chat_message_get_file_transfer_information(pauline->stat.last_received_chat_message); - BC_ASSERT_PTR_NOT_NULL(content); - linphone_content_unref(content); - } - if (!first_file_transfer || !second_file_transfer) { - const char *content = linphone_chat_message_get_text_content(pauline->stat.last_received_chat_message); - BC_ASSERT_PTR_NOT_NULL(content); - if (!first_file_transfer) - BC_ASSERT_STRING_EQUAL(content, "Hello part 1"); - else if (!second_file_transfer) - BC_ASSERT_STRING_EQUAL(content, "Hello part 2"); - } + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "multipart/mixed"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index c0587fe7d..db3f0ca07 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -430,10 +430,8 @@ static void test_presence_list_base(bool_t enable_compression) { lcs = bctbx_list_append(lcs, pauline->lc); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 4000); - BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); - BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); - BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); if (!BC_ASSERT_PTR_NOT_NULL(lf)) goto end; BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); @@ -487,8 +485,7 @@ static void test_presence_list_base(bool_t enable_compression) { /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); - BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); - BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); diff --git a/tester/tester.c b/tester/tester.c index cd8481381..6eaafeab9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -606,7 +606,7 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&stun_test_suite); bc_tester_add_suite(&event_test_suite); bc_tester_add_suite(&conference_event_test_suite); - bc_tester_add_suite(&contents_test_suite); + bc_tester_add_suite(&content_manager_test_suite); bc_tester_add_suite(&flexisip_test_suite); bc_tester_add_suite(&remote_provisioning_test_suite); bc_tester_add_suite(&quality_reporting_test_suite);