--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiPIMServicePlugin/src/HtiSimDirHandler.cpp Wed Aug 25 15:45:01 2010 +0300
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description: Implementation of SIM card contacts handling using the new
+ * Virtual Phonebook API
+ *
+ */
+
+// INCLUDE FILES
+#include "HtiSimDirHandler.h"
+#include "HtiPIMServicePlugin.h"
+
+#include <HtiDispatcherInterface.h>
+#include <HtiLogging.h>
+
+#include <mmtsy_names.h>
+#include <mpbutil.h>
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+const TInt KSimInfoResponseLength = 12;
+const TInt KOneSimContactBufferSize = 512;
+// MACROS
+// LOCAL CONSTANTS AND MACROS
+_LIT8( KErrorUnrecognizedCommand, "Unrecognized command" );
+_LIT8( KErrorInvalidParameters, "Invalid command parameters" );
+_LIT8( KErrorImportFailed, "Contact import failed" );
+_LIT8( KErrorDeleteFailed, "Failed to delete contact" );
+_LIT8( KErrorSimCardInfoFailed, "Failed to get SIM card info" );
+_LIT8( KErrorFieldNotSupported, "Field is not supported");
+_LIT8( KErrorFieldTooBig, "Filed is too long");
+//_LIT8( KErrorSimStoreOpenFailed, "Failed to open SIM contact store" );
+//_LIT8( KErrorSimStoreUnavailable, "SIM contact store unavailable" );
+//_LIT8( KErrorContactOperationFailed, "SIM contact operation failed" );
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+CHtiSimDirHandler* CHtiSimDirHandler::NewL()
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::NewL" );
+ CHtiSimDirHandler* self = new (ELeave) CHtiSimDirHandler();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::NewL" );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::CHtiSimDirHandler
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ----------------------------------------------------------------------------
+CHtiSimDirHandler::CHtiSimDirHandler() :
+ iIsBusy(EFalse), iStoreIsOpen(EFalse)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::CHtiSimDirHandler" );
+
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::CHtiSimDirHandler" );
+ }
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::~CHtiSimDirHandler
+// Destructor.
+// -----------------------------------------------------------------------------
+CHtiSimDirHandler::~CHtiSimDirHandler()
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::~CHtiSimDirHandler" );
+ iEtelStore.Close();
+ iEtelPhone.Close();
+ iEtelServer.Close();
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::~CHtiSimDirHandler" );
+ }
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CHtiSimDirHandler::ConstructL()
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::ConstructL" );
+
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::ConstructL" );
+ }
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::SetDispatcher
+// Sets the dispatcher pointer.
+// -----------------------------------------------------------------------------
+
+void CHtiSimDirHandler::SetDispatcher(MHtiDispatcher* aDispatcher)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::SetDispatcher" );
+ iDispatcher = aDispatcher;
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::SetDispatcher" );
+ }
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::ProcessMessageL
+// Parses the received message and calls handler functions.
+// -----------------------------------------------------------------------------
+void CHtiSimDirHandler::ProcessMessageL(const TDesC8& aMessage,
+ THtiMessagePriority /*aPriority*/)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::ProcessMessageL" );
+
+ if (iStoreIsOpen == EFalse)
+ {
+ User::LeaveIfError(iEtelServer.Connect());
+ User::LeaveIfError(iEtelServer.LoadPhoneModule(KMmTsyModuleName));
+ User::LeaveIfError(iEtelPhone.Open(iEtelServer, KMmTsyPhoneName));
+ User::LeaveIfError(iEtelStore.Open(iEtelPhone, KETelIccAdnPhoneBook));
+ HTI_LOG_TEXT( "SIM card open" );
+ iStoreIsOpen = ETrue;
+ }
+
+ if (iIsBusy)
+ {
+ HTI_LOG_TEXT( "HtiSimDirHandler is busy - leaving" );
+ User::Leave(KErrInUse);
+ }
+
+ // Will be set to EFalse in the SendOkMsgL or SendErrorMessageL methods.
+ iIsBusy = ETrue;
+
+ // Zero legth of aMessage tested already in CHtiPIMServicePlugin.
+ // Other sanity checks must be done here.
+ TInt err = KErrNone;
+ TUint8 command = aMessage.Ptr()[0];
+ switch (command)
+ {
+ case CHtiPIMServicePlugin::ESimCardInfo:
+ {
+ TRAP(err ,HandleSimCardInfoL(aMessage.Right(aMessage.Length() - 1)));
+ break;
+ }
+ case CHtiPIMServicePlugin::EImportSimContact:
+ {
+ TRAP(err ,HandleSimContactImportL(aMessage.Right(aMessage.Length() - 1)));
+ break;
+ }
+ case CHtiPIMServicePlugin::EDeleteSimContact:
+ {
+ TRAP(err ,HandleSimContactDeleteL(aMessage.Right(aMessage.Length() - 1)));
+ break;
+ }
+ default:
+ {
+ SendErrorMessageL(KErrArgument, KErrorUnrecognizedCommand);
+ return;
+ }
+ }
+
+ if (err != KErrNone)
+ {
+ iIsBusy = EFalse;
+ User::Leave(err);
+ }
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::ProcessMessageL" );
+ }
+
+// -----------------------------------------------------------------------------
+// CHtiSimDirHandler::IsBusy
+// -----------------------------------------------------------------------------
+//
+TBool CHtiSimDirHandler::IsBusy()
+ {
+ return iIsBusy;
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::HandleSimCardInfoL
+// Gets information about the SIM card.
+// ----------------------------------------------------------------------------
+void CHtiSimDirHandler::HandleSimCardInfoL(const TDesC8& aData)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::HandleSimCardInfoL" );
+ if (aData.Length() != 0)
+ {
+ HTI_LOG_TEXT( "CHtiSimDirHandler: wrong length of data" );
+ SendErrorMessageL(KErrArgument, KErrorInvalidParameters);
+ return;
+ }
+
+ RMobilePhoneBookStore::TMobilePhoneBookInfoV5 etelStoreInfo;
+ RMobilePhoneBookStore::TMobilePhoneBookInfoV5Pckg etelStoreInfoPckg(etelStoreInfo);
+
+ TRequestStatus requestStatus;
+ iEtelStore.GetInfo(requestStatus, (TDes8&) etelStoreInfoPckg);
+ User::WaitForRequest(requestStatus);
+ if (requestStatus.Int() != KErrNone)
+ {
+ HTI_LOG_TEXT( "CHtiSimDirHandler: Failed to get SIM card info" );
+ SendErrorMessageL(requestStatus.Int(), KErrorSimCardInfoFailed);
+ return;
+ }
+
+ // Create and send response message
+ TBuf8<KSimInfoResponseLength> reply;
+ reply.Append(etelStoreInfo.iMaxSecondNames > 0 ? etelStoreInfo.iMaxSecondNames : 0);
+ reply.Append(etelStoreInfo.iMaxAdditionalNumbers > 0 ? etelStoreInfo.iMaxAdditionalNumbers : 0);
+ reply.Append(etelStoreInfo.iMaxEmailAddr > 0 ? etelStoreInfo.iMaxEmailAddr : 0);
+ reply.Append(etelStoreInfo.iMaxTextLength > 0 ? etelStoreInfo.iMaxTextLength : 0);
+ reply.Append(etelStoreInfo.iMaxNumLength > 0 ? etelStoreInfo.iMaxNumLength : 0);
+ reply.Append(etelStoreInfo.iMaxTextLengthSecondName > 0 ?
+ etelStoreInfo.iMaxTextLengthSecondName : 0);
+ reply.Append(etelStoreInfo.iMaxNumLengthAdditionalNumber > 0?
+ etelStoreInfo.iMaxNumLengthAdditionalNumber : 0);
+ reply.Append(etelStoreInfo.iMaxTextLengthEmailAddr > 0 ? etelStoreInfo.iMaxTextLengthEmailAddr : 0);
+ reply.Append( ( TUint8* ) ( &etelStoreInfo.iTotalEntries ), 2 );
+ reply.Append( ( TUint8* ) ( &etelStoreInfo.iUsedEntries ), 2 );
+ SendOkMsgL(reply);
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::HandleSimCardInfoL" );
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::HandleSimContactImportL
+// Imports the contact to SIM card.
+// ----------------------------------------------------------------------------
+void CHtiSimDirHandler::HandleSimContactImportL(const TDesC8& aData)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::HandleSimContactImportL" );
+
+ if(CheckImportMsg(aData) == EFalse)
+ {
+ return;
+ }
+
+ RBuf8 buffer;
+ buffer.CreateL(KOneSimContactBufferSize);
+ CleanupClosePushL(buffer);
+ CPhoneBookBuffer* pbBuffer = new (ELeave) CPhoneBookBuffer();
+ CleanupStack::PushL(pbBuffer);
+ pbBuffer->Set(&buffer);
+
+ //add new enty tag
+ User::LeaveIfError(pbBuffer->AddNewEntryTag());
+
+ TInt offset = 0;
+ TInt fieldCount = aData[offset];
+ offset++;
+
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ HTI_LOG_FORMAT( "Processing field %d", i + 1 );
+
+ TContactFieldType type = (TContactFieldType) aData[offset];
+ offset++;
+ TInt fieldLength = aData[offset];
+ offset++;
+ HBufC* fieldData = HBufC::NewLC(fieldLength);
+ fieldData->Des().Copy(aData.Mid(offset, fieldLength));
+ switch (type)
+ {
+ case ENameField:
+ User::LeaveIfError(pbBuffer->PutTagAndValue(
+ RMobilePhoneBookStore::ETagPBText, fieldData->Des()));
+ break;
+ case ESecondNameField:
+ User::LeaveIfError(pbBuffer->PutTagAndValue(
+ RMobilePhoneBookStore::ETagPBSecondName,
+ fieldData->Des()));
+ break;
+ case EPhoneNumberField:
+ User::LeaveIfError(
+ pbBuffer->PutTagAndValue(
+ RMobilePhoneBookStore::ETagPBNumber,
+ fieldData->Des()));
+ break;
+ case EEMailField:
+ User::LeaveIfError(pbBuffer->PutTagAndValue(
+ RMobilePhoneBookStore::ETagPBEmailAddress,
+ fieldData->Des()));
+ break;
+ case EAdditNumberField:
+ User::LeaveIfError(pbBuffer->AddNewNumberTag());
+ User::LeaveIfError(
+ pbBuffer->PutTagAndValue(
+ RMobilePhoneBookStore::ETagPBNumber,
+ fieldData->Des()));
+ break;
+ default:
+ HTI_LOG_FORMAT( "Unknown field type %d", type );
+ User::Leave(KErrArgument);
+ break;
+ }
+ CleanupStack::PopAndDestroy(); // fieldData
+ offset += fieldLength;
+ }
+
+ // save contact into sim card
+ TInt index = -1;
+ TRequestStatus status;
+ //store the entry in the first free location and then return
+ //this location within index when it completes the request
+ iEtelStore.Write(status, buffer, index);
+ User::WaitForRequest(status);
+ if(status.Int() != KErrNone)
+ {
+ HTI_LOG_TEXT("Failed to add SIM contact");
+ SendErrorMessageL( status.Int(), KErrorImportFailed );
+ }
+ else
+ {
+ HTI_LOG_TEXT( "SIM contact added" );
+ TBuf8<4> idBuf;
+ idBuf.Append( ( TUint8* ) &index, 4 );
+ SendOkMsgL( idBuf );
+ }
+ CleanupStack::PopAndDestroy(2); // buffer, pbBuffer
+
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::HandleSimContactImportL" );
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::HandleSimContactDeleteL
+// Creates a contact view containing the contacts to be deleted.
+// ----------------------------------------------------------------------------
+void CHtiSimDirHandler::HandleSimContactDeleteL(const TDesC8& aData)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::HandleSimContactDeleteL" );
+ TInt dataLength = aData.Length();
+ if ( dataLength != 0 && dataLength != 4 )
+ {
+ HTI_LOG_TEXT( "CHtiSimDirHandler: Wrong length of data" )
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return;
+ }
+
+ TRequestStatus status;
+ if (dataLength == 0) //delete all
+ {
+ iEtelStore.DeleteAll(status);
+ HTI_LOG_TEXT("Delete all SIM contacts");
+ }
+ else //delete one contact with given id
+ {
+ TInt id = aData[0] + (aData[1] << 8) + (aData[2] << 16) + (aData[3]
+ << 24);
+ HTI_LOG_FORMAT( "Delete SIM contact with id %d", id );
+ iEtelStore.Delete(status, id);
+ }
+
+ User::WaitForRequest(status);
+ if(status.Int() != KErrNone)
+ {
+ HTI_LOG_TEXT("Failed to delete contact(s)");
+ SendErrorMessageL( status.Int(), KErrorDeleteFailed );
+ }
+ else
+ {
+ HTI_LOG_TEXT("SIM contact(s) deleted");
+ SendOkMsgL( KNullDesC8 );
+ }
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::HandleSimContactDeleteL" );
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::CheckImportMsg
+// Validates the syntax of import contact message.
+// ----------------------------------------------------------------------------
+TBool CHtiSimDirHandler::CheckImportMsg(const TDesC8& aData)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::CheckImportMsg" );
+ // Import command syntax:
+ // amount of fields (1 byte) __
+ // type of field (1 byte) |
+ // length of data field (1 byte) | repeated <amount of fields> times
+ // field data (variable) __|
+
+ TInt length = aData.Length();
+ if (length < 4) // min length 4 bytes
+ {
+ HTI_LOG_FORMAT( "Message too short %d", length );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ RMobilePhoneBookStore::TMobilePhoneBookInfoV5 etelStoreInfo;
+ RMobilePhoneBookStore::TMobilePhoneBookInfoV5Pckg etelStoreInfoPckg(etelStoreInfo);
+
+ TRequestStatus requestStatus;
+ iEtelStore.GetInfo(requestStatus, (TDes8&) etelStoreInfoPckg);
+ User::WaitForRequest(requestStatus);
+ if (requestStatus.Int() != KErrNone)
+ {
+ HTI_LOG_TEXT( "CHtiSimDirHandler: Failed to get SIM card info" );
+ SendErrorMessageL(requestStatus.Int(), KErrorSimCardInfoFailed);
+ return EFalse;
+ }
+ TInt offset = 0;
+ TInt fieldCount = aData[offset];
+ HTI_LOG_FORMAT( "Fields %d", fieldCount );
+ if (fieldCount < 1) // must be at least one field
+ {
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ offset++;
+ TInt fieldsFound = 0;
+ while (offset < length)
+ {
+ fieldsFound++;
+ TContactFieldType fieldType = (TContactFieldType) aData[offset];
+ HTI_LOG_FORMAT( "Field type %d", fieldType );
+ TInt maxLength = 0;
+ if(fieldType == ENameField)
+ {
+ maxLength = etelStoreInfo.iMaxTextLength;
+ }
+ else if(fieldType == ESecondNameField)
+ {
+ maxLength = etelStoreInfo.iMaxTextLengthSecondName;
+ }
+ else if(fieldType == EPhoneNumberField)
+ {
+ maxLength = etelStoreInfo.iMaxNumLength;
+ }
+ else if(fieldType == EEMailField)
+ {
+ maxLength = etelStoreInfo.iMaxTextLengthEmailAddr;
+ }
+ else if(fieldType == EAdditNumberField)
+ {
+ maxLength = etelStoreInfo.iMaxNumLengthAdditionalNumber;
+ }
+ else
+ {
+ HTI_LOG_TEXT("Unknown field type");
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse; // invalid field type
+ }
+
+ if(maxLength <= 0)
+ {
+ HTI_LOG_TEXT("Field not supported");
+ SendErrorMessageL(KErrArgument, KErrorFieldNotSupported);
+ return EFalse;
+ }
+
+ offset++; // the type of field byte
+ if (offset >= length)
+ {
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt fieldLength = aData[offset];
+ HTI_LOG_FORMAT( "Field length %d", fieldLength );
+ if (fieldLength < 1)
+ {
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse; // Field data can not be empty
+ }
+ else if(fieldLength > maxLength)
+ {
+ HTI_LOG_TEXT("The length of field is too long");
+ SendErrorMessageL( KErrArgument, KErrorFieldTooBig );
+ return EFalse;
+ }
+ offset++; // advance over the length of data byte
+ offset += fieldLength; // and the field data
+ }
+
+ if (offset == length && fieldsFound == fieldCount)
+ {
+ HTI_LOG_TEXT( "Message OK" );
+ return ETrue;
+ }
+
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::SendOkMsgL
+// Helper function for sending response messages.
+// ----------------------------------------------------------------------------
+void CHtiSimDirHandler::SendOkMsgL(const TDesC8& aData)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::SendOkMsgL" );
+ iIsBusy = EFalse; // Done with the current request
+ User::LeaveIfNull(iDispatcher);
+ HBufC8* temp = HBufC8::NewL(aData.Length() + 1);
+ TPtr8 response = temp->Des();
+ response.Append((TChar) CHtiPIMServicePlugin::EResultOk);
+ response.Append(aData);
+ User::LeaveIfError(iDispatcher->DispatchOutgoingMessage(temp,
+ KPIMServiceUid));
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::SendOkMsgL" );
+ }
+
+// ----------------------------------------------------------------------------
+// CHtiSimDirHandler::SendErrorMessageL
+// Helper function for sending error response messages.
+// ----------------------------------------------------------------------------
+void CHtiSimDirHandler::SendErrorMessageL(TInt aError,
+ const TDesC8& aDescription)
+ {
+ HTI_LOG_FUNC_IN( "CHtiSimDirHandler::SendErrorMessageL" );
+ iIsBusy = EFalse; // Done with the current request
+ User::LeaveIfNull(iDispatcher);
+ User::LeaveIfError(iDispatcher->DispatchOutgoingErrorMessage(aError,
+ aDescription, KPIMServiceUid));
+ HTI_LOG_FUNC_OUT( "CHtiSimDirHandler::SendErrorMessageL" );
+ }
+
+// End of file