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.
22 * @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 <MapiStorage.h>
36 #include <MapiMessage.h>
40 using namespace TizenApis::Api::Messaging;
43 const char* EMPTY_ID = "0";
50 Sms::Sms(const string& id) :
55 LogDebug("m_id=" << getIdRef());
56 LogDebug("m_msgType=" << getMessageType());
58 if (getIdRef().empty()) {
61 readExistingMessage();
72 // release platform message structure
73 msg_release_message(&m_messageData);
77 void Sms::update(bool draftsOnly)
79 LogDebug("updating m_id=" << getIdRef());
82 //error if platform message not exists
83 LogError("message can not be updated");
84 Throw(WrtDeviceApis::Commons::PlatformException);
88 if (!draftsOnly || getCurrentFolder() == Api::Messaging::DRAFTBOX) {
92 updateSourceAddress();
97 void Sms::readAllData()
99 readExistingMessage();
102 void Sms::moveToFolder(const FolderType newFolder)
108 const MSG_FOLDER_ID_T platfromFolderId =
109 Messaging::convertFolderToPlatform(newFolder);
111 //call platform api to move message to other folder
112 if (msg_move_msg_to_folder(MsgGetCommonHandle(), convertId(getId()),
113 platfromFolderId) != MSG_SUCCESS) {
114 Throw(WrtDeviceApis::Commons::PlatformException);
118 Catch(WrtDeviceApis::Commons::PlatformException) {
119 LogError("remove message error");
124 void Sms::moveToFolder(const std::string& newFolder)
130 void Sms::copyToFolder(const FolderType newFolder)
134 msg_message_t msg = msg_new_message();
138 MSG_SENDINGOPT_S option = { false, false, false };
139 option.option.smsSendOpt.bReplyPath = true;
140 // trying to get message from platform
142 msg_get_message(MsgGetCommonHandle(), convertId(getIdRef()), msg,
144 const MSG_FOLDER_ID_T platfromFolderId =
145 Messaging::convertFolderToPlatform(newFolder);
146 // new id will me set (initialize to 0)
147 msg_set_message_id(msg, 0);
148 msg_set_folder_id(msg, platfromFolderId);
150 // trying to add message
151 int error = msg_add_message(MsgGetCommonHandle(), msg, &option);
152 if (error != MSG_SUCCESS) {
153 LogError("msg_add_message failed, error code=" << error);
154 Throw(WrtDeviceApis::Commons::PlatformException);
157 //releasing platform message structure
158 msg_release_message(&msg);
162 Catch(WrtDeviceApis::Commons::PlatformException) {
163 LogError("remove message error");
165 //releasing platform message structure
166 msg_release_message(&msg);
172 void Sms::copyToFolder(const std::string& newFolder)
180 LogDebug("sending message, id=" << getIdRef());
182 //prepare for sending sms
186 LogDebug("Start Sending Message...");
187 LogDebug("msgId=" << msg_get_message_id(m_messageData));
188 LogDebug("subject: " << msg_get_subject(m_messageData));
189 LogDebug("recipient count: " << msg_get_address_count(m_messageData));
193 for (int i = 0; i < msg_get_address_count(m_messageData); ++i) {
194 if (MSG_RECIPIENTS_TYPE_TO !=
195 msg_get_ith_recipient_type(m_messageData, i)) {
198 msg_message_t msg = createNewCopyOfPLatformMsg(m_messageData);
200 // remove all addresses except ith
201 msg_reset_address(msg);
202 const char* to = msg_get_ith_address(m_messageData, i);
203 msg_add_address(msg, to, MSG_RECIPIENTS_TYPE_TO);
205 setMessageStatus(MESSAGE_STATUS_SENDING);
207 LogDebug("recipient: " << msg_get_ith_address(msg, 0));
208 LogDebug("body: " << msg_sms_get_message_body(msg));
213 DPL::Mutex::ScopedLock lock(&m_mutex);
214 m_sendRequests.push(req);
219 LogDebug("sending method finished");
221 return 0; //sms handle is -1;
224 void Sms::sendingCallback(MSG_SENT_STATUS_S *sent_status)
227 "sendingCallback callback received. Req id = " <<
228 sent_status->reqId << " Status = " << (int)sent_status->status <<
229 ", Recipient=" << getRecipient());
231 DPL::Mutex::ScopedLock lock(&m_mutex);
233 if (sent_status->status != MSG_NETWORK_SEND_SUCCESS) {
234 m_sendRequests.front().failed = true; // TODO mutex
235 //send callback, error for recipient
236 setSendingStatusFailed(getRecipient());
237 setMessageStatus(MESSAGE_STATUS_FAILED);
239 setSendingStatusOk(getRecipient());
240 setMessageStatus(MESSAGE_STATUS_SENT);
243 msg_release_message(¤tQueue().front());
244 currentQueue().pop();
246 //schedule another sub message send
250 void Sms::OnEventReceived(const int&)
257 Api::Messaging::FolderType Sms::toFolder(const std::string &folder)
259 if (folder == "INBOX") {
261 } else if (folder == "OUTBOX") {
263 } else if (folder == "SENTBOX") {
265 } else if (folder == "DRAFTBOX") {
268 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Invalid folder");
271 void Sms::sendSubMessage()
275 DPL::Mutex::ScopedLock lock(&m_mutex);
277 // if current request queue gets empty, try next one
278 while (!m_sendRequests.empty()) {
279 // send as long as the sending fails until there are no more messages
280 for (MSG_ERROR_T err = MSG_ERR_UNKNOWN;
281 err != MSG_SUCCESS && !currentQueue().empty();
283 err = CallbackMgrSingleton::Instance().registerAndSend(
284 msg_sms_send_message,
285 currentQueue().front(),
287 LogInfo("Sending Message (submit request) result:" << err);
288 if (err != MSG_SUCCESS) {
290 "Sending Message (submit request) failed!!! err=" << err);
291 msg_release_message(¤tQueue().front());
292 currentQueue().pop();
293 m_sendRequests.front().failed = true;
294 //send callback, error for recipient
295 setSendingStatusFailed(getRecipient());
299 // empty queue -> notify about results
300 if (currentQueue().empty()) {
302 if (m_sendRequests.front().failed) {
303 setSendingStatusFailed();
305 setSendingStatusOk();
308 // this request is finished, try next one
309 m_sendRequests.pop();
316 void Sms::setSendingStatusOk(const string &recipient)
318 LogDebug("enter, success number is : " << recipient);
319 //success callback should be executed here
320 ReqReceiverMessage *requestReceiver = getRequestReceiver();
321 if (requestReceiver) {
322 EventSendMessagePtr event = getSendMessageEvent();
323 event->setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::None);
324 event->m_successRecipients.push_back(recipient);
325 //LogDebug("total address size : " << msg_get_address_count(m_messageData) << " Status size : " << event->m_successRecipients.size() + event->m_failRecipients.size());
326 if ( event->m_successRecipients.size() + event->m_failRecipients.size() == msg_get_address_count(m_messageData))
328 requestReceiver->WrtDeviceApis::Commons::EventRequestReceiver< EventSendMessage >::ManualAnswer(event);
333 void Sms::setSendingStatusFailed(const string &recipient)
335 LogDebug("enter, fail number is : " << recipient);
336 //error callback should be executed here
337 EventOnSendingFailedEmitterPtr emitter = getEmitter();
339 EventOnSendingFailedPtr event(new EventOnSendingFailed);
340 event->setError(EventOnSendingFailed::UNKNOWN); // TODO error codes
341 emitter->emit(event);
343 ReqReceiverMessage *requestReceiver = getRequestReceiver();
344 if (requestReceiver) {
345 LogError("calling JS error callback");
346 EventSendMessagePtr event = getSendMessageEvent();
347 event->setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
348 event->m_failRecipients.push_back(recipient);
349 //LogDebug("total address size : " << msg_get_address_count(m_messageData) << " Status size : " << event->m_successRecipients.size() + event->m_failRecipients.size());
350 if ( event->m_successRecipients.size() + event->m_failRecipients.size() == msg_get_address_count(m_messageData))
352 requestReceiver->WrtDeviceApis::Commons::EventRequestReceiver< EventSendMessage >::ManualAnswer(event);
362 // delete message from platform
363 if (msg_delete_message(MsgGetCommonHandle(),
364 convertId(getId())) != MSG_SUCCESS) {
365 LogError("delete message failed");
366 Throw(WrtDeviceApis::Commons::PlatformException);
368 LogDebug("message deleted succesfully");
372 Catch(WrtDeviceApis::Commons::PlatformException) {
373 LogError("remove message error");
378 void Sms::createNewMessage()
381 // release platform message if it was created previously
382 msg_release_message(&m_messageData);
383 m_messageData = NULL;
385 // create new platform message
386 m_messageData = msg_new_message();
389 MSG_SENDINGOPT_S option = { false, false, false };
390 option.option.smsSendOpt.bReplyPath = true;
392 //default message initialization
393 msg_set_message_id(m_messageData, 0); // It should be set 0
394 msg_set_folder_id(m_messageData, MSG_DRAFT_ID);
395 msg_set_message_type(m_messageData, MSG_TYPE_SMS);
396 msg_set_storage_id(m_messageData, MSG_STORAGE_PHONE);
397 msg_set_network_status(m_messageData, MSG_NETWORK_NOT_SEND);
403 setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
405 tm dateT = getDateTime();
406 msg_set_time(m_messageData, mktime(&dateT));
408 setMessageStatus(Api::Messaging::MESSAGE_STATUS_CREATED);
409 LogDebug("Message created successfully, msgId=" << getId());
412 Catch(WrtDeviceApis::Commons::PlatformException) {
413 LogError("Problem with message creation, cleaning");
417 void Sms::readExistingMessage()
419 if (getIdRef().empty() || (EMPTY_ID == getIdRef())) {
420 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Empty id.");
424 MSG_SENDINGOPT_S option = { false, false, false };
425 option.option.smsSendOpt.bReplyPath = true;
428 msg_release_message(&m_messageData);
429 m_messageData = NULL;
430 // create new platform structure
431 m_messageData = msg_new_message();
433 MSG_MESSAGE_ID_T l_id = convertId(getIdRef());
434 LogDebug("reading message id=" << l_id);
435 // trying to get message from platform
437 msg_get_message(MsgGetCommonHandle(), l_id, m_messageData,
439 LogDebug("message found with msgId=" << getIdRef());
441 // read all mms dat to abstraction layer
442 readRecipientList(m_messageData);
443 readBody(m_messageData);
444 readFolder(m_messageData);
445 readDateTime(m_messageData);
446 readReadStatus(m_messageData);
447 readSize(m_messageData);
449 LogError("message not found with msgId=" << getIdRef());
453 Catch(WrtDeviceApis::Commons::PlatformException) {
458 void Sms::updateBody()
460 // check if abstraction body value has been changed
464 LogInfo("updating platfoprm body");
466 // change body value in platform structure
467 msg_sms_set_message_body(m_messageData, getBodyRef().c_str(),
468 getBodyRef().length());
470 // set flag as true - platform synchronized with abstraction
471 setBodyValidity(true);
476 // check if abstraction recipient (to) value has been changed
477 if (getToRecipients().isValid()) {
480 LogInfo("updating platform to");
482 // change recipient value in platform structure
483 msg_reset_address(m_messageData);
484 vector<string> to = getToRecipients().getRecipients();
485 LogInfo("updating to");
486 for (size_t i = 0; i < to.size(); i++) {
487 if (i >= MAX_TO_ADDRESS_CNT) {
488 LogError("max number of recipient exceeded");
491 LogDebug("adding to[" << i << "]=" << to[i]);
492 string tmpAddr = to[i];
493 // function for validating phone number
494 if (validatePhoneNumber(tmpAddr)) {
495 // add phone number to platform message struncture
496 if (msg_add_address(m_messageData, tmpAddr.c_str(),
497 MSG_RECIPIENTS_TYPE_TO) != MSG_SUCCESS) {
498 LogError("problem witgh add address");
499 Throw(WrtDeviceApis::Commons::PlatformException);
502 //nothing to do if wrong format
503 LogError("wrong phone number format");
508 // set flag as true - platform synchronized with abstraction
512 void Sms::updateFrom()
514 // check if abstraction from field value has been changed
515 if (getFromValidity()) {
516 // do not update if not changed
519 LogInfo("updating platform from");
523 // set flag as true - platform synchronized with abstraction
524 setFromValidity(true);
527 void Sms::updateSourceAddress()
529 // check if abstraction source address value has been changed
530 if (getSourceAddressValidity()) {
531 // do not update if not changed
534 LogInfo("updating platform source address");
538 // set flag as true - platform synchronized with abstraction
539 setSourceAddressValidity(true);
542 void Sms::updateReadStatus()
544 LogInfo("updating platform read status: " << isRead());
545 if (isReadStatusValid()) {
546 // do not update if not changed
550 if (MSG_SUCCESS != msg_set_read_status(m_messageData, isRead())) {
551 LogError("problem with setting subject");
552 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Problem with setting subject");
554 setReadStatusValidity(true);
557 void Sms::updateIsRead()
559 LogDebug("updating m_id=" << getIdRef());
561 if (!m_messageData) {
562 //error if platform message not exists
563 LogError("message can not be updated");
564 Throw(WrtDeviceApis::Commons::PlatformException);
567 // check if abstraction from m_isReadChange value has been changed
568 if (isReadChangeStatusValid()) {
569 // do not update if not changed
575 if (this->getIdRef().empty()) {
576 LogError("existing msgId is zero, remove msg not done");
577 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
578 "existing msgId is zero, remove msg not done");
582 msg_update_read_status(MsgGetCommonHandle(), convertId(getIdRef()), isReadChangeStatus()))
584 LogError("Failed to update isRead");
585 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to update isRead");
588 Catch(WrtDeviceApis::Commons::PlatformException) {
589 LogError("platform error occurs");
591 setisReadChangeStatusValidity(true);
596 void Sms::addMessageToDraft()
598 LogDebug("convert m_id= " << convertId(getIdRef()));
600 //prepare for add sms to draft folder
601 if (!m_messageData) {
602 //error if platform message not exists
603 LogError("message can not be updated");
604 Throw(WrtDeviceApis::Commons::PlatformException);
607 //update all sms data
608 if (getCurrentFolder() == Api::Messaging::DRAFTBOX) {
612 updateSourceAddress();
617 MSG_SENDINGOPT_S option = { false, false, false };
618 option.option.smsSendOpt.bReplyPath = true;
619 // trying to get message from platform
621 const MSG_FOLDER_ID_T platfromFolderId =
622 Messaging::convertFolderToPlatform(DRAFTBOX);
624 msg_set_message_id(m_messageData, 0);
625 msg_set_folder_id(m_messageData, platfromFolderId);
626 msg_set_network_status(m_messageData, MSG_NETWORK_NOT_SEND);
628 // trying to add message
629 int ret = msg_add_message(MsgGetCommonHandle(), m_messageData, &option);
630 if (ret < MSG_SUCCESS) {
631 LogError("msg_add_message failed, error code=" << ret);
632 Throw(WrtDeviceApis::Commons::PlatformException);
635 //releasing platform message structure
636 //msg_release_message(&m_messageData);
638 setFolderType(Api::Messaging::DRAFTBOX);
639 setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
641 Catch(WrtDeviceApis::Commons::PlatformException) {
642 LogError("remove message error");
644 //releasing platform message structure
645 msg_release_message(&m_messageData);
653 void Sms::readRecipientList(msg_message_t& messageData)
655 LogDebug("Adding recipients to message, count=" <<
656 msg_get_address_count(messageData));
657 // iterate for all address and store in abstraction
658 for (int i = 0; i < msg_get_address_count(messageData); i++) {
659 string tmp = msg_get_ith_address(messageData, i);
660 int type = msg_get_direction_info(messageData);
662 if (MSG_DIRECTION_TYPE_MT == type) {
663 if (validatePhoneNumber(tmp)) {
664 setSourceAddress(tmp);
667 } else if (MSG_DIRECTION_TYPE_MO == type) {
668 appendToRecipients(tmp);
670 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Wrong type of recipient.");
675 void Sms::readBody(msg_message_t& messageData)
677 //set abstraction body value
678 setBody(msg_sms_get_message_body(messageData));
681 void Sms::readFolder(msg_message_t& messageData)
683 switch (msg_get_folder_id(messageData)) {
685 setFolderType(Api::Messaging::INBOX);
688 setFolderType(Api::Messaging::OUTBOX);
691 setFolderType(Api::Messaging::SENTBOX);
694 setFolderType(Api::Messaging::DRAFTBOX);
697 setFolderType(Api::Messaging::SPAMBOX);
700 LogError("Wrong folder id");
701 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Unsupported folder id.");
705 void Sms::readDateTime(msg_message_t& messageData)
707 tm* time = localtime(msg_get_time(messageData));
709 LogError("localtime failed");
710 Throw(WrtDeviceApis::Commons::PlatformException);
715 void Sms::readReadStatus(msg_message_t& messageData)
718 setReadStatus(msg_is_read(messageData));
721 void Sms::readSize(msg_message_t& messageData)
723 setSize(msg_get_message_body_size(messageData));
726 msg_message_t Sms::createNewCopyOfPLatformMsg(const msg_message_t src) const
728 msg_message_t msg = msg_new_message();
730 msg_set_message_id(msg, 0);
731 msg_set_storage_id(msg, msg_get_storage_id(src));
732 msg_set_message_type(msg, msg_get_message_type(src));
733 msg_set_folder_id(msg, msg_get_folder_id(src));
734 for (int i = 0; i < msg_get_address_count(src); i++) {
735 msg_add_address(msg, msg_get_ith_address(src,
737 msg_get_ith_recipient_type(src, i));
739 msg_sms_set_message_body(msg, msg_sms_get_message_body(
740 src), msg_get_message_body_size(src));
741 msg_set_subject(msg, msg_get_subject(src));
742 msg_set_time(msg, *msg_get_time(src));
743 msg_set_network_status(msg, msg_get_network_status(src));
744 msg_set_encode_type(msg, msg_get_encode_type(src));
745 msg_set_read_status(msg, msg_is_read(src));
746 msg_set_protect_status(msg, msg_is_protected(src));
747 msg_set_priority_info(msg, msg_get_priority_info(src));
748 msg_set_direction_info(msg, msg_get_direction_info(src));
749 msg_set_port(msg, msg_get_dest_port(src), msg_get_src_port(src));
750 msg_set_scheduled_time(msg, *msg_get_scheduled_time(src));