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 LogDebug("Message created successfully, msgId=" << getId());
411 Catch(WrtDeviceApis::Commons::PlatformException) {
412 LogError("Problem with message creation, cleaning");
416 void Sms::readExistingMessage()
418 if (getIdRef().empty() || (EMPTY_ID == getIdRef())) {
419 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Empty id.");
423 MSG_SENDINGOPT_S option = { false, false, false };
424 option.option.smsSendOpt.bReplyPath = true;
427 msg_release_message(&m_messageData);
428 m_messageData = NULL;
429 // create new platform structure
430 m_messageData = msg_new_message();
432 MSG_MESSAGE_ID_T l_id = convertId(getIdRef());
433 LogDebug("reading message id=" << l_id);
434 // trying to get message from platform
436 msg_get_message(MsgGetCommonHandle(), l_id, m_messageData,
438 LogDebug("message found with msgId=" << getIdRef());
440 // read all mms dat to abstraction layer
441 readRecipientList(m_messageData);
442 readBody(m_messageData);
443 readFolder(m_messageData);
444 readDateTime(m_messageData);
445 readReadStatus(m_messageData);
446 readSize(m_messageData);
448 LogError("message not found with msgId=" << getIdRef());
452 Catch(WrtDeviceApis::Commons::PlatformException) {
457 void Sms::updateBody()
459 // check if abstraction body value has been changed
463 LogInfo("updating platfoprm body");
465 // change body value in platform structure
466 msg_sms_set_message_body(m_messageData, getBodyRef().c_str(),
467 getBodyRef().length());
469 // set flag as true - platform synchronized with abstraction
470 setBodyValidity(true);
475 // check if abstraction recipient (to) value has been changed
476 if (getToRecipients().isValid()) {
479 LogInfo("updating platform to");
481 // change recipient value in platform structure
482 msg_reset_address(m_messageData);
483 vector<string> to = getToRecipients().getRecipients();
484 LogInfo("updating to");
485 for (size_t i = 0; i < to.size(); i++) {
486 if (i >= MAX_TO_ADDRESS_CNT) {
487 LogError("max number of recipient exceeded");
490 LogDebug("adding to[" << i << "]=" << to[i]);
491 string tmpAddr = to[i];
492 // function for validating phone number
493 if (validatePhoneNumber(tmpAddr)) {
494 // add phone number to platform message struncture
495 if (msg_add_address(m_messageData, tmpAddr.c_str(),
496 MSG_RECIPIENTS_TYPE_TO) != MSG_SUCCESS) {
497 LogError("problem witgh add address");
498 Throw(WrtDeviceApis::Commons::PlatformException);
501 //nothing to do if wrong format
502 LogError("wrong phone number format");
507 // set flag as true - platform synchronized with abstraction
511 void Sms::updateFrom()
513 // check if abstraction from field value has been changed
514 if (getFromValidity()) {
515 // do not update if not changed
518 LogInfo("updating platform from");
522 // set flag as true - platform synchronized with abstraction
523 setFromValidity(true);
526 void Sms::updateSourceAddress()
528 // check if abstraction source address value has been changed
529 if (getSourceAddressValidity()) {
530 // do not update if not changed
533 LogInfo("updating platform source address");
537 // set flag as true - platform synchronized with abstraction
538 setSourceAddressValidity(true);
541 void Sms::updateReadStatus()
543 LogInfo("updating platform read status: " << isRead());
544 if (isReadStatusValid()) {
545 // do not update if not changed
549 if (MSG_SUCCESS != msg_set_read_status(m_messageData, isRead())) {
550 LogError("problem with setting subject");
551 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Problem with setting subject");
553 setReadStatusValidity(true);
556 void Sms::updateIsRead()
558 LogDebug("updating m_id=" << getIdRef());
560 if (!m_messageData) {
561 //error if platform message not exists
562 LogError("message can not be updated");
563 Throw(WrtDeviceApis::Commons::PlatformException);
566 // check if abstraction from m_isReadChange value has been changed
567 if (isReadChangeStatusValid()) {
568 // do not update if not changed
574 if (this->getIdRef().empty()) {
575 LogError("existing msgId is zero, remove msg not done");
576 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
577 "existing msgId is zero, remove msg not done");
581 msg_update_read_status(MsgGetCommonHandle(), convertId(getIdRef()), isReadChangeStatus()))
583 LogError("Failed to update isRead");
584 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to update isRead");
587 Catch(WrtDeviceApis::Commons::PlatformException) {
588 LogError("platform error occurs");
590 setisReadChangeStatusValidity(true);
595 void Sms::addMessageToDraft()
597 LogDebug("convert m_id= " << convertId(getIdRef()));
599 //prepare for add sms to draft folder
600 if (!m_messageData) {
601 //error if platform message not exists
602 LogError("message can not be updated");
603 Throw(WrtDeviceApis::Commons::PlatformException);
606 //update all sms data
607 if (getCurrentFolder() == Api::Messaging::DRAFTBOX) {
611 updateSourceAddress();
616 MSG_SENDINGOPT_S option = { false, false, false };
617 option.option.smsSendOpt.bReplyPath = true;
618 // trying to get message from platform
620 const MSG_FOLDER_ID_T platfromFolderId =
621 Messaging::convertFolderToPlatform(DRAFTBOX);
623 msg_set_message_id(m_messageData, 0);
624 msg_set_folder_id(m_messageData, platfromFolderId);
625 msg_set_network_status(m_messageData, MSG_NETWORK_NOT_SEND);
627 // trying to add message
628 int ret = msg_add_message(MsgGetCommonHandle(), m_messageData, &option);
629 if (ret < MSG_SUCCESS) {
630 LogError("msg_add_message failed, error code=" << ret);
631 Throw(WrtDeviceApis::Commons::PlatformException);
634 //releasing platform message structure
635 msg_release_message(&m_messageData);
637 Catch(WrtDeviceApis::Commons::PlatformException) {
638 LogError("remove message error");
640 //releasing platform message structure
641 msg_release_message(&m_messageData);
649 void Sms::readRecipientList(msg_message_t& messageData)
651 LogDebug("Adding recipients to message, count=" <<
652 msg_get_address_count(messageData));
653 // iterate for all address and store in abstraction
654 for (int i = 0; i < msg_get_address_count(messageData); i++) {
655 string tmp = msg_get_ith_address(messageData, i);
656 int type = msg_get_direction_info(messageData);
658 if (MSG_DIRECTION_TYPE_MT == type) {
659 if (validatePhoneNumber(tmp)) {
660 setSourceAddress(tmp);
663 } else if (MSG_DIRECTION_TYPE_MO == type) {
664 appendToRecipients(tmp);
666 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Wrong type of recipient.");
671 void Sms::readBody(msg_message_t& messageData)
673 //set abstraction body value
674 setBody(msg_sms_get_message_body(messageData));
677 void Sms::readFolder(msg_message_t& messageData)
679 switch (msg_get_folder_id(messageData)) {
681 setFolderType(Api::Messaging::INBOX);
684 setFolderType(Api::Messaging::OUTBOX);
687 setFolderType(Api::Messaging::SENTBOX);
690 setFolderType(Api::Messaging::DRAFTBOX);
693 setFolderType(Api::Messaging::SPAMBOX);
696 LogError("Wrong folder id");
697 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Unsupported folder id.");
701 void Sms::readDateTime(msg_message_t& messageData)
703 tm* time = localtime(msg_get_time(messageData));
705 LogError("localtime failed");
706 Throw(WrtDeviceApis::Commons::PlatformException);
711 void Sms::readReadStatus(msg_message_t& messageData)
714 setReadStatus(msg_is_read(messageData));
717 void Sms::readSize(msg_message_t& messageData)
719 setSize(msg_get_message_body_size(messageData));
722 msg_message_t Sms::createNewCopyOfPLatformMsg(const msg_message_t src) const
724 msg_message_t msg = msg_new_message();
726 msg_set_message_id(msg, 0);
727 msg_set_storage_id(msg, msg_get_storage_id(src));
728 msg_set_message_type(msg, msg_get_message_type(src));
729 msg_set_folder_id(msg, msg_get_folder_id(src));
730 for (int i = 0; i < msg_get_address_count(src); i++) {
731 msg_add_address(msg, msg_get_ith_address(src,
733 msg_get_ith_recipient_type(src, i));
735 msg_sms_set_message_body(msg, msg_sms_get_message_body(
736 src), msg_get_message_body_size(src));
737 msg_set_subject(msg, msg_get_subject(src));
738 msg_set_time(msg, *msg_get_time(src));
739 msg_set_network_status(msg, msg_get_network_status(src));
740 msg_set_encode_type(msg, msg_get_encode_type(src));
741 msg_set_read_status(msg, msg_is_read(src));
742 msg_set_protect_status(msg, msg_is_protected(src));
743 msg_set_priority_info(msg, msg_get_priority_info(src));
744 msg_set_direction_info(msg, msg_get_direction_info(src));
745 msg_set_port(msg, msg_get_dest_port(src), msg_get_src_port(src));
746 msg_set_scheduled_time(msg, *msg_get_scheduled_time(src));