wvuing/Utils/CAUtils.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/Utils/CAUtils.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,903 @@
+/*
+* Copyright (c) 2004-2006 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:  Utils for IM modules.
+*
+*/
+
+
+#include "CAUtils.h"
+#include "CCAStorageManagerFactory.h"
+#include "MCAStoredContacts.h"
+#include "ChatDebugPrint.h"
+#include "impsbuilddefinitions.h"
+
+#include <EscapeUtils.h>
+#include <collate.h>
+
+// needed to skip prefixes in domain-neutral comparison (TUint version)
+const TUint KColonUInt( ':' );
+
+// needed to skip domains in domain-neutral comparison (TUint version)
+const TUint KAtUInt( '@' );
+// general colon needed in various places
+_LIT( KColon, ":" );
+
+// general slash needed in various places
+_LIT( KSlash, "/" );
+
+// needed to skip domains in domain-neutral comparison
+_LIT( KAt, "@" );
+
+// "test character identity and accents, ignore case"
+const TInt KCollationLevel = 1;
+
+// max number to store any values
+const TInt KMAX_NUMBER = 12;
+
+// max number to fit
+const TInt KMAX_LIMIT = 255;
+
+// max number base
+const TInt KMAX_NUMBERBASE = 10;
+
+// some character value constants
+//const TUint K7LSBMask       = 0x7f     // bitmask for 7 lsb bits
+const TUint K8BitMask       = 0xff;     // full bitmask
+//const TUint KCharCodeZero   = 0x30     // '0'
+//const TUint KCharCodeSmallZ = 0x7a     // 'z'
+//const TUint KCharCodeSpace  = 0x20     // ' '
+const TUint KCharToArea     = 0x030;
+
+// Unused areas (2) in ISO 8859-1 specification
+//const TUint KUnused8859start1 = 0x00
+const TUint KUnused8859end1 = 0x1F;
+const TUint KUnused8859start2 = 0x7F;
+const TUint KUnused8859end2 = 0x9F;
+
+// forbidden characters that cannot appear in Wireless Village Ids
+_LIT( KWVForbiddenCharacters, "/@+ \t:" );
+
+/**
+ * Constants to use in validation.
+ *
+ */
+_LIT( KCUImpsId_WhiteSpace, " " );
+_LIT( KCUImpsId_At, "@" );
+_LIT( KCUImpsId_Dot, "." );
+_LIT( KCUImpsId_TwoDots, ".." );
+_LIT( KCUImpsId_Slash, "/" );
+_LIT( KCUImpsId_Plus, "+" );
+_LIT( KCUImpsId_Tabulator, "\t" );
+_LIT( KCUImpsId_WVPrefix, "wv:" );
+
+_LIT( KCUImpsId_AtEnc, "%40" );
+_LIT( KCUImpsId_SlashEnc, "%2F" );
+_LIT( KCUImpsId_PlusEnc, "%2B" );
+_LIT( KCUImpsId_TabulatorEnc, "%09" );
+_LIT( KCUImpsId_WhiteSpaceEnc, "%20" );
+
+// length of "wv:" prefix
+const TInt KCUImpsId_WVPrefixLength = 3;
+
+// maximum length of user id
+const TInt KServerWVUserIdMaxLength = 50;
+
+// defines how far we are going to search for the protocol part in user id
+const TInt KMaxLengthSearchProtPart = 4;
+
+// maximum numerical value to append to generated WVID.
+const TInt KMaxAppendNumber = 9999;
+
+// -----------------------------------------------------------------------------
+// CAUtils::NeutralCompare
+// -----------------------------------------------------------------------------
+//
+TInt CAUtils::NeutralCompare( const TDesC& aId1,
+                              const TDesC& aId2, TBool aDomainNeutral )
+    {
+    // points to user part of id
+    TPtrC ptrId1( aId1 );
+    TPtrC ptrId2( aId2 );
+
+    // Reduce looking for protocol part only to beginning of the WVID and
+    // skip protocol part ("anything:") in the beginning of the WVID
+    TInt colonPos1 = aId1.Left( KMaxLengthSearchProtPart ).Locate( KColonUInt );
+
+    // first id
+    if ( ( KErrNotFound != colonPos1 ) && ( aId1.Length() - 1 != colonPos1 ) )
+        {
+        // contains ":", and it is not the last char
+        ptrId1.Set( aId1.Mid( colonPos1 + 1 ) );
+        }
+
+    TInt colonPos2 = aId2.Left( KMaxLengthSearchProtPart ).Locate( KColonUInt );
+
+    // second id
+    if ( ( KErrNotFound != colonPos2 ) && ( aId2.Length() - 1 != colonPos2 ) )
+        {
+        // contains ":", and it is not the last char
+        ptrId2.Set( aId2.Mid( colonPos2 + 1 ) );
+        }
+
+    // find out if we have domains in the ids
+    TInt domainPos1( ptrId1.Locate( KAtUInt ) );
+    TInt domainPos2( ptrId2.Locate( KAtUInt ) );
+
+    TBool domainIn1( KErrNotFound != domainPos1 );
+    TBool domainIn2( KErrNotFound != domainPos2 );
+
+    // points to domains in the neutral id
+    TPtrC ptrDom1( KNullDesC );
+    TPtrC ptrDom2( KNullDesC );
+
+    // points to user parts in the neutral id
+    TPtrC ptrUid1( ptrId1 );
+    TPtrC ptrUid2( ptrId2 );
+
+    // separate user id parts and domain parts
+    if ( domainIn1 )
+        {
+        ptrDom1.Set( ptrId1.Mid( domainPos1 + 1 ) );
+        ptrUid1.Set( ptrId1.Mid( 0, domainPos1 ) );
+        }
+
+    if ( domainIn2 )
+        {
+        ptrDom2.Set( ptrId2.Mid( domainPos2 + 1 ) );
+        ptrUid2.Set( ptrId2.Mid( 0, domainPos2 ) );
+        }
+
+    // Create custom collation method to ignore punctuations
+    // index 0 gets the default method
+    TCollationMethod collation =
+        *Mem::CollationMethodByIndex( 0 );
+    collation.iFlags |= TCollationMethod::EIgnoreNone;
+
+    // domains are compared only when it is really needed
+    // check if userid part is the same in both ids
+    TInt idResult = ptrUid1.CompareC( ptrUid2, KCollationLevel, &collation );
+
+    if ( idResult != 0 )
+        {
+        return idResult;
+        }
+
+    // id part is same, we have to compare domain
+
+    // If domain comparison is neutral and one id is without domain
+    // -> Domains are same. Other situation domainResult stays valid.
+    if ( aDomainNeutral && ( domainIn1 ^ domainIn2 ) )
+        {
+        return 0;
+        }
+    else
+        {
+        return ptrDom1.CompareC( ptrDom2, KCollationLevel, &collation );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::DisplayId
+// -----------------------------------------------------------------------------
+//
+TPtrC CAUtils::DisplayId( const TDesC& aId, TBool aListHiding )
+    {
+    TPtrC ret( aId );
+
+    MCAStoredContacts* contacts = NULL;
+    TRAPD( err, contacts = CCAStorageManagerFactory::ContactListInterfaceL() );
+    if ( err != KErrNone || !contacts )
+        {
+        // some error, don't modify
+        CHAT_DP_FUNC_DP( "DisplayId", "Got some error, not hiding" );
+        return ret;
+        }
+
+    // if we've branded the feature out, don't modify anything
+    // UI CR : 101-39728:  Check for prefix hiding or Wv hiding.
+    if ( contacts->WVHiding() || contacts->WVHidingPrefixOnly() )
+        {
+        // locate ":" for userid, groupid.
+        // locate "/" for list id.
+        TInt pos = aId.FindC( aListHiding ? KSlash : KColon );
+
+        if ( ( pos != KErrNotFound ) && ( pos != aId.Length() - 1 ) )
+            {
+            // contains the special character, and it is not the last char
+            // remove everything before the special char (including the char)
+            ret.Set( aId.Mid( pos + 1 ) );
+            }
+        if ( contacts->WVHiding() || aListHiding )
+            {
+            // remove also the domain part
+            TInt domainPos = ret.FindC( KAt );
+            if ( ( domainPos != KErrNotFound ) && ( domainPos != 0 ) )
+                {
+                ret.Set( ret.Mid( 0, domainPos ) );
+                }
+
+            }
+        }
+
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// CAUtils::GenerateIdLC
+// -----------------------------------------------------------------------------
+//
+HBufC* CAUtils::GenerateIdLC( const TDesC& aId, TInt aNum )
+    {
+    // copy ID
+    HBufC* result = HBufC::NewLC( KServerWVUserIdMaxLength );
+    TPtr resultPtr( result->Des() );
+    resultPtr.Copy( aId );
+
+    TInt len( resultPtr.Length() );
+
+    // Start from end of data
+    for ( TInt i( len - 1 ); i >= 0; --i )
+        {
+        // Do quick and dirty UNICODE to ISO-8859-1 conversion
+        // and modify all non-ISO-8859-1 characters
+        // to be in valid ranges
+        const TInt& currentChar = resultPtr[ i ];
+        TUint ch = currentChar & K8BitMask;
+
+        // is ch in first unused area
+        if ( ch <= KUnused8859end1 )
+            {
+            ch += KUnused8859end1 + 1;
+            }
+
+        // is ch in second unused area
+        if ( ch >= KUnused8859start2 && ch <= KUnused8859end2 )
+            {
+            TInt difference = ch - KUnused8859start2;
+            ch = KUnused8859end2 + difference + 1;
+            }
+
+        TChar isoFixedChar = TChar( ch );
+        // put it into the string
+        HBufC* isoFixed = HBufC::NewLC( 1 );
+        isoFixed->Des().Append( isoFixedChar );
+
+        resultPtr.Replace( i, 1, *isoFixed );
+        CleanupStack::PopAndDestroy( isoFixed );
+
+        // now all the specials get removed
+        TPtrC c = resultPtr.Mid( i, 1 );  // next character
+        TInt position = KWVForbiddenCharacters().FindF( c );
+
+        if ( position != KErrNotFound )
+            {
+            // the current character is a FORBIDDEN CHARACTER,
+            // remove it
+            resultPtr.Delete( i, 1 );
+            }
+        }
+
+    CHAT_DP( D_CHAT_LIT( "CAUtils::GenerateIdLC conversion '%S' -> '%S'" ), &aId, &resultPtr );
+
+    // "Append" number
+    if ( aNum > 0 && aNum <= KMaxAppendNumber )
+        {
+        TBuf<KMAX_NUMBER> number; // 12, enough space to store a very large number
+        number.AppendNum( aNum );
+
+        TInt numLength = number.Length();
+        TInt resultLength = resultPtr.Length();
+        if ( numLength + resultLength > KServerWVUserIdMaxLength )
+            {
+            // can't append directly because we would exceed the space.
+            // use replace instead
+            TInt usableSpace = KServerWVUserIdMaxLength - resultLength;
+            TInt startPos = resultLength - numLength + usableSpace;
+            TInt replaceAmount = numLength - usableSpace;
+
+            resultPtr.Replace( startPos, replaceAmount, number );
+            }
+        else
+            {
+            // enough space in the end, just append
+            resultPtr.AppendNum( aNum );
+            }
+        }
+
+    CHAT_DP( D_CHAT_LIT( "CAUtils::GenerateIdLC returning '%S'" ), &resultPtr );
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+//  CAUtils::ExternalizeBufferToStreamL
+//  Helper method for externalize the buffer
+// -----------------------------------------------------------------------------
+//
+void CAUtils::ExternalizeBufferToStreamL( const TDesC& aBuffer, RWriteStream& aStream )
+    {
+    aStream.WriteInt32L( aBuffer.Length() );
+    aStream.WriteL( aBuffer );
+    }
+
+// -----------------------------------------------------------------------------
+//  CAUtils::ExternalizeBufferToStreamL
+//  Helper method for externalize the buffer
+// -----------------------------------------------------------------------------
+//
+void CAUtils::ExternalizeBufferToStreamL( const TDesC8& aBuffer, RWriteStream& aStream )
+    {
+    aStream.WriteInt32L( aBuffer.Length() );
+    aStream.WriteL( aBuffer );
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::InternalizeBufferFromStreamL
+// Helper method for internalize the buffer
+// -----------------------------------------------------------------------------
+//
+HBufC* CAUtils::InternalizeBufferFromStreamLC( RReadStream& aStream )
+    {
+    HBufC* buffer = NULL;
+
+    TInt length = aStream.ReadInt32L();
+
+    if ( length == 0 )
+        {
+        buffer = KNullDesC().AllocLC();
+        }
+    else
+        {
+        buffer = HBufC::NewLC( length );
+        TPtr ptr( buffer->Des() );
+        aStream.ReadL( ptr, length );
+        }
+
+    return buffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::InternalizeBufferFromStreamL
+// Helper method for internalize the buffer
+// -----------------------------------------------------------------------------
+//
+HBufC8* CAUtils::InternalizeBuffer8FromStreamLC( RReadStream& aStream )
+    {
+    HBufC8* buffer = NULL;
+
+    TInt length = aStream.ReadInt32L();
+
+    if ( length == 0 )
+        {
+        buffer = KNullDesC8().AllocLC();
+        }
+    else
+        {
+        buffer = HBufC8::NewLC( length );
+        TPtr8 ptr( buffer->Des() );
+        aStream.ReadL( ptr, length );
+        }
+
+    return buffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::InternalizeBufferFromStreamL
+// Helper method for internalize the buffer
+// -----------------------------------------------------------------------------
+//
+HBufC* CAUtils::InternalizeBufferFromStreamL( RReadStream& aStream )
+    {
+    HBufC* buffer = InternalizeBufferFromStreamLC( aStream );
+    CleanupStack::Pop( buffer );
+    return buffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::InternalizeBufferFromStreamL
+// Helper method for internalize the buffer
+// -----------------------------------------------------------------------------
+//
+HBufC8* CAUtils::InternalizeBuffer8FromStreamL( RReadStream& aStream )
+    {
+    HBufC8* buffer = InternalizeBuffer8FromStreamLC( aStream );
+    CleanupStack::Pop( buffer );
+    return buffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CAUtils::ValidLoginIdL()
+// -----------------------------------------------------------------------------
+//
+TBool CAUtils::ValidLoginIdL( const TDesC& aPresenceId )
+    {
+    TBool incorrectDomain ( EFalse );
+    TBool forbiddenChars ( EFalse );
+    TBool incorrectUserPart ( EFalse );
+
+    HBufC* wvId = aPresenceId.AllocLC();
+    TPtr wvIdPtr = wvId->Des();
+
+    TInt maxLength ( KServerWVUserIdMaxLength );
+
+    // let's take out the "wv:" from beginning of user id
+    TInt position( KErrNotFound );
+    if ( KCUImpsId_WVPrefix().CompareF( wvId->Left( KCUImpsId_WVPrefix().Length() ) ) == 0 )
+        {
+        wvIdPtr.Delete( 0, KCUImpsId_WVPrefix().Length() );
+        position = KErrNotFound;
+        // we just took out 3 characters from the id, we have to adjust the max length
+        maxLength = maxLength - KCUImpsId_WVPrefixLength;
+        }
+
+    // where is "@" ?
+    TInt atIndex( wvId->Find( KCUImpsId_At ) );
+    // we want the domain part without the '@'
+    TPtrC domainPart( wvId->Mid( atIndex + 1 ) );
+
+    if ( atIndex > 0 )
+        {
+        // check if the domain part is empty
+        if ( domainPart.Length() == 0 )
+            {
+            incorrectDomain = ETrue;
+            }
+        }
+    else if ( atIndex == 0 )
+        {
+        // the '@' is the first character
+        incorrectUserPart = ETrue;
+        }
+
+    TInt returnValue = domainPart.Find( KCUImpsId_At() );
+    // check the correctness of the domain part
+    if ( returnValue != KErrNotFound )
+        {
+        // extra @-mark found in the domain part
+        incorrectDomain = ETrue;
+        }
+
+    returnValue = domainPart.Find( KCUImpsId_Dot() );
+    if ( returnValue != KErrNotFound )
+        {
+        // the part after the '.'
+        TPtrC partAfterDot ( domainPart.Mid( returnValue + 1 ) );
+        // the part before the '.'
+        TPtrC partBeforeDot ( domainPart.Left( returnValue ) );
+        // if the '.' is the last character or the first character after the '@'
+        // the domain part is wrong
+        if ( ( 0 == partAfterDot.Length() ) || ( 0 == partBeforeDot.Length() ) )
+            {
+            // the '.' is the last character
+            incorrectDomain = ETrue;
+            }
+        }
+
+    returnValue = domainPart.Find( KCUImpsId_TwoDots() );
+    if ( returnValue != KErrNotFound )
+        {
+        // there are two sequential dots in the domain part
+        incorrectDomain = ETrue;
+        }
+
+
+    // check the wvid for forbidden chars
+
+    // first we must delete one '@' char if existing
+    position = wvIdPtr.Find( KCUImpsId_At );
+    if ( position != KErrNotFound )
+        {
+        wvIdPtr.Delete( position, KCUImpsId_At().Length() );
+        }
+
+    returnValue = wvIdPtr.Find( KCUImpsId_WhiteSpace() );
+    // no empty chars allowed in the user part
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+    // no encoded empty chars allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_WhiteSpaceEnc() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+
+    // no '+' allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_Plus() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+    // no encoded '+' allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_PlusEnc() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+
+
+    // no '\t' allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_Tabulator() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+    // no encoded tabulator allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_TabulatorEnc() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+
+    // no '/' allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_Slash() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+    // no encoded '/' allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_SlashEnc() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+
+    // no encoded '@' chars allowed in the user part
+    returnValue = wvIdPtr.Find( KCUImpsId_AtEnc() );
+    if ( returnValue != KErrNotFound )
+        {
+        forbiddenChars = ETrue;
+        }
+
+    TPtr userId = wvId->Des();
+
+    // no 16bit Unicode chars characters allowed in the user part
+    for ( TInt index = 0; index < wvIdPtr.Length(); index++ )
+        {
+        TUint value = userId[index];
+        // if the character does not fit into 8 bits, it's forbidden 255
+        if ( value > KMAX_LIMIT )
+            {
+            forbiddenChars = ETrue;
+            }
+        }
+
+    TBool tooLongId ( EFalse );
+
+    // check if the user id is too long when encoded, but only if there are no forbidden chars
+    if ( !forbiddenChars )
+        {
+        HBufC* encodedUserId = EscapeUtils::EscapeEncodeL( *wvId, EscapeUtils::EEscapeUrlEncoded );
+
+        if ( atIndex != KErrNotFound )
+            {
+            // @-character was removed from the ID, since it should not be encoded
+            // so the maxlength has to be decreased by it's length
+            maxLength = maxLength - KCUImpsId_At().Length();
+            }
+
+        if ( encodedUserId->Length() > maxLength )
+            {
+            tooLongId = ETrue;
+            }
+        delete encodedUserId;
+        }
+
+    CleanupStack::PopAndDestroy( wvId );
+
+    if ( forbiddenChars )
+        {
+        return EFalse;
+        }
+    else if ( incorrectDomain )
+        {
+        return EFalse;
+        }
+    else if ( tooLongId )
+        {
+        return EFalse;
+        }
+    else if ( incorrectUserPart )
+        {
+        return EFalse;
+        }
+
+    return ETrue;
+    }
+
+
+// ---------------------------------------------------------
+// CAUtils::ReconstructIdL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+HBufC* CAUtils::ReconstructIdL( const TDesC& aOrigId, const TDesC& aUserId )
+    {
+    CHAT_DP( D_CHAT_LIT( "** ReconstructIdL, the original  id: %S" ), &aOrigId );
+    CHAT_DP( D_CHAT_LIT( "** ReconstructIdL, user entered  id: %S" ), &aUserId );
+
+    // we got user id, add the removed parts ("wv:" and "@something" )
+    TInt colonPos( aOrigId.Locate( KColonUInt ) );
+    TInt domainPos( aOrigId.Locate( KAtUInt ) );
+    TInt userColonPos( aUserId.Locate( KColonUInt ) );
+    TInt userDomainPos( aUserId.Locate( KAtUInt ) );
+
+    // calculate the new length and determine what additions are needed
+    TInt newLength( aUserId.Length() );
+    TBool addPrefix( EFalse );
+    TBool addDomain( EFalse );
+
+    if ( colonPos != KErrNotFound &&
+         ( colonPos + 1 ) != aOrigId.Length() &&
+         userColonPos == KErrNotFound )
+        {
+        // the original id had ":" (not last character) and the current one doesn't
+        // => we'll be adding "wv:"
+        newLength += colonPos + 1;
+        addPrefix = ETrue;
+        }
+
+    if ( domainPos != KErrNotFound && userDomainPos == KErrNotFound )
+        {
+        // the original id had domain and the current one doesn't
+        // => we'll be adding "@something"
+        newLength += aOrigId.Length() - domainPos;
+        addDomain = ETrue;
+        }
+
+    HBufC* newId = HBufC::NewL( newLength );
+    // NOTE: NO LEAVING METHODS ALLOWED AFTER THIS!
+
+    TPtr newIdPtr( newId->Des() );
+    newIdPtr.Zero();
+
+    if ( addPrefix )
+        {
+        // add removed "wv:" prefix
+        newIdPtr.Append( aOrigId.Left( colonPos + 1 ) );
+        }
+    newIdPtr.Append( aUserId );
+    if ( addDomain )
+        {
+        // add removed domain part
+        newIdPtr.Append( aOrigId.Right( aOrigId.Length() - domainPos ) );
+        }
+
+    CHAT_DP( D_CHAT_LIT( "** ReconstructIdL, reconstructed id: %S" ), &newIdPtr );
+    return newId;
+    }
+
+// ---------------------------------------------------------
+// CAUtils::NeutralFind
+// ---------------------------------------------------------
+//
+TInt CAUtils::NeutralFind( const MDesCArray& aUserList, const TDesC& aUserId )
+    {
+    TInt count( aUserList.MdcaCount() );
+    for ( TInt i( 0 ); i < count; ++i )
+        {
+        if ( CAUtils::NeutralCompare( aUserList.MdcaPoint( i ),
+                                      aUserId ) == 0 )
+            {
+            return i;
+            }
+        }
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------
+// Static helper method used in
+// LanguageSpecificNumberConversion.
+// ---------------------------------------------------------
+//
+static TChar NumberToBase( TChar ch )
+    {
+    TDigitType d[] = { EDigitTypeWestern,
+                       EDigitTypeArabicIndic,
+                       EDigitTypeEasternArabicIndic,
+                       EDigitTypeDevanagari,
+                       EDigitTypeThai
+                     };
+    TInt i = 0;
+    TInt num = sizeof( d ) / sizeof( d[0] );
+    // code scanner warning can be ignored
+    while ( i < num )
+        {
+        if ( ch > TChar( d[i] ) && ch < TChar( d[i] + KMAX_NUMBERBASE ) )
+            {
+            return d[i];
+            }
+        i++;
+        }
+
+    return ch;
+    }
+
+// ---------------------------------------------------------
+// CAUtils::LanguageSpecificNumberConversion
+// ---------------------------------------------------------
+//
+void CAUtils::LanguageSpecificNumberConversion( TDes& aDes )
+    {
+    // Get current locale and digit type
+    TLocale locale;
+    locale.Refresh();
+    TDigitType digitType = locale.DigitType();
+
+    // Check if conversion is needed
+    TBool conversion = ( digitType == EDigitTypeArabicIndic )
+                       || ( digitType == EDigitTypeEasternArabicIndic )
+                       || ( digitType == EDigitTypeDevanagari );
+
+    if ( !conversion )
+        {
+        // Don't do anything
+        return;
+        }
+
+    // Do conversion, logic for this conversion
+    // comes from AknTextUtils::LanguageSpecificNumberConversion.
+    // Logic is copied here to avoid using Avkon in engine side.
+    TChar toArea = KCharToArea;
+
+    switch ( digitType )
+        {
+        case EDigitTypeWestern:
+        case EDigitTypeArabicIndic:
+        case EDigitTypeEasternArabicIndic:
+        case EDigitTypeDevanagari:
+        case EDigitTypeThai:    // Flowthrough
+            {
+            toArea = digitType;
+            break;
+            }
+        case EDigitTypeUnknown:
+        case EDigitTypeAllTypes:
+        default:    // Flowthrough
+            {
+            return;
+            }
+        }
+
+    TInt length = aDes.Length();
+
+    for ( TInt i = 0; i < length; i++ )
+        {
+        TChar ch = aDes[i];
+        TChar fromArea = NumberToBase( ch );
+        TChar::TBdCategory cat = ch.GetBdCategory();
+        switch ( cat )
+            {
+            case TChar::EArabicNumber:
+            case TChar::EEuropeanNumber:    // Flowthrough
+                {
+                ch += toArea;
+                ch -= fromArea;
+                aDes[i] = TUint16( ch );
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    }
+// ---------------------------------------------------------
+// CAUtils::CapitalizeListNameL : UI CR :  101-39727
+// ---------------------------------------------------------
+//
+HBufC* CAUtils::CapitalizeListNameL( const TDesC& aListname )
+    {
+    MCAStoredContacts* contacts = NULL;
+    TRAPD( err, contacts = CCAStorageManagerFactory::ContactListInterfaceL() );
+
+    if ( err == KErrNone && contacts
+         && contacts->CapitalizingEnabled()
+         && ( aListname.Length() ) )
+        {
+        HBufC* capitalPartBuf = HBufC::NewL( KServerWVUserIdMaxLength );
+        TPtr capitalPartptr( capitalPartBuf->Des() );
+
+        if ( aListname.Length() == 1 )
+            {
+            capitalPartptr.CopyUC( aListname );
+            return capitalPartBuf;
+            }
+        capitalPartptr.CopyUC( aListname.Left( 1 ) );// copy and capitalize first letter
+        capitalPartptr.Append( aListname.Right( ( aListname.Length() - 1 ) ) );// append the remaining
+        return capitalPartBuf;
+        }
+
+    // some error, don't modify
+    CHAT_DP_FUNC_DP( "CapitalizeListNameL", "Got some error, not Capitalizing" );
+    HBufC* capitalPartBuf = aListname.AllocL();
+    return capitalPartBuf;
+    }
+
+
+// ---------------------------------------------------------
+// CAUtils::CapitalizingEnabled   UI CR : 101-39727
+// ---------------------------------------------------------
+//
+TBool CAUtils::CapitalizingEnabled()
+    {
+    MCAStoredContacts* contacts = NULL;
+    TRAPD( err, contacts = CCAStorageManagerFactory::ContactListInterfaceL() );
+    if ( err != KErrNone || !contacts )
+        {
+        // some error, return Efalse
+        return EFalse;
+        }
+    return ( contacts->CapitalizingEnabled() );
+    }
+
+
+// ---------------------------------------------------------
+// CAUtils::CapitalizeListNameL   UI CR : 101-39727
+// ---------------------------------------------------------
+//
+
+HBufC* CAUtils::CapitalizeListIdL( const TDesC& aId )
+    {
+    TPtrC ret( aId );
+    TBool slashfound( EFalse );
+    TBool domainfound( EFalse );
+    // locate "/" for list id.
+    TInt pos = aId.FindC( KSlash  );
+
+    if ( ( pos != KErrNotFound ) && ( pos != aId.Length() - 1 ) )
+        {
+        // make it true if slash found and it should not be at the last position
+        slashfound = ETrue;
+        }
+
+    // locate for the domain part
+
+    TInt domainPos = ret.FindC( KAt );
+    if ( ( domainPos != KErrNotFound ) && ( domainPos != 0 ) )
+        {
+        // make it true if domain part is found and itshould not be at the first position
+        domainfound = ETrue;
+        }
+
+    MCAStoredContacts* contacts = NULL;
+    TRAPD( err, contacts = CCAStorageManagerFactory::ContactListInterfaceL() );
+
+    if ( err == KErrNone && contacts                      // extrachecking here bcoz
+         && contacts->CapitalizingEnabled()// it has to return NULL
+         && aId.Length() )                 // (not the list id)
+        {                                                   // if error occurs
+        if ( slashfound && !domainfound )
+            {
+            //remove upto  '/' and capitalize
+            return  CAUtils::CapitalizeListNameL( aId.Right( ( aId.Length() - ( pos + 1 ) ) ) );
+            }
+        else  if ( slashfound && domainfound )
+            {
+            // remove upto  '/' and after domain part and capitalize
+            return CAUtils::CapitalizeListNameL( aId.Mid( pos + 1, ( domainPos - pos - 1 ) ) );
+            }
+        else
+            {
+            // if only domain part found or both part not found just capitalize listId
+            return CAUtils::CapitalizeListNameL( aId );
+            }
+
+        }
+
+    // some error,return null
+    return NULL;
+    }
+
+// End of file