diff -r 000000000000 -r 8466d47a6819 ipsservices/ipssosplugin/src/ipsplgmrulist.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ipsservices/ipssosplugin/src/ipsplgmrulist.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,496 @@ +/* +* Copyright (c) 2007 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: This file implements class CIpsPlgMruList. +* +*/ + + + +#include "emailtrace.h" +#include "ipsplgheaders.h" + +const TUint32 KMruListMailboxMask = 0x0000FFFF; +const TUint32 KMruListMailboxPartKey = 0x0; +const TUint32 KMruListValueMask = 0xFFFF0000; +const TUint32 KMruListIncorrectMBoxKey = 0xFFFFFFFF; +const TUint32 KMruListKeyBaseValue = 0x00010000; +// what are actual size in Freestyle framework? +const TInt KMruListPrefDesSize = 40; +const TInt KMruListMaxDesSize = 200; +const TInt KMruListArrayInitSize = 8; + +// +const TInt KIpsSmtpOperationCharLessThan = '<'; +const TInt KIpsSmtpOperationCharMoreThan = '>'; +// + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::NewL( ) +// --------------------------------------------------------------------------- +// +CIpsPlgMruList* CIpsPlgMruList::NewL( ) + { + FUNC_LOG; + CIpsPlgMruList* self = new( ELeave ) CIpsPlgMruList( ); + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::~CIpsPlgMruList() +// --------------------------------------------------------------------------- +// +CIpsPlgMruList::~CIpsPlgMruList() + { + FUNC_LOG; + delete iRepository; + iHbufArray.ResetAndDestroy(); + iHbufArray.Close(); + iKeys.Reset(); + iKeys.Close(); + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::CIpsPlgMruList() +// --------------------------------------------------------------------------- +// +CIpsPlgMruList::CIpsPlgMruList( ) + : iRepository( NULL ) + { + FUNC_LOG; + + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::ConstructL( ) +// --------------------------------------------------------------------------- +// +void CIpsPlgMruList::ConstructL( ) + { + FUNC_LOG; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::GetMruListL +// --------------------------------------------------------------------------- +// +CDesCArrayFlat* CIpsPlgMruList::GetMruListL( const TFSMailMsgId& aMailbox ) + { + FUNC_LOG; + // create iRepository if not yet created + CreateRepositoryL( iRepository ); + + TBool returnEmpty( EFalse ); + + // Do not cache anything, there are multiple plugin instances + iKeys.Reset(); + TUint32 mboxKey; + if ( KErrNone != GetMailboxKeyFromRepositoryL( aMailbox.Id(), mboxKey, iKeys ) ) + { + returnEmpty = ETrue; + } + iKeys.Reset(); + + // get correct mailbox key and fill corresponding name and address keys + // in keys array + if ( !returnEmpty ) + { + if ( KErrNone != iRepository->FindL( mboxKey, KMruListValueMask, iKeys ) ) + { + returnEmpty = ETrue; + } + } + + // if we have found correct key find all keys that + // maches pattern 0xMKEY**** key array should contain + // at least 3 items, and size shoud be odd + // or array is empty or corrupted + TInt keyCount( iKeys.Count() ); + if ( !returnEmpty && keyCount >= 3 && ( keyCount%2 ) == 1 ) + { + iHbufArray.ResetAndDestroy(); + iKeys.SortUnsigned(); + TInt i(0); + + // first item in array should be mbox key + if ( iKeys[0] == mboxKey ) + { + // index to first name key + i = 1; + // store name and address in one loop cycle + while ( !returnEmpty && i <= ( keyCount-2 ) ) + { + TUint key = iKeys[i]; + // name is always in odd and address in even key + if ( (key%2==1) && (iKeys[i+1]==key+1) ) + { + // adding name and email to hbuf array + if ( StoreToArrayL(iKeys[i]) != KErrNone ) + { + // something went wrong in name store + // just break the loop and return empty + HandleRepositoryError( mboxKey, KErrCorrupt ); + returnEmpty = ETrue; + } + if ( StoreToArrayL(iKeys[i+1]) != KErrNone ) + { + // store is corrupted + HandleRepositoryError( mboxKey, KErrCorrupt ); + returnEmpty = ETrue; + } + } + i = i+2; + } + } + else + { + // first item was not mailbox key + // centrep data is corrupted + HandleRepositoryError( mboxKey, KErrCorrupt ); + returnEmpty = ETrue; + } + } + else if ( !returnEmpty ) + { + // mailbox found but there is no data or centrep is corrupted, + // return empty + HandleRepositoryError( mboxKey, KErrCorrupt ); + returnEmpty = ETrue; + } + + // create and return des array + CDesCArrayFlat* retArr = NULL; + + if ( !returnEmpty ) + { + retArr = new ( ELeave ) CDesCArrayFlat( KMruListArrayInitSize ); + CleanupStack::PushL( retArr ); + + TInt count( iHbufArray.Count() ); + // fill descriptor array + for ( TInt i(0); i < count; i++ ) + { + HBufC* app = iHbufArray[i]; + retArr->AppendL(*app); + } + CleanupStack::Pop( retArr ); + } + else + { + iHbufArray.ResetAndDestroy(); + retArr = new ( ELeave ) CDesCArrayFlat( KMruListArrayInitSize ); + } + + return retArr; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::SetMruListL +// --------------------------------------------------------------------------- +// +void CIpsPlgMruList::SetMruListL( const TFSMailMsgId& aMailBoxId, + MDesCArray* aNewMruList ) + { + FUNC_LOG; + // create iRepository if not yet created + CreateRepositoryL( iRepository ); + + TUint32 mboxKey = KMruListIncorrectMBoxKey; + iKeys.Reset(); + // get mailbox keys to keys array and + // check if mailboxid is already stored in some key + TInt error = GetMailboxKeyFromRepositoryL( + aMailBoxId.Id(), mboxKey, iKeys ); + + if ( KErrNone == error ) + { + // mailbox found + TUint32 errorKey; + error = iRepository->Delete( mboxKey, KMruListValueMask, errorKey ); + HandleRepositoryError( mboxKey, error ); + } + else + { + // mailbox not found, create new key + mboxKey = GetUnusedMboxKey( iKeys ); + } + + // set new values to central repository + // create mailboxid key + error = iRepository->Create( mboxKey, TInt( aMailBoxId.Id() ) ); + // handle error + TInt count( aNewMruList->MdcaCount() ); + // + for ( TInt i(0); error == KErrNone && i < count; i += 2 ) + { + if( i + 1 < count ) + { + TPtrC displayName = aNewMruList->MdcaPoint(i); + TPtrC emailAddress = aNewMruList->MdcaPoint(i + 1); + + // Need to locate angle brackets from end of the data, if there + // is display name with special characters + TInt start( emailAddress.LocateReverse( KIpsSmtpOperationCharLessThan ) ); + TInt end( emailAddress.LocateReverse( KIpsSmtpOperationCharMoreThan ) ); + + if ( KErrNotFound != start && KErrNotFound != end ) + { + start += 1; + emailAddress.Set( aNewMruList->MdcaPoint(i + 1).Mid( start, ( end - start ) ) ); + } + + // check validity of email before saving diplay name and address + if( IpsSetUtils::IsValidEmailAddressL(emailAddress) ) + { + // set values to ascending keys + mboxKey++; + + if ( aNewMruList->MdcaPoint(i).Length() <= KMruListMaxDesSize ) + { + error = iRepository->Create( mboxKey, aNewMruList->MdcaPoint(i) ); + // handle errors + } + else + { + TDesC des = aNewMruList->MdcaPoint(i); + error = iRepository->Create( + mboxKey, des.Mid(0,KMruListMaxDesSize) ); + } + + mboxKey++; + + if( error == KErrNone ) + { + if ( aNewMruList->MdcaPoint(i + 1).Length() <= KMruListMaxDesSize ) + { + error = iRepository->Create( mboxKey, aNewMruList->MdcaPoint(i + 1) ); + } + else + { + TDesC des = aNewMruList->MdcaPoint(i + 1); + error = iRepository->Create( + mboxKey, des.Mid(0,KMruListMaxDesSize) ); + } + } + } + } + } + // + + if ( KErrNone != error ) + { + HandleRepositoryError( mboxKey, error ); + } + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::ClearDataL +// --------------------------------------------------------------------------- +// +void CIpsPlgMruList::ClearDataL( const TFSMailMsgId& aMailBoxId ) + { + FUNC_LOG; + CreateRepositoryL( iRepository ); + + TUint32 mboxKey = KMruListIncorrectMBoxKey; + iKeys.Reset(); + // get mailbox keys to keys array and + // check if mailboxid is already sotred in some key + TInt error = GetMailboxKeyFromRepositoryL( + aMailBoxId.Id(), mboxKey, iKeys ); + + // we have found correct mboxKey + if ( KErrNone == error ) + { + TUint32 errorKey; + error = iRepository->Delete( mboxKey, KMruListValueMask, errorKey ); + HandleRepositoryError( mboxKey, error ); + } + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::StoreToArrayL +// --------------------------------------------------------------------------- +// +TInt CIpsPlgMruList::StoreToArrayL( TUint32 aKey ) + { + FUNC_LOG; + HBufC* hbuf = HBufC::NewLC( KMruListPrefDesSize ); + + TPtr pdes = hbuf->Des(); + TInt actualSize(0); + + TInt error = iRepository->Get( aKey, pdes, actualSize ); + + // the case descriptor is larger than pref size + if ( error == KErrOverflow ) + { + if ( actualSize > KMruListMaxDesSize ) + { + // centrep contains too large descriptors + // impossible if centrep is edited only by this code, + // set corrupted + error = KErrCorrupt; + } + else + { + CleanupStack::PopAndDestroy( hbuf ); + hbuf = HBufC::NewLC( actualSize ); + TPtr pdes2 = hbuf->Des(); + error = iRepository->Get( aKey, pdes2 ); + } + } + + // add or delete + if ( KErrNone == error ) + { + iHbufArray.AppendL( hbuf ); + CleanupStack::Pop( hbuf ); + } + else + { + CleanupStack::PopAndDestroy( hbuf ); + } + return error; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::GetMailboxKeyFromRepositoryL +// --------------------------------------------------------------------------- +// +TInt CIpsPlgMruList::GetMailboxKeyFromRepositoryL( + TInt aMboxId, + TUint32& aMboxKey, + RArray& aArray ) + { + FUNC_LOG; + // keys is found from centrep with partkey 0x0 and mask 0x0000FFFF + // result is array of keys that maches to pattern 0x****0000 + TInt error = iRepository->FindL( + KMruListMailboxPartKey, KMruListMailboxMask, aArray ); + + // No need to handle other errors than not found, + // this function should only return KErrNone or KErrNotFound + TInt tempId; + error = KErrNotFound; + + //find correct mailbox key from array: + for ( TInt i = 0; error == KErrNotFound && i < aArray.Count(); i++ ) + { + if ( iRepository->Get( aArray[i], tempId ) == KErrNone + && tempId == aMboxId ) + { + aMboxKey = aArray[i]; + error = KErrNone; + } + } + + return error; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::GetUnusedMboxKey +// --------------------------------------------------------------------------- +// +TUint32 CIpsPlgMruList::GetUnusedMboxKey( RArray& aKeys ) + { + FUNC_LOG; + // Warning: this function is complex and may contain bugs!!! + + TUint32 newKey = aKeys.Count()*KMruListKeyBaseValue; + + if ( aKeys.Count() > 1 ) + { + // this loop finds smallest unused key from sorted key array, + // if array[i] == i*basekey at every i when i == 0...count-1 + // then newKey is not changed + aKeys.SortUnsigned(); + TUint32 tempKey = newKey; + for ( TInt i = 0; tempKey == newKey && i < ( aKeys.Count() - 1); i++ ) + { + if ( aKeys[i] + KMruListKeyBaseValue != aKeys[i+1] ) + { + tempKey = aKeys[i] + KMruListKeyBaseValue; + } + } + newKey = tempKey; + } + else if ( aKeys.Count() == 1 && aKeys[0] == KMruListKeyBaseValue ) + { + newKey = 0; + } + + + return newKey; + } + +// --------------------------------------------------------------------------- +// CIpsPlgMruList::HandleRepositoryError +// --------------------------------------------------------------------------- +// +void CIpsPlgMruList::HandleRepositoryError( TUint32 aMboxKey, TInt aError ) + { + FUNC_LOG; + TBool doClear = EFalse; + switch ( aError ) + { + // log these error cases + case KErrNone: + // no error + break; + case KErrNotFound: + // no serious error + break; + case KErrPermissionDenied: + // this should be panic because application has no + // privileges for mru repository + break; + case KErrAbort: + // transaction has previously failed + // clear mailbox data if it helps... + doClear = ETrue; + break; + case KErrArgument: + // error in argument, for ex. trying to put integer to descriptor + // key, solution clear all keys matching aMailbox + doClear = ETrue; + break; + case KErrCorrupt: + // just clear all keys matching aMailbox + doClear = ETrue; + break; + case KErrAlreadyExists: + // should handle elsewhere, if ends here clear data + doClear = ETrue; + break; + default: + // something wrong , clear data + doClear = ETrue; + break; + } + + if ( doClear ) + { + // don't care about errors... + TUint32 errorKey; + TInt error = iRepository->Delete( aMboxKey, KMruListValueMask, errorKey ); + } + } + + +// End of file + +