diff --git a/coreapi/chat.c b/coreapi/chat.c index d17b6cef7..eab5ed37e 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -146,86 +146,6 @@ LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const c return _linphone_core_get_or_create_chat_room(lc, to); } -void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg) { - xmlChar *file_url = NULL; - xmlDocPtr xmlMessageBody; - xmlNodePtr cur; - /* parse the msg body to get all informations from it */ - xmlMessageBody = xmlParseDoc((const xmlChar *)linphone_chat_message_get_text(msg)); - LinphoneContent *content = linphone_content_new(); - linphone_chat_message_set_file_transfer_information(msg, content); - - cur = xmlDocGetRootElement(xmlMessageBody); - if (cur != NULL) { - cur = cur->xmlChildrenNode; - while (cur != NULL) { - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { - /* we found a file info node, check if it has a type="file" attribute */ - xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); - if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ - cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ - while (cur != NULL) { - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) { - xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - linphone_content_set_size(content, (size_t)strtol((const char *)fileSizeString, NULL, 10)); - xmlFree(fileSizeString); - } - - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) { - xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - linphone_content_set_name(content, (char *)filename); - xmlFree(filename); - } - if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) { - xmlChar *contentType = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - int contentTypeIndex = 0; - char *type; - char *subtype; - while (contentType[contentTypeIndex] != '/' && contentType[contentTypeIndex] != '\0') { - contentTypeIndex++; - } - type = ms_strndup((char *)contentType, contentTypeIndex); - subtype = ms_strdup(((char *)contentType + contentTypeIndex + 1)); - linphone_content_set_type(content, type); - linphone_content_set_subtype(content, subtype); - ms_free(subtype); - ms_free(type); - xmlFree(contentType); - } - if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { - file_url = xmlGetProp(cur, (const xmlChar *)"url"); - } - - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { - /* there is a key in the msg: file has been encrypted */ - /* convert the key from base 64 */ - xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - size_t keyLength = b64::b64_decode((char *)keyb64, strlen((char *)keyb64), NULL, 0); - uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); - /* decode the key into local key buffer */ - b64::b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength); - linphone_content_set_key(content, (char *)keyBuffer, keyLength); - /* duplicate key value into the linphone content private structure */ - xmlFree(keyb64); - free(keyBuffer); - } - - cur = cur->next; - } - xmlFree(typeAttribute); - break; - } - xmlFree(typeAttribute); - } - cur = cur->next; - } - } - xmlFreeDoc(xmlMessageBody); - - linphone_chat_message_set_external_body_url(msg, (const char *)file_url); - xmlFree(file_url); -} - int linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) { LinphoneAddress *addr = linphone_address_new(sal_msg->from); linphone_address_clean(addr); diff --git a/coreapi/private.h b/coreapi/private.h index 228339482..9e430c6cd 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1111,7 +1111,6 @@ LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call); void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); void linphone_chat_message_deactivate(LinphoneChatMessage *msg); void linphone_chat_message_release(LinphoneChatMessage *msg); -void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg); void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id); void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason); diff --git a/src/chat/chat-message-p.h b/src/chat/chat-message-p.h index 7fc20f851..199768d78 100644 --- a/src/chat/chat-message-p.h +++ b/src/chat/chat-message-p.h @@ -141,10 +141,9 @@ private: void fileUploadEndBackgroundTask(); void fileUploadBeginBackgroundTask(); bool isFileTransferInProgressAndValid(); - int startHttpTransfer(std::string url, std::string action, belle_http_request_listener_callbacks_t *cbs); - void releaseHttpRequest(); + void createFileTransferInformationsFromVndGsmaRcsFtHttpXml(); std::shared_ptr getPublicSharedPtr(); diff --git a/src/chat/chat-message.cpp b/src/chat/chat-message.cpp index 8ae8d0dcc..47f174c33 100644 --- a/src/chat/chat-message.cpp +++ b/src/chat/chat-message.cpp @@ -187,6 +187,10 @@ LinphoneContent * ChatMessagePrivate::getFileTransferInformation() const { } void ChatMessagePrivate::setFileTransferInformation(LinphoneContent *content) { + if (cFileTransferInformation) { + linphone_content_unref(cFileTransferInformation); + cFileTransferInformation = NULL; + } cFileTransferInformation = content; } @@ -894,6 +898,86 @@ void ChatMessagePrivate::releaseHttpRequest() { } } +void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml() { + xmlChar *file_url = NULL; + xmlDocPtr xmlMessageBody; + xmlNodePtr cur; + /* parse the msg body to get all informations from it */ + xmlMessageBody = xmlParseDoc((const xmlChar *)getText().c_str()); + LinphoneContent *content = linphone_content_new(); + setFileTransferInformation(content); + + cur = xmlDocGetRootElement(xmlMessageBody); + if (cur != NULL) { + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { + /* we found a file info node, check if it has a type="file" attribute */ + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ + cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) { + xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + linphone_content_set_size(content, (size_t)strtol((const char *)fileSizeString, NULL, 10)); + xmlFree(fileSizeString); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) { + xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + linphone_content_set_name(content, (char *)filename); + xmlFree(filename); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) { + xmlChar *contentType = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + int contentTypeIndex = 0; + char *type; + char *subtype; + while (contentType[contentTypeIndex] != '/' && contentType[contentTypeIndex] != '\0') { + contentTypeIndex++; + } + type = ms_strndup((char *)contentType, contentTypeIndex); + subtype = ms_strdup(((char *)contentType + contentTypeIndex + 1)); + linphone_content_set_type(content, type); + linphone_content_set_subtype(content, subtype); + ms_free(subtype); + ms_free(type); + xmlFree(contentType); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { + file_url = xmlGetProp(cur, (const xmlChar *)"url"); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { + /* there is a key in the msg: file has been encrypted */ + /* convert the key from base 64 */ + xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + size_t keyLength = b64::b64_decode((char *)keyb64, strlen((char *)keyb64), NULL, 0); + uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); + /* decode the key into local key buffer */ + b64::b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength); + linphone_content_set_key(content, (char *)keyBuffer, keyLength); + /* duplicate key value into the linphone content private structure */ + xmlFree(keyb64); + free(keyBuffer); + } + + cur = cur->next; + } + xmlFree(typeAttribute); + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + xmlFreeDoc(xmlMessageBody); + + externalBodyUrl = string((const char *)file_url); + xmlFree(file_url); +} + LinphoneReason ChatMessagePrivate::receive() { L_Q(); @@ -917,8 +1001,6 @@ LinphoneReason ChatMessagePrivate::receive() { chatRoom->getPrivate()->notifyUndecryptableMessageReceived(getPublicSharedPtr()); reason = linphone_error_code_to_reason(retval); q->sendDeliveryNotification(reason); - /* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */ - reason = LinphoneReasonNone; return reason; } @@ -941,7 +1023,7 @@ LinphoneReason ChatMessagePrivate::receive() { } if (ContentType::isFileTransfer(getContentType())) { - create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(L_GET_C_BACK_PTR(getPublicSharedPtr())); + createFileTransferInformationsFromVndGsmaRcsFtHttpXml(); store = true; } else if (ContentType::isText(getContentType())) { store = true; diff --git a/src/chat/chat-room.cpp b/src/chat/chat-room.cpp index 352f9b730..c6b9e7c6e 100644 --- a/src/chat/chat-room.cpp +++ b/src/chat/chat-room.cpp @@ -419,6 +419,12 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa reason = msg->getPrivate()->receive(); + if (reason == LinphoneReasonNotAcceptable || reason == LinphoneReasonUnknown) { + /* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */ + reason = LinphoneReasonNone; + goto end; + } + if (ContentType::isImIsComposing(msg->getPrivate()->getContentType())) { isComposingReceived(msg->getPrivate()->getText()); increaseMsgCount = FALSE;