cf6b0181ced4fb0418baf435afa74b6eef799473
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / Messaging / Sms.cpp
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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. 
15 */
16
17
18 /**
19  *
20  *
21  * @file       Sms.cpp
22  * @author     Pawel Misiak (p.misiak@samsung.com)
23  * @version    0.1
24  * @brief
25  */
26 #include "Sms.h"
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"
33
34 extern "C" {
35 #include <MapiStorage.h>
36 #include <MapiMessage.h>
37 }
38
39 using namespace std;
40 using namespace TizenApis::Api::Messaging;
41
42 namespace {
43 const char* EMPTY_ID = "0";
44 }
45
46 namespace TizenApis {
47 namespace Platform {
48 namespace Messaging {
49
50 Sms::Sms(const string& id) :
51     IMessage(SMS, id),
52     m_messageData(NULL)
53 {
54     LogDebug("enter");
55     LogDebug("m_id=" << getIdRef());
56     LogDebug("m_msgType=" << getMessageType());
57
58     if (getIdRef().empty()) {
59         createNewMessage();
60     } else {
61         readExistingMessage();
62     }
63
64     Touch();
65 }
66
67 Sms::~Sms()
68 {
69     LogDebug("enter");
70
71     if (m_messageData) {
72         // release platform message structure
73         msg_release_message(&m_messageData);
74     }
75 }
76
77 void Sms::update(bool draftsOnly)
78 {
79     LogDebug("updating m_id=" << getIdRef());
80
81     if (!m_messageData) {
82         //error if platform message not exists
83         LogError("message can not be updated");
84         Throw(WrtDeviceApis::Commons::PlatformException);
85     }
86
87     //update all sms data
88     if (!draftsOnly || getCurrentFolder() == Api::Messaging::DRAFTBOX) {
89         updateBody();
90         updateFrom();
91         updateTo();
92         updateSourceAddress();
93     }
94     updateReadStatus();
95 }
96
97 void Sms::readAllData()
98 {
99     readExistingMessage();
100 }
101
102 void Sms::moveToFolder(const FolderType newFolder)
103 {
104     update();
105
106     Try
107     {
108         const MSG_FOLDER_ID_T platfromFolderId =
109             Messaging::convertFolderToPlatform(newFolder);
110
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);
115         }
116     }
117
118     Catch(WrtDeviceApis::Commons::PlatformException) {
119         LogError("remove message error");
120         throw;
121     }
122 }
123
124 void Sms::moveToFolder(const std::string& newFolder)
125 {
126     update();
127     //TODO
128 }
129
130 void Sms::copyToFolder(const FolderType newFolder)
131 {
132     update();
133
134     msg_message_t msg = msg_new_message();
135
136     Try
137     {
138         MSG_SENDINGOPT_S option = { false, false, false };
139         option.option.smsSendOpt.bReplyPath = true;
140         // trying to get message from platform
141         if (MSG_SUCCESS ==
142             msg_get_message(MsgGetCommonHandle(), convertId(getIdRef()), msg,
143                             &option)) {
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);
149
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);
155             }
156
157             //releasing platform message structure
158             msg_release_message(&msg);
159         }
160     }
161
162     Catch(WrtDeviceApis::Commons::PlatformException) {
163         LogError("remove message error");
164         if (msg) {
165             //releasing platform message structure
166             msg_release_message(&msg);
167         }
168         throw;
169     }
170 }
171
172 void Sms::copyToFolder(const std::string& newFolder)
173 {
174     update();
175     //TODO
176 }
177
178 int Sms::send()
179 {
180     LogDebug("sending message, id=" << getIdRef());
181
182     //prepare for sending sms
183     update();
184
185     // split the message
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));
190
191     SendRequest req;
192
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)) {
196             continue;
197         }
198         msg_message_t msg = createNewCopyOfPLatformMsg(m_messageData);
199
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);
204
205         setMessageStatus(MESSAGE_STATUS_SENDING);
206
207         LogDebug("recipient: " << msg_get_ith_address(msg, 0));
208         LogDebug("body: " << msg_sms_get_message_body(msg));
209
210         req.queue.push(msg);
211     }
212
213     DPL::Mutex::ScopedLock lock(&m_mutex);
214     m_sendRequests.push(req);
215
216     // schedule sending
217     PostEvent(0);
218
219     LogDebug("sending method finished");
220
221     return 0;           //sms handle is -1;
222 }
223
224 void Sms::sendingCallback(MSG_SENT_STATUS_S *sent_status)
225 {
226     LogInfo(
227         "sendingCallback callback received. Req id = " <<
228         sent_status->reqId << " Status = " << (int)sent_status->status <<
229         ", Recipient=" << getRecipient());
230
231     DPL::Mutex::ScopedLock lock(&m_mutex);
232
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);
238     } else {
239         setSendingStatusOk(getRecipient());
240         setMessageStatus(MESSAGE_STATUS_SENT);
241     }
242         
243     msg_release_message(&currentQueue().front());
244     currentQueue().pop();
245
246     //schedule another sub message send
247     PostEvent(0);
248 }
249
250 void Sms::OnEventReceived(const int&)
251 {
252     LogDebug("enter");
253     // send another one
254     sendSubMessage();
255 }
256
257 Api::Messaging::FolderType Sms::toFolder(const std::string &folder)
258 {
259     if (folder == "INBOX") {
260         return INBOX;
261     } else if (folder == "OUTBOX") {
262         return OUTBOX;
263     } else if (folder == "SENTBOX") {
264         return SENTBOX;
265     } else if (folder == "DRAFTBOX") {
266         return DRAFTBOX;
267     }
268     ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Invalid folder");
269 }
270
271 void Sms::sendSubMessage()
272 {
273     LogDebug("enter");
274
275     DPL::Mutex::ScopedLock lock(&m_mutex);
276
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();
282              ) {
283             err = CallbackMgrSingleton::Instance().registerAndSend(
284                     msg_sms_send_message,
285                     currentQueue().front(),
286                     this);
287             LogInfo("Sending Message (submit request) result:" << err);
288             if (err != MSG_SUCCESS) {
289                 LogError(
290                     "Sending Message (submit request) failed!!! err=" << err);
291                 msg_release_message(&currentQueue().front());
292                 currentQueue().pop();
293                 m_sendRequests.front().failed = true;
294                 //send callback, error for recipient
295                 setSendingStatusFailed(getRecipient());
296             }
297         }
298
299         // empty queue -> notify about results
300         if (currentQueue().empty()) {
301                 /*
302             if (m_sendRequests.front().failed) {
303                 setSendingStatusFailed();
304             } else {
305                 setSendingStatusOk();
306             }
307             */
308             // this request is finished, try next one
309             m_sendRequests.pop();
310             continue;
311         }
312         break;
313     }
314 }
315
316 void Sms::setSendingStatusOk(const string &recipient)
317 {
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))
327         {
328                 requestReceiver->WrtDeviceApis::Commons::EventRequestReceiver< EventSendMessage >::ManualAnswer(event);
329         }
330     }
331 }
332
333 void Sms::setSendingStatusFailed(const string &recipient)
334 {
335     LogDebug("enter, fail number is : " << recipient);
336     //error callback should be executed here
337     EventOnSendingFailedEmitterPtr emitter = getEmitter();
338     if (emitter) {
339         EventOnSendingFailedPtr event(new EventOnSendingFailed);
340         event->setError(EventOnSendingFailed::UNKNOWN); // TODO error codes
341         emitter->emit(event);
342     } else {
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))
351                  {
352                         requestReceiver->WrtDeviceApis::Commons::EventRequestReceiver< EventSendMessage >::ManualAnswer(event);
353                  }
354         }
355     }
356 }
357
358 void Sms::remove()
359 {
360     Try
361     {
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);
367         } else {
368             LogDebug("message deleted succesfully");
369         }
370     }
371
372     Catch(WrtDeviceApis::Commons::PlatformException) {
373         LogError("remove message error");
374         throw;
375     }
376 }
377
378 void Sms::createNewMessage()
379 {
380     if (m_messageData) {
381         // release platform message if it was created previously
382         msg_release_message(&m_messageData);
383         m_messageData = NULL;
384     }
385     // create new platform message
386     m_messageData = msg_new_message();
387     Try
388     {
389         MSG_SENDINGOPT_S option = { false, false, false };
390         option.option.smsSendOpt.bReplyPath = true;
391
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);
398
399         // update sms data
400         updateBody();
401         updateTo();
402
403         setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
404
405         tm dateT = getDateTime();
406         msg_set_time(m_messageData, mktime(&dateT));
407
408         LogDebug("Message created successfully, msgId=" << getId());
409     }
410
411     Catch(WrtDeviceApis::Commons::PlatformException) {
412         LogError("Problem with message creation, cleaning");
413     }
414 }
415
416 void Sms::readExistingMessage()
417 {
418     if (getIdRef().empty() || (EMPTY_ID == getIdRef())) {
419         ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Empty id.");
420     }
421
422     Try {
423         MSG_SENDINGOPT_S option = { false, false, false };
424         option.option.smsSendOpt.bReplyPath = true;
425
426         // release old data
427         msg_release_message(&m_messageData);
428         m_messageData = NULL;
429         // create new platform structure
430         m_messageData = msg_new_message();
431
432         MSG_MESSAGE_ID_T l_id = convertId(getIdRef());
433         LogDebug("reading message id=" << l_id);
434         // trying to get message from platform
435         if (MSG_SUCCESS ==
436             msg_get_message(MsgGetCommonHandle(), l_id, m_messageData,
437                             &option)) {
438             LogDebug("message found with msgId=" << getIdRef());
439
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);
447         } else {
448             LogError("message not found with msgId=" << getIdRef());
449             setId("");
450         }
451     }
452     Catch(WrtDeviceApis::Commons::PlatformException) {
453         // nothing to do
454     }
455 }
456
457 void Sms::updateBody()
458 {
459     // check if abstraction body value has been changed
460     if (isBodyValid()) {
461         return;
462     }
463     LogInfo("updating platfoprm body");
464
465     // change body value in platform structure
466     msg_sms_set_message_body(m_messageData, getBodyRef().c_str(),
467                              getBodyRef().length());
468
469     // set flag as true - platform synchronized with abstraction
470     setBodyValidity(true);
471 }
472
473 void Sms::updateTo()
474 {
475     // check if abstraction recipient (to) value has been changed
476     if (getToRecipients().isValid()) {
477         return;
478     }
479     LogInfo("updating platform to");
480
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");
488             break;
489         }
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);
499             }
500         } else {
501             //nothing to do if wrong format
502             LogError("wrong phone number format");
503                  
504         }
505     }
506
507     // set flag as true - platform synchronized with abstraction
508     setToValidity(true);
509 }
510
511 void Sms::updateFrom()
512 {
513     // check if abstraction from field value has been changed
514     if (getFromValidity()) {
515         // do not update if not changed
516         return;
517     }
518     LogInfo("updating platform from");
519
520     //TODO
521
522     // set flag as true - platform synchronized with abstraction
523     setFromValidity(true);
524 }
525
526 void Sms::updateSourceAddress()
527 {
528     // check if abstraction source address value has been changed
529     if (getSourceAddressValidity()) {
530         // do not update if not changed
531         return;
532     }
533     LogInfo("updating platform source address");
534
535     //TODO
536
537     // set flag as true - platform synchronized with abstraction
538     setSourceAddressValidity(true);
539 }
540
541 void Sms::updateReadStatus()
542 {
543     LogInfo("updating platform read status: " << isRead());
544     if (isReadStatusValid()) {
545         // do not update if not changed
546         return;
547     }
548
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");
552     }
553     setReadStatusValidity(true);
554 }
555
556 void Sms::updateIsRead()
557 {
558     LogDebug("updating m_id=" << getIdRef());
559
560     if (!m_messageData) {
561         //error if platform message not exists
562         LogError("message can not be updated");
563         Throw(WrtDeviceApis::Commons::PlatformException);
564     }
565         
566     // check if abstraction from m_isReadChange value has been changed
567     if (isReadChangeStatusValid()) {
568         // do not update if not changed
569         return;
570     }
571         
572     Try
573     {
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");
578         }
579
580         if (MSG_SUCCESS !=
581             msg_update_read_status(MsgGetCommonHandle(), convertId(getIdRef()), isReadChangeStatus()))
582         {
583             LogError("Failed to update isRead");
584             ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to update isRead");
585         }
586     }
587     Catch(WrtDeviceApis::Commons::PlatformException) {
588         LogError("platform error occurs");
589     }
590     setisReadChangeStatusValidity(true);
591         
592 }
593
594
595 void Sms::addMessageToDraft()
596 {
597     LogDebug("convert m_id= " << convertId(getIdRef()));        
598
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);
604     }
605
606     //update all sms data
607     if (getCurrentFolder() == Api::Messaging::DRAFTBOX) {
608         updateBody();
609         updateFrom();
610         updateTo();
611         updateSourceAddress();
612     }
613
614     Try
615     {
616         MSG_SENDINGOPT_S option = { false, false, false };
617         option.option.smsSendOpt.bReplyPath = true;
618         // trying to get message from platform
619
620         const MSG_FOLDER_ID_T platfromFolderId =
621         Messaging::convertFolderToPlatform(DRAFTBOX);
622
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);
626
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);
632         }
633
634         //releasing platform message structure
635         msg_release_message(&m_messageData);
636     }
637     Catch(WrtDeviceApis::Commons::PlatformException) {
638         LogError("remove message error");
639         if (m_messageData) {
640             //releasing platform message structure
641             msg_release_message(&m_messageData);
642         }
643         throw;
644     }
645
646 }
647
648
649 void Sms::readRecipientList(msg_message_t& messageData)
650 {
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);
657
658         if (MSG_DIRECTION_TYPE_MT == type) {
659             if (validatePhoneNumber(tmp)) {
660                 setSourceAddress(tmp);
661                 setFrom(tmp);
662             }
663         } else if (MSG_DIRECTION_TYPE_MO == type) {
664             appendToRecipients(tmp);
665         } else {
666             ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Wrong type of recipient.");
667         }
668     }
669 }
670
671 void Sms::readBody(msg_message_t& messageData)
672 {
673     //set abstraction body value
674     setBody(msg_sms_get_message_body(messageData));
675 }
676
677 void Sms::readFolder(msg_message_t& messageData)
678 {
679     switch (msg_get_folder_id(messageData)) {
680     case MSG_INBOX_ID:
681         setFolderType(Api::Messaging::INBOX);
682         break;
683     case MSG_OUTBOX_ID:
684         setFolderType(Api::Messaging::OUTBOX);
685         break;
686     case MSG_SENTBOX_ID:
687         setFolderType(Api::Messaging::SENTBOX);
688         break;
689     case MSG_DRAFT_ID:
690         setFolderType(Api::Messaging::DRAFTBOX);
691         break;
692     case MSG_SPAMBOX_ID:
693         setFolderType(Api::Messaging::SPAMBOX);
694         break;
695     default:
696         LogError("Wrong folder id");
697         ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Unsupported folder id.");
698     }
699 }
700
701 void Sms::readDateTime(msg_message_t& messageData)
702 {
703     tm* time = localtime(msg_get_time(messageData));
704     if (!time) {
705         LogError("localtime failed");
706         Throw(WrtDeviceApis::Commons::PlatformException);
707     }
708     setDateTime(*time);
709 }
710
711 void Sms::readReadStatus(msg_message_t& messageData)
712 {
713     // get read status
714     setReadStatus(msg_is_read(messageData));
715 }
716
717 void Sms::readSize(msg_message_t& messageData)
718 {
719     setSize(msg_get_message_body_size(messageData));
720 }
721
722 msg_message_t Sms::createNewCopyOfPLatformMsg(const msg_message_t src) const
723 {
724     msg_message_t msg = msg_new_message();
725
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,
732                                                  i),
733                         msg_get_ith_recipient_type(src, i));
734     }
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));
747
748     return msg;
749 }
750 }
751 }
752 }