iaupdate/IAD/engine/controller/src/iaupdatexmlparser.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/iaupdate/IAD/engine/controller/src/iaupdatexmlparser.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,351 @@
+/*
+* Copyright (c) 2009 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:   ?Description
+*
+*/
+
+
+
+#include <xml/parser.h>
+#include <stringpool.h>
+#include <utf.h>
+#include <e32cmn.h>
+#include <bautils.h>
+
+#include "iaupdatexmlparser.h"
+#include "iaupdatexmlsubparser.h"
+#include "iaupdatedebug.h"
+
+
+// The text type to parse
+_LIT8( KXmlType, "text/xml" );
+
+
+EXPORT_C CIAUpdateXmlParser* CIAUpdateXmlParser::NewL( 
+    CIAUpdateXmlSubParser* aSubParser )
+    {
+    CIAUpdateXmlParser* self =
+        CIAUpdateXmlParser::NewLC( aSubParser );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+EXPORT_C CIAUpdateXmlParser* CIAUpdateXmlParser::NewLC( 
+    CIAUpdateXmlSubParser* aSubParser )
+    {
+    CIAUpdateXmlParser* self =
+        new( ELeave ) CIAUpdateXmlParser( aSubParser );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;    
+    }
+
+
+EXPORT_C CIAUpdateXmlParser::CIAUpdateXmlParser( 
+    CIAUpdateXmlSubParser* aSubParser )
+: CBase(),
+  iSubParser( aSubParser )
+    {
+    
+    }
+    
+    
+EXPORT_C void CIAUpdateXmlParser::ConstructL()
+    {
+    if ( !iSubParser )
+        {
+        User::Leave( KErrNotFound );
+        }
+    iParser = Xml::CParser::NewL( KXmlType, *iSubParser );
+    }
+
+
+EXPORT_C CIAUpdateXmlParser::~CIAUpdateXmlParser()
+    {
+    delete iParser;
+    delete iSubParser;
+    }
+
+
+EXPORT_C void CIAUpdateXmlParser::ParseFileL( 
+    const TDesC& aFilePath )    
+    {
+    HBufC8* data( ReadFileL( aFilePath ) );
+    CleanupStack::PushL( data );
+    
+    ParseL( *data );
+
+    CleanupStack::PopAndDestroy( data );
+    }
+
+
+EXPORT_C void CIAUpdateXmlParser::ParsePrivateFileL( 
+    const TDesC& aFileName )
+    {
+    RFs fsSession;	
+    User::LeaveIfError( fsSession.Connect() );
+    CleanupClosePushL( fsSession );
+
+    // This will set the correct drive and private path 
+    // for the file server session.    
+    SetPrivateDriveL( fsSession, aFileName );
+
+	TFileName configFilePath;    
+    User::LeaveIfError( fsSession.SessionPath( configFilePath ) );
+    configFilePath.Append( aFileName );
+    
+    CleanupStack::PopAndDestroy( &fsSession );    
+
+    ParseFileL( configFilePath );    
+    }
+
+
+EXPORT_C void CIAUpdateXmlParser::ParseL( const TDesC8& aData )
+    {
+    // Use parent class functions to handle the parsing
+    Parser().ParseBeginL();
+    Parser().ParseL( aData );
+    Parser().ParseEndL();
+    }
+
+
+EXPORT_C void CIAUpdateXmlParser::ParseL( const TDesC& aData )
+    {
+    HBufC8* utf8( ConvertUnicodeToUtf8L( aData ) );
+    CleanupStack::PushL( utf8 );
+
+    ParseL( *utf8 );
+
+    CleanupStack::PopAndDestroy( utf8 );
+    }    
+
+
+EXPORT_C CIAUpdateXmlSubParser& CIAUpdateXmlParser::SubParser()
+    {
+    return *iSubParser;
+    }
+
+
+Xml::CParser& CIAUpdateXmlParser::Parser()
+    {
+    return *iParser;
+    }
+
+    
+HBufC8* CIAUpdateXmlParser::ReadFileL( const TDesC& aFilePath )
+    {
+    RFs fs;
+    
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    
+    RFile file;
+    User::LeaveIfError( file.Open( fs,
+                                   aFilePath,
+                                   EFileRead ) );
+    CleanupClosePushL( file );
+    TInt size;
+    User::LeaveIfError( file.Size( size ) );
+    HBufC8* buffer = HBufC8::NewLC( size );
+    TPtr8 ptr( buffer->Des() );
+    User::LeaveIfError( file.Read( ptr, size ) );
+    CleanupStack::Pop( buffer );
+    CleanupStack::PopAndDestroy( &file );    
+
+    CleanupStack::PopAndDestroy( &fs );
+
+    return buffer;
+    }    
+
+
+HBufC8* CIAUpdateXmlParser::ConvertUnicodeToUtf8L( 
+    const TDesC16& aUnicodeText )
+    {
+    const TInt KConvertBufferSize( 64 );
+
+    // Place converted data here, 
+    // initial size double the conversion buffer.
+    HBufC8* convertedData = HBufC8::NewL( KConvertBufferSize * 2 );
+    CleanupStack::PushL( convertedData );
+    TPtr8 destination( convertedData->Des() );
+
+    // Create a small output buffer
+    TBuf8< KConvertBufferSize > outputBuffer;
+    
+    // Create a buffer for the unconverted text - initialised with the 
+    // input text
+    TPtrC16 remainderOfUnicodeText( aUnicodeText );
+
+    for ( ;; ) // conversion loop
+        {
+        // Start conversion. When the output buffer is full, return the 
+        // number of characters that were not converted
+        const TInt returnValue(
+            CnvUtfConverter::ConvertFromUnicodeToUtf8( 
+                outputBuffer, 
+                remainderOfUnicodeText ) );
+
+        // check to see that the descriptor isn’t corrupt 
+        // - leave if it is
+        if ( returnValue == CnvUtfConverter::EErrorIllFormedInput )
+            {            
+            User::Leave( KErrCorrupt );
+            }
+        else if ( returnValue < 0 )
+            {            
+            // future-proof against "TError" expanding
+            User::Leave( KErrGeneral );
+            }
+
+        // Do something here to store the contents of the output buffer.
+        if ( destination.Length() + outputBuffer.Length() >= 
+             destination.MaxLength() )
+            {
+            HBufC8* newBuffer = convertedData->ReAllocL(
+                ( destination.MaxLength() + outputBuffer.Length() ) * 2 );
+            
+            CleanupStack::Pop( convertedData );
+            convertedData = newBuffer;
+            CleanupStack::PushL( convertedData );
+            destination.Set( convertedData->Des() );
+            }
+
+        destination.Append( outputBuffer );
+        outputBuffer.Zero();
+
+        // Finish conversion if there are no unconverted characters 
+        // in the remainder buffer
+        if ( returnValue == 0 ) 
+            {            
+            break; 
+            }
+
+        // Remove the converted source text from the remainder buffer.
+        // The remainder buffer is then fed back into loop
+        remainderOfUnicodeText.Set( 
+            remainderOfUnicodeText.Right( returnValue ) );
+        }
+        
+    CleanupStack::Pop( convertedData );
+    return convertedData;
+    }
+
+
+void CIAUpdateXmlParser::SetPrivateDriveL( 
+    RFs& aFs,
+    const TDesC& aFileName ) const
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateXmlParser::SetPrivateDriveL() begin: %S", 
+                     &aFileName);
+    
+    // This will set the correct drive and private path 
+    // for the file server session.    
+
+    // First try to find the file from the private directory
+    // of the drive where the process exists.
+    RProcess process;
+
+    // Set the session private path according to 
+    // the process file name drive.
+    TInt driveNum( 
+        SetSessionPrivatePathL( aFs, process.FileName() ) );
+
+    // Get the session path that was set above.
+    IAUPDATE_TRACE_1("[IAUPDATE] Find file: %d", driveNum);
+    TFileName sessionPath;
+    User::LeaveIfError( aFs.SessionPath( sessionPath ) );
+    IAUPDATE_TRACE_1("[IAUPDATE] Session path: %S", &sessionPath);
+
+    // Use the file finder to check if the file actually exists 
+    // in the given drive path. If it does not, the file finder 
+    // will automatically check from other drives. So, here we 
+    // should always find the file if any exists.
+    TFindFile finder( aFs );
+    User::LeaveIfError( finder.FindByDir( aFileName, sessionPath ) );
+
+    // The drive may have changed if the file was not found from
+    // the first suggested drive. So, be sure to have the correct
+    // private path.
+    driveNum = SetSessionPrivatePathL( aFs, finder.File() );
+
+    // Use the drive info to check if the drive is ROM drive.
+    // We prefer non ROM drives. But, accept ROM if nothing else is
+    // available.
+    IAUPDATE_TRACE_1("[IAUPDATE] Check ROM info: %d", driveNum);
+    TDriveInfo info;
+    User::LeaveIfError( aFs.Drive( info, driveNum ) );
+    TBool isRomDrive( info.iDriveAtt & KDriveAttRom );
+    if ( !isRomDrive )
+        {
+        // The current file is not in ROM drive so use that.
+        IAUPDATE_TRACE("[IAUPDATE] First file search done. Non ROM found.");
+        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateXmlParser::SetPrivateDriveL() end");
+        return;
+        }
+
+    // Because previous finding was ROM file, try to find a non ROM file.
+    IAUPDATE_TRACE("[IAUPDATE] Try to find non ROM file.");
+    TInt findErrorCode( finder.Find() );
+    if ( findErrorCode == KErrNotFound )
+        {
+        // Because no new file is found, use the current settings.
+        IAUPDATE_TRACE("[IAUPDATE] Second search done. No file found.");
+        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateXmlParser::SetPrivateDriveL() end");
+        return;
+        }
+    User::LeaveIfError( findErrorCode );
+
+    IAUPDATE_TRACE("[IAUPDATE] New file found. Use that.");
+    // Update the session path for the correct file.
+    SetSessionPrivatePathL( aFs, finder.File() );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateXmlParser::SetPrivateDriveL() end");
+    }
+
+
+TInt CIAUpdateXmlParser::SetSessionPrivatePathL( 
+    RFs& aFs,
+    const TDesC& aPath ) const
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateXmlParser::SetSessionPrivateL() begin: %S", 
+                     &aPath);
+                     
+    // Use the parser to get the drive information from the path.
+    TParsePtrC parser( aPath );
+
+    if ( !parser.DrivePresent() )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] ERROR: Missing drive info.");
+        User::Leave( KErrArgument );
+        }
+
+    // Drive check was passed above.
+    // So, drive information is safe to use.
+    const TDesC& drive( parser.Drive() );
+    const TChar driveChar( drive[ 0 ] );
+    TInt driveNum( EDriveA );
+    User::LeaveIfError( 
+        RFs::CharToDrive( driveChar, driveNum ) );
+    IAUPDATE_TRACE_2("[IAUPDATE] Drive: %S, %d", &drive, driveNum );
+
+    // Set the file drive to be file session private path drive.
+    User::LeaveIfError( aFs.SetSessionToPrivate( driveNum ) );
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateXmlParser::SetSessionPrivateL() end: %d",
+                     driveNum);
+
+    return driveNum;
+    }
+