diff -r 000000000000 -r ba25891c3a9e iaupdate/IAD/engine/controller/src/iaupdatexmlparser.cpp --- /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 +#include +#include +#include +#include + +#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; + } +