pkiutilities/CertmanUi/SRC/CertmanuiCertificateHelper.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
child 12 a005fc61b02a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2003-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 class CCertManUICertificateHelper
*
*/


#include <X509CertNameParser.h>
#include <certmanui.rsg>
#include <hash.h>                   // MD5 fingerprint
#include <aknmessagequerydialog.h>
#include <pkixcertchain.h>          // for validation
#include <aknnotewrappers.h>        // for warning & information notes
#include <sysutil.h>
#include <ErrorUI.h>
#include <unifiedkeystore.h>
#include <TrustedSitesStore.h>
#include <x509keys.h>               // TX509KeyFactory
#include <e32math.h>                // Pow
#include "Certmanui.hrh"
#include "CertmanuiCertificateHelper.h"
#include "CertmanuiCommon.h"
#include "CertmanuiSyncWrapper.h"
#include "CertManUILogger.h"

const TInt KFileCertStoreUid( 0x101F501A );
const TInt KTrustedServerCertStoreUid( 0x101FB66F );
const TInt KDeviceCertStoreUid( 0x101FB668 );
const TInt KDeviceKeyStoreUid( 0x101FB66A );

_LIT( KBlockSeparator, " " );

template <class T>
class CleanupResetAndDestroy
    {
public:
    inline static void PushL( T& aRef );
private:
    static void ResetAndDestroy( TAny *aPtr );
    };

template <class T>
inline void CleanupResetAndDestroyPushL( T& aRef );

template <class T>
inline void CleanupResetAndDestroy<T>::PushL( T& aRef )
    {
    CleanupStack::PushL( TCleanupItem( &ResetAndDestroy, &aRef ) );
    }

template <class T>
void CleanupResetAndDestroy<T>::ResetAndDestroy( TAny *aPtr )
    {
    if( aPtr )
        {
        static_cast<T*>( aPtr )->ResetAndDestroy();
        }
    }

template <class T>
inline void CleanupResetAndDestroyPushL( T& aRef )
    {
    CleanupResetAndDestroy<T>::PushL( aRef );
    }


// ---------------------------------------------------------
// CCertManUICertificateHelper::CCertManUICertificateHelper()
// Default C++ Constructor
// ---------------------------------------------------------
//
CCertManUICertificateHelper::CCertManUICertificateHelper( CCertManUIKeeper& aKeeper )
: iKeeper(aKeeper)
    {
  }

// ---------------------------------------------------------
// CCertManUICertificateHelper::~CCertManUICertificateHelper()
// Destructor
// ---------------------------------------------------------
//
CCertManUICertificateHelper::~CCertManUICertificateHelper()
    {
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::CutCertificateField(TPtrC aField)
// If CertLabel, Issuer and Owner length is over 80 characters,
// cut it down to 80
// Returns the cut certificate field.
// ---------------------------------------------------------
//
TPtrC CCertManUICertificateHelper::CutCertificateField( TPtrC aField )
    {
    CERTMANUILOGGER_ENTERFN(
         "CCertManUICertificateHelper::CutCertificateField" );

    TInt fieldLength = aField.Length();
    if ( fieldLength >= KMaxLengthTextCertLabelVisible )
        {
        TPtrC cutCertLabel = aField.Mid( 0, KMaxLengthTextCertLabelVisible );

        CERTMANUILOGGER_LEAVEFN(
           "CCertManUICertificateHelper::CutCertificateField" );

        return cutCertLabel;
        }

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::CutCertificateField" );

    return aField;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::IsCertificateDeletable
// Check whether certificate is deletable
// ---------------------------------------------------------
//
TBool CCertManUICertificateHelper::IsCertificateDeletable( TInt aIndex,
    TInt aType ) const
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::IsCertificateDeletable" );
    TBool ret = ETrue;

    // If wim has not been enabled and certificate resides in smart card
    // we cannot delete it since we don't have smart card certificate
    // delete functionality in non WIM builds. So in non WIM builds all
    // smart card certificates are marked read-only.
    if( aIndex > -1 )
        {
        CCTCertInfo* entry;
        if ( aType == KCertTypeAuthority )
            {
            entry = iKeeper.iCALabelEntries[ aIndex ]->iCAEntry;
            }
        else if( aType == KCertTypeTrustedSite )
            {
            entry = iKeeper.iPeerLabelEntries[ aIndex ]->iPeerEntry;
            }
        else if( aType == KCertTypeDevice )
            {
            entry = iKeeper.iDeviceLabelEntries[ aIndex ]->iDeviceEntry;
            }
        else
            {
            entry = iKeeper.iUserLabelEntries[ aIndex ]->iUserEntry;
            }
        if ( !entry->IsDeletable() )
            {
            ret = EFalse;
            }
        }

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::IsCertificateDeletable" );
    return ret;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::IsOneMarkedCertificateDeletable
// Check whether one marked certificate is deletable, or
// if none certificate is marked, check if the highlighted
// certificate is deletable
// ---------------------------------------------------------
//
TBool CCertManUICertificateHelper::IsOneMarkedCertificateDeletable
    ( CEikColumnListBox* aListBox, TInt aType ) const
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::IsOneMarkedCertificateDeletable" );

    const CArrayFix<TInt>* array  = aListBox->SelectionIndexes();
    TInt markedCount = array->Count();
    TBool oneIsDeletable = EFalse;

    if ( 0 == markedCount )
        {
        TInt currentItem = aListBox->CurrentItemIndex();
        return IsCertificateDeletable( currentItem, aType );
        }

    for ( TInt i = 0; !oneIsDeletable && i < markedCount; i++ )
        {
        oneIsDeletable = IsCertificateDeletable( (*array)[i], aType );
        }

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::IsOneMarkedCertificateDeletable" );

    return oneIsDeletable;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::MessageQueryViewDetailsL(TInt aIndex)
// Creates the whole of certificate details view
// Appends strings from both resources and CertManAPI to one
// message body text and displays it.
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::MessageQueryViewDetailsL( TInt aIndex,
    TInt aType,
    CEikonEnv* aEikonEnv )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::MessageQueryViewDetailsL" );
     LOG_WRITE_FORMAT( "certificate index %i", aIndex );

    iKeeper.StartWaitDialogL( ECertmanUiWaitDialog );

    HBufC* message = HBufC::NewLC( KMaxLengthTextDetailsBody );
    TRAPD( err, CreateMessageBodyTextL( aIndex, aType, aEikonEnv, *message ) );

    iKeeper.CloseWaitDialogL();
    User::LeaveIfError( err );

    if( message->Length() )
        {
        HBufC* header = StringLoader::LoadLC( R_TEXT_RESOURCE_DETAILS_VIEW_HEADER );
        CAknMessageQueryDialog* dlg = CAknMessageQueryDialog::NewL( *message );
        dlg->PrepareLC( R_MESSAGE_QUERY_DETAILS_VIEW );
        dlg->QueryHeading()->SetTextL( *header );
        dlg->RunLD();
        CleanupStack::PopAndDestroy( header );
        }

    CleanupStack::PopAndDestroy( message );

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::MessageQueryViewDetailsL" );
    }

// ---------------------------------------------------------
// CCertManUIViewAuthority::ValidateCertificateL(
// Checks if the certificate is corrupted
// Checks the validity period of the certificate
// Display only one warning note, in the following order:
// 1) Expired/Not yet valid
// 2) Corrupted
// 3) Not trusted
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::ValidateCertificateL(
    TInt aIndex, CCertificate* aDetails, const CCTCertInfo& aCertInfo, TInt aType )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::ValidateCertificateL" );

    TInt poppableItems = 0;
    // Check allways first the validity period
    // Show Expired/Not yet valid notes
    const CValidityPeriod& validityPeriod = aDetails->ValidityPeriod();
    const TTime& startValue = validityPeriod.Start();
    const TTime& finishValue = validityPeriod.Finish();
    TTime current;
    current.UniversalTime();

    if ( startValue > current )
        {
        // certificate is not valid yet
        HBufC* string = StringLoader::LoadLC(
            R_WARNING_NOTE_TEXT_CERTIFICATE_NOT_VALID_YET );
        DisplayWarningNoteLD(string);
        }
    else if ( finishValue < current )
        {
        // certificate is expired
        HBufC* string = StringLoader::LoadLC(
            R_WARNING_NOTE_TEXT_CERTIFICATE_EXPIRED );
        DisplayWarningNoteLD( string );
        }
    else
        {
        // put here check for certificate status, show warning notes if needed
        TBool noValidationError = ETrue;
        CArrayFixFlat<TValidationError>* status = NULL;
        TCertificateFormat certificateFormat;

        if ( aType == KCertTypeAuthority )
            {
            certificateFormat = iKeeper.iCALabelEntries[aIndex]->
                                        iCAEntry->CertificateFormat();
            }
        else if ( aType == KCertTypeTrustedSite )
            {
            certificateFormat = iKeeper.iPeerLabelEntries[aIndex]->
                                        iPeerEntry->CertificateFormat();
            }
        else if ( aType == KCertTypeDevice )
            {
            certificateFormat = iKeeper.iDeviceLabelEntries[aIndex]->
                                        iDeviceEntry->CertificateFormat();
            }
        else
            {
            certificateFormat = iKeeper.iUserLabelEntries[aIndex]->
                                        iUserEntry->CertificateFormat();
            }

        switch ( certificateFormat )
            {
            case EX509Certificate:
                {
                status = ValidateX509CertificateL(
                    (CX509Certificate*)aDetails );
                break;
                }
            default:
                {
                status = new ( ELeave) CArrayFixFlat<TValidationError>( 1 );
                break;
                }
            }
        CleanupStack::PushL( status );
        poppableItems++;

        TInt errorCount = status->Count();
        TBool ready = EFalse;
        for ( TInt i = 0; i < errorCount && !ready; i++ )
            {
            TValidationError errorType = status->At(i);

            switch ( errorType )
                {
                case EValidatedOK:
                case EChainHasNoRoot:
                case EBadKeyUsage:
                // Ignore these errors
                    LOG_WRITE( "Ignored certificate validation error" );
                    break;

                default:
                // certificate is corrupted
                noValidationError = EFalse;
                HBufC* string = StringLoader::LoadLC(
                    R_WARNING_NOTE_TEXT_CERTIFICATE_CORRUPTED );
                DisplayWarningNoteLD( string );
                ready = ETrue;
                    break;
                }
            }

        if ( noValidationError  && (aType == KCertTypeAuthority ))
        // Check for last if the CA certificate has no clients,
        // ie. the trust state of every client is No
        // For user certificates we don't do the check
            {

            RArray<TUid> trusterUids;
            CleanupClosePushL( trusterUids );
            poppableItems++;

            iKeeper.iWrapper->GetApplicationsL(
                iKeeper.CertManager(), aCertInfo, trusterUids );

            if ( trusterUids.Count() == 0)
                {
                HBufC* string = StringLoader::LoadLC(
                    R_WARNING_NOTE_TEXT_CERTIFICATE_NOT_TRUSTED );
                DisplayWarningNoteLD( string );
                }
            }
        }
    CleanupStack::PopAndDestroy( poppableItems );

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::ValidateCertificateL" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DetailsFieldDynamicL(
// Appends a field that has string from resources and string from CertManAPI
// to the details view message body
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DetailsFieldDynamicL(
    HBufC& aMessage, TPtrC aValue, TInt aResourceOne, TInt aResourceTwo )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DetailsFieldDynamicL" );

    DetailsResourceL( aMessage, aResourceOne );
    DetailsDynamicL( aMessage, aValue, aResourceTwo );
    aMessage.Des().Append( KCertManUIDetailsViewEnter );

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DetailsFieldDynamicL" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DetailsResourceL(
// Reads line from resources
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DetailsResourceL(
    HBufC& aMessage, TInt aResourceOne )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DetailsResourceL" );

    HBufC* stringHolder = StringLoader::LoadLC( aResourceOne );
    aMessage.Des().Append( stringHolder->Des() );
    CleanupStack::PopAndDestroy();  // stringHolder
    aMessage.Des().Append( KCertManUIDetailsViewEnter );

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DetailsResourceL" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DetailsFieldResourceL(
// Appends a field that has two strings from resources
// to the details view message body
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DetailsFieldResourceL(
    HBufC& aMessage, TInt aResourceOne,
    TInt aResourceTwo)
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DetailsFieldResourceL" );

    DetailsResourceL( aMessage, aResourceOne );
    DetailsResourceL( aMessage, aResourceTwo );
    aMessage.Des().Append( KCertManUIDetailsViewEnter );

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DetailsFieldResourceL" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DevideToBlocks
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DevideToBlocks( const TDesC8& aInput, TPtr aOutput )
    {
    const TInt KBlockLength = 2;
    TInt blockIndex = 0;
    for ( TInt j = 0 ; j < aInput.Length() ; j++ )
        {
        if ( blockIndex == KBlockLength )
            {
            aOutput.Append( KBlockSeparator );
            blockIndex = 0;
            }
        aOutput.AppendNumFixedWidthUC( (TUint)(aInput[ j ]), EHex, 2 );
        ++blockIndex;
        }
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DisplayWarningNoteLD(HBufC* aString)
// Displays the warning note for corrupted/expired/not yet valid certificate
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DisplayWarningNoteLD( HBufC* aString )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DisplayWarningNoteLD" );

    CAknWarningNote* note = new ( ELeave ) CAknWarningNote( ETrue );
    note->ExecuteLD( *aString );
    CleanupStack::PopAndDestroy();  // aString

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DisplayWarningNoteLD" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::ValidateX509CertificateL(CX509Certificate* aDetails)
// Checks if the certificate is corrupted
// Checks the validity period of the certificate
// Display only one warning note, in the following order:
// 1) Expired/Not yet valid
// 2) Corrupted
// 3) Not trusted
// ---------------------------------------------------------
//
CArrayFixFlat<TValidationError>* CCertManUICertificateHelper::
    ValidateX509CertificateL( CX509Certificate* aDetails )
    {
    TInt poppableItems = 0;
    CArrayFixFlat<TValidationError>* status =
        new ( ELeave ) CArrayFixFlat<TValidationError>( 1 );
    CleanupStack::PushL( status ); //This is returned, so it isn't destroyed at the end.

    TTime GMTTime;
    GMTTime.UniversalTime(); // Get Universal Time
    RPointerArray<CX509Certificate> certArray( &aDetails, 1 );

    CPKIXCertChain* chain = CPKIXCertChain::NewLC(
        iKeeper.iRfs, aDetails->Encoding(), certArray );
    poppableItems++;

    CPKIXValidationResult* result = CPKIXValidationResult::NewLC();
    poppableItems++;
    iKeeper.iWrapper->ValidateX509RootCertificateL( result, GMTTime, chain );

    TValidationStatus validationStatus = result->Error();
    //Set reserve space. One for error, other for warnings.
    status->SetReserveL( 1 + result->Warnings().Count() );
    status->AppendL(validationStatus.iReason);
    for ( TUint8 i = 0; i < result->Warnings().Count(); i++ )
        {
        status->AppendL( result->Warnings().At(0).iReason );
        }

    CleanupStack::PopAndDestroy( poppableItems );    //  All but status.
    CleanupStack::Pop();        //  status
    return status;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DetailsDynamicL(
// HBufC& aMessage, TPtrC aValue, TInt aResourceOne)
// Reads dynamic text from CertManAPI, if the string is empty
// put a not defined text from the resource in its place
// KMaxLengthTextCertLabel = 510, used by CertLabel(), Issuer(), Owner()
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DetailsDynamicL(
    HBufC& aMessage, TPtrC aValue, TInt aResourceOne )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DetailsDynamicL" );

    HBufC* buf = HBufC::NewLC( KMaxLengthTextCertLabel );
    buf->Des() = aValue;
    buf->Des().TrimLeft();
    // Cut CertLabel after fourth semi colon
    TPtrC trimmedCertLabel = CutCertificateField( buf->Des() );
    buf->Des().Copy( trimmedCertLabel );
    TInt length = buf->Des().Length();
    if ( length == 0 )
        {
        DetailsResourceL( aMessage, aResourceOne );
        }
    else
        {
        //LRM (Left-to-Right mark 200E)
        const TInt KLRMark = 0x200E;
        aMessage.Des().Append( buf->Des() );
        aMessage.Des().Append(KLRMark);
        aMessage.Des().Append( KCertManUIDetailsViewEnter );
        }
    CleanupStack::PopAndDestroy();  // buf

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DetailsDynamicL" );
    }

// ---------------------------------------------------------
// CCertManUIViewAuthority::ConfirmationQueryDeleteCertL()
// Deletes either certificate in focus if there are no marked items,
// or deletes the marked items
// Shows read-only information notes if certificates are not deletable
// Returns ETrue if at least one certificate is deleted
// ---------------------------------------------------------
//
TBool CCertManUICertificateHelper::ConfirmationQueryDeleteCertL(
    TInt aType,
    CEikColumnListBox* aListBox )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::ConfirmationQueryDeleteCertL" );

    TBool result = EFalse;

    const CArrayFix<TInt>* array = aListBox->SelectionIndexes();
    TInt focusPosition = aListBox->CurrentItemIndex();
    CCTCertInfo* entry;
    TInt queryOk = 0;
    // comes here when there is no selection, can be read-only
    // certificate if Clear key is pressed, must check
    if ( array->Count() == 0 && IsCertificateDeletable( focusPosition, aType ) )
        {
        if( aType == KCertTypeAuthority )
            {
            entry = iKeeper.iCALabelEntries[ focusPosition ]->iCAEntry;
            }
        else if( aType == KCertTypeTrustedSite )
            {
            entry = iKeeper.iPeerLabelEntries[ focusPosition ]->iPeerEntry;
            }
        else if( aType == KCertTypeDevice )
            {
            entry = iKeeper.iDeviceLabelEntries[ focusPosition ]->iDeviceEntry;
            }
        else
            {
            entry = iKeeper.iUserLabelEntries[ focusPosition ]->iUserEntry;
            }
        queryOk = DeleteSingleItemQueryL( *entry );
        if ( queryOk )
            {
            if (IsCertificateDeletable( focusPosition, aType ))
                {
                DeleteSingleItemL( *entry, focusPosition, aListBox, aType );


                AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(
                    aListBox, focusPosition, ETrue );
                result = ETrue;
                }
            else
                {
                ReadOnlySingleItemNoteL( *entry );
                }
            }
        }
    else if ( IsOneMarkedCertificateDeletable(aListBox, aType) ) //if (array->Count()=>1)
        {
        if ( aType == KCertTypeAuthority )
            {
            entry = iKeeper.iCALabelEntries[ array->At(0) ]->iCAEntry;
            }
        else if ( aType == KCertTypeTrustedSite )
            {
            entry = iKeeper.iPeerLabelEntries[ array->At(0) ]->iPeerEntry;
            }
        else if( aType == KCertTypeDevice )
            {
            entry = iKeeper.iDeviceLabelEntries[ array->At(0) ]->iDeviceEntry;
            }
        else
            {
            entry = iKeeper.iUserLabelEntries[ array->At(0) ]->iUserEntry;
            }

        if (array->Count()==1)
            {
            queryOk = DeleteSingleItemQueryL( *entry );
            }
        else
            {
            HBufC* prompt = StringLoader::LoadLC(
                R_CONFIRMATION_QUERY_DELETE_CERT_PLURAL, array->Count() );
            queryOk = DisplayConfirmationLD( prompt );
            }
        if ( queryOk )
            {
            TInt readonlyCount = 0;
            TInt singleReadOnlyPosition = 0;
            TInt markedPosition = 0;
            TKeyArrayFix ownKey( 0, ECmpTInt );
            CONST_CAST(CArrayFix<int>*, array)->Sort( ownKey ); //lint !e665 expression macro param ok
            TInt markedCount = array->Count();
            CArrayFixFlat<TInt>* deletedIndexes = new (ELeave)CArrayFixFlat<TInt>( 4 );
            CleanupStack::PushL( deletedIndexes );

            iKeeper.StartWaitDialogL( ECertmanUiDeleteDialog );
            CleanupCloseWaitDialogPushL( iKeeper );

            for ( TInt i = markedCount; i > 0; i-- )
                {
                markedPosition = array->At( i-1 );
                // move focus up the list if marked items were
                // between focus and the beginning of the list
                if ( focusPosition > markedPosition )
                    {
                    focusPosition--;
                    }

                // Check whether certificate is deletable

                if( aType == KCertTypeAuthority )
                    {
                    entry = iKeeper.iCALabelEntries[ markedPosition ]->iCAEntry;
                    }
                else if( aType == KCertTypeTrustedSite )
                    {
                    entry = iKeeper.iPeerLabelEntries[ markedPosition ]->iPeerEntry;
                    }
                else if( aType == KCertTypeDevice )
                    {
                    entry = iKeeper.iDeviceLabelEntries[ markedPosition ]->iDeviceEntry;
                    }
                else
                    {
                    entry = iKeeper.iUserLabelEntries[ markedPosition ]->iUserEntry;
                    }

                if (IsCertificateDeletable(markedPosition, aType))
                    {
                    DeleteSingleItemL( *entry, markedPosition, aListBox, aType );
                    deletedIndexes->AppendL(markedPosition);
                    result = ETrue;
                    }
                else // Cannot be deleted
                    {
                    readonlyCount++;
                    singleReadOnlyPosition = markedPosition;
                    }
                }

            CleanupStack::PopAndDestroy();    // closes wait dialog

            if ( readonlyCount == 1 )
                {
                if( aType == KCertTypeAuthority  )
                    {
                    entry = iKeeper.iCALabelEntries[ singleReadOnlyPosition ]->iCAEntry;
                    }
                else if( aType == KCertTypeTrustedSite  )
                    {
                    entry = iKeeper.iPeerLabelEntries[ singleReadOnlyPosition ]->iPeerEntry;
                    }
                else if( aType == KCertTypeDevice )
                    {
                    entry = iKeeper.iDeviceLabelEntries[ singleReadOnlyPosition ]->iDeviceEntry;
                    }
                else
                    {
                    entry = iKeeper.iUserLabelEntries[ singleReadOnlyPosition ]->iUserEntry;
                    }

                ReadOnlySingleItemNoteL( *entry );
                }
            else if ( readonlyCount > 1 )
                {
                HBufC* string = StringLoader::LoadLC(
                    R_INFO_NOTE_TEXT_CERTIFICATE_READ_ONLY_MULTIPLE,
                    readonlyCount );
                DisplayNoteLD( string );
                }
            else
                { // For lint
                }

            aListBox->ClearSelection();
            AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(
                aListBox, focusPosition, *deletedIndexes);
            CleanupStack::PopAndDestroy(deletedIndexes);

            }
        }
    else
        {
        result = EFalse;
        }

    aListBox->DrawNow();//lint !e539

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::ConfirmationQueryDeleteCertL" );


    return result;
    }

// ---------------------------------------------------------
// CCertManUIViewAuthority::DeleteSingleItemQueryL(CCTCertInfo& aEntry)
// Gets the certificate name (or No label/No subject) for the Confirmation note
// ---------------------------------------------------------
//
TInt CCertManUICertificateHelper::DeleteSingleItemQueryL( CCTCertInfo& aEntry )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DeleteSingleItemQueryL" );

    TInt selection = 0;

    HBufC* buf = HBufC::NewLC( KMaxLengthTextCertLabel );
    buf->Des() = aEntry.Label();
    buf->Des().TrimLeft();
    // Cut CertLabel after fourth semi colon
    TPtrC trimmedCertLabel = CutCertificateField( buf->Des() );
    buf->Des().Copy(trimmedCertLabel);
    TInt length = buf->Des().Length();
    if ( length == 0 )
        {
        // here the resource name is _NO_LABEL, but it returns only "Delete certificate?"
        // not any "No label" or "No subject" string
        HBufC* prompt = StringLoader::LoadLC(
            R_CONFIRMATION_QUERY_DELETE_CERT_NO_LABEL );
        selection = DisplayConfirmationLD( prompt );
        }
    else
        {
        HBufC* prompt = StringLoader::LoadLC(
            R_CONFIRMATION_QUERY_DELETE_CERT, buf->Des() );
        selection = DisplayConfirmationLD(prompt);
        }
    CleanupStack::PopAndDestroy();  // buf

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::DeleteSingleItemQueryL" );

    return selection;
    }


// ---------------------------------------------------------
// CCertManUICertificateHelper::DeleteSingleItemL(CCrCertEntry& aEntry, TInt aPosition, TInt aType)
// Deletes one item from CertManAPI and from listbox
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DeleteSingleItemL( CCTCertInfo& aEntry,
    TInt aPosition,
    CEikColumnListBox* aListBox,
    TInt aType )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::DeleteSingleItemL" );

    TInt status( KErrNone );

    if ( aType == KCertTypeTrustedSite )
        {
        status = iKeeper.iWrapper->DeleteCertL(
                                              iKeeper.CertManager(),
                                              aEntry,
                                              KCMTrustedServerTokenUid
                                              );
        }
    else if( aType == KCertTypeDevice )
        {
        status = iKeeper.iWrapper->DeleteCertL(
                                              iKeeper.CertManager(),
                                              aEntry,
                                              KCMDeviceCertStoreTokenUid
                                              );
        }
    else
        {
        status = iKeeper.iWrapper->DeleteCertL( iKeeper.CertManager(), aEntry );
        }

    // Update the list after delete. In case of a error, a note show inside DeleteCertL.
    if ( status == KErrNone )
        {
        MDesCArray *itemList = aListBox->Model()->ItemTextArray();
        CDesCArray* itemArray = STATIC_CAST( CDesCArray*, itemList );
        itemArray->Delete( aPosition );
        }

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::DeleteSingleItemL" ); //lint !e539
    }


// ---------------------------------------------------------
// CCertManUICertificateHelper::MoveKeyL(const TCTKeyAttributeFilter& aFilter,
//                       TUid aSourceStore, TUid aSourceStore )
// Moves a key from one store to another
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::MoveKeyL(
    const TCTKeyAttributeFilter& aFilter,
    const TUid aSourceStore,
    const TUid aTargetStore )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::MoveCertL" );

    iKeeper.iWrapper->MoveKeyL( iKeeper.KeyManager(), aFilter, aSourceStore, aTargetStore );

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::MoveCertL" );
    }


// ---------------------------------------------------------
// CCertManUICertificateHelper::MoveCertL(CCrCertEntry& aEntry,
//                        TInt aPosition, CEikColumnListBox* aListBox,
//                        TUid aSourceStore, TUid aSourceStore )
// Moves a certificate from one store to another
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::MoveCertL( CCTCertInfo& aEntry,
    TInt aPosition,
    CEikColumnListBox* aListBox,
    const TUid aSourceStore,
    const TUid aTargetStore )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::MoveCertL" );

    TInt certCount(0);

    TRAPD( err, certCount = iKeeper.iWrapper->MoveCertL( iKeeper.CertManager(), aEntry, aSourceStore, aTargetStore ));

    // Update the list after moving the certificate
    if ( err == KErrNone )
        {
        MDesCArray *itemList = aListBox->Model()->ItemTextArray();
        CDesCArray* itemArray = STATIC_CAST( CDesCArray*, itemList );
        if ( certCount == 1  )
            {
            // Delete single item
            itemArray->Delete( aPosition );
            AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(
                          aListBox, aPosition, ETrue );
            }
         else
            {
            // More than one certificate moved. Empty listbox items.
            // It will be updated later
            itemArray->Reset();
            }
        }
    else
        {
        User::Leave( err );
        }

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::MoveCertL" );
    }


// ---------------------------------------------------------
// CCertManUICertificateHelper::ReadOnlySingleItemNoteL(CCTCertInfo& aEntry)
// Gets the certificate name (or No label/No subject) for the read-only note
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::ReadOnlySingleItemNoteL(CCTCertInfo& aEntry )
    {
    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::ReadOnlySingleItemNoteL" );

    HBufC* buf = HBufC::NewLC( KMaxLengthTextCertLabel );
    buf->Des() = aEntry.Label();
    buf->Des().TrimLeft();
    // Cut CertLabel after fourth semi colon
    TPtrC trimmedCertLabel = CutCertificateField( buf->Des() );
    buf->Des().Copy(trimmedCertLabel);
    TInt length = buf->Des().Length();
    if ( length == 0 )
        {
        // here the resource name is _NO_LABEL, but it returns only "Cannot delete certificate"
        // not any "No label" or "No subject" string
        HBufC* stringHolder = StringLoader::LoadLC(
                                R_INFO_NOTE_TEXT_CERTIFICATE_READ_ONLY_NO_LABEL );
        DisplayNoteLD( stringHolder );
        }
    else
        {
        HBufC* stringHolder = StringLoader::LoadLC(
                                R_INFO_NOTE_TEXT_CERTIFICATE_READ_ONLY, buf->Des() );
        DisplayNoteLD( stringHolder );
        }
    CleanupStack::PopAndDestroy();  // buf


    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::ReadOnlySingleItemNoteL" );
    }
// ---------------------------------------------------------
// CCertManUICertificateHelper::DisplayConfirmationLD(HBufC* aString)
// Displays Delete yes/no confirmation notes
// ---------------------------------------------------------
//
TInt CCertManUICertificateHelper::DisplayConfirmationLD( HBufC* aString )
    {
    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::DisplayConfirmationLD" );

    CAknQueryDialog* dlg = CAknQueryDialog::NewL( CAknQueryDialog::ENoTone );
    TInt selection = dlg->ExecuteLD( R_CERTMANUI_CONFIRMATION_QUERY_YES_NO, *aString );
    // Takes ownership and destroys aString
    CleanupStack::PopAndDestroy();  // aString

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::DisplayConfirmationLD" );

    return selection;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::DisplayNoteLD(HBufC* aString)
// Displays read-only information notes
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::DisplayNoteLD(HBufC* aString)
    {
    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::DisplayNoteLD" );

    CAknInformationNote* note = new ( ELeave ) CAknInformationNote( ETrue );
    note->ExecuteLD( *aString );
    CleanupStack::PopAndDestroy();  // aString

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::DisplayNoteLD" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::FFSSpaceBelowCriticalLevelL
// Handle deleting when disk is getting full
// ---------------------------------------------------------
//
TBool CCertManUICertificateHelper::FFSSpaceBelowCriticalLevelL(
    TBool aShowErrorNote, TInt aBytesToWrite )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::FFSSpaceBelowCriticalLevelL" );

    TBool ret = EFalse;
    if ( SysUtil::FFSSpaceBelowCriticalLevelL(
        &(CCoeEnv::Static()->FsSession()), aBytesToWrite ) )
        {
        ret = ETrue;
        if ( aShowErrorNote )
            {
            CErrorUI* errorUi = CErrorUI::NewLC( *(CCoeEnv::Static()) );
            errorUi->ShowGlobalErrorNoteL( KErrDiskFull );
            CleanupStack::PopAndDestroy();  // errorUi
            }
        }

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::FFSSpaceBelowCriticalLevelL" );

    return ret;
    }
// ---------------------------------------------------------
// CCertManUICertificateHelper::HandleMarkableListCommandL( TInt aCommand )
// Handles marking and unmarking of the list.
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::HandleMarkableListCommandL( TInt aCommand,
                                                    CEikColumnListBox* aListBox )
    {
    CERTMANUILOGGER_ENTERFN(
        "CCertManUICertificateHelper::HandleMarkableListCommandL" );

    TInt index;
    switch ( aCommand )
        {
        case ECertManUICmdMark:
            {
            index = aListBox->CurrentItemIndex();
            if ( index >= 0 )
                {
                // This is done to make sure listbox updates its state
                // to make shift+arrow work correctly after shift+ok
                aListBox->View()->UpdateSelectionL( CListBoxView::EDisjointSelection );
                aListBox->View()->SelectItemL( index );
                }
            break;
            }
        case ECertManUICmdUnmark:
            {
            index = aListBox->CurrentItemIndex();
            if ( index >= 0 )
                {
                // This is done to make sure listbox updates its state
                // to make shift+arrow work correctly after shift+ok
                aListBox->View()->UpdateSelectionL(
                      CListBoxView::EDisjointSelection );
                aListBox->View()->DeselectItem( index );
                }
            break;
            }
        case ECertManUICmdMarkAll:
            {
            aListBox->ClearSelection();
            TInt count = aListBox->Model()->NumberOfItems();
            if ( count )
                {
                CArrayFixFlat<TInt>* selection =
                    new( ELeave ) CArrayFixFlat<TInt>( 1 );
                CleanupStack::PushL( selection );
                selection->SetReserveL( count );
                for( TInt i = 0; i < count; i++ )
                    {
                    selection->AppendL( i );
                    }
                aListBox->SetSelectionIndexesL( selection );
                CleanupStack::PopAndDestroy();  // selection
                }
            break;
            }
        case ECertManUICmdUnmarkAll:
            {
            aListBox->ClearSelection();
            break;
            }
        default:
      break;
      }

    CERTMANUILOGGER_LEAVEFN(
        "CCertManUICertificateHelper::HandleMarkableListCommandL" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::GetKeyUsageAndLocationL( CCTCertInfo* aCertEntry,
//                                                      TUid* aKeyLocation)
// Returns key usage and location.
// ---------------------------------------------------------
//
TKeyUsagePKCS15 CCertManUICertificateHelper::GetKeyUsageAndLocationL( CCTCertInfo* aCertEntry,
                                                                     TUid* aKeyLocation )
    {
    TKeyUsagePKCS15 keyUsage;

    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::GetKeyUsageAndLocationL" );

    // Check whether we have key for this certificate
    RMPointerArray<CCTKeyInfo> keyEntry;
    TCTKeyAttributeFilter filter;
    filter.iKeyId = aCertEntry->SubjectKeyId();

    iKeeper.iWrapper->ListL( iKeeper.KeyManager(), &keyEntry, filter );

    if (keyEntry.Count())
        {
        keyUsage = keyEntry[0]->Usage();
        // Get Location
        aKeyLocation->iUid = keyEntry[0]->Token().TokenType().Type().iUid ;
        }
    else
        {
        keyUsage = EPKCS15UsageNone;
        }

    keyEntry.Close();
    LOG_WRITE_FORMAT( "Key usage : %X", keyUsage );
    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::GetKeyUsageAndLocationL" );
    return keyUsage;
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::SetLocationInfoL( (HBufC& aMessage,
//                                               TBool aCertificate,
//                                               TUid* aLocUid)
// Adds certificate/private key's location info to certificate details
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::SetLocationInfoL(
    HBufC& aMessage,
    TBool aCertificate,
    TUid* aLocUid)
    {
    TInt location = 0;
    TInt locationRes = 0;

    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::SetLocationInfo" );

    switch ( aLocUid->iUid )
        {
        case KFileCertStoreUid:
        case KTrustedServerCertStoreUid:
        case KDeviceCertStoreUid:
        case KDeviceKeyStoreUid:
        case KTokenTypeFileKeystore:
            location = R_TEXT_RESOURCE_DETAILS_VIEW_LOCATION_PHONE_MEMORY;
            break;

        case KWIMCertStoreUid:
            location = R_TEXT_RESOURCE_DETAILS_VIEW_LOCATION_SMART_CARD;
            break;

        default:
            if ( aCertificate )
                {
                location = R_TEXT_RESOURCE_DETAILS_VIEW_NOT_DEFINED;
                }
            else
                {
                location = R_TEXT_RESOURCE_DETAILS_VIEW_NO_PRIVATE_KEY;
                }
            break;
        }

    if ( aCertificate )
        {
        locationRes = R_TEXT_RESOURCE_DETAILS_VIEW_CERTIFICATE_LOCATION;
        }
    else
        {
        locationRes = R_TEXT_RESOURCE_DETAILS_VIEW_PRIVATE_KEY_LOCATION;
        }

    DetailsFieldResourceL( aMessage, locationRes, location );

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::SetLocationInfo" );
    }

// ---------------------------------------------------------
// CCertManUICertificateHelper::CreateMessageBodyTextL()
// ---------------------------------------------------------
//
void CCertManUICertificateHelper::CreateMessageBodyTextL( TInt aIndex, TInt aType,
        CEikonEnv* aEikonEnv, HBufC& aMessage )
    {
    CERTMANUILOGGER_ENTERFN( "CCertManUICertificateHelper::CreateMessageBodyTextL" );

    // Use certificate index from previous view
    HBufC8* urlBuf = NULL;
    CCTCertInfo* entry = NULL;
    CCertificate* details = NULL;
    CUnifiedCertStore*& store = iKeeper.CertManager();

    if( aType == KCertTypeAuthority )
        {
        entry = ( iKeeper.iCALabelEntries )[ aIndex ]->iCAEntry;
        }
    else if( aType == KCertTypeTrustedSite )
        {
        entry = ( iKeeper.iPeerLabelEntries )[ aIndex ]->iPeerEntry;
        }
    else if( aType == KCertTypeDevice )
        {
        entry = ( iKeeper.iDeviceLabelEntries )[ aIndex ]->iDeviceEntry;
        }
    else
        {
        entry = ( iKeeper.iUserLabelEntries )[ aIndex ]->iUserEntry;
        }

    TCertificateFormat certiticateFormat = entry->CertificateFormat();

    if( certiticateFormat != EX509CertificateUrl )
        {
        TInt err = iKeeper.iWrapper->GetCertificateL( store, *entry, details );
        CleanupStack::PushL( details );
        User::LeaveIfError( err );

        ValidateCertificateL( aIndex, details, *entry, aType );
        }
    else
        {
        urlBuf = HBufC8::NewLC( entry->Size() );
        TPtr8 urlPtr = urlBuf->Des();
        TInt err = iKeeper.iWrapper->GetUrlCertificateL( store, *entry, urlPtr );
        User::LeaveIfError( err );
        }

    if( aType == KCertTypeTrustedSite )
        {
        CTrustSitesStore* trustedSitesStore = CTrustSitesStore::NewL();
        CleanupStack::PushL( trustedSitesStore );

        RPointerArray<HBufC> trustedSites;
        CleanupResetAndDestroyPushL( trustedSites );
        trustedSitesStore->GetTrustedSitesL( details->Encoding(), trustedSites );

        if( trustedSites.Count() > 0 )
            {
            if( trustedSites.Count() == 1 )
                {
                DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_SITE );
                }
            else
                {
                DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_SITES );
                }

            for( TInt i = 0; i < trustedSites.Count(); i++ )
                {
                aMessage.Des().Append( *trustedSites[ i ] );
                aMessage.Des().Append( KCertManUIDetailsViewEnter );
                }
            aMessage.Des().Append( KCertManUIDetailsViewEnter );
            }

        CleanupStack::PopAndDestroy( &trustedSites );
        CleanupStack::PopAndDestroy( trustedSitesStore );
        }
    else
        {
        DetailsFieldDynamicL( aMessage, entry->Label(),
                R_TEXT_RESOURCE_DETAILS_VIEW_LABEL,
                R_TEXT_RESOURCE_VIEW_NO_LABEL_DETAILS );
        }

    // certificate issuer and owner
    if( certiticateFormat == EX509Certificate )
        {
        HBufC* owner = NULL;
        X509CertNameParser::SubjectFullNameL( *(CX509Certificate*)details, owner );
        CleanupStack::PushL( owner );

        HBufC* issuer = NULL;
        X509CertNameParser::IssuerFullNameL( *(CX509Certificate*)details, issuer );
        CleanupStack::PushL( issuer );

        DetailsFieldDynamicL( aMessage, issuer->Des(),
            R_TEXT_RESOURCE_DETAILS_VIEW_ISSUER,
            R_TEXT_RESOURCE_DETAILS_VIEW_NOT_DEFINED );
        CleanupStack::PopAndDestroy( issuer );

        // certificate subject
        DetailsFieldDynamicL( aMessage, owner->Des(),
            R_TEXT_RESOURCE_DETAILS_VIEW_SUBJECT,
            R_TEXT_RESOURCE_VIEW_NO_SUBJECT_DETAILS );
        CleanupStack::PopAndDestroy( owner );
        }

    // Get key usage and location. This is done only client certificates.
    const TInt KLocationUnknown = 0;
    TUid keyLocation = { KLocationUnknown };

    if(( aType == KCertTypePersonal ) || ( aType == KCertTypeDevice ))
        {
        TInt usage;
        switch( GetKeyUsageAndLocationL( entry, &keyLocation ) )
            {
            case EPKCS15UsageSignSignRecover:
            case EPKCS15UsageSignDecrypt:
            case EPKCS15UsageSign:
                usage = R_TEXT_RESOURCE_DETAILS_VIEW_CLIENT_AUTHENTICATION;
                break;
            case EPKCS15UsageNonRepudiation:
                usage = R_TEXT_RESOURCE_DETAILS_VIEW_DIGITAL_SIGNING;
                break;
            default:
                usage = R_TEXT_RESOURCE_DETAILS_VIEW_NOT_DEFINED;
                break;
            }
        DetailsFieldResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_KEY_USAGE, usage );
        }

    if( certiticateFormat == EX509Certificate )
        {
        // Certificate validity period
        // Hometime's offset to UTC
        TLocale locale;
        TTimeIntervalSeconds offSet = locale.UniversalTimeOffset();

        DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_VALID_FROM );
        const CValidityPeriod& validityPeriod = details->ValidityPeriod();
        TTime startValue = validityPeriod.Start();
        startValue += offSet;

        HBufC* dateFormatString = aEikonEnv->AllocReadResourceLC( R_QTN_DATE_USUAL_WITH_ZERO );

        TBuf<KMaxLengthTextDateString> startString;
        startValue.FormatL( startString, *dateFormatString );
        AknTextUtils::DisplayTextLanguageSpecificNumberConversion( startString );
        aMessage.Des().Append( startString );
        aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );

        DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_VALID_UNTIL );
        TTime finishValue = validityPeriod.Finish();
        finishValue += offSet;
        TBuf<KMaxLengthTextDateString> finishString;

        finishValue.FormatL( finishString, *dateFormatString );
        AknTextUtils::DisplayTextLanguageSpecificNumberConversion( finishString );
        aMessage.Des().Append( finishString );
        aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );

        CleanupStack::PopAndDestroy( dateFormatString );

        TUid certLoc;
        certLoc.iUid = entry->Token().TokenType().Type().iUid;
        SetLocationInfoL( aMessage, ETrue, &certLoc );
        }
    else if( certiticateFormat == EX509CertificateUrl )
        {
        HBufC* urlBuf16 = HBufC::NewLC( urlBuf->Length() );
        TPtr urlPtr = urlBuf16->Des();
        urlPtr.Copy(*urlBuf);
        DetailsFieldDynamicL( aMessage, urlBuf16->Des(),
                R_TEXT_RESOURCE_DETAILS_VIEW_CERTIFICATE_LOCATION,
                R_TEXT_RESOURCE_DETAILS_VIEW_NOT_DEFINED );
        CleanupStack::PopAndDestroy( urlBuf16 );
        }
    else
        {
        // nothing
        }

    // certificate format
    TInt fieldType = 0;
    TInt fieldType2 = 0;
    switch( certiticateFormat )
        {
        case EX509Certificate:
        case EX509CertificateUrl:
            {
            fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_CERT_FORMAT_X509;
            break;
            }
         default:
            {
            fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_NOT_DEFINED;
            break;
            }
        }
    DetailsFieldResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_CERT_FORMAT, fieldType );

    // Private key location, only for user and device certicates
    if(( aType == KCertTypePersonal ) || ( aType == KCertTypeDevice ))
        {
        SetLocationInfoL( aMessage, EFalse, &keyLocation );
        }

    if( certiticateFormat == EX509Certificate )
        {
        __UHEAP_MARK;

        // certificate algorithms

        // digest algorithm
        TAlgorithmId algorithmId = details->SigningAlgorithm().DigestAlgorithm().Algorithm();
        switch( algorithmId )
            {
            case EMD2:
                {
                fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_MD2;
                break;
                }
            case EMD5:
                {
                fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_MD5;
                break;
                }
            case ESHA1:
                {
                fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_SHA1;
                break;
                }
            default:
                {
                fieldType = R_TEXT_RESOURCE_DETAILS_VIEW_UNKNOWN;
                break;
                }
            }

        // public-key algorithm
        algorithmId = details->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
        switch( algorithmId )
            {
            case ERSA:
                {
                fieldType2 = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_RSA;
                break;
                }
            case EDSA:
                {
                fieldType2 = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_DSA;
                break;
                }
            case EDH:
                {
                fieldType2 = R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM_DH;
                break;
                }
            default:
                {
                fieldType2 = R_TEXT_RESOURCE_DETAILS_VIEW_UNKNOWN;
                }
            }

        // If other algorithm is unknown
        if( fieldType == R_TEXT_RESOURCE_DETAILS_VIEW_UNKNOWN ||
                fieldType2 == R_TEXT_RESOURCE_DETAILS_VIEW_UNKNOWN )
            {
            DetailsFieldResourceL( aMessage,
                    R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM,
                    R_TEXT_RESOURCE_DETAILS_VIEW_UNKNOWN );
            }
        else // Both are known.
            {
            DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_ALGORITHM );
            HBufC* stringHolder = StringLoader::LoadLC( fieldType );
            aMessage.Des().Append( stringHolder->Des() );
            CleanupStack::PopAndDestroy( stringHolder );
            stringHolder = StringLoader::LoadLC( fieldType2 );
            aMessage.Des().Append( stringHolder->Des() );
            CleanupStack::PopAndDestroy( stringHolder );
            aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );
            }

        // certificate serial number
        DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_SERIAL_NUMBER );
        TPtrC8 serialNumber = details->SerialNumber();
        TBuf<KMaxLengthTextSerialNumberFormatting> buf2;

        for( TInt i = 0; i < serialNumber.Length(); i++ )
           {
           buf2.Format( KCertManUIDetailsViewHexaFormat, serialNumber[i] );
           aMessage.Des().Append( buf2 );
           }

        aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );

        // certificate fingerprint SHA-1
        DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_FINGERPRINT );
        TPtrC8 sha1_fingerprint = details->Fingerprint();
        DevideToBlocks( sha1_fingerprint, aMessage.Des() );
        aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );

        // certificate fingerprint MD5
        DetailsResourceL( aMessage, R_TEXT_RESOURCE_DETAILS_VIEW_FINGERPRINT_MD5 );

        CMD5* md5 = CMD5::NewL();
        CleanupStack::PushL( md5 );
        TBuf8<20> fingerprint = md5->Hash( details->Encoding() );
        CleanupStack::PopAndDestroy( md5 );

        DevideToBlocks( fingerprint, aMessage.Des() );
        aMessage.Des().Append( KCertManUIDetailsViewEnterEnter );

        // Public key
        // qtn_cm_public_key looks like this "Public key (%0U %1N bit):"
        // so DetailsResource cannot be used to get it.

        // We already know the public key algorithm, it has been put into fieldType2 above.
        HBufC* pubkeyHolder = StringLoader::LoadLC( fieldType2 );  // %0U

        CDesCArrayFlat* strArray = new (ELeave) CDesCArrayFlat( 1 );
        CleanupStack::PushL( strArray );

        strArray->InsertL( 0, *pubkeyHolder );

        // Get public key already here to get length of it for string loader.
        const CSubjectPublicKeyInfo& publicKey = details->PublicKey();
        TPtrC8 keyData = publicKey.KeyData();
        TInt size = keyData.Size();  // %1N

        // To get key size decode DER encoded key got from the certificate.
        TX509KeyFactory key;

        // There doesn't seem to be definition of MAX_INT anywhere so calculate it.
        TReal maxInt;
        TReal intBits = sizeof( TInt ) * 8;
        Math::Pow( maxInt, 2, intBits );
        maxInt = ( maxInt / 2 ) - 1;

        switch( algorithmId )
            {
            case ERSA:
                {
                const CRSAPublicKey* keyRSA = key.RSAPublicKeyL( keyData );

                const TInteger& n = keyRSA->N();

                TUint keySizeN = n.BitCount();

                // Play it safe.
                if( keySizeN < maxInt )
                    {
                    size = keySizeN;
                    }

                delete keyRSA;

                break;
                }
            case EDSA:
                {
                TPtrC8 params = publicKey.EncodedParams();
                const CDSAPublicKey* keyDSA = key.DSAPublicKeyL( params, keyData );

                const TInteger& y = keyDSA->Y();

                TUint keySizeY = y.BitCount();

                // Play it safe.
                if( keySizeY < maxInt )
                    {
                    size = keySizeY;
                    }

                delete keyDSA;

                break;
                }
            // There doesn't seem to be TX509KeyFactory function for DH keys.
            // If the key is DH or unknown, just multiply length of the key
            // in bytes with 8. It is not correct but at least gives an idea.
            // Without setting something to size 'unknown' text should be used
            // below for the string which is much more error prone than setting
            // at least something.
            case EDH:
            default:
                {
                size = 8 * keyData.Size();
                }
            }

        CArrayFixFlat<TInt>* intArr = new (ELeave) CArrayFixFlat<TInt>( 1 );
        CleanupStack::PushL( intArr );
        intArr->AppendL( size );

        // Load string and set algorithm and key length strings.
        HBufC* stringHolder = StringLoader::LoadLC( R_TEXT_RESOURCE_DETAILS_VIEW_PUBLIC_KEY,
                *strArray, *intArr );
        aMessage.Des().Append( stringHolder->Des() );
        aMessage.Des().Append( KCertManUIDetailsViewEnter );

        // Finally append the public key.
        DevideToBlocks( keyData, aMessage.Des() );

        const TInt KItemsInCleanupStack = 4; // stringHolder, intArr, strArray, pubkeyHolder
        CleanupStack::PopAndDestroy( KItemsInCleanupStack, pubkeyHolder );

        __UHEAP_MARKEND;
        }
    else
        {
        // SetUrlCertAlgorihm()
        }

    if( certiticateFormat != EX509CertificateUrl )
        {
        CleanupStack::PopAndDestroy( details );
        }
    else
        {
        CleanupStack::PopAndDestroy( urlBuf );
        }

    aMessage.Des().Append( KCertManUIDetailsViewEnter );

    CERTMANUILOGGER_LEAVEFN( "CCertManUICertificateHelper::CreateMessageBodyTextL" );
    }


// End of file