qtmobility/plugins/contacts/symbiansim/src/cntsimstoreprivate.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include "cntsimstoreprivate.h"
    42 #include "cntsimstoreprivate.h"
    43 #include "cntsymbiansimtransformerror.h"
    43 #include "cntsymbiansimtransformerror.h"
    44 #include "cntsimstore.h"
    44 #include "cntsimstore.h"
       
    45 #include "cntsimstoreeventlistener.h"
    45 
    46 
    46 #include <mmtsy_names.h>
    47 #include <mmtsy_names.h>
    47 #include <qtcontacts.h>
    48 #include <qtcontacts.h>
    48 
    49 #include <qcontactchangeset.h>
    49 
    50 #include <QDebug>
    50 const int KOneSimContactBufferSize = 512;
    51 
       
    52 const TInt KOneSimContactBufferSize = 512;
    51 const TInt KDataClientBuf  = 128;
    53 const TInt KDataClientBuf  = 128;
    52 const TInt KEtsiTonPosition = 0x70;
    54 const TInt KEtsiTonPosition = 0x70;
    53 
    55 
    54 CntSimStorePrivate* CntSimStorePrivate::NewL(CntSymbianSimEngine &engine, CntSimStore &simStore, const QString &storeName)
    56 CntSimStorePrivate* CntSimStorePrivate::NewL(CntSymbianSimEngine &engine, CntSimStore &simStore, const QString &storeName)
    55 {
    57 {
    64     :CActive(CActive::EPriorityStandard),
    66     :CActive(CActive::EPriorityStandard),
    65      m_state(InactiveState),
    67      m_state(InactiveState),
    66      m_engine(engine),
    68      m_engine(engine),
    67      m_simStore(simStore),
    69      m_simStore(simStore),
    68      m_storeName(storeName),
    70      m_storeName(storeName),
    69      m_storeInfoPckg(m_storeInfo)
    71      m_readOnlyAccess(false),
       
    72      m_storeInfoPckg(m_storeInfo),
       
    73      m_listener(0)
    70 {
    74 {
    71     CActiveScheduler::Add(this);
    75     CActiveScheduler::Add(this);
    72     m_managerUri = engine.managerUri();
    76     m_managerUri = engine.managerUri();
    73 }
    77 }
    74 
    78 
    75 void CntSimStorePrivate::ConstructL()
    79 void CntSimStorePrivate::ConstructL()
    76 {
    80 {
    77     TBuf<RMobilePhoneBookStore::KMaxPBIDSize> storeName;
    81     TBuf<RMobilePhoneBookStore::KMaxPBIDSize> storeName;
    78     convertStoreNameL(storeName);
    82     convertStoreNameL(storeName);
    79     
    83     
       
    84     // SDN store is always read only
       
    85     if (m_storeName == KParameterValueSimStoreNameSdn)
       
    86         m_readOnlyAccess = true;
       
    87 
    80     // Open etel server
    88     // Open etel server
    81     User::LeaveIfError(m_etelServer.Connect());
    89     User::LeaveIfError(m_etelServer.Connect());
    82     User::LeaveIfError(m_etelServer.LoadPhoneModule(KMmTsyModuleName));
    90     User::LeaveIfError(m_etelServer.LoadPhoneModule(KMmTsyModuleName));
    83 
    91 
    84     // Open etel phone
    92     // Open etel phone
   102     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - UsedEntries = %d"),
   110     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - UsedEntries = %d"),
   103             m_storeInfo.iUsedEntries);
   111             m_storeInfo.iUsedEntries);
   104     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxNumLength = %d"),
   112     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxNumLength = %d"),
   105             m_storeInfo.iMaxNumLength);
   113             m_storeInfo.iMaxNumLength);
   106     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxTextLength = %d"),
   114     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxTextLength = %d"),
   107             m_storeInfo.iMaxTextLength);    
   115             m_storeInfo.iMaxTextLength);
       
   116     
       
   117     m_listener = new (ELeave) CntSimStoreEventListener(m_engine, m_etelStore);
       
   118     m_listener->start();
   108 }
   119 }
   109 
   120 
   110 CntSimStorePrivate::~CntSimStorePrivate()
   121 CntSimStorePrivate::~CntSimStorePrivate()
   111 {
   122 {
   112     Cancel();
   123     Cancel();
   113     m_buffer.Close();
   124     delete m_listener;
   114     m_etelStore.Close();
   125     m_etelStore.Close();
   115     m_etelPhone.Close();
   126     m_etelPhone.Close();
   116     m_etelServer.Close();    
   127     m_etelServer.Close();
   117 }
   128 }
   118 
   129 
   119 void CntSimStorePrivate::convertStoreNameL(TDes &storeName)
   130 void CntSimStorePrivate::convertStoreNameL(TDes &storeName)
   120 {
   131 {
   121     if(storeName.MaxLength() < RMobilePhoneBookStore::KMaxPBIDSize) {
   132     if(storeName.MaxLength() < RMobilePhoneBookStore::KMaxPBIDSize) {
   138     if(storeName.Length() == 0) {
   149     if(storeName.Length() == 0) {
   139         User::Leave(KErrArgument);
   150         User::Leave(KErrArgument);
   140     }
   151     }
   141 }
   152 }
   142 
   153 
   143 QContactManager::Error CntSimStorePrivate::getInfo()
   154 bool CntSimStorePrivate::read(int index, int numSlots, QContactManager::Error *error)
   144 {
   155 {
   145     if (IsActive())
   156     if (IsActive()) {
   146         return QContactManager::LockedError;
   157         *error = QContactManager::LockedError;
   147     
   158         return false;
   148     // start get info request
   159     }
   149     m_etelStore.GetInfo(iStatus, (TDes8&)m_storeInfoPckg);
       
   150     SetActive();
       
   151     m_state = GetInfoState;
       
   152     
       
   153     return QContactManager::NoError;
       
   154 }
       
   155 
       
   156 QContactManager::Error CntSimStorePrivate::read(int index, int numSlots)
       
   157 {
       
   158     if (IsActive())
       
   159         return QContactManager::LockedError;
       
   160     
   160     
   161     // start reading
   161     // start reading
   162     m_buffer.Zero();
   162     m_buffer.Zero();
   163     m_buffer.ReAlloc(KOneSimContactBufferSize*numSlots);
   163     m_buffer.ReAlloc(KOneSimContactBufferSize*numSlots);
   164     m_etelStore.Read(iStatus, index, numSlots, m_buffer);
   164     m_etelStore.Read(iStatus, index, numSlots, m_buffer);
   165     SetActive();
   165     SetActive();
   166     m_state = ReadState;
   166     m_state = ReadState;
   167     
   167     
   168     return QContactManager::NoError;
   168     *error = QContactManager::NoError;
   169 }
   169     return true;
   170 
   170 }
   171 QContactManager::Error CntSimStorePrivate::write(const QContact &contact)
   171 
   172 {
   172 bool CntSimStorePrivate::write(const QContact &contact, QContactManager::Error *error)
   173     if (IsActive())
   173 {
   174         return QContactManager::LockedError;
   174     if (IsActive()) {
       
   175         *error = QContactManager::LockedError;
       
   176         return false;
       
   177     }
   175     
   178     
   176     // get index
   179     // get index
   177     m_writeIndex = KErrNotFound;
   180     m_writeIndex = KErrNotFound;
   178     if (contact.id().managerUri() == m_managerUri &&
   181     if (contact.id().managerUri() == m_managerUri &&
   179         contact.localId() > 0) {
   182         contact.localId() > 0) {
   180         m_writeIndex = contact.localId();  
   183         m_writeIndex = contact.localId();
       
   184 
       
   185         // TODO: check that the contact exist in the sim 
   181     }
   186     }
   182     
   187     
   183     // encode
   188     // encode
   184     m_buffer.Zero();
   189     m_buffer.Zero();
   185     m_buffer.ReAlloc(KOneSimContactBufferSize);
   190     m_buffer.ReAlloc(KOneSimContactBufferSize);
   186     TRAPD(err, m_convertedContact = encodeSimContactL(&contact, m_buffer));
   191     m_convertedContact = QContact(contact);
       
   192 
       
   193     TRAPD(err, encodeSimContactL(&m_convertedContact, m_buffer));
   187     if (err != KErrNone) {
   194     if (err != KErrNone) {
   188         QContactManager::Error qtError;
   195         CntSymbianSimTransformError::transformError(err, error);
   189         CntSymbianSimTransformError::transformError(err, qtError);
   196         return false;
   190         return qtError;
       
   191     }
   197     }
   192 
   198 
   193     // start writing
   199     // start writing
   194     m_etelStore.Write(iStatus, m_buffer, m_writeIndex);
   200     m_etelStore.Write(iStatus, m_buffer, m_writeIndex);
   195     SetActive();
   201     SetActive();
   196     m_state = WriteState;
   202     m_state = WriteState;
   197     
   203     
   198     return QContactManager::NoError;
   204     *error = QContactManager::NoError;
   199 }
   205     return true;
   200 
   206 }
   201 QContactManager::Error CntSimStorePrivate::remove(int index)
   207 
   202 {
   208 bool CntSimStorePrivate::remove(int index, QContactManager::Error *error)
   203     if (IsActive())
   209 {
   204         return QContactManager::LockedError;
   210     if (IsActive()) {
       
   211         *error = QContactManager::LockedError;
       
   212         return false;
       
   213     }
   205     
   214     
   206     // NOTE:
   215     // NOTE:
   207     // If index points to an empty slot and running in hardware the 
   216     // If index points to an empty slot and running in hardware the 
   208     // delete operation will not return any error.
   217     // delete operation will not return any error.
   209     
   218     
   210     m_etelStore.Delete(iStatus, index);
   219     m_etelStore.Delete(iStatus, index);
   211     SetActive();
   220     SetActive();
   212     m_state = DeleteState;
   221     m_state = DeleteState;
   213     
   222     
   214     return QContactManager::NoError;
   223     *error = QContactManager::NoError;
       
   224     return true;
       
   225 }
       
   226 
       
   227 bool CntSimStorePrivate::getReservedSlots(QContactManager::Error *error)
       
   228 {
       
   229     if (IsActive()) {
       
   230         *error = QContactManager::LockedError;
       
   231         return false;
       
   232     }
       
   233     
       
   234     // start reading
       
   235     m_buffer.Zero();
       
   236     m_buffer.ReAlloc(KOneSimContactBufferSize*m_storeInfo.iTotalEntries);
       
   237     m_etelStore.Read(iStatus, 1, m_storeInfo.iTotalEntries, m_buffer);
       
   238     SetActive();
       
   239     m_state = ReadReservedSlotsState;
       
   240     
       
   241     *error = QContactManager::NoError;
       
   242     return true;  
   215 }
   243 }
   216 
   244 
   217 void CntSimStorePrivate::DoCancel()
   245 void CntSimStorePrivate::DoCancel()
   218 {
   246 {
   219     if (m_state == GetInfoState)
       
   220         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreGetInfo);
       
   221     if (m_state == ReadState)
   247     if (m_state == ReadState)
   222         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreRead);
   248         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreRead);
   223     if (m_state == WriteState)
   249     if (m_state == WriteState)
   224         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreWrite);
   250         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreWrite);
   225     if (m_state == DeleteState)
   251     if (m_state == DeleteState)
   226         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreDelete);
   252         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreDelete);
       
   253     if (m_state == ReadReservedSlotsState)
       
   254         m_etelStore.CancelAsyncRequest(EMobilePhoneStoreRead);
   227     
   255     
   228     m_state = InactiveState;
   256     m_state = InactiveState;
   229 }
   257 }
   230 
   258 
   231 void CntSimStorePrivate::RunL()
   259 void CntSimStorePrivate::RunL()
   232 {
   260 {
       
   261     //qDebug() << "CntSimStorePrivate::RunL()" << m_state << iStatus.Int();
       
   262     
       
   263     m_asyncError = iStatus.Int();
   233     User::LeaveIfError(iStatus.Int());
   264     User::LeaveIfError(iStatus.Int());
   234     
   265     
   235     // NOTE: It is assumed that emitting signals is queued
   266     // NOTE: It is assumed that emitting signals is queued
   236     
   267     
   237     switch (m_state)
   268     switch (m_state)
   238     {
   269     {
   239         case GetInfoState:
       
   240         {
       
   241             emit m_simStore.getInfoComplete(m_storeInfo, QContactManager::NoError);
       
   242         }
       
   243         break;
       
   244         
       
   245         case ReadState:
   270         case ReadState:
   246         {
   271         {
   247             QList<QContact> contacts = decodeSimContactsL(m_buffer);
   272             QList<QContact> contacts = decodeSimContactsL(m_buffer);
   248             m_buffer.Zero();
   273 
       
   274             // set sync target
       
   275             QList<QContact>::iterator i;
       
   276             for (i = contacts.begin(); i != contacts.end(); ++i) {
       
   277                 QContactSyncTarget syncTarget;
       
   278                 syncTarget.setSyncTarget(KSimSyncTarget);
       
   279                 i->saveDetail(&syncTarget);
       
   280             }
       
   281             
   249             emit m_simStore.readComplete(contacts, QContactManager::NoError);
   282             emit m_simStore.readComplete(contacts, QContactManager::NoError);
   250         }
   283         }
   251         break;
   284         break;
   252         
   285         
   253         case WriteState:
   286         case WriteState:
   257             contactId.setLocalId(m_writeIndex);
   290             contactId.setLocalId(m_writeIndex);
   258             contactId.setManagerUri(m_managerUri);
   291             contactId.setManagerUri(m_managerUri);
   259             m_convertedContact.setId(contactId);  
   292             m_convertedContact.setId(contactId);  
   260             
   293             
   261             // set sync target
   294             // set sync target
   262             QContactSyncTarget syncTarget;
   295             if(m_convertedContact.detail(QContactSyncTarget::DefinitionName).isEmpty()) {
   263             syncTarget.setSyncTarget(KSimSyncTarget);
   296                 QContactSyncTarget syncTarget = m_convertedContact.detail(QContactSyncTarget::DefinitionName);
   264             m_convertedContact.saveDetail(&syncTarget);
   297                 syncTarget.setSyncTarget(KSimSyncTarget);
   265             
   298                 m_convertedContact.saveDetail(&syncTarget);
       
   299             }
       
   300 
   266             emit m_simStore.writeComplete(m_convertedContact, QContactManager::NoError);
   301             emit m_simStore.writeComplete(m_convertedContact, QContactManager::NoError);
   267         }
   302         }
   268         break;
   303         break;
   269         
   304         
   270         case DeleteState:
   305         case DeleteState:
   271         {
   306         {
   272             emit m_simStore.removeComplete(QContactManager::NoError);
   307             emit m_simStore.removeComplete(QContactManager::NoError);
   273         }
   308         }
   274         break;
   309         break;
   275         
   310         
       
   311         case ReadReservedSlotsState:
       
   312         {
       
   313             QList<int> reservedSlots = decodeReservedSlotsL(m_buffer);
       
   314             emit m_simStore.getReservedSlotsComplete(reservedSlots, QContactManager::NoError);
       
   315         }
       
   316         break;
       
   317         
   276         default:
   318         default:
   277         {
   319         {
   278             User::Leave(KErrUnknown);
   320             User::Leave(KErrUnknown);
   279         }
   321         }
   280         break;
   322         break;
   283 }
   325 }
   284 
   326 
   285 TInt CntSimStorePrivate::RunError(TInt aError)
   327 TInt CntSimStorePrivate::RunError(TInt aError)
   286 {
   328 {
   287     QContactManager::Error qtError = QContactManager::NoError;
   329     QContactManager::Error qtError = QContactManager::NoError;
   288     CntSymbianSimTransformError::transformError(aError, qtError);
   330     CntSymbianSimTransformError::transformError(aError, &qtError);
   289     
   331     
   290     // NOTE: It is assumed that emitting signals is queued
   332     // NOTE: It is assumed that emitting signals is queued
   291         
   333         
   292     if (m_state == GetInfoState) {
   334     if (m_state == ReadState) 
   293         RMobilePhoneBookStore::TMobilePhoneBookInfoV5 emptyInfo;
   335         emit m_simStore.readComplete(QList<QContact>(), qtError);            
   294         emit m_simStore.getInfoComplete(emptyInfo, qtError);
   336     else if (m_state == WriteState)
   295     } else if (m_state == ReadState) {
       
   296         QList<QContact> emptyList;
       
   297         emit m_simStore.readComplete(emptyList, qtError);            
       
   298     } else if (m_state == WriteState) {
       
   299         emit m_simStore.writeComplete(m_convertedContact, qtError);  
   337         emit m_simStore.writeComplete(m_convertedContact, qtError);  
   300     } else if (m_state == DeleteState) {
   338      else if (m_state == DeleteState)
   301         emit m_simStore.removeComplete(qtError);
   339         emit m_simStore.removeComplete(qtError);
   302     }
   340     else if (m_state == ReadReservedSlotsState)
   303     
   341         emit m_simStore.getReservedSlotsComplete(QList<int>(), qtError);
       
   342         
   304     m_state = InactiveState;
   343     m_state = InactiveState;
   305     
   344     
   306     return KErrNone;
   345     return KErrNone;
   307 }
   346 }
   308 
   347 
   366                             QContactPhoneNumber lastNumber = static_cast<QContactPhoneNumber>(
   405                             QContactPhoneNumber lastNumber = static_cast<QContactPhoneNumber>(
   367                                 phoneNumbers.at(phoneNumbers.count() - 1));
   406                                 phoneNumbers.at(phoneNumbers.count() - 1));
   368                             QString number = lastNumber.number();
   407                             QString number = lastNumber.number();
   369                             number.insert(0, "+");
   408                             number.insert(0, "+");
   370                             lastNumber.setNumber(number);
   409                             lastNumber.setNumber(number);
       
   410                             if (m_readOnlyAccess)
       
   411                                 m_engine.setReadOnlyAccessConstraint(&lastNumber);
   371                             currentContact.saveDetail(&lastNumber);
   412                             currentContact.saveDetail(&lastNumber);
   372                         }
   413                         }
   373                     }
   414                     }
   374                 }
   415                 }
   375 
   416 
   388                     else {
   429                     else {
   389                         // Contact name otherwise
   430                         // Contact name otherwise
   390                         QContactName name;
   431                         QContactName name;
   391                         QString nameString = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   432                         QString nameString = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   392                         name.setCustomLabel(nameString);
   433                         name.setCustomLabel(nameString);
       
   434                         if (m_readOnlyAccess)
       
   435                             m_engine.setReadOnlyAccessConstraint(&name);                        
   393                         currentContact.saveDetail(&name);
   436                         currentContact.saveDetail(&name);
   394                         QContactManager::Error error(QContactManager::NoError);
   437                         QContactManager::Error error(QContactManager::NoError);
   395                         currentContact = m_engine.setContactDisplayLabel(m_engine.synthesizedDisplayLabel(currentContact, error), currentContact);
   438                         m_engine.setContactDisplayLabel(&currentContact, m_engine.synthesizedDisplayLabel(currentContact, &error));
   396                     }
   439                     }
   397                 }
   440                 }
   398                 break;
   441                 break;
   399             }
   442             }
   400             case RMobilePhoneBookStore::ETagPBSecondName:
   443             case RMobilePhoneBookStore::ETagPBSecondName:
   401             {
   444             {
   402                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   445                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   403                     QContactNickname nickName;
   446                     QContactNickname nickName;
   404                     QString name = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   447                     QString name = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   405                     nickName.setNickname(name);
   448                     nickName.setNickname(name);
       
   449                     if (m_readOnlyAccess)
       
   450                         m_engine.setReadOnlyAccessConstraint(&nickName);                    
   406                     currentContact.saveDetail(&nickName);
   451                     currentContact.saveDetail(&nickName);
   407                 }
   452                 }
   408                 break;
   453                 break;
   409             }
   454             }
   410             case RMobilePhoneBookStore::ETagPBNumber:
   455             case RMobilePhoneBookStore::ETagPBNumber:
   411             {
   456             {
   412                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   457                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   413                     QContactPhoneNumber phoneNumber;
   458                     QContactPhoneNumber phoneNumber;
   414                     phoneNumber.setSubTypes( QContactPhoneNumber::SubTypeMobile );
       
   415                     QString number = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   459                     QString number = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   416                     phoneNumber.setNumber(number);
   460                     phoneNumber.setNumber(number);
       
   461                     if (m_readOnlyAccess)
       
   462                         m_engine.setReadOnlyAccessConstraint(&phoneNumber);                    
   417                     currentContact.saveDetail(&phoneNumber);
   463                     currentContact.saveDetail(&phoneNumber);
   418                 }
   464                 }
   419                 break;
   465                 break;
   420             }
   466             }
   421             case RMobilePhoneBookStore::ETagPBAnrStart:
   467             case RMobilePhoneBookStore::ETagPBAnrStart:
   428             {
   474             {
   429                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   475                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   430                     QContactEmailAddress email;
   476                     QContactEmailAddress email;
   431                     QString emailAddress = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   477                     QString emailAddress = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   432                     email.setEmailAddress(emailAddress);
   478                     email.setEmailAddress(emailAddress);
       
   479                     if (m_readOnlyAccess)
       
   480                         m_engine.setReadOnlyAccessConstraint(&email);                    
   433                     currentContact.saveDetail(&email);
   481                     currentContact.saveDetail(&email);
   434                 }
   482                 }
   435                 break;
   483                 break;
   436             }
   484             }
   437             case RMobilePhoneBookStore::ETagPBNewEntry:
   485             case RMobilePhoneBookStore::ETagPBNewEntry:
   471 
   519 
   472 /*! Converts QContact to the TLV format which is used to save it to the Etel store.
   520 /*! Converts QContact to the TLV format which is used to save it to the Etel store.
   473  *
   521  *
   474  * \param contact QContact to be converted
   522  * \param contact QContact to be converted
   475  * \param rawData Contact in TLV format on return.
   523  * \param rawData Contact in TLV format on return.
   476  * \return QContact containing actually saved information.
       
   477 */
   524 */
   478 QContact CntSimStorePrivate::encodeSimContactL(const QContact* contact, TDes8& rawData) const
   525 void CntSimStorePrivate::encodeSimContactL(QContact* contact, TDes8& rawData) const
   479 {
   526 {
   480     PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - IN"));
   527     // TODO: get detail definition schema and verify (unique)
   481     QContact convertedContact;
   528 
       
   529     // Keep track of the count of phone numbers added
       
   530     int phoneNumberCount(0);
       
   531     int emailCount(0);
       
   532 
   482     CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer();
   533     CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer();
   483     CleanupStack::PushL(pbBuffer);
   534     CleanupStack::PushL(pbBuffer);
   484     pbBuffer->Set(&rawData);
   535     pbBuffer->Set(&rawData);
   485 
       
   486     //add new enty tag
       
   487     User::LeaveIfError(pbBuffer->AddNewEntryTag());
   536     User::LeaveIfError(pbBuffer->AddNewEntryTag());
   488 
   537 
   489     //add name
   538     foreach(QContactDetail detail, contact->details()) {
   490     QString name;
   539         QString definitionName = detail.definitionName();
   491     QList<QContactDetail> nameDetails = contact->details(QContactName::DefinitionName);
   540 
   492     if (nameDetails.count() == 0) {
   541         if (definitionName == QContactName::DefinitionName) {
   493         // TODO: should we leave name empty?
   542             // Name
   494         name.append("Unnamed");
   543             QContactName nameDetail = static_cast<QContactName>(detail);
   495     }
   544             // Trim to the max possible length
   496     else {
   545             QString name = nameDetail.customLabel().left(m_storeInfo.iMaxTextLength);
   497         QContactName nameDetail = static_cast<QContactName>(nameDetails.at(0));
   546             if (name.isEmpty()) {
   498         name.append(nameDetail.customLabel());
   547                 name = "Unnamed";
   499         if (name.isNull()) {
   548             }
   500             // TODO: should we leave name empty?
   549             putTagAndValueL(
   501             name.append("Unnamed)");
   550                 pbBuffer,
       
   551                 RMobilePhoneBookStore::ETagPBText,
       
   552                 name);
       
   553             // Replace detail value with the trimmed one
       
   554             nameDetail.setCustomLabel(name);
       
   555             contact->saveDetail(&nameDetail);
       
   556         } else if (definitionName == QContactPhoneNumber::DefinitionName
       
   557 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
       
   558             && (phoneNumberCount == 0
       
   559             || phoneNumberCount <= m_storeInfo.iMaxAdditionalNumbers)) {
       
   560 #else
       
   561             && phoneNumberCount == 0) {
       
   562 #endif
       
   563             // Phone number
       
   564             phoneNumberCount++;
       
   565             QContactPhoneNumber numberDetail = static_cast<QContactPhoneNumber>(detail);
       
   566             QString number = numberDetail.number();
       
   567 
       
   568             // Verify the number only contains legal digits
       
   569             foreach (const QChar character, number) {
       
   570                 if(!character.isDigit()) {
       
   571                     if(character != QChar('+')
       
   572                         && character != QChar('*')
       
   573                         && character != QChar('#')
       
   574                         && character != QChar('p')
       
   575                         && character != QChar('w')) {
       
   576                         User::Leave(KErrArgument);
       
   577                     }
       
   578                 }
       
   579             }
       
   580 
       
   581             // TODO: check if the number is empty (do we have a test case for that?)
       
   582 
       
   583             // Verify the number length
       
   584             PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - phone number length = %d"),
       
   585                 numberDetail.number().length());
       
   586             if (numberDetail.number().length() > m_storeInfo.iMaxNumLength) {
       
   587                 User::Leave(KErrTooBig);
       
   588             }
       
   589 
       
   590             if (phoneNumberCount > 1) {
       
   591                 // Mark the beginning of an additional number
       
   592                 User::LeaveIfError(pbBuffer->AddNewNumberTag());
       
   593             }
       
   594 
       
   595             // The number itself
       
   596             putTagAndValueL(
       
   597                 pbBuffer,
       
   598                 RMobilePhoneBookStore::ETagPBNumber,
       
   599                 number);
       
   600 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
       
   601         // Phonebook info version 1 does not support nick name or e-mail
       
   602         } else if (definitionName == QContactNickname::DefinitionName
       
   603             && m_storeInfo.iMaxSecondNames > 0) {
       
   604             // nickname
       
   605             QContactNickname nicknameDetail = static_cast<QContactNickname>(detail);
       
   606             // Trim to the max possible length;
       
   607             QString nickname = nicknameDetail.nickname().left(m_storeInfo.iMaxTextLengthSecondName);
       
   608             putTagAndValueL(
       
   609                 pbBuffer,
       
   610                 RMobilePhoneBookStore::ETagPBSecondName,
       
   611                 nickname);
       
   612             // Replace detail value with the trimmed one
       
   613             nicknameDetail.setNickname(nickname);
       
   614             contact->saveDetail(&nicknameDetail);
       
   615         } else if (definitionName == QContactEmailAddress::DefinitionName
       
   616             && emailCount < m_storeInfo.iMaxEmailAddr) {
       
   617             emailCount++;
       
   618             QContactEmailAddress emailDetail = static_cast<QContactEmailAddress>(detail);
       
   619             if (emailDetail.emailAddress().length() > m_storeInfo.iMaxTextLengthEmailAddr) {
       
   620                 User::Leave(KErrTooBig);
       
   621             }
       
   622             putTagAndValueL(
       
   623                 pbBuffer,
       
   624                 RMobilePhoneBookStore::ETagPBEmailAddress,
       
   625                 emailDetail.emailAddress());
       
   626 #endif
       
   627         // These are ignored in the conversion
       
   628         } else if (definitionName == QContactSyncTarget::DefinitionName
       
   629             || definitionName == QContactDisplayLabel::DefinitionName
       
   630             || definitionName == QContactType::DefinitionName) {
       
   631             // Do nothing
       
   632         } else {
       
   633             User::Leave(KErrArgument);
   502         }
   634         }
   503     }
   635     }
   504     name = name.left(m_storeInfo.iMaxTextLength); //trim to the max possible length
       
   505     TPtrC nameValue(reinterpret_cast<const TUint16*>(name.utf16()));
       
   506     User::LeaveIfError(pbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText, nameValue));
       
   507 
       
   508     QContactName convertedNameDetail;
       
   509     convertedNameDetail.setCustomLabel(name);
       
   510     convertedContact.saveDetail(&convertedNameDetail);
       
   511 
       
   512     //add nickname
       
   513     if (m_storeInfo.iMaxSecondNames > 0) {
       
   514         QString nickname;
       
   515         QList<QContactDetail> nicknameDetails = contact->details(QContactNickname::DefinitionName);
       
   516         if (nicknameDetails.count() > 0) {
       
   517             QContactNickname nicknameDetail = static_cast<QContactNickname>(nicknameDetails.at(0));
       
   518             nickname = nicknameDetail.nickname();
       
   519             nickname = nickname.left(m_storeInfo.iMaxTextLengthSecondName); //trim to the max possible length
       
   520             TPtrC nicknameValue(reinterpret_cast<const TUint16*>(nickname.utf16()));
       
   521             User::LeaveIfError(pbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBSecondName, nicknameValue));
       
   522 
       
   523             QContactNickname convertedNicknameDetail;
       
   524             convertedNicknameDetail.setNickname(nickname);
       
   525             convertedContact.saveDetail(&convertedNicknameDetail);
       
   526         }
       
   527     }
       
   528 
       
   529     //add phone number
       
   530     QList<QContactDetail> phoneNumberDetails = contact->details(QContactPhoneNumber::DefinitionName);
       
   531     if (phoneNumberDetails.count() > 0) {
       
   532         PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - add phone number"));
       
   533         QContactPhoneNumber phoneNumberDetail = static_cast<QContactPhoneNumber>(phoneNumberDetails.at(0));
       
   534         QString number = phoneNumberDetail.number();
       
   535         foreach (const QChar character, number) {
       
   536             if(!character.isDigit()) {
       
   537                 if(character != QChar('+')
       
   538                     && character != QChar('*')
       
   539                     && character != QChar('#')
       
   540                     && character != QChar('p')
       
   541                     && character != QChar('w')) {
       
   542                     User::Leave(KErrArgument);
       
   543                 }
       
   544             }
       
   545         }
       
   546         PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - phone number length = %d"),
       
   547             phoneNumberDetail.number().length());
       
   548         if (phoneNumberDetail.number().length() > m_storeInfo.iMaxNumLength) {
       
   549             User::Leave(KErrTooBig);
       
   550         }
       
   551         TPtrC phoneNumberValue(reinterpret_cast<const TUint16*>(phoneNumberDetail.number().utf16()));
       
   552         PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - number = %S"), &phoneNumberValue);
       
   553         User::LeaveIfError(pbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber, phoneNumberValue));
       
   554 
       
   555         QContactPhoneNumber convertedPhoneNumberDetail;
       
   556         convertedPhoneNumberDetail.setNumber(phoneNumberDetail.number());
       
   557         convertedContact.saveDetail(&convertedPhoneNumberDetail);
       
   558     }
       
   559 
       
   560     //add additional numbers
       
   561     if (m_storeInfo.iMaxAdditionalNumbers > 0) {
       
   562         //one number is saved already
       
   563         for (int i = 1; i < phoneNumberDetails.count() && i-1 < m_storeInfo.iMaxAdditionalNumbers; ++i) {
       
   564             QContactPhoneNumber phoneNumberDetail = static_cast<QContactPhoneNumber>(phoneNumberDetails.at(i));
       
   565             if (phoneNumberDetail.number().length() > m_storeInfo.iMaxNumLengthAdditionalNumber) {
       
   566                 User::Leave(KErrTooBig);
       
   567             }
       
   568             //mark the beginning of an additional number
       
   569             User::LeaveIfError(pbBuffer->AddNewNumberTag());
       
   570             //add number itself
       
   571             TPtrC phoneNumberValue(reinterpret_cast<const TUint16*>(phoneNumberDetail.number().utf16()));
       
   572             User::LeaveIfError(pbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber, phoneNumberValue));
       
   573 
       
   574             QContactPhoneNumber convertedPhoneNumberDetail;
       
   575             convertedPhoneNumberDetail.setNumber(phoneNumberDetail.number());
       
   576             convertedContact.saveDetail(&convertedPhoneNumberDetail);
       
   577         }
       
   578     }
       
   579 
       
   580     //add e-mails
       
   581     if (m_storeInfo.iMaxEmailAddr > 0) {
       
   582         QList<QContactDetail> emailDetails = contact->details(QContactEmailAddress::DefinitionName);
       
   583         for (int i = 0; i < emailDetails.count() && i < m_storeInfo.iMaxEmailAddr; ++i) {
       
   584             QContactEmailAddress emailDetail = static_cast<QContactEmailAddress>(emailDetails.at(i));
       
   585             TPtrC emailValue(reinterpret_cast<const TUint16*>(emailDetail.emailAddress().utf16()));
       
   586             if (emailValue.Length() > m_storeInfo.iMaxTextLengthEmailAddr) {
       
   587                 User::Leave(KErrTooBig);
       
   588             }
       
   589             User::LeaveIfError(pbBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBEmailAddress, emailValue));
       
   590 
       
   591             QContactEmailAddress convertedEmailDetail;
       
   592             convertedEmailDetail.setEmailAddress(emailDetail.emailAddress());
       
   593             convertedContact.saveDetail(&convertedEmailDetail);
       
   594         }
       
   595     }
       
   596 
       
   597     CleanupStack::PopAndDestroy(pbBuffer);
   636     CleanupStack::PopAndDestroy(pbBuffer);
   598     PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - OUT"));
   637 }
   599     return convertedContact;
   638 
   600 }
   639 void CntSimStorePrivate::putTagAndValueL(CPhoneBookBuffer* pbBuffer, TUint8 tag, QString data) const
   601 
   640 {
       
   641     TPtrC value(reinterpret_cast<const TUint16*>(data.utf16()));
       
   642     User::LeaveIfError(pbBuffer->PutTagAndValue(tag, value));
       
   643 }
       
   644 
       
   645 QList<int> CntSimStorePrivate::decodeReservedSlotsL(TDes8& rawData) const
       
   646 {
       
   647     QList<int> reservedSlots;
       
   648 
       
   649     TUint8 tagValue(0);
       
   650     CPhoneBookBuffer::TPhBkTagType dataType;
       
   651 
       
   652     CPhoneBookBuffer* pbBuffer = new (ELeave) CPhoneBookBuffer();
       
   653     CleanupStack::PushL(pbBuffer);
       
   654     pbBuffer->Set(&rawData);
       
   655     pbBuffer->StartRead();
       
   656 
       
   657     while (pbBuffer->GetTagAndType(tagValue, dataType) == KErrNone)
       
   658     {
       
   659         if (tagValue == RMobilePhoneBookStore::ETagPBAdnIndex) 
       
   660         {
       
   661             TUint16 index;
       
   662             if (pbBuffer->GetValue(index) == KErrNone)
       
   663                 reservedSlots.append(index);
       
   664         } else
       
   665             pbBuffer->SkipValue(dataType);
       
   666     } //while
       
   667     
       
   668     CleanupStack::PopAndDestroy(pbBuffer);
       
   669     return reservedSlots;
       
   670 }