mmsengine/genutils/src/mmsgenutils.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *       Utility methods for UI and engine modules. Provides help for address
       
    16 *       string parsing, resource files and contact database access.
       
    17 *       General address format is either
       
    18 *           alias<real-address>
       
    19 *       or
       
    20 *           <real-address>
       
    21 *       as used in the Client MTM API.
       
    22 *
       
    23 */
       
    24 
       
    25  
       
    26 
       
    27 // INCLUDE FILES
       
    28 #include <barsc.h>               // resource file
       
    29 #include <bautils.h>
       
    30 #include <miutpars.h>            // e-mail utilities
       
    31 
       
    32 #include <miutconv.h>            // CharConv 
       
    33 #include <flogger.h>
       
    34 #include <e32svr.h>
       
    35 #include <e32base.h>
       
    36 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    37 #include <imcvcodc.h>
       
    38 #else
       
    39 #include <imcvcodc.h>
       
    40 #include <cimconvertheader.h>
       
    41 #endif
       
    42 #include <f32file.h>                 
       
    43 #include <UiklafInternalCRKeys.h>
       
    44 #include <telconfigcrkeys.h>
       
    45 #include <centralrepository.h>
       
    46 #include <CoreApplicationUIsSDKCRKeys.h>
       
    47 #include <data_caging_path_literals.hrh>
       
    48 
       
    49 #include <MVPbkContactStore.h>
       
    50 #include <MVPbkContactStoreProperties.h>
       
    51 #include <MVPbkContactLink.h>
       
    52 #include <CPbk2StoreConfiguration.h>   // Contact store configuration
       
    53 #include <contactmatcher.h> // contact match wrapper
       
    54 #include <CVPbkPhoneNumberMatchStrategy.h>
       
    55 #include <CVPbkContactLinkArray.h>
       
    56 #include <CVPbkFieldTypeRefsList.h>
       
    57 #include <TVPbkFieldVersitProperty.h>
       
    58 #include <VPbkFieldType.hrh>
       
    59 #include <MVPbkStoreContactFieldCollection.h>
       
    60 #include <MVPbkStoreContact.h>
       
    61 #include <CVPbkContactStoreUriArray.h>
       
    62 #include <VPbkContactStoreUris.h>
       
    63 #include <TVPbkContactStoreUriPtr.h>
       
    64 #include "mmsgenutils.h"
       
    65 #include "MmsEnginePrivateCRKeys.h"
       
    66 
       
    67 // EXTERNAL DATA STRUCTURES
       
    68 
       
    69 // EXTERNAL FUNCTION PROTOTYPES  
       
    70 
       
    71 // CONSTANTS
       
    72 const TInt KLogBufferLength = 256;
       
    73 #ifdef _DEBUG
       
    74 _LIT( KLogDir, "mmsc" );
       
    75 _LIT( KLogFile, "mmsc.txt" );
       
    76 #endif
       
    77 const TUint KMinAliasMaxLength = 14;
       
    78 const TUint KExtraSpaceForConversion10 = 10;
       
    79 const TUint KExtraSpaceForConversion30 = 30;
       
    80 
       
    81 const TInt KErrMultipleMatchFound = KErrGeneral;
       
    82 // MACROS
       
    83 
       
    84 // LOCAL CONSTANTS AND MACROS
       
    85 
       
    86 // MODULE DATA STRUCTURES
       
    87 
       
    88 // LOCAL FUNCTION PROTOTYPES
       
    89 
       
    90 // ==================== LOCAL FUNCTIONS ====================
       
    91 
       
    92 // ================= MEMBER FUNCTIONS =======================
       
    93 
       
    94 // Constructor 
       
    95 //
       
    96 EXPORT_C TMmsGenUtils::TMmsGenUtils()
       
    97     {
       
    98     }
       
    99 
       
   100 // Destructor 
       
   101 //
       
   102 // THERE SHOULD NOT BE DESTRUCTOR IN T-CLASS.
       
   103 // MUST BE REMOVED
       
   104 EXPORT_C TMmsGenUtils::~TMmsGenUtils()
       
   105     {
       
   106     }
       
   107 
       
   108 
       
   109 // ---------------------------------------------------------
       
   110 // TMmsGenUtils::AddressTypeAndRealAddress
       
   111 // ---------------------------------------------------------
       
   112 //
       
   113 EXPORT_C TInt TMmsGenUtils::AddressTypeAndRealAddress(
       
   114     const TDesC& aAddress,
       
   115     TMmsAddressType& aType,
       
   116     TDes& aRealAddress,
       
   117     TInt aMaxLength,
       
   118     const TDesC& aOpen,
       
   119     const TDesC& aClose )
       
   120     {
       
   121     aRealAddress.Zero();
       
   122     aType = EMmsAddressTypeUnknown;
       
   123 
       
   124     TPtrC realAddress;
       
   125     realAddress.Set( PureAddress( aAddress, aOpen, aClose ) );
       
   126 
       
   127     if ( realAddress.Length() > aMaxLength )
       
   128         {
       
   129         return KErrTooBig;
       
   130         }
       
   131 
       
   132     if ( IsValidMMSPhoneAddress( realAddress ) )
       
   133         {
       
   134         aType = EMmsAddressTypeMobile;
       
   135         }
       
   136     else if ( IsValidEmailAddress( realAddress ) )
       
   137         {
       
   138         aType = EMmsAddressTypeEmail;
       
   139         }
       
   140     else
       
   141         {
       
   142     	
       
   143         }
       
   144 
       
   145     // we returned earlier if address was too big.
       
   146     if ( aType != EMmsAddressTypeUnknown )
       
   147         {
       
   148         aRealAddress.Copy( realAddress );
       
   149         }
       
   150 
       
   151     return KErrNone; 
       
   152     }
       
   153 
       
   154 // ---------------------------------------------------------
       
   155 // TMmsGenUtils::IsValidAddress
       
   156 // ---------------------------------------------------------
       
   157 //
       
   158 EXPORT_C TBool TMmsGenUtils::IsValidAddress( 
       
   159    const TDesC& aAddress,
       
   160    TBool aReal,
       
   161    const TDesC& aOpen,
       
   162    const TDesC& aClose )
       
   163    {
       
   164    TPtrC realAddress;
       
   165 
       
   166    if ( !aReal)
       
   167        {
       
   168        realAddress.Set( PureAddress( aAddress, aOpen, aClose ) );
       
   169        }
       
   170    else
       
   171        {
       
   172        realAddress.Set ( aAddress );
       
   173        }
       
   174 
       
   175    if ( !IsValidMMSPhoneAddress( realAddress ) )
       
   176        {
       
   177        return IsValidEmailAddress( realAddress );
       
   178        }
       
   179 
       
   180    return ETrue;
       
   181    }
       
   182 
       
   183 // ---------------------------------------------------------
       
   184 // TMmsGenUtils::IsValidEmailAddress
       
   185 // ---------------------------------------------------------
       
   186 //          
       
   187 EXPORT_C TBool TMmsGenUtils::IsValidEmailAddress( 
       
   188     const TDesC& aAddress,
       
   189     TBool aReal,
       
   190     const TDesC& aOpen,
       
   191     const TDesC& aClose )
       
   192     {
       
   193     // Strip off alias part if necessary
       
   194     TPtrC realAddress;
       
   195     if ( aReal )
       
   196       {
       
   197       realAddress.Set( aAddress ); 
       
   198       }
       
   199     else
       
   200       {
       
   201       realAddress.Set( PureAddress( aAddress, aOpen, aClose ) );
       
   202       }
       
   203     TImMessageField email;
       
   204     return email.ValidInternetEmailAddress( realAddress );
       
   205     }
       
   206 
       
   207 // ---------------------------------------------------------
       
   208 // TMmsGenUtils::IsValidMMSPhoneAddress
       
   209 // ---------------------------------------------------------
       
   210 //
       
   211 EXPORT_C TBool TMmsGenUtils::IsValidMMSPhoneAddress( 
       
   212   const TDesC& aAddress,
       
   213   TBool aReal,
       
   214   const TDesC& aOpen,
       
   215   const TDesC& aClose  )
       
   216   {
       
   217   // global_phone_number = [+] 1*(DIGIT, written-sep)
       
   218   // written_sep = ('-')
       
   219 
       
   220   // Strip off alias part if necessary
       
   221   TPtrC realAddress;
       
   222   if ( aReal )
       
   223       {
       
   224       realAddress.Set( aAddress ); 
       
   225       }
       
   226   else
       
   227       {
       
   228       realAddress.Set( PureAddress( aAddress, aOpen, aClose ) );
       
   229       }
       
   230 
       
   231   TInt length = realAddress.Length();
       
   232 
       
   233   if ( length == 0 )
       
   234       {
       
   235       return EFalse;
       
   236       }
       
   237 
       
   238   TInt pos = 0;
       
   239   TInt ich = realAddress[0];
       
   240   TChar ch = ich;
       
   241   if ( ch == '+' )
       
   242       {
       
   243       pos++;
       
   244       }
       
   245 
       
   246   if ( pos == length )
       
   247       {
       
   248       return EFalse;
       
   249       }
       
   250 
       
   251   while ( pos < length )
       
   252       {
       
   253       ich = realAddress[pos];
       
   254       ch = ich;
       
   255       ch.Fold(); 
       
   256       TInt fch = ch;
       
   257         // do not check for fch == '.'
       
   258 	//Even # and * are valid characters now
       
   259         if ( !( ch.IsDigit() || fch == '-' || fch == '#' || fch == '*' ) )
       
   260           {
       
   261           return EFalse;
       
   262           }
       
   263       pos++;
       
   264       }
       
   265 
       
   266   return ETrue;
       
   267   }
       
   268 
       
   269 
       
   270 // ---------------------------------------------------------
       
   271 // TMmsGenUtils::Alias
       
   272 // ---------------------------------------------------------
       
   273 //
       
   274 EXPORT_C TPtrC TMmsGenUtils::Alias( 
       
   275     const TDesC& aAddress,
       
   276     const TDesC& aOpen,
       
   277     const TDesC& aClose )
       
   278     {
       
   279 
       
   280     // syntax is :
       
   281     // <alias><separator1><pure_address><separator2> |
       
   282     // <pure_address>
       
   283     TInt firstPos = 0;
       
   284     TInt lastPos = 0;
       
   285     TInt length = aAddress.Length();
       
   286     TInt sepaLen1 = aOpen.Length();
       
   287     TInt sepaLen2 = aClose.Length();
       
   288     TInt firstSeparatorPosition = 0;
       
   289 
       
   290     while( firstSeparatorPosition >= 0 )
       
   291         {
       
   292         firstSeparatorPosition = aAddress.Mid( firstPos ).Find( aOpen );
       
   293         if ( firstSeparatorPosition >= 0 )
       
   294             {
       
   295             firstPos += firstSeparatorPosition + sepaLen1;
       
   296             }
       
   297         }
       
   298     if ( firstPos <= 0 )
       
   299         {
       
   300         // No alias
       
   301         return TPtrC();
       
   302         }
       
   303 
       
   304     // Search another separator after the first separator from
       
   305     lastPos = aAddress.Mid( firstPos ).Find( aClose );
       
   306     if ( lastPos == KErrNotFound )
       
   307         {
       
   308         return TPtrC();
       
   309         }
       
   310     firstPos -= sepaLen1; // point to first separator    
       
   311     if ( lastPos == length - firstPos - sepaLen1 - sepaLen2 )
       
   312         {
       
   313         // Alias part found
       
   314         // remove trailing and leading spaces
       
   315         lastPos = firstPos;
       
   316         firstPos = 0;
       
   317         while ( firstPos < aAddress.Length() &&
       
   318             aAddress.Mid( firstPos, 1 ).Compare( KSpace16 ) == 0 )
       
   319             {
       
   320             // remove leading spaces
       
   321             firstPos++;
       
   322             }
       
   323         while ( lastPos > 0 && aAddress.Mid( lastPos - 1, 1 ).Compare( KSpace16 ) == 0 )
       
   324             {
       
   325             lastPos--;
       
   326             }
       
   327         if ( lastPos > firstPos )
       
   328             {
       
   329             return aAddress.Mid( firstPos, lastPos - firstPos );
       
   330             }
       
   331         }
       
   332     // No alias defined - spaces alone do not count as alias.
       
   333     return TPtrC();
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------
       
   337 // TMmsGenUtils::PureAddress
       
   338 // ---------------------------------------------------------
       
   339 //
       
   340 EXPORT_C TPtrC TMmsGenUtils::PureAddress( 
       
   341     const TDesC& aAddress,
       
   342     const TDesC& aOpen,
       
   343     const TDesC& aClose )
       
   344     {
       
   345     // syntax is :
       
   346     // <alias><separator1><pure_address><separator2> |
       
   347     // <pure_address>
       
   348     TInt firstPos = 0;
       
   349     TInt lastPos = 0;
       
   350     TInt length = aAddress.Length();
       
   351     TInt sepaLen1 = aOpen.Length();
       
   352     TInt sepaLen2 = aClose.Length();
       
   353     TInt firstSeparatorPosition = 0;
       
   354     
       
   355     while( firstSeparatorPosition >= 0 )
       
   356         {
       
   357         firstSeparatorPosition = aAddress.Mid( firstPos ).Find( aOpen );
       
   358         if ( firstSeparatorPosition >= 0 )
       
   359             {
       
   360             firstPos += firstSeparatorPosition + sepaLen1;
       
   361             }
       
   362         }
       
   363     if ( firstPos <= 0 )
       
   364         {
       
   365         // No alias
       
   366         return aAddress;
       
   367         }
       
   368         
       
   369     // Check if the second separator ends the address
       
   370     TPtrC last = aAddress.Right( sepaLen2 );
       
   371     lastPos = length - sepaLen2;
       
   372     
       
   373     if ( !last.Compare( aClose ) )
       
   374         {
       
   375         // Alias part found
       
   376         if ( lastPos > firstPos )
       
   377             {
       
   378             return aAddress.Mid( firstPos, lastPos - firstPos );
       
   379             }
       
   380         }
       
   381     // No alias defined - return the original string as pure address
       
   382     // If syntax is weird, namely 
       
   383     // alias <>
       
   384     // with nothing between the separators, we return the original string as is
       
   385     return aAddress;
       
   386     }
       
   387 
       
   388 // ---------------------------------------------------------
       
   389 // TMmsGenUtils::GenerateDetails
       
   390 // ---------------------------------------------------------
       
   391 //
       
   392 EXPORT_C TInt TMmsGenUtils::GenerateDetails( 
       
   393     const TDesC& aAddress,
       
   394     TDes& aAlias,
       
   395     TInt aMaxLength,
       
   396     RFs& aFs ) 
       
   397     {
       
   398     
       
   399     TInt err = KErrNone;
       
   400     
       
   401     // alias search order: Local alias, remote alias, none
       
   402     
       
   403     TPtrC realAddress;
       
   404     realAddress.Set( PureAddress( aAddress, KSepaOpen, KSepaClose ) );
       
   405 
       
   406     TRAP( err, DoGetAliasL( aFs, realAddress, aAlias, aMaxLength ) );
       
   407     if ( err != KErrNone || aAlias.Length() == 0 )
       
   408         {
       
   409         // No alias found from Contact db, see if there is a local alias
       
   410         TPtrC myAddress = Alias( aAddress, KSepaOpen, KSepaClose );
       
   411         if ( myAddress.Length() > 0 )
       
   412             {
       
   413             // Alias was found from the address
       
   414             aAlias.Copy( myAddress.Left( aMaxLength ) );
       
   415             return KErrNone;
       
   416             }
       
   417         else
       
   418             {
       
   419             if ( err == KErrNotFound )
       
   420                 {
       
   421                 err = KErrNone;
       
   422                 }
       
   423             // just keep the original address
       
   424             aAlias.Copy( aAddress.Left( aMaxLength ) );
       
   425             }
       
   426         }
       
   427 
       
   428     return err;
       
   429 
       
   430     }
       
   431     
       
   432 
       
   433 // ---------------------------------------------------------
       
   434 // TMmsGenUtils::GetAlias
       
   435 // ---------------------------------------------------------
       
   436 //
       
   437 EXPORT_C TInt TMmsGenUtils::GetAlias( 
       
   438     const TDesC& aAddress,
       
   439     TDes& aAlias,
       
   440     TInt aMaxLength,
       
   441     RFs& aFs )
       
   442     {
       
   443     TInt err = KErrNone;
       
   444     TRAP( err, DoGetAliasL( aFs, aAddress, aAlias, aMaxLength ) );
       
   445     if ( err == KErrNotFound )
       
   446         {
       
   447         err = KErrNone;
       
   448         }
       
   449     return err;
       
   450     }
       
   451 
       
   452     
       
   453 // ---------------------------------------------------------
       
   454 // TMmsGenUtils::GetAliasForAllL
       
   455 // This function searches aliases for all addresses in a 
       
   456 // address field by opening the contact db only once for all 
       
   457 // addresses. This significantly reduces processing time 
       
   458 // when executing "Create Reply to all" with a lot of addresses
       
   459 // ---------------------------------------------------------
       
   460 // 
       
   461 EXPORT_C void TMmsGenUtils::GetAliasForAllL(
       
   462     const CDesCArray& aAddress,
       
   463     CDesCArray& aAlias,
       
   464     TInt aMaxLength,
       
   465     RFs& aFs )
       
   466     {
       
   467     
       
   468     if ( aMaxLength <= 0 )
       
   469         {
       
   470         User::Leave( KErrArgument );
       
   471         }
       
   472     
       
   473     TUint stack = 0;
       
   474 
       
   475     //Let's find the number of digits to match
       
   476     TInt digitsToMatch = DigitsToMatch();
       
   477     TInt err = KErrNone;
       
   478     
       
   479     // Use contact wrapper to open all databases
       
   480     CContactMatcher* contactMatcher = OpenAllStoresL( aFs );
       
   481     CleanupStack::PushL( contactMatcher );
       
   482     stack++;
       
   483     
       
   484     HBufC* helpBuffer = HBufC::NewL( aMaxLength );
       
   485     CleanupStack::PushL( helpBuffer );
       
   486     stack++; 
       
   487        
       
   488     TPtr pHelpBuffer = helpBuffer->Des();   
       
   489    
       
   490     for ( TInt i = 0; i < aAddress.MdcaCount(); i++  )
       
   491         {  
       
   492         // We trap these one by one in order to be able
       
   493         // to continue to next match in case of error (not found)
       
   494         
       
   495         // make sure the alias is empty if nothing found
       
   496         pHelpBuffer.Zero();
       
   497         
       
   498     	TRAP( err, DoGetAliasL( 
       
   499             aAddress.MdcaPoint(i), 
       
   500     	    pHelpBuffer, 
       
   501     	    aMaxLength, 
       
   502     	    *contactMatcher, 
       
   503     	    digitsToMatch ) );
       
   504 
       
   505         // if alias is not found, we'll have an empty buffer
       
   506         // We have to insert it anyway to keep the indexes correct
       
   507         // as we have two parallel arrays
       
   508         aAlias.InsertL( i, pHelpBuffer );
       
   509         }
       
   510         
       
   511     // closing is best effort only.    
       
   512     TRAP_IGNORE( contactMatcher->CloseStoresL() );
       
   513     CleanupStack::PopAndDestroy( stack, contactMatcher );  //contactMatcher, helpBuffer   
       
   514     
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------
       
   518 // TMmsGenUtils::GenerateAddress
       
   519 // ---------------------------------------------------------
       
   520 //
       
   521 EXPORT_C HBufC* TMmsGenUtils::GenerateAddressL(
       
   522     const TDesC& aRealAddress,
       
   523     const TDesC& aAlias,
       
   524     const TDesC& aOpen,
       
   525     const TDesC& aClose )
       
   526     {
       
   527     TInt sepaLen1 = aOpen.Length();
       
   528     TInt sepaLen2 = aClose.Length();
       
   529     TInt length = aRealAddress.Length() + aAlias.Length() + sepaLen1 + sepaLen2;
       
   530     HBufC* buf = HBufC::NewL( length );
       
   531     buf->Des().Copy( aAlias );
       
   532     buf->Des().Append( aOpen );
       
   533     buf->Des().Append( aRealAddress );
       
   534     buf->Des().Append( aClose );
       
   535     return buf;
       
   536     }
       
   537 
       
   538 // ---------------------------------------------------------
       
   539 // TMmsGenUtils::GetDescriptionL
       
   540 // ---------------------------------------------------------
       
   541 //
       
   542 EXPORT_C void TMmsGenUtils::GetDescriptionL( 
       
   543     RFs& aFs,
       
   544     const TDesC& aPath,
       
   545     TInt aFileSize,
       
   546     TPtrC8 aMimetype,
       
   547     TInt aCharSet,
       
   548     TDes& aDescription )
       
   549     {
       
   550     TInt fileSize = aFileSize;  // file size in characters
       
   551     TInt error = KErrNone;
       
   552     // set empty description if we cannot get anything
       
   553     aDescription = TPtrC();
       
   554 
       
   555     // No subject set, so we have to 
       
   556     // find the first text/plain attachment.
       
   557 
       
   558     // Update iDescription if necessary 
       
   559     
       
   560     if ( aMimetype.CompareF( KMmsTextPlain ))
       
   561         {
       
   562         // no description available
       
   563         return;
       
   564         }
       
   565     
       
   566     TInt outLength = aDescription.MaxLength();
       
   567                 
       
   568     // Open the attachment file
       
   569     RFileReadStream reader;
       
   570     reader.PushL(); 
       
   571     error = reader.Open( aFs, 
       
   572         aPath, 
       
   573         EFileShareReadersOnly );
       
   574     if ( error != KErrNone )
       
   575         {
       
   576         CleanupStack::PopAndDestroy( &reader );  //reader
       
   577         // cannot open file, cannot get description
       
   578         return;
       
   579         }
       
   580 
       
   581     TInt firstSize = 0;
       
   582     if ( TUint( aCharSet ) == KMmsIso10646Ucs2 )
       
   583        {                    
       
   584        // Read the content
       
   585        TUint16 word = 0;
       
   586        TBool bom = EFalse;
       
   587        TBool nativeEndian = EFalse;
       
   588 
       
   589        // Check if first character is BOM and if so, then what kind it is.
       
   590        TRAP ( error, {word = reader.ReadUint16L();}); 
       
   591        if ( error != KErrNone )
       
   592            {
       
   593            CleanupStack::PopAndDestroy( &reader ); //reader
       
   594            return; // no description available        
       
   595            }
       
   596 
       
   597        // reserve extra space for conversion
       
   598        firstSize = outLength + KExtraSpaceForConversion10;
       
   599        HBufC* buf1 = HBufC::NewLC( firstSize ); 
       
   600        TPtr tp = buf1->Des();
       
   601 
       
   602        if ( word == KMmsByteOrderMark )
       
   603            {
       
   604            bom = ETrue;
       
   605            nativeEndian = ETrue;
       
   606            }
       
   607        else if ( word == KMmsReversedByteOrderMark )
       
   608            {
       
   609            bom = ETrue;
       
   610            } 
       
   611        else
       
   612            {
       
   613            }
       
   614 
       
   615        if ( bom )
       
   616            {
       
   617            fileSize -= 2;
       
   618            }
       
   619 
       
   620        fileSize = fileSize / 2;
       
   621                                                                                  
       
   622        // Read the rest of the characters
       
   623        if ( nativeEndian )
       
   624            {
       
   625            // No need for byte order changes
       
   626            reader.ReadL( tp, Min( firstSize, fileSize ));
       
   627            }
       
   628        else if ( bom )
       
   629            {
       
   630            // Change byte order.
       
   631            TUint8 byte1 = 0;
       
   632            TUint16 byte2 = 0;
       
   633            TUint16 word1 = 0;
       
   634            TInt numChars = Min( firstSize, fileSize );
       
   635            for ( TInt i = 0; i < numChars; i++ )
       
   636                {
       
   637                byte1 = reader.ReadUint8L();
       
   638                byte2 = reader.ReadUint8L();
       
   639                word1 = byte1;
       
   640                const TInt KMmsBitsInByte = 8;
       
   641                word1 <<= KMmsBitsInByte; 
       
   642                word1 |= byte2;
       
   643                tp.Append( word1 );
       
   644                }
       
   645            }
       
   646           
       
   647        else // no bom
       
   648            {
       
   649            // Return the first character if it was not BOM.
       
   650            // should not happen regularly
       
   651            // Read the characters
       
   652            reader.ReadL( tp, Min( firstSize, fileSize - 2 ));
       
   653            TBuf<2> auxBuf;
       
   654            auxBuf.Append(word);
       
   655            tp.Insert(0, auxBuf);
       
   656            } 
       
   657 
       
   658        // Replace CR and LF with SPACE. 
       
   659        ReplaceCRLFAndTrim( tp );
       
   660 
       
   661         // Set output parameter
       
   662        aDescription = tp.Left( Min( outLength, tp.Length()) );
       
   663        CleanupStack::PopAndDestroy( buf1 );  
       
   664        }
       
   665 
       
   666     else if ( aCharSet == KMmsUsAscii )
       
   667         {
       
   668         // reserve extra space for conversion
       
   669         firstSize = outLength + KExtraSpaceForConversion10;
       
   670         HBufC8* buf8 = HBufC8::NewLC( firstSize );
       
   671         TPtr8 tp8 = buf8->Des();             
       
   672 
       
   673         // Read the characters
       
   674         reader.ReadL( tp8, Min( firstSize, fileSize ));
       
   675 
       
   676         // Replace CR and LF with SPACE
       
   677         ReplaceCRLFAndTrim( tp8 );
       
   678 
       
   679         // Copy 8 bit data to 16 bit description
       
   680         HBufC* buf16 = NULL;
       
   681         buf16 = HBufC::NewLC( tp8.Length() );
       
   682         TPtr tp16 = buf16->Des(); 
       
   683         tp16.Copy( tp8 );
       
   684 
       
   685         // Set output parameter
       
   686         aDescription = tp16.Left( Min( outLength, tp16.Length()) );
       
   687         CleanupStack::PopAndDestroy( buf16 );  
       
   688         CleanupStack::PopAndDestroy( buf8 );
       
   689         }
       
   690     else if ( aCharSet == KMmsUtf8 )
       
   691         {
       
   692                
       
   693         if ( fileSize > KMmsMaxDescription )
       
   694            {
       
   695            fileSize = KMmsMaxDescription;
       
   696            }
       
   697 
       
   698         // reserve extra space for conversion
       
   699         firstSize = outLength + KExtraSpaceForConversion30;
       
   700         HBufC8* buf8 = HBufC8::NewLC( firstSize );
       
   701         TPtr8 tp8 = buf8->Des(); 
       
   702 
       
   703         // Read the characters
       
   704         TRAP( error, reader.ReadL( tp8, Min( firstSize, fileSize )));
       
   705 
       
   706         if ( error == KErrNone )
       
   707             {
       
   708             // Convert 8-bit UTF to Unicode
       
   709             HBufC* buf16 = HBufC::NewLC( tp8.Length() );
       
   710             TPtr tp16 = buf16->Des();
       
   711             CnvUtfConverter::ConvertToUnicodeFromUtf8( tp16, tp8 );
       
   712 
       
   713             // Replace CR and LF with SPACE
       
   714             ReplaceCRLFAndTrim( tp16 );
       
   715             
       
   716             // Set output parameter
       
   717             aDescription = tp16.Left( Min( outLength, tp16.Length()) );
       
   718             CleanupStack::PopAndDestroy( buf16 );  
       
   719             }
       
   720         CleanupStack::PopAndDestroy( buf8 );  
       
   721         }
       
   722     else
       
   723         {
       
   724     	
       
   725         }
       
   726 
       
   727     // Free memory
       
   728     CleanupStack::PopAndDestroy( &reader ); //reader
       
   729     }
       
   730 
       
   731 // ---------------------------------------------------------
       
   732 // TMmsGenUtils::ReplaceCRLFAndTrim
       
   733 // ---------------------------------------------------------
       
   734 //
       
   735 EXPORT_C void TMmsGenUtils::ReplaceCRLFAndTrim( TDes16& aDes )
       
   736     {
       
   737     TInt position = -1;
       
   738 
       
   739     // Find all <CR> and <LF> characters and replace them with spaces
       
   740 
       
   741     for ( position = 0; position < aDes.Length(); position++ )
       
   742         {
       
   743         if ( aDes.Mid( position, 1 ) < KSpace16 ||
       
   744             aDes.Mid( position, 1 ) == KMmsUnicodeLineSeparator ||
       
   745             aDes.Mid( position, 1 ) == KMmsUnicodeParagraphSeparator ||
       
   746             aDes.Mid( position, 1 ) == KMmsIdeographicSpace ||
       
   747             ((TChar)aDes[position]).IsControl() )
       
   748             {
       
   749             aDes.Replace( position, 1, KSpace16 );
       
   750             }
       
   751         }
       
   752             
       
   753     // Delete leading and trailing space characters from the descriptor’s
       
   754     // data and replace each contiguous set of space characters within 
       
   755     // the data by one space character. 
       
   756     aDes.TrimAll();
       
   757     }
       
   758 
       
   759 
       
   760 // ---------------------------------------------------------
       
   761 // TMmsGenUtils::ReplaceCRLFAndTrim
       
   762 // ---------------------------------------------------------
       
   763 //
       
   764 EXPORT_C void TMmsGenUtils::ReplaceCRLFAndTrim( TDes8& aDes )
       
   765     {
       
   766     // This function should be used for US-ASCII only
       
   767     TInt position = -1;
       
   768 
       
   769     for ( position = 0; position < aDes.Length(); position++ )
       
   770         {
       
   771         if ( aDes.Mid( position, 1 ) < KSpace8 )
       
   772              {
       
   773              aDes.Replace( position, 1, KSpace8 );
       
   774              }
       
   775         }
       
   776 
       
   777     // Delete leading and trailing space characters from the descriptor’s
       
   778     // data and replace each contiguous set of space characters within 
       
   779     // the data by one space character. 
       
   780     aDes.TrimAll();
       
   781     }
       
   782 
       
   783 // ---------------------------------------------------------
       
   784 // TMmsGenUtils::Log
       
   785 // ---------------------------------------------------------
       
   786 //
       
   787 EXPORT_C void TMmsGenUtils::Log( TRefByValue<const TDesC> aFmt,...)
       
   788     {
       
   789 #ifdef _DEBUG
       
   790     VA_LIST list;
       
   791     VA_START( list, aFmt );
       
   792 
       
   793     // Print to log file
       
   794     TBuf<KLogBufferLength> buf;
       
   795     buf.FormatList( aFmt, list );
       
   796 
       
   797     // Write to log file
       
   798     RFileLogger::Write( KLogDir, KLogFile, EFileLoggingModeAppend, buf );
       
   799 #endif
       
   800     }
       
   801 
       
   802 // ---------------------------------------------------------
       
   803 // TMmsGenUtils::DoGetAliasL
       
   804 // ---------------------------------------------------------
       
   805 //
       
   806 void TMmsGenUtils::DoGetAliasL(
       
   807     RFs& aFs,
       
   808     const TDesC& aAddress, 
       
   809     TDes& aAlias, 
       
   810     TInt aMaxLength )
       
   811     {
       
   812     
       
   813     //Let's find the number of digits to match
       
   814     TInt digitsToMatch = DigitsToMatch();
       
   815  
       
   816     // We have only one address and one alias to put into the array
       
   817     CDesCArray* aliasArray = new ( ELeave )CDesCArrayFlat( 1 );
       
   818     CleanupStack::PushL( aliasArray ); 
       
   819 
       
   820     CDesCArray* realAddressArray = new ( ELeave )CDesCArrayFlat( 1 );
       
   821     CleanupStack::PushL( realAddressArray ); 
       
   822 
       
   823     realAddressArray->InsertL( 0, aAddress );
       
   824     
       
   825     // GetAliasForAllL opens contact matcher
       
   826     GetAliasForAllL( *realAddressArray, *aliasArray, aMaxLength, aFs );
       
   827     
       
   828     TInt size = aliasArray->MdcaCount();
       
   829     
       
   830     if ( size > 0 )
       
   831         {
       
   832         // only one item in our array
       
   833         aAlias.Copy( aliasArray->MdcaPoint( 0 ).Left( Min( aMaxLength, aAlias.MaxLength() ) ) );
       
   834         }
       
   835     
       
   836     CleanupStack::PopAndDestroy( realAddressArray );
       
   837     CleanupStack::PopAndDestroy( aliasArray );
       
   838     
       
   839     return;
       
   840     
       
   841     }
       
   842 
       
   843 
       
   844 // ---------------------------------------------------------
       
   845 // TMmsGenUtils::DoGetAliasL
       
   846 // ---------------------------------------------------------
       
   847 //
       
   848 void TMmsGenUtils::DoGetAliasL(
       
   849     const TDesC& aAddress, 
       
   850     TDes& aAlias, 
       
   851     TInt aMaxLength,
       
   852     CContactMatcher& aContactMatcher,
       
   853     TInt aDigitsToMatch  )
       
   854     {
       
   855     // It appears that with the new phonebook system with multiple phonebooks,
       
   856     // TContactItemId type id cannot be extracted.
       
   857     // The result contains MVPbkContactLink type objects.
       
   858     
       
   859     // The given descriptor has to be at least 14 in length
       
   860     // (otherwise this method would leave later)
       
   861     if( aAlias.MaxLength() < KMinAliasMaxLength )
       
   862         {
       
   863         User::Leave( KErrBadDescriptor );
       
   864         }
       
   865     
       
   866     // These should be inline with each other, but if necessary,
       
   867     // size down aMaxLength.
       
   868     // aMaxLength, however, can be smaller than the buffer
       
   869     if ( aMaxLength > aAlias.MaxLength() )
       
   870         {
       
   871         aMaxLength = aAlias.MaxLength();
       
   872         }
       
   873 
       
   874     if ( aMaxLength > 0 )
       
   875         {
       
   876         // set length of alias to 0
       
   877         // this can be used to determine if alias was found
       
   878         // contact id not needed or used
       
   879         aAlias.Zero();
       
   880         }
       
   881 
       
   882     // Convert to real address just in case. The address should be pure already,
       
   883     // but we are just being paranoid...
       
   884     
       
   885     TPtrC realAddress;
       
   886     realAddress.Set( PureAddress( aAddress, KSepaOpen, KSepaClose ) );
       
   887     CVPbkContactLinkArray* linkArray = CVPbkContactLinkArray::NewL();
       
   888     CleanupStack::PushL( linkArray );
       
   889     
       
   890     // Check if the address is phone number or EMail address
       
   891     if ( IsValidMMSPhoneAddress( realAddress, ETrue ) )
       
   892         {
       
   893         // Lookup the telephone number in the contact database
       
   894         // For numbers shorter than 7 digits, only exact matches are returned
       
   895         
       
   896         aContactMatcher.MatchPhoneNumberL( realAddress, aDigitsToMatch, 
       
   897 	        CVPbkPhoneNumberMatchStrategy::EVPbkMatchFlagsNone, *linkArray );
       
   898 
       
   899         // If more than one matches have been found,
       
   900         // the first one will be used.
       
   901         }
       
   902     else if ( IsValidEmailAddress( realAddress ) )
       
   903         {
       
   904         // Try to match with EMail address
       
   905                 
       
   906         TVPbkFieldVersitProperty prop;
       
   907         CVPbkFieldTypeRefsList* fieldTypes = CVPbkFieldTypeRefsList::NewL();
       
   908         CleanupStack::PushL( fieldTypes );
       
   909         
       
   910         const MVPbkFieldTypeList& fieldTypeList = aContactMatcher.FieldTypes();
       
   911         const MVPbkFieldType* foundType = NULL;
       
   912 
       
   913         prop.SetName( EVPbkVersitNameEMAIL );
       
   914 /*        
       
   915         // Remove code because matching matches properies, too.
       
   916         // We don't care about properties.
       
   917         
       
   918         // The phonebook should provide a function that allows mathcing name only
       
   919         foundType = fieldTypeList.FindMatch( prop, 0 );     
       
   920          
       
   921         if ( foundType )
       
   922             {
       
   923             fieldTypes->AppendL( *foundType );   
       
   924             }
       
   925 */
       
   926            
       
   927         // The field type matching does not work because it tries to match
       
   928         // parameters we are not interested in.
       
   929         // We try to generate a list that has all entries with versit type EMAIL
       
   930         
       
   931         TInt i;
       
   932         for ( i = 0; i < fieldTypeList.FieldTypeCount(); i++ )
       
   933             {
       
   934             foundType = &(fieldTypeList.FieldTypeAt( i ));
       
   935             if ( foundType->VersitProperties().Count() > 0
       
   936                 && foundType->VersitProperties()[0].Name() == prop.Name() )
       
   937                 {
       
   938                 fieldTypes->AppendL( *foundType );
       
   939                 }
       
   940             }
       
   941         
       
   942      
       
   943         // Here we stop at first match - email addresses should be unique
       
   944 		aContactMatcher.MatchDataL( realAddress, *fieldTypes, *linkArray );
       
   945 		CleanupStack::PopAndDestroy( fieldTypes );    
       
   946         }
       
   947     else
       
   948         {
       
   949         User::Leave( KErrNotFound );
       
   950         }
       
   951 
       
   952     TInt nameIndex = 0; //correct index if only one match is found
       
   953     if( linkArray->Count() == 0 )
       
   954         {
       
   955         Log( _L( "No match found" ) );
       
   956         User::Leave( KErrNotFound );        
       
   957         }
       
   958     else if( linkArray->Count() > 1 )
       
   959         {
       
   960         //Multiple matches found. Get the current store single match index if any.
       
   961         nameIndex = GetCurrentStoreIndexL( *linkArray );
       
   962         if( nameIndex == KErrMultipleMatchFound )
       
   963             {
       
   964             /* No unique match in current store, Hence show the name only if all the matches have 
       
   965              * identical names
       
   966              */
       
   967             if( ShowContactNameL( linkArray, nameIndex, aContactMatcher) == EFalse)
       
   968                 {
       
   969                 Log( _L( "No (Perfect) match found" ) );
       
   970                 User::Leave( KErrMultipleMatchFound );
       
   971                 }
       
   972             }
       
   973         }        
       
   974     
       
   975     // if not interested in alias, skip this
       
   976     if ( aMaxLength > 0 )
       
   977         {
       
   978         HBufC* alias = GetContactNameL( linkArray->At(nameIndex), aContactMatcher );
       
   979         if ( alias && alias->Des().Length() > 0 )
       
   980             {
       
   981             aAlias.Copy( alias->Des().Left( aMaxLength ) );
       
   982             }
       
   983         else
       
   984             {
       
   985             aAlias.Copy( TPtrC() );
       
   986             }
       
   987         delete alias;
       
   988         alias = NULL;
       
   989         // end of part skipped if not interested in alias
       
   990         }
       
   991 
       
   992     linkArray->ResetAndDestroy();
       
   993     CleanupStack::PopAndDestroy( linkArray );
       
   994     }
       
   995 
       
   996 // ---------------------------------------------------------
       
   997 // TMmsGenUtils::ConvertEscapesFromUri
       
   998 // ---------------------------------------------------------
       
   999 //
       
  1000 /*TInt TMmsGenUtils::ConvertEscapesFromUri(
       
  1001     const TDesC8& aInput,
       
  1002     TDes8& aOutput )
       
  1003     {
       
  1004     TInt retval = KErrNone;
       
  1005 
       
  1006     // Checkings
       
  1007     if( aOutput.MaxLength() < aInput.Length() )
       
  1008         {
       
  1009         retval = KErrArgument;
       
  1010         return retval;
       
  1011         }
       
  1012 
       
  1013     // Loop through aInput and find the number of '%' chars
       
  1014     for( TUint8 i = 0; i < aInput.Length(); i++ )
       
  1015         {
       
  1016         if( aInput[i] == 0x25 ) // '%' found
       
  1017             {
       
  1018             // Store the chars representing the hexvalue
       
  1019             TUint8 highbyte = aInput[i+1];
       
  1020             TUint8 lowbyte  = aInput[i+2];
       
  1021 
       
  1022             // Check the bytes
       
  1023             TUint8 result = 0;
       
  1024             
       
  1025             // Map the highbyte to correct upperbits of result
       
  1026             // (In order to save code lines and keep code readable,
       
  1027             //  the following does not follow the coding convention.)
       
  1028             if(highbyte == 0x30) result = 0x0;
       
  1029             if(highbyte == 0x31) result = 0x1;
       
  1030             if(highbyte == 0x32) result = 0x2;
       
  1031             if(highbyte == 0x33) result = 0x3;
       
  1032             if(highbyte == 0x34) result = 0x4;
       
  1033             if(highbyte == 0x35) result = 0x5;
       
  1034             if(highbyte == 0x36) result = 0x6;
       
  1035             if(highbyte == 0x37) result = 0x7;
       
  1036             if(highbyte == 0x38) result = 0x8;
       
  1037             if(highbyte == 0x39) result = 0x9;
       
  1038             if(highbyte == 0x41 || highbyte == 0x61) result = 0xA;
       
  1039             if(highbyte == 0x42 || highbyte == 0x62) result = 0xB;
       
  1040             if(highbyte == 0x43 || highbyte == 0x63) result = 0xC;
       
  1041             if(highbyte == 0x44 || highbyte == 0x64) result = 0xD;
       
  1042             if(highbyte == 0x45 || highbyte == 0x65) result = 0xE;
       
  1043             if(highbyte == 0x46 || highbyte == 0x66) result = 0xF;
       
  1044 
       
  1045             if( ( result == 0 ) && ( highbyte != 0x30 ) )
       
  1046                 {
       
  1047                 retval = KErrArgument;
       
  1048                 }
       
  1049             result <<= 4;
       
  1050 
       
  1051             // Map the lowbyte to correct lowerbits of result
       
  1052             // (In order to save code lines and keep code readable,
       
  1053             //  the following does not follow the coding convention.)
       
  1054             if(lowbyte == 0x30) result += 0x0;
       
  1055             if(lowbyte == 0x31) result += 0x1;
       
  1056             if(lowbyte == 0x32) result += 0x2;
       
  1057             if(lowbyte == 0x33) result += 0x3;
       
  1058             if(lowbyte == 0x34) result += 0x4;
       
  1059             if(lowbyte == 0x35) result += 0x5;
       
  1060             if(lowbyte == 0x36) result += 0x6;
       
  1061             if(lowbyte == 0x37) result += 0x7;
       
  1062             if(lowbyte == 0x38) result += 0x8;
       
  1063             if(lowbyte == 0x39) result += 0x9;
       
  1064             if(lowbyte == 0x41 || lowbyte == 0x61) result += 0xA;
       
  1065             if(lowbyte == 0x42 || lowbyte == 0x62) result += 0xB;
       
  1066             if(lowbyte == 0x43 || lowbyte == 0x63) result += 0xC;
       
  1067             if(lowbyte == 0x44 || lowbyte == 0x64) result += 0xD;
       
  1068             if(lowbyte == 0x45 || lowbyte == 0x65) result += 0xE;
       
  1069             if(lowbyte == 0x46 || lowbyte == 0x66) result += 0xF;
       
  1070             
       
  1071             if( ( ( result & 0xF ) == 0 ) && ( lowbyte != 0x30 ) ) 
       
  1072                 {
       
  1073                 retval = KErrArgument;
       
  1074                 }
       
  1075 
       
  1076             // Abort if error has occurred
       
  1077             if( retval != KErrNone )
       
  1078                 {
       
  1079                 return retval;
       
  1080                 }
       
  1081 
       
  1082             // Insert the value to output parameter
       
  1083             aOutput.Append( result );
       
  1084             i += 2; // Jumping over the two chars already handled
       
  1085             }
       
  1086         else
       
  1087             {
       
  1088             aOutput.Append( aInput[i] );
       
  1089             }
       
  1090         } // for
       
  1091     return retval;
       
  1092     }*/
       
  1093 
       
  1094 // ---------------------------------------------------------
       
  1095 // TMmsGenUtils::DecodeMessageHeader
       
  1096 // ---------------------------------------------------------
       
  1097 //
       
  1098 EXPORT_C void TMmsGenUtils::DecodeAndConvertMessageHeaderL(
       
  1099             const TDesC8& aInput,
       
  1100             TDes16& aOutput,
       
  1101             RFs& aFs
       
  1102             )
       
  1103     {
       
  1104     // Create CCnvCharacterSetConverter
       
  1105     CCnvCharacterSetConverter* characterSetConverter
       
  1106         = CCnvCharacterSetConverter::NewL();
       
  1107     CleanupStack::PushL( characterSetConverter );
       
  1108 
       
  1109     // Create CImConvertCharconv 
       
  1110     // (this is a wrapper for the actual char converter)
       
  1111     CImConvertCharconv* converter 
       
  1112         = CImConvertCharconv::NewL( *characterSetConverter, aFs );
       
  1113     CleanupStack::PushL( converter );
       
  1114 
       
  1115     // Create CImConvertHeader that actually does the task
       
  1116     CImConvertHeader* headerConverter = CImConvertHeader::NewL( *converter );
       
  1117     CleanupStack::PushL( headerConverter );
       
  1118 
       
  1119     // Perform the decoding and charset conversion
       
  1120     headerConverter->DecodeHeaderFieldL( aInput, aOutput );
       
  1121 
       
  1122     // Clean up and return
       
  1123     CleanupStack::PopAndDestroy( headerConverter );
       
  1124     CleanupStack::PopAndDestroy( converter );
       
  1125     CleanupStack::PopAndDestroy( characterSetConverter );
       
  1126     }
       
  1127     
       
  1128 
       
  1129 // ---------------------------------------------------------
       
  1130 //
       
  1131 // Return the free space in a drive identified by the aDrive parameter
       
  1132 // and the media type of the drive.
       
  1133 //
       
  1134 // ---------------------------------------------------------
       
  1135 static TInt64 FreeSpaceL(RFs* aFs, TInt aDrive, TMediaType& aMediaType)
       
  1136 {
       
  1137     RFs fs;
       
  1138     TInt err = KErrNone;
       
  1139 
       
  1140     if ( !aFs )
       
  1141         User::LeaveIfError(fs.Connect());  // Create temp session
       
  1142     else
       
  1143         fs = *aFs;
       
  1144 
       
  1145     TVolumeInfo vinfo;
       
  1146     err = fs.Volume(vinfo, aDrive);
       
  1147 
       
  1148     TDriveInfo driveInfo;
       
  1149     TInt errorCode = fs.Drive( driveInfo, aDrive );
       
  1150     if ( errorCode == KErrNone )
       
  1151         {
       
  1152         aMediaType = driveInfo.iType;
       
  1153         }
       
  1154     else
       
  1155         {
       
  1156         aMediaType = EMediaUnknown;
       
  1157         }
       
  1158 
       
  1159     if ( !aFs )
       
  1160         fs.Close(); // Close temp. session
       
  1161 
       
  1162     if (err != KErrNone)
       
  1163         {
       
  1164         User::LeaveIfError(err);
       
  1165         }
       
  1166 
       
  1167     return TInt64(vinfo.iFree);
       
  1168 }
       
  1169 
       
  1170 // ---------------------------------------------------------
       
  1171 // TMmsGenUtils::DiskSpaceBelowCriticalLevelL
       
  1172 // ---------------------------------------------------------
       
  1173 //
       
  1174 EXPORT_C TBool TMmsGenUtils::DiskSpaceBelowCriticalLevelL(
       
  1175     RFs* aFs, TInt aBytesToWrite, TInt aDrive)
       
  1176     {
       
  1177     TInt64 free;
       
  1178     TInt64 criticalLevel;
       
  1179     CRepository* repository = NULL;
       
  1180     TMediaType mediaType = EMediaNotPresent;
       
  1181     free = FreeSpaceL(aFs, aDrive, mediaType);
       
  1182 
       
  1183     TInt64 newFree = free - (TInt64)aBytesToWrite;
       
  1184 
       
  1185     // Querying Critical Level from CenRep
       
  1186     TInt error = KErrNone;
       
  1187     TInt level = 0;
       
  1188     TRAP( error, repository = CRepository::NewL( KCRUidUiklaf ) );  
       
  1189     if ( error == KErrNone)
       
  1190     	{
       
  1191     	error = repository->Get( KUikOODDiskCriticalThreshold, level );
       
  1192         delete repository;
       
  1193         if( error != KErrNone )
       
  1194             {
       
  1195             // Default value 0 means "anything goes"
       
  1196             level = 0;
       
  1197     	    }
       
  1198     	}
       
  1199     	
       
  1200 #ifdef _DEBUG
       
  1201     if ( error != KErrNone )
       
  1202         {
       
  1203         _LIT( KMmsCriticalSpaceError, "- Get critical disk space threshold returned error %d" );
       
  1204         Log( KMmsCriticalSpaceError, error );
       
  1205         }
       
  1206     else
       
  1207         {
       
  1208         _LIT( KMmsCriticalSpaceLog, "- Critical level: %d, free space: %d" );
       
  1209         Log( KMmsCriticalSpaceLog, level, newFree );
       
  1210         }
       
  1211 #endif    
       
  1212 
       
  1213     criticalLevel = level;
       
  1214     return newFree <= criticalLevel;
       
  1215     }
       
  1216 
       
  1217 // ---------------------------------------------------------
       
  1218 // TMmsGenUtils::NetworkOperationsAllowed()
       
  1219 //
       
  1220 // ---------------------------------------------------------
       
  1221 //
       
  1222 EXPORT_C TBool TMmsGenUtils::NetworkOperationsAllowed()
       
  1223     {
       
  1224     TBool networkAllowed = ETrue; // optimist
       
  1225     // If there is no such key, we will continue normally.
       
  1226     // This means that in a system where online/offline mode switching
       
  1227     // is not supported, we behave as we were always online
       
  1228     
       
  1229     CRepository* repository = NULL;
       
  1230     TInt error = KErrNone;
       
  1231     TInt value = ECoreAppUIsNetworkConnectionAllowed;
       
  1232     TRAP( error, repository = CRepository::NewL( KCRUidCoreApplicationUIs ) );
       
  1233     if( error == KErrNone )
       
  1234         {
       
  1235         repository->Get( KCoreAppUIsNetworkConnectionAllowed, value );
       
  1236         delete repository;
       
  1237         repository = NULL;
       
  1238         if ( value == ECoreAppUIsNetworkConnectionNotAllowed )
       
  1239             {
       
  1240             networkAllowed = EFalse;
       
  1241             }
       
  1242         }
       
  1243 
       
  1244     return networkAllowed;
       
  1245     }
       
  1246     
       
  1247 // ---------------------------------------------------------
       
  1248 // TMmsGenUtils::GetLoggingSettings
       
  1249 // ---------------------------------------------------------
       
  1250 //
       
  1251 EXPORT_C void TMmsGenUtils::GetLoggingSettings( TBool& aDecodeLoggingOn, TBool& aDumpOn )
       
  1252     {
       
  1253     // Consult CenRep for decodelogging and binarydump settings
       
  1254     CRepository* repository = NULL;
       
  1255     // default values are false if not found in repository
       
  1256     aDecodeLoggingOn = EFalse;
       
  1257     aDumpOn = EFalse;
       
  1258     
       
  1259     TInt retval = KErrNone;
       
  1260     TRAP_IGNORE( 
       
  1261         {
       
  1262         repository = CRepository::NewL( KUidMmsServerMtm );
       
  1263         CleanupStack::PushL( repository );
       
  1264         TInt temp = 0;
       
  1265         retval = repository->Get( KMmsEngineDecodeLog, temp );
       
  1266         if( retval == KErrNone )
       
  1267             {
       
  1268             aDecodeLoggingOn = ( temp != 0 );
       
  1269             }
       
  1270         retval = repository->Get( KMmsEngineBinaryDump, temp );
       
  1271         if( retval == KErrNone )
       
  1272             {
       
  1273             aDumpOn = ( temp != 0 );
       
  1274             }
       
  1275         CleanupStack::PopAndDestroy( repository );
       
  1276         repository = NULL;
       
  1277         }
       
  1278         );
       
  1279 #ifndef __WINS__
       
  1280     // turn decode logging on in armv5 version
       
  1281     // Release versions never log anyway
       
  1282     aDecodeLoggingOn = ETrue;
       
  1283 #endif            
       
  1284     }
       
  1285     
       
  1286 // ---------------------------------------------------------
       
  1287 // TMmsGenUtils::AddAttributeL
       
  1288 //
       
  1289 // ---------------------------------------------------------
       
  1290 //
       
  1291 EXPORT_C void TMmsGenUtils::AddAttributeL(
       
  1292             const TDesC& aName,
       
  1293             const TDesC& aValue,
       
  1294             CDesCArray& aAttributeList )
       
  1295     {
       
  1296     TInt position = FindAttributePosition( aName, aAttributeList );
       
  1297     TInt error = KErrNone;
       
  1298     
       
  1299     if ( position == KErrNotFound )
       
  1300         {
       
  1301         // not found, append to end
       
  1302         aAttributeList.AppendL( aName );
       
  1303         TRAP ( error, aAttributeList.AppendL( aValue ) );
       
  1304         if ( error != KErrNone )
       
  1305             {
       
  1306             // could not add value, delete name, too.
       
  1307             // It is the last item in the list
       
  1308             aAttributeList.Delete( aAttributeList.MdcaCount() - 1 );
       
  1309             }
       
  1310         }
       
  1311     else
       
  1312         {
       
  1313         // delete old value and insert new one
       
  1314         aAttributeList.Delete( position + 1 );
       
  1315         TRAP ( error, aAttributeList.InsertL( position + 1,  aValue ) );
       
  1316         if ( error != KErrNone )
       
  1317             {
       
  1318             // could not add value, delete name, too.
       
  1319             aAttributeList.Delete( position );
       
  1320             }
       
  1321         }
       
  1322     User::LeaveIfError( error );        
       
  1323     
       
  1324     }
       
  1325     
       
  1326 // ---------------------------------------------------------
       
  1327 // TMmsGenUtils::GetAttributeL
       
  1328 //
       
  1329 // ---------------------------------------------------------
       
  1330 //
       
  1331 EXPORT_C TPtrC TMmsGenUtils::GetAttributeL(
       
  1332             const TDesC& aName,
       
  1333             const CDesCArray& aAttributeList )
       
  1334     {
       
  1335     TInt position = FindAttributePosition( aName, aAttributeList );
       
  1336     
       
  1337     if ( position == KErrNotFound )
       
  1338         {
       
  1339         User::Leave( KErrNotFound );
       
  1340         }
       
  1341     return ( aAttributeList.MdcaPoint( position + 1 ) );
       
  1342     }
       
  1343 
       
  1344 // ---------------------------------------------------------
       
  1345 // TMmsGenUtils::FindAttribute
       
  1346 //
       
  1347 // ---------------------------------------------------------
       
  1348 //
       
  1349 EXPORT_C TBool TMmsGenUtils::FindAttribute(
       
  1350             const TDesC& aName,
       
  1351             const CDesCArray& aAttributeList )
       
  1352     {
       
  1353     if ( FindAttributePosition( aName, aAttributeList ) == KErrNotFound )
       
  1354         {
       
  1355         return EFalse;
       
  1356         }
       
  1357     return ETrue;
       
  1358     }
       
  1359 
       
  1360 // ---------------------------------------------------------
       
  1361 // TMmsGenUtils::DeleteAttribute
       
  1362 //
       
  1363 // ---------------------------------------------------------
       
  1364 //
       
  1365 EXPORT_C void TMmsGenUtils::DeleteAttribute(
       
  1366             const TDesC& aName,
       
  1367             CDesCArray& aAttributeList )
       
  1368     {
       
  1369     TInt position = FindAttributePosition( aName, aAttributeList );
       
  1370     
       
  1371     if ( position == KErrNotFound )
       
  1372         {
       
  1373         return; // not found, nothing to delete
       
  1374         }
       
  1375     // delete both name and value
       
  1376     aAttributeList.Delete( position, 2 );
       
  1377     }
       
  1378 
       
  1379 // ---------------------------------------------------------
       
  1380 // TMmsGenUtils::FindAttributePosition
       
  1381 //
       
  1382 // ---------------------------------------------------------
       
  1383 //
       
  1384 TInt TMmsGenUtils::FindAttributePosition(
       
  1385            const TDesC& aName,
       
  1386             const CDesCArray& aAttributeList )
       
  1387     {
       
  1388     TInt position = KErrNotFound;
       
  1389     
       
  1390     TInt i;
       
  1391     
       
  1392     for ( i = 0; i < aAttributeList.MdcaCount() - 1; i+=2 )
       
  1393         {
       
  1394         //It is not possible to index out of bound (codescanner warning)
       
  1395         if ( aAttributeList[i].Compare( aName ) == 0 )
       
  1396             {
       
  1397             position = i;
       
  1398             }
       
  1399         }
       
  1400     return position;
       
  1401     }
       
  1402     
       
  1403     
       
  1404 // ---------------------------------------------------------
       
  1405 // TMmsGenUtils::DigitsToMatch
       
  1406 //
       
  1407 // ---------------------------------------------------------
       
  1408 TInt TMmsGenUtils::DigitsToMatch()
       
  1409     {
       
  1410     // Find the number of digits to be used when matching phone numbers
       
  1411     TInt digitsToMatch( KMmsNumberOfDigitsToMatch );
       
  1412 
       
  1413     CRepository* repository = NULL;
       
  1414     TRAPD( err, repository = CRepository::NewL( KCRUidTelConfiguration ));
       
  1415     if ( err == KErrNone )
       
  1416         {
       
  1417         err = repository->Get( KTelMatchDigits , digitsToMatch );
       
  1418         delete repository;
       
  1419         if( err != KErrNone )
       
  1420             {
       
  1421             digitsToMatch=KMmsNumberOfDigitsToMatch;
       
  1422             }
       
  1423     	}
       
  1424     return digitsToMatch;
       
  1425     }
       
  1426     
       
  1427 // ---------------------------------------------------------
       
  1428 // TMmsGenUtils::OpenAllStoresL
       
  1429 //
       
  1430 // ---------------------------------------------------------
       
  1431 CContactMatcher* TMmsGenUtils::OpenAllStoresL( RFs& aFs )
       
  1432     {
       
  1433     // Use contact wrapper to open all databases
       
  1434     CContactMatcher* contactMatcher = CContactMatcher::NewL( &aFs );
       
  1435     CleanupStack::PushL( contactMatcher );
       
  1436     
       
  1437     contactMatcher->OpenDefaultMatchStoresL();    
       
  1438     
       
  1439     CleanupStack::Pop( contactMatcher );
       
  1440     return contactMatcher;
       
  1441     }
       
  1442 
       
  1443 // -----------------------------------------------------------------------------
       
  1444 // TMmsGenUtils::GetContactNameL
       
  1445 // -----------------------------------------------------------------------------
       
  1446 //
       
  1447 HBufC* TMmsGenUtils::GetContactNameL(
       
  1448         const MVPbkContactLink& aContactLink,
       
  1449         CContactMatcher &aContactMatcher)
       
  1450     {
       
  1451     Log(_L( "- TMmsGenUtils::GetContactNameL  -> start" ) );
       
  1452     MVPbkStoreContact* tempContact;
       
  1453     aContactMatcher.GetStoreContactL(aContactLink, &tempContact);
       
  1454     tempContact->PushL();
       
  1455     
       
  1456     MVPbkStoreContactFieldCollection& coll = tempContact->Fields();
       
  1457     HBufC* nameBuff = aContactMatcher.GetNameL( coll );
       
  1458     
       
  1459     CleanupStack::PopAndDestroy(tempContact); // tempContact
       
  1460     
       
  1461     Log( _L( "- TMmsGenUtils::GetContactNameL <- end" ) );
       
  1462     return nameBuff;
       
  1463     }
       
  1464 
       
  1465 // -----------------------------------------------------------------------------
       
  1466 // TMmsGenUtils::GetContactNameInLowerCaseL
       
  1467 // -----------------------------------------------------------------------------
       
  1468 //
       
  1469 HBufC* TMmsGenUtils::GetContactNameInLowerCaseL(
       
  1470         const MVPbkContactLink& aContactLink,
       
  1471         CContactMatcher &aContactMatcher)
       
  1472     {
       
  1473     //get the name 
       
  1474     HBufC* nameBuff =  GetContactNameL( aContactLink, aContactMatcher );
       
  1475     CleanupStack::PushL( nameBuff );
       
  1476        
       
  1477     //Convert to lower case , since this name buffer is used to compare names.    
       
  1478     HBufC* nameInLowerCase = HBufC::NewL( nameBuff->Length() + 2 );
       
  1479     nameInLowerCase->Des().CopyLC( *nameBuff );
       
  1480     
       
  1481     CleanupStack::PopAndDestroy( nameBuff ); // nameBuff
       
  1482     return nameInLowerCase;
       
  1483     }
       
  1484 
       
  1485 // -----------------------------------------------------------------------------
       
  1486 // TMmsGenUtils::ShowContactNameL
       
  1487 // -----------------------------------------------------------------------------
       
  1488 //
       
  1489 TBool TMmsGenUtils::ShowContactNameL(
       
  1490         CVPbkContactLinkArray* aLinkArray,
       
  1491         TInt &aNameIndex,
       
  1492         CContactMatcher &aContactMatcher)
       
  1493     {
       
  1494     Log( _L("- TMmsGenUtils::ShowContactName -> start") );
       
  1495     Log( _L("Contact Match statistics to follow..." ) );
       
  1496     Log( _L("Match count: %d"), aLinkArray->Count() );
       
  1497     /* TODO:: compare the names upto standard
       
  1498      * 1. if all the names are same - display the name 
       
  1499      *    eg: "abcdef xyz" && "abcdef xyz"
       
  1500      * 2. find min name legth among all,(if ONLY Part-match is needed )
       
  1501      *    if this length is > standard length and matches upto standard length - display the larger name.
       
  1502      *    eg: abcdef xyz123,  abcdef xyz12, abcdef xyz and std length is 10,
       
  1503      *        since match upto 10 chars is fine, display abcdef xyz123
       
  1504      * 3. in any other case do not show name
       
  1505      *    eg: abcdef xyz , abcde xyz
       
  1506      *        abcdef xyz , abcdef xy
       
  1507      *        abcdef xyz , abcde
       
  1508      */
       
  1509     TInt i, minLength = 999, maxLength = 0, length = 0, maxLengthIndex = 0, stdLength = 14;
       
  1510     TBool retVal = ETrue ;
       
  1511     
       
  1512     for( i = 0 ; i < aLinkArray->Count(); i++ )
       
  1513         {
       
  1514         HBufC* alias = GetContactNameL( aLinkArray->At(i), aContactMatcher );
       
  1515         Log( _L(":-> %s" ), alias->Des().PtrZ());
       
  1516         length = alias->Des().Length();
       
  1517         if(minLength > length)
       
  1518             {
       
  1519             minLength = length;
       
  1520             }
       
  1521         if(maxLength < length)
       
  1522             {
       
  1523             maxLength = length;
       
  1524             maxLengthIndex = i;
       
  1525             }
       
  1526         delete alias;
       
  1527         alias = NULL;
       
  1528         }
       
  1529     
       
  1530     Log( _L( "Contact Lengths: Std Length  : %d\n MinLength   : %d\n MaxLength   : %d\n MaxLen index: %d" ),
       
  1531             stdLength,
       
  1532             minLength,
       
  1533             maxLength,
       
  1534             maxLengthIndex);
       
  1535     
       
  1536     if(minLength != maxLength)
       
  1537         {
       
  1538         //complete length match not possible
       
  1539         retVal = EFalse;
       
  1540         
       
  1541         /* NOTE:
       
  1542          * Uncomment below code if partial length(upto stdLength) match is sufficient, 
       
  1543          * ensure stdLength is correct
       
  1544          */
       
  1545         /*
       
  1546         if(minLength < stdLength)
       
  1547             {
       
  1548             retVal = EFalse;
       
  1549             }
       
  1550         */
       
  1551         }
       
  1552     
       
  1553     if( retVal )
       
  1554         {
       
  1555         TInt ret;
       
  1556         HBufC* longestName = GetContactNameInLowerCaseL( aLinkArray->At(maxLengthIndex), aContactMatcher );
       
  1557         Log( _L( "Longest name:-> %s" ), longestName->Des().PtrZ());
       
  1558         for ( i = 0; i < aLinkArray->Count() && retVal; i++ )
       
  1559             {
       
  1560             HBufC* nameI = GetContactNameInLowerCaseL( aLinkArray->At(i), aContactMatcher );
       
  1561             Log( _L( "compared with -> %s" ), nameI->Des().PtrZ());
       
  1562             ret = longestName->Find(nameI->Des());
       
  1563             if(ret == KErrNotFound || ret != 0)
       
  1564                 {
       
  1565                 Log( _L( "Part/Full Match error/offset: %d" ), ret);
       
  1566                 retVal = EFalse;
       
  1567                 }
       
  1568             delete nameI;
       
  1569             nameI = NULL;
       
  1570            }
       
  1571         delete longestName;
       
  1572         longestName = NULL;
       
  1573         }
       
  1574 
       
  1575     aNameIndex = maxLengthIndex;
       
  1576 
       
  1577     Log( _L( "Final Match result : %d\n Final Match index  : %d" ), retVal, maxLengthIndex);
       
  1578     Log( _L( "- TMmsGenUtils::ShowContactName <- end" ) );
       
  1579     
       
  1580     return retVal;
       
  1581     }
       
  1582     
       
  1583 // -----------------------------------------------------------------------------
       
  1584 // TMmsGenUtils::GetCurrentStoreIndexL
       
  1585 // -----------------------------------------------------------------------------
       
  1586 //
       
  1587 TInt TMmsGenUtils::GetCurrentStoreIndexL( CVPbkContactLinkArray& aLinkArray )
       
  1588     {
       
  1589     TInt curStoreIndex( KErrMultipleMatchFound );
       
  1590     TInt curStoreMatchCount = 0;
       
  1591     RArray<TInt> otherStoreMatchIndices;
       
  1592     CleanupClosePushL( otherStoreMatchIndices );
       
  1593     
       
  1594     //Get the current configured contact store array(s)
       
  1595     CPbk2StoreConfiguration* storeConfiguration = CPbk2StoreConfiguration::NewL();
       
  1596     CleanupStack::PushL( storeConfiguration );
       
  1597     CVPbkContactStoreUriArray* currStoreArray = storeConfiguration->CurrentConfigurationL();
       
  1598     CleanupStack::PopAndDestroy(storeConfiguration);
       
  1599 
       
  1600     if ( currStoreArray )
       
  1601         {
       
  1602         /* Contact's store is compared against user selected stores.
       
  1603          * If contact is from such store, found index is incremented
       
  1604          * else, other store contact indices are populated into array for further use
       
  1605          */
       
  1606         for ( TInt i = 0; i < aLinkArray.Count(); i++ )
       
  1607             {
       
  1608             TVPbkContactStoreUriPtr uri = aLinkArray.At(i).ContactStore().StoreProperties().Uri();
       
  1609             if ( currStoreArray->IsIncluded( uri ) )
       
  1610                 {
       
  1611                 // Set index to found contact and increment the count.
       
  1612                 curStoreIndex = i;
       
  1613                 curStoreMatchCount++;
       
  1614                 }
       
  1615             else
       
  1616                 {
       
  1617                 otherStoreMatchIndices.AppendL(i);
       
  1618                 }
       
  1619             }
       
  1620         
       
  1621         delete currStoreArray;    
       
  1622         if ( curStoreMatchCount > 1)
       
  1623             {
       
  1624             /* Multiple matches found from current user selected store(s) 
       
  1625              * Delete match from other stores in aLinkArray. New aLinkArray should only contain 
       
  1626              * current store contact matches, so that next level pruning can be done(e.g, names can be 
       
  1627              * compared and displayed if they are identical).
       
  1628              */
       
  1629             for(TInt i = otherStoreMatchIndices.Count() - 1; i >= 0; i--)
       
  1630                 {
       
  1631                 aLinkArray.Delete( otherStoreMatchIndices[i] );
       
  1632                 }
       
  1633             curStoreIndex = KErrMultipleMatchFound;
       
  1634             }
       
  1635         }
       
  1636     CleanupStack::PopAndDestroy( &otherStoreMatchIndices );
       
  1637     return curStoreIndex;
       
  1638     }
       
  1639 
       
  1640 // ================= OTHER EXPORTED FUNCTIONS ==============
       
  1641 
       
  1642 //  End of File