webengine/widgetinstaller/Src/WidgetBackupRegistryXml.cpp
changeset 10 a359256acfc6
child 11 c8a366e56285
equal deleted inserted replaced
5:10e98eab6f85 10:a359256acfc6
       
     1 /*
       
     2 * Copyright (c) 2008 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 the License "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:  Processes registry persistent data in XML.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <f32file.h>
       
    21 #include <libxml2_globals.h>
       
    22 #include <libxml2_parser.h>
       
    23 #include <charconv.h>
       
    24 #include "WidgetBackupRegistryXml.h"
       
    25 
       
    26 _LIT( KPropertyListVersion,  "PropertyListVersion" );
       
    27 _LIT( KBundleIdentifier,     "BundleIdentifier" );
       
    28 _LIT( KBundleName,           "BundleName" );
       
    29 _LIT( KBundleDisplayName,    "BundleDisplayName" );
       
    30 _LIT( KMainHTML,             "MainHTML" );
       
    31 _LIT( KBundleShortVersion,   "BundleShortVersion" );
       
    32 _LIT( KBundleVersion,        "BundleVersion" );
       
    33 _LIT( KHeight,               "Height" );
       
    34 _LIT( KWidth,                "Width" );
       
    35 _LIT( KAllowFullAccess,      "AllowFullAccess" );
       
    36 _LIT( KAllowNetworkAccess,   "AllowNetworkAccess" );
       
    37 _LIT( KDriveName,            "DriveName" );
       
    38 _LIT( KBasePath,             "BasePath" );
       
    39 _LIT( KIconPath,             "IconPath" );
       
    40 _LIT( KUrl,                  "Url" );
       
    41 _LIT( KFileSize,             "FileSize" );
       
    42 _LIT( KUid,                  "Uid" );
       
    43 _LIT( KNokiaWidget,          "NokiaWidget" );
       
    44 _LIT( KMiniViewEnabled,      "MiniViewEnabled" );
       
    45 _LIT( KBlanketPermGranted,   "BlanketPermissionGranted" );         // optional
       
    46 
       
    47 // ============================================================================
       
    48 // CWidgetBackupRegistryXml::NewL()
       
    49 // two-phase constructor
       
    50 //
       
    51 // @since 5.0
       
    52 // ============================================================================
       
    53 //
       
    54 CWidgetBackupRegistryXml* CWidgetBackupRegistryXml::NewL()
       
    55     {
       
    56     CWidgetBackupRegistryXml *self = new (ELeave) CWidgetBackupRegistryXml();
       
    57     CleanupStack::PushL( self );
       
    58     self->ConstructL();
       
    59     CleanupStack::Pop();
       
    60     return self;
       
    61     }
       
    62 
       
    63 // ============================================================================
       
    64 // CWidgetBackupRegistryXml::CWidgetBackupRegistryXml()
       
    65 // C++ constructor
       
    66 //
       
    67 // @since 5.0
       
    68 // ============================================================================
       
    69 //
       
    70 CWidgetBackupRegistryXml::CWidgetBackupRegistryXml() : iProperties(EWidgetPropertyIdCount)
       
    71     {
       
    72     }
       
    73 
       
    74 // ============================================================================
       
    75 // CWidgetUIConfigHandler::ConstructL()
       
    76 // C++ constructor
       
    77 //
       
    78 // @since 5.0
       
    79 // ============================================================================
       
    80 //
       
    81 void CWidgetBackupRegistryXml::ConstructL()
       
    82     {
       
    83     TWidgetProperty property;
       
    84 
       
    85     property.id = EWidgetPropertyListVersion;
       
    86     property.name.Set( KPropertyListVersion );
       
    87     property.type = EWidgetPropTypeInt;
       
    88     iProperties.AppendL(property);
       
    89     //
       
    90     property.id = EBundleIdentifier;
       
    91     property.name.Set( KBundleIdentifier );
       
    92     property.type = EWidgetPropTypeString;
       
    93     iProperties.AppendL(property);
       
    94     //
       
    95     property.id = EBundleName;
       
    96     property.name.Set( KBundleName );
       
    97     property.type = EWidgetPropTypeString;
       
    98     iProperties.AppendL(property);
       
    99     //
       
   100     property.id = EBundleDisplayName;
       
   101     property.name.Set( KBundleDisplayName );
       
   102     property.type = EWidgetPropTypeString;
       
   103     iProperties.AppendL(property);
       
   104     //
       
   105     property.id = EMainHTML;
       
   106     property.name.Set( KMainHTML );
       
   107     property.type = EWidgetPropTypeString;
       
   108     iProperties.AppendL(property);
       
   109     //
       
   110     property.id = EBundleShortVersion;
       
   111     property.name.Set( KBundleShortVersion );
       
   112     property.type = EWidgetPropTypeString;
       
   113     iProperties.AppendL(property);
       
   114     //
       
   115     property.id = EBundleVersion;
       
   116     property.name.Set( KBundleVersion );
       
   117     property.type = EWidgetPropTypeString;
       
   118     iProperties.AppendL(property);
       
   119     //
       
   120     property.id = EHeight;
       
   121     property.name.Set( KHeight );
       
   122     property.type = EWidgetPropTypeInt;
       
   123     iProperties.AppendL(property);
       
   124     //
       
   125     property.id = EWidth;
       
   126     property.name.Set( KWidth );
       
   127     property.type = EWidgetPropTypeInt;
       
   128     iProperties.AppendL(property);
       
   129     //
       
   130     property.id = EAllowFullAccess;
       
   131     property.name.Set( KAllowFullAccess );
       
   132     property.type = EWidgetPropTypeInt;
       
   133     iProperties.AppendL(property);
       
   134     //
       
   135     property.id = EAllowNetworkAccess;
       
   136     property.name.Set( KAllowNetworkAccess );
       
   137     property.type = EWidgetPropTypeInt;
       
   138     iProperties.AppendL(property);
       
   139     //
       
   140     property.id = EDriveName;
       
   141     property.name.Set( KDriveName );
       
   142     property.type = EWidgetPropTypeString;
       
   143     iProperties.AppendL(property);
       
   144     //
       
   145     property.id = EBasePath;
       
   146     property.name.Set( KBasePath );
       
   147     property.type = EWidgetPropTypeString;
       
   148     iProperties.AppendL(property);
       
   149     //
       
   150     property.id = EIconPath;
       
   151     property.name.Set( KIconPath );
       
   152     property.type = EWidgetPropTypeString;
       
   153     iProperties.AppendL(property);
       
   154     //
       
   155     property.id = EUrl;
       
   156     property.name.Set( KUrl );
       
   157     property.type = EWidgetPropTypeString;
       
   158     iProperties.AppendL(property);
       
   159     //
       
   160     property.id = EFileSize;
       
   161     property.name.Set( KFileSize );
       
   162     property.type = EWidgetPropTypeInt;
       
   163     iProperties.AppendL(property);
       
   164     //
       
   165     property.id = EUid;
       
   166     property.name.Set( KUid );
       
   167     property.type = EWidgetPropTypeInt; // not TUid
       
   168     iProperties.AppendL(property);
       
   169     //
       
   170     property.id = ENokiaWidget;
       
   171     property.name.Set( KNokiaWidget );
       
   172     property.type = EWidgetPropTypeInt;
       
   173     iProperties.AppendL(property);
       
   174     //
       
   175     property.id = EMiniViewEnable;
       
   176     property.name.Set( KMiniViewEnabled );
       
   177     property.type = EWidgetPropTypeInt;
       
   178     iProperties.AppendL(property);
       
   179     //
       
   180     property.id = EBlanketPermGranted;
       
   181     property.name.Set( KBlanketPermGranted );
       
   182     property.type = EWidgetPropTypeInt;
       
   183     iProperties.AppendL(property);
       
   184     }
       
   185 
       
   186 // ============================================================================
       
   187 // CWidgetBackupRegistryXml::~CWidgetBackupRegistryXml()
       
   188 // destructor
       
   189 //
       
   190 // @since 5.0
       
   191 // ============================================================================
       
   192 //
       
   193 CWidgetBackupRegistryXml::~CWidgetBackupRegistryXml()
       
   194     {
       
   195     for (TInt i = iProperties.Count() - 1; i >= EWidgetPropertyIdCount; i--)
       
   196         {
       
   197         TUint16* name = const_cast<TUint16*>(iProperties[i].name.Ptr());
       
   198         iProperties[i].name.Set(KNullDesC);
       
   199         delete [] name;
       
   200         }
       
   201     iProperties.Reset();
       
   202     iProperties.Close();
       
   203     }
       
   204 
       
   205 // ============================================================================
       
   206 // Get the property descriptiont by finding entry for name.
       
   207 //
       
   208 // @param aPropName The name of the prop: <prop>propName</prop>
       
   209 // @since 5.0
       
   210 // @return prop type.
       
   211 // ============================================================================
       
   212 //
       
   213 TInt CWidgetBackupRegistryXml::GetPropertyId(
       
   214     const TDesC& aPropName )
       
   215     {
       
   216     TInt i = 0;
       
   217     for (; i < iProperties.Count(); ++i )
       
   218         {
       
   219         // use case insensitive match for property names
       
   220         if ( 0 == aPropName.CompareF( iProperties[i].name ) )
       
   221             {
       
   222             return iProperties[i].id;
       
   223             }
       
   224         }
       
   225     TUint16* name = NULL;
       
   226     name = new TUint16 [aPropName.Length()];
       
   227     if (name)
       
   228         {
       
   229         TPtr namePtr(name, aPropName.Length());
       
   230         namePtr.Copy(aPropName);
       
   231         TWidgetProperty property;
       
   232         property.id = iProperties.Count();
       
   233         property.name.Set( namePtr );
       
   234         property.type = EWidgetPropTypeUnknown;
       
   235         TInt err = iProperties.Append(property);
       
   236         if (err == KErrNone)
       
   237             {
       
   238             return iProperties.Count() - 1;
       
   239             }
       
   240         delete name;
       
   241         }
       
   242     return EWidgetPropertyIdInvalid;
       
   243     }
       
   244 
       
   245 // ============================================================================
       
   246 // Get the property name from the property id. Used in entry Externalize
       
   247 //
       
   248 // @param aPropertyId property id
       
   249 // @since 5.0
       
   250 // @return property name.
       
   251 // ============================================================================
       
   252 //
       
   253 
       
   254 const TPtrC& CWidgetBackupRegistryXml::XmlPropertyName(
       
   255     TInt aPropertyId )
       
   256     {
       
   257     for ( TInt i = 0; i < iProperties.Count(); i++ )
       
   258         {
       
   259         if ( iProperties[i].id == aPropertyId )
       
   260             {
       
   261             return iProperties[i].name;
       
   262             }
       
   263         }
       
   264     return iProperties[0].name; // should never get here
       
   265     }
       
   266 
       
   267 
       
   268 // ============================================================================
       
   269 // CWidgetBackupRegistryXml::ToUnicodeL
       
   270 // Utility to bundle transcoding to unicode steps.
       
   271 //
       
   272 // @since 5.0
       
   273 // @param aEncoding input buffer encoding
       
   274 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char
       
   275 // @param aInBuf input data in encoding
       
   276 // @param aOutBuf malloc'ed output buf, caller takes ownership
       
   277 // @param aFileSession CCnvCharacterSetConverter requires it
       
   278 // ============================================================================
       
   279 //
       
   280 void CWidgetBackupRegistryXml::ToUnicodeL( TInt aEncoding,
       
   281                                      TInt aUnicodeSizeMultiplier,
       
   282                                      TPtrC8 aInBuf, HBufC16** aOutBuf,
       
   283                                      RFs& aFileSession )
       
   284     {
       
   285     *aOutBuf = NULL;
       
   286 
       
   287     // outbuf sizing and alloction
       
   288     HBufC16* outBuf = HBufC16::NewLC(aUnicodeSizeMultiplier * aInBuf.Length());
       
   289     TPtr16 outPtr = outBuf->Des();
       
   290 
       
   291     // convert to unicode
       
   292     CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC();
       
   293     charConv->PrepareToConvertToOrFromL( aEncoding, aFileSession );
       
   294     TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   295     TInt rep = 0; // number of unconvertible characters
       
   296     TInt rIndx = 0; // index of first unconvertible character
       
   297     User::LeaveIfError(
       
   298         charConv->ConvertToUnicode( outPtr, aInBuf, state, rep, rIndx ) );
       
   299     CleanupStack::PopAndDestroy( charConv );
       
   300 
       
   301     CleanupStack::Pop( outBuf );
       
   302     *aOutBuf = outBuf;
       
   303     }
       
   304 
       
   305 // ============================================================================
       
   306 // CWidgetBackupRegistryXml::FromUnicodeL
       
   307 // Utility to bundle transcoding to unicode steps.
       
   308 //
       
   309 // @since 5.0
       
   310 // @param aEncoding input buffer encoding
       
   311 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char
       
   312 // @param aInBuf input data in encoding
       
   313 // @param aOutBuf malloc'ed output buf, caller takes ownership
       
   314 // @param aFileSession CCnvCharacterSetConverter requires it
       
   315 // ============================================================================
       
   316 //
       
   317 void CWidgetBackupRegistryXml::FromUnicodeL( TInt aEncoding,
       
   318                                      TInt aUnicodeSizeMultiplier,
       
   319                                      TPtrC16 aInBuf, HBufC8** aOutBuf,
       
   320                                      RFs& aFileSession )
       
   321     {
       
   322     *aOutBuf = NULL;
       
   323 
       
   324     // outbuf sizing and alloction
       
   325     HBufC8* outBuf = HBufC8::NewLC(aUnicodeSizeMultiplier * (aInBuf.Length() + 1));
       
   326     TPtr8 outPtr = outBuf->Des();
       
   327 
       
   328     // convert from unicode
       
   329     CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC();
       
   330     charConv->PrepareToConvertToOrFromL( aEncoding, aFileSession );
       
   331     User::LeaveIfError(
       
   332         charConv->ConvertFromUnicode( outPtr, aInBuf));
       
   333     outPtr.ZeroTerminate();
       
   334     CleanupStack::PopAndDestroy( charConv );
       
   335 
       
   336     CleanupStack::Pop( outBuf ); 
       
   337     *aOutBuf = outBuf;
       
   338     }
       
   339 
       
   340 // ============================================================================
       
   341 // CWidgetBackupRegistryXml::GetContentL
       
   342 // Utility to bundle extraction of XML text content
       
   343 //
       
   344 // @since 5.0
       
   345 // @param aEncoding input buffer encoding
       
   346 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char
       
   347 // @param aInBuf input data in encoding
       
   348 // @param aOutBuf malloc'ed output buf, caller takes ownership
       
   349 // @param aFileSession CCnvCharacterSetConverter requires it
       
   350 // ============================================================================
       
   351 //
       
   352 void CWidgetBackupRegistryXml::GetContentL( RFs& aFileSession,
       
   353                                       xmlDocPtr aDoc,
       
   354                                       xmlNode* aNode,
       
   355                                       HBufC** aContent )
       
   356     {
       
   357     // xml uses UTF-8 for the internal representation
       
   358     xmlChar* xmlContent =
       
   359         xmlNodeListGetString( aDoc, aNode, 1 /* expand entities inline */);
       
   360     if ( NULL == xmlContent )
       
   361         {
       
   362         User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt );
       
   363         }
       
   364     // we must transcode UTF-8 to UCS-2 (historical
       
   365     // and now inaccurate name "unicode")
       
   366     CleanupStack::PushL( xmlContent );
       
   367     TPtrC8 content( xmlContent );
       
   368     ToUnicodeL( KCharacterSetIdentifierUtf8, 2,
       
   369                 content, aContent, aFileSession );
       
   370     CleanupStack::PopAndDestroy(); // xmlContent equivalent to xmlFree()
       
   371     if ( NULL == *aContent )
       
   372         {
       
   373         User::Leave( KErrCorrupt );
       
   374         }
       
   375     }
       
   376    
       
   377 // ============================================================================
       
   378 // CWidgetBackupRegistryXml::GetTextContentAsStringL
       
   379 //
       
   380 // ============================================================================
       
   381 //
       
   382 void CWidgetBackupRegistryXml::GetTextContentAsStringL( RFs& aFileSession, xmlDocPtr aDoc,
       
   383                                                   xmlNode* aNode, HBufC** aContent )
       
   384     {
       
   385     HBufC* tmpBuf = NULL;
       
   386     TInt len = 0;
       
   387     GetSubtreeAsStringL (aFileSession, aDoc, aNode, NULL, len);
       
   388     tmpBuf = HBufC::NewLC(len);
       
   389     GetSubtreeAsStringL (aFileSession, aDoc, aNode, &tmpBuf, len);
       
   390     *aContent = tmpBuf;
       
   391     CleanupStack::Pop(); // tmpBuf
       
   392     }
       
   393 
       
   394 void  CWidgetBackupRegistryXml::GetSubtreeAsStringL (RFs& aFileSession, xmlDocPtr aDoc, xmlNode* aNode, HBufC** aBuf, TInt& aLen)
       
   395     {
       
   396     xmlNode* node = aNode;
       
   397     switch (node->type)
       
   398         {
       
   399         case XML_ELEMENT_NODE:
       
   400             {
       
   401             const xmlChar* name = node->name;
       
   402             TPtrC8 tmpName(name);
       
   403             if (aBuf)
       
   404                 {
       
   405                 HBufC* tmpBuf = NULL;
       
   406                 ToUnicodeL( KCharacterSetIdentifierUtf8, 2,
       
   407                             tmpName, &tmpBuf, aFileSession );
       
   408                 CleanupStack::PushL(tmpBuf);
       
   409                 (*aBuf)->Des().Append(_L("<"));
       
   410                 (*aBuf)->Des().Append(*tmpBuf);
       
   411                 (*aBuf)->Des().Append(_L(">"));
       
   412                 if (node->children)
       
   413                     {
       
   414                     GetSubtreeAsStringL (aFileSession, aDoc, node->children, aBuf, aLen);
       
   415                     }
       
   416                 (*aBuf)->Des().Append(_L("</"));
       
   417                 (*aBuf)->Des().Append(*tmpBuf);
       
   418                 (*aBuf)->Des().Append(_L(">"));
       
   419                 CleanupStack::PopAndDestroy(tmpBuf);
       
   420                 }
       
   421             else
       
   422                 {
       
   423                 aLen += (5 + 2 * tmpName.Length());
       
   424                 if (node->children)
       
   425                     {
       
   426                     GetSubtreeAsStringL (aFileSession, aDoc, node->children, aBuf, aLen);
       
   427                     }
       
   428                 }
       
   429             break;
       
   430             }
       
   431         //case XML_ATTRIBUTE_NODE:
       
   432         case XML_TEXT_NODE:
       
   433             {
       
   434             xmlChar* content = node->content;
       
   435             TPtrC8 tmpContent(content);
       
   436             if (aBuf)
       
   437                 {
       
   438                 HBufC* tmpBuf = NULL;
       
   439                 xmlChar* encodedContent = EncodeStringL(aDoc, content);
       
   440                 CleanupStack::PushL( encodedContent );
       
   441                 TPtrC8 encodedContentPtr(encodedContent);
       
   442                 ToUnicodeL( KCharacterSetIdentifierUtf8, 2,
       
   443                             encodedContentPtr, &tmpBuf, aFileSession );
       
   444                 CleanupStack::PushL(tmpBuf);
       
   445                 (*aBuf)->Des().Append(*tmpBuf);
       
   446                 CleanupStack::PopAndDestroy(2); // encodedContent, tmpBuf
       
   447                 }
       
   448             else
       
   449                 {
       
   450                 aLen += EncodedStringLength(tmpContent);
       
   451                 }
       
   452             break;
       
   453             }
       
   454         case XML_CDATA_SECTION_NODE:
       
   455             {
       
   456             xmlChar* content = node->content;
       
   457             TPtrC8 tmpContent(content);
       
   458             if (aBuf)
       
   459                 {
       
   460                 HBufC* tmpBuf = NULL;
       
   461                 ToUnicodeL( KCharacterSetIdentifierUtf8, 2,
       
   462                             content, &tmpBuf, aFileSession);
       
   463                 CleanupStack::PushL(tmpBuf);
       
   464                 (*aBuf)->Des().Append(_L("<![CDATA["));
       
   465                 (*aBuf)->Des().Append(*tmpBuf);
       
   466                 (*aBuf)->Des().Append(_L("]]>"));
       
   467                 CleanupStack::PopAndDestroy(); // tmpBuf
       
   468                 }
       
   469             else
       
   470                 {
       
   471                 aLen += (12 + tmpContent.Length());
       
   472                 }
       
   473             break;
       
   474             }
       
   475         //case XML_ENTITY_REF_NODE:
       
   476         //case XML_ENTITY_NODE:
       
   477         //case XML_PI_NODE:
       
   478         //case XML_COMMENT_NODE:
       
   479         //case XML_DOCUMENT_NODE:
       
   480         //case XML_DOCUMENT_TYPE_NODE:
       
   481         //case XML_DOCUMENT_FRAG_NODE:
       
   482         //case XML_NOTATION_NODE:
       
   483         //case XML_HTML_DOCUMENT_NODE:
       
   484         //case XML_DTD_NODE:
       
   485         //case XML_ELEMENT_DECL:
       
   486         //case XML_ATTRIBUTE_DECL:
       
   487         //case XML_ENTITY_DECL:
       
   488         //case XML_NAMESPACE_DECL:
       
   489         //case XML_XINCLUDE_START:
       
   490         //case XML_XINCLUDE_END:
       
   491         }
       
   492     if (node->next)
       
   493         {
       
   494         node = node->next;
       
   495         GetSubtreeAsStringL(aFileSession, aDoc, node, aBuf, aLen);
       
   496         }
       
   497     }
       
   498 
       
   499 xmlChar* CWidgetBackupRegistryXml::EncodeStringL(xmlDocPtr aDoc, xmlChar* aStringToConvert)
       
   500     {
       
   501     xmlChar* noEntitiesContent = xmlEncodeSpecialChars(aDoc, aStringToConvert);
       
   502     if ( NULL == noEntitiesContent )
       
   503         {
       
   504         User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt );
       
   505         }
       
   506     return noEntitiesContent;
       
   507     }
       
   508 
       
   509 HBufC* CWidgetBackupRegistryXml::EncodeStringL(xmlDocPtr aDoc, TPtrC aStringToConvert, RFs& aFileSession)
       
   510     {
       
   511     HBufC8* out = NULL;
       
   512     FromUnicodeL( KCharacterSetIdentifierUtf8, 2, aStringToConvert, &out, aFileSession );
       
   513     CleanupStack::PushL(out);
       
   514     xmlChar* noEntitiesContent = xmlEncodeSpecialChars(aDoc, out->Des().Ptr());
       
   515     if ( NULL == noEntitiesContent )
       
   516         {
       
   517         User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt );
       
   518         }
       
   519     CleanupStack::PushL( noEntitiesContent );
       
   520     TPtrC8 noEntitiesPtr(noEntitiesContent);
       
   521     HBufC* noEntitiesBuf = NULL;
       
   522     noEntitiesBuf = HBufC::NewL(noEntitiesPtr.Length());
       
   523     noEntitiesBuf->Des().Copy(noEntitiesPtr);
       
   524     CleanupStack::PopAndDestroy(2, out); // out, noEntitiesContent
       
   525 
       
   526     return noEntitiesBuf;
       
   527     }
       
   528 
       
   529 
       
   530 TInt CWidgetBackupRegistryXml::EncodedStringLength(TPtrC8 aStringToConvert)
       
   531     {
       
   532     _LIT(KEntity, "\"&\r<>");
       
   533     if (aStringToConvert.Length() == 0 ) return 0;
       
   534     TInt entityLength[] = {6,5,5,4,4};
       
   535     TInt i;
       
   536     TInt count = 0;
       
   537     for (i = 0; i < aStringToConvert.Length(); i++)
       
   538         {
       
   539         TInt entityIndex = KEntity().Locate(aStringToConvert[i]);
       
   540         if (entityIndex != KErrNotFound)
       
   541             {
       
   542             count+= entityLength[entityIndex];
       
   543             }
       
   544         else
       
   545             {
       
   546             count++;
       
   547             }
       
   548         }
       
   549     return count;
       
   550     }