browserutilities/favouritesengine/ClientServer/srvsrc/FavouritesSrvDb.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *      Implementation of class CFavouritesSrvDb
       
    16 *      
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #include <s32std.h>
       
    24 #include <eikenv.h>
       
    25 #include <rfsApMapper.h>
       
    26 #include <commdb.h>
       
    27 #include "FavouritesSrvDb.h"
       
    28 #include "FavouritesSrvTable.h"
       
    29 #include "FavouritesItemImpl.h"
       
    30 #include "FavouritesItemImplList.h"
       
    31 #include "FavouritesPanic.h"
       
    32 #include "FavouritesLimits.h"
       
    33 #include "FavouritesItemData.h"
       
    34 #include "FavouritesFilter.h"
       
    35 #include "UidMap.h"
       
    36 #include "FavouritesLogger.h" 
       
    37 #include "FavouritesFolder.h"
       
    38 
       
    39 
       
    40 
       
    41 // CONSTANTS
       
    42 
       
    43 /// Uid list granularity.
       
    44 LOCAL_D const TInt KUidListGranularity = 4;
       
    45 /// Postfix list granularity.
       
    46 LOCAL_D const TInt KPostfixListGranularity = 4;
       
    47 /// Number of updates needed to trigger automatic compaction.
       
    48 LOCAL_D const TInt KUpdatesNeededForAutoCompact = 32;
       
    49 /// Length of filename: 8 char.
       
    50 LOCAL_D const TInt KFnameLength = 8;
       
    51 
       
    52 // Secure policy ID of the Faveng database files.
       
    53 LOCAL_D const TUint KUidFavengDbPolicy = 0x101FD685;
       
    54 
       
    55 
       
    56 // ==================== LOCAL FUNCTIONS ====================
       
    57 
       
    58 /**
       
    59 * Given aName in the format <prefix> or <prefix><integer in parenthesis>,
       
    60 * return a pointer to the leading part. That is, if there is trailing
       
    61 * <integer in  parenthesis>, then that is excluded; if there is no trailing
       
    62 * part, then the original decriptor is returned.
       
    63 * Examples:
       
    64 *   - "Foo" returns "Foo";
       
    65 *   - "Foo(12)" returns "Foo";
       
    66 *   - "Foo(12 34)" returns "Foo(12 34)";
       
    67 *
       
    68 * @param aName Name to get prefix from.
       
    69 * @return Pointer to prefix part.
       
    70 */
       
    71 LOCAL_C TPtrC GetPrefix( const TDesC& aName )
       
    72     {
       
    73     TPtrC prefix = aName;
       
    74     TInt length = aName.Length();
       
    75     if ( length >= 3 && aName[length - 1] == ')' )
       
    76         {
       
    77         // Any name shorter than 3 chars cannot have a postfix.
       
    78         TInt openPar = aName.LocateReverse('(');
       
    79         if ( openPar != KErrNotFound )
       
    80             {
       
    81             // aName looks like "<prefix>(<something>)".
       
    82             // See if <something> is an integer number.
       
    83             TPtrC num = aName.Mid( openPar + 1, length - openPar - 2);
       
    84             TInt val;
       
    85             TLex lex( num );
       
    86             if ( lex.Val( val ) == KErrNone )
       
    87                 {
       
    88                 // Yes, the trailer is a parenthesized integer.
       
    89                 prefix.Set( aName.Left( openPar ) );
       
    90                 }
       
    91             }
       
    92         }
       
    93     return prefix;
       
    94     }
       
    95 
       
    96 /**
       
    97 * If aName is constructed from aPrefix with a positive integer postfix,
       
    98 * get the numeric value of the postfix, e.g:
       
    99 *   - GetPostfix( "Foo(3)", "Foo" ) == 3
       
   100 * If aName is the same as aPrefix, return 0, e.g.:
       
   101 *   - GetPostfix( "Foo", "Foo" ) == 0
       
   102 * If aName is not constructed from aPrefix, return -1, e.g.:
       
   103 *   - GetPostfix( "Foobar", "Foo" ) == -1
       
   104 *   - GetPostfix( "Foo(23 45)", "Foo" ) == -1
       
   105 * If postfix is 0 or negative, return -1, e.g.:
       
   106 *   - GetPostfix( "Foo(00)", "Foo" ) == -1
       
   107 *   - GetPostfix( "Foo(-8)", "Foo" ) == -1
       
   108 *
       
   109 * Return values for the following cases cannot be differentiated (-1 for all):
       
   110 * - postfix is 0;
       
   111 * - postfix is negative;
       
   112 * - aName not constructed from aPrefix.
       
   113 *
       
   114 * @param aName Name to get postfix from.
       
   115 * @param aPrefix Prefix to be searched.
       
   116 * @return Postfix value.
       
   117 */
       
   118 LOCAL_C TInt GetPostfix( const TDesC& aName, const TDesC& aPrefix )
       
   119     {
       
   120     TInt postfix = -1;
       
   121     TInt nameLength = aName.Length();
       
   122     TInt prefixLength = aPrefix.Length();
       
   123     if ( nameLength >= prefixLength && aName.FindF( aPrefix ) == 0 )
       
   124         {
       
   125         // aName is longer or equal length, and
       
   126         // aPrefix can be found in the beginning of aName.
       
   127         if ( nameLength == prefixLength )
       
   128             {
       
   129             // They have the same length; they equal.
       
   130             postfix = 0;
       
   131             }
       
   132         else if (
       
   133                 nameLength - prefixLength >= 3 &&   // Because of this...
       
   134                 aName[prefixLength] == '(' &&
       
   135                 aName[nameLength - 1] == ')'        // ... this is safe (*)
       
   136                 )
       
   137             {
       
   138             // (*) "aName[nameLength - 1]" no need to check whether this
       
   139             // index is valid. nameLength is at least 3 characters longer
       
   140             // than prefixLength (a positive integer) -> nameLength >= 3.
       
   141 
       
   142             // aName looks like "aPrefix(<something>)".
       
   143             // See if <something> is an integer number.
       
   144             TPtrC num = aName.Mid
       
   145                 ( prefixLength + 1, nameLength - prefixLength - 2 );    // (**)
       
   146             // (**) These are also safe because nameLength - prefixLength >= 3.
       
   147             TInt val;
       
   148             TLex lex( num );
       
   149             if ( lex.Val( val ) == KErrNone && val > 0)
       
   150                 {
       
   151                 // Yes, the trailer is a positive integer.
       
   152                 postfix = val;
       
   153                 }
       
   154             }
       
   155         }
       
   156     return postfix;
       
   157     }
       
   158 
       
   159 /**
       
   160 * Generate filename for uid: return number as 8 character hex string.
       
   161 * @param aUid Uid.
       
   162 * @param aName Filename returned here. Minimum length KFnameLength.
       
   163 */
       
   164 LOCAL_C void FilenameForUid( TInt aUid, TDes& aName )
       
   165     {
       
   166     __ASSERT_DEBUG( aName.MaxLength() >= KFnameLength, \
       
   167         FavouritesPanic( EFavouritesInternal ) );
       
   168     aName.NumFixedWidth( STATIC_CAST( TUint, aUid ), EHex, KFnameLength );
       
   169     }
       
   170 
       
   171 /**
       
   172 * Get uid for filename; reverse of FilenameForUid.
       
   173 * @param aName Filename.
       
   174 * @return Uid or KFavouritesNullUid.
       
   175 */
       
   176 LOCAL_C TInt UidForFilename( const TDesC& aName )
       
   177     {
       
   178     // Parse the supplied text as hex number.
       
   179     TInt uid = KFavouritesNullUid;
       
   180     if ( aName.Length() == KFnameLength )
       
   181         {
       
   182         // Length is OK, check contents.
       
   183         TUint val;
       
   184         TLex lex( aName );
       
   185         if ( !lex.Val( val, EHex ) && lex.Eos() )
       
   186             {
       
   187             // OK, this filename can be parsed as hex TUint.
       
   188             uid = STATIC_CAST( TInt, val );
       
   189             }
       
   190         }
       
   191     return uid;
       
   192     }
       
   193 
       
   194 // ================= MEMBER FUNCTIONS =======================
       
   195 
       
   196 
       
   197 // ---------------------------------------------------------
       
   198 // CBookmarkSrvDb::NewL
       
   199 // ---------------------------------------------------------
       
   200 //
       
   201 CFavouritesSrvDb* CFavouritesSrvDb::NewL
       
   202 ( RFs& aFs, RDbs& aDbs, const TDesC& aPath, const TDesC& aDBName )
       
   203     {
       
   204     CFavouritesSrvDb* db = new (ELeave) CFavouritesSrvDb( aFs, aDbs );
       
   205     CleanupStack::PushL( db );
       
   206     db->ConstructL( aPath , aDBName );
       
   207     CleanupStack::Pop();    // db
       
   208     return db;
       
   209     }
       
   210 
       
   211 
       
   212 // ---------------------------------------------------------
       
   213 // CFavouritesSrvDb::~CFavouritesSrvDb
       
   214 // ---------------------------------------------------------
       
   215 //
       
   216 CFavouritesSrvDb::~CFavouritesSrvDb()
       
   217     {
       
   218     if ( iOpen )
       
   219         {
       
   220         if ( iInTransaction )
       
   221             {
       
   222             Rollback();
       
   223             }
       
   224         TRAP_IGNORE( DeleteOrphanedFilesL() );
       
   225         // TODO move compacting to server side, when last client exits.
       
   226         (void)iDatabase.Compact();  // Any error is silently ignored.
       
   227         iDatabase.Close();
       
   228         iOpen = EFalse;
       
   229         }
       
   230     delete iPath;   
       
   231     delete iSavedFilePath;    
       
   232     iSecureDbFormat.Close();
       
   233     }
       
   234 
       
   235 // ---------------------------------------------------------
       
   236 // CFavouritesSrvDb::IsDamagedL
       
   237 // ---------------------------------------------------------
       
   238 //
       
   239 TBool CFavouritesSrvDb::IsDamagedL()
       
   240     {
       
   241     TBool damaged = EFalse;
       
   242     // We must open a table to make RDbNameDatabase::IsDamaged() work!.
       
   243     RFavouritesSrvTable table;
       
   244     table.OpenL( iDatabase );
       
   245     damaged = iDatabase.IsDamaged();
       
   246     table.Close();
       
   247     return damaged;
       
   248     }
       
   249 
       
   250 // ---------------------------------------------------------
       
   251 // CFavouritesSrvDb::RecoverL
       
   252 // ---------------------------------------------------------
       
   253 //
       
   254 void CFavouritesSrvDb::RecoverL()
       
   255     {
       
   256     User::LeaveIfError( iDatabase.Recover() );
       
   257     }
       
   258 
       
   259 // ---------------------------------------------------------
       
   260 // CFavouritesSrvDb::CompactL
       
   261 // ---------------------------------------------------------
       
   262 //
       
   263 void CFavouritesSrvDb::CompactL()
       
   264     {
       
   265     User::LeaveIfError( iDatabase.Compact() );
       
   266     iUpdatesSinceLastCompact = 0;
       
   267     }
       
   268 
       
   269 // ---------------------------------------------------------
       
   270 // CFavouritesSrvDb::Size
       
   271 // ---------------------------------------------------------
       
   272 //
       
   273 RDbDatabase::TSize CFavouritesSrvDb::Size() const
       
   274     {
       
   275     return iDatabase.Size();
       
   276     }
       
   277 
       
   278 // ---------------------------------------------------------
       
   279 // CFavouritesSrvDb::UpdateStatsL
       
   280 // ---------------------------------------------------------
       
   281 //
       
   282 void CFavouritesSrvDb::UpdateStatsL()
       
   283     {
       
   284     User::LeaveIfError( iDatabase.UpdateStats() );
       
   285     }
       
   286 
       
   287 // ---------------------------------------------------------
       
   288 // CFavouritesSrvDb::BeginL
       
   289 // ---------------------------------------------------------
       
   290 //
       
   291 void CFavouritesSrvDb::BeginL( TBool aWrite /*=EFalse*/ )
       
   292     {
       
   293     __ASSERT_DEBUG( !iInTransaction, \
       
   294         FavouritesPanic( EFavouritesNestedTransaction ) );
       
   295 
       
   296     // Three parts: table open + transacion + (optional) write lock.
       
   297     // Temp use of cleanup items make the three atomic.
       
   298     iTable.OpenL( iDatabase );
       
   299     CleanupClosePushL<RFavouritesSrvTable>( iTable );
       
   300     User::LeaveIfError( iDatabase.Begin() );
       
   301     iInTransaction = ETrue;
       
   302     CleanupStack::PushL( TCleanupItem( StaticRollback, this ) );
       
   303     if ( aWrite )
       
   304         {
       
   305         iTable.PutWriteLockL();
       
   306         }
       
   307     CleanupStack::Pop( 2 ); // Rollback, Closing iTable
       
   308     }
       
   309 
       
   310 // ---------------------------------------------------------
       
   311 // CFavouritesSrvDb::CommitL
       
   312 // ---------------------------------------------------------
       
   313 //
       
   314 void CFavouritesSrvDb::CommitL()
       
   315     {
       
   316     __ASSERT_DEBUG( iInTransaction, \
       
   317         FavouritesPanic( EFavouritesNoTransaction ) );
       
   318 
       
   319     User::LeaveIfError( iDatabase.Commit() );
       
   320     iInTransaction = EFalse;
       
   321     iTable.Close();
       
   322     if ( iUpdatesSinceLastCompact > KUpdatesNeededForAutoCompact )
       
   323         {
       
   324         // Auto-compact, to avoid overgrowth.
       
   325         TRAP_IGNORE( CompactL() );
       
   326         }
       
   327     }
       
   328 
       
   329 // ---------------------------------------------------------
       
   330 // CFavouritesSrvDb::Rollback
       
   331 // ---------------------------------------------------------
       
   332 //
       
   333 void CFavouritesSrvDb::Rollback()
       
   334     {
       
   335     __ASSERT_DEBUG( iInTransaction, \
       
   336         FavouritesPanic( EFavouritesNoTransaction ) );
       
   337 
       
   338     iDatabase.Rollback();
       
   339     iInTransaction = EFalse;
       
   340     iTable.Close();
       
   341     }
       
   342 
       
   343 // ---------------------------------------------------------
       
   344 // CFavouritesSrvDb::GetL
       
   345 // ---------------------------------------------------------
       
   346 //
       
   347 void CFavouritesSrvDb::GetL( TInt aUid, CFavouritesItemImpl& aItem )
       
   348     {
       
   349     TBool ownTransaction;
       
   350     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   351     iTable.GotoToUidL( aUid );
       
   352     iTable.GetL();
       
   353     iTable.ReadItemDataL( aItem );
       
   354     CommitIfNeededL( ownTransaction );
       
   355     }
       
   356 
       
   357 // ---------------------------------------------------------
       
   358 // CFavouritesSrvDb::GetAllL
       
   359 // ---------------------------------------------------------
       
   360 //
       
   361 void CFavouritesSrvDb::GetAllL
       
   362 ( CFavouritesItemImplList& aItemList, const TFavouritesFilter& aFilter )
       
   363     {
       
   364     TBool ownTransaction;
       
   365 
       
   366     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   367     iTable.SetFiltersL( aFilter );
       
   368     CFavouritesItemImpl* item;
       
   369     iTable.BeginningL();
       
   370     while( iTable.NextL() )
       
   371         {
       
   372         item = CFavouritesItemImpl::NewLC();
       
   373         iTable.GetL();
       
   374         iTable.ReadItemDataL( *item );
       
   375         aItemList.AppendL( item );
       
   376         CleanupStack::Pop();    // item; owner is the list now.
       
   377         }
       
   378     iTable.ClearFilters();
       
   379     CommitIfNeededL( ownTransaction );
       
   380     }
       
   381 
       
   382 // ---------------------------------------------------------
       
   383 // CFavouritesSrvDb::PreferredUidL
       
   384 // ---------------------------------------------------------
       
   385 //
       
   386 TInt CFavouritesSrvDb::PreferredUidL( TInt aFolder )
       
   387 {
       
   388     TInt uid( KFavouritesNullUid );
       
   389     TBool ownTransaction;
       
   390     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   391     if ( iTable.SeekToUidL( aFolder ) )
       
   392         {
       
   393         iTable.GetL();
       
   394         if ( iTable.Type() == CFavouritesItem::EFolder )
       
   395             {
       
   396             uid = iTable.PreferredUid();
       
   397             }
       
   398         }
       
   399     CommitIfNeededL( ownTransaction );
       
   400     return uid;
       
   401 }
       
   402 
       
   403 // ---------------------------------------------------------
       
   404 // CFavouritesSrvDb::GetUidsL
       
   405 // ---------------------------------------------------------
       
   406 //
       
   407 void CFavouritesSrvDb::GetUidsL
       
   408 ( CArrayFix<TInt>& aUids, const TFavouritesFilter& aFilter )
       
   409     {
       
   410     TBool ownTransaction;
       
   411     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   412     iTable.SetFiltersL( aFilter );
       
   413     iTable.BeginningL();
       
   414     while( iTable.NextL() )
       
   415         {
       
   416         iTable.GetL();
       
   417         aUids.AppendL( iTable.Uid() );
       
   418         }
       
   419     iTable.ClearFilters();
       
   420     CommitIfNeededL( ownTransaction );
       
   421     }
       
   422 
       
   423 // ---------------------------------------------------------
       
   424 // CFavouritesSrvDb::DeleteL
       
   425 // ---------------------------------------------------------
       
   426 //
       
   427 void CFavouritesSrvDb::DeleteL( TInt aUid )
       
   428     {
       
   429     if ( aUid == KFavouritesRootUid || aUid == KFavouritesHomepageUid )
       
   430         {
       
   431         // Cannot delete these.
       
   432         User::Leave( KErrAccessDenied );
       
   433         }
       
   434     // Make a list, to remember which items were deleted.
       
   435     CArrayFix<TInt>* deletedUids =
       
   436         new (ELeave) CArrayFixFlat<TInt>( KUidListGranularity );
       
   437     CleanupStack::PushL( deletedUids );
       
   438 
       
   439     TBool ownTransaction;
       
   440     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   441     iTable.GotoToUidL( aUid );
       
   442     DeleteCurrentL( *deletedUids );
       
   443     CommitIfNeededL( ownTransaction );
       
   444 
       
   445     // Delete associated files.
       
   446     TInt i;
       
   447     TBuf<KFnameLength> name;
       
   448     TParse parse;
       
   449     for ( i = 0; i < deletedUids->Count(); i++ )
       
   450         {
       
   451         FilenameForUid( deletedUids->At( i ), name );
       
   452         User::LeaveIfError( parse.SetNoWild( name, iPath, NULL ) );
       
   453         (void)iFs.Delete( parse.FullName() );
       
   454         // Errors ignored; the file may be locked etc. etc.
       
   455         // Orphaned file cleanup will remove them eventually.
       
   456         }
       
   457 
       
   458     CleanupStack::PopAndDestroy();  // deletedUids
       
   459     }
       
   460 
       
   461 // ---------------------------------------------------------
       
   462 // CFavouritesSrvDb::UpdateL
       
   463 // ---------------------------------------------------------
       
   464 //
       
   465 void CFavouritesSrvDb::UpdateL
       
   466 ( CFavouritesItemImpl& aItem, TInt aUid, TBool aAutoRename )
       
   467     {
       
   468     if ( aUid == KFavouritesRootUid ||
       
   469          aUid == KFavouritesHomepageUid ||
       
   470          aUid == KFavouritesLastVisitedUid )
       
   471         {
       
   472         // Cannot modify these.
       
   473         // (Root cannot be modified at all; the others can be modified but
       
   474         // not through this method.)
       
   475         User::Leave( KErrAccessDenied );
       
   476         }
       
   477     TBool ownTransaction;
       
   478     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   479     iTable.GotoToUidL( aUid );
       
   480     UpdateCurrentL( aItem, aAutoRename ? EAutoRename : EDontRename );
       
   481     CommitIfNeededL( ownTransaction );
       
   482     }
       
   483 
       
   484 // ---------------------------------------------------------
       
   485 // CFavouritesSrvDb::AddL
       
   486 // ---------------------------------------------------------
       
   487 //
       
   488 void CFavouritesSrvDb::AddL( CFavouritesItemImpl& aItem, TBool aAutoRename )
       
   489     {
       
   490     TBool ownTransaction;
       
   491     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   492     DoAddL( aItem, aAutoRename ? EAutoRename : EDontRename );
       
   493     CommitIfNeededL( ownTransaction );
       
   494     }
       
   495 
       
   496 // ---------------------------------------------------------
       
   497 // CFavouritesSrvDb::SetSpecialItemL
       
   498 // ---------------------------------------------------------
       
   499 //
       
   500 void CFavouritesSrvDb::SetSpecialItemL( CFavouritesItemImpl& aItem, TInt aUid )
       
   501     {
       
   502     __ASSERT_DEBUG( \
       
   503         aUid == KFavouritesHomepageUid || aUid == KFavouritesLastVisitedUid, \
       
   504         FavouritesPanic( EFavouritesInternal )
       
   505         );
       
   506 
       
   507     if ( aItem.ParentFolder() != KFavouritesRootUid )
       
   508         {
       
   509         // Must be in root.
       
   510         User::Leave( KErrArgument );
       
   511         }
       
   512 
       
   513     TBool ownTransaction;
       
   514     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   515     if ( iTable.SeekToUidL( aUid ) )
       
   516         {
       
   517         UpdateCurrentL( aItem, ESuppressCheck );
       
   518         }
       
   519     else
       
   520         {
       
   521         DoAddL( aItem, ESuppressCheck );
       
   522         // Cursor is still on the new record. Write uid back.
       
   523         iTable.UpdateLC();
       
   524         iTable.SetUidL( aUid );
       
   525         iTable.PutL();
       
   526         aItem.SetUid( aUid );                   // Get uid back.
       
   527         aItem.SetModified( iTable.Modified() ); // Get modtime.
       
   528         }
       
   529     CommitIfNeededL( ownTransaction );
       
   530     }
       
   531 
       
   532 // ---------------------------------------------------------
       
   533 // CFavouritesSrvDb::SetFactoryItemL
       
   534 // ---------------------------------------------------------
       
   535 //
       
   536 void CFavouritesSrvDb::SetFactoryItemL( TInt aUid, TBool aFactoryItem )
       
   537     {
       
   538     TBool ownTransaction;
       
   539     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   540     iTable.GotoToUidL( aUid );
       
   541     iTable.UpdateLC();
       
   542     iTable.SetFactoryItemL( aFactoryItem );
       
   543     iTable.PutL();
       
   544     CommitIfNeededL( ownTransaction );
       
   545     }
       
   546 
       
   547 // ---------------------------------------------------------
       
   548 // CFavouritesSrvDb::SetReadOnlyL
       
   549 // ---------------------------------------------------------
       
   550 //
       
   551 void CFavouritesSrvDb::SetReadOnlyL( TInt aUid, TBool aReadOnly )
       
   552     {
       
   553     TBool ownTransaction;
       
   554     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   555     iTable.GotoToUidL( aUid );
       
   556     iTable.UpdateLC();
       
   557     iTable.SetReadOnlyL( aReadOnly );
       
   558     iTable.PutL();
       
   559     CommitIfNeededL( ownTransaction );
       
   560     }
       
   561 
       
   562 // ---------------------------------------------------------
       
   563 // CFavouritesSrvDb::SetModifiedL
       
   564 // ---------------------------------------------------------
       
   565 //
       
   566 void CFavouritesSrvDb::SetModifiedL( TInt aUid, TTime aModified )
       
   567     {
       
   568     TBool ownTransaction;
       
   569     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   570     iTable.GotoToUidL( aUid );
       
   571     iTable.UpdateLC();
       
   572     iTable.SetModifiedL( aModified );
       
   573     iTable.PutL( /*aTouch=*/ EFalse );
       
   574     CommitIfNeededL( ownTransaction );
       
   575     }
       
   576 
       
   577 // ---------------------------------------------------------
       
   578 // CFavouritesSrvDb::SetPreferredUidL
       
   579 // ---------------------------------------------------------
       
   580 //
       
   581 void CFavouritesSrvDb::SetPreferredUidL( TInt aFolder, TInt aUid )
       
   582     {
       
   583     TBool ownTransaction;
       
   584     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   585     iTable.GotoToUidL( aFolder );
       
   586     iTable.GetL();
       
   587     if ( iTable.Type() == CFavouritesItem::EFolder )
       
   588         {
       
   589         iTable.UpdateLC();
       
   590         iTable.SetPreferredUidL( aUid );
       
   591         iTable.PutL();
       
   592         }
       
   593     else
       
   594         {
       
   595         User::Leave( KErrArgument );
       
   596         }
       
   597     CommitIfNeededL( ownTransaction );
       
   598     }
       
   599 
       
   600 // ---------------------------------------------------------
       
   601 // CFavouritesSrvDb::ItemExistsL
       
   602 // ---------------------------------------------------------
       
   603 //
       
   604 TBool CFavouritesSrvDb::ItemExistsL( TInt aUid )
       
   605     {
       
   606     TBool ownTransaction;
       
   607     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   608     TBool res = iTable.SeekToUidL( aUid );
       
   609     CommitIfNeededL( ownTransaction );
       
   610     return res;
       
   611     }
       
   612 
       
   613 // ---------------------------------------------------------
       
   614 // CFavouritesSrvDb::FolderExistsL
       
   615 // ---------------------------------------------------------
       
   616 //
       
   617 TBool CFavouritesSrvDb::FolderExistsL( TInt aFolder )
       
   618     {
       
   619     TBool res = EFalse;
       
   620     TBool ownTransaction;
       
   621     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   622     if ( iTable.SeekToUidL( aFolder ) )
       
   623         {
       
   624         iTable.GetL();
       
   625         if ( iTable.Type() == CFavouritesItem::EFolder )
       
   626             {
       
   627             res = ETrue;
       
   628             }
       
   629         }
       
   630     CommitIfNeededL( ownTransaction );
       
   631     return res;
       
   632     }
       
   633 
       
   634 // ---------------------------------------------------------
       
   635 // CFavouritesSrvDb::CountL
       
   636 // ---------------------------------------------------------
       
   637 //
       
   638 TInt CFavouritesSrvDb::CountL( const TFavouritesFilter& aFilter )
       
   639     {
       
   640     TInt count = 0;
       
   641     TBool ownTransaction;
       
   642     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   643     iTable.SetFiltersL( aFilter );
       
   644     // Get all items in the aFolder.
       
   645     iTable.BeginningL();
       
   646     while( iTable.NextL() )
       
   647         {
       
   648         count++;
       
   649         }
       
   650     iTable.ClearFilters();
       
   651     CommitIfNeededL( ownTransaction );
       
   652     return count;
       
   653     }
       
   654 
       
   655 // ---------------------------------------------------------
       
   656 // CFavouritesSrvDb::SetDataL
       
   657 // ---------------------------------------------------------
       
   658 //
       
   659 void CFavouritesSrvDb::SetDataL( TInt aUid, MStreamBuf& aSource )
       
   660     {
       
   661     TBool ownTransaction;
       
   662     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   663     iTable.GotoToUidL( aUid );
       
   664     iTable.UpdateLC();
       
   665     iTable.SetExtraDataL( aSource );
       
   666     iTable.PutL();
       
   667     CommitIfNeededL( ownTransaction );
       
   668     }
       
   669 
       
   670 // ---------------------------------------------------------
       
   671 // CFavouritesSrvDb::GetDataL
       
   672 // ---------------------------------------------------------
       
   673 //
       
   674 void CFavouritesSrvDb::GetDataL( TInt aUid, MStreamBuf& aSink )
       
   675     {
       
   676     TBool ownTransaction;
       
   677     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   678     iTable.GotoToUidL( aUid );
       
   679     iTable.GetL();
       
   680     iTable.GetExtraDataL( aSink );
       
   681     CommitIfNeededL( ownTransaction );
       
   682     }
       
   683 
       
   684 // ---------------------------------------------------------
       
   685 // CFavouritesSrvDb::SetBrowserDataL
       
   686 // ---------------------------------------------------------
       
   687 //
       
   688 void CFavouritesSrvDb::SetBrowserDataL( TInt aUid, MStreamBuf& aSource )
       
   689     {
       
   690     TBool ownTransaction;
       
   691     BeginIfNeededL( /*aWrite=*/ETrue, ownTransaction );
       
   692     iTable.GotoToUidL( aUid );
       
   693     iTable.UpdateLC();
       
   694     iTable.SetBrowserDataL( aSource );
       
   695     iTable.PutL();
       
   696     CommitIfNeededL( ownTransaction );
       
   697     }
       
   698 
       
   699 // ---------------------------------------------------------
       
   700 // CFavouritesSrvDb::GetBrowserDataL
       
   701 // ---------------------------------------------------------
       
   702 //
       
   703 void CFavouritesSrvDb::GetBrowserDataL( TInt aUid, MStreamBuf& aSink )
       
   704     {
       
   705     TBool ownTransaction;
       
   706     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   707     iTable.GotoToUidL( aUid );
       
   708     iTable.GetL();
       
   709     iTable.GetBrowserDataL( aSink );
       
   710     CommitIfNeededL( ownTransaction );
       
   711     }
       
   712 
       
   713 // ---------------------------------------------------------
       
   714 // CFavouritesSrvDb::MakeUniqueNameL
       
   715 // ---------------------------------------------------------
       
   716 //
       
   717 void CFavouritesSrvDb::MakeUniqueNameL( TDes& aName, TInt aFolder )
       
   718     {
       
   719     // Trim aName first.
       
   720     HBufC* buf = HBufC::NewLC( aName.Length() + KFavouritesMaxPostfix );
       
   721     TPtr ptr( buf->Des() );
       
   722     CFavouritesItemImpl::MakeName( aName, ptr );
       
   723 
       
   724     if ( !CFavouritesItemImpl::IsValidName( ptr ) )
       
   725         {
       
   726         User::Leave( KErrBadName ); // aName is invalid.
       
   727         }
       
   728 
       
   729     TBool ownTransaction;
       
   730     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   731     if ( !FolderExistsL( aFolder ) )
       
   732         {
       
   733         User::Leave( KErrArgument );    // No parent folder.
       
   734         }
       
   735 
       
   736     if ( !IsUniqueNameL( ptr, aFolder, KFavouritesNullUid ) )
       
   737         {
       
   738         MakeUniqueNameL( ptr, aFolder, KFavouritesNullUid );
       
   739         }
       
   740     // Always set it back, even if it was unique in the first place:
       
   741     // It may be trimmed.
       
   742     aName = ptr;
       
   743 
       
   744     CommitIfNeededL( ownTransaction );
       
   745     CleanupStack::PopAndDestroy();  // buf
       
   746     }
       
   747 
       
   748 // ---------------------------------------------------------
       
   749 // CFavouritesSrvDb::RestoreFactorySettingsL
       
   750 // ---------------------------------------------------------
       
   751 //
       
   752 void CFavouritesSrvDb::RestoreFactorySettingsL
       
   753 ( const TDesC& aReferenceDbPath, CUidMap& aApMap )
       
   754     {
       
   755     __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
       
   756     FLOG(( _L("restoer: FavoritesSvrDb.cpp CFavouritesSrvDb::RestoreFactorySettingsL") ));
       
   757         
       
   758     // Open a read-only database on the reference db (client-side access).
       
   759     RDbNamedDatabase refDb;
       
   760     
       
   761     FLOG(( _L("CFavouritesSrvDb::RestoreFactorySettingsL before Leave call") ));    
       
   762 
       
   763     RFs fsSession;
       
   764     User::LeaveIfError(fsSession.Connect());
       
   765     
       
   766     CleanupClosePushL(fsSession);
       
   767     User::LeaveIfError(refDb.Open(fsSession, aReferenceDbPath, TPtrC(), RDbNamedDatabase::EReadOnly));
       
   768 
       
   769     FLOG(( _L("CFavouritesSrvDb::RestoreFactorySettingsL after Leave call") ));
       
   770     CleanupClosePushL<RDbNamedDatabase>( refDb );
       
   771     // Open a read-only table on the database.
       
   772     RFavouritesSrvTable refTable;
       
   773     refTable.OpenL( refDb, RDbRowSet::EReadOnly );
       
   774     CleanupClosePushL<RFavouritesSrvTable>( refTable );
       
   775     // No transaction needed - the database is opened read-only
       
   776     // with exclusive access.
       
   777     RestoreFactorySettingsL( refTable, aApMap );
       
   778     CleanupStack::PopAndDestroy( 2 );   // close refTable, close refDb
       
   779 
       
   780     CleanupStack::PopAndDestroy(); // close fsSession
       
   781     }
       
   782     
       
   783 
       
   784 // ---------------------------------------------------------
       
   785 // CFavouritesSession::InitSavedFilePathL
       
   786 // ---------------------------------------------------------
       
   787 //
       
   788 void CFavouritesSrvDb::InitSavedFilePathL( const TDesC&  aDBName )
       
   789     {
       
   790     TParse parse;
       
   791     TDriveName cDrive = TDriveUnit( EDriveC ).Name();
       
   792     TFileName path;
       
   793     User::LeaveIfError( iFs.PrivatePath( path ) );
       
   794     User::LeaveIfError( parse.SetNoWild( path, &cDrive, NULL ) );
       
   795     parse.AddDir(aDBName);       
       
   796     delete iSavedFilePath;
       
   797 	iSavedFilePath = NULL;
       
   798 
       
   799     iSavedFilePath =  parse.FullName().AllocL();
       
   800     iFs.CreatePrivatePath(EDriveC);
       
   801     iFs.MkDirAll(*iSavedFilePath);    
       
   802     }
       
   803     
       
   804     
       
   805     
       
   806 // ---------------------------------------------------------
       
   807 // CFavouritesSrvDb::FilenameL
       
   808 // ---------------------------------------------------------
       
   809 //
       
   810 void CFavouritesSrvDb::FilenameL( TInt aUid, TParse& aParse )
       
   811     {
       
   812     // Check if item exists.
       
   813     TBool ownTransaction;
       
   814     BeginIfNeededL( /*aWrite=*/EFalse, ownTransaction );
       
   815     iTable.GotoToUidL( aUid );
       
   816     CommitIfNeededL( ownTransaction );
       
   817     // Generate filename.
       
   818     TBuf<KFnameLength> name;
       
   819     FilenameForUid( aUid, name );
       
   820     // Append filename to session path.
       
   821     User::LeaveIfError( aParse.SetNoWild( name, iSavedFilePath, NULL ) );
       
   822     }
       
   823 
       
   824 // ---------------------------------------------------------
       
   825 // CFavouritesSrvDb::CFavouritesSrvDb
       
   826 // ---------------------------------------------------------
       
   827 //
       
   828 CFavouritesSrvDb::CFavouritesSrvDb( RFs& aFs, RDbs& aDbs )
       
   829 : iFs( aFs ),
       
   830   iDbs( aDbs ),
       
   831   iOpen( EFalse ),
       
   832   iInTransaction( EFalse ),
       
   833   iUpdatesSinceLastCompact( 0 )
       
   834     {
       
   835     }
       
   836 
       
   837 
       
   838 // ---------------------------------------------------------
       
   839 // CFavouritesSrvDb::ConstructL
       
   840 // ---------------------------------------------------------
       
   841 //
       
   842 void CFavouritesSrvDb::ConstructL( const TDesC& aPath, const TDesC&  aDBName )
       
   843     {
       
   844     const TUid KDbPolicyUid = TUid::Uid(KUidFavengDbPolicy);
       
   845     
       
   846     iPath = aPath.AllocL();
       
   847     
       
   848     InitSavedFilePathL(aDBName );
       
   849 
       
   850 	_LIT( KSecureKeyword, "SECURE" );
       
   851     iSecureDbFormat.CreateL( KSecureKeyword(), KSecureKeyword().Length() + 
       
   852     	KDbPolicyUid.Name().Length() );
       
   853 	iSecureDbFormat += KDbPolicyUid.Name();
       
   854     
       
   855     // Check if we have the database.
       
   856     TBool isDbExists = EFalse;
       
   857     
       
   858     CDbDatabaseNames *dbNames = iDbs.DatabaseNamesL(EDriveC, KDbPolicyUid);
       
   859     
       
   860     CleanupStack::PushL(dbNames);
       
   861     
       
   862     TParse dbFile;
       
   863     User::LeaveIfError( dbFile.SetNoWild( aPath, NULL, NULL ) );
       
   864     
       
   865     for(int i = 0; i < dbNames->Count(); i++)
       
   866     	{
       
   867     	if( (*dbNames)[i] == dbFile.NameAndExt() )
       
   868     		{
       
   869     		isDbExists = ETrue;
       
   870     		break;
       
   871     		}
       
   872     	}
       
   873     
       
   874     CleanupStack::PopAndDestroy(dbNames);
       
   875     
       
   876     if ( !isDbExists )
       
   877         {
       
   878         // No such database. Make it now.
       
   879         TInt err = KErrNone;
       
   880         TBool doImport = ( aDBName.Compare( KBrowserBookmarks ) == 0 );
       
   881         TRAP( err, CreateDatabaseL( dbFile, doImport ) );
       
   882 
       
   883         // Bookmark import failed. Create an empty DB
       
   884         if ( err && doImport )
       
   885         	{
       
   886         	iDbs.DeleteDatabase( aPath, KDbPolicyUid );
       
   887         	TRAP( err, CreateDatabaseL( dbFile, EFalse ) );
       
   888         	}
       
   889         if ( err )
       
   890             {
       
   891             // Should anything go wrong during the database creation,
       
   892             // delete the database. This ensures that we never have
       
   893             // half-constructed database (e.g. database created but no
       
   894             // root folder because of leave). No data is lost by deleting
       
   895             // the file; it has just been created.
       
   896             iDbs.DeleteDatabase( aPath, KDbPolicyUid );
       
   897             User::Leave( err );
       
   898             }
       
   899         }
       
   900 
       
   901     // Here we have the database, successfully created. It is closed now.
       
   902     // Open it and make some repairs if needed.
       
   903 	TInt error;
       
   904 	error = iDatabase.Open( iDbs, dbFile.FullName(), iSecureDbFormat );
       
   905 	if (error != KErrNone)
       
   906 		{
       
   907 		User::Leave( error );
       
   908 		}
       
   909     iOpen = ETrue;
       
   910     if ( IsDamagedL() )
       
   911         {
       
   912         RecoverL();
       
   913         }
       
   914     // Verify structure and upgrade if needed.
       
   915     RFavouritesSrvTable::VerifyStructureL( iDatabase, ETrue );
       
   916     }
       
   917 
       
   918 // ---------------------------------------------------------
       
   919 // CFavouritesSrvDb::DeleteOrphanedFilesL
       
   920 // ---------------------------------------------------------
       
   921 //
       
   922 void CFavouritesSrvDb::DeleteOrphanedFilesL()
       
   923     {
       
   924     // Get all uids and sort them by uid.
       
   925     CArrayFix<TInt>* uids =
       
   926         new (ELeave) CArrayFixFlat<TInt>( KUidListGranularity );
       
   927     CleanupStack::PushL( uids );
       
   928     GetUidsL( *uids, TFavouritesFilter() );
       
   929     TKeyArrayFix key( 0, ECmpTInt32 );
       
   930     uids->Sort( key );
       
   931 
       
   932     // Get a directory listing.
       
   933     RDir dir;
       
   934     User::LeaveIfError( dir.Open( iFs, *iSavedFilePath, KEntryAttNormal ) );
       
   935     CleanupClosePushL<RDir>( dir );
       
   936 
       
   937     TEntryArray files;
       
   938     TInt err = dir.Read( files );
       
   939     if( err != KErrEof )    // KErrEof means all files read.
       
   940         {
       
   941         User::Leave( err );
       
   942         }
       
   943 
       
   944     // Now check if any of the files is orphaned.
       
   945     TParse parse;
       
   946     TInt dummy;
       
   947     TInt uid;
       
   948     TInt i;
       
   949     const TInt KElementFound = 0;
       
   950     
       
   951     for ( i = 0; i < files.Count(); i++ )
       
   952         {
       
   953         uid = UidForFilename( files[i].iName );
       
   954         if ( uid == KFavouritesNullUid || 
       
   955         	 uids->FindIsq( uid, key, dummy ) != KElementFound )
       
   956             {
       
   957             // The filename is in the required format (8 char hex number),
       
   958             // but no item for this file -> an orphaned file.
       
   959             User::LeaveIfError
       
   960                 ( parse.SetNoWild( files[i].iName, iSavedFilePath, NULL ) );
       
   961             (void)iFs.Delete( parse.FullName() );
       
   962             }
       
   963         }
       
   964 
       
   965     CleanupStack::PopAndDestroy( 2, uids ); // dir, uids
       
   966     }
       
   967 
       
   968 
       
   969 // ---------------------------------------------------------
       
   970 // CFavouritesSrvDb::BeginIfNeededL
       
   971 // ---------------------------------------------------------
       
   972 //
       
   973 void CFavouritesSrvDb::BeginIfNeededL( TBool aWrite, TBool& aOwnTransaction )
       
   974     {
       
   975     aOwnTransaction = EFalse;
       
   976     if ( !iInTransaction )
       
   977         {
       
   978         // Not in transaction yet.
       
   979         BeginL( aWrite );
       
   980         aOwnTransaction = ETrue;
       
   981         CleanupStack::PushL( TCleanupItem( StaticRollback, this ) );
       
   982         }
       
   983     }
       
   984 
       
   985 // ---------------------------------------------------------
       
   986 // CFavouritesSrvDb::CommitIfNeeded
       
   987 // ---------------------------------------------------------
       
   988 //
       
   989 void CFavouritesSrvDb::CommitIfNeededL( TBool aOwnTransaction )
       
   990     {
       
   991     if ( aOwnTransaction )
       
   992         {
       
   993         CommitL();
       
   994         CleanupStack::Pop();    // StaticRollback, pushed in BeginL
       
   995         }
       
   996     }
       
   997 
       
   998 
       
   999 // ---------------------------------------------------------
       
  1000 // CFavouritesSrvDb::CreateDatabaseL
       
  1001 // ---------------------------------------------------------
       
  1002 //
       
  1003 void CFavouritesSrvDb::CreateDatabaseL( TParse& aDbFile, TBool aDoImport )
       
  1004     {
       
  1005     // Make the database.
       
  1006     // 
       
  1007     TInt errorCode = iDatabase.Create( iDbs, aDbFile.FullName(), iSecureDbFormat);
       
  1008     
       
  1009     User::LeaveIfError( errorCode );
       
  1010     CleanupClosePushL<RDbNamedDatabase>( iDatabase );
       
  1011 	// Create table.
       
  1012     RFavouritesSrvTable::CreateStructureL( iDatabase );
       
  1013     // Create the root folder. No need to close the database after schema
       
  1014     // modifications in ER5.
       
  1015     CreateRootFolderL();
       
  1016     // If the bookmark import file exists on the z: drive, re-import the bookmarks.
       
  1017 #ifndef __WINSCW__
       
  1018     _LIT(KBookmarkImportFile,"z:\\data\\BookmarkImportSample.txt");            // armv5
       
  1019 #else
       
  1020     _LIT(KBookmarkImportFile,"c:\\private\\10008d38\\BookmarkImportSample.txt"); // winscw
       
  1021 #endif
       
  1022     if( aDoImport )
       
  1023     	{
       
  1024         TUint attImport;
       
  1025         User::LeaveIfError( iFs.Connect() );
       
  1026         TInt errImport = iFs.Att( KBookmarkImportFile(), attImport );
       
  1027         if ( errImport == KErrNone )
       
  1028            {
       
  1029            // Bookmark import file exists.  Import to browserbookmarks.db database.
       
  1030            ImportL( KBookmarkImportFile() );
       
  1031            }
       
  1032     	}
       
  1033     CleanupStack::PopAndDestroy();  // close iDatabase
       
  1034     }
       
  1035 
       
  1036 
       
  1037 
       
  1038 // ---------------------------------------------------------
       
  1039 // CFavouritesSrvDb::CreateRootFolderL
       
  1040 // ---------------------------------------------------------
       
  1041 //
       
  1042 void CFavouritesSrvDb::CreateRootFolderL()
       
  1043     {
       
  1044     // Database just created; we have exclusive access.
       
  1045     iTable.OpenL( iDatabase );
       
  1046     CleanupClosePushL<RFavouritesSrvTable>( iTable );
       
  1047     CFavouritesItemImpl* root = CFavouritesItemImpl::NewLC();
       
  1048     // Add a new empty folder to the database.
       
  1049     root->SetType( CFavouritesItem::EFolder );
       
  1050     root->SetParentFolder( KFavouritesNullUid );
       
  1051     iTable.InsertLC();
       
  1052     iTable.WriteItemDataL( *root );
       
  1053     // Now the cursor is positioned over the new entry; change its Uid
       
  1054     // so it becomes the root folder.
       
  1055     iTable.SetUidL( KFavouritesRootUid );
       
  1056     iTable.PutL();
       
  1057     // Now we have the root. The first entry added came with 0 Uid, so this
       
  1058     // value will never be used again.
       
  1059     CleanupStack::PopAndDestroy( 2 );   // root, close iTable
       
  1060     }
       
  1061 
       
  1062 // ---------------------------------------------------------
       
  1063 // CFavouritesSrvDb::DeleteCurrentL
       
  1064 // ---------------------------------------------------------
       
  1065 //
       
  1066 void CFavouritesSrvDb::DeleteCurrentL( CArrayFix<TInt>& aDeletedUids )
       
  1067     {
       
  1068     TInt uid;
       
  1069     iTable.GetL();
       
  1070     if( iTable.ReadOnly() )
       
  1071         {
       
  1072         User::Leave( KErrAccessDenied );
       
  1073         }
       
  1074     if ( iTable.Type() == CFavouritesItem::EFolder )
       
  1075         {
       
  1076         // This is a folder. Delete contents.
       
  1077         // Save cursor pos, since the cursor will be moved.
       
  1078         TDbBookmark originalPos = iTable.Bookmark();
       
  1079         iTable.SetFiltersL( TFavouritesFilter( iTable.Uid(),
       
  1080             CFavouritesItem::ENone, NULL, KFavouritesNullContextId ) );
       
  1081         iTable.BeginningL();
       
  1082         while ( iTable.NextL() )
       
  1083             {
       
  1084             iTable.GetL();
       
  1085             if( iTable.ReadOnly() )
       
  1086                 {
       
  1087                 // Read-only item in a non-read-only folder.
       
  1088                 User::Leave( KErrAccessDenied );
       
  1089                 }
       
  1090             else
       
  1091                 {
       
  1092                 // Get uid of item to be deleted
       
  1093                 uid = iTable.Uid();
       
  1094                 iTable.DeleteL();
       
  1095                 aDeletedUids.AppendL( uid );
       
  1096                 iUpdatesSinceLastCompact++;
       
  1097                 }
       
  1098             }
       
  1099         // Restore cursor pos.
       
  1100         iTable.ClearFilters();
       
  1101         iTable.GotoL( originalPos );
       
  1102         iTable.GetL();
       
  1103         }
       
  1104 
       
  1105     // Now delete the item itself. If it's a folder and there is no error
       
  1106     // so far, it is empty by now. Error indicates read-only item in this
       
  1107     // non-read-only folder, so keep the folder as well.
       
  1108     uid = iTable.Uid();
       
  1109     iTable.DeleteL();
       
  1110     aDeletedUids.AppendL( uid );
       
  1111     iUpdatesSinceLastCompact++;
       
  1112     }
       
  1113 
       
  1114 // ---------------------------------------------------------
       
  1115 // CFavouritesSrvDb::UpdateCurrentL
       
  1116 // ---------------------------------------------------------
       
  1117 //
       
  1118 void CFavouritesSrvDb::UpdateCurrentL
       
  1119 ( CFavouritesItemImpl& aItem, CFavouritesSrvDb::TRenameType aRenameType )
       
  1120     {
       
  1121     if ( !CFavouritesItemImpl::IsValidName( aItem.Name() ) )
       
  1122         {
       
  1123         // CFavouritesItemImpl::IsValidL also checks this; but we want to
       
  1124         // return different error code for this case, so manually check this
       
  1125         // first.
       
  1126         User::Leave( KErrBadName );
       
  1127         }
       
  1128 
       
  1129     if ( !aItem.IsValid() )
       
  1130         {
       
  1131         User::Leave( KErrArgument );
       
  1132         }
       
  1133 
       
  1134     HBufC* newName = NULL;
       
  1135     // Save cursor pos; parent folder and name checking will move it.
       
  1136     TDbBookmark originalPos = iTable.Bookmark();
       
  1137     iTable.GetL();
       
  1138     TInt oldParent = iTable.ParentFolder();
       
  1139     TInt uid = iTable.Uid();
       
  1140     if ( iTable.Type() != aItem.Type() )
       
  1141         {
       
  1142         // Cannot change type.
       
  1143         User::Leave( KErrArgument );
       
  1144         }
       
  1145 
       
  1146     if ( iTable.ReadOnly() )
       
  1147         {
       
  1148         // Read-only item.
       
  1149         User::Leave( KErrAccessDenied );
       
  1150         }
       
  1151 
       
  1152     if ( aItem.Type() == CFavouritesItem::EFolder &&
       
  1153         aItem.ParentFolder() != KFavouritesRootUid )
       
  1154         {
       
  1155         // Folders must be in the root folder
       
  1156         // (folder hierarchy is only one-level deep).
       
  1157         User::Leave( KErrArgument );
       
  1158         }
       
  1159 
       
  1160     if ( oldParent != aItem.ParentFolder() &&
       
  1161         !FolderExistsL( aItem.ParentFolder() ) )
       
  1162         {
       
  1163         // No parent folder.
       
  1164         // (Not checked if the parent folder has not changed.)
       
  1165         User::Leave( KErrArgument );
       
  1166         }
       
  1167 
       
  1168     if ( aRenameType != ESuppressCheck )
       
  1169         {
       
  1170         if ( !IsUniqueNameL( aItem.Name(), aItem.ParentFolder(), uid ) )
       
  1171             {
       
  1172             if ( aRenameType == EAutoRename )
       
  1173                 {
       
  1174                 // Name is conflicting, rename automatically.
       
  1175                 newName = AllocUniqueNameLC
       
  1176                     ( aItem.Name(), aItem.ParentFolder(), uid );
       
  1177                 }
       
  1178             else
       
  1179                 {
       
  1180                 User::Leave( KErrAlreadyExists );
       
  1181                 }
       
  1182             }
       
  1183         }
       
  1184 
       
  1185     // All is well so far; update is valid.
       
  1186     iTable.PutWriteLockL();
       
  1187     // If there is a new name, set it.
       
  1188     if ( newName )
       
  1189         {
       
  1190         aItem.SetNameL( *newName );
       
  1191         }
       
  1192     // Validation may have moved the cursor; set it back.
       
  1193     iTable.GotoL( originalPos );
       
  1194     iTable.UpdateLC();                      // Prepare for update.
       
  1195     iTable.WriteItemDataL( aItem );         // Put the data.
       
  1196     iTable.SetFactoryItemL( EFalse );
       
  1197     iTable.PutL();                          // Apply changes.
       
  1198     aItem.SetUid( iTable.Uid() );           // Get Uid.
       
  1199     aItem.SetModified( iTable.Modified() ); // Get modtime.
       
  1200     // Sanity check; it must be the specified Uid.
       
  1201     __ASSERT_DEBUG( aItem.Uid() == uid,
       
  1202         FavouritesPanic( EFavouritesInternal ) );
       
  1203     iUpdatesSinceLastCompact++;
       
  1204 
       
  1205     if ( newName )
       
  1206         {
       
  1207         CleanupStack::PopAndDestroy();  // newName
       
  1208         }
       
  1209     }
       
  1210 
       
  1211 // ---------------------------------------------------------
       
  1212 // CFavouritesSrvDb::DoAddL
       
  1213 // ---------------------------------------------------------
       
  1214 //
       
  1215 void CFavouritesSrvDb::DoAddL
       
  1216         (
       
  1217         CFavouritesItemImpl& aItem,
       
  1218         CFavouritesSrvDb::TRenameType aRenameType,
       
  1219         TBool aFactoryItem /*=EFalse*/,
       
  1220         TBool aReadOnly /*=EFalse*/
       
  1221         )
       
  1222     {
       
  1223     if ( !CFavouritesItemImpl::IsValidName( aItem.Name() ) )
       
  1224         {
       
  1225         // CFavouritesItemImpl::IsValidL also checks this; but we want to
       
  1226         // return different error code for this case, so manually check this
       
  1227         // first.
       
  1228         User::Leave( KErrBadName );
       
  1229         }
       
  1230 
       
  1231     if ( !aItem.IsValid() )
       
  1232         {
       
  1233         User::Leave( KErrArgument );
       
  1234         }
       
  1235 
       
  1236     HBufC* newName = NULL;
       
  1237     if ( aItem.Type() == CFavouritesItem::EFolder &&
       
  1238         aItem.ParentFolder() != KFavouritesRootUid )
       
  1239         {
       
  1240         // Folders must be in the root folder
       
  1241         // (folder hierarchy is only one-level deep).
       
  1242         User::Leave( KErrArgument );
       
  1243         }
       
  1244 
       
  1245     if ( !FolderExistsL( aItem.ParentFolder() ) )
       
  1246         {
       
  1247         // No parent folder.
       
  1248         User::Leave( KErrArgument );
       
  1249         }
       
  1250 
       
  1251     if ( aRenameType != ESuppressCheck )
       
  1252         {
       
  1253         if ( !IsUniqueNameL
       
  1254                 ( aItem.Name(), aItem.ParentFolder(), KFavouritesNullUid ) )
       
  1255             {
       
  1256             if ( aRenameType == EAutoRename )
       
  1257                 {
       
  1258                 // Name is conflicting, rename automatically.
       
  1259                 newName = AllocUniqueNameLC
       
  1260                     ( aItem.Name(), aItem.ParentFolder(), KFavouritesNullUid );
       
  1261                 }
       
  1262             else
       
  1263                 {
       
  1264                 User::Leave( KErrAlreadyExists );
       
  1265                 }
       
  1266             }
       
  1267         }
       
  1268 
       
  1269     // All is well so far; update is valid.
       
  1270     iTable.PutWriteLockL();
       
  1271     // If there is a new name, set it.
       
  1272     if ( newName )
       
  1273         {
       
  1274         aItem.SetNameL( *newName );
       
  1275         }
       
  1276     // Validation may have moved the cursor; set it back.
       
  1277     iTable.InsertLC();                      // Prepare for update.
       
  1278     iTable.WriteItemDataL( aItem );         // Put the data.
       
  1279     iTable.SetFactoryItemL( aFactoryItem );
       
  1280     iTable.SetReadOnlyL( aReadOnly );
       
  1281     iTable.PutL();                          // Apply changes.
       
  1282     aItem.SetUid( iTable.Uid() );           // Get Uid.
       
  1283     aItem.SetModified( iTable.Modified() ); // Get modtime.
       
  1284     // Sanity check; no item can exist with the Null uid.
       
  1285     __ASSERT_DEBUG( aItem.Uid() != KFavouritesNullUid,
       
  1286         FavouritesPanic( EFavouritesNullUidInDatabase ) );
       
  1287     iUpdatesSinceLastCompact++;
       
  1288 
       
  1289     if ( newName )
       
  1290         {
       
  1291         CleanupStack::PopAndDestroy();  // newName
       
  1292         }
       
  1293     }
       
  1294 
       
  1295 // ---------------------------------------------------------
       
  1296 // CFavouritesSrvDb::IsUniqueNameL
       
  1297 // ---------------------------------------------------------
       
  1298 //
       
  1299 TBool CFavouritesSrvDb::IsUniqueNameL
       
  1300 ( const TDesC& aName, TInt aFolder, TInt aAcceptUid )
       
  1301     {
       
  1302     __ASSERT_DEBUG( CFavouritesItemImpl::IsValidName( aName ), \
       
  1303         FavouritesPanic( EFavouritesInternal ) );
       
  1304     TBool unique = ETrue;
       
  1305     TInt uid;
       
  1306     iTable.SetFiltersL( TFavouritesFilter( aFolder, CFavouritesItem::ENone,
       
  1307         &aName, KFavouritesNullContextId ) );
       
  1308     iTable.BeginningL();
       
  1309     while ( iTable.NextL() )
       
  1310         {
       
  1311         // We have an item with this name; check if it is aAcceptUid or
       
  1312         // one of the special items (for which names need not be unique).
       
  1313         iTable.GetL();
       
  1314         uid = iTable.Uid();
       
  1315         if (
       
  1316            uid != aAcceptUid &&
       
  1317            uid != KFavouritesHomepageUid &&
       
  1318            uid != KFavouritesLastVisitedUid &&
       
  1319            uid != KFavouritesStartPageUid &&
       
  1320            uid != KFavouritesAdaptiveItemsFolderUid
       
  1321            )
       
  1322             {
       
  1323             // It's not aAcceptUid or special item. We have a name clash.
       
  1324             unique = EFalse;
       
  1325             break;
       
  1326             }
       
  1327         }
       
  1328     iTable.ClearFilters();
       
  1329     return unique;
       
  1330     }
       
  1331 
       
  1332 // ---------------------------------------------------------
       
  1333 // CFavouritesSrvDb::MakeNameUniqueL
       
  1334 // ---------------------------------------------------------
       
  1335 //
       
  1336 void CFavouritesSrvDb::MakeUniqueNameL
       
  1337 ( TDes& aName, TInt aFolder, TInt aAcceptUid )
       
  1338     {
       
  1339     TBool forcePostfix = EFalse;
       
  1340     __ASSERT_DEBUG( CFavouritesItemImpl::IsValidName( aName ), \
       
  1341         FavouritesPanic( EFavouritesInternal ) );
       
  1342     // Make sure the result fits.
       
  1343     __ASSERT_DEBUG( aName.MaxLength() >= Min\
       
  1344         ( aName.Length() + KFavouritesMaxPostfix, KFavouritesMaxName ), \
       
  1345         FavouritesPanic( EFavouritesBufferTooSmall ) );
       
  1346 
       
  1347     TPtrC prefix = GetPrefix( aName );
       
  1348     if ( prefix.Length() + KFavouritesMaxPostfix > KFavouritesMaxName )
       
  1349         {
       
  1350         // Oops, this prefix is so long that if we append the longest possible
       
  1351         // postfix to it, the result will not fit into a bookmark name!
       
  1352         // In this case, we truncate the prefix. The truncated prefix is most
       
  1353         // likely not conflicting as is, but we do the postfix appending
       
  1354         // anyway.
       
  1355         prefix.Set
       
  1356             ( prefix.Left( KFavouritesMaxName - KFavouritesMaxPostfix ) );
       
  1357         forcePostfix = ETrue;
       
  1358         }
       
  1359     HBufC* buf = HBufC::NewLC( prefix.Length() + KFavouritesMaxPostfix );
       
  1360     _LIT( KFormatPrefix, "%S*" );
       
  1361     buf->Des().Format( KFormatPrefix, &prefix );
       
  1362     iTable.SetFiltersL( TFavouritesFilter
       
  1363         ( aFolder, CFavouritesItem::ENone, buf, KFavouritesNullContextId ) );
       
  1364     CleanupStack::PopAndDestroy();  // buf
       
  1365 
       
  1366     TInt uid;
       
  1367     TInt postfix;
       
  1368     CArrayFix<TInt>* postfixes =
       
  1369         new (ELeave) CArrayFixFlat<TInt>( KPostfixListGranularity );
       
  1370     CleanupStack::PushL( postfixes );
       
  1371     iTable.BeginningL();
       
  1372     while ( iTable.NextL() )
       
  1373         {
       
  1374         iTable.GetL();
       
  1375         uid = iTable.Uid();
       
  1376         if (
       
  1377            uid != aAcceptUid &&
       
  1378            uid != KFavouritesHomepageUid &&
       
  1379            uid != KFavouritesLastVisitedUid &&
       
  1380            uid != KFavouritesStartPageUid &&
       
  1381            uid != KFavouritesAdaptiveItemsFolderUid
       
  1382            )
       
  1383             {
       
  1384             // Appending all values (incl. negative values and duplicates).
       
  1385             postfixes->AppendL( GetPostfix( iTable.Name(), prefix ) );
       
  1386             }
       
  1387         }
       
  1388     iTable.ClearFilters();
       
  1389 
       
  1390     // Sort postfixes ascending.
       
  1391     TKeyArrayFix key( 0, ECmpTInt );
       
  1392     User::LeaveIfError( postfixes->Sort( key ) );
       
  1393 
       
  1394     // Initial postfix candidate is 0 ("no postfix"), or 1 if forcePostfix
       
  1395     // is ETrue.
       
  1396     postfix = forcePostfix ? 1 : 0;
       
  1397     // Find the first free postfix, above the starting candidate (0 or 1).
       
  1398     // The loop skips negative values and duplicates.
       
  1399     TInt i;
       
  1400     for ( i = 0; i < postfixes->Count(); i++ )
       
  1401         {
       
  1402         if ( postfixes->At( i ) < postfix )
       
  1403             {
       
  1404             // This value is smaller than the current candidate;
       
  1405             // candidate stays the current one (do nothing); but keep checking
       
  1406             // forthcoming bigger values (continue).
       
  1407             ;
       
  1408             }
       
  1409         else if ( postfixes->At( i ) == postfix )
       
  1410             {
       
  1411             // This postfix already taken. Candidate is next one.
       
  1412             postfix++;
       
  1413             }
       
  1414         else
       
  1415             {
       
  1416             // postfixes->At( i ) > postfix: a "hole" is found.
       
  1417             //
       
  1418             // This case could be the condition in the controlling "for" (and
       
  1419             // the "break" statement could be avoided); but I intentionally
       
  1420             // placed it here so the logic of the "hole-search" can be seen
       
  1421             // more clearly.
       
  1422             break;
       
  1423             }
       
  1424         }
       
  1425     CleanupStack::PopAndDestroy();      // postfixes
       
  1426 
       
  1427     if ( postfix == 0 )
       
  1428         {
       
  1429         // First unique name is the prefix without any postfix.
       
  1430         // Simply set length to the prefix length.
       
  1431         aName.SetLength( prefix.Length() );
       
  1432         }
       
  1433     else
       
  1434         {
       
  1435         // Append a new postfix to the prefix.
       
  1436         // It seems we have to copy the prefix into a buffer.
       
  1437         // The prefix points to aName, so Format would format aName
       
  1438         // using the prefix from itself. But Format does some weird
       
  1439         // tricks (filling the buffer with some rubbish before writing
       
  1440         // into it). It's not sprintf :-(.
       
  1441         buf = prefix.AllocLC();
       
  1442         _LIT( KFormatSmallPostfix, "%S(0%d)" );
       
  1443         _LIT( KFormatLargePostfix, "%S(%d)" );
       
  1444         if ( postfix < 10 )
       
  1445             {
       
  1446             aName.Format( KFormatSmallPostfix, buf, postfix );
       
  1447             }
       
  1448         else
       
  1449             {
       
  1450             aName.Format( KFormatLargePostfix, buf, postfix );
       
  1451             }
       
  1452         CleanupStack::PopAndDestroy();  // buf
       
  1453         }
       
  1454 
       
  1455     // Sanity check. The generated name should really be unique.
       
  1456     __ASSERT_DEBUG \
       
  1457         ( \
       
  1458         IsUniqueNameL( aName, aFolder, aAcceptUid ), \
       
  1459         FavouritesPanic( EFavouritesInternal ) \
       
  1460         );
       
  1461     }
       
  1462 
       
  1463 // ---------------------------------------------------------
       
  1464 // CFavouritesSrvDb::AllocUniqueNameLC
       
  1465 // ---------------------------------------------------------
       
  1466 //
       
  1467 HBufC* CFavouritesSrvDb::AllocUniqueNameLC
       
  1468 ( const TDesC& aName, TInt aFolder, TInt aAcceptUid )
       
  1469     {
       
  1470     HBufC* uniqueName = HBufC::NewLC( aName.Length() + KFavouritesMaxPostfix );
       
  1471     *uniqueName = aName;
       
  1472     TPtr ptr( uniqueName->Des() );
       
  1473     MakeUniqueNameL( ptr, aFolder, aAcceptUid );
       
  1474     return uniqueName;
       
  1475     }
       
  1476 
       
  1477 // ---------------------------------------------------------
       
  1478 // CFavouritesSrvDb::StaticRollback
       
  1479 // ---------------------------------------------------------
       
  1480 //
       
  1481 void CFavouritesSrvDb::StaticRollback( TAny* aDb )
       
  1482     {
       
  1483     STATIC_CAST( CFavouritesSrvDb*, aDb )->Rollback();
       
  1484     }
       
  1485 
       
  1486 // ---------------------------------------------------------
       
  1487 // CFavouritesSrvDb::RestoreFactorySettingsL
       
  1488 // ---------------------------------------------------------
       
  1489 //
       
  1490 void CFavouritesSrvDb::RestoreFactorySettingsL
       
  1491 ( RFavouritesSrvTable& aReferenceTable, CUidMap& aApMap )
       
  1492     {
       
  1493     __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
       
  1494 
       
  1495     // 1. Check ContextId-s of folders in reference table, and clear all those
       
  1496     //    ContextId-s from our folders.
       
  1497     //
       
  1498     //    This part is a bit "out of line" for the Engine, as here we do deal
       
  1499     //    with ContextId semantics: we ensure that we don't create more folders
       
  1500     //    with a given ContextId. This ensures the expected correct behaviour
       
  1501     //    of Seamless Link functionality after an RFS: the newly restored
       
  1502     //    folders become the Seamless Link folders.
       
  1503     //    (Note: if the reference table contains more folders with the same
       
  1504     //    ContextId, they will be mechanically copied. Checking that is really
       
  1505     //    not our business.)
       
  1506 
       
  1507     TInt32 contextId;
       
  1508     aReferenceTable.BeginningL();
       
  1509     while ( aReferenceTable.NextL() )
       
  1510         {
       
  1511         aReferenceTable.GetL();
       
  1512         contextId = aReferenceTable.ContextId();
       
  1513         if ( contextId != KFavouritesNullContextId )
       
  1514             {
       
  1515             // Folders from root with given context id.
       
  1516             iTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
       
  1517                 CFavouritesItem::EFolder, NULL, contextId ) );
       
  1518             iTable.BeginningL();
       
  1519             while( iTable.NextL() )
       
  1520                 {
       
  1521                 iTable.UpdateLC();
       
  1522                 iTable.SetContextIdL( KFavouritesNullContextId );
       
  1523                 iTable.PutL( /*aTouch=*/EFalse );
       
  1524                 }
       
  1525             iTable.ClearFilters();
       
  1526             }
       
  1527         }
       
  1528 
       
  1529     // 2. Delete all items that have the "factory item" flag.
       
  1530     //    (These are the unmodified factory items - any modification
       
  1531     //    clears the flag.) The "factory item" and read-only flag of floders are cleared.
       
  1532     
       
  1533 	iTable.BeginningL();
       
  1534     while ( iTable.NextL() )
       
  1535         {
       
  1536         iTable.GetL();
       
  1537         if ( iTable.FactoryItem() )
       
  1538             {
       
  1539             switch ( iTable.Type() )
       
  1540                 {
       
  1541                 case CFavouritesItem::EItem:
       
  1542                     {
       
  1543 					// Delete unmodified factory item 
       
  1544 					iTable.DeleteL();
       
  1545                     break;
       
  1546                     }
       
  1547 
       
  1548                 case CFavouritesItem::EFolder:
       
  1549                     {
       
  1550                     // Clear flags for folders.
       
  1551                     iTable.UpdateLC();
       
  1552                     iTable.SetFactoryItemL( EFalse );
       
  1553                     iTable.SetReadOnlyL( EFalse );
       
  1554                     iTable.PutL( /*aTouch=*/EFalse );
       
  1555                     break;
       
  1556                     }
       
  1557 
       
  1558                 default:
       
  1559                     {
       
  1560                     FavouritesPanic( EFavouritesInternal );
       
  1561                     break;
       
  1562                     }
       
  1563                 }
       
  1564             }
       
  1565         }
       
  1566 
       
  1567     // 3. Lookup folders by name, creating new ones if necessary. The target
       
  1568     //    folder gets the attributes of the source folder (read-only and
       
  1569     //    factory item flag), regardless of whether it is existing or newly
       
  1570     //    created. During this process, a mapping table
       
  1571     //    (source folder uid -> target folder uid) is built. 
       
  1572 
       
  1573     TTime modTime;
       
  1574     SUidPair mapping;
       
  1575     TPtrC name;
       
  1576     CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
       
  1577     CUidMap* parentMap = new (ELeave) CUidMap( 1 );
       
  1578     CleanupStack::PushL( parentMap );
       
  1579 
       
  1580     // Add the "root->root" mapping to the map.
       
  1581     mapping.iUid1 = KFavouritesRootUid;
       
  1582     mapping.iUid2 = KFavouritesRootUid;
       
  1583     parentMap->AppendL( mapping );
       
  1584 
       
  1585     // All folder of reference table in root.
       
  1586     aReferenceTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
       
  1587         CFavouritesItem::EFolder, NULL, KFavouritesNullContextId ) );
       
  1588     aReferenceTable.BeginningL();
       
  1589     while( aReferenceTable.NextL() )
       
  1590         {
       
  1591         aReferenceTable.GetL();
       
  1592         name.Set( aReferenceTable.Name() );
       
  1593         __ASSERT_DEBUG( name.Length(), FavouritesPanic( EFavouritesInternal ) );
       
  1594         // Folders matching the name.
       
  1595         iTable.SetFiltersL( TFavouritesFilter( KFavouritesRootUid,
       
  1596             CFavouritesItem::EFolder, &name, KFavouritesNullContextId ) );
       
  1597         iTable.BeginningL();
       
  1598         if( iTable.NextL() )
       
  1599             {
       
  1600             // Folder exists with this name.
       
  1601             // Copy read-only and factory item flags from reference table.
       
  1602             // Also copy ContextId (possibly we cleared that earlier).
       
  1603             iTable.UpdateLC();
       
  1604             iTable.SetReadOnlyL( aReferenceTable.ReadOnly() );
       
  1605             iTable.SetFactoryItemL( aReferenceTable.FactoryItem() );
       
  1606             iTable.SetContextIdL( aReferenceTable.ContextId() );
       
  1607             iTable.PutL( /*aTouch=*/EFalse );
       
  1608             }
       
  1609         else
       
  1610             {
       
  1611             // No folder exists with this name.
       
  1612             // Add now by copying from reference table (incl. modtime).
       
  1613             aReferenceTable.ReadItemDataL( *item );
       
  1614             modTime = item->Modified();
       
  1615             DoAddL
       
  1616                 (
       
  1617                 *item,
       
  1618                 EDontRename,
       
  1619                 /*aFactoryItem=*/item->IsFactoryItem(),
       
  1620                 /*aReadOnly=*/item->IsReadOnly()
       
  1621                 );
       
  1622             // Cursor is still on the added record. Set modtime.
       
  1623             // Not using CFavouritesSrvDb::SetModifiedL() - that would mess up
       
  1624             // the filters.
       
  1625             iTable.UpdateLC();
       
  1626             iTable.SetModifiedL( modTime );
       
  1627             iTable.PutL( /*aTouch=*/ EFalse );
       
  1628             }
       
  1629         // In both cases (existing folder updated, or new added), the cursor
       
  1630         // is now on the target folder. Add a new mapping entry.
       
  1631         mapping.iUid1 = aReferenceTable.Uid();
       
  1632         mapping.iUid2 = iTable.Uid();
       
  1633         parentMap->AppendL( mapping );
       
  1634         iTable.ClearFilters();
       
  1635         }
       
  1636     aReferenceTable.ClearFilters();
       
  1637 
       
  1638     // 4. Replace the unmodified factory items of our table with corresponding items from reference table and 
       
  1639 	// add remaining items in the reference table to our table,
       
  1640 	// with AP mapping and parent folder mapping applied.
       
  1641 
       
  1642     TInt i;
       
  1643     TFavouritesWapAp ap;
       
  1644 	TInt origId;
       
  1645 	TInt newId;
       
  1646 
       
  1647     // Get all items.
       
  1648     aReferenceTable.SetFiltersL( TFavouritesFilter ( KFavouritesNullUid,
       
  1649         CFavouritesItem::EItem, NULL, KFavouritesNullContextId ) );
       
  1650     aReferenceTable.BeginningL();
       
  1651 
       
  1652     while ( aReferenceTable.NextL() )
       
  1653         {
       
  1654         aReferenceTable.GetL();
       
  1655         aReferenceTable.ReadItemDataL( *item );
       
  1656         modTime = item->Modified();
       
  1657 		origId = item->Uid();
       
  1658 
       
  1659         // Remap parent folder.
       
  1660         for( i = 0; i < parentMap->Count(); i++ )
       
  1661             {
       
  1662             if( item->ParentFolder() == parentMap->At( i ).iUid1 )
       
  1663                 {
       
  1664                 item->SetParentFolder( parentMap->At( i ).iUid2 );
       
  1665                 break;
       
  1666                 }
       
  1667             // Parent folder mapping should always be successful.
       
  1668             __ASSERT_DEBUG( i < parentMap->Count(), \
       
  1669                 FavouritesPanic( EFavouritesInternal ) );
       
  1670             }
       
  1671 				
       
  1672 		// Add the item.
       
  1673 		DoAddL
       
  1674 			(
       
  1675 			*item,
       
  1676 			EAutoRename,
       
  1677 			/*aFactoryItem=*/ETrue,
       
  1678 			/*aReadOnly=*/item->IsReadOnly()
       
  1679 			);	
       
  1680 
       
  1681 		// Cursor is still on the added record. Set modtime.
       
  1682         // Not using CFavouritesSrvDb::SetModifiedL() - that would mess up
       
  1683         // the filters.
       
  1684         iTable.UpdateLC();
       
  1685         iTable.SetModifiedL( modTime );
       
  1686         iTable.PutL( /*aTouch=*/ EFalse );
       
  1687 		
       
  1688 		// Get the new item UID 
       
  1689 		newId = item->Uid();
       
  1690 
       
  1691 		if( !iTable.SeekToUidL( origId ) )
       
  1692 			{
       
  1693 			iTable.GotoToUidL(newId);
       
  1694 			iTable.UpdateLC();
       
  1695 			iTable.SetUidL( origId );
       
  1696 			iTable.PutL( /*aTouch=*/ EFalse );
       
  1697 			item->SetUid( origId );
       
  1698 			}        
       
  1699 
       
  1700         // Check AP, enrol for mapping if needed.
       
  1701         ap = item->WapAp();
       
  1702         if ( !ap.IsDefault() && !ap.IsNull() )
       
  1703             {
       
  1704             mapping.iUid1 = item->Uid();
       
  1705             mapping.iUid2 = STATIC_CAST( TInt, ap.ApId() );
       
  1706             aApMap.AppendL( mapping );
       
  1707             }
       
  1708         }
       
  1709     aReferenceTable.ClearFilters();
       
  1710 
       
  1711     CleanupStack::PopAndDestroy( 2 );   // parentMap, item
       
  1712     }
       
  1713 
       
  1714 // ---------------------------------------------------------
       
  1715 // CFavouritesSrvDb::SetAccessPointsL
       
  1716 // ---------------------------------------------------------
       
  1717 //
       
  1718 void CFavouritesSrvDb::SetAccessPointsL( const CUidMap& aApMap )
       
  1719     {
       
  1720     __ASSERT_DEBUG( InTransaction(), FavouritesPanic( EFavouritesInternal ) );
       
  1721     TInt i;
       
  1722     TFavouritesWapAp ap;
       
  1723     for ( i = 0; i < aApMap.Count(); i++ )
       
  1724         {
       
  1725         ap.SetApId( STATIC_CAST( TUint32, aApMap[i].iUid2 ) );
       
  1726         iTable.GotoToUidL( aApMap[i].iUid1 );
       
  1727         iTable.GetL();
       
  1728         iTable.UpdateLC();
       
  1729         iTable.SetWapApL( ap );
       
  1730         iTable.PutL( /*aTouch=*/ EFalse );
       
  1731         }
       
  1732     }
       
  1733 
       
  1734 
       
  1735 // ---------------------------------------------------------
       
  1736 // IMPORT BOOKMARKS CODE INTEGRATED FROM BOOKMARKS UTILITY
       
  1737 // ---------------------------------------------------------
       
  1738 
       
  1739 // CONSTANTS
       
  1740 
       
  1741 /// ',' character.
       
  1742 LOCAL_C const TUint KComma = ',';
       
  1743 /// '#' character.
       
  1744 LOCAL_C const TUint KHash = '#';
       
  1745 /// EOF (0) character.
       
  1746 LOCAL_C const TUint KEof = 0;
       
  1747 /// '\r' character.
       
  1748 LOCAL_C const TUint KCr = '\r';
       
  1749 /// '\n' character.
       
  1750 LOCAL_C const TUint KLf = '\n';
       
  1751 
       
  1752 /// LF-EOF stop token set.
       
  1753 _LIT( KStopLfEof, "\n\0" );
       
  1754 /// Comma stop token set.
       
  1755 _LIT( KStopComma, "," );
       
  1756 /// Comma-LF-EOF stop token set.
       
  1757 _LIT( KStopCommaLfEof, ",\n\0" );
       
  1758 
       
  1759 /// "Folder" kewyword.
       
  1760 _LIT( KFolder, "Folder" );
       
  1761 /// "Item" kewyword.
       
  1762 _LIT( KItem, "Item" );
       
  1763 
       
  1764 // ---------------------------------------------------------
       
  1765 // CFavouritesSrvDb::ImportL
       
  1766 // ---------------------------------------------------------
       
  1767 //
       
  1768 void CFavouritesSrvDb::ImportL( const TDesC& aFileName )
       
  1769     {
       
  1770     User::LeaveIfError( iFile.Open( iFs, aFileName,
       
  1771         EFileRead | EFileShareReadersOnly ) );
       
  1772     CleanupClosePushL<RUnicodeFile>( iFile );
       
  1773 
       
  1774     iFolderNames = new (ELeave) CArrayFixFlat<CFavouritesFolder>( 1 ); 
       
  1775     User::LeaveIfNull( iFolderNames  );                                
       
  1776     CleanupStack::PushL( iFolderNames );                               
       
  1777     
       
  1778     iBuf = new (ELeave) TText16[KFavouritesMaxUrl];
       
  1779     User::LeaveIfNull( iBuf );
       
  1780     CleanupStack::PushL( iBuf );
       
  1781 
       
  1782     iMaxCh = iBuf + KFavouritesMaxUrl;
       
  1783 
       
  1784     GetCharL();
       
  1785 
       
  1786     while( NextLineL() )
       
  1787        {;}
       
  1788 
       
  1789     TUint count = iFolderNames->Count();
       
  1790     for (TUint i = 0; i < count; i++)
       
  1791         {
       
  1792         CFavouritesFolder folder = iFolderNames->At(i);
       
  1793         delete folder.Name();
       
  1794         }
       
  1795     
       
  1796     CleanupStack::Pop(iBuf); //iBuf
       
  1797     delete iBuf;
       
  1798     CleanupStack::Pop(iFolderNames); //iFolderNames
       
  1799     delete iFolderNames;
       
  1800     CleanupStack::PopAndDestroy();  // close iFile
       
  1801     }
       
  1802 
       
  1803 // ---------------------------------------------------------
       
  1804 // CFavouritesSrvDb::GetCharL
       
  1805 // ---------------------------------------------------------
       
  1806 //
       
  1807 void CFavouritesSrvDb::GetCharL()
       
  1808     {
       
  1809     iCurCh = iFile.GetCharL();
       
  1810     if ( iCurCh == KCr )
       
  1811         {
       
  1812         // CR character found - ignore it. Not expecting CR to appear anywhere
       
  1813         // else than before an LF.
       
  1814         iCurCh = iFile.GetCharL();
       
  1815         }
       
  1816     }
       
  1817 
       
  1818 // ---------------------------------------------------------
       
  1819 // CFavouritesSrvDb::NextLineL
       
  1820 // ---------------------------------------------------------
       
  1821 //
       
  1822 TBool CFavouritesSrvDb::NextLineL()
       
  1823     {
       
  1824     switch( iCurCh )
       
  1825         {
       
  1826         case KEof:
       
  1827             // EOF
       
  1828             return EFalse;
       
  1829 
       
  1830         case KHash:
       
  1831             // Comment line; skip over.
       
  1832             SkipL( KStopLfEof );
       
  1833             GetCharL();
       
  1834             break;
       
  1835 
       
  1836         case KCr:
       
  1837         case KLf:
       
  1838             // Empty line; skip over.
       
  1839             GetCharL();
       
  1840             break;
       
  1841 
       
  1842         default:
       
  1843             // Parse bookmark attributes.
       
  1844             AttrsL();
       
  1845             break;
       
  1846         }
       
  1847     return ETrue;
       
  1848     }
       
  1849 
       
  1850 // ---------------------------------------------------------
       
  1851 // CFavouritesSrvDb::NextTokenL
       
  1852 // ---------------------------------------------------------
       
  1853 //
       
  1854 TPtrC CFavouritesSrvDb::NextTokenL( const TDesC& aStopCharSet )
       
  1855     {
       
  1856     iNextCh = iBuf; // Start storing token at start of buffer.
       
  1857     while ( iNextCh < iMaxCh )
       
  1858         {
       
  1859         if ( aStopCharSet.Locate( iCurCh ) != KErrNotFound )
       
  1860             {
       
  1861             // Stop character found - return what we have stored so far. This
       
  1862             // may be an empty string as well.
       
  1863             return TPtrC( iBuf, iNextCh - iBuf );
       
  1864             }
       
  1865         *iNextCh = STATIC_CAST( TText16, iCurCh );
       
  1866         iNextCh++;
       
  1867         GetCharL();
       
  1868         }
       
  1869     // No more space in buffer to store token.
       
  1870     User::Leave( KErrOverflow );
       
  1871     /*NOTREACHED*/
       
  1872     return TPtrC();
       
  1873     }
       
  1874 
       
  1875 // ---------------------------------------------------------
       
  1876 // CFavouritesSrvDb::NextIntTokenL
       
  1877 // ---------------------------------------------------------
       
  1878 //
       
  1879 TInt CFavouritesSrvDb::NextIntTokenL( const TDesC& aStopCharSet )
       
  1880     {
       
  1881     TInt ret = 0;
       
  1882     TPtrC token( NextTokenL( aStopCharSet ) );
       
  1883     if ( token.Length() )
       
  1884         {
       
  1885         TLex lex( token );
       
  1886         User::LeaveIfError( lex.Val( ret ) );
       
  1887         }
       
  1888     return ret;
       
  1889     }
       
  1890 
       
  1891 // ---------------------------------------------------------
       
  1892 // CFavouritesSrvDb::NextHexTokenL
       
  1893 // ---------------------------------------------------------
       
  1894 //
       
  1895 TInt32 CFavouritesSrvDb::NextHexTokenL( const TDesC& aStopCharSet )
       
  1896     {
       
  1897     TUint32 ret = 0;
       
  1898     TPtrC token( NextTokenL( aStopCharSet ) );
       
  1899     if ( token.Length() )
       
  1900         {
       
  1901         TLex lex( token );
       
  1902         User::LeaveIfError( lex.Val( ret, EHex ) );
       
  1903         }
       
  1904     return STATIC_CAST( TInt32, ret );
       
  1905     }
       
  1906 
       
  1907 // ---------------------------------------------------------
       
  1908 // CFavouritesSrvDb::SkipL
       
  1909 // ---------------------------------------------------------
       
  1910 //
       
  1911 void CFavouritesSrvDb::SkipL( const TDesC& aStopCharSet )
       
  1912     {
       
  1913     // Note that EOF also can be a stop character; aStopChar check has
       
  1914     // precendence over EOF check. That is the 'expected EOF' case.
       
  1915     while( aStopCharSet.Locate( iCurCh ) == KErrNotFound )
       
  1916         {
       
  1917         if ( iCurCh == KEof )
       
  1918             {
       
  1919             // Unexpected EOF.
       
  1920             User::Leave( KErrEof );
       
  1921             }
       
  1922         GetCharL();
       
  1923         }
       
  1924     }
       
  1925 
       
  1926 // ---------------------------------------------------------
       
  1927 // CFavouritesSrvDb::AttrsL
       
  1928 // ---------------------------------------------------------
       
  1929 //
       
  1930 void CFavouritesSrvDb::AttrsL()
       
  1931     {
       
  1932     TPtrC token;
       
  1933     TInt num = 0;
       
  1934     TBool readOnly( EFalse );
       
  1935   //  TBool factoryItem;
       
  1936     TBool preferred( EFalse );
       
  1937     TBool hidden( EFalse );
       
  1938     TFavouritesWapAp ap;
       
  1939     
       
  1940     iTable.OpenL( iDatabase );
       
  1941     CleanupClosePushL<RFavouritesSrvTable>( iTable );
       
  1942     iTable.BeginningL();
       
  1943     iTable.InsertLC();
       
  1944 
       
  1945     // Parse the line and fill item.
       
  1946 
       
  1947     // Type (including special items).
       
  1948     token.Set( NextTokenL( KStopComma ) );
       
  1949     if ( !token.Compare( KFolder ) )
       
  1950         {
       
  1951         iTable.SetTypeL( CFavouritesItem::EFolder );
       
  1952         }
       
  1953     else if ( !token.Compare( KItem ) )
       
  1954         {
       
  1955         iTable.SetTypeL( CFavouritesItem::EItem );
       
  1956         }
       
  1957     else
       
  1958         {
       
  1959         // Expected "Folder", "Item"
       
  1960         User::Leave( KErrCorrupt );
       
  1961         }
       
  1962     GetCharL();
       
  1963     // Name.
       
  1964     iTable.SetNameL( NextTokenL( KStopComma ) );
       
  1965     if (iTable.Type() == CFavouritesItem::EFolder)    // Remember the folder name for UID lookup.
       
  1966         {      
       
  1967         HBufC* buf = HBufC::NewLC( iTable.Name().Length() );
       
  1968         TPtr ptr( buf->Des() );
       
  1969         ptr.Copy( iTable.Name() );
       
  1970         CFavouritesFolder folder( buf, iTable.Uid() );
       
  1971         iFolderNames->AppendL( folder );
       
  1972         CleanupStack::Pop(); // for newlc of buf
       
  1973         }
       
  1974     GetCharL();
       
  1975 
       
  1976     // Parent folder.
       
  1977     iTable.SetParentFolderL( FolderByNameL( NextTokenL( KStopComma ) ) );
       
  1978 
       
  1979     GetCharL();
       
  1980 
       
  1981     // URL.
       
  1982     iTable.SetUrlL( NextTokenL( KStopComma ) );
       
  1983     GetCharL();
       
  1984 
       
  1985     // WAP AP.
       
  1986     token.Set( NextTokenL( KStopComma ) );
       
  1987     if ( token.Length() )
       
  1988         {
       
  1989         TLex lex( token );
       
  1990         if ( lex.Val( num ) != KErrNone )
       
  1991            {
       
  1992              IAPIdByNameL( token, num );
       
  1993            }
       
  1994         ap = num;
       
  1995         }
       
  1996     else
       
  1997     	{
       
  1998         ap.SetDefault();
       
  1999     	}
       
  2000     
       
  2001     iTable.SetWapApL( ap );
       
  2002     
       
  2003     GetCharL();
       
  2004 
       
  2005     // User name.
       
  2006     iTable.SetUsernameL( NextTokenL( KStopComma ) );
       
  2007     GetCharL();
       
  2008 
       
  2009     // Password.
       
  2010     iTable.SetPasswordL( NextTokenL( KStopComma ) );
       
  2011     GetCharL();
       
  2012 
       
  2013     // Read-only flag.
       
  2014     num = NextIntTokenL( KStopComma );
       
  2015     if ( num == 0 )
       
  2016         {
       
  2017         readOnly = EFalse;
       
  2018         }
       
  2019     else if ( num == 1 )
       
  2020         {
       
  2021         readOnly = ETrue;
       
  2022         }
       
  2023     else
       
  2024         {
       
  2025         // Expected "0" or "1".
       
  2026         User::Leave( KErrCorrupt );
       
  2027         }
       
  2028     GetCharL();
       
  2029 
       
  2030     // Factory item flag.
       
  2031     num = NextIntTokenL( KStopComma );
       
  2032     if ( num == 0 )
       
  2033         {
       
  2034   //      factoryItem = EFalse;
       
  2035         }
       
  2036     else if ( num == 1 )
       
  2037         {
       
  2038   //      factoryItem = ETrue;
       
  2039         }
       
  2040     else
       
  2041         {
       
  2042         // Expected "0" or "1".
       
  2043         User::Leave( KErrCorrupt );
       
  2044         }
       
  2045     GetCharL();
       
  2046 
       
  2047     // Context id.
       
  2048     iTable.SetContextIdL( NextHexTokenL( KStopCommaLfEof ) );
       
  2049     
       
  2050     GetCharL();
       
  2051     num = NextIntTokenL( KStopCommaLfEof );
       
  2052     if ( num == 0 )
       
  2053         {
       
  2054         hidden = EFalse;
       
  2055         }
       
  2056     else if ( num == 1 )
       
  2057         {
       
  2058         hidden = ETrue;
       
  2059         }
       
  2060     else
       
  2061         {
       
  2062         // Expected "0" or "1".
       
  2063         User::Leave( KErrCorrupt );
       
  2064         }
       
  2065 
       
  2066     iTable.SetHiddenL(hidden);
       
  2067     
       
  2068     // No GetCharL yet - PreferredUid is optional, so we need to investigate
       
  2069     // lookeahed character first.
       
  2070 
       
  2071     // Preferred flag (optional).
       
  2072     if ( iCurCh == KComma )
       
  2073         {
       
  2074         GetCharL();
       
  2075         num = NextIntTokenL( KStopLfEof );
       
  2076         if ( num == 0 )
       
  2077             {
       
  2078             preferred = EFalse;
       
  2079             }
       
  2080         else if ( num == 1 )
       
  2081             {
       
  2082             preferred = ETrue;
       
  2083             }
       
  2084         else
       
  2085             {
       
  2086             // Expected "0" or "1".
       
  2087             User::Leave( KErrCorrupt );
       
  2088             }
       
  2089         }
       
  2090     GetCharL();
       
  2091 
       
  2092     if ( preferred )
       
  2093         {
       
  2094         iTable.SetPreferredUidL( iTable.Uid() );
       
  2095         }
       
  2096     iTable.SetReadOnlyL( readOnly );
       
  2097     iTable.PutL();
       
  2098     // Now we have the root. The first entry added came with 0 Uid, so this
       
  2099     // value will never be used again.
       
  2100     iTable.Close();
       
  2101     CleanupStack::Pop( );             // close iTable
       
  2102     }
       
  2103 
       
  2104 // ---------------------------------------------------------
       
  2105 // CFavouritesSrvDb::FolderByNameL
       
  2106 // ---------------------------------------------------------
       
  2107 //
       
  2108 TInt CFavouritesSrvDb::FolderByNameL( const TDesC& aName )
       
  2109     {
       
  2110     TInt folderUid = KFavouritesRootUid;
       
  2111 
       
  2112     if ( aName.Length() )
       
  2113         {
       
  2114         // loop through iFolderNames and if bookmark name is found, return the index/UID where found
       
  2115         // else return root UID.
       
  2116         for (TUint x = 0; x < iFolderNames->Count(); ++x)
       
  2117             {
       
  2118             CFavouritesFolder folder = iFolderNames->At(x);
       
  2119             HBufC* fn = folder.Name();
       
  2120             TPtr ptr( fn->Des());
       
  2121             if (aName.Compare(ptr) == 0)
       
  2122                 {
       
  2123                 folderUid = folder.Uid();
       
  2124                 return folderUid;
       
  2125                 }
       
  2126              }
       
  2127         }
       
  2128 
       
  2129     return folderUid;
       
  2130     }
       
  2131 
       
  2132 
       
  2133 // ---------------------------------------------------------
       
  2134 // CFavouritesSrvDb::IAPIdByNameL
       
  2135 // ---------------------------------------------------------
       
  2136 //
       
  2137 TInt CFavouritesSrvDb::IAPIdByNameL( TDesC& aName, TInt& aIapId )
       
  2138 	{
       
  2139 	TUint pushCount = 0;
       
  2140 	TInt retVal = KErrNone;
       
  2141     TBool found = EFalse;
       
  2142     TUint32 iapId = 0;
       
  2143     TInt err = KErrNone;
       
  2144     
       
  2145     CCommsDatabase* db = CCommsDatabase::NewL();
       
  2146 	CleanupStack::PushL(db);
       
  2147 	pushCount++;
       
  2148 	CCommsDbTableView* tableView = db->OpenTableLC( TPtrC(WAP_ACCESS_POINT) );
       
  2149 
       
  2150 	pushCount++;
       
  2151 	retVal = tableView->GotoFirstRecord();
       
  2152 	
       
  2153 	while( retVal == KErrNone && !found )
       
  2154 		{
       
  2155 	    TBuf< KCommsDbSvrMaxFieldLength > iapName;
       
  2156 	    tableView->ReadTextL( TPtrC( COMMDB_NAME ), iapName );
       
  2157 	    if (iapName.CompareF( aName ) == 0 )
       
  2158 	    	{
       
  2159 	        TRAP( err, tableView->ReadUintL( TPtrC(COMMDB_ID), iapId ) );
       
  2160 	        found = ETrue;
       
  2161 	    	}
       
  2162 	    retVal = tableView->GotoNextRecord();
       
  2163 		}
       
  2164     	aIapId = iapId;
       
  2165 	
       
  2166 	CleanupStack::PopAndDestroy( pushCount );
       
  2167 	return retVal;
       
  2168 	}
       
  2169 //  End of File