--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/favouritesengine/ClientServer/srvsrc/FavouritesSrvDb.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,2169 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Implementation of class CFavouritesSrvDb
+*
+*
+*/
+
+
+// INCLUDE FILES
+
+#include <s32std.h>
+#include <eikenv.h>
+#include <rfsApMapper.h>
+#include <commdb.h>
+#include "FavouritesSrvDb.h"
+#include "FavouritesSrvTable.h"
+#include "FavouritesItemImpl.h"
+#include "FavouritesItemImplList.h"
+#include "FavouritesPanic.h"
+#include "FavouritesLimits.h"
+#include "FavouritesItemData.h"
+#include "FavouritesFilter.h"
+#include "UidMap.h"
+#include "FavouritesLogger.h"
+#include "FavouritesFolder.h"
+
+
+
+// CONSTANTS
+
+/// Uid list granularity.
+LOCAL_D const TInt KUidListGranularity = 4;
+/// Postfix list granularity.
+LOCAL_D const TInt KPostfixListGranularity = 4;
+/// Number of updates needed to trigger automatic compaction.
+LOCAL_D const TInt KUpdatesNeededForAutoCompact = 32;
+/// Length of filename: 8 char.
+LOCAL_D const TInt KFnameLength = 8;
+
+// Secure policy ID of the Faveng database files.
+LOCAL_D const TUint KUidFavengDbPolicy = 0x101FD685;
+
+
+// ==================== LOCAL FUNCTIONS ====================
+
+/**
+* Given aName in the format <prefix> or <prefix><integer in parenthesis>,
+* return a pointer to the leading part. That is, if there is trailing
+* <integer in parenthesis>, then that is excluded; if there is no trailing
+* part, then the original decriptor is returned.
+* Examples:
+* - "Foo" returns "Foo";
+* - "Foo(12)" returns "Foo";
+* - "Foo(12 34)" returns "Foo(12 34)";
+*
+* @param aName Name to get prefix from.
+* @return Pointer to prefix part.
+*/
+LOCAL_C TPtrC GetPrefix( const TDesC& aName )
+ {
+ TPtrC prefix = aName;
+ TInt length = aName.Length();
+ if ( length >= 3 && aName[length - 1] == ')' )
+ {
+ // Any name shorter than 3 chars cannot have a postfix.
+ TInt openPar = aName.LocateReverse('(');
+ if ( openPar != KErrNotFound )
+ {
+ // aName looks like "<prefix>(<something>)".
+ // See if <something> is an integer number.
+ TPtrC num = aName.Mid( openPar + 1, length - openPar - 2);
+ TInt val;
+ TLex lex( num );
+ if ( lex.Val( val ) == KErrNone )
+ {
+ // Yes, the trailer is a parenthesized integer.
+ prefix.Set( aName.Left( openPar ) );
+ }
+ }
+ }
+ return prefix;
+ }
+
+/**
+* If aName is constructed from aPrefix with a positive integer postfix,
+* get the numeric value of the postfix, e.g:
+* - GetPostfix( "Foo(3)", "Foo" ) == 3
+* If aName is the same as aPrefix, return 0, e.g.:
+* - GetPostfix( "Foo", "Foo" ) == 0
+* If aName is not constructed from aPrefix, return -1, e.g.:
+* - GetPostfix( "Foobar", "Foo" ) == -1
+* - GetPostfix( "Foo(23 45)", "Foo" ) == -1
+* If postfix is 0 or negative, return -1, e.g.:
+* - GetPostfix( "Foo(00)", "Foo" ) == -1
+* - GetPostfix( "Foo(-8)", "Foo" ) == -1
+*
+* Return values for the following cases cannot be differentiated (-1 for all):
+* - postfix is 0;
+* - postfix is negative;
+* - aName not constructed from aPrefix.
+*
+* @param aName Name to get postfix from.
+* @param aPrefix Prefix to be searched.
+* @return Postfix value.
+*/
+LOCAL_C TInt GetPostfix( const TDesC& aName, const TDesC& aPrefix )
+ {
+ TInt postfix = -1;
+ TInt nameLength = aName.Length();
+ TInt prefixLength = aPrefix.Length();
+ if ( nameLength >= prefixLength && aName.FindF( aPrefix ) == 0 )
+ {
+ // aName is longer or equal length, and
+ // aPrefix can be found in the beginning of aName.
+ if ( nameLength == prefixLength )
+ {
+ // They have the same length; they equal.
+ postfix = 0;
+ }
+ else if (
+ nameLength - prefixLength >= 3 && // Because of this...
+ aName[prefixLength] == '(' &&
+ aName[nameLength - 1] == ')' // ... this is safe (*)
+ )
+ {
+ // (*) "aName[nameLength - 1]" no need to check whether this
+ // index is valid. nameLength is at least 3 characters longer
+ // than prefixLength (a positive integer) -> nameLength >= 3.
+
+ // aName looks like "aPrefix(<something>)".
+ // See if <something> is an integer number.
+ TPtrC num = aName.Mid
+ ( prefixLength + 1, nameLength - prefixLength - 2 ); // (**)
+ // (**) These are also safe because nameLength - prefixLength >= 3.
+ TInt val;
+ TLex lex( num );
+ if ( lex.Val( val ) == KErrNone && val > 0)
+ {
+ // Yes, the trailer is a positive integer.
+ postfix = val;
+ }
+ }
+ }
+ return postfix;
+ }
+
+/**
+* Generate filename for uid: return number as 8 character hex string.
+* @param aUid Uid.
+* @param aName Filename returned here. Minimum length KFnameLength.
+*/
+LOCAL_C void FilenameForUid( TInt aUid, TDes& aName )
+ {
+ __ASSERT_DEBUG( aName.MaxLength() >= KFnameLength, \
+ FavouritesPanic( EFavouritesInternal ) );
+ aName.NumFixedWidth( STATIC_CAST( TUint, aUid ), EHex, KFnameLength );
+ }
+
+/**
+* Get uid for filename; reverse of FilenameForUid.
+* @param aName Filename.
+* @return Uid or KFavouritesNullUid.
+*/
+LOCAL_C TInt UidForFilename( const TDesC& aName )
+ {
+ // Parse the supplied text as hex number.
+ TInt uid = KFavouritesNullUid;
+ if ( aName.Length() == KFnameLength )
+ {
+ // Length is OK, check contents.
+ TUint val;
+ TLex lex( aName );
+ if ( !lex.Val( val, EHex ) && lex.Eos() )
+ {
+ // OK, this filename can be parsed as hex TUint.
+ uid = STATIC_CAST( TInt, val );
+ }
+ }
+ return uid;
+ }
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+// ---------------------------------------------------------
+// CBookmarkSrvDb::NewL
+// ---------------------------------------------------------
+//
+CFavouritesSrvDb* CFavouritesSrvDb::NewL
+( RFs& aFs, RDbs& aDbs, const TDesC& aPath, const TDesC& aDBName )
+ {
+ CFavouritesSrvDb* db = new (ELeave) CFavouritesSrvDb( aFs, aDbs );
+ CleanupStack::PushL( db );
+ db->ConstructL( aPath , aDBName );
+ CleanupStack::Pop(); // db
+ return db;
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::~CFavouritesSrvDb
+// ---------------------------------------------------------
+//
+CFavouritesSrvDb::~CFavouritesSrvDb()
+ {
+ if ( iOpen )
+ {
+ if ( iInTransaction )
+ {
+ Rollback();
+ }
+ TRAP_IGNORE( DeleteOrphanedFilesL() );
+ // TODO move compacting to server side, when last client exits.
+ (void)iDatabase.Compact(); // Any error is silently ignored.
+ iDatabase.Close();
+ iOpen = EFalse;
+ }
+ delete iPath;
+ delete iSavedFilePath;
+ iSecureDbFormat.Close();
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::IsDamagedL
+// ---------------------------------------------------------
+//
+TBool CFavouritesSrvDb::IsDamagedL()
+ {
+ TBool damaged = EFalse;
+ // We must open a table to make RDbNameDatabase::IsDamaged() work!.
+ RFavouritesSrvTable table;
+ table.OpenL( iDatabase );
+ damaged = iDatabase.IsDamaged();
+ table.Close();
+ return damaged;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::RecoverL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::RecoverL()
+ {
+ User::LeaveIfError( iDatabase.Recover() );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CompactL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::CompactL()
+ {
+ User::LeaveIfError( iDatabase.Compact() );
+ iUpdatesSinceLastCompact = 0;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::Size
+// ---------------------------------------------------------
+//
+RDbDatabase::TSize CFavouritesSrvDb::Size() const
+ {
+ return iDatabase.Size();
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::UpdateStatsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::UpdateStatsL()
+ {
+ User::LeaveIfError( iDatabase.UpdateStats() );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::BeginL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::BeginL( TBool aWrite /*=EFalse*/ )
+ {
+ __ASSERT_DEBUG( !iInTransaction, \
+ FavouritesPanic( EFavouritesNestedTransaction ) );
+
+ // Three parts: table open + transacion + (optional) write lock.
+ // Temp use of cleanup items make the three atomic.
+ iTable.OpenL( iDatabase );
+ CleanupClosePushL<RFavouritesSrvTable>( iTable );
+ User::LeaveIfError( iDatabase.Begin() );
+ iInTransaction = ETrue;
+ CleanupStack::PushL( TCleanupItem( StaticRollback, this ) );
+ if ( aWrite )
+ {
+ iTable.PutWriteLockL();
+ }
+ CleanupStack::Pop( 2 ); // Rollback, Closing iTable
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CommitL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::CommitL()
+ {
+ __ASSERT_DEBUG( iInTransaction, \
+ FavouritesPanic( EFavouritesNoTransaction ) );
+
+ User::LeaveIfError( iDatabase.Commit() );
+ iInTransaction = EFalse;
+ iTable.Close();
+ if ( iUpdatesSinceLastCompact > KUpdatesNeededForAutoCompact )
+ {
+ // Auto-compact, to avoid overgrowth.
+ TRAP_IGNORE( CompactL() );
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::Rollback
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::Rollback()
+ {
+ __ASSERT_DEBUG( iInTransaction, \
+ FavouritesPanic( EFavouritesNoTransaction ) );
+
+ iDatabase.Rollback();
+ iInTransaction = EFalse;
+ iTable.Close();
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetL( TInt aUid, CFavouritesItemImpl& aItem )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.GetL();
+ iTable.ReadItemDataL( aItem );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetAllL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetAllL
+( CFavouritesItemImplList& aItemList, const TFavouritesFilter& aFilter )
+ {
+ TBool ownTransaction;
+
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.SetFiltersL( aFilter );
+ CFavouritesItemImpl* item;
+ iTable.BeginningL();
+ while( iTable.NextL() )
+ {
+ item = CFavouritesItemImpl::NewLC();
+ iTable.GetL();
+ iTable.ReadItemDataL( *item );
+ aItemList.AppendL( item );
+ CleanupStack::Pop(); // item; owner is the list now.
+ }
+ iTable.ClearFilters();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::PreferredUidL
+// ---------------------------------------------------------
+//
+TInt CFavouritesSrvDb::PreferredUidL( TInt aFolder )
+{
+ TInt uid( KFavouritesNullUid );
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ if ( iTable.SeekToUidL( aFolder ) )
+ {
+ iTable.GetL();
+ if ( iTable.Type() == CFavouritesItem::EFolder )
+ {
+ uid = iTable.PreferredUid();
+ }
+ }
+ CommitIfNeededL( ownTransaction );
+ return uid;
+}
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetUidsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetUidsL
+( CArrayFix<TInt>& aUids, const TFavouritesFilter& aFilter )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.SetFiltersL( aFilter );
+ iTable.BeginningL();
+ while( iTable.NextL() )
+ {
+ iTable.GetL();
+ aUids.AppendL( iTable.Uid() );
+ }
+ iTable.ClearFilters();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::DeleteL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::DeleteL( TInt aUid )
+ {
+ if ( aUid == KFavouritesRootUid || aUid == KFavouritesHomepageUid )
+ {
+ // Cannot delete these.
+ User::Leave( KErrAccessDenied );
+ }
+ // Make a list, to remember which items were deleted.
+ CArrayFix<TInt>* deletedUids =
+ new (ELeave) CArrayFixFlat<TInt>( KUidListGranularity );
+ CleanupStack::PushL( deletedUids );
+
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ DeleteCurrentL( *deletedUids );
+ CommitIfNeededL( ownTransaction );
+
+ // Delete associated files.
+ TInt i;
+ TBuf<KFnameLength> name;
+ TParse parse;
+ for ( i = 0; i < deletedUids->Count(); i++ )
+ {
+ FilenameForUid( deletedUids->At( i ), name );
+ User::LeaveIfError( parse.SetNoWild( name, iPath, NULL ) );
+ (void)iFs.Delete( parse.FullName() );
+ // Errors ignored; the file may be locked etc. etc.
+ // Orphaned file cleanup will remove them eventually.
+ }
+
+ CleanupStack::PopAndDestroy(); // deletedUids
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::UpdateL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::UpdateL
+( CFavouritesItemImpl& aItem, TInt aUid, TBool aAutoRename )
+ {
+ if ( aUid == KFavouritesRootUid ||
+ aUid == KFavouritesHomepageUid ||
+ aUid == KFavouritesLastVisitedUid )
+ {
+ // Cannot modify these.
+ // (Root cannot be modified at all; the others can be modified but
+ // not through this method.)
+ User::Leave( KErrAccessDenied );
+ }
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ UpdateCurrentL( aItem, aAutoRename ? EAutoRename : EDontRename );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::AddL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::AddL( CFavouritesItemImpl& aItem, TBool aAutoRename )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ DoAddL( aItem, aAutoRename ? EAutoRename : EDontRename );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetSpecialItemL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetSpecialItemL( CFavouritesItemImpl& aItem, TInt aUid )
+ {
+ __ASSERT_DEBUG( \
+ aUid == KFavouritesHomepageUid || aUid == KFavouritesLastVisitedUid, \
+ FavouritesPanic( EFavouritesInternal )
+ );
+
+ if ( aItem.ParentFolder() != KFavouritesRootUid )
+ {
+ // Must be in root.
+ User::Leave( KErrArgument );
+ }
+
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ if ( iTable.SeekToUidL( aUid ) )
+ {
+ UpdateCurrentL( aItem, ESuppressCheck );
+ }
+ else
+ {
+ DoAddL( aItem, ESuppressCheck );
+ // Cursor is still on the new record. Write uid back.
+ iTable.UpdateLC();
+ iTable.SetUidL( aUid );
+ iTable.PutL();
+ aItem.SetUid( aUid ); // Get uid back.
+ aItem.SetModified( iTable.Modified() ); // Get modtime.
+ }
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetFactoryItemL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetFactoryItemL( TInt aUid, TBool aFactoryItem )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.UpdateLC();
+ iTable.SetFactoryItemL( aFactoryItem );
+ iTable.PutL();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetReadOnlyL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetReadOnlyL( TInt aUid, TBool aReadOnly )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.UpdateLC();
+ iTable.SetReadOnlyL( aReadOnly );
+ iTable.PutL();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetModifiedL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetModifiedL( TInt aUid, TTime aModified )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.UpdateLC();
+ iTable.SetModifiedL( aModified );
+ iTable.PutL( /*aTouch=*/ EFalse );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetPreferredUidL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetPreferredUidL( TInt aFolder, TInt aUid )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aFolder );
+ iTable.GetL();
+ if ( iTable.Type() == CFavouritesItem::EFolder )
+ {
+ iTable.UpdateLC();
+ iTable.SetPreferredUidL( aUid );
+ iTable.PutL();
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::ItemExistsL
+// ---------------------------------------------------------
+//
+TBool CFavouritesSrvDb::ItemExistsL( TInt aUid )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ TBool res = iTable.SeekToUidL( aUid );
+ CommitIfNeededL( ownTransaction );
+ return res;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::FolderExistsL
+// ---------------------------------------------------------
+//
+TBool CFavouritesSrvDb::FolderExistsL( TInt aFolder )
+ {
+ TBool res = EFalse;
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ if ( iTable.SeekToUidL( aFolder ) )
+ {
+ iTable.GetL();
+ if ( iTable.Type() == CFavouritesItem::EFolder )
+ {
+ res = ETrue;
+ }
+ }
+ CommitIfNeededL( ownTransaction );
+ return res;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CountL
+// ---------------------------------------------------------
+//
+TInt CFavouritesSrvDb::CountL( const TFavouritesFilter& aFilter )
+ {
+ TInt count = 0;
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.SetFiltersL( aFilter );
+ // Get all items in the aFolder.
+ iTable.BeginningL();
+ while( iTable.NextL() )
+ {
+ count++;
+ }
+ iTable.ClearFilters();
+ CommitIfNeededL( ownTransaction );
+ return count;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetDataL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetDataL( TInt aUid, MStreamBuf& aSource )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.UpdateLC();
+ iTable.SetExtraDataL( aSource );
+ iTable.PutL();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetDataL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetDataL( TInt aUid, MStreamBuf& aSink )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.GetL();
+ iTable.GetExtraDataL( aSink );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetBrowserDataL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetBrowserDataL( TInt aUid, MStreamBuf& aSource )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.UpdateLC();
+ iTable.SetBrowserDataL( aSource );
+ iTable.PutL();
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetBrowserDataL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetBrowserDataL( TInt aUid, MStreamBuf& aSink )
+ {
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ iTable.GetL();
+ iTable.GetBrowserDataL( aSink );
+ CommitIfNeededL( ownTransaction );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::MakeUniqueNameL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::MakeUniqueNameL( TDes& aName, TInt aFolder )
+ {
+ // Trim aName first.
+ HBufC* buf = HBufC::NewLC( aName.Length() + KFavouritesMaxPostfix );
+ TPtr ptr( buf->Des() );
+ CFavouritesItemImpl::MakeName( aName, ptr );
+
+ if ( !CFavouritesItemImpl::IsValidName( ptr ) )
+ {
+ User::Leave( KErrBadName ); // aName is invalid.
+ }
+
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ if ( !FolderExistsL( aFolder ) )
+ {
+ User::Leave( KErrArgument ); // No parent folder.
+ }
+
+ if ( !IsUniqueNameL( ptr, aFolder, KFavouritesNullUid ) )
+ {
+ MakeUniqueNameL( ptr, aFolder, KFavouritesNullUid );
+ }
+ // Always set it back, even if it was unique in the first place:
+ // It may be trimmed.
+ aName = ptr;
+
+ CommitIfNeededL( ownTransaction );
+ CleanupStack::PopAndDestroy(); // buf
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::RestoreFactorySettingsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::RestoreFactorySettingsL
+( const TDesC& aReferenceDbPath, CUidMap& aApMap )
+ {
+ __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
+ FLOG(( _L("restoer: FavoritesSvrDb.cpp CFavouritesSrvDb::RestoreFactorySettingsL") ));
+
+ // Open a read-only database on the reference db (client-side access).
+ RDbNamedDatabase refDb;
+
+ FLOG(( _L("CFavouritesSrvDb::RestoreFactorySettingsL before Leave call") ));
+
+ RFs fsSession;
+ User::LeaveIfError(fsSession.Connect());
+
+ CleanupClosePushL(fsSession);
+ User::LeaveIfError(refDb.Open(fsSession, aReferenceDbPath, TPtrC(), RDbNamedDatabase::EReadOnly));
+
+ FLOG(( _L("CFavouritesSrvDb::RestoreFactorySettingsL after Leave call") ));
+ CleanupClosePushL<RDbNamedDatabase>( refDb );
+ // Open a read-only table on the database.
+ RFavouritesSrvTable refTable;
+ refTable.OpenL( refDb, RDbRowSet::EReadOnly );
+ CleanupClosePushL<RFavouritesSrvTable>( refTable );
+ // No transaction needed - the database is opened read-only
+ // with exclusive access.
+ RestoreFactorySettingsL( refTable, aApMap );
+ CleanupStack::PopAndDestroy( 2 ); // close refTable, close refDb
+
+ CleanupStack::PopAndDestroy(); // close fsSession
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSession::InitSavedFilePathL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::InitSavedFilePathL( const TDesC& aDBName )
+ {
+ TParse parse;
+ TDriveName cDrive = TDriveUnit( EDriveC ).Name();
+ TFileName path;
+ User::LeaveIfError( iFs.PrivatePath( path ) );
+ User::LeaveIfError( parse.SetNoWild( path, &cDrive, NULL ) );
+ parse.AddDir(aDBName);
+ delete iSavedFilePath;
+ iSavedFilePath = NULL;
+
+ iSavedFilePath = parse.FullName().AllocL();
+ iFs.CreatePrivatePath(EDriveC);
+ iFs.MkDirAll(*iSavedFilePath);
+ }
+
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::FilenameL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::FilenameL( TInt aUid, TParse& aParse )
+ {
+ // Check if item exists.
+ TBool ownTransaction;
+ BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
+ iTable.GotoToUidL( aUid );
+ CommitIfNeededL( ownTransaction );
+ // Generate filename.
+ TBuf<KFnameLength> name;
+ FilenameForUid( aUid, name );
+ // Append filename to session path.
+ User::LeaveIfError( aParse.SetNoWild( name, iSavedFilePath, NULL ) );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CFavouritesSrvDb
+// ---------------------------------------------------------
+//
+CFavouritesSrvDb::CFavouritesSrvDb( RFs& aFs, RDbs& aDbs )
+: iFs( aFs ),
+ iDbs( aDbs ),
+ iOpen( EFalse ),
+ iInTransaction( EFalse ),
+ iUpdatesSinceLastCompact( 0 )
+ {
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::ConstructL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::ConstructL( const TDesC& aPath, const TDesC& aDBName )
+ {
+ const TUid KDbPolicyUid = TUid::Uid(KUidFavengDbPolicy);
+
+ iPath = aPath.AllocL();
+
+ InitSavedFilePathL(aDBName );
+
+ _LIT( KSecureKeyword, "SECURE" );
+ iSecureDbFormat.CreateL( KSecureKeyword(), KSecureKeyword().Length() +
+ KDbPolicyUid.Name().Length() );
+ iSecureDbFormat += KDbPolicyUid.Name();
+
+ // Check if we have the database.
+ TBool isDbExists = EFalse;
+
+ CDbDatabaseNames *dbNames = iDbs.DatabaseNamesL(EDriveC, KDbPolicyUid);
+
+ CleanupStack::PushL(dbNames);
+
+ TParse dbFile;
+ User::LeaveIfError( dbFile.SetNoWild( aPath, NULL, NULL ) );
+
+ for(int i = 0; i < dbNames->Count(); i++)
+ {
+ if( (*dbNames)[i] == dbFile.NameAndExt() )
+ {
+ isDbExists = ETrue;
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(dbNames);
+
+ if ( !isDbExists )
+ {
+ // No such database. Make it now.
+ TInt err = KErrNone;
+ TBool doImport = ( aDBName.Compare( KBrowserBookmarks ) == 0 );
+ TRAP( err, CreateDatabaseL( dbFile, doImport ) );
+
+ // Bookmark import failed. Create an empty DB
+ if ( err && doImport )
+ {
+ iDbs.DeleteDatabase( aPath, KDbPolicyUid );
+ TRAP( err, CreateDatabaseL( dbFile, EFalse ) );
+ }
+ if ( err )
+ {
+ // Should anything go wrong during the database creation,
+ // delete the database. This ensures that we never have
+ // half-constructed database (e.g. database created but no
+ // root folder because of leave). No data is lost by deleting
+ // the file; it has just been created.
+ iDbs.DeleteDatabase( aPath, KDbPolicyUid );
+ User::Leave( err );
+ }
+ }
+
+ // Here we have the database, successfully created. It is closed now.
+ // Open it and make some repairs if needed.
+ TInt error;
+ error = iDatabase.Open( iDbs, dbFile.FullName(), iSecureDbFormat );
+ if (error != KErrNone)
+ {
+ User::Leave( error );
+ }
+ iOpen = ETrue;
+ if ( IsDamagedL() )
+ {
+ RecoverL();
+ }
+ // Verify structure and upgrade if needed.
+ RFavouritesSrvTable::VerifyStructureL( iDatabase, ETrue );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::DeleteOrphanedFilesL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::DeleteOrphanedFilesL()
+ {
+ // Get all uids and sort them by uid.
+ CArrayFix<TInt>* uids =
+ new (ELeave) CArrayFixFlat<TInt>( KUidListGranularity );
+ CleanupStack::PushL( uids );
+ GetUidsL( *uids, TFavouritesFilter() );
+ TKeyArrayFix key( 0, ECmpTInt32 );
+ uids->Sort( key );
+
+ // Get a directory listing.
+ RDir dir;
+ User::LeaveIfError( dir.Open( iFs, *iSavedFilePath, KEntryAttNormal ) );
+ CleanupClosePushL<RDir>( dir );
+
+ TEntryArray files;
+ TInt err = dir.Read( files );
+ if( err != KErrEof ) // KErrEof means all files read.
+ {
+ User::Leave( err );
+ }
+
+ // Now check if any of the files is orphaned.
+ TParse parse;
+ TInt dummy;
+ TInt uid;
+ TInt i;
+ const TInt KElementFound = 0;
+
+ for ( i = 0; i < files.Count(); i++ )
+ {
+ uid = UidForFilename( files[i].iName );
+ if ( uid == KFavouritesNullUid ||
+ uids->FindIsq( uid, key, dummy ) != KElementFound )
+ {
+ // The filename is in the required format (8 char hex number),
+ // but no item for this file -> an orphaned file.
+ User::LeaveIfError
+ ( parse.SetNoWild( files[i].iName, iSavedFilePath, NULL ) );
+ (void)iFs.Delete( parse.FullName() );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 2, uids ); // dir, uids
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::BeginIfNeededL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::BeginIfNeededL( TBool aWrite, TBool& aOwnTransaction )
+ {
+ aOwnTransaction = EFalse;
+ if ( !iInTransaction )
+ {
+ // Not in transaction yet.
+ BeginL( aWrite );
+ aOwnTransaction = ETrue;
+ CleanupStack::PushL( TCleanupItem( StaticRollback, this ) );
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CommitIfNeeded
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::CommitIfNeededL( TBool aOwnTransaction )
+ {
+ if ( aOwnTransaction )
+ {
+ CommitL();
+ CleanupStack::Pop(); // StaticRollback, pushed in BeginL
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CreateDatabaseL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::CreateDatabaseL( TParse& aDbFile, TBool aDoImport )
+ {
+ // Make the database.
+ //
+ TInt errorCode = iDatabase.Create( iDbs, aDbFile.FullName(), iSecureDbFormat);
+
+ User::LeaveIfError( errorCode );
+ CleanupClosePushL<RDbNamedDatabase>( iDatabase );
+ // Create table.
+ RFavouritesSrvTable::CreateStructureL( iDatabase );
+ // Create the root folder. No need to close the database after schema
+ // modifications in ER5.
+ CreateRootFolderL();
+ // If the bookmark import file exists on the z: drive, re-import the bookmarks.
+#ifndef __WINSCW__
+ _LIT(KBookmarkImportFile,"z:\\data\\BookmarkImportSample.txt"); // armv5
+#else
+ _LIT(KBookmarkImportFile,"c:\\private\\10008d38\\BookmarkImportSample.txt"); // winscw
+#endif
+ if( aDoImport )
+ {
+ TUint attImport;
+ User::LeaveIfError( iFs.Connect() );
+ TInt errImport = iFs.Att( KBookmarkImportFile(), attImport );
+ if ( errImport == KErrNone )
+ {
+ // Bookmark import file exists. Import to browserbookmarks.db database.
+ ImportL( KBookmarkImportFile() );
+ }
+ }
+ CleanupStack::PopAndDestroy(); // close iDatabase
+ }
+
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::CreateRootFolderL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::CreateRootFolderL()
+ {
+ // Database just created; we have exclusive access.
+ iTable.OpenL( iDatabase );
+ CleanupClosePushL<RFavouritesSrvTable>( iTable );
+ CFavouritesItemImpl* root = CFavouritesItemImpl::NewLC();
+ // Add a new empty folder to the database.
+ root->SetType( CFavouritesItem::EFolder );
+ root->SetParentFolder( KFavouritesNullUid );
+ iTable.InsertLC();
+ iTable.WriteItemDataL( *root );
+ // Now the cursor is positioned over the new entry; change its Uid
+ // so it becomes the root folder.
+ iTable.SetUidL( KFavouritesRootUid );
+ iTable.PutL();
+ // Now we have the root. The first entry added came with 0 Uid, so this
+ // value will never be used again.
+ CleanupStack::PopAndDestroy( 2 ); // root, close iTable
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::DeleteCurrentL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::DeleteCurrentL( CArrayFix<TInt>& aDeletedUids )
+ {
+ TInt uid;
+ iTable.GetL();
+ if( iTable.ReadOnly() )
+ {
+ User::Leave( KErrAccessDenied );
+ }
+ if ( iTable.Type() == CFavouritesItem::EFolder )
+ {
+ // This is a folder. Delete contents.
+ // Save cursor pos, since the cursor will be moved.
+ TDbBookmark originalPos = iTable.Bookmark();
+ iTable.SetFiltersL( TFavouritesFilter( iTable.Uid(),
+ CFavouritesItem::ENone, NULL, KFavouritesNullContextId ) );
+ iTable.BeginningL();
+ while ( iTable.NextL() )
+ {
+ iTable.GetL();
+ if( iTable.ReadOnly() )
+ {
+ // Read-only item in a non-read-only folder.
+ User::Leave( KErrAccessDenied );
+ }
+ else
+ {
+ // Get uid of item to be deleted
+ uid = iTable.Uid();
+ iTable.DeleteL();
+ aDeletedUids.AppendL( uid );
+ iUpdatesSinceLastCompact++;
+ }
+ }
+ // Restore cursor pos.
+ iTable.ClearFilters();
+ iTable.GotoL( originalPos );
+ iTable.GetL();
+ }
+
+ // Now delete the item itself. If it's a folder and there is no error
+ // so far, it is empty by now. Error indicates read-only item in this
+ // non-read-only folder, so keep the folder as well.
+ uid = iTable.Uid();
+ iTable.DeleteL();
+ aDeletedUids.AppendL( uid );
+ iUpdatesSinceLastCompact++;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::UpdateCurrentL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::UpdateCurrentL
+( CFavouritesItemImpl& aItem, CFavouritesSrvDb::TRenameType aRenameType )
+ {
+ if ( !CFavouritesItemImpl::IsValidName( aItem.Name() ) )
+ {
+ // CFavouritesItemImpl::IsValidL also checks this; but we want to
+ // return different error code for this case, so manually check this
+ // first.
+ User::Leave( KErrBadName );
+ }
+
+ if ( !aItem.IsValid() )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ HBufC* newName = NULL;
+ // Save cursor pos; parent folder and name checking will move it.
+ TDbBookmark originalPos = iTable.Bookmark();
+ iTable.GetL();
+ TInt oldParent = iTable.ParentFolder();
+ TInt uid = iTable.Uid();
+ if ( iTable.Type() != aItem.Type() )
+ {
+ // Cannot change type.
+ User::Leave( KErrArgument );
+ }
+
+ if ( iTable.ReadOnly() )
+ {
+ // Read-only item.
+ User::Leave( KErrAccessDenied );
+ }
+
+ if ( aItem.Type() == CFavouritesItem::EFolder &&
+ aItem.ParentFolder() != KFavouritesRootUid )
+ {
+ // Folders must be in the root folder
+ // (folder hierarchy is only one-level deep).
+ User::Leave( KErrArgument );
+ }
+
+ if ( oldParent != aItem.ParentFolder() &&
+ !FolderExistsL( aItem.ParentFolder() ) )
+ {
+ // No parent folder.
+ // (Not checked if the parent folder has not changed.)
+ User::Leave( KErrArgument );
+ }
+
+ if ( aRenameType != ESuppressCheck )
+ {
+ if ( !IsUniqueNameL( aItem.Name(), aItem.ParentFolder(), uid ) )
+ {
+ if ( aRenameType == EAutoRename )
+ {
+ // Name is conflicting, rename automatically.
+ newName = AllocUniqueNameLC
+ ( aItem.Name(), aItem.ParentFolder(), uid );
+ }
+ else
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+ }
+ }
+
+ // All is well so far; update is valid.
+ iTable.PutWriteLockL();
+ // If there is a new name, set it.
+ if ( newName )
+ {
+ aItem.SetNameL( *newName );
+ }
+ // Validation may have moved the cursor; set it back.
+ iTable.GotoL( originalPos );
+ iTable.UpdateLC(); // Prepare for update.
+ iTable.WriteItemDataL( aItem ); // Put the data.
+ iTable.SetFactoryItemL( EFalse );
+ iTable.PutL(); // Apply changes.
+ aItem.SetUid( iTable.Uid() ); // Get Uid.
+ aItem.SetModified( iTable.Modified() ); // Get modtime.
+ // Sanity check; it must be the specified Uid.
+ __ASSERT_DEBUG( aItem.Uid() == uid,
+ FavouritesPanic( EFavouritesInternal ) );
+ iUpdatesSinceLastCompact++;
+
+ if ( newName )
+ {
+ CleanupStack::PopAndDestroy(); // newName
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::DoAddL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::DoAddL
+ (
+ CFavouritesItemImpl& aItem,
+ CFavouritesSrvDb::TRenameType aRenameType,
+ TBool aFactoryItem /*=EFalse*/,
+ TBool aReadOnly /*=EFalse*/
+ )
+ {
+ if ( !CFavouritesItemImpl::IsValidName( aItem.Name() ) )
+ {
+ // CFavouritesItemImpl::IsValidL also checks this; but we want to
+ // return different error code for this case, so manually check this
+ // first.
+ User::Leave( KErrBadName );
+ }
+
+ if ( !aItem.IsValid() )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ HBufC* newName = NULL;
+ if ( aItem.Type() == CFavouritesItem::EFolder &&
+ aItem.ParentFolder() != KFavouritesRootUid )
+ {
+ // Folders must be in the root folder
+ // (folder hierarchy is only one-level deep).
+ User::Leave( KErrArgument );
+ }
+
+ if ( !FolderExistsL( aItem.ParentFolder() ) )
+ {
+ // No parent folder.
+ User::Leave( KErrArgument );
+ }
+
+ if ( aRenameType != ESuppressCheck )
+ {
+ if ( !IsUniqueNameL
+ ( aItem.Name(), aItem.ParentFolder(), KFavouritesNullUid ) )
+ {
+ if ( aRenameType == EAutoRename )
+ {
+ // Name is conflicting, rename automatically.
+ newName = AllocUniqueNameLC
+ ( aItem.Name(), aItem.ParentFolder(), KFavouritesNullUid );
+ }
+ else
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+ }
+ }
+
+ // All is well so far; update is valid.
+ iTable.PutWriteLockL();
+ // If there is a new name, set it.
+ if ( newName )
+ {
+ aItem.SetNameL( *newName );
+ }
+ // Validation may have moved the cursor; set it back.
+ iTable.InsertLC(); // Prepare for update.
+ iTable.WriteItemDataL( aItem ); // Put the data.
+ iTable.SetFactoryItemL( aFactoryItem );
+ iTable.SetReadOnlyL( aReadOnly );
+ iTable.PutL(); // Apply changes.
+ aItem.SetUid( iTable.Uid() ); // Get Uid.
+ aItem.SetModified( iTable.Modified() ); // Get modtime.
+ // Sanity check; no item can exist with the Null uid.
+ __ASSERT_DEBUG( aItem.Uid() != KFavouritesNullUid,
+ FavouritesPanic( EFavouritesNullUidInDatabase ) );
+ iUpdatesSinceLastCompact++;
+
+ if ( newName )
+ {
+ CleanupStack::PopAndDestroy(); // newName
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::IsUniqueNameL
+// ---------------------------------------------------------
+//
+TBool CFavouritesSrvDb::IsUniqueNameL
+( const TDesC& aName, TInt aFolder, TInt aAcceptUid )
+ {
+ __ASSERT_DEBUG( CFavouritesItemImpl::IsValidName( aName ), \
+ FavouritesPanic( EFavouritesInternal ) );
+ TBool unique = ETrue;
+ TInt uid;
+ iTable.SetFiltersL( TFavouritesFilter( aFolder, CFavouritesItem::ENone,
+ &aName, KFavouritesNullContextId ) );
+ iTable.BeginningL();
+ while ( iTable.NextL() )
+ {
+ // We have an item with this name; check if it is aAcceptUid or
+ // one of the special items (for which names need not be unique).
+ iTable.GetL();
+ uid = iTable.Uid();
+ if (
+ uid != aAcceptUid &&
+ uid != KFavouritesHomepageUid &&
+ uid != KFavouritesLastVisitedUid &&
+ uid != KFavouritesStartPageUid &&
+ uid != KFavouritesAdaptiveItemsFolderUid
+ )
+ {
+ // It's not aAcceptUid or special item. We have a name clash.
+ unique = EFalse;
+ break;
+ }
+ }
+ iTable.ClearFilters();
+ return unique;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::MakeNameUniqueL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::MakeUniqueNameL
+( TDes& aName, TInt aFolder, TInt aAcceptUid )
+ {
+ TBool forcePostfix = EFalse;
+ __ASSERT_DEBUG( CFavouritesItemImpl::IsValidName( aName ), \
+ FavouritesPanic( EFavouritesInternal ) );
+ // Make sure the result fits.
+ __ASSERT_DEBUG( aName.MaxLength() >= Min\
+ ( aName.Length() + KFavouritesMaxPostfix, KFavouritesMaxName ), \
+ FavouritesPanic( EFavouritesBufferTooSmall ) );
+
+ TPtrC prefix = GetPrefix( aName );
+ if ( prefix.Length() + KFavouritesMaxPostfix > KFavouritesMaxName )
+ {
+ // Oops, this prefix is so long that if we append the longest possible
+ // postfix to it, the result will not fit into a bookmark name!
+ // In this case, we truncate the prefix. The truncated prefix is most
+ // likely not conflicting as is, but we do the postfix appending
+ // anyway.
+ prefix.Set
+ ( prefix.Left( KFavouritesMaxName - KFavouritesMaxPostfix ) );
+ forcePostfix = ETrue;
+ }
+ HBufC* buf = HBufC::NewLC( prefix.Length() + KFavouritesMaxPostfix );
+ _LIT( KFormatPrefix, "%S*" );
+ buf->Des().Format( KFormatPrefix, &prefix );
+ iTable.SetFiltersL( TFavouritesFilter
+ ( aFolder, CFavouritesItem::ENone, buf, KFavouritesNullContextId ) );
+ CleanupStack::PopAndDestroy(); // buf
+
+ TInt uid;
+ TInt postfix;
+ CArrayFix<TInt>* postfixes =
+ new (ELeave) CArrayFixFlat<TInt>( KPostfixListGranularity );
+ CleanupStack::PushL( postfixes );
+ iTable.BeginningL();
+ while ( iTable.NextL() )
+ {
+ iTable.GetL();
+ uid = iTable.Uid();
+ if (
+ uid != aAcceptUid &&
+ uid != KFavouritesHomepageUid &&
+ uid != KFavouritesLastVisitedUid &&
+ uid != KFavouritesStartPageUid &&
+ uid != KFavouritesAdaptiveItemsFolderUid
+ )
+ {
+ // Appending all values (incl. negative values and duplicates).
+ postfixes->AppendL( GetPostfix( iTable.Name(), prefix ) );
+ }
+ }
+ iTable.ClearFilters();
+
+ // Sort postfixes ascending.
+ TKeyArrayFix key( 0, ECmpTInt );
+ User::LeaveIfError( postfixes->Sort( key ) );
+
+ // Initial postfix candidate is 0 ("no postfix"), or 1 if forcePostfix
+ // is ETrue.
+ postfix = forcePostfix ? 1 : 0;
+ // Find the first free postfix, above the starting candidate (0 or 1).
+ // The loop skips negative values and duplicates.
+ TInt i;
+ for ( i = 0; i < postfixes->Count(); i++ )
+ {
+ if ( postfixes->At( i ) < postfix )
+ {
+ // This value is smaller than the current candidate;
+ // candidate stays the current one (do nothing); but keep checking
+ // forthcoming bigger values (continue).
+ ;
+ }
+ else if ( postfixes->At( i ) == postfix )
+ {
+ // This postfix already taken. Candidate is next one.
+ postfix++;
+ }
+ else
+ {
+ // postfixes->At( i ) > postfix: a "hole" is found.
+ //
+ // This case could be the condition in the controlling "for" (and
+ // the "break" statement could be avoided); but I intentionally
+ // placed it here so the logic of the "hole-search" can be seen
+ // more clearly.
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(); // postfixes
+
+ if ( postfix == 0 )
+ {
+ // First unique name is the prefix without any postfix.
+ // Simply set length to the prefix length.
+ aName.SetLength( prefix.Length() );
+ }
+ else
+ {
+ // Append a new postfix to the prefix.
+ // It seems we have to copy the prefix into a buffer.
+ // The prefix points to aName, so Format would format aName
+ // using the prefix from itself. But Format does some weird
+ // tricks (filling the buffer with some rubbish before writing
+ // into it). It's not sprintf :-(.
+ buf = prefix.AllocLC();
+ _LIT( KFormatSmallPostfix, "%S(0%d)" );
+ _LIT( KFormatLargePostfix, "%S(%d)" );
+ if ( postfix < 10 )
+ {
+ aName.Format( KFormatSmallPostfix, buf, postfix );
+ }
+ else
+ {
+ aName.Format( KFormatLargePostfix, buf, postfix );
+ }
+ CleanupStack::PopAndDestroy(); // buf
+ }
+
+ // Sanity check. The generated name should really be unique.
+ __ASSERT_DEBUG \
+ ( \
+ IsUniqueNameL( aName, aFolder, aAcceptUid ), \
+ FavouritesPanic( EFavouritesInternal ) \
+ );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::AllocUniqueNameLC
+// ---------------------------------------------------------
+//
+HBufC* CFavouritesSrvDb::AllocUniqueNameLC
+( const TDesC& aName, TInt aFolder, TInt aAcceptUid )
+ {
+ HBufC* uniqueName = HBufC::NewLC( aName.Length() + KFavouritesMaxPostfix );
+ *uniqueName = aName;
+ TPtr ptr( uniqueName->Des() );
+ MakeUniqueNameL( ptr, aFolder, aAcceptUid );
+ return uniqueName;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::StaticRollback
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::StaticRollback( TAny* aDb )
+ {
+ STATIC_CAST( CFavouritesSrvDb*, aDb )->Rollback();
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::RestoreFactorySettingsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::RestoreFactorySettingsL
+( RFavouritesSrvTable& aReferenceTable, CUidMap& aApMap )
+ {
+ __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
+
+ // 1. Check ContextId-s of folders in reference table, and clear all those
+ // ContextId-s from our folders.
+ //
+ // This part is a bit "out of line" for the Engine, as here we do deal
+ // with ContextId semantics: we ensure that we don't create more folders
+ // with a given ContextId. This ensures the expected correct behaviour
+ // of Seamless Link functionality after an RFS: the newly restored
+ // folders become the Seamless Link folders.
+ // (Note: if the reference table contains more folders with the same
+ // ContextId, they will be mechanically copied. Checking that is really
+ // not our business.)
+
+ TInt32 contextId;
+ aReferenceTable.BeginningL();
+ while ( aReferenceTable.NextL() )
+ {
+ aReferenceTable.GetL();
+ contextId = aReferenceTable.ContextId();
+ if ( contextId != KFavouritesNullContextId )
+ {
+ // Folders from root with given context id.
+ iTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
+ CFavouritesItem::EFolder, NULL, contextId ) );
+ iTable.BeginningL();
+ while( iTable.NextL() )
+ {
+ iTable.UpdateLC();
+ iTable.SetContextIdL( KFavouritesNullContextId );
+ iTable.PutL( /*aTouch=*/EFalse );
+ }
+ iTable.ClearFilters();
+ }
+ }
+
+ // 2. Delete all items that have the "factory item" flag.
+ // (These are the unmodified factory items - any modification
+ // clears the flag.) The "factory item" and read-only flag of floders are cleared.
+
+ iTable.BeginningL();
+ while ( iTable.NextL() )
+ {
+ iTable.GetL();
+ if ( iTable.FactoryItem() )
+ {
+ switch ( iTable.Type() )
+ {
+ case CFavouritesItem::EItem:
+ {
+ // Delete unmodified factory item
+ iTable.DeleteL();
+ break;
+ }
+
+ case CFavouritesItem::EFolder:
+ {
+ // Clear flags for folders.
+ iTable.UpdateLC();
+ iTable.SetFactoryItemL( EFalse );
+ iTable.SetReadOnlyL( EFalse );
+ iTable.PutL( /*aTouch=*/EFalse );
+ break;
+ }
+
+ default:
+ {
+ FavouritesPanic( EFavouritesInternal );
+ break;
+ }
+ }
+ }
+ }
+
+ // 3. Lookup folders by name, creating new ones if necessary. The target
+ // folder gets the attributes of the source folder (read-only and
+ // factory item flag), regardless of whether it is existing or newly
+ // created. During this process, a mapping table
+ // (source folder uid -> target folder uid) is built.
+
+ TTime modTime;
+ SUidPair mapping;
+ TPtrC name;
+ CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
+ CUidMap* parentMap = new (ELeave) CUidMap( 1 );
+ CleanupStack::PushL( parentMap );
+
+ // Add the "root->root" mapping to the map.
+ mapping.iUid1 = KFavouritesRootUid;
+ mapping.iUid2 = KFavouritesRootUid;
+ parentMap->AppendL( mapping );
+
+ // All folder of reference table in root.
+ aReferenceTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
+ CFavouritesItem::EFolder, NULL, KFavouritesNullContextId ) );
+ aReferenceTable.BeginningL();
+ while( aReferenceTable.NextL() )
+ {
+ aReferenceTable.GetL();
+ name.Set( aReferenceTable.Name() );
+ __ASSERT_DEBUG( name.Length(), FavouritesPanic( EFavouritesInternal ) );
+ // Folders matching the name.
+ iTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
+ CFavouritesItem::EFolder, &name, KFavouritesNullContextId ) );
+ iTable.BeginningL();
+ if( iTable.NextL() )
+ {
+ // Folder exists with this name.
+ // Copy read-only and factory item flags from reference table.
+ // Also copy ContextId (possibly we cleared that earlier).
+ iTable.UpdateLC();
+ iTable.SetReadOnlyL( aReferenceTable.ReadOnly() );
+ iTable.SetFactoryItemL( aReferenceTable.FactoryItem() );
+ iTable.SetContextIdL( aReferenceTable.ContextId() );
+ iTable.PutL( /*aTouch=*/EFalse );
+ }
+ else
+ {
+ // No folder exists with this name.
+ // Add now by copying from reference table (incl. modtime).
+ aReferenceTable.ReadItemDataL( *item );
+ modTime = item->Modified();
+ DoAddL
+ (
+ *item,
+ EDontRename,
+ /*aFactoryItem=*/item->IsFactoryItem(),
+ /*aReadOnly=*/item->IsReadOnly()
+ );
+ // Cursor is still on the added record. Set modtime.
+ // Not using CFavouritesSrvDb::SetModifiedL() - that would mess up
+ // the filters.
+ iTable.UpdateLC();
+ iTable.SetModifiedL( modTime );
+ iTable.PutL( /*aTouch=*/ EFalse );
+ }
+ // In both cases (existing folder updated, or new added), the cursor
+ // is now on the target folder. Add a new mapping entry.
+ mapping.iUid1 = aReferenceTable.Uid();
+ mapping.iUid2 = iTable.Uid();
+ parentMap->AppendL( mapping );
+ iTable.ClearFilters();
+ }
+ aReferenceTable.ClearFilters();
+
+ // 4. Replace the unmodified factory items of our table with corresponding items from reference table and
+ // add remaining items in the reference table to our table,
+ // with AP mapping and parent folder mapping applied.
+
+ TInt i;
+ TFavouritesWapAp ap;
+ TInt origId;
+ TInt newId;
+
+ // Get all items.
+ aReferenceTable.SetFiltersL( TFavouritesFilter ( KFavouritesNullUid,
+ CFavouritesItem::EItem, NULL, KFavouritesNullContextId ) );
+ aReferenceTable.BeginningL();
+
+ while ( aReferenceTable.NextL() )
+ {
+ aReferenceTable.GetL();
+ aReferenceTable.ReadItemDataL( *item );
+ modTime = item->Modified();
+ origId = item->Uid();
+
+ // Remap parent folder.
+ for( i = 0; i < parentMap->Count(); i++ )
+ {
+ if( item->ParentFolder() == parentMap->At( i ).iUid1 )
+ {
+ item->SetParentFolder( parentMap->At( i ).iUid2 );
+ break;
+ }
+ // Parent folder mapping should always be successful.
+ __ASSERT_DEBUG( i < parentMap->Count(), \
+ FavouritesPanic( EFavouritesInternal ) );
+ }
+
+ // Add the item.
+ DoAddL
+ (
+ *item,
+ EAutoRename,
+ /*aFactoryItem=*/ETrue,
+ /*aReadOnly=*/item->IsReadOnly()
+ );
+
+ // Cursor is still on the added record. Set modtime.
+ // Not using CFavouritesSrvDb::SetModifiedL() - that would mess up
+ // the filters.
+ iTable.UpdateLC();
+ iTable.SetModifiedL( modTime );
+ iTable.PutL( /*aTouch=*/ EFalse );
+
+ // Get the new item UID
+ newId = item->Uid();
+
+ if( !iTable.SeekToUidL( origId ) )
+ {
+ iTable.GotoToUidL(newId);
+ iTable.UpdateLC();
+ iTable.SetUidL( origId );
+ iTable.PutL( /*aTouch=*/ EFalse );
+ item->SetUid( origId );
+ }
+
+ // Check AP, enrol for mapping if needed.
+ ap = item->WapAp();
+ if ( !ap.IsDefault() && !ap.IsNull() )
+ {
+ mapping.iUid1 = item->Uid();
+ mapping.iUid2 = STATIC_CAST( TInt, ap.ApId() );
+ aApMap.AppendL( mapping );
+ }
+ }
+ aReferenceTable.ClearFilters();
+
+ CleanupStack::PopAndDestroy( 2 ); // parentMap, item
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SetAccessPointsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SetAccessPointsL( const CUidMap& aApMap )
+ {
+ __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
+ TInt i;
+ TFavouritesWapAp ap;
+ for ( i = 0; i < aApMap.Count(); i++ )
+ {
+ ap.SetApId( STATIC_CAST( TUint32, aApMap[i].iUid2 ) );
+ iTable.GotoToUidL( aApMap[i].iUid1 );
+ iTable.GetL();
+ iTable.UpdateLC();
+ iTable.SetWapApL( ap );
+ iTable.PutL( /*aTouch=*/ EFalse );
+ }
+ }
+
+
+// ---------------------------------------------------------
+// IMPORT BOOKMARKS CODE INTEGRATED FROM BOOKMARKS UTILITY
+// ---------------------------------------------------------
+
+// CONSTANTS
+
+/// ',' character.
+LOCAL_C const TUint KComma = ',';
+/// '#' character.
+LOCAL_C const TUint KHash = '#';
+/// EOF (0) character.
+LOCAL_C const TUint KEof = 0;
+/// '\r' character.
+LOCAL_C const TUint KCr = '\r';
+/// '\n' character.
+LOCAL_C const TUint KLf = '\n';
+
+/// LF-EOF stop token set.
+_LIT( KStopLfEof, "\n\0" );
+/// Comma stop token set.
+_LIT( KStopComma, "," );
+/// Comma-LF-EOF stop token set.
+_LIT( KStopCommaLfEof, ",\n\0" );
+
+/// "Folder" kewyword.
+_LIT( KFolder, "Folder" );
+/// "Item" kewyword.
+_LIT( KItem, "Item" );
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::ImportL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::ImportL( const TDesC& aFileName )
+ {
+ User::LeaveIfError( iFile.Open( iFs, aFileName,
+ EFileRead | EFileShareReadersOnly ) );
+ CleanupClosePushL<RUnicodeFile>( iFile );
+
+ iFolderNames = new (ELeave) CArrayFixFlat<CFavouritesFolder>( 1 );
+ User::LeaveIfNull( iFolderNames );
+ CleanupStack::PushL( iFolderNames );
+
+ iBuf = new (ELeave) TText16[KFavouritesMaxUrl];
+ User::LeaveIfNull( iBuf );
+ CleanupStack::PushL( iBuf );
+
+ iMaxCh = iBuf + KFavouritesMaxUrl;
+
+ GetCharL();
+
+ while( NextLineL() )
+ {;}
+
+ TUint count = iFolderNames->Count();
+ for (TUint i = 0; i < count; i++)
+ {
+ CFavouritesFolder folder = iFolderNames->At(i);
+ delete folder.Name();
+ }
+
+ CleanupStack::Pop(iBuf); //iBuf
+ delete iBuf;
+ CleanupStack::Pop(iFolderNames); //iFolderNames
+ delete iFolderNames;
+ CleanupStack::PopAndDestroy(); // close iFile
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::GetCharL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::GetCharL()
+ {
+ iCurCh = iFile.GetCharL();
+ if ( iCurCh == KCr )
+ {
+ // CR character found - ignore it. Not expecting CR to appear anywhere
+ // else than before an LF.
+ iCurCh = iFile.GetCharL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::NextLineL
+// ---------------------------------------------------------
+//
+TBool CFavouritesSrvDb::NextLineL()
+ {
+ switch( iCurCh )
+ {
+ case KEof:
+ // EOF
+ return EFalse;
+
+ case KHash:
+ // Comment line; skip over.
+ SkipL( KStopLfEof );
+ GetCharL();
+ break;
+
+ case KCr:
+ case KLf:
+ // Empty line; skip over.
+ GetCharL();
+ break;
+
+ default:
+ // Parse bookmark attributes.
+ AttrsL();
+ break;
+ }
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::NextTokenL
+// ---------------------------------------------------------
+//
+TPtrC CFavouritesSrvDb::NextTokenL( const TDesC& aStopCharSet )
+ {
+ iNextCh = iBuf; // Start storing token at start of buffer.
+ while ( iNextCh < iMaxCh )
+ {
+ if ( aStopCharSet.Locate( iCurCh ) != KErrNotFound )
+ {
+ // Stop character found - return what we have stored so far. This
+ // may be an empty string as well.
+ return TPtrC( iBuf, iNextCh - iBuf );
+ }
+ *iNextCh = STATIC_CAST( TText16, iCurCh );
+ iNextCh++;
+ GetCharL();
+ }
+ // No more space in buffer to store token.
+ User::Leave( KErrOverflow );
+ /*NOTREACHED*/
+ return TPtrC();
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::NextIntTokenL
+// ---------------------------------------------------------
+//
+TInt CFavouritesSrvDb::NextIntTokenL( const TDesC& aStopCharSet )
+ {
+ TInt ret = 0;
+ TPtrC token( NextTokenL( aStopCharSet ) );
+ if ( token.Length() )
+ {
+ TLex lex( token );
+ User::LeaveIfError( lex.Val( ret ) );
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::NextHexTokenL
+// ---------------------------------------------------------
+//
+TInt32 CFavouritesSrvDb::NextHexTokenL( const TDesC& aStopCharSet )
+ {
+ TUint32 ret = 0;
+ TPtrC token( NextTokenL( aStopCharSet ) );
+ if ( token.Length() )
+ {
+ TLex lex( token );
+ User::LeaveIfError( lex.Val( ret, EHex ) );
+ }
+ return STATIC_CAST( TInt32, ret );
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::SkipL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::SkipL( const TDesC& aStopCharSet )
+ {
+ // Note that EOF also can be a stop character; aStopChar check has
+ // precendence over EOF check. That is the 'expected EOF' case.
+ while( aStopCharSet.Locate( iCurCh ) == KErrNotFound )
+ {
+ if ( iCurCh == KEof )
+ {
+ // Unexpected EOF.
+ User::Leave( KErrEof );
+ }
+ GetCharL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::AttrsL
+// ---------------------------------------------------------
+//
+void CFavouritesSrvDb::AttrsL()
+ {
+ TPtrC token;
+ TInt num = 0;
+ TBool readOnly( EFalse );
+ // TBool factoryItem;
+ TBool preferred( EFalse );
+ TBool hidden( EFalse );
+ TFavouritesWapAp ap;
+
+ iTable.OpenL( iDatabase );
+ CleanupClosePushL<RFavouritesSrvTable>( iTable );
+ iTable.BeginningL();
+ iTable.InsertLC();
+
+ // Parse the line and fill item.
+
+ // Type (including special items).
+ token.Set( NextTokenL( KStopComma ) );
+ if ( !token.Compare( KFolder ) )
+ {
+ iTable.SetTypeL( CFavouritesItem::EFolder );
+ }
+ else if ( !token.Compare( KItem ) )
+ {
+ iTable.SetTypeL( CFavouritesItem::EItem );
+ }
+ else
+ {
+ // Expected "Folder", "Item"
+ User::Leave( KErrCorrupt );
+ }
+ GetCharL();
+ // Name.
+ iTable.SetNameL( NextTokenL( KStopComma ) );
+ if (iTable.Type() == CFavouritesItem::EFolder) // Remember the folder name for UID lookup.
+ {
+ HBufC* buf = HBufC::NewLC( iTable.Name().Length() );
+ TPtr ptr( buf->Des() );
+ ptr.Copy( iTable.Name() );
+ CFavouritesFolder folder( buf, iTable.Uid() );
+ iFolderNames->AppendL( folder );
+ CleanupStack::Pop(); // for newlc of buf
+ }
+ GetCharL();
+
+ // Parent folder.
+ iTable.SetParentFolderL( FolderByNameL( NextTokenL( KStopComma ) ) );
+
+ GetCharL();
+
+ // URL.
+ iTable.SetUrlL( NextTokenL( KStopComma ) );
+ GetCharL();
+
+ // WAP AP.
+ token.Set( NextTokenL( KStopComma ) );
+ if ( token.Length() )
+ {
+ TLex lex( token );
+ if ( lex.Val( num ) != KErrNone )
+ {
+ IAPIdByNameL( token, num );
+ }
+ ap = num;
+ }
+ else
+ {
+ ap.SetDefault();
+ }
+
+ iTable.SetWapApL( ap );
+
+ GetCharL();
+
+ // User name.
+ iTable.SetUsernameL( NextTokenL( KStopComma ) );
+ GetCharL();
+
+ // Password.
+ iTable.SetPasswordL( NextTokenL( KStopComma ) );
+ GetCharL();
+
+ // Read-only flag.
+ num = NextIntTokenL( KStopComma );
+ if ( num == 0 )
+ {
+ readOnly = EFalse;
+ }
+ else if ( num == 1 )
+ {
+ readOnly = ETrue;
+ }
+ else
+ {
+ // Expected "0" or "1".
+ User::Leave( KErrCorrupt );
+ }
+ GetCharL();
+
+ // Factory item flag.
+ num = NextIntTokenL( KStopComma );
+ if ( num == 0 )
+ {
+ // factoryItem = EFalse;
+ }
+ else if ( num == 1 )
+ {
+ // factoryItem = ETrue;
+ }
+ else
+ {
+ // Expected "0" or "1".
+ User::Leave( KErrCorrupt );
+ }
+ GetCharL();
+
+ // Context id.
+ iTable.SetContextIdL( NextHexTokenL( KStopCommaLfEof ) );
+
+ GetCharL();
+ num = NextIntTokenL( KStopCommaLfEof );
+ if ( num == 0 )
+ {
+ hidden = EFalse;
+ }
+ else if ( num == 1 )
+ {
+ hidden = ETrue;
+ }
+ else
+ {
+ // Expected "0" or "1".
+ User::Leave( KErrCorrupt );
+ }
+
+ iTable.SetHiddenL(hidden);
+
+ // No GetCharL yet - PreferredUid is optional, so we need to investigate
+ // lookeahed character first.
+
+ // Preferred flag (optional).
+ if ( iCurCh == KComma )
+ {
+ GetCharL();
+ num = NextIntTokenL( KStopLfEof );
+ if ( num == 0 )
+ {
+ preferred = EFalse;
+ }
+ else if ( num == 1 )
+ {
+ preferred = ETrue;
+ }
+ else
+ {
+ // Expected "0" or "1".
+ User::Leave( KErrCorrupt );
+ }
+ }
+ GetCharL();
+
+ if ( preferred )
+ {
+ iTable.SetPreferredUidL( iTable.Uid() );
+ }
+ iTable.SetReadOnlyL( readOnly );
+ iTable.PutL();
+ // Now we have the root. The first entry added came with 0 Uid, so this
+ // value will never be used again.
+ iTable.Close();
+ CleanupStack::Pop( ); // close iTable
+ }
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::FolderByNameL
+// ---------------------------------------------------------
+//
+TInt CFavouritesSrvDb::FolderByNameL( const TDesC& aName )
+ {
+ TInt folderUid = KFavouritesRootUid;
+
+ if ( aName.Length() )
+ {
+ // loop through iFolderNames and if bookmark name is found, return the index/UID where found
+ // else return root UID.
+ for (TUint x = 0; x < iFolderNames->Count(); ++x)
+ {
+ CFavouritesFolder folder = iFolderNames->At(x);
+ HBufC* fn = folder.Name();
+ TPtr ptr( fn->Des());
+ if (aName.Compare(ptr) == 0)
+ {
+ folderUid = folder.Uid();
+ return folderUid;
+ }
+ }
+ }
+
+ return folderUid;
+ }
+
+
+// ---------------------------------------------------------
+// CFavouritesSrvDb::IAPIdByNameL
+// ---------------------------------------------------------
+//
+TInt CFavouritesSrvDb::IAPIdByNameL( TDesC& aName, TInt& aIapId )
+ {
+ TUint pushCount = 0;
+ TInt retVal = KErrNone;
+ TBool found = EFalse;
+ TUint32 iapId = 0;
+ TInt err = KErrNone;
+
+ CCommsDatabase* db = CCommsDatabase::NewL();
+ CleanupStack::PushL(db);
+ pushCount++;
+ CCommsDbTableView* tableView = db->OpenTableLC( TPtrC(WAP_ACCESS_POINT) );
+
+ pushCount++;
+ retVal = tableView->GotoFirstRecord();
+
+ while( retVal == KErrNone && !found )
+ {
+ TBuf< KCommsDbSvrMaxFieldLength > iapName;
+ tableView->ReadTextL( TPtrC( COMMDB_NAME ), iapName );
+ if (iapName.CompareF( aName ) == 0 )
+ {
+ TRAP( err, tableView->ReadUintL( TPtrC(COMMDB_ID), iapId ) );
+ found = ETrue;
+ }
+ retVal = tableView->GotoNextRecord();
+ }
+ aIapId = iapId;
+
+ CleanupStack::PopAndDestroy( pushCount );
+ return retVal;
+ }
+// End of File