httpfilters/cookie/ManagerSrc/CookieManagerClient.cpp
branchRCL_3
changeset 9 9015645363c8
parent 7 2611c08ee28e
child 18 5f1cd966e0d9
equal deleted inserted replaced
8:73e95e652591 9:9015645363c8
    47 // ---------------------------------------------------------
    47 // ---------------------------------------------------------
    48 // RCookieManager::RCookieManager
    48 // RCookieManager::RCookieManager
    49 // ---------------------------------------------------------
    49 // ---------------------------------------------------------
    50 //
    50 //
    51 EXPORT_C RCookieManager::RCookieManager( RStringPool aStringPool )
    51 EXPORT_C RCookieManager::RCookieManager( RStringPool aStringPool )
    52 : iStringPool( aStringPool ), iCookiePacker( iStringPool )
    52 : iStringPool( aStringPool ),iCookieMgrData(NULL)
    53     {
    53     {
    54     CLOG(( EClient, 0, _L(" ") ));
    54     CLOG(( EClient, 0, _L(" ") ));
    55     CLOG(( EClient, 0, _L("*****************") ));
    55     CLOG(( EClient, 0, _L("*****************") ));
    56     CLOG(( EClient, 0, _L("RCookieManager::RCookieManager") ));
    56     CLOG(( EClient, 0, _L("RCookieManager::RCookieManager") ));
    57     }
    57     }
    79 // ---------------------------------------------------------
    79 // ---------------------------------------------------------
    80 //
    80 //
    81 EXPORT_C TInt RCookieManager::Connect()
    81 EXPORT_C TInt RCookieManager::Connect()
    82     {
    82     {
    83     CLOG( ( EClientConnect, 0, _L( "-> RCookieManager::Connect" ) ) );
    83     CLOG( ( EClientConnect, 0, _L( "-> RCookieManager::Connect" ) ) );
    84     CCookieClientDataArray::GetInstance()->Ref();
    84     iCookieMgrData = new TCookieMgrInternalStruct(iStringPool);
       
    85     if (!(iCookieMgrData && iCookieMgrData->Init() == KErrNone))
       
    86         return KErrNoMemory;
       
    87             
    85     TInt error = KErrNone;
    88     TInt error = KErrNone;
    86     RProcess server;
    89     RProcess server;
    87     error = server.Create( KCookieServerExe, TPtr( NULL, 0 ),
    90     error = server.Create( KCookieServerExe, TPtr( NULL, 0 ),
    88                            TUidType( KNullUid, KNullUid, KCookieServerExeUid ) );
    91                            TUidType( KNullUid, KNullUid, KCookieServerExeUid ) );
    89     CLOG( ( EClientConnect, 0,
    92     CLOG( ( EClientConnect, 0,
   183 										RPointerArray<CCookie>& aCookies,
   186 										RPointerArray<CCookie>& aCookies,
   184 										TBool& aCookie2Reqd )
   187 										TBool& aCookie2Reqd )
   185     {
   188     {
   186     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetCookiesL" ) ) );
   189     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetCookiesL" ) ) );
   187     TBool cookiefound(EFalse);
   190     TBool cookiefound(EFalse);
   188     CCookieClientDataArray* cookieclientdataarray = CCookieClientDataArray::GetInstance();
   191     CCookieClientDataArray* cookieclientdataarray = iCookieMgrData->GetCookieClientDataArray();
   189     if(cookieclientdataarray) // redundant check
   192     
       
   193     if(cookieclientdataarray) 
   190         {
   194         {
   191     TInt clientarraycount = cookieclientdataarray->Count();
   195     TInt clientarraycount = cookieclientdataarray->Count();
   192     if ( clientarraycount!=0 )
   196     if ( clientarraycount!=0 )
   193         {
   197         {
   194         TInt clerr = GetClientSideCookies(aUri,aCookies,cookiefound,0);
   198         TInt clerr = GetClientSideCookies(aUri,aCookies,cookiefound,0);
   215 		TPtr8 des( buf->Des() );
   219 		TPtr8 des( buf->Des() );
   216 		User::LeaveIfError( DoGetCookies( des ) );
   220 		User::LeaveIfError( DoGetCookies( des ) );
   217 
   221 
   218 		// it seems this is the only place where we cannot avoid leaving
   222 		// it seems this is the only place where we cannot avoid leaving
   219 		// ==> we allocate memory for cookies when we fill up the cookie array.
   223 		// ==> we allocate memory for cookies when we fill up the cookie array.
   220 		iCookiePacker.UnpackCookiesFromBufferL( *buf, aCookies );
   224 		iCookieMgrData->GetCookiePacker().UnpackCookiesFromBufferL( *buf, aCookies );
   221 
       
   222 		TInt count = aCookies.Count();
   225 		TInt count = aCookies.Count();
   223 		TInt i = 0;
   226 		TInt i = 0;
   224 		TBool anyCookie2( EFalse );
   227 		TBool anyCookie2( EFalse );
   225 		TBool anyUnknownVersion( EFalse );
   228 		TBool anyUnknownVersion( EFalse );
   226 		for ( ; i < count; i++ )
   229 		for ( ; i < count; i++ )
   252 //
   255 //
   253 EXPORT_C TInt RCookieManager::StoreCookie( const CCookie& aCookie,
   256 EXPORT_C TInt RCookieManager::StoreCookie( const CCookie& aCookie,
   254 								 const TUriC8& aUri )
   257 								 const TUriC8& aUri )
   255     {
   258     {
   256     CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreCookie" ) ) );
   259     CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreCookie" ) ) );
   257 
   260     StoreCookieAtClientSide(&aCookie,aUri.UriDes()); 
   258 	TInt err;
   261 	TInt err;
   259 
   262 
   260 	TInt cookieSize = aCookie.Size( EFalse );
   263 	TInt cookieSize = aCookie.Size( EFalse );
   261 	HBufC8* buf = HBufC8::New( cookieSize );
   264 	HBufC8* buf = HBufC8::New( cookieSize );
   262 	if ( buf )
   265 	if ( buf )
   264 		CLOG( ( EClient, 0,
   267 		CLOG( ( EClient, 0,
   265 			    _L( "RCookieManager::StoreCookie, cookie size:%d" ), 
   268 			    _L( "RCookieManager::StoreCookie, cookie size:%d" ), 
   266                 cookieSize ) );
   269                 cookieSize ) );
   267 
   270 
   268 		TPtr8 bufDes( buf->Des() );
   271 		TPtr8 bufDes( buf->Des() );
   269 		err = iCookiePacker.CliPackCookie( bufDes, aCookie );
   272 		err = iCookieMgrData->GetCookiePacker().CliPackCookie( bufDes, aCookie );
   270 		if ( !err )
   273 		if ( !err )
   271 			{
   274 			{
   272 			//Appuid value only takes 8 chars
   275 			//Appuid value only takes 8 chars
   273             HBufC* appbuf = HBufC::New(8); // harendra: 8 chars needed
   276             HBufC* appbuf = HBufC::New(8);
   274             TPtr ptr(appbuf->Des());
   277             TPtr ptr(appbuf->Des());
   275             TUint32 appUid(0);
   278             TUint32 appUid(0);
   276             ptr.AppendNum(appUid,EHex);    
   279             ptr.AppendNum(appUid,EHex);    
   277             err = DoStoreCookie( *buf, aUri.UriDes(),ptr );
   280             err = DoStoreCookie( *buf, aUri.UriDes(),ptr );
   278             delete appbuf;
   281             delete appbuf;
   313 //
   316 //
   314 EXPORT_C TInt RCookieManager::SetAppUidL( const TUint32& aAppUid )
   317 EXPORT_C TInt RCookieManager::SetAppUidL( const TUint32& aAppUid )
   315     {
   318     {
   316     CLOG(( EClient, 0, _L("->RCookieManager::SetAppUid") ));   
   319     CLOG(( EClient, 0, _L("->RCookieManager::SetAppUid") ));   
   317     TUint32 groupid = RProcess().SecureId().iId;
   320     TUint32 groupid = RProcess().SecureId().iId;
   318     CCookieClientData* cookieclientdata = CCookieClientDataArray::GetInstance()->Find(groupid, const_cast<TUint32&> (aAppUid));
   321     CCookieClientData* cookieclientdata = iCookieMgrData->GetCookieClientDataArray()->Find(groupid, const_cast<TUint32&> (aAppUid));
   319     if(cookieclientdata)
   322     if(cookieclientdata)
   320         {
   323         {
   321         cookieclientdata->SetWidgetUid(aAppUid);
   324         cookieclientdata->SetWidgetUid(aAppUid);
   322         }
   325         }
   323     else
   326     else
   324         {
   327         {
   325         TBool cookieSharableFlag(EFalse);
   328         TBool cookieSharableFlag(EFalse);
   326         TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   329         TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   327         CCookieClientData* cookieclientdata = CCookieClientData::NewL(groupid, aAppUid, cookieSharableFlag,ETrue);
   330         cookieclientdata = CCookieClientData::NewL(groupid, aAppUid, cookieSharableFlag,ETrue);
   328         cookieclientdata->SetInitFlag(ETrue);
   331         cookieclientdata->SetInitFlag(ETrue);
   329         CCookieClientDataArray::GetInstance()->AddClientGroupDataL(cookieclientdata);
   332         iCookieMgrData->GetCookieClientDataArray()->AddClientGroupDataL(cookieclientdata);
   330         }
   333         }
   331     //Appuid value only takes 8 chars
   334     //Appuid value only takes 8 chars
   332     HBufC* buf = HBufC::NewLC(8);
   335     HBufC* buf = HBufC::NewLC(8);
   333     TPtr ptr(buf->Des());
   336     TPtr ptr(buf->Des());
   334     ptr.AppendNum(aAppUid,EHex);    
   337     ptr.AppendNum(aAppUid,EHex);    
   343 //
   346 //
   344 
   347 
   345 EXPORT_C void RCookieManager::Close()
   348 EXPORT_C void RCookieManager::Close()
   346     {
   349     {
   347     CLOG(( EClient, 0, _L("-> RCookieManager::Close") ));
   350     CLOG(( EClient, 0, _L("-> RCookieManager::Close") ));
   348     CCookieClientDataArray::GetInstance()->DeRef();
       
   349     TInt deletestatus =0;
   351     TInt deletestatus =0;
   350     DestroyCookiesFromMemory(deletestatus);
   352     DestroyCookiesFromMemory(deletestatus);
       
   353     delete iCookieMgrData;
       
   354     iCookieMgrData = NULL;
   351     CLOG(( EClient, 0, _L("-> RCookieManager::Close deletestatus = %d"), deletestatus ));
   355     CLOG(( EClient, 0, _L("-> RCookieManager::Close deletestatus = %d"), deletestatus ));
   352     RSessionBase::Close();
   356     RSessionBase::Close();
   353     CLOG(( EClient, 0, _L("<- RCookieManager::Close") ));
   357     CLOG(( EClient, 0, _L("<- RCookieManager::Close") ));
   354     }
   358     }
   355 // ---------------------------------------------------------
   359 // ---------------------------------------------------------
   370         CLOG( ( EClient, 0,
   374         CLOG( ( EClient, 0,
   371                 _L( "RCookieManager::StoreCookie, cookie size:%d" ), 
   375                 _L( "RCookieManager::StoreCookie, cookie size:%d" ), 
   372                 cookieSize ) );
   376                 cookieSize ) );
   373 
   377 
   374         TPtr8 bufDes( buf->Des() );
   378         TPtr8 bufDes( buf->Des() );
   375         err = iCookiePacker.CliPackCookie( bufDes, aCookie );
   379         err = iCookieMgrData->GetCookiePacker().CliPackCookie( bufDes, aCookie );
   376         
   380         
   377         if ( !err )
   381         if ( !err )
   378             {
   382             {
   379             //Appuid value only takes 8 chars
   383             //Appuid value only takes 8 chars
   380             HBufC* appbuf = HBufC::New(8);
   384             HBufC* appbuf = HBufC::New(8);
   405                                         RPointerArray<CCookie>& aCookies,
   409                                         RPointerArray<CCookie>& aCookies,
   406                                         TBool& aCookie2Reqd,TUint32& aAppUid )
   410                                         TBool& aCookie2Reqd,TUint32& aAppUid )
   407     {
   411     {
   408     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetCookiesL" ) ) );
   412     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetCookiesL" ) ) );
   409     TBool cookiefound(EFalse);
   413     TBool cookiefound(EFalse);
   410     CCookieClientDataArray* cookieclientdataarray = CCookieClientDataArray::GetInstance();
   414     CCookieClientDataArray* cookieclientdataarray = iCookieMgrData->GetCookieClientDataArray();
   411     if(cookieclientdataarray)
   415     if(cookieclientdataarray)
   412         {
   416         {
   413          TInt clientarraycount = cookieclientdataarray->Count();
   417          TInt clientarraycount = cookieclientdataarray->Count();
   414          if (clientarraycount == 0)
   418          if (clientarraycount == 0)
   415            {
   419            {
   423          else
   427          else
   424            {
   428            {
   425         
   429         
   426             CLOG( ( EClient, 0, _L( "-> RCookieManager::GetClientSideCookies:" ) ) );
   430             CLOG( ( EClient, 0, _L( "-> RCookieManager::GetClientSideCookies:" ) ) );
   427             //Gets the Cookie objects for aUri in case it is present
   431             //Gets the Cookie objects for aUri in case it is present
   428             //TInt clerr = cookieclientdata->GetClientSideCookies(aUri,aCookies,cookiefound);
       
   429             TInt clerr = GetClientSideCookies(aUri,aCookies,cookiefound,aAppUid);
   432             TInt clerr = GetClientSideCookies(aUri,aCookies,cookiefound,aAppUid);
   430             CLOG( ( EClient, 0, _L( "RCookieManager::GetClientSideCookies:cookiefound = %d" ), cookiefound ) );
   433             CLOG( ( EClient, 0, _L( "RCookieManager::GetClientSideCookies:cookiefound = %d" ), cookiefound ) );
   431         
   434         
   432            }
   435            }
   433         } 
   436         } 
   449             TPtr8 des( buf->Des() );
   452             TPtr8 des( buf->Des() );
   450             User::LeaveIfError( DoGetCookies( des ) );
   453             User::LeaveIfError( DoGetCookies( des ) );
   451     
   454     
   452             // it seems this is the only place where we cannot avoid leaving
   455             // it seems this is the only place where we cannot avoid leaving
   453             // ==> we allocate memory for cookies when we fill up the cookie array.
   456             // ==> we allocate memory for cookies when we fill up the cookie array.
   454             iCookiePacker.UnpackCookiesFromBufferL( *buf, aCookies );
   457             iCookieMgrData->GetCookiePacker().UnpackCookiesFromBufferL( *buf, aCookies );
   455     
       
   456             TInt count = aCookies.Count();
   458             TInt count = aCookies.Count();
   457             for(TInt j=0; j<count; j++)
   459             for(TInt j=0; j<count; j++)
   458                 {
   460                 {
   459                 CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreClientSideCookies: aUri=%S" ), &aUri ) );
   461                 CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreClientSideCookies: aUri=%S" ), &aUri ) );
   460                 //cookieclientdata->StoreCookieAtClientSide( aCookies[j],aUri );
   462                 //cookieclientdata->StoreCookieAtClientSide( aCookies[j],aUri );
   493 //
   495 //
   494 EXPORT_C TInt RCookieManager::ClearAllAppUidCookies(const TUint32& aAppUid)
   496 EXPORT_C TInt RCookieManager::ClearAllAppUidCookies(const TUint32& aAppUid)
   495     {
   497     {
   496     CLOG(( EClient, 0, _L("-> RCookieManager::ClearCookies") ));
   498     CLOG(( EClient, 0, _L("-> RCookieManager::ClearCookies") ));
   497     //Client side cookie deletion specific to a appuid
   499     //Client side cookie deletion specific to a appuid
   498     CCookieClientDataArray::GetInstance()->DestroyClientData(aAppUid);
   500     iCookieMgrData->GetCookieClientDataArray()->DestroyClientData(aAppUid);
   499     //Server side Cookie deletion specific to a appuid
   501     //Server side Cookie deletion specific to a appuid
   500     //Appuid value only takes 8 chars
   502     //Appuid value only takes 8 chars
   501     HBufC* buf = HBufC::NewLC(8);
   503     HBufC* buf = HBufC::NewLC(8);
   502     TPtr ptr(buf->Des());
   504     TPtr ptr(buf->Des());
   503     ptr.AppendNum(aAppUid,EHex);
   505     ptr.AppendNum(aAppUid,EHex);
   512 //
   514 //
   513 void RCookieManager::StoreCookieAtClientSide( const CCookie* aCookie, const TDesC8& aUri,TUint32 aWidgetUid )
   515 void RCookieManager::StoreCookieAtClientSide( const CCookie* aCookie, const TDesC8& aUri,TUint32 aWidgetUid )
   514     {
   516     {
   515     CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreCookieAtClientSide" ) ) );
   517     CLOG( ( EClient, 0, _L( "-> RCookieManager::StoreCookieAtClientSide" ) ) );
   516     TUint32 groupid = RProcess().SecureId().iId;
   518     TUint32 groupid = RProcess().SecureId().iId;
   517     CCookieClientDataArray* cookieclientdataarray = CCookieClientDataArray::GetInstance();
   519     CCookieClientDataArray* cookieclientdataarray = iCookieMgrData->GetCookieClientDataArray();
       
   520     CCookieClientData* cookieclientdata(NULL);
   518     TInt count = cookieclientdataarray->Count();
   521     TInt count = cookieclientdataarray->Count();
       
   522     if (count == 0)
       
   523         {
       
   524         TBool cookieSharableFlag(EFalse);
       
   525         TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
       
   526         cookieclientdata = CCookieClientData::NewL(groupid, aWidgetUid, cookieSharableFlag,ETrue);
       
   527         cookieclientdata->SetInitFlag(ETrue);
       
   528         cookieclientdataarray->AddClientGroupDataL(cookieclientdata);
       
   529         cookieclientdata->StoreCookieAtClientSideL(aCookie,aUri);
       
   530         return;
       
   531         }
   519     TInt itemIndex =0;
   532     TInt itemIndex =0;
   520     for(TInt i=0; i<count; i++)
   533     for(TInt i=0; i<count; i++)
   521         {
   534         {
   522           if (cookieclientdataarray->At(i)->GetGroupId() == groupid 
   535           if (cookieclientdataarray->At(i)->GetGroupId() == groupid 
   523                   && cookieclientdataarray->At(i)->GetCookieSharableFlag())
   536                   && cookieclientdataarray->At(i)->GetCookieSharableFlag())
   531               {
   544               {
   532               itemIndex = i;
   545               itemIndex = i;
   533               break;
   546               break;
   534               }
   547               }
   535         }
   548         }
   536     CCookieClientData* cookieclientdata = cookieclientdataarray->At(itemIndex);
   549     cookieclientdata = cookieclientdataarray->At(itemIndex);
   537     cookieclientdata->StoreCookieAtClientSideL(aCookie,aUri);
   550     cookieclientdata->StoreCookieAtClientSideL(aCookie,aUri);
   538     CLOG( ( EClient, 0, _L( "<- RCookieManager::StoreCookieAtClientSide" ) ) );
   551     CLOG( ( EClient, 0, _L( "<- RCookieManager::StoreCookieAtClientSide" ) ) );
   539     }
   552     }
   540 
   553 
   541 // ---------------------------------------------------------
   554 // ---------------------------------------------------------
   545 TInt RCookieManager::GetClientSideCookies( const TDesC8& aRequestUri,RPointerArray<CCookie>& aCookies
   558 TInt RCookieManager::GetClientSideCookies( const TDesC8& aRequestUri,RPointerArray<CCookie>& aCookies
   546                 ,TBool& aCookieFound, TUint32 aWidgetUid )
   559                 ,TBool& aCookieFound, TUint32 aWidgetUid )
   547     {
   560     {
   548     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetClientSideCookies" ) ) );
   561     CLOG( ( EClient, 0, _L( "-> RCookieManager::GetClientSideCookies" ) ) );
   549     TUint32 groupid = RProcess().SecureId().iId;
   562     TUint32 groupid = RProcess().SecureId().iId;
   550     //TInt itemIndex =0;
       
   551     CCookieClientData* cookieclientdata = NULL;
   563     CCookieClientData* cookieclientdata = NULL;
   552     CCookieClientDataArray* cookieclientdataarray = CCookieClientDataArray::GetInstance();
   564     CCookieClientDataArray* cookieclientdataarray = iCookieMgrData->GetCookieClientDataArray();
   553     TInt count = cookieclientdataarray->Count();
   565     TInt count = cookieclientdataarray->Count();
   554     if (count == 0)
   566     if (count == 0)
   555         {
   567         {
   556         TBool cookieSharableFlag(EFalse);
   568         TBool cookieSharableFlag(EFalse);
   557         TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   569         TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   558         cookieclientdata = CCookieClientData::NewL(groupid, aWidgetUid, cookieSharableFlag,ETrue);
   570         cookieclientdata = CCookieClientData::NewL(groupid, aWidgetUid, cookieSharableFlag,ETrue);
   559         cookieclientdata->SetInitFlag(ETrue);
   571         cookieclientdata->SetInitFlag(ETrue);
   560         cookieclientdataarray->AddClientGroupDataL(cookieclientdata);
   572         cookieclientdataarray->AddClientGroupDataL(cookieclientdata);
   561         } else 
   573         } else 
   562            {
   574            {
   563            //harendra: move this for loop in CCookieClientDataArray::Find(), it should index or object
       
   564            cookieclientdata = cookieclientdataarray->Find(groupid, aWidgetUid);
   575            cookieclientdata = cookieclientdataarray->Find(groupid, aWidgetUid);
   565            }
   576            }
   566      if(cookieclientdata)
   577      if(cookieclientdata)
   567         {
   578         {
   568          if(!cookieclientdata->GetInitFlag())
   579          if(!cookieclientdata->GetInitFlag())
   569            {
   580            {
   570             TBool cookieSharableFlag(EFalse);
   581             TBool cookieSharableFlag(EFalse);
   571             TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   582             TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   572             cookieclientdata->SetCookieCookieSharableFlag(cookieSharableFlag);
   583             cookieclientdata->SetCookieCookieSharableFlag(cookieSharableFlag);
   573            }
   584            }
   574            //cookieclientdata->SetInitFlag(ETrue);
       
   575            return cookieclientdata->GetClientSideCookies( aRequestUri,aCookies, aCookieFound );
   585            return cookieclientdata->GetClientSideCookies( aRequestUri,aCookies, aCookieFound );
   576          } else 
   586          } else 
   577               {
   587               {
   578                TBool cookieSharableFlag(EFalse);
   588                TBool cookieSharableFlag(EFalse);
   579                TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   589                TInt err = GetCookieSharableFlagFromServer(cookieSharableFlag);
   586                }
   596                }
   587     CLOG( ( EClient, 0, _L( "<- RCookieManager::GetClientSideCookies" ) ) );
   597     CLOG( ( EClient, 0, _L( "<- RCookieManager::GetClientSideCookies" ) ) );
   588     return KErrNone;
   598     return KErrNone;
   589     }
   599     }
   590 
   600 
       
   601 RCookieManager::TCookieMgrInternalStruct::~TCookieMgrInternalStruct()
       
   602     {
       
   603     delete iCookieClientDataArray;
       
   604     }
       
   605 
       
   606 TInt RCookieManager::TCookieMgrInternalStruct::Init()
       
   607     {
       
   608     iCookieClientDataArray = CCookieClientDataArray::New();
       
   609     if (iCookieClientDataArray)
       
   610         return KErrNone;
       
   611     return KErrNoMemory;
       
   612         
       
   613     }
       
   614 
   591 // End of file
   615 // End of file