--- a/mmsengine/genutils/src/mmsgenutils.cpp Tue Aug 31 15:11:31 2010 +0300
+++ b/mmsengine/genutils/src/mmsgenutils.cpp Wed Sep 01 12:31:54 2010 +0100
@@ -28,22 +28,39 @@
#include <barsc.h> // resource file
#include <bautils.h>
#include <miutpars.h> // e-mail utilities
-#include "cimconvertcharconv.h"
-#include "cimconvertheader.h"
+
#include <miutconv.h> // CharConv
#include <flogger.h>
#include <e32svr.h>
#include <e32base.h>
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <imcvcodc.h>
+#else
+#include <imcvcodc.h>
+#include <cimconvertheader.h>
+#endif
#include <f32file.h>
#include <UiklafInternalCRKeys.h>
-// #include <telconfigcrkeys.h>
+#include <telconfigcrkeys.h>
#include <centralrepository.h>
#include <CoreApplicationUIsSDKCRKeys.h>
#include <data_caging_path_literals.hrh>
-
-#include "telconfigcrkeys.h"
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactLink.h>
+#include <CPbk2StoreConfiguration.h> // Contact store configuration
+#include <contactmatcher.h> // contact match wrapper
+#include <CVPbkPhoneNumberMatchStrategy.h>
+#include <CVPbkContactLinkArray.h>
+#include <CVPbkFieldTypeRefsList.h>
+#include <TVPbkFieldVersitProperty.h>
+#include <VPbkFieldType.hrh>
+#include <MVPbkStoreContactFieldCollection.h>
+#include <MVPbkStoreContact.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <VPbkContactStoreUris.h>
+#include <TVPbkContactStoreUriPtr.h>
#include "mmsgenutils.h"
#include "MmsEnginePrivateCRKeys.h"
@@ -52,17 +69,16 @@
// EXTERNAL FUNCTION PROTOTYPES
// CONSTANTS
-
+const TInt KLogBufferLength = 256;
#ifdef _DEBUG
-const TInt KLogBufferLength = 256;
_LIT( KLogDir, "mmsc" );
_LIT( KLogFile, "mmsc.txt" );
#endif
-
+const TUint KMinAliasMaxLength = 14;
const TUint KExtraSpaceForConversion10 = 10;
const TUint KExtraSpaceForConversion30 = 30;
-
+const TInt KErrMultipleMatchFound = KErrGeneral;
// MACROS
// LOCAL CONSTANTS AND MACROS
@@ -419,12 +435,18 @@
// ---------------------------------------------------------
//
EXPORT_C TInt TMmsGenUtils::GetAlias(
- const TDesC& /*aAddress*/,
- TDes& /*aAlias*/,
- TInt /*aMaxLength*/,
- RFs& /*aFs*/ )
+ const TDesC& aAddress,
+ TDes& aAlias,
+ TInt aMaxLength,
+ RFs& aFs )
{
- return KErrNone;
+ TInt err = KErrNone;
+ TRAP( err, DoGetAliasL( aFs, aAddress, aAlias, aMaxLength ) );
+ if ( err == KErrNotFound )
+ {
+ err = KErrNone;
+ }
+ return err;
}
@@ -437,13 +459,59 @@
// ---------------------------------------------------------
//
EXPORT_C void TMmsGenUtils::GetAliasForAllL(
- const CDesCArray& /*aAddress*/,
- CDesCArray& /*aAlias*/,
- TInt /*aMaxLength*/,
- RFs& /*aFs*/ )
+ const CDesCArray& aAddress,
+ CDesCArray& aAlias,
+ TInt aMaxLength,
+ RFs& aFs )
{
-
+ if ( aMaxLength <= 0 )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ TUint stack = 0;
+
+ //Let's find the number of digits to match
+ TInt digitsToMatch = DigitsToMatch();
+ TInt err = KErrNone;
+
+ // Use contact wrapper to open all databases
+ CContactMatcher* contactMatcher = OpenAllStoresL( aFs );
+ CleanupStack::PushL( contactMatcher );
+ stack++;
+
+ HBufC* helpBuffer = HBufC::NewL( aMaxLength );
+ CleanupStack::PushL( helpBuffer );
+ stack++;
+
+ TPtr pHelpBuffer = helpBuffer->Des();
+
+ for ( TInt i = 0; i < aAddress.MdcaCount(); i++ )
+ {
+ // We trap these one by one in order to be able
+ // to continue to next match in case of error (not found)
+
+ // make sure the alias is empty if nothing found
+ pHelpBuffer.Zero();
+
+ TRAP( err, DoGetAliasL(
+ aAddress.MdcaPoint(i),
+ pHelpBuffer,
+ aMaxLength,
+ *contactMatcher,
+ digitsToMatch ) );
+
+ // if alias is not found, we'll have an empty buffer
+ // We have to insert it anyway to keep the indexes correct
+ // as we have two parallel arrays
+ aAlias.InsertL( i, pHelpBuffer );
+ }
+
+ // closing is best effort only.
+ TRAP_IGNORE( contactMatcher->CloseStoresL() );
+ CleanupStack::PopAndDestroy( stack, contactMatcher ); //contactMatcher, helpBuffer
+
}
// ---------------------------------------------------------
@@ -736,12 +804,40 @@
// ---------------------------------------------------------
//
void TMmsGenUtils::DoGetAliasL(
- RFs& /*aFs*/,
- const TDesC& /*aAddress*/,
- TDes& /*aAlias*/,
- TInt /*aMaxLength*/ )
+ RFs& aFs,
+ const TDesC& aAddress,
+ TDes& aAlias,
+ TInt aMaxLength )
{
-
+
+ //Let's find the number of digits to match
+ TInt digitsToMatch = DigitsToMatch();
+
+ // We have only one address and one alias to put into the array
+ CDesCArray* aliasArray = new ( ELeave )CDesCArrayFlat( 1 );
+ CleanupStack::PushL( aliasArray );
+
+ CDesCArray* realAddressArray = new ( ELeave )CDesCArrayFlat( 1 );
+ CleanupStack::PushL( realAddressArray );
+
+ realAddressArray->InsertL( 0, aAddress );
+
+ // GetAliasForAllL opens contact matcher
+ GetAliasForAllL( *realAddressArray, *aliasArray, aMaxLength, aFs );
+
+ TInt size = aliasArray->MdcaCount();
+
+ if ( size > 0 )
+ {
+ // only one item in our array
+ aAlias.Copy( aliasArray->MdcaPoint( 0 ).Left( Min( aMaxLength, aAlias.MaxLength() ) ) );
+ }
+
+ CleanupStack::PopAndDestroy( realAddressArray );
+ CleanupStack::PopAndDestroy( aliasArray );
+
+ return;
+
}
@@ -750,12 +846,151 @@
// ---------------------------------------------------------
//
void TMmsGenUtils::DoGetAliasL(
- const TDesC& /*aAddress*/,
- TDes& /*aAlias*/,
- TInt /*aMaxLength*/,
- CContactMatcher& /*aContactMatcher*/,
- TInt /*aDigitsToMatch*/ )
+ const TDesC& aAddress,
+ TDes& aAlias,
+ TInt aMaxLength,
+ CContactMatcher& aContactMatcher,
+ TInt aDigitsToMatch )
{
+ // It appears that with the new phonebook system with multiple phonebooks,
+ // TContactItemId type id cannot be extracted.
+ // The result contains MVPbkContactLink type objects.
+
+ // The given descriptor has to be at least 14 in length
+ // (otherwise this method would leave later)
+ if( aAlias.MaxLength() < KMinAliasMaxLength )
+ {
+ User::Leave( KErrBadDescriptor );
+ }
+
+ // These should be inline with each other, but if necessary,
+ // size down aMaxLength.
+ // aMaxLength, however, can be smaller than the buffer
+ if ( aMaxLength > aAlias.MaxLength() )
+ {
+ aMaxLength = aAlias.MaxLength();
+ }
+
+ if ( aMaxLength > 0 )
+ {
+ // set length of alias to 0
+ // this can be used to determine if alias was found
+ // contact id not needed or used
+ aAlias.Zero();
+ }
+
+ // Convert to real address just in case. The address should be pure already,
+ // but we are just being paranoid...
+
+ TPtrC realAddress;
+ realAddress.Set( PureAddress( aAddress, KSepaOpen, KSepaClose ) );
+ CVPbkContactLinkArray* linkArray = CVPbkContactLinkArray::NewL();
+ CleanupStack::PushL( linkArray );
+
+ // Check if the address is phone number or EMail address
+ if ( IsValidMMSPhoneAddress( realAddress, ETrue ) )
+ {
+ // Lookup the telephone number in the contact database
+ // For numbers shorter than 7 digits, only exact matches are returned
+
+ aContactMatcher.MatchPhoneNumberL( realAddress, aDigitsToMatch,
+ CVPbkPhoneNumberMatchStrategy::EVPbkMatchFlagsNone, *linkArray );
+
+ // If more than one matches have been found,
+ // the first one will be used.
+ }
+ else if ( IsValidEmailAddress( realAddress ) )
+ {
+ // Try to match with EMail address
+
+ TVPbkFieldVersitProperty prop;
+ CVPbkFieldTypeRefsList* fieldTypes = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( fieldTypes );
+
+ const MVPbkFieldTypeList& fieldTypeList = aContactMatcher.FieldTypes();
+ const MVPbkFieldType* foundType = NULL;
+
+ prop.SetName( EVPbkVersitNameEMAIL );
+/*
+ // Remove code because matching matches properies, too.
+ // We don't care about properties.
+
+ // The phonebook should provide a function that allows mathcing name only
+ foundType = fieldTypeList.FindMatch( prop, 0 );
+
+ if ( foundType )
+ {
+ fieldTypes->AppendL( *foundType );
+ }
+*/
+
+ // The field type matching does not work because it tries to match
+ // parameters we are not interested in.
+ // We try to generate a list that has all entries with versit type EMAIL
+
+ TInt i;
+ for ( i = 0; i < fieldTypeList.FieldTypeCount(); i++ )
+ {
+ foundType = &(fieldTypeList.FieldTypeAt( i ));
+ if ( foundType->VersitProperties().Count() > 0
+ && foundType->VersitProperties()[0].Name() == prop.Name() )
+ {
+ fieldTypes->AppendL( *foundType );
+ }
+ }
+
+
+ // Here we stop at first match - email addresses should be unique
+ aContactMatcher.MatchDataL( realAddress, *fieldTypes, *linkArray );
+ CleanupStack::PopAndDestroy( fieldTypes );
+ }
+ else
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ TInt nameIndex = 0; //correct index if only one match is found
+ if( linkArray->Count() == 0 )
+ {
+ Log( _L( "No match found" ) );
+ User::Leave( KErrNotFound );
+ }
+ else if( linkArray->Count() > 1 )
+ {
+ //Multiple matches found. Get the current store single match index if any.
+ nameIndex = GetCurrentStoreIndexL( *linkArray );
+ if( nameIndex == KErrMultipleMatchFound )
+ {
+ /* No unique match in current store, Hence show the name only if all the matches have
+ * identical names
+ */
+ if( ShowContactNameL( linkArray, nameIndex, aContactMatcher) == EFalse)
+ {
+ Log( _L( "No (Perfect) match found" ) );
+ User::Leave( KErrMultipleMatchFound );
+ }
+ }
+ }
+
+ // if not interested in alias, skip this
+ if ( aMaxLength > 0 )
+ {
+ HBufC* alias = GetContactNameL( linkArray->At(nameIndex), aContactMatcher );
+ if ( alias && alias->Des().Length() > 0 )
+ {
+ aAlias.Copy( alias->Des().Left( aMaxLength ) );
+ }
+ else
+ {
+ aAlias.Copy( TPtrC() );
+ }
+ delete alias;
+ alias = NULL;
+ // end of part skipped if not interested in alias
+ }
+
+ linkArray->ResetAndDestroy();
+ CleanupStack::PopAndDestroy( linkArray );
}
// ---------------------------------------------------------
@@ -1193,17 +1428,16 @@
// TMmsGenUtils::OpenAllStoresL
//
// ---------------------------------------------------------
-CContactMatcher* TMmsGenUtils::OpenAllStoresL( RFs& /*aFs*/ )
+CContactMatcher* TMmsGenUtils::OpenAllStoresL( RFs& aFs )
{
// Use contact wrapper to open all databases
- /* CContactMatcher* contactMatcher = CContactMatcher::NewL( &aFs );
+ CContactMatcher* contactMatcher = CContactMatcher::NewL( &aFs );
CleanupStack::PushL( contactMatcher );
contactMatcher->OpenDefaultMatchStoresL();
CleanupStack::Pop( contactMatcher );
- return contactMatcher;*/
- return NULL;
+ return contactMatcher;
}
// -----------------------------------------------------------------------------
@@ -1211,11 +1445,21 @@
// -----------------------------------------------------------------------------
//
HBufC* TMmsGenUtils::GetContactNameL(
- const MVPbkContactLink& /*aContactLink*/,
- CContactMatcher& /*aContactMatcher*/)
+ const MVPbkContactLink& aContactLink,
+ CContactMatcher &aContactMatcher)
{
-
- return NULL;
+ Log(_L( "- TMmsGenUtils::GetContactNameL -> start" ) );
+ MVPbkStoreContact* tempContact;
+ aContactMatcher.GetStoreContactL(aContactLink, &tempContact);
+ tempContact->PushL();
+
+ MVPbkStoreContactFieldCollection& coll = tempContact->Fields();
+ HBufC* nameBuff = aContactMatcher.GetNameL( coll );
+
+ CleanupStack::PopAndDestroy(tempContact); // tempContact
+
+ Log( _L( "- TMmsGenUtils::GetContactNameL <- end" ) );
+ return nameBuff;
}
// -----------------------------------------------------------------------------
@@ -1243,21 +1487,154 @@
// -----------------------------------------------------------------------------
//
TBool TMmsGenUtils::ShowContactNameL(
- CVPbkContactLinkArray* /*aLinkArray*/,
- TInt& /*aNameIndex*/,
- CContactMatcher& /*aContactMatcher*/)
+ CVPbkContactLinkArray* aLinkArray,
+ TInt &aNameIndex,
+ CContactMatcher &aContactMatcher)
{
- return 0;
+ Log( _L("- TMmsGenUtils::ShowContactName -> start") );
+ Log( _L("Contact Match statistics to follow..." ) );
+ Log( _L("Match count: %d"), aLinkArray->Count() );
+ /* TODO:: compare the names upto standard
+ * 1. if all the names are same - display the name
+ * eg: "abcdef xyz" && "abcdef xyz"
+ * 2. find min name legth among all,(if ONLY Part-match is needed )
+ * if this length is > standard length and matches upto standard length - display the larger name.
+ * eg: abcdef xyz123, abcdef xyz12, abcdef xyz and std length is 10,
+ * since match upto 10 chars is fine, display abcdef xyz123
+ * 3. in any other case do not show name
+ * eg: abcdef xyz , abcde xyz
+ * abcdef xyz , abcdef xy
+ * abcdef xyz , abcde
+ */
+ TInt i, minLength = 999, maxLength = 0, length = 0, maxLengthIndex = 0, stdLength = 14;
+ TBool retVal = ETrue ;
+
+ for( i = 0 ; i < aLinkArray->Count(); i++ )
+ {
+ HBufC* alias = GetContactNameL( aLinkArray->At(i), aContactMatcher );
+ Log( _L(":-> %s" ), alias->Des().PtrZ());
+ length = alias->Des().Length();
+ if(minLength > length)
+ {
+ minLength = length;
+ }
+ if(maxLength < length)
+ {
+ maxLength = length;
+ maxLengthIndex = i;
+ }
+ delete alias;
+ alias = NULL;
+ }
+
+ Log( _L( "Contact Lengths: Std Length : %d\n MinLength : %d\n MaxLength : %d\n MaxLen index: %d" ),
+ stdLength,
+ minLength,
+ maxLength,
+ maxLengthIndex);
+
+ if(minLength != maxLength)
+ {
+ //complete length match not possible
+ retVal = EFalse;
+
+ /* NOTE:
+ * Uncomment below code if partial length(upto stdLength) match is sufficient,
+ * ensure stdLength is correct
+ */
+ /*
+ if(minLength < stdLength)
+ {
+ retVal = EFalse;
+ }
+ */
+ }
+
+ if( retVal )
+ {
+ TInt ret;
+ HBufC* longestName = GetContactNameInLowerCaseL( aLinkArray->At(maxLengthIndex), aContactMatcher );
+ Log( _L( "Longest name:-> %s" ), longestName->Des().PtrZ());
+ for ( i = 0; i < aLinkArray->Count() && retVal; i++ )
+ {
+ HBufC* nameI = GetContactNameInLowerCaseL( aLinkArray->At(i), aContactMatcher );
+ Log( _L( "compared with -> %s" ), nameI->Des().PtrZ());
+ ret = longestName->Find(nameI->Des());
+ if(ret == KErrNotFound || ret != 0)
+ {
+ Log( _L( "Part/Full Match error/offset: %d" ), ret);
+ retVal = EFalse;
+ }
+ delete nameI;
+ nameI = NULL;
+ }
+ delete longestName;
+ longestName = NULL;
+ }
+
+ aNameIndex = maxLengthIndex;
+
+ Log( _L( "Final Match result : %d\n Final Match index : %d" ), retVal, maxLengthIndex);
+ Log( _L( "- TMmsGenUtils::ShowContactName <- end" ) );
+
+ return retVal;
}
// -----------------------------------------------------------------------------
// TMmsGenUtils::GetCurrentStoreIndexL
// -----------------------------------------------------------------------------
//
-TInt TMmsGenUtils::GetCurrentStoreIndexL( CVPbkContactLinkArray& /*aLinkArray*/ )
+TInt TMmsGenUtils::GetCurrentStoreIndexL( CVPbkContactLinkArray& aLinkArray )
{
-
- return 0;
+ TInt curStoreIndex( KErrMultipleMatchFound );
+ TInt curStoreMatchCount = 0;
+ RArray<TInt> otherStoreMatchIndices;
+ CleanupClosePushL( otherStoreMatchIndices );
+
+ //Get the current configured contact store array(s)
+ CPbk2StoreConfiguration* storeConfiguration = CPbk2StoreConfiguration::NewL();
+ CleanupStack::PushL( storeConfiguration );
+ CVPbkContactStoreUriArray* currStoreArray = storeConfiguration->CurrentConfigurationL();
+ CleanupStack::PopAndDestroy(storeConfiguration);
+
+ if ( currStoreArray )
+ {
+ /* Contact's store is compared against user selected stores.
+ * If contact is from such store, found index is incremented
+ * else, other store contact indices are populated into array for further use
+ */
+ for ( TInt i = 0; i < aLinkArray.Count(); i++ )
+ {
+ TVPbkContactStoreUriPtr uri = aLinkArray.At(i).ContactStore().StoreProperties().Uri();
+ if ( currStoreArray->IsIncluded( uri ) )
+ {
+ // Set index to found contact and increment the count.
+ curStoreIndex = i;
+ curStoreMatchCount++;
+ }
+ else
+ {
+ otherStoreMatchIndices.AppendL(i);
+ }
+ }
+
+ delete currStoreArray;
+ if ( curStoreMatchCount > 1)
+ {
+ /* Multiple matches found from current user selected store(s)
+ * Delete match from other stores in aLinkArray. New aLinkArray should only contain
+ * current store contact matches, so that next level pruning can be done(e.g, names can be
+ * compared and displayed if they are identical).
+ */
+ for(TInt i = otherStoreMatchIndices.Count() - 1; i >= 0; i--)
+ {
+ aLinkArray.Delete( otherStoreMatchIndices[i] );
+ }
+ curStoreIndex = KErrMultipleMatchFound;
+ }
+ }
+ CleanupStack::PopAndDestroy( &otherStoreMatchIndices );
+ return curStoreIndex;
}
// ================= OTHER EXPORTED FUNCTIONS ==============