csxhelp/HelpEngine/src/CSXHRuntimeIndexing.cpp
branchRCL_3
changeset 18 cbffe13eac63
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/csxhelp/HelpEngine/src/CSXHRuntimeIndexing.cpp	Wed Sep 01 12:30:56 2010 +0100
@@ -0,0 +1,360 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  CCSXHRuntimeIndexing class definition
+*
+*/
+
+
+#include <pathinfo.h>
+#include <utf.h>
+#include <bautils.h>
+#include <eikenv.h>
+#include <aknnotedialog.h> // for CAknNoteDialog
+#include <aknnotewrappers.h>
+#include <SenXmlUtils.h>
+#include <SenXmlConstants.h>
+
+#include "CSXHRuntimeIndexing.h"
+#include "CSXHHtmlTOC1.h"
+#include "csxhconstants.h"
+
+// buffer length of Drive information in index file
+//
+const TInt KMaxDriveInfo = 100;
+
+CCSXHRuntimeIndexing::CCSXHRuntimeIndexing()
+    {
+    iCoeEnv = CCoeEnv::Static();
+    }
+    
+CCSXHRuntimeIndexing::~CCSXHRuntimeIndexing()
+    {
+    delete iFullDirName;
+    iFile.Close();
+    }
+    
+CCSXHRuntimeIndexing* CCSXHRuntimeIndexing::NewL()
+    {
+    CCSXHRuntimeIndexing* self = new ( ELeave ) CCSXHRuntimeIndexing();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+    
+void CCSXHRuntimeIndexing::ConstructL()
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    iFullDirName = HBufC::NewL( KMaxFileName );
+
+    TFileName fullDirName;
+    
+    GetPrivatePath( fullDirName );
+    if ( !BaflUtils::PathExists( fileSession, fullDirName ) )
+        {
+        fileSession.CreatePrivatePath( EDriveC );
+        }
+    
+    TInt len = fullDirName.Length();
+    TDriveList dirList; 
+    if( fileSession.DriveList( dirList ) == KErrNone )
+        {
+        TDriveInfo info;
+        TInt driveListLen = dirList.Length();
+        
+        for ( TInt i = 0; i < driveListLen; i++ )
+            {
+            // make separate folder for C/D/E/... drive
+            // e.g. C:\\private\\10005234\\C\\
+
+            TInt err = fileSession.Drive( info, i );
+            if ( err == KErrNone &&
+                    info.iType != EMediaNotPresent )
+                {
+                TChar driveChar;
+                RFs::DriveToChar( i, driveChar );
+                fullDirName.Append( driveChar );
+                fullDirName.Append( KFwdSlash );
+                fileSession.MkDir( fullDirName );
+                fullDirName.Delete( len, 3 );
+                }
+            }
+        
+        }
+    }
+    
+TBool CCSXHRuntimeIndexing::IndexFileExistsL()
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    TBuf<KMaxFileName> fileName;
+    GetPrivatePath( fileName );
+    fileName.Append( _L("Z\\") );
+    AppendLocaleL( fileName );
+    fileName.Append( KMasterMetaFile );
+    
+    // Now the dirName is C:\\private\\<app-uid>\\Z\\index.xml
+    // check if it exists, if yes, runtime indexing must be launched before
+    // since Z based Help content must be delivered with cell phone
+    //
+    return BaflUtils::FileExists( fileSession, fileName );
+    
+    }
+    
+void CCSXHRuntimeIndexing::BeginIndexFileL( const TChar& aDrive )
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    TPtr des = iFullDirName->Des();
+    iDriveLetter = aDrive;
+    des.Zero();
+    GetPrivatePath( des );
+    des.Append( aDrive );
+    des.Append( KFwdSlash );
+    AppendLocaleL( des );
+    if ( !BaflUtils::PathExists( fileSession, des ) )
+        {
+        // generate C:\\private\\<help-uid>\\<aDrive>\\ folder
+        //
+        fileSession.MkDir( des );
+        }
+    
+    // for temporary usage, once it's finished successfully,
+    // rename to index.xml. otherwise, the old index file still exists.
+    //
+    des.Append( KMasterMetaTmpFile );
+    iFile.Replace( fileSession, des, EFileWrite );
+    
+    HBufC8* driveInfo = HBufC8::NewLC( KMaxDriveInfo );
+    TPtr8 ptr = driveInfo->Des();
+    ptr.Append( KIndexXMLVesion );
+    ptr.Append( _L( "<collections drive=\"" ) );
+    ptr.Append( aDrive);
+    ptr.Append( _L( "\">\r\n" ) );
+    iFile.Write( *driveInfo );
+    CleanupStack::PopAndDestroy( driveInfo );
+    }
+    
+void CCSXHRuntimeIndexing::FinishAndCloseIndexFileL()
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    iFile.Write( KIndexCollectEnd );
+    iFile.Close();  
+      
+    TTime time;
+    // Replace the index.xml with temporary file, in case it fails, will have no impact
+    // the original index.xml, it's a backup solution
+    //
+    TBuf<KMaxFileName> newName;
+    TInt err = KErrNone;
+    newName.Copy( *iFullDirName );
+    TInt pos = newName.LocateReverse( TChar('\\') );
+    newName.Delete( pos + 1, newName.Length() - pos - 1 ); // remove the temp name
+    newName.Append( KMasterMetaFile ); //  and append index.xml
+    
+    err = fileSession.Replace( *iFullDirName, newName );
+    
+    if ( err == KErrNone )
+        {
+        // set the modified date of master index.xml
+        // to be the same with related help content folder
+        // e.g. C:\\resource\\xhtml\\01\\ modified time is 2009.3.1
+        // C:\\private\\10005234\\C\\01\\index.xml will be 2009.3.1
+        // this will make sure once help content folder changed, index.xml can be
+        // determined to change.
+        TBuf<KMaxFileName> helpDir;
+        helpDir.Append( iDriveLetter );  
+        helpDir.Append( KInstallPath );
+        // append locale information
+        AppendLocaleL( helpDir );
+        
+        fileSession.Modified( helpDir, time );
+        err = fileSession.SetModified( newName, time );
+        
+        }
+    
+    }
+      
+void CCSXHRuntimeIndexing::RuntimeGenerateIndexL( const CCSXHHtmlTOC1& aToc1, const TDesC& aFeature )
+    {
+    // Form into an entry, like
+    // <collection FeatureID="-1" id="0x10005951" navtitle="Bluetooth"></collection>
+    HBufC8* appName = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aToc1.GetName() );
+    CleanupStack::PushL(appName);
+    TRAPD( err, SenXmlUtils::LeaveOnXmlEscapesL( *appName ) );
+    TInt length = KMaxIndexEntryExclude;
+    TBuf8<KMaxUidLength> buffUid;
+    
+    buffUid.Append( KHexPrefix );
+    buffUid.AppendNumFixedWidth( aToc1.GetAppUid().iUid, EHex, 8 );
+    length += appName->Length();
+    length += aFeature.Length();
+    HBufC8* entry = HBufC8::NewLC( length );
+    TPtr8 des = entry->Des();
+    // Append entry tag
+    des.Append( KIndexXMLEntryBegin );
+    // Append feature id attribute "FeatureID"
+    des.Append( KAppFeatureIDTag );
+    des.Append( KIndexQuoteBegin );
+    // Append feature id
+    des.Append( aFeature );
+    des.Append( KIndexQuoteEnd );
+    // Append app id attribute "id"
+    des.Append( KMasterCollection_idTag );
+    des.Append( KIndexQuoteBegin );
+    // Append app id
+    des.Append( buffUid );
+    des.Append( KIndexQuoteEnd );
+    // Append app priority 
+    des.Append( KPriorityTag );
+    des.Append( KIndexQuoteBegin );
+    des.AppendNum(aToc1.Priority());
+    des.Append( KIndexQuoteEnd );
+    // Append app name attribut "navtitle"
+    des.Append( KTOC2NameTag );
+    des.Append( KIndexQuoteBegin );
+    if ( err == KErrSenInvalidCharacters )
+        {
+        // special handling to the XML-Escaped char
+        HBufC8* newElement = SenXmlUtils::EncodeHttpCharactersLC( *appName );
+        des.Append( *newElement );
+        CleanupStack::PopAndDestroy( newElement );
+        }
+    else
+        {
+        des.Append( *appName );
+        }
+
+    des.Append( KIndexXMLEntryEnd );
+    iFile.Write( *entry );
+    
+    CleanupStack::PopAndDestroy( entry );
+    CleanupStack::PopAndDestroy( appName );
+    
+    }
+    
+void CCSXHRuntimeIndexing::GetPrivatePath( TDes& aName )
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    TBuf<KMaxFileName> privatePath;
+    TChar drive;
+    RFs::DriveToChar( EDriveC, drive );
+    
+    fileSession.PrivatePath( privatePath );
+    aName.Append( drive );
+    aName.Append( TChar(':') ); 
+    aName.Append( privatePath );
+    }
+
+void CCSXHRuntimeIndexing::AppendLocaleL( TDes& aDir )
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    RArray<TLanguage> langs;
+    BaflUtils::GetDowngradePathL( fileSession, User::Language(), langs );
+    TInt len = aDir.Length();
+    
+    if ( len > 0 )
+        {
+        TLanguage lang = langs[0];
+        if(lang < 10)
+            {
+            aDir.AppendNumFixedWidth( lang, EDecimal,2 );
+            }
+        else
+            {
+            aDir.AppendNum( lang );
+            }
+        }
+    else
+        {
+        // rarely case, if no current language, use English
+        aDir.Append( _L("01") );
+        }
+        
+    aDir.Append( KFwdSlash );
+    langs.Reset();
+    }
+    
+void CCSXHRuntimeIndexing::DeleteIndexFileL( const TChar& aDrive )
+    {
+    RFs& fileSession = iCoeEnv->FsSession();
+    TBuf<KMaxFileName> des;
+    GetPrivatePath( des );
+    des.Append( aDrive );
+    des.Append( KFwdSlash );
+    AppendLocaleL( des );
+    // C:\\private\\<app-uid>\\<drive letter>\\<language-id>\\index.xml
+    des.Append( KMasterMetaFile );
+    
+    if ( BaflUtils::FileExists( fileSession, des ) )
+        {
+        fileSession.Delete( des );
+        }
+
+    }
+    
+TInt CCSXHRuntimeIndexing::CheckDirChangeL( const TChar& aDrive )
+    {
+    RFs& fsSession = iCoeEnv->FsSession();
+    
+    // Begin to search help content folder to see if there are date modify
+    // meanwhile, compare to the related folder in private directory
+    TFileName dirName;
+    dirName.Append( aDrive );
+    dirName.Append( KInstallPath );
+
+    // Begin to append locale, note this will append current locale,
+    // thru which, app can determine if it's caused by user changed locales
+    AppendLocaleL( dirName );
+
+    TTime dirModified(0);
+    TTime fileModified(0);
+    
+    if ( BaflUtils::PathExists( fsSession, dirName ) )
+        {
+        // here is modified time of help content folder
+        fsSession.Modified( dirName, dirModified );
+        }
+    else
+        {
+        // fast return, no need to go on checking
+        return KNoDirExist;
+        }
+
+    TFileName filename;
+    GetPrivatePath( filename );
+    filename.Append( aDrive );
+    filename.Append( KFwdSlash );
+    AppendLocaleL( filename );
+    filename.Append( KMasterMetaFile );
+                
+    if ( BaflUtils::FileExists( fsSession, filename ) )
+        {
+        // here is modified time of index.xml
+        //
+        fsSession.Modified( filename, fileModified );
+        }
+    else
+        {
+        return KNoIndexExist;
+        }
+                    
+    if ( fileModified != dirModified )
+        {
+        // folder changed, return it
+        TInt ret = KErrNotFound;
+        RFs::CharToDrive( aDrive, ret );
+        return ret;
+        }
+    
+    return KNoChange;
+    }