omadrm/drmengine/agentv2/src/Oma2AgentData.cpp
changeset 0 95b198f216e5
child 12 8a03a285ab14
equal deleted inserted replaced
-1:000000000000 0:95b198f216e5
       
     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:  Implementation of the CAF Agent Data class
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include <caf/caf.h>
       
    20 #include <caf/bitset.h>
       
    21 #include <caf/attribute.h>
       
    22 #include <e32test.h>
       
    23 #include "drmcommon.h"
       
    24 #include "oma2agentdata.h"
       
    25 #include "oma2agentattributes.h"
       
    26 #include "oma1dcf.h"
       
    27 #include "oma2dcf.h"
       
    28 #include "symmetric.h"
       
    29 #include "drmrightsclient.h"
       
    30 #include "drmprotectedroparser.h"
       
    31 #include "dcfcache.h"
       
    32 #include "cleanupresetanddestroy.h"
       
    33 
       
    34 using namespace ContentAccess;
       
    35 //TRACE macros
       
    36 #ifdef _DEBUG
       
    37 #include <e32debug.h> // RDebug
       
    38 #define TRACE( x ) RDebug::Print( _L( x ) )
       
    39 #define TRACE2( x, y ) RDebug::Print( _L( x ), y )
       
    40 #define TRACE3( x, y, z ) RDebug::Print( _L( x ), y, z )
       
    41 #else
       
    42 #define TRACE( x )
       
    43 #define TRACE2( x, y )
       
    44 #define TRACE3( x, y, z )
       
    45 #endif
       
    46 // CONSTANTS
       
    47 _LIT8(KMimeAudio, "audio");
       
    48 _LIT8(KMimeImage, "image");
       
    49 // LOCAL FUNCTION PROTOTYPES
       
    50 LOCAL_C TInt MapContentShareMode( TContentShareMode aMode );
       
    51 
       
    52 // ============================= LOCAL FUNCTIONS ===============================
       
    53 
       
    54 // -----------------------------------------------------------------------------
       
    55 // MapContentShareMode
       
    56 // Maps the CAF specific file share mode to the RFs/RFile sharing mode
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 LOCAL_C TInt MapContentShareMode( TContentShareMode aMode )
       
    60     {
       
    61     TInt r = EFileRead | EFileShareAny;
       
    62 
       
    63     switch ( aMode )
       
    64         {
       
    65         case EContentShareReadOnly:
       
    66             r = EFileRead | EFileShareReadersOnly;
       
    67             break;
       
    68         case EContentShareReadWrite:
       
    69             r = EFileRead | EFileShareReadersOrWriters;
       
    70             break;
       
    71         case EContentShareExclusive:
       
    72             r = EFileRead | EFileShareExclusive;
       
    73             break;
       
    74         }
       
    75     return r;
       
    76     }
       
    77 
       
    78 // ============================ MEMBER FUNCTIONS ===============================
       
    79 
       
    80 // -----------------------------------------------------------------------------
       
    81 // COma2AgentData::COma2AgentData
       
    82 // C++ default constructor can NOT contain any code, that
       
    83 // might leave.
       
    84 // -----------------------------------------------------------------------------
       
    85 //
       
    86 COma2AgentData::COma2AgentData() :
       
    87     iDcf( NULL ),
       
    88     iDataPosition( 0 ),
       
    89     iRightsStatus( KErrNone ),
       
    90     iVirtualPath( KNullDesC ),
       
    91     iCache( NULL ),
       
    92     iGroupKeyUsed( EFalse ),
       
    93     iLastFileSize( 0 )
       
    94     {
       
    95     }
       
    96 
       
    97 // -----------------------------------------------------------------------------
       
    98 // COma2AgentData::ConstructL
       
    99 // Symbian 2nd phase constructor can leave.
       
   100 // -----------------------------------------------------------------------------
       
   101 //
       
   102 void COma2AgentData::ConstructL(
       
   103     const TVirtualPathPtr& aVirtualPath,
       
   104     TContentShareMode aShareMode )
       
   105     {
       
   106     User::LeaveIfError( iRdb.Connect() );
       
   107     User::LeaveIfError( iFs.Connect() );
       
   108     User::LeaveIfError( iFs.ShareAuto() );
       
   109     User::LeaveIfError( iFile.Open( iFs, aVirtualPath.URI(),
       
   110         MapContentShareMode( aShareMode ) ) );
       
   111     iDcf = CDcfCommon::NewL( iFile );
       
   112     iVirtualPath = aVirtualPath;
       
   113     User::LeaveIfError( iDcf->OpenPart( iVirtualPath.UniqueId() ) );
       
   114     InitializeL();
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 void COma2AgentData::ConstructL(
       
   120     RFile& aFile,
       
   121     const TDesC& aUniqueId )
       
   122     {
       
   123     User::LeaveIfError( iRdb.Connect() );
       
   124     User::LeaveIfError( iFs.Connect() );
       
   125     User::LeaveIfError( iFs.ShareAuto() );
       
   126     User::LeaveIfError( iFile.Duplicate( aFile ) );
       
   127     iDcf = CDcfCommon::NewL( iFile );
       
   128     User::LeaveIfError( iDcf->OpenPart( aUniqueId ) );
       
   129     InitializeL();
       
   130     iUniqueId = aUniqueId.AllocL();
       
   131     }
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // COma2AgentData::InitializeL
       
   135 // -----------------------------------------------------------------------------
       
   136 //
       
   137 void COma2AgentData::InitializeL()
       
   138     {
       
   139     TInt r = KErrNone;
       
   140     TBuf8<KDCFKeySize * 2> blocks;
       
   141     CDrmProtectedRoParser* parser;
       
   142     TInt pos;
       
   143     COma2Dcf* dcf2 = NULL;
       
   144     TInt i;
       
   145     TBool reinit = EFalse;
       
   146     TInt error = KErrNone;
       
   147 
       
   148     if ( iDcf->iVersion == EOma2Dcf )
       
   149         {
       
   150         dcf2 = static_cast<COma2Dcf*> ( iDcf );
       
   151         // Encrypted images are not supported, but plain ones are:
       
   152         if ( dcf2->iMimeType->Left( KMimeImage().Length() ).CompareF(
       
   153             KMimeImage ) == 0 && iDcf->iEncryptionMethod != EMethodNULL )
       
   154             {
       
   155             User::Leave( KErrNotSupported );
       
   156             }
       
   157         }
       
   158 
       
   159     // Set the session key for this file
       
   160     if ( iDcf->iEncryptionMethod == EMethodAES_128_CBC )
       
   161         {
       
   162         // Check if we can use the group key first
       
   163         if ( dcf2 && dcf2->iGroupId )
       
   164             {
       
   165             r = iRdb.InitializeGroupKey( *dcf2->iGroupId, *dcf2->iGroupKey,
       
   166                 dcf2->iGkEncryptionMethod );
       
   167             if ( r == KErrNone )
       
   168                 {
       
   169                 iGroupKeyUsed = ETrue;
       
   170                 }
       
   171             }
       
   172         else
       
   173             {
       
   174             r = iRdb.InitializeKey( *iDcf->iContentID );
       
   175             }
       
   176 
       
   177         // If the DCF contains a domain RO, try to save and use it
       
   178         if ( dcf2 && dcf2->iRightsObjects.Count() )
       
   179             {
       
   180             error = r;
       
   181             __UHEAP_MARK;
       
   182             for ( i = 0; i < dcf2->iRightsObjects.Count(); i++ )
       
   183                 {
       
   184                 RPointerArray<CDRMRights> rights;
       
   185                 CleanupResetAndDestroyPushL( rights );
       
   186                 parser = CDrmProtectedRoParser::NewL();
       
   187                 CleanupStack::PushL( parser );
       
   188                 // NOTE:
       
   189                 // This is trapped for a reason, the file opening must not fail
       
   190                 // even if the parsing of the embedded rights object fails
       
   191                 // for some reason it is possible that the rights are already
       
   192                 // put into the database and the leave occurs because of this,
       
   193                 // also it's possible that there are existing rights
       
   194                 // that work with the given content.
       
   195                 TRAP( r, parser->ParseAndStoreL( *dcf2->iRightsObjects[i],
       
   196                     rights) );
       
   197                 CleanupStack::PopAndDestroy( parser );
       
   198                 CleanupStack::PopAndDestroy( &rights );
       
   199                 if ( r == KErrNone && !reinit )
       
   200                     {
       
   201                     reinit = ETrue;
       
   202                     }
       
   203                 }
       
   204             __UHEAP_MARKEND;
       
   205             if ( reinit && !iGroupKeyUsed )
       
   206                 {
       
   207                 r = iRdb.InitializeKey( *iDcf->iContentID );
       
   208                 }
       
   209             else
       
   210                 {
       
   211                 r = error;
       
   212                 }
       
   213             }
       
   214 
       
   215         if ( r != KErrCANoRights && r != KErrCANoPermission &&
       
   216             r != KErrCAPendingRights && r != KErrNone )
       
   217             {
       
   218             User::Leave( r );
       
   219             }
       
   220         iRightsStatus = r;
       
   221         }
       
   222     else if ( iDcf->iEncryptionMethod != EMethodNULL )
       
   223         {
       
   224         User::Leave( KErrNotSupported );
       
   225         }
       
   226 
       
   227     iCache = CDcfCache::NewL( iRdb, iFile, *iDcf, 0, 0 );
       
   228     if ( iDcf->iPadding == -1 && iRightsStatus == KErrNone )
       
   229         {
       
   230         pos = iDcf->iOffset + iDcf->iDataLength - 2 * KDCFKeySize;
       
   231         iFile.Seek( ESeekStart, pos );
       
   232         iFile.Read( blocks );
       
   233         iDcf->iPadding = iRdb.CalculatePadding( blocks );
       
   234         if ( iDcf->iPadding >= 0 )
       
   235             {
       
   236             iDcf->iPlainTextLength -= iDcf->iPadding;
       
   237             iDcf->iPlainTextLengthValid = ETrue;
       
   238             }
       
   239         }
       
   240     User::LeaveIfError( iFile.Size( iLastFileSize ) );
       
   241     }
       
   242 
       
   243 // -----------------------------------------------------------------------------
       
   244 // COma2AgentData::NewL
       
   245 // Two-phased constructor.
       
   246 // -----------------------------------------------------------------------------
       
   247 //
       
   248 COma2AgentData* COma2AgentData::NewL(
       
   249     const TVirtualPathPtr& aVirtualPath,
       
   250     TContentShareMode aShareMode )
       
   251     {
       
   252     COma2AgentData* self = NewLC( aVirtualPath, aShareMode );
       
   253     CleanupStack::Pop( self );
       
   254     return self;
       
   255     }
       
   256 
       
   257 // -----------------------------------------------------------------------------
       
   258 // COma2AgentData::NewLC
       
   259 // -----------------------------------------------------------------------------
       
   260 //
       
   261 COma2AgentData* COma2AgentData::NewLC(
       
   262     const TVirtualPathPtr& aVirtualPath,
       
   263     TContentShareMode aShareMode )
       
   264     {
       
   265     COma2AgentData* self = new ( ELeave ) COma2AgentData();
       
   266     CleanupStack::PushL( self );
       
   267     self->ConstructL( aVirtualPath, aShareMode );
       
   268     return self;
       
   269     }
       
   270 
       
   271 // -----------------------------------------------------------------------------
       
   272 // COma2AgentData::NewL
       
   273 // -----------------------------------------------------------------------------
       
   274 //
       
   275 COma2AgentData* COma2AgentData::NewL(
       
   276     RFile& aFile,
       
   277     const TDesC& aUniqueId )
       
   278     {
       
   279     COma2AgentData* self = COma2AgentData::NewLC( aFile, aUniqueId );
       
   280     CleanupStack::Pop( self );
       
   281     return self;
       
   282     }
       
   283 
       
   284 // -----------------------------------------------------------------------------
       
   285 // COma2AgentData::NewLC
       
   286 // -----------------------------------------------------------------------------
       
   287 //
       
   288 COma2AgentData* COma2AgentData::NewLC(
       
   289     RFile& aFile,
       
   290     const TDesC& aUniqueId )
       
   291     {
       
   292     COma2AgentData* self = new ( ELeave ) COma2AgentData();
       
   293     CleanupStack::PushL( self );
       
   294     self->ConstructL( aFile, aUniqueId );
       
   295     return self;
       
   296     }
       
   297 
       
   298 // Destructor
       
   299 COma2AgentData::~COma2AgentData()
       
   300     {
       
   301     iRdb.Close();
       
   302     iFile.Close();
       
   303     iFs.Close();
       
   304     delete iDcf;
       
   305     delete iCache;
       
   306     delete iUniqueId;
       
   307     }
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // COma2AgentData::DataSizeL
       
   311 // Re-create the DCF because it's size may have changed.
       
   312 // for progressive download etc.
       
   313 // -----------------------------------------------------------------------------
       
   314 //
       
   315 void COma2AgentData::DataSizeL( TInt &aSize )
       
   316     {
       
   317     TInt fileSize = 0;
       
   318     TInt seekPos = 0;
       
   319 
       
   320     User::LeaveIfError( iFile.Size( fileSize ) );
       
   321 
       
   322     if ( iDcf )
       
   323         {
       
   324         // if the size of the file has changed update info:
       
   325         if ( fileSize != iLastFileSize )
       
   326             {
       
   327             // Delete the old dcf
       
   328             delete iDcf;
       
   329             iDcf = NULL;
       
   330 
       
   331             // seek the file to the beginning
       
   332             iFile.Seek( ESeekStart, seekPos );
       
   333 
       
   334             // Create new dcf as the size may have changed
       
   335             iDcf = CDcfCommon::NewL( iFile );
       
   336 
       
   337             // open the content part
       
   338             if ( iUniqueId )
       
   339                 {
       
   340                 User::LeaveIfError( iDcf->OpenPart( iUniqueId->Des() ) );
       
   341                 }
       
   342             else
       
   343                 {
       
   344                 User::LeaveIfError( iDcf->OpenPart( iVirtualPath.UniqueId() ) );
       
   345                 }
       
   346             // re-initialize the dcf, this updates the iLastFileSize
       
   347             InitializeL();
       
   348             }
       
   349 
       
   350         aSize = iDcf->iPlainTextLength;
       
   351         }
       
   352     else
       
   353         {
       
   354         User::Leave( KErrNotReady );
       
   355         }
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // COma2AgentData::EvaluateIntent
       
   360 // -----------------------------------------------------------------------------
       
   361 //
       
   362 TInt COma2AgentData::EvaluateIntent( TIntent aIntent )
       
   363     {
       
   364     TInt r = KErrNone;
       
   365 
       
   366     // Check for a mismatch in the MIME type and the intent
       
   367     if ( ( iDcf->iMimeType->Left(
       
   368             KMimeAudio().Length() ).CompareF( KMimeAudio ) == 0 &&
       
   369             ( aIntent == EView || aIntent == EPrint || aIntent == EExecute ) )
       
   370         ||
       
   371         ( iDcf->iMimeType->Left(
       
   372             KMimeImage().Length() ).CompareF( KMimeImage ) == 0 &&
       
   373             ( aIntent == EPlay || aIntent == EExecute ) ) )
       
   374         {
       
   375         r = KErrArgument;
       
   376         }
       
   377     else if ( iDcf->iEncryptionMethod )
       
   378         {
       
   379         if ( iGroupKeyUsed )
       
   380             {
       
   381             r = iRdb.CheckConsume( aIntent,
       
   382                 *( static_cast<COma2Dcf*> ( iDcf )->iGroupId ) );
       
   383             }
       
   384         else
       
   385             {
       
   386             r = iRdb.CheckConsume( aIntent, *iDcf->iContentID );
       
   387             }
       
   388         }
       
   389     return r;
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // COma2AgentData::ExecuteIntent
       
   394 // -----------------------------------------------------------------------------
       
   395 //
       
   396 TInt COma2AgentData::ExecuteIntent( TIntent aIntent )
       
   397     {
       
   398     TInt r = KErrNone;
       
   399     TBuf8<KDCFKeySize> key;
       
   400 
       
   401     // Check for a mismatch in the MIME type and the intent
       
   402     if ( ( iDcf->iMimeType->Left(
       
   403             KMimeAudio().Length() ).CompareF( KMimeAudio ) == 0 &&
       
   404             ( aIntent == EView || aIntent == EPrint || aIntent == EExecute ) )
       
   405         ||
       
   406         ( iDcf->iMimeType->Left(
       
   407             KMimeImage().Length() ).CompareF( KMimeImage ) == 0 &&
       
   408             ( aIntent == EPlay || aIntent == EExecute ) ) )
       
   409         {
       
   410         r = KErrArgument;
       
   411         }
       
   412     else if ( iDcf->iEncryptionMethod )
       
   413         {
       
   414         // If the MIME type allows it, do the consumption
       
   415         if ( iGroupKeyUsed )
       
   416             {
       
   417             r = iRdb.Consume( aIntent,
       
   418                 *( static_cast<COma2Dcf*> ( iDcf )->iGroupId ) );
       
   419             }
       
   420         else
       
   421             {
       
   422             r = iRdb.Consume( aIntent, *iDcf->iContentID );
       
   423             }
       
   424 
       
   425         // If the consumption succeeded, try to get the decryption key.
       
   426         // This is possible at this time because the permission is now known on
       
   427         // the server side, and the server can return the key if the
       
   428         // security level allows it. The decision is made based on the
       
   429         // used permission and the caller identity.
       
   430         if ( r == KErrNone && iRdb.GetDecryptionKey( aIntent,
       
   431             *iDcf->iContentID, key ) == KErrNone && key.Length()
       
   432             == KDCFKeySize )
       
   433             {
       
   434             iCache->SetKey( key );
       
   435             }
       
   436         }
       
   437     return r;
       
   438     }
       
   439 
       
   440 // -----------------------------------------------------------------------------
       
   441 // COma2AgentData::Read
       
   442 // -----------------------------------------------------------------------------
       
   443 //
       
   444 TInt COma2AgentData::Read( TDes8& aDes )
       
   445     {
       
   446     return Read( aDes, aDes.MaxLength() );
       
   447     }
       
   448 
       
   449 // -----------------------------------------------------------------------------
       
   450 // COma2AgentData::Read
       
   451 // -----------------------------------------------------------------------------
       
   452 //
       
   453 TInt COma2AgentData::Read(
       
   454     TDes8& aDes,
       
   455     TInt aLength )
       
   456     {
       
   457     return iCache->Read( iDataPosition, aDes, aLength );
       
   458     }
       
   459 
       
   460 // -----------------------------------------------------------------------------
       
   461 // COma2AgentData::Read
       
   462 // -----------------------------------------------------------------------------
       
   463 //
       
   464 void COma2AgentData::Read(
       
   465     TDes8& aDes,
       
   466     TRequestStatus& aStatus )
       
   467     {
       
   468     TRequestStatus* status = &aStatus;
       
   469     User::RequestComplete( status, Read( aDes, aDes.MaxLength() ) );
       
   470     }
       
   471 
       
   472 // -----------------------------------------------------------------------------
       
   473 // COma2AgentData::Read
       
   474 // asynchronous read
       
   475 // -----------------------------------------------------------------------------
       
   476 //
       
   477 void COma2AgentData::Read(
       
   478     TDes8& aDes,
       
   479     TInt aLength,
       
   480     TRequestStatus& aStatus )
       
   481     {
       
   482     TRequestStatus* status = &aStatus;
       
   483     User::RequestComplete( status, Read( aDes, aLength ) );
       
   484     }
       
   485 
       
   486 #ifdef ASYNC_READ
       
   487 
       
   488 // -----------------------------------------------------------------------------
       
   489 // COma2AgentData::Read
       
   490 // asynchronous read (not really asynchronous)
       
   491 // -----------------------------------------------------------------------------
       
   492 //
       
   493 TInt COma2AgentData::Read(
       
   494     TInt aPos,
       
   495     TDes8& aDes,
       
   496     TInt aLength,
       
   497     TRequestStatus& aStatus )
       
   498     {
       
   499     return iCache->Read( aPos, aDes, aLength, aStatus );
       
   500     }
       
   501 
       
   502 // -----------------------------------------------------------------------------
       
   503 // COma2AgentData::ReadCancel
       
   504 // -----------------------------------------------------------------------------
       
   505 //
       
   506 void COma2AgentData::ReadCancel( TRequestStatus& aStatus )
       
   507     {
       
   508     TRACE("+ COma2AgentData::ReadCancel");
       
   509     iCache->ReadCancel( aStatus );
       
   510     TRACE("- COma2AgentData::ReadCancel");
       
   511     }
       
   512 #endif
       
   513 
       
   514 // -----------------------------------------------------------------------------
       
   515 // COma2AgentData::Seek
       
   516 // -----------------------------------------------------------------------------
       
   517 //
       
   518 TInt COma2AgentData::Seek( TSeek aMode, TInt& aPos )
       
   519     {
       
   520     TInt r = KErrNone;
       
   521 
       
   522     switch ( aMode )
       
   523         {
       
   524         case ESeekStart:
       
   525             break;
       
   526         case ESeekEnd:
       
   527             aPos = iDcf->iPlainTextLength + aPos;
       
   528             break;
       
   529         case ESeekCurrent:
       
   530             aPos = iDataPosition + aPos;
       
   531             break;
       
   532         default:
       
   533             r = KErrNotSupported;
       
   534             break;
       
   535         }
       
   536     aPos = Max( aPos, 0 );
       
   537     aPos = Min( aPos, iDcf->iPlainTextLength );
       
   538     iDataPosition = aPos;
       
   539     return r;
       
   540     }
       
   541 
       
   542 // -----------------------------------------------------------------------------
       
   543 // COma2AgentData::SetProperty
       
   544 // -----------------------------------------------------------------------------
       
   545 //
       
   546 TInt COma2AgentData::SetProperty(
       
   547     TAgentProperty /*aProperty*/,
       
   548     TInt /*aValue*/)
       
   549     {
       
   550     return KErrCANotSupported;
       
   551     }
       
   552 
       
   553 // -----------------------------------------------------------------------------
       
   554 // COma2AgentData::GetAttribute
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 TInt COma2AgentData::GetAttribute(
       
   558     TInt aAttribute,
       
   559     TInt& aValue )
       
   560     {
       
   561     TInt ret( KErrCANotSupported );
       
   562     ret = TOma2AgentAttributes::GetAttribute( *iDcf, aAttribute,
       
   563         iVirtualPath, &iRdb );
       
   564     if ( ret >= KErrNone )
       
   565         {
       
   566         aValue = ret;
       
   567         ret = KErrNone;
       
   568         }
       
   569     return ret;
       
   570     }
       
   571 
       
   572 // -----------------------------------------------------------------------------
       
   573 // COma2AgentData::GetAttributeSet
       
   574 // -----------------------------------------------------------------------------
       
   575 //
       
   576 
       
   577 TInt COma2AgentData::GetAttributeSet(
       
   578     RAttributeSet& aAttributeSet )
       
   579     {
       
   580     return TOma2AgentAttributes::GetAttributeSet( *iDcf, aAttributeSet,
       
   581         iVirtualPath, &iRdb );
       
   582     }
       
   583 
       
   584 // -----------------------------------------------------------------------------
       
   585 // COma2AgentData::GetStringAttribute
       
   586 // -----------------------------------------------------------------------------
       
   587 //
       
   588 
       
   589 TInt COma2AgentData::GetStringAttribute(
       
   590     TInt aAttribute,
       
   591     TDes& aValue )
       
   592     {
       
   593     return TOma2AgentAttributes::GetStringAttribute( *iDcf, aAttribute,
       
   594         aValue, iVirtualPath, &iRdb );
       
   595     }
       
   596 
       
   597 // -----------------------------------------------------------------------------
       
   598 // COma2AgentData::GetStringAttributeSet
       
   599 // -----------------------------------------------------------------------------
       
   600 //
       
   601 
       
   602 TInt COma2AgentData::GetStringAttributeSet(
       
   603     RStringAttributeSet& aStringAttributeSet )
       
   604     {
       
   605     return TOma2AgentAttributes::GetStringAttributeSet( *iDcf,
       
   606         aStringAttributeSet, iVirtualPath, &iRdb );
       
   607     }
       
   608 
       
   609 //  End of File