ipsservices/ipssosplugin/src/ipsplgmrulist.cpp
changeset 0 8466d47a6819
child 24 d189ee25cf9d
--- /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;
+
+// <cmail>
+const TInt KIpsSmtpOperationCharLessThan = '<';
+const TInt KIpsSmtpOperationCharMoreThan = '>';
+// </cmail>
+
+// ---------------------------------------------------------------------------
+// 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() );
+    // <cmail>
+    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) );
+                        }
+                    }
+                }
+            }
+        }
+    // </cmail>
+
+    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<TUint32>& 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<TUint32>& 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
+
+