ut_sms_epoc.cpp

Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2009-2009 HIIT and Tero Hasu
00003 // Copyright (c) 2007-2009 Google Inc.
00004 // Copyright (c) 2006-2007 Jaiku Ltd.
00005 // Copyright (c) 2002-2006 Mika Raento and Renaud Petit
00006 //
00007 // This software is licensed at your choice under either 1 or 2 below.
00008 //
00009 // 1. MIT License
00010 //
00011 // Permission is hereby granted, free of charge, to any person obtaining a copy
00012 // of this software and associated documentation files (the "Software"), to deal
00013 // in the Software without restriction, including without limitation the rights
00014 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00015 // copies of the Software, and to permit persons to whom the Software is
00016 // furnished to do so, subject to the following conditions:
00017 //
00018 // The above copyright notice and this permission notice shall be included in
00019 // all copies or substantial portions of the Software.
00020 //
00021 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00022 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00024 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00027 // THE SOFTWARE.
00028 //
00029 // 2. Gnu General Public license 2.0
00030 //
00031 // This program is free software; you can redistribute it and/or
00032 // modify it under the terms of the GNU General Public License
00033 // as published by the Free Software Foundation; either version 2
00034 // of the License, or (at your option) any later version.
00035 //
00036 // This program is distributed in the hope that it will be useful,
00037 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00038 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00039 // GNU General Public License for more details.
00040 //
00041 // You should have received a copy of the GNU General Public License
00042 // along with this program; if not, write to the Free Software
00043 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00044 //
00045 
00046 /*
00047  !concept {:name => "Observing SMS events",
00048    :desc => "Detecting and getting information about incoming and outgoing SMS messages."}
00049 */
00050 
00051 #include "ut_sms_epoc.hpp"
00052 
00053 #include "er_errors.h"
00054 #include "jaiku_compat.hpp"
00055 #include "symbian_auto_ptr.hpp"
00056 #include "utils_cl2.h"
00057 
00058 #include <mtclreg.h>                        // for CClientMtmRegistry 
00059 #include <msvids.h>                         // for Message type IDs
00060 #include <smscmds.h>
00061 #include <smuthdr.h>
00062 #include <smutset.h>
00063 #include <msvuids.h>
00064 #include <txtrich.h>
00065 #include <smsclnt.h>
00066 #include <mtmdef.h>
00067 #include <gsmupdu.h>
00068 #include <mmsconst.h>
00069 #include <mmsclient.h>
00070 
00071 #include <rsendas.h>
00072 #include <rsendasmessage.h>
00073 
00074 // --------------------------------------------------
00075 // 
00076 // --------------------------------------------------
00077 
00078 void i_handle_received_sms::handle_reception(const TMsvId& entry_id, 
00079                const TMsvId& folder_id, 
00080                TUid aMtmUid, 
00081                CBaseMtm* aMtm)
00082 {
00083   if (aMtmUid == KUidMsgTypeSMS) {
00084     CSmsClientMtm* smsMtm = STATIC_CAST(CSmsClientMtm*, aMtm);
00085     handle_reception(entry_id, folder_id, 
00086          smsMtm->SmsHeader().FromAddress(), 
00087          // Body returns a value of type CRichText&. The
00088          // value is empty for non-message contexts. The 0
00089          // argument to Read is the starting position, and
00090          // this only returns the first message fragment.
00091          smsMtm->Body());
00092   }
00093 }
00094 
00095 void i_handle_received_sms::handle_sending(const TMsvId& entry_id, 
00096              TUid aMtmUid, CBaseMtm* aMtm)
00097 {
00098   if (aMtmUid == KUidMsgTypeSMS) {
00099     CSmsClientMtm* smsMtm = STATIC_CAST(CSmsClientMtm*, aMtm);
00100     handle_sending(entry_id,
00101        smsMtm->SmsHeader().FromAddress(), 
00102        smsMtm->Body());
00103   }
00104 }
00105 
00106 // --------------------------------------------------
00107 // 
00108 // --------------------------------------------------
00109 
00110 // xxx The callback implementation needs fixing so that things will work if the callee does a "delete" on us. So there must be only one callback, and it must be the last thing that affects internal state in the handler.
00111 
00112 CSmsEventNotifier* CSmsEventNotifier::NewL()
00113 {
00114   CSmsEventNotifier* obj = new (ELeave) CSmsEventNotifier();
00115   CleanupStack::PushL(obj);
00116   obj->ConstructL();
00117   CleanupStack::Pop(obj);
00118   return obj;
00119 }
00120 
00121 CSmsEventNotifier::CSmsEventNotifier()
00122 {
00123   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("CSmsEventNotifier"));
00124 
00125 }
00126 
00127 CSmsEventNotifier::~CSmsEventNotifier()
00128 {
00129   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("~CSmsEventNotifier"));
00130 
00131   delete iReceiveMtm;
00132   delete iMMSMtm;
00133   delete iReceiveMtmReg;
00134   delete iReceiveSession;
00135 }
00136 
00137 void CSmsEventNotifier::ConstructL()
00138 {
00139   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("ConstructL"));
00140 
00141 #if 1
00142   iReceiveSession = CMsvSession::OpenAsObserverL(*this);
00143 #else
00144   iReceiveSession = CMsvSession::OpenSyncL(*this);
00145 #endif
00146 
00147   iReceiveMtmReg = CClientMtmRegistry::NewL(*iReceiveSession);
00148   // iReceiveMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeSMS);
00149   // iMMSMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeMultimedia);
00150 }
00151 
00152 void CSmsEventNotifier::SetHandler(i_handle_received_sms* handler)
00153 {
00154   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("AddHandler"));
00155 
00156   iHandler = handler;
00157 }
00158 
00159 // See msvapi.h for the enum TMsvSessionEvent values.
00160 //
00161 // What will happen if we leave here? Do not know, but we won't.
00162 void CSmsEventNotifier::HandleSessionEventL(TMsvSessionEvent aEvent, 
00163               TAny* aArg1, TAny* aArg2, TAny* aArg3)
00164 {
00165   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("HandleSessionEventL"));
00166   //logg("TMsvSessionEvent %d", (int)aEvent);
00167   TRAPD(errCode, DoHandleSessionEventL(aEvent, aArg1, aArg2, aArg3));
00168   if (errCode)
00169     HandleErrorL(errCode);
00170 }
00171 
00172 void CSmsEventNotifier::DoHandleSessionEventL(TMsvSessionEvent aEvent, 
00173                 TAny* aArg1, TAny* aArg2, TAny* aArg3)
00174 {
00175   DELETE_Z(iMMSMtm);
00176   DELETE_Z(iReceiveMtm);
00177 
00178   switch(aEvent) {
00179   case EMsvEntriesCreated:
00180     {
00181       if (!aArg1 || !aArg2 ) return;
00182       CMsvEntrySelection* entries=(CMsvEntrySelection *)aArg1;
00183       TMsvId id=*(TMsvId*)aArg2;
00184       if (id == KMsvGlobalInBoxIndexEntryId) {
00185   for (int i=0; i< entries->Count(); i++) {
00186     HandleReceivedL(entries->At(i), id);
00187   }
00188       }
00189     }
00190     break;
00191 
00192   case EMsvEntriesMoved:      // this event is given when message entries are moved
00193     {
00194       // An entry has been moved to another parent
00195       // We are interested messages that have been moved to Sent folder
00196       if (!aArg1 || !aArg2 || !aArg3 ) return;
00197       
00198       TMsvId* toEntryId;
00199       TMsvId* fromEntryId;
00200       toEntryId = static_cast<TMsvId*>(aArg2); 
00201       fromEntryId = static_cast<TMsvId*>(aArg3);
00202       
00203       // We take the moved entries into a selection
00204       CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1);
00205 
00206       // the entry has been moved into Sent folder
00207       if ( *toEntryId == KMsvSentEntryId )
00208   {
00209     // Process each created entry, one at a time.
00210     for(TInt i = 0; i < entries->Count(); i++)
00211       {
00212         HandleSentL(entries->At(i)); 
00213       }
00214   }
00215     }
00216     break;
00217 
00218     // Apparently all clients should respond to these events.
00219   case EMsvCloseSession:
00220   case EMsvServerTerminated:
00221     {
00222       if (iHandler) iHandler->handle_close();
00223     }
00224     break;
00225 
00226   default:
00227     break;
00228   }
00229 }
00230 
00231 void CSmsEventNotifier::HandleErrorL(TInt aError)
00232 {
00233   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("HandleErrorL"));
00234 
00235   if (iHandler) iHandler->handle_error(aError);
00236 }
00237 
00238 // May also return KNullUid to indicate failure.
00239 TUid CSmsEventNotifier::loadmessageL(const TMsvId& entry_id, TMsvEntry& entry)
00240 {
00241   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("loadmessageL"));
00242 
00243   TInt err;
00244   
00245   e_auto_ptr<CMsvEntry> realentry(0);
00246   CC_TRAP(err, realentry.reset(iReceiveSession->GetEntryL(entry_id)) );
00247   if (err != KErrNone) 
00248     {
00249       return KNullUid;
00250     }
00251   entry=realentry->Entry();
00252 
00253   if (entry.iMtm != KUidMsgTypeSMS && entry.iMtm != KUidMsgTypeMultimedia) 
00254     {
00255       // Not an SMS or MMS.
00256       return KNullUid;
00257     }
00258 
00259   CBaseMtm* mtm=0;
00260   // SetCurrentEntryL takes ownership of the CMsvEntry
00261   TMsvPartList validationFlags(KMsvMessagePartDescription|KMsvMessagePartOriginator);
00262   if (entry.iMtm == KUidMsgTypeSMS) {
00263     if (iReceiveMtm==0) iReceiveMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeSMS);
00264     mtm = iReceiveMtm;
00265     validationFlags |= KMsvMessagePartBody;
00266   } else {
00267     if (iMMSMtm==0) iMMSMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeMultimedia);
00268     mtm = iMMSMtm;
00269   }
00270   CC_TRAP(err, mtm->SetCurrentEntryL(realentry.get()));
00271   realentry.release();
00272   if (err!=KErrNone) 
00273     {
00274       return KNullUid;
00275     }
00276   if (mtm->ValidateMessage(validationFlags != 0)) 
00277     {
00278       // Not validated!
00279       return KNullUid;
00280     }
00281   
00282   // The message loading sometimes fails with KErrAccessDenied - the
00283   // message server is busy. Just retry loading.
00284   TInt retry_count=0; 
00285   const TInt MAX_RETRIES=5;
00286   while (retry_count<MAX_RETRIES) 
00287     {
00288       CC_TRAP(err, mtm->LoadMessageL());
00289       if (err==KErrAccessDenied || err==KErrInUse) {
00290   retry_count++;
00291   User::After(TTimeIntervalMicroSeconds32(100*1000)); //100 ms
00292       } else if (err==-1) {
00293   // can ignore
00294   return KNullUid;
00295       } else if (err != KErrNone) {
00296   return KNullUid;
00297       } else {
00298   break;
00299       }
00300     }
00301   if (retry_count==MAX_RETRIES) {
00302     return KNullUid;
00303   }
00304   return entry.iMtm;
00305 }
00306 
00307 void CSmsEventNotifier::HandleReceivedL(const TMsvId& entry_id, 
00308           const TMsvId& folder_id)
00309 {
00310   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("HandleReceivedL"));
00311 
00312   TMsvEntry entry;
00313   TUid mtmuid=loadmessageL(entry_id, entry);
00314   CBaseMtm* mtm = 0;
00315   if (mtmuid == KUidMsgTypeSMS ) {
00316     if (iReceiveMtm==0) iReceiveMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeSMS);
00317     mtm=iReceiveMtm;
00318   } else if ( mtmuid== KUidMsgTypeMultimedia ) {
00319     if (iMMSMtm==0) iMMSMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeMultimedia);
00320     mtm=iMMSMtm;
00321   } else {
00322     return;
00323   }
00324 
00325   if (iHandler) iHandler->handle_reception(entry_id, folder_id, mtmuid, mtm);
00326 }
00327 
00328 void CSmsEventNotifier::HandleSentL(const TMsvId& entry_id)
00329 {
00330   CALLSTACKITEM_N(_CL("CSmsEventNotifier"), _CL("HandleSentL"));
00331 
00332   TMsvEntry entry;
00333   TUid mtmuid=loadmessageL(entry_id, entry);
00334     
00335   CBaseMtm* mtm = 0;
00336   if (mtmuid == KUidMsgTypeSMS ) {
00337     if (iReceiveMtm==0) iReceiveMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeSMS);
00338     mtm=iReceiveMtm;
00339   } else if ( mtmuid== KUidMsgTypeMultimedia ) {
00340     if (iMMSMtm==0) iMMSMtm = iReceiveMtmReg->NewMtmL(KUidMsgTypeMultimedia);
00341     mtm=iMMSMtm;
00342   } else {
00343     logt("sent: not an sms or mms");
00344     return;
00345   }
00346 
00347   if (iHandler) iHandler->handle_sending(entry_id, mtmuid, mtm);
00348 }

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:57 2011 by Doxygen 1.6.1