mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 03:28:07 +00:00
More work related to ChatMessage file transfer
This commit is contained in:
parent
0118f6ee53
commit
ba89633e45
12 changed files with 655 additions and 220 deletions
|
|
@ -84,6 +84,9 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
|
|||
content/content-manager.h
|
||||
content/content-type.h
|
||||
content/content.h
|
||||
content/content-p.h
|
||||
content/file-content.h
|
||||
content/file-transfer-content.h
|
||||
core/core-accessor.h
|
||||
core/core-p.h
|
||||
core/core.h
|
||||
|
|
@ -184,6 +187,8 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
|
|||
content/content-manager.cpp
|
||||
content/content-type.cpp
|
||||
content/content.cpp
|
||||
content/file-content.cpp
|
||||
content/file-transfer-content.cpp
|
||||
core/core-accessor.cpp
|
||||
core/core-chat-room.cpp
|
||||
core/core.cpp
|
||||
|
|
|
|||
|
|
@ -252,12 +252,8 @@ const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChat
|
|||
// Methods
|
||||
// =============================================================================
|
||||
|
||||
int linphone_chat_room_upload_file(LinphoneChatMessage *msg) {
|
||||
return ((LinphoneStatus)L_GET_CPP_PTR_FROM_C_OBJECT(msg)->uploadFile());
|
||||
}
|
||||
|
||||
LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *msg) {
|
||||
return ((LinphoneStatus)L_GET_CPP_PTR_FROM_C_OBJECT(msg)->downloadFile());
|
||||
return ((LinphoneStatus)L_GET_PRIVATE_FROM_C_OBJECT(msg)->downloadFile());
|
||||
}
|
||||
|
||||
void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "chat/chat-message/chat-message.h"
|
||||
#include "chat/notification/imdn.h"
|
||||
#include "content/content.h"
|
||||
#include "content/file-content.h"
|
||||
#include "content/file-transfer-content.h"
|
||||
#include "content/content-type.h"
|
||||
#include "object/object-p.h"
|
||||
#include "sal/sal.h"
|
||||
|
|
@ -92,6 +94,8 @@ public:
|
|||
|
||||
LinphoneContent *getFileTransferInformation() const;
|
||||
void setFileTransferInformation(const LinphoneContent *content);
|
||||
|
||||
int downloadFile ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Need to be public to be called from static C callbacks
|
||||
|
|
@ -138,7 +142,7 @@ private:
|
|||
bool isReadOnly = false;
|
||||
std::list<Content > contents;
|
||||
Content internalContent;
|
||||
Content *currentFileTransferContent;
|
||||
FileContent *currentFileContentToTransfer;
|
||||
std::unordered_map<std::string, std::string> customHeaders;
|
||||
mutable LinphoneErrorInfo * errorInfo = nullptr;
|
||||
belle_http_request_t *httpRequest = nullptr;
|
||||
|
|
@ -153,7 +157,8 @@ private:
|
|||
std::string cText;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
int uploadFile ();
|
||||
std::string createImdnXml(Imdn::Type imdnType, LinphoneReason reason);
|
||||
|
||||
void fileUploadEndBackgroundTask();
|
||||
|
|
@ -165,7 +170,7 @@ private:
|
|||
belle_http_request_listener_callbacks_t *cbs
|
||||
);
|
||||
void releaseHttpRequest();
|
||||
void createFileTransferInformationsFromVndGsmaRcsFtHttpXml(const std::string &body);
|
||||
void createFileTransferInformationsFromVndGsmaRcsFtHttpXml(FileTransferContent &content);
|
||||
|
||||
L_DECLARE_PUBLIC(ChatMessage);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "chat/modifier/cpim-chat-message-modifier.h"
|
||||
#include "chat/modifier/encryption-chat-message-modifier.h"
|
||||
#include "chat/modifier/multipart-chat-message-modifier.h"
|
||||
#include "content/file-content.h"
|
||||
#include "content/content.h"
|
||||
#include "core/core.h"
|
||||
|
||||
|
|
@ -151,6 +152,8 @@ string ChatMessagePrivate::getSalCustomHeaderValue (const string &name) {
|
|||
return L_C_TO_STRING(sal_custom_header_find(salCustomHeaders, name.c_str()));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Below methods are only for C API backward compatibility...
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const ContentType &ChatMessagePrivate::getContentType () {
|
||||
|
|
@ -208,7 +211,6 @@ void ChatMessagePrivate::setText (const string &text) {
|
|||
|
||||
LinphoneContent *ChatMessagePrivate::getFileTransferInformation () const {
|
||||
L_Q();
|
||||
//TODO cache and unref to prevent leak
|
||||
if (q->hasFileTransferContent()) {
|
||||
return q->getFileTransferContent().toLinphoneContent();
|
||||
}
|
||||
|
|
@ -218,16 +220,29 @@ LinphoneContent *ChatMessagePrivate::getFileTransferInformation () const {
|
|||
void ChatMessagePrivate::setFileTransferInformation (const LinphoneContent *c_content) {
|
||||
L_Q();
|
||||
|
||||
Content content;
|
||||
// Create a FileContent, it will create the FileTransferContent at upload time
|
||||
FileContent fileContent;
|
||||
ContentType contentType(linphone_content_get_type(c_content), linphone_content_get_subtype(c_content));
|
||||
content.setContentType(contentType);
|
||||
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) != NULL) {
|
||||
content.setBody(linphone_content_get_string_buffer(c_content));
|
||||
fileContent.setBody(linphone_content_get_string_buffer(c_content));
|
||||
}
|
||||
content.setContentDisposition(linphone_content_get_name(c_content));
|
||||
content.setExpectedSize(linphone_content_get_size(c_content));
|
||||
|
||||
q->addContent(content);
|
||||
q->addContent(fileContent);
|
||||
}
|
||||
|
||||
int ChatMessagePrivate::downloadFile () {
|
||||
L_Q();
|
||||
|
||||
for (Content& content : contents) {
|
||||
if (content.getContentType() == ContentType::FileTransfer) {
|
||||
return q->downloadFile(static_cast<FileTransferContent&>(content));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -367,7 +382,7 @@ void ChatMessagePrivate::fileTransferOnProgress (
|
|||
|
||||
LinphoneChatMessage *msg = L_GET_C_BACK_PTR(q);
|
||||
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
|
||||
LinphoneContent *content = currentFileTransferContent->toLinphoneContent();
|
||||
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 {
|
||||
|
|
@ -420,12 +435,12 @@ int ChatMessagePrivate::onSendBody (
|
|||
|
||||
// if we've not reach the end of file yet, ask for more data
|
||||
// in case of file body handler, won't be called
|
||||
if (fileTransferFilePath.empty() && offset < currentFileTransferContent->getExpectedSize()) {
|
||||
if (currentFileContentToTransfer->getFilePath().empty() && offset < currentFileContentToTransfer->getFileSize()) {
|
||||
// get data from call back
|
||||
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
|
||||
LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb =
|
||||
linphone_chat_message_cbs_get_file_transfer_send(cbs);
|
||||
LinphoneContent *content = currentFileTransferContent->toLinphoneContent();
|
||||
LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent();
|
||||
if (file_transfer_send_cb) {
|
||||
LinphoneBuffer *lb = file_transfer_send_cb(msg, content, offset, *size);
|
||||
if (lb == nullptr) {
|
||||
|
|
@ -564,10 +579,10 @@ void ChatMessagePrivate::onRecvBody (belle_sip_user_body_handler_t *bh, belle_si
|
|||
ms_free(decrypted_buffer);
|
||||
|
||||
if (retval <= 0) {
|
||||
if (fileTransferFilePath.empty()) {
|
||||
if (currentFileContentToTransfer->getFilePath().empty()) {
|
||||
LinphoneChatMessage *msg = L_GET_C_BACK_PTR(q);
|
||||
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
|
||||
LinphoneContent *content = currentFileTransferContent->toLinphoneContent();
|
||||
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);
|
||||
|
|
@ -608,10 +623,10 @@ void ChatMessagePrivate::onRecvEnd (belle_sip_user_body_handler_t *bh) {
|
|||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
if (fileTransferFilePath.empty()) {
|
||||
if (currentFileContentToTransfer->getFilePath().empty()) {
|
||||
LinphoneChatMessage *msg = L_GET_C_BACK_PTR(q);
|
||||
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
|
||||
LinphoneContent *content = currentFileTransferContent->toLinphoneContent();
|
||||
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);
|
||||
|
|
@ -625,6 +640,18 @@ void ChatMessagePrivate::onRecvEnd (belle_sip_user_body_handler_t *bh) {
|
|||
}
|
||||
|
||||
if (retval <= 0 && state != ChatMessage::State::FileTransferError) {
|
||||
// Remove the FileTransferContent from the message and store the FileContent
|
||||
FileContent fileContent = *currentFileContentToTransfer;
|
||||
q->addContent(fileContent);
|
||||
for (Content &content : contents) {
|
||||
if (content.getContentType() == ContentType::FileTransfer) {
|
||||
FileTransferContent fileTransferContent = static_cast<FileTransferContent&>(content);
|
||||
if (fileTransferContent.getFileContent() == fileContent) {
|
||||
q->removeContent(content);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(ChatMessage::State::FileTransferDone);
|
||||
}
|
||||
}
|
||||
|
|
@ -689,38 +716,38 @@ void ChatMessagePrivate::processResponseFromPostFile (const belle_http_response_
|
|||
first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\"";
|
||||
} else {
|
||||
// temporary storage for the Content-disposition header value
|
||||
first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileTransferContent->getContentDisposition() + "\"";
|
||||
first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileContentToTransfer->getContentDisposition() + "\"";
|
||||
}
|
||||
|
||||
// create a user body handler to take care of the file and add the content disposition and content-type headers
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(currentFileTransferContent->getExpectedSize(),
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(currentFileContentToTransfer->getFileSize(),
|
||||
_chat_message_file_transfer_on_progress, nullptr, nullptr,
|
||||
_chat_message_on_send_body, _chat_message_on_send_end, this);
|
||||
if (!fileTransferFilePath.empty()) {
|
||||
if (!currentFileContentToTransfer->getFilePath().empty()) {
|
||||
belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh;
|
||||
// No need to add again the callback for progression, otherwise it will be called twice
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(fileTransferFilePath.c_str(), nullptr, this);
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), nullptr, this);
|
||||
//linphone_content_set_size(cFileTransferInformation, belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh));
|
||||
belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler);
|
||||
} else if (!currentFileTransferContent->isEmpty()) {
|
||||
} else if (!currentFileContentToTransfer->isEmpty()) {
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
|
||||
ms_strdup(currentFileTransferContent->getBodyAsString().c_str()),
|
||||
currentFileTransferContent->getSize(), _chat_message_file_transfer_on_progress, this);
|
||||
ms_strdup(currentFileContentToTransfer->getBodyAsString().c_str()),
|
||||
currentFileContentToTransfer->getSize(), _chat_message_file_transfer_on_progress, this);
|
||||
}
|
||||
|
||||
belle_sip_body_handler_add_header(first_part_bh,
|
||||
belle_sip_header_create("Content-disposition", first_part_header.c_str()));
|
||||
belle_sip_body_handler_add_header(first_part_bh,
|
||||
(belle_sip_header_t *)belle_sip_header_content_type_create(
|
||||
currentFileTransferContent->getContentType().getType().c_str(),
|
||||
currentFileTransferContent->getContentType().getSubType().c_str()));
|
||||
currentFileContentToTransfer->getContentType().getType().c_str(),
|
||||
currentFileContentToTransfer->getContentType().getSubType().c_str()));
|
||||
|
||||
// insert it in a multipart body handler which will manage the boundaries of multipart msg
|
||||
bh = belle_sip_multipart_body_handler_new(_chat_message_file_transfer_on_progress, this, first_part_bh, nullptr);
|
||||
|
||||
releaseHttpRequest();
|
||||
fileUploadBeginBackgroundTask();
|
||||
q->uploadFile();
|
||||
uploadFile();
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(httpRequest), BELLE_SIP_BODY_HANDLER(bh));
|
||||
} else if (code == 200) { // file has been uploaded correctly, get server reply and send it
|
||||
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
|
||||
|
|
@ -784,9 +811,15 @@ void ChatMessagePrivate::processResponseFromPostFile (const belle_http_response_
|
|||
setText(body);
|
||||
}
|
||||
setContentType(ContentType::FileTransfer);*/
|
||||
|
||||
(*currentFileTransferContent).setContentType(ContentType::FileTransfer);
|
||||
(*currentFileTransferContent).setBody(body);
|
||||
FileContent fileContent = *currentFileContentToTransfer;
|
||||
|
||||
FileTransferContent fileTransferContent;
|
||||
fileTransferContent.setContentType(ContentType::FileTransfer);
|
||||
fileTransferContent.setFileContent(fileContent);
|
||||
fileTransferContent.setBody(body);
|
||||
|
||||
q->removeContent(fileContent);
|
||||
q->addContent(fileTransferContent);
|
||||
|
||||
q->updateState(ChatMessage::State::FileTransferDone);
|
||||
releaseHttpRequest();
|
||||
|
|
@ -812,8 +845,8 @@ static void _chat_process_response_headers_from_get_file (void *data, const bell
|
|||
d->processResponseHeadersFromGetFile(event);
|
||||
}
|
||||
|
||||
static Content createFileTransferInformationFromHeaders (const belle_sip_message_t *m) {
|
||||
Content content;
|
||||
static FileContent createFileTransferInformationFromHeaders (const belle_sip_message_t *m) {
|
||||
FileContent content;
|
||||
|
||||
belle_sip_header_content_length_t *content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(m, "Content-Length"));
|
||||
belle_sip_header_content_type_t *content_type_hdr = BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(m, "Content-Type"));
|
||||
|
|
@ -824,10 +857,11 @@ static Content createFileTransferInformationFromHeaders (const belle_sip_message
|
|||
subtype = belle_sip_header_content_type_get_subtype(content_type_hdr);
|
||||
lInfo() << "Extracted content type " << type << " / " << subtype << " from header";
|
||||
ContentType contentType(type, subtype);
|
||||
content.setContentType(contentType);
|
||||
}
|
||||
if (content_length_hdr) {
|
||||
content.setExpectedSize(belle_sip_header_content_length_get_content_length(content_length_hdr));
|
||||
lInfo() << "Extracted content length " << content.getExpectedSize() << " from header";
|
||||
content.setFileSize(belle_sip_header_content_length_get_content_length(content_length_hdr));
|
||||
lInfo() << "Extracted content length " << content.getFileSize() << " from header";
|
||||
}
|
||||
|
||||
return content;
|
||||
|
|
@ -843,26 +877,26 @@ void ChatMessagePrivate::processResponseHeadersFromGetFile (const belle_http_res
|
|||
belle_sip_body_handler_t *body_handler = nullptr;
|
||||
size_t body_size = 0;
|
||||
|
||||
if (currentFileTransferContent == nullptr) {
|
||||
if (currentFileContentToTransfer == nullptr) {
|
||||
lWarning() << "No file transfer information for msg [" << this << "]: creating...";
|
||||
Content content = createFileTransferInformationFromHeaders(response);
|
||||
FileContent content = createFileTransferInformationFromHeaders(response);
|
||||
q->addContent(content);
|
||||
} else {
|
||||
belle_sip_header_content_length_t *content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(response, "Content-Length"));
|
||||
currentFileTransferContent->setExpectedSize(belle_sip_header_content_length_get_content_length(content_length_hdr));
|
||||
lInfo() << "Extracted content length " << currentFileTransferContent->getExpectedSize() << " from header";
|
||||
currentFileContentToTransfer->setFileSize(belle_sip_header_content_length_get_content_length(content_length_hdr));
|
||||
lInfo() << "Extracted content length " << currentFileContentToTransfer->getFileSize() << " from header";
|
||||
}
|
||||
|
||||
if (q->hasFileTransferContent()) {
|
||||
body_size = q->getFileTransferContent().getExpectedSize();
|
||||
if (currentFileContentToTransfer) {
|
||||
body_size = currentFileContentToTransfer->getFileSize();
|
||||
}
|
||||
|
||||
body_handler = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(body_size, _chat_message_file_transfer_on_progress,
|
||||
nullptr, _chat_message_on_recv_body,
|
||||
nullptr, _chat_message_on_recv_end, this);
|
||||
if (!fileTransferFilePath.empty()) {
|
||||
if (!currentFileContentToTransfer->getFilePath().empty()) {
|
||||
belle_sip_user_body_handler_t *bh = (belle_sip_user_body_handler_t *)body_handler;
|
||||
body_handler = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(fileTransferFilePath.c_str(), _chat_message_file_transfer_on_progress, this);
|
||||
body_handler = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), _chat_message_file_transfer_on_progress, this);
|
||||
if (belle_sip_body_handler_get_size((belle_sip_body_handler_t *)body_handler) == 0) {
|
||||
// If the size of the body has not been initialized from the file stat, use the one from the
|
||||
// file_transfer_information.
|
||||
|
|
@ -1008,14 +1042,38 @@ void ChatMessagePrivate::releaseHttpRequest () {
|
|||
}
|
||||
}
|
||||
|
||||
void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml (const string &body) {
|
||||
int ChatMessagePrivate::uploadFile () {
|
||||
L_Q();
|
||||
|
||||
if (httpRequest) {
|
||||
lError() << "linphone_chat_room_upload_file(): there is already an upload in progress.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// THIS IS ONLY FOR BACKWARD C API COMPAT
|
||||
if (currentFileContentToTransfer->getFilePath().empty() && !q->getFileTransferFilepath().empty()) {
|
||||
currentFileContentToTransfer->setFilePath(q->getFileTransferFilepath());
|
||||
}
|
||||
|
||||
belle_http_request_listener_callbacks_t cbs = { 0 };
|
||||
cbs.process_response = _chat_message_process_response_from_post_file;
|
||||
cbs.process_io_error = _chat_message_process_io_error_upload;
|
||||
cbs.process_auth_requested = _chat_message_process_auth_requested_upload;
|
||||
|
||||
int err = startHttpTransfer(linphone_core_get_file_transfer_server(q->getCore()->getCCore()), "POST", &cbs);
|
||||
if (err == -1)
|
||||
setState(ChatMessage::State::NotDelivered);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferContent &fileTransferContent) {
|
||||
xmlChar *file_url = nullptr;
|
||||
xmlDocPtr xmlMessageBody;
|
||||
xmlNodePtr cur;
|
||||
/* parse the msg body to get all informations from it */
|
||||
xmlMessageBody = xmlParseDoc((const xmlChar *)body.c_str());
|
||||
Content content;
|
||||
xmlMessageBody = xmlParseDoc((const xmlChar *)fileTransferContent.getBodyAsString().c_str());
|
||||
FileContent fileContent;
|
||||
|
||||
cur = xmlDocGetRootElement(xmlMessageBody);
|
||||
if (cur != nullptr) {
|
||||
|
|
@ -1030,13 +1088,13 @@ void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml (
|
|||
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) {
|
||||
xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
|
||||
size_t size = (size_t)strtol((const char *)fileSizeString, nullptr, 10);
|
||||
content.setExpectedSize(size);
|
||||
fileContent.setFileSize(size);
|
||||
xmlFree(fileSizeString);
|
||||
}
|
||||
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) {
|
||||
xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
|
||||
content.setContentDisposition((char *)filename);
|
||||
fileContent.setFileName((char *)filename);
|
||||
xmlFree(filename);
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) {
|
||||
|
|
@ -1050,7 +1108,7 @@ void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml (
|
|||
type = ms_strndup((char *)content_type, contentTypeIndex);
|
||||
subtype = ms_strdup(((char *)content_type + contentTypeIndex + 1));
|
||||
ContentType contentType(type, subtype);
|
||||
content.setContentType(contentType);
|
||||
fileContent.setContentType(contentType);
|
||||
ms_free(subtype);
|
||||
ms_free(type);
|
||||
ms_free(content_type);
|
||||
|
|
@ -1086,8 +1144,12 @@ void ChatMessagePrivate::createFileTransferInformationsFromVndGsmaRcsFtHttpXml (
|
|||
}
|
||||
xmlFreeDoc(xmlMessageBody);
|
||||
|
||||
externalBodyUrl = string((const char *)file_url);
|
||||
q->addContent(content);
|
||||
fileContent.setFilePath(fileTransferContent.getFilePath()); // Copy file path from file transfer content to file content for file body handler
|
||||
fileTransferContent.setFileUrl(string((const char *)file_url)); // Set file url in the file transfer content for the download
|
||||
|
||||
// Link the FileContent to the FileTransferContent
|
||||
fileTransferContent.setFileContent(fileContent);
|
||||
|
||||
xmlFree(file_url);
|
||||
}
|
||||
|
||||
|
|
@ -1163,12 +1225,10 @@ LinphoneReason ChatMessagePrivate::receive () {
|
|||
}
|
||||
|
||||
bool messageToBeStored = false;
|
||||
for (const auto &c : contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
messageToBeStored = true;
|
||||
createFileTransferInformationsFromVndGsmaRcsFtHttpXml(c.getBodyAsString());
|
||||
} else if (c.getContentType() == ContentType::PlainText)
|
||||
for (Content &c : contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer || c.getContentType() == ContentType::PlainText) {
|
||||
messageToBeStored = true;
|
||||
}
|
||||
}
|
||||
if (messageToBeStored)
|
||||
q->store();
|
||||
|
|
@ -1185,23 +1245,24 @@ void ChatMessagePrivate::send () {
|
|||
if ((currentSendStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) {
|
||||
lInfo() << "File upload step already done, skipping";
|
||||
} else {
|
||||
currentFileTransferContent = nullptr;
|
||||
currentFileContentToTransfer = nullptr;
|
||||
// For each FileContent, upload it and create a FileTransferContent
|
||||
for (Content &content : contents) {
|
||||
ContentType contentType = content.getContentType();
|
||||
//TODO Improve !
|
||||
//TODO Improve
|
||||
if (contentType != ContentType::FileTransfer && contentType != ContentType::PlainText &&
|
||||
contentType != ContentType::ExternalBody && contentType != ContentType::Imdn &&
|
||||
contentType != ContentType::ImIsComposing && contentType != ContentType::ResourceLists &&
|
||||
contentType != ContentType::Sdp && contentType != ContentType::ConferenceInfo &&
|
||||
contentType != ContentType::Cpim) {
|
||||
lInfo() << "Found content with type " << contentType.asString() << ", set it for file upload";
|
||||
currentFileTransferContent = &content;
|
||||
currentFileContentToTransfer = (FileContent *)&content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentFileTransferContent != nullptr) {
|
||||
if (currentFileContentToTransfer != nullptr) {
|
||||
/* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
|
||||
if (q->uploadFile() == 0) {
|
||||
if (uploadFile() == 0) {
|
||||
setState(ChatMessage::State::InProgress);
|
||||
}
|
||||
return;
|
||||
|
|
@ -1250,18 +1311,6 @@ void ChatMessagePrivate::send () {
|
|||
// Start of message modification
|
||||
// ---------------------------------------
|
||||
|
||||
// TODO Remove : This won't be necessary once we store the contentsList
|
||||
string clearTextMessage;
|
||||
ContentType clearTextContentType;
|
||||
|
||||
if (!getText().empty()) {
|
||||
clearTextMessage = getText().c_str();
|
||||
}
|
||||
if (getContentType().isValid()) {
|
||||
clearTextContentType = getContentType();
|
||||
}
|
||||
// End of TODO Remove
|
||||
|
||||
if (applyModifiers) {
|
||||
if ((currentSendStep &ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) {
|
||||
lInfo() << "Multipart step already done, skipping";
|
||||
|
|
@ -1309,7 +1358,7 @@ void ChatMessagePrivate::send () {
|
|||
internalContent = contents.front();
|
||||
}
|
||||
|
||||
if (!externalBodyUrl.empty()) {
|
||||
if (!externalBodyUrl.empty()) { // Deprecated way of sending files
|
||||
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", externalBodyUrl.c_str());
|
||||
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
|
||||
msgOp->send_message(from.asString().c_str(), to.asString().c_str(), content_type, nullptr, nullptr);
|
||||
|
|
@ -1323,16 +1372,14 @@ void ChatMessagePrivate::send () {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO Remove : This won't be necessary once we store the contentsList
|
||||
if (!getText().empty() && getText() == clearTextMessage) {
|
||||
/* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */
|
||||
setText(clearTextMessage);
|
||||
for (Content &content : contents) {
|
||||
// Restore FileContents and remove FileTransferContents
|
||||
if (content.getContentType() == ContentType::FileTransfer) {
|
||||
FileTransferContent fileTransferContent = static_cast<FileTransferContent&>(content);
|
||||
q->removeContent(content);
|
||||
q->addContent(fileTransferContent.getFileContent());
|
||||
}
|
||||
}
|
||||
if (getContentType().isValid() && (getContentType() != clearTextContentType)) {
|
||||
/* We replace the encrypted content type by the original one */
|
||||
setContentType(clearTextContentType);
|
||||
}
|
||||
// End of TODO Remove
|
||||
|
||||
q->setImdnMessageId(op->get_call_id()); /* must be known at that time */
|
||||
|
||||
|
|
@ -1373,16 +1420,6 @@ shared_ptr<ChatRoom> ChatMessage::getChatRoom () const {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const string &ChatMessage::getExternalBodyUrl () const {
|
||||
L_D();
|
||||
return d->externalBodyUrl;
|
||||
}
|
||||
|
||||
void ChatMessage::setExternalBodyUrl (const string &url) {
|
||||
L_D();
|
||||
d->externalBodyUrl = url;
|
||||
}
|
||||
|
||||
time_t ChatMessage::getTime () const {
|
||||
L_D();
|
||||
return d->time;
|
||||
|
|
@ -1434,19 +1471,6 @@ bool ChatMessage::isRead () const {
|
|||
return d->state == State::Delivered || d->state == State::Displayed || d->state == State::DeliveredToUser;
|
||||
}
|
||||
|
||||
const string &ChatMessage::getAppdata () const {
|
||||
L_D();
|
||||
return d->appData;
|
||||
}
|
||||
|
||||
void ChatMessage::setAppdata (const string &appData) {
|
||||
L_D();
|
||||
d->appData = appData;
|
||||
|
||||
// TODO: history.
|
||||
// linphone_chat_message_store_appdata(L_GET_C_BACK_PTR(this));
|
||||
}
|
||||
|
||||
const Address &ChatMessage::getFromAddress () const {
|
||||
L_D();
|
||||
return d->from;
|
||||
|
|
@ -1475,16 +1499,6 @@ const Address &ChatMessage::getRemoteAddress () const {
|
|||
return getDirection() != Direction::Incoming ? getToAddress() : getFromAddress();
|
||||
}
|
||||
|
||||
const string &ChatMessage::getFileTransferFilepath () const {
|
||||
L_D();
|
||||
return d->fileTransferFilePath;
|
||||
}
|
||||
|
||||
void ChatMessage::setFileTransferFilepath (const string &path) {
|
||||
L_D();
|
||||
d->fileTransferFilePath = path;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const LinphoneErrorInfo *ChatMessage::getErrorInfo () const {
|
||||
|
|
@ -1559,48 +1573,6 @@ void ChatMessage::removeCustomHeader (const string &headerName) {
|
|||
d->customHeaders.erase(headerName);
|
||||
}
|
||||
|
||||
bool ChatMessage::hasTextContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::PlainText) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Content &ChatMessage::getTextContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::PlainText) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return Content::Empty;
|
||||
}
|
||||
|
||||
bool ChatMessage::hasFileTransferContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Content &ChatMessage::getFileTransferContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return Content::Empty;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatMessage::store () {
|
||||
L_D();
|
||||
|
||||
|
|
@ -1660,44 +1632,32 @@ void ChatMessage::sendDisplayNotification () {
|
|||
d->sendImdn(Imdn::Type::Display, LinphoneReasonNone);
|
||||
}
|
||||
|
||||
int ChatMessage::uploadFile () {
|
||||
int ChatMessage::downloadFile(FileTransferContent& fileTransferContent) {
|
||||
L_D();
|
||||
|
||||
if (d->httpRequest) {
|
||||
lError() << "linphone_chat_room_upload_file(): there is already an upload in progress.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
belle_http_request_listener_callbacks_t cbs = { 0 };
|
||||
cbs.process_response = _chat_message_process_response_from_post_file;
|
||||
cbs.process_io_error = _chat_message_process_io_error_upload;
|
||||
cbs.process_auth_requested = _chat_message_process_auth_requested_upload;
|
||||
|
||||
int err = d->startHttpTransfer(linphone_core_get_file_transfer_server(getCore()->getCCore()), "POST", &cbs);
|
||||
if (err == -1)
|
||||
d->setState(State::NotDelivered);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int ChatMessage::downloadFile () {
|
||||
L_D();
|
||||
|
||||
|
||||
if (d->httpRequest) {
|
||||
lError() << "linphone_chat_message_download_file(): there is already a download in progress";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hasFileTransferContent()) {
|
||||
d->currentFileTransferContent = (Content *)&getFileTransferContent();
|
||||
if (fileTransferContent.getContentType() != ContentType::FileTransfer) {
|
||||
lError() << "linphone_chat_message_download_file(): content type is not FileTransfer";
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->createFileTransferInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent);
|
||||
FileContent fileContent = fileTransferContent.getFileContent();
|
||||
d->currentFileContentToTransfer = &fileContent;
|
||||
if (d->currentFileContentToTransfer == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
belle_http_request_listener_callbacks_t cbs = { 0 };
|
||||
cbs.process_response_headers = _chat_process_response_headers_from_get_file;
|
||||
cbs.process_response = _chat_message_process_response_from_get_file;
|
||||
cbs.process_io_error = _chat_message_process_io_error_download;
|
||||
cbs.process_auth_requested = _chat_message_process_auth_requested_download;
|
||||
int err = d->startHttpTransfer(d->externalBodyUrl, "GET", &cbs);
|
||||
int err = d->startHttpTransfer(fileTransferContent.getFileUrl(), "GET", &cbs); // File URL has been set by createFileTransferInformationsFromVndGsmaRcsFtHttpXml
|
||||
|
||||
if (err == -1) return -1;
|
||||
// start the download, status is In Progress
|
||||
|
|
@ -1716,9 +1676,9 @@ void ChatMessage::cancelFileTransfer () {
|
|||
if (chatRoom) {
|
||||
shared_ptr<Core> core = getCore();
|
||||
lInfo() << "Canceling file transfer " << (
|
||||
d->externalBodyUrl.empty()
|
||||
d->currentFileContentToTransfer->getFilePath().empty()
|
||||
? linphone_core_get_file_transfer_server(core->getCCore())
|
||||
: d->externalBodyUrl.c_str()
|
||||
: d->currentFileContentToTransfer->getFilePath().c_str()
|
||||
);
|
||||
belle_http_provider_cancel_request(core->getCCore()->http_provider, d->httpRequest);
|
||||
} else {
|
||||
|
|
@ -1780,4 +1740,83 @@ int ChatMessage::putCharacter (uint32_t character) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Below methods are only for C API backward compatibility...
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool ChatMessage::hasTextContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::PlainText) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Content &ChatMessage::getTextContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::PlainText) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return Content::Empty;
|
||||
}
|
||||
|
||||
bool ChatMessage::hasFileTransferContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Content &ChatMessage::getFileTransferContent() const {
|
||||
L_D();
|
||||
for (const auto &c : d->contents) {
|
||||
if (c.getContentType() == ContentType::FileTransfer) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return Content::Empty;
|
||||
}
|
||||
|
||||
const string &ChatMessage::getFileTransferFilepath () const {
|
||||
L_D();
|
||||
return d->fileTransferFilePath;
|
||||
}
|
||||
|
||||
void ChatMessage::setFileTransferFilepath (const string &path) {
|
||||
L_D();
|
||||
d->fileTransferFilePath = path;
|
||||
}
|
||||
|
||||
const string &ChatMessage::getAppdata () const {
|
||||
L_D();
|
||||
return d->appData;
|
||||
}
|
||||
|
||||
void ChatMessage::setAppdata (const string &appData) {
|
||||
L_D();
|
||||
d->appData = appData;
|
||||
|
||||
// TODO: history.
|
||||
// linphone_chat_message_store_appdata(L_GET_C_BACK_PTR(this));
|
||||
}
|
||||
|
||||
const string &ChatMessage::getExternalBodyUrl () const {
|
||||
L_D();
|
||||
return d->externalBodyUrl;
|
||||
}
|
||||
|
||||
void ChatMessage::setExternalBodyUrl (const string &url) {
|
||||
L_D();
|
||||
d->externalBodyUrl = url;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
class Address;
|
||||
class ChatRoom;
|
||||
class Content;
|
||||
class FileTransferContent;
|
||||
class ChatMessagePrivate;
|
||||
|
||||
class LINPHONE_PUBLIC ChatMessage : public Object, public CoreAccessor {
|
||||
|
|
@ -61,8 +62,6 @@ public:
|
|||
void setAppdata (const std::string &appData);
|
||||
const std::string &getExternalBodyUrl () const;
|
||||
void setExternalBodyUrl (const std::string &url);
|
||||
int uploadFile ();
|
||||
int downloadFile ();
|
||||
void cancelFileTransfer ();
|
||||
int putCharacter (uint32_t character);
|
||||
void updateState (State state);
|
||||
|
|
@ -115,6 +114,8 @@ public:
|
|||
void addCustomHeader (const std::string &headerName, const std::string &headerValue);
|
||||
void removeCustomHeader (const std::string &headerName);
|
||||
|
||||
int downloadFile (FileTransferContent& content);
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(ChatMessage);
|
||||
L_DISABLE_COPY(ChatMessage);
|
||||
|
|
|
|||
43
src/content/content-p.h
Normal file
43
src/content/content-p.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* content-p.h
|
||||
* Copyright (C) 2010-2017 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 _CONTENT_P_H_
|
||||
#define _CONTENT_P_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "object/clonable-object-p.h"
|
||||
#include "object/object-p.h"
|
||||
#include "content-type.h"
|
||||
#include "content.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ContentPrivate : public ClonableObjectPrivate {
|
||||
public:
|
||||
std::vector<char> body;
|
||||
ContentType contentType;
|
||||
std::string contentDisposition;
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _CONTENT_P_H_
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
#include "content-type.h"
|
||||
#include "object/clonable-object-p.h"
|
||||
|
||||
#include "content-p.h"
|
||||
#include "content.h"
|
||||
#include "linphone/core.h"
|
||||
|
||||
|
|
@ -29,14 +29,6 @@ using namespace std;
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ContentPrivate : public ClonableObjectPrivate {
|
||||
public:
|
||||
vector<char> body;
|
||||
ContentType contentType;
|
||||
string contentDisposition;
|
||||
size_t expectedSize;
|
||||
};
|
||||
|
||||
const Content Content::Empty;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -48,7 +40,6 @@ Content::Content (const Content &src) : ClonableObject(*new ContentPrivate), App
|
|||
d->body = src.getBody();
|
||||
d->contentType = src.getContentType();
|
||||
d->contentDisposition = src.getContentDisposition();
|
||||
d->expectedSize = src.getExpectedSize();
|
||||
}
|
||||
|
||||
Content::Content (Content &&src) : ClonableObject(*new ContentPrivate), AppDataContainer(move(src)) {
|
||||
|
|
@ -56,7 +47,10 @@ Content::Content (Content &&src) : ClonableObject(*new ContentPrivate), AppDataC
|
|||
d->body = move(src.getPrivate()->body);
|
||||
d->contentType = move(src.getPrivate()->contentType);
|
||||
d->contentDisposition = move(src.getPrivate()->contentDisposition);
|
||||
d->expectedSize = move(src.getExpectedSize());
|
||||
}
|
||||
|
||||
Content::Content (ContentPrivate &p) : ClonableObject(p) {
|
||||
|
||||
}
|
||||
|
||||
Content &Content::operator= (const Content &src) {
|
||||
|
|
@ -65,7 +59,6 @@ Content &Content::operator= (const Content &src) {
|
|||
d->body = src.getBody();
|
||||
d->contentType = src.getContentType();
|
||||
d->contentDisposition = src.getContentDisposition();
|
||||
d->expectedSize = src.getExpectedSize();
|
||||
AppDataContainer::operator=(src);
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +70,6 @@ Content &Content::operator= (Content &&src) {
|
|||
d->body = move(src.getPrivate()->body);
|
||||
d->contentType = move(src.getPrivate()->contentType);
|
||||
d->contentDisposition = move(src.getPrivate()->contentDisposition);
|
||||
d->expectedSize = move(src.getExpectedSize());
|
||||
AppDataContainer::operator=(move(src));
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -150,16 +142,6 @@ size_t Content::getSize () const {
|
|||
return d->body.size();
|
||||
}
|
||||
|
||||
void Content::setExpectedSize(size_t expectedSize) {
|
||||
L_D();
|
||||
d->expectedSize = expectedSize;
|
||||
}
|
||||
|
||||
size_t Content::getExpectedSize() const {
|
||||
L_D();
|
||||
return d->expectedSize;
|
||||
}
|
||||
|
||||
bool Content::isEmpty () const {
|
||||
return getSize() == 0;
|
||||
}
|
||||
|
|
@ -174,8 +156,6 @@ LinphoneContent * Content::toLinphoneContent() const {
|
|||
content = linphone_core_create_content(NULL);
|
||||
linphone_content_set_type(content, getContentType().getType().c_str());
|
||||
linphone_content_set_subtype(content, getContentType().getSubType().c_str());
|
||||
linphone_content_set_size(content, getExpectedSize());
|
||||
linphone_content_set_name(content, getContentDisposition().c_str());
|
||||
return content;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,17 +60,17 @@ public:
|
|||
|
||||
size_t getSize () const;
|
||||
|
||||
void setExpectedSize(size_t expectedSize);
|
||||
size_t getExpectedSize() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
bool isEmpty () const;
|
||||
|
||||
LinphoneContent * toLinphoneContent() const;
|
||||
virtual LinphoneContent * toLinphoneContent() const;
|
||||
|
||||
static const Content Empty;
|
||||
|
||||
protected:
|
||||
explicit Content (ContentPrivate &p);
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(Content);
|
||||
};
|
||||
|
|
|
|||
126
src/content/file-content.cpp
Normal file
126
src/content/file-content.cpp
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* file-content.cpp
|
||||
* Copyright (C) 2010-2017 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 "content-p.h"
|
||||
#include "file-content.h"
|
||||
#include "linphone/core.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class FileContentPrivate : public ContentPrivate {
|
||||
public:
|
||||
string fileName;
|
||||
string filePath;
|
||||
size_t fileSize;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
FileContent::FileContent() : Content(*new FileContentPrivate()) {
|
||||
|
||||
}
|
||||
|
||||
FileContent::FileContent (const FileContent &src) : Content(*new FileContentPrivate) {
|
||||
L_D();
|
||||
d->fileName = src.getFileName();
|
||||
d->filePath = src.getFilePath();
|
||||
d->fileSize = src.getFileSize();
|
||||
}
|
||||
|
||||
FileContent::FileContent (FileContent &&src) : Content(*new FileContentPrivate) {
|
||||
L_D();
|
||||
d->fileName = move(src.getPrivate()->fileName);
|
||||
d->filePath = move(src.getPrivate()->filePath);
|
||||
d->fileSize = move(src.getPrivate()->fileSize);
|
||||
}
|
||||
|
||||
FileContent &FileContent::operator= (const FileContent &src) {
|
||||
L_D();
|
||||
if (this != &src) {
|
||||
Content::operator=(src);
|
||||
d->fileName = src.getFileName();
|
||||
d->filePath = src.getFilePath();
|
||||
d->fileSize = src.getFileSize();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileContent &FileContent::operator= (FileContent &&src) {
|
||||
L_D();
|
||||
Content::operator=(move(src));
|
||||
d->fileName = move(src.getPrivate()->fileName);
|
||||
d->filePath = move(src.getPrivate()->filePath);
|
||||
d->fileSize = move(src.getPrivate()->fileSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FileContent::operator== (const FileContent &content) const {
|
||||
L_D();
|
||||
return Content::operator==(content) &&
|
||||
d->fileName == content.getFileName() &&
|
||||
d->filePath == content.getFilePath() &&
|
||||
d->fileSize == content.getFileSize();
|
||||
}
|
||||
|
||||
void FileContent::setFileSize(size_t size) {
|
||||
L_D();
|
||||
d->fileSize = size;
|
||||
}
|
||||
|
||||
size_t FileContent::getFileSize() const {
|
||||
L_D();
|
||||
return d->fileSize;
|
||||
}
|
||||
|
||||
void FileContent::setFileName(const string &name) {
|
||||
L_D();
|
||||
d->fileName = name;
|
||||
}
|
||||
|
||||
string FileContent::getFileName() const {
|
||||
L_D();
|
||||
return d->fileName;
|
||||
}
|
||||
|
||||
void FileContent::setFilePath(const string &path) {
|
||||
L_D();
|
||||
d->filePath = path;
|
||||
}
|
||||
|
||||
string FileContent::getFilePath() const {
|
||||
L_D();
|
||||
return d->filePath;
|
||||
}
|
||||
|
||||
LinphoneContent * FileContent::toLinphoneContent() const {
|
||||
LinphoneContent* content;
|
||||
content = linphone_core_create_content(NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
58
src/content/file-content.h
Normal file
58
src/content/file-content.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* file-content.h
|
||||
* Copyright (C) 2010-2017 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 _FILE_CONTENT_H_
|
||||
#define _FILE_CONTENT_H_
|
||||
|
||||
#include "content.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class FileContentPrivate;
|
||||
|
||||
class LINPHONE_PUBLIC FileContent : public Content {
|
||||
public:
|
||||
FileContent();
|
||||
FileContent (const FileContent &src);
|
||||
FileContent (FileContent &&src);
|
||||
|
||||
FileContent &operator= (const FileContent &src);
|
||||
FileContent &operator= (FileContent &&src);
|
||||
bool operator== (const FileContent &content) const;
|
||||
|
||||
void setFileSize(size_t size);
|
||||
size_t getFileSize() const;
|
||||
|
||||
void setFileName(const std::string &name);
|
||||
std::string getFileName() const;
|
||||
|
||||
void setFilePath(const std::string &path);
|
||||
std::string getFilePath() const;
|
||||
|
||||
LinphoneContent * toLinphoneContent() const override;
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(FileContent);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _FILE_CONTENT_H_
|
||||
123
src/content/file-transfer-content.cpp
Normal file
123
src/content/file-transfer-content.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* file-transfer-content.cpp
|
||||
* Copyright (C) 2010-2017 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 "content-p.h"
|
||||
#include "file-transfer-content.h"
|
||||
#include "linphone/core.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class FileTransferContentPrivate : public ContentPrivate {
|
||||
public:
|
||||
string fileUrl;
|
||||
string filePath;
|
||||
FileContent fileContent;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
FileTransferContent::FileTransferContent() : Content(*new FileTransferContentPrivate()) {
|
||||
|
||||
}
|
||||
|
||||
FileTransferContent::FileTransferContent (const FileTransferContent &src) : Content(*new FileTransferContentPrivate) {
|
||||
L_D();
|
||||
d->fileUrl = src.getFileUrl();
|
||||
d->filePath = src.getFilePath();
|
||||
d->fileContent = src.getFileContent();
|
||||
}
|
||||
|
||||
FileTransferContent::FileTransferContent (FileTransferContent &&src) : Content(*new FileTransferContentPrivate) {
|
||||
L_D();
|
||||
d->fileUrl = move(src.getPrivate()->fileUrl);
|
||||
d->filePath = move(src.getPrivate()->filePath);
|
||||
d->fileContent = move(src.getPrivate()->fileContent);
|
||||
}
|
||||
|
||||
FileTransferContent &FileTransferContent::operator= (const FileTransferContent &src) {
|
||||
L_D();
|
||||
if (this != &src) {
|
||||
Content::operator=(src);
|
||||
d->fileUrl = src.getFileUrl();
|
||||
d->filePath = src.getFilePath();
|
||||
d->fileContent = src.getFileContent();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileTransferContent &FileTransferContent::operator= (FileTransferContent &&src) {
|
||||
L_D();
|
||||
Content::operator=(move(src));
|
||||
d->fileUrl = move(src.getPrivate()->fileUrl);
|
||||
d->filePath = move(src.getPrivate()->filePath);
|
||||
d->fileContent = move(src.getPrivate()->fileContent);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FileTransferContent::operator== (const FileTransferContent &content) const {
|
||||
L_D();
|
||||
return Content::operator==(content) &&
|
||||
d->fileUrl == content.getFileUrl() &&
|
||||
d->filePath == content.getFilePath();
|
||||
}
|
||||
|
||||
void FileTransferContent::setFileUrl(const string &url) {
|
||||
L_D();
|
||||
d->fileUrl = url;
|
||||
}
|
||||
|
||||
string FileTransferContent::getFileUrl() const {
|
||||
L_D();
|
||||
return d->fileUrl;
|
||||
}
|
||||
|
||||
void FileTransferContent::setFilePath(const string &path) {
|
||||
L_D();
|
||||
d->filePath = path;
|
||||
}
|
||||
|
||||
string FileTransferContent::getFilePath() const {
|
||||
L_D();
|
||||
return d->filePath;
|
||||
}
|
||||
|
||||
void FileTransferContent::setFileContent(const FileContent &content) {
|
||||
L_D();
|
||||
d->fileContent = content;
|
||||
}
|
||||
|
||||
FileContent FileTransferContent::getFileContent() const {
|
||||
L_D();
|
||||
return d->fileContent;
|
||||
}
|
||||
|
||||
LinphoneContent * FileTransferContent::toLinphoneContent() const {
|
||||
LinphoneContent* content;
|
||||
content = linphone_core_create_content(NULL);
|
||||
linphone_content_set_type(content, getContentType().getType().c_str());
|
||||
linphone_content_set_subtype(content, getContentType().getSubType().c_str());
|
||||
return content;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
59
src/content/file-transfer-content.h
Normal file
59
src/content/file-transfer-content.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* file-transfer-content.h
|
||||
* Copyright (C) 2010-2017 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 _FILE_TRANSFER_CONTENT_H_
|
||||
#define _FILE_TRANSFER_CONTENT_H_
|
||||
|
||||
#include "content.h"
|
||||
#include "file-content.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class FileTransferContentPrivate;
|
||||
|
||||
class LINPHONE_PUBLIC FileTransferContent : public Content {
|
||||
public:
|
||||
FileTransferContent();
|
||||
FileTransferContent (const FileTransferContent &src);
|
||||
FileTransferContent (FileTransferContent &&src);
|
||||
|
||||
FileTransferContent &operator= (const FileTransferContent &src);
|
||||
FileTransferContent &operator= (FileTransferContent &&src);
|
||||
bool operator== (const FileTransferContent &content) const;
|
||||
|
||||
void setFileUrl(const std::string &url);
|
||||
std::string getFileUrl() const;
|
||||
|
||||
void setFilePath(const std::string &path);
|
||||
std::string getFilePath() const;
|
||||
|
||||
void setFileContent(const FileContent &content);
|
||||
FileContent getFileContent() const;
|
||||
|
||||
LinphoneContent * toLinphoneContent() const override;
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(FileTransferContent);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _FILE_TRANSFER_CONTENT_H_
|
||||
Loading…
Add table
Reference in a new issue