2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 * @author Pawel Misiak (p.misiak@samsung.com)
27 #include <dpl/log/log.h>
28 #include <Commons/Exception.h>
29 #include <API/Messaging/ReqReceiverMessage.h>
30 #include "Messaging.h"
31 #include "CallbackMgr.h"
32 #include "MsgServiceHandleMgr.h"
35 #include <MapiControl.h>
36 #include <MapiMessage.h>
37 #include <MapiStorage.h>
41 const char* TEXT_AREA = "Text";
42 const char* TEXT_FILE_EXTENSION = ".txt";
43 const int WHITE_COLOR = 0xffffff;
44 const int BLACK_COLOR = 0x000000;
45 const int ROOT_LAYOUT_WIDTH = 100;
46 const int ROOT_LAYOUT_HEIGHT = 100;
47 const char* EMPTY_ID = "0";
51 using namespace WrtDeviceApis::Messaging;
52 using namespace WrtDeviceApis::Messaging::Api;
54 namespace WrtDeviceApis {
56 Mms::Mms(const string& id) :
58 m_bodyFilePath(string(tmpnam(NULL)) + TEXT_FILE_EXTENSION),
62 LogDebug("m_id=" << getIdRef());
63 LogDebug("m_msgType=" << getMessageType());
64 if (getIdRef().empty()) {
67 readExistingMessage();
76 // release platform message structure
77 msg_release_message(&m_messageData);
81 //trying to remove file, return value is skipped
82 if (!m_bodyFilePath.empty()) {
83 LogDebug("remove tmp file=" << m_bodyFilePath);
84 (void) ::remove(m_bodyFilePath.c_str());
88 void Mms::createNewMessage()
91 msg_release_message(&m_messageData);
94 m_messageData = msg_new_message();
96 MSG_SENDINGOPT_S sendOpt;
97 memset(&sendOpt, 0, sizeof(MSG_SENDINGOPT_S));
99 sendOpt.bSetting = false;
101 // initialize platform message structure
102 msg_set_message_id(m_messageData, 0); // It should be set 0
103 msg_set_folder_id(m_messageData, MSG_DRAFT_ID);
104 msg_set_message_type(m_messageData, MSG_TYPE_MMS);
105 msg_set_storage_id(m_messageData, MSG_STORAGE_PHONE);
106 msg_set_subject(m_messageData, "");
107 msg_set_read_status(m_messageData, false);
108 msg_set_network_status(m_messageData, MSG_NETWORK_NOT_SEND);
109 msg_set_direction_info(m_messageData, MSG_DIRECTION_TYPE_MO);
110 msg_set_priority_info(m_messageData, MSG_MESSAGE_PRIORITY_NORMAL);
112 tm dateT = getDateTime();
113 msg_set_time(m_messageData, mktime(&dateT));
115 setMmsType(MULTIPART_MIXED);
116 setReadStatus(false);
118 LogDebug("Message created successfully, Id: " << getIdRef());
121 void Mms::readExistingMessage()
125 if (getIdRef().empty() || (EMPTY_ID == getIdRef())) {
126 ThrowMsg(Commons::PlatformException, "Empty id.");
130 MSG_SENDINGOPT_S option;
131 option.bSetting = false;
134 msg_release_message(&m_messageData);
135 m_messageData = NULL;
136 // crate new structure
137 m_messageData = msg_new_message();
139 // trying to get message from platform
140 if (MSG_SUCCESS != msg_get_message(
141 MsgGetCommonHandle(), convertId(getIdRef()), m_messageData,
143 LogError("get message error");
144 Throw(Commons::PlatformException);
146 LogDebug("message found with msgId=" << getIdRef());
148 // read all mms dat to abstraction layer
149 readRecipientList(m_messageData);
150 readPriority(m_messageData);
151 readSubject(m_messageData);
152 readBodyAndAttachments(m_messageData);
153 readFolder(m_messageData);
154 readDateTime(m_messageData);
155 readReadStatus(m_messageData);
157 Catch(Commons::Exception) {
162 void Mms::readDateTime(msg_message_t& messageData)
164 tm* time = localtime(msg_get_time(messageData));
166 LogError("localtime failed");
167 Throw(Commons::PlatformException);
172 void Mms::readReadStatus(msg_message_t& messageData)
174 setReadStatus(msg_is_read(messageData));
177 void Mms::readFolder(msg_message_t& messageData)
179 switch (msg_get_folder_id(messageData)) {
181 setFolderType(Api::INBOX);
184 setFolderType(Api::OUTBOX);
187 setFolderType(Api::SENTBOX);
190 setFolderType(Api::DRAFTBOX);
193 setFolderType(Api::SPAMBOX);
196 ThrowMsg(Commons::PlatformException, "Unsupported folder id.");
200 void Mms::readPriority(msg_message_t& messageData)
202 switch (msg_get_priority_info(messageData)) {
203 case MSG_MESSAGE_PRIORITY_LOW:
204 setPriority(MessagePriority::LOW);
206 case MSG_MESSAGE_PRIORITY_NORMAL:
207 setPriority(MessagePriority::NORMAL);
209 case MSG_MESSAGE_PRIORITY_HIGH:
210 setPriority(MessagePriority::HIGH);
213 LogError("Wrong priority type");
214 ThrowMsg(Commons::PlatformException, "Wrong priority type");
218 void Mms::readRecipientList(msg_message_t& messageData)
220 std::string phoneNumber;
221 int recipientCount = msg_get_address_count(messageData);
222 LogDebug("Recipient count " << recipientCount);
223 for (int i = 0; i < recipientCount; ++i) {
224 int type = msg_get_direction_info(messageData);
226 if (MSG_DIRECTION_TYPE_MT == type) {
227 phoneNumber = msg_get_ith_address(messageData, i);
228 if (validatePhoneNumber(phoneNumber)) {
229 setSourceAddress(phoneNumber);
230 setFrom(phoneNumber);
232 LogDebug("phone number: " << phoneNumber);
233 } else if (MSG_DIRECTION_TYPE_MO == type) {
234 switch (msg_get_ith_recipient_type(messageData, i)) {
235 case MSG_RECIPIENTS_TYPE_TO:
236 appendToRecipients(msg_get_ith_address(messageData, i));
238 case MSG_RECIPIENTS_TYPE_CC:
239 appendCcRecipients(msg_get_ith_address(messageData, i));
241 case MSG_RECIPIENTS_TYPE_BCC:
242 appendBccRecipients(msg_get_ith_address(messageData, i));
245 LogError("Wrong type of recipient");
246 ThrowMsg(Commons::PlatformException, "Wrong type of recipient");
249 LogError("Wrong type of recipient");
250 ThrowMsg(Commons::PlatformException, "Wrong type of recipient");
255 void Mms::readSubject(msg_message_t& messageData)
257 setSubject(msg_get_subject(messageData));
260 void Mms::readBodyAndAttachments(msg_message_t& messageData)
263 MMS_MESSAGE_DATA_S msgBody;
264 memset(&msgBody, 0, sizeof(MMS_MESSAGE_DATA_S));
265 msg_mms_get_message_body(messageData, &msgBody);
267 //if any page then multipart is related type
268 if (msgBody.pageCnt > 0) {
269 setMmsType(MULTIPART_RELATED);
271 setMmsType(MULTIPART_MIXED);
274 LogDebug("page count: " << msgBody.pageCnt);
276 for (int p = 0; p < msgBody.pageCnt; ++p) {
277 LogDebug("page " << p);
278 MMS_PAGE_S *page = msg_mms_get_page(p);
280 LogError("returned page is null, continue");
283 for (int m = 0; m < page->mediaCnt; ++m) {
284 LogDebug("media file " << m);
285 MMS_MEDIA_S* media = msg_mms_get_media(page, m);
287 LogError("returned media is null, continue");
290 if (0 == p && MMS_SMIL_MEDIA_TEXT == media->mediatype) {
291 //text value on first page goes to body attribute
292 LogDebug("setting body from " << media->szFilePath);
294 f = fopen(media->szFilePath, "r");
296 LogError("cannot read file with body" << media->szFilePath);
297 ThrowMsg(Commons::PlatformException,
298 "Cannot read file with body");
300 fseek(f, 0, SEEK_END);
301 long int size = ftell(f);
302 fseek(f, 0, SEEK_SET);
303 char* data = new (nothrow) char[size + 1];
305 memset(data, 0, size + 1);
306 fread(data, 1, size, f);
310 LogError("body is not set");
312 LogDebug("message body: '" << getBody() << "'");
315 LogDebug("adding attachment " << media->szFilePath);
316 IAttachmentPtr attachment = appendAttachment(media->szFilePath,
318 if (NULL != media->szFileName &&
319 strnlen(media->szFileName, MSG_FILENAME_LEN_MAX) > 0) {
320 LogDebug("renaming to " << media->szFileName);
321 attachment->rename(media->szFileName);
322 } else if (MMS_SMIL_MEDIA_TEXT == media->mediatype) {
323 std::stringstream newName;
324 newName << "body_page_" << p + 1 << ".txt";
325 LogDebug("renaming to " << newName.str());
326 attachment->rename(newName.str());
332 LogDebug("attachment count: " << msgBody.attachCnt);
333 for (int a = 0; a < msgBody.attachCnt; ++a) {
334 MMS_ATTACH_S* attachment = msg_mms_get_attachment(a);
336 LogError("attachment is null, continue");
339 IAttachmentPtr att = appendAttachment(attachment->szFilePath, false);
340 if (NULL != attachment->szFileName &&
341 strnlen(attachment->szFileName, MSG_FILENAME_LEN_MAX) > 0) {
342 LogDebug("renaming to " << attachment->szFileName);
343 att->rename(attachment->szFileName);
348 void Mms::update(bool draftsOnly)
350 LogDebug("updating m_id=" << getIdRef());
352 if (!m_messageData) {
353 //error if platform message not exists
354 LogError("message can not be updated");
355 Throw(Commons::PlatformException);
358 //update mms data from abstraction
359 if (!draftsOnly || getCurrentFolder() == Api::DRAFTBOX) {
361 updateBodyAndAttachments();
362 updateRecipientList();
368 void Mms::updatePriority()
370 if (isPriorityValid()) {
374 LogInfo("MMS updating priority");
376 //set priority in platform
377 switch (getPriority()) {
378 case MessagePriority::LOW:
379 priority = MSG_MESSAGE_PRIORITY_LOW;
381 case MessagePriority::NORMAL:
382 priority = MSG_MESSAGE_PRIORITY_NORMAL;
384 case MessagePriority::HIGH:
385 priority = MSG_MESSAGE_PRIORITY_HIGH;
388 LogError("Wrong priority");
389 Throw(Commons::PlatformException);
392 msg_set_priority_info(m_messageData, MSG_MESSAGE_PRIORITY_LOW)) {
393 LogError("Error during setting priority");
394 Throw(Commons::PlatformException);
398 void Mms::updateRecipientList()
400 // check if abstraction recipient value has been changed
401 if (getToRecipients().isValid() &&
402 getBccRecipients().isValid() &&
403 getCcRecipients().isValid()) {
407 LogInfo("MMS updating platform recipients");
409 // reset addresses in platform structure
410 msg_reset_address(m_messageData);
412 vector<string> to = getToRecipients().getRecipients();
413 vector<string> cc = getCcRecipients().getRecipients();
414 vector<string> bcc = getBccRecipients().getRecipients();
416 // update addresses in platform structure
418 LogInfo("updating to");
419 for (size_t i = 0; i < to.size(); i++) {
420 if (msg_get_address_count(m_messageData) >= MAX_TO_ADDRESS_CNT) {
421 LogError("max number of recipient exceeded");
424 LogDebug("adding to[" << i << "]=" << to[i]);
425 if (msg_add_address(m_messageData, to[i].c_str(),
426 MSG_RECIPIENTS_TYPE_TO) != MSG_SUCCESS) {
427 LogError("problem with adding to address");
428 ThrowMsg(Commons::PlatformException,
429 "Problem with adding to address");
435 LogInfo("updating cc");
436 for (size_t i = 0; i < cc.size(); i++) {
437 if (msg_get_address_count(m_messageData) >= MAX_TO_ADDRESS_CNT) {
438 LogError("max number of recipient exceeded");
441 LogDebug("adding cc[" << i << "]=" << cc[i]);
442 if (msg_add_address(m_messageData, cc[i].c_str(),
443 MSG_RECIPIENTS_TYPE_CC) != MSG_SUCCESS) {
444 LogError("problem with adding cc address");
445 ThrowMsg(Commons::PlatformException,
446 "Problem with adding cc address");
452 LogInfo("updating bcc");
453 for (size_t i = 0; i < bcc.size(); i++) {
454 if (msg_get_address_count(m_messageData) >= MAX_TO_ADDRESS_CNT) {
455 LogError("max number of recipient exceeded");
458 LogDebug("adding bcc[" << i << "]=" << bcc[i]);
459 if (msg_add_address(m_messageData, bcc[i].c_str(),
460 MSG_RECIPIENTS_TYPE_BCC) != MSG_SUCCESS) {
461 LogError("problem with adding bcc address");
462 ThrowMsg(Commons::PlatformException,
463 "Problem with adding bcc address");
470 setBccValidity(true);
473 void Mms::updateSubject()
475 // check if abstraction subject value has been changed
476 if (isSubjectValid()) {
479 LogInfo("updating platform subject: " << getSubjectRef());
481 msg_set_subject(m_messageData, getSubjectRef().c_str())) {
482 LogError("problem with setting subject");
483 ThrowMsg(Commons::PlatformException, "Problem with setting subject");
485 setSubjectValidity(true);
488 void Mms::updateBodyAndAttachments()
490 // check if attachment or body source address value has been changed
491 if (isAttachmentsValid() && isBodyValid()) {
494 MMS_MESSAGE_DATA_S *mmsData = NULL;
495 LogInfo("updating platform body and attachment");
499 if (getMessageType() != MMS) {
500 LogError("Wrong msg type");
501 ThrowMsg(Commons::PlatformException, "Wrong msg type");
503 mmsData = msg_mms_create_message();
505 LogError("create message body failed");
506 ThrowMsg(Commons::PlatformException, "create message body failed");
510 if (!getBodyRef().empty()) {
512 f = fopen(m_bodyFilePath.c_str(), "w");
514 LogError("cannot create file with body" << m_bodyFilePath);
515 ThrowMsg(Commons::PlatformException,
516 "cannot create file with body");
518 LogDebug("body file: " << m_bodyFilePath);
519 fprintf(f, getBodyRef().c_str());
521 if (!msg_mms_set_rootlayout(mmsData, ROOT_LAYOUT_WIDTH,
522 ROOT_LAYOUT_HEIGHT, WHITE_COLOR)) {
523 LogError("cannot create root layout");
524 ThrowMsg(Commons::PlatformException,
525 "cannot create root layout");
527 if (!msg_mms_add_region(mmsData, TEXT_AREA, 0, 0, ROOT_LAYOUT_WIDTH,
528 ROOT_LAYOUT_HEIGHT, WHITE_COLOR)) {
529 LogError("cannot create region");
530 ThrowMsg(Commons::PlatformException, "cannot create region");
532 MMS_PAGE_S* page = msg_mms_add_page(mmsData, 0);
534 LogError("cannot create page");
535 ThrowMsg(Commons::PlatformException, "cannot create page");
537 MMS_MEDIA_S* media = msg_mms_add_media(page,
541 m_bodyFilePath.c_str()));
543 LogError("cannot create media");
544 ThrowMsg(Commons::PlatformException, "cannot create media");
546 media->sMedia.sText.nColor = BLACK_COLOR;
547 media->sMedia.sText.nSize = MMS_SMIL_FONT_SIZE_NORMAL;
553 for (size_t i = 0; i < getAttachmentsRef().size(); ++i) {
554 Api::IAttachmentPtr att = getAttachment(i);
559 LogDebug("Add attachment=" << att->getFullPath());
561 errnum = stat(att->getFullPath().c_str(), &buffer);
563 LogError("Opening file: " <<
564 att->getFullPath().c_str() <<
565 " " << strerror(errnum));
566 ThrowMsg(Commons::PlatformException,
567 "cannot open attachment file");
570 //this function should return valid pointer
571 if (!msg_mms_add_attachment(mmsData,
572 const_cast<char*>(att->getFullPath().
574 LogError("add attachment failed");
575 ThrowMsg(Commons::PlatformException, "add attachment failed");
577 LogDebug("Attachment added");
583 if (MSG_SUCCESS != msg_mms_set_message_body(m_messageData, mmsData)) {
584 LogError("set message body error");
585 ThrowMsg(Commons::PlatformException, "set message body error");
588 msg_mms_destroy_message(mmsData);
589 setAttachmentsValidity(true);
590 setBodyValidity(true);
593 Catch(Commons::PlatformException) {
594 LogError("Platform error");
596 msg_mms_destroy_message(mmsData);
602 void Mms::updateReadStatus()
604 if (isReadStatusValid()) {
608 LogInfo("updating platform read status: " << isRead());
609 if (MSG_SUCCESS != msg_set_read_status(m_messageData, isRead())) {
610 LogError("problem with setting subject");
611 ThrowMsg(Commons::PlatformException, "Problem with setting subject");
614 setReadStatusValidity(true);
617 void Mms::readAllData()
619 readExistingMessage();
622 void Mms::moveToFolder(const FolderType newFolder)
628 MSG_FOLDER_ID_T platfromFolderId = Messaging::convertFolderToPlatform(
631 if (msg_move_msg_to_folder(MsgGetCommonHandle(), convertId(getId()),
632 platfromFolderId) != MSG_SUCCESS) {
633 ThrowMsg(Commons::PlatformException, "Error during movinf message");
637 Catch(Commons::PlatformException) {
638 LogError("remove message error");
643 void Mms::moveToFolder(const string& newFolder)
649 MSG_FOLDER_ID_T platfromFolderId = Messaging::convertFolderToPlatform(
652 if (msg_move_msg_to_folder(MsgGetCommonHandle(), convertId(getId()),
653 platfromFolderId) != MSG_SUCCESS) {
654 LogError("msg_move_msg_to_folder error");
655 ThrowMsg(Commons::PlatformException, "msg_move_msg_to_folder error");
659 Catch(Commons::PlatformException) {
660 LogError("remove message error");
665 void Mms::copyToFolder(const FolderType newFolder)
669 msg_message_t msg = msg_new_message();
673 MSG_SENDINGOPT_S option;
674 memset(&option, 0, sizeof(MSG_SENDINGOPT_S));
675 option.option.smsSendOpt.bReplyPath = true;
677 msg_get_message(MsgGetCommonHandle(), convertId(getIdRef()), msg,
679 const MSG_FOLDER_ID_T platfromFolderId =
680 Messaging::convertFolderToPlatform(newFolder);
681 msg_set_message_id(msg, 0);
682 msg_set_folder_id(msg, platfromFolderId);
684 int error = msg_add_message(MsgGetCommonHandle(), msg, &option);
685 if (error != MSG_SUCCESS) {
686 LogError("msg_add_message failed, error code=" << error);
687 ThrowMsg(Commons::PlatformException, "msg_add_message failed");
691 msg_release_message(&msg);
695 Catch(Commons::PlatformException) {
696 LogError("remove message error");
698 msg_release_message(&msg);
704 void Mms::copyToFolder(const string& newFolder)
708 msg_message_t msg = msg_new_message();
712 MSG_SENDINGOPT_S option;
713 memset(&option, 0, sizeof(MSG_SENDINGOPT_S));
714 option.option.smsSendOpt.bReplyPath = true;
716 msg_get_message(MsgGetCommonHandle(), convertId(getIdRef()), msg,
718 const MSG_FOLDER_ID_T platfromFolderId =
719 Messaging::convertFolderToPlatform(newFolder);
720 msg_set_message_id(msg, 0);
721 msg_set_folder_id(msg, platfromFolderId);
723 int error = msg_add_message(MsgGetCommonHandle(), msg, &option);
724 if (error != MSG_SUCCESS) {
725 LogError("msg_add_message failed, error code=" << error);
726 ThrowMsg(Commons::PlatformException, "msg_add_message failed");
730 msg_release_message(&msg);
734 Catch(Commons::PlatformException) {
735 LogError("remove message error");
737 msg_release_message(&msg);
745 LogDebug("delete m_id=" << getIdRef());
749 if (this->getIdRef().empty()) {
750 LogError("existing msgId is zero, remove msg not done");
751 ThrowMsg(Commons::PlatformException,
752 "existing msgId is zero, remove msg not done");
756 msg_delete_message(MsgGetCommonHandle(),
757 convertId(getIdRef()))) {
758 LogError("Failed to delete Message");
759 ThrowMsg(Commons::PlatformException, "Failed to delete Message");
763 Catch(Commons::PlatformException) {
764 LogError("platform error occurs");
770 LogDebug("sending message, id=" << getIdRef());
773 //prepare for sending sms/mms
776 LogDebug("Start Sending Message...");
777 LogDebug("msgId=" << msg_get_message_id(m_messageData));
778 LogDebug("subject: " << msg_get_subject(m_messageData));
779 LogDebug("recipient count: " << msg_get_address_count(m_messageData));
780 for (int i = 0; i < msg_get_address_count(m_messageData); ++i) {
781 LogDebug("recipient[" << i << "]: " <<
782 msg_get_ith_address(m_messageData, i));
785 LogDebug("trying to send mms");
786 MSG_ERROR_T err = CallbackMgrSingleton::Instance().registerAndSend(
787 msg_mms_send_message,
790 if (err != MSG_SUCCESS) {
791 LogError("Sending Message (submit request) failed!!! err=" << err);
792 setSendingStatusFailed();
796 LogDebug("Sending Message request is submitted!");
798 Catch(Commons::PlatformException) {
799 LogError("message is not send, manually run callback");
800 setSendingStatusFailed();
804 void Mms::sendingCallback(MSG_SENT_STATUS_S *sent_status)
807 "sendingCallback callback received. Req id = " <<
808 sent_status->reqId << " Status = " << (int)sent_status->status);
809 if (MSG_NETWORK_SEND_SUCCESS == sent_status->status) {
810 LogDebug("sending ok");
811 setSendingStatusOk();
813 LogError("sending failed: " <<
814 static_cast<unsigned int>(sent_status->status));
815 setSendingStatusFailed();
819 void Mms::sendCancel()
821 LogDebug("sending message, id=" << getIdRef());
825 void Mms::setSendingStatusOk()
827 ReqReceiverMessage *requestReceiver = getRequestReceiver();
830 LogInfo("calling JS success callback");
831 EventSendMessagePtr event = getSendMessageEvent();
832 event->addRecipientsSendResult(getToRecipientsPtr()->getRecipientsRef(),
834 event->setExceptionCode(Commons::ExceptionCodes::None);
835 requestReceiver->Commons::EventRequestReceiver<EventSendMessage>::
840 void Mms::setSendingStatusFailed()
842 EventOnSendingFailedEmitterPtr emitter = getEmitter();
845 EventOnSendingFailedPtr event(new EventOnSendingFailed);
846 event->setError(EventOnSendingFailed::UNKNOWN); // TODO error codes
847 emitter->emit(event);
851 ReqReceiverMessage *requestReceiver = getRequestReceiver();
854 LogError("calling JS error callback");
855 EventSendMessagePtr event = getSendMessageEvent();
856 event->addRecipientsSendResult(
857 getToRecipientsPtr()->getRecipientsRef(),
859 event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
860 requestReceiver->Commons::EventRequestReceiver<EventSendMessage>
861 ::ManualAnswer(event);
866 Api::FolderType Mms::toFolder(const std::string &folder)
868 if (folder == "INBOX") {
870 } else if (folder == "OUTBOX") {
872 } else if (folder == "SENTBOX") {
874 } else if (folder == "DRAFTBOX") {
877 ThrowMsg(Commons::PlatformException, "Invalid folder");