applicationmanagement/server/src/AMDeploymentComponentData.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 15:26:00 +0300
branchRCL_3
changeset 40 f2101057ffeb
parent 0 3ce708148e4d
child 57 6757f1e2efd2
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*
 * Copyright (c) 2000 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: Implementation of applicationmanagement components
 *
 */

#include "amdeploymentcomponentdata.h"

#include <bautils.h>
#include <sisdataprovider.h>

#include <DRMLicenseManager.h>
#include "debug.h"
#include <pathinfo.h>
#include <zipfilemember.h>

_LIT8( KSisxMimeType, "x-epoc/x-sisx-app" );
_LIT( KTempDir, "piptemp\\" );
_LIT8( KPipMimeType, "application/x-pip" );
_LIT8( KDrmMessageMimeType, "application/vnd.oma.drm.message" );
_LIT8( KDrmContentMimeType, "application/vnd.oma.drm.content" );
_LIT8( KSisMimeType, "application/vnd.symbian.install");

using namespace NApplicationManagement;

/**
 *  Data class to Data access
 */
CDeploymentComponentData::CDeploymentComponentData()
    {
    }

CDeploymentComponentData::CDeploymentComponentData(TType aType,
        const TDesC8 &aDataFile) :
    iDataFileName(aDataFile), iType(aType)
    {

    }

void CDeploymentComponentData::ConstructL(const TDesC8 &aData,
        const TDesC8 &aMime)
    {
    SetDataL(aData, aMime);
    }

CDeploymentComponentData &CDeploymentComponentData::operator=(
        const CDeploymentComponentData &aData )
    {
    if( &aData != this )
        {
        SetDataL( aData.Data(), aData.MimeType() );
        iType = aData.iType;
        iDataFileName = aData.iDataFileName;
        }
    return *this;
    }

void CDeploymentComponentData::ConstructLoadL(RReadStream &aStream)
    {
    TUint32 len(aStream.ReadUint32L() );
    aStream.ReadL(iDataFileName, len);

    len = aStream.ReadUint32L();
    aStream.ReadL(iMimeType, len);
    }

CDeploymentComponentData* CDeploymentComponentData::NewL(TType aType,
        const TDesC8 &aData, const TDesC8 &aMime, const TDesC8 &aDataFile)
    {
    CDeploymentComponentData *self = CDeploymentComponentData::NewLC(aType,
            aData, aMime, aDataFile);
    CleanupStack::Pop();
    return self;
    }

CDeploymentComponentData* CDeploymentComponentData::NewLC(TType aType,
        const TDesC8 &aData, const TDesC8 &aMime, const TDesC8 &aDataFile)
    {
    CDeploymentComponentData *self = new ( ELeave ) CDeploymentComponentData( aType, aDataFile);
    CleanupStack::PushL(self) ;
    self->ConstructL(aData, aMime);
    return self;
    }

CDeploymentComponentData* CDeploymentComponentData::LoadL(
        RReadStream &aBuffer)
    {
    CDeploymentComponentData *self =
            CDeploymentComponentData::LoadLC(aBuffer);
    CleanupStack::Pop();
    return self;
    }

CDeploymentComponentData* CDeploymentComponentData::LoadLC(
        RReadStream &aBuffer)
    {
    CDeploymentComponentData *self = new ( ELeave ) CDeploymentComponentData();
    CleanupStack::PushL(self) ;
    self->ConstructLoadL(aBuffer);
    return self;
    }

CDeploymentComponentData::~CDeploymentComponentData()
    {
    RDEBUG8_3("CDeploymentComponentData::~CDeploymentComponentData 0x%X - 0x%X", reinterpret_cast<TUint>(this),
            reinterpret_cast<TUint>(this)+sizeof( CDeploymentComponentData ) );

    delete iData;
    iData = NULL;
    }

TInt CDeploymentComponentData::DataLengthL() const
    {
    TInt ret( 0);
    if (iData == NULL)
        {
        if (iDataFileName.Length() > 0)
            {
            RFs fs;
            User::LeaveIfError(fs.Connect() );
            CleanupClosePushL(fs); // 1
            TEntry entry;
            TFileName fileName;
            fileName.Copy(iDataFileName);
            User::LeaveIfError(fs.Entry(fileName, entry) );
            ret = entry.iSize;
            CleanupStack::PopAndDestroy( &fs);
            }
        }
    else
        {
        ret = iData->Length();
        }
    return ret;
    }

const TDesC8 &CDeploymentComponentData::Data() const
    {
    if (iData == NULL)
        {
        TRAPD( err, LoadDataL() )
        ;
        if (err != KErrNone)
            {
            return KNullDesC8();
            }
        }
    if (iData != NULL)
        {
        return *iData;
        }
    else
        {
        return KNullDesC8();
        }
    }

void CDeploymentComponentData::LoadDataL() const
    {

    if (iDataFileName.Length() > 0)
        {
        RFs fs;
        User::LeaveIfError(fs.Connect() );
        CleanupClosePushL(fs); // 1
        RFile file;
        TFileName fileName;
        fileName.Copy(iDataFileName);
        TInt err(file.Open(fs, fileName, EFileRead) );
        if (err == KErrNone)
            {
            CleanupClosePushL(file); // 2
            TInt fsize;
            User::LeaveIfError(file.Size(fsize) );
            iData = HBufC8::NewL(fsize);
            TPtr8 ptr(iData->Des() );
            User::LeaveIfError(file.Read(ptr) );
            CleanupStack::PopAndDestroy( &file);
            }
        else
            {
            RDEBUG_3( "ERROR Leaving CDeploymentComponentData::Data - SEVERE Could not open data file '%S': %d!",
                    &fileName, err );
            User::Leave(KErrNotFound) ;
            }
        CleanupStack::PopAndDestroy( &fs);
        }
    else
        {
        RDEBUG( "ERROR Leaving CDeploymentComponentData::LoadDataL() - No file to load!" );
        User::Leave(KErrNotFound) ;
        }
    }

TUid CDeploymentComponentData::SetDataL(const TDesC8& aMimeType)
    {
    RDEBUG8_2("CDeploymentComponentData::SetDataL() aMimeType: (%S)", &aMimeType);

    TUid ret(TUid::Null());
    iMimeType = aMimeType.Left(KMaxMimeLength);

    if (IsSISInstallFile(aMimeType) )
        {
        RFs fs;
        User::LeaveIfError(fs.Connect() );
        CleanupClosePushL(fs);
        ret = ResolveUidL(fs);
        CleanupStack::PopAndDestroy( &fs);
        }
    RDEBUG8_2("CDeploymentComponentData::SetDataL() UID: (0x%x)", ret.iUid);
    return ret;
    }

TUid CDeploymentComponentData::SetDataL(const TFileName &aData,
        const TDesC8& aMimeType)
    {
    RDEBUG_2("CDeploymentComponentData::SetDataL() TFileName: (%S)", &aData);

    TUid ret(TUid::Null());
    iMimeType = aMimeType.Left(KMaxMimeLength) ;
    RFs fs;
    User::LeaveIfError(fs.Connect() );
    CleanupClosePushL(fs);
    CFileMan *fm = CFileMan::NewL(fs);
    CleanupStack::PushL(fm);
    TFileName fn;
    fn.Copy(iDataFileName);
    User::LeaveIfError(fm->Copy(aData, fn) );

    if (IsSISInstallFile(aMimeType) )
        {
        ret = ResolveUidL(fs);
        }

    CleanupStack::PopAndDestroy(fm);
    CleanupStack::PopAndDestroy( &fs);
    RDEBUG_2("CDeploymentComponentData::SetDataL() (%d)", ret.iUid);

    return ret;
    }

TUid CDeploymentComponentData::SetDataL(const TDesC8 &aData,
        const TDesC8 &aMimeType)
    {
    TUid ret(TUid::Null());
    if (iData)
        {
        delete iData;
        iData = NULL;
        }
    iData = aData.AllocL();
    ret = SetDataL(aMimeType);
    return ret;
    }

TBool CDeploymentComponentData::IsSISInstallFile(const TDesC8 &aMimeType)
    {
    TBool isSIS(EFalse);

    if (aMimeType == KSisxMimeType || aMimeType == KPipMimeType || aMimeType
            == KDrmMessageMimeType || aMimeType == KDrmContentMimeType || aMimeType == KSisMimeType)
        {
        isSIS = ETrue;
        }

    return isSIS;
    }

TUid CDeploymentComponentData::ResolveUidL(RFs& aFs)
    {
    RDEBUG("CDeploymentComponentData::ResolveUidL()");

    TUid ret(TUid::Null() );
    HBufC* buf = HBufC::NewLC(KMaxFileName);
    TPtr16 ptr = buf->Des();
    ptr.Copy(iDataFileName);

    // if PIP/DRM package, we need to use license manager to extract the sis file
    if (iMimeType == KPipMimeType || iMimeType == KDrmMessageMimeType
            || iMimeType == KDrmContentMimeType)
        {
        RDEBUG8_2("	-> mime: %S", &iMimeType );

        RFile originalFile;
        RFile decryptedFile;
        TFileName decryptedTempFileName;

        RDEBUG_2("	-> opening original file: %S", &ptr );
        // leave if can not open the original file
        User::LeaveIfError(originalFile.Open(aFs, ptr, EFileWrite) );
        RDEBUG("	-> done");

        // First construct the temp path
        User::LeaveIfError(aFs.PrivatePath(decryptedTempFileName) );
        // set drive letter into the path
        decryptedTempFileName.Insert( 0, TParsePtrC( PathInfo::PhoneMemoryRootPath() ).Drive() );
        // append "piptemp\\"	
        decryptedTempFileName.Append(KTempDir);
        // create the folder
        aFs.MkDir(decryptedTempFileName);

        // Use license manager to extract files from the pip package
        CDRMLicenseManager* licenseMgr = CDRMLicenseManager::NewL();
        CleanupStack::PushL(licenseMgr);
        // decryp from the original file into the temp file   
        RDEBUG_2("	-> extracting SIS file into: %S", &decryptedTempFileName);
        User::LeaveIfError(licenseMgr->ExtractSISFileL(originalFile,
                decryptedTempFileName) );
        RDEBUG("	-> done");

        // Get the sis file name 
        decryptedTempFileName.Append( *(licenseMgr->GetSISMemberL()->Name() ));
        // open temporary handle to it.
        RDEBUG_2("	-> opening decrypted file: %S", &decryptedTempFileName );
        User::LeaveIfError(decryptedFile.Open(aFs, decryptedTempFileName,
                EFileShareAny) );
        RDEBUG("	-> done");
        // parse the uid from the file
        ret = ParseUidFromSisFileL(decryptedFile);

        // no use anymore for the decrypted file
        decryptedFile.Close();
        // delete the temp file
        TInt err = aFs.Delete(decryptedTempFileName);
        if (err != KErrNone)
            {
            RDEBUG_2("**** ERROR, unable to delete temporary file: %S", &decryptedTempFileName );
            }

        CleanupStack::PopAndDestroy(licenseMgr);
        decryptedFile.Close();
        originalFile.Close();
        }
    else
        if (iMimeType == KSisxMimeType || iMimeType == KSisMimeType )
            {
            RDEBUG("	-> mime: x-epoc/x-sisx-app");
            RFile originalFile;
            RDEBUG_2("	-> opening file: %S", &ptr );
            User::LeaveIfError(originalFile.Open(aFs, ptr, EFileRead) );
            RDEBUG("	-> opened ok");
            ret = ParseUidFromSisFileL(originalFile);
            originalFile.Close();
            }

        else
            {
            RDEBUG8_2( "**** ERROR - CDeploymentComponentData::ResolveUidL( ) - cannot get uid from mime type: %S", &iMimeType );
            }

    CleanupStack::PopAndDestroy(buf);
    return ret;
    }

void CDeploymentComponentData::SerializedFormL(RWriteStream &aBuffer) const
    {
    aBuffer.WriteUint32L(iDataFileName.Length() );
    aBuffer.WriteL(iDataFileName);

    aBuffer.WriteUint32L(iMimeType.Length() );
    aBuffer.WriteL(iMimeType);

    }

void CDeploymentComponentData::DestroyL(RFs &aFs) const
    {
    TFileName fn;
    fn.Copy(iDataFileName);
    aFs.Delete(fn) ;
    }

const TDesC8 &CDeploymentComponentData::DataFileName() const
    {
    return iDataFileName;
    }

void CDeploymentComponentData::PersistL(RFs &aFs)
    {
    if (iData)
        {
        RFile file;
        TFileName aFile;
        aFile.Copy(iDataFileName) ;
        RDEBUG_3( "CDeploymentComponentData::PersistL() - Saving '%S', dataLenght %d", &aFile, (iData ? iData->Length() : 0) );
        User::LeaveIfError(file.Replace(aFs, aFile, EFileWrite) );
        CleanupClosePushL(file) ;

        file.Write( *iData) ;
        file.Flush();
        delete iData;
        iData = NULL;
        CleanupStack::PopAndDestroy( &file) ; // file
        }
    else
        {
        RDEBUG( "CDeploymentComponentData::PersistL() - Already persisted" );
        }
    RDEBUG( "CDeploymentComponentData::PersistL() - Done" );
    }

TInt CDeploymentComponentData::SerializedFormLength() const
    {
    return iDataFileName.Length() + (2 * 4) + iMimeType.Length();
    }

void CDeploymentComponentData::SetDataFileNameL(const TDesC8 &aNewFileName)
    {
    if (aNewFileName.Length() > 0)
        {
        RFs fs;
        User::LeaveIfError(fs.Connect() );
        CleanupClosePushL(fs);
        TFileName newfile;
        newfile.Copy(aNewFileName);
        TFileName oldfile;
        oldfile.Copy(iDataFileName);
        User::LeaveIfError(BaflUtils::RenameFile(fs, oldfile, newfile) );
        CleanupStack::PopAndDestroy( &fs);
        iDataFileName = aNewFileName;
        }
    else
        {
        RDEBUG( "CDeploymentComponentData::SetDataFileNameL - ERROR Cannot set empty filename!" );
        User::Leave(KErrArgument);
        }
    }
void CDeploymentComponentData::SetMimeTypeL(const TDesC8 &aMimeType)
{
	iMimeType = aMimeType.Left(KMaxMimeLength) ;
}
void CDeploymentComponentData::ResetData(RFs &aFs)
    {
    TRAP_IGNORE(DestroyL( aFs ));
    iDataFileName = KNullDesC8();
    delete iData;
    iData = NULL;
    }

TUid CDeploymentComponentData::ParseUidFromSisFileL(RFile& aHandleToFile)
    {
    RDEBUG("CDeploymentComponentData::ParseUidFromSisFileL");

    TUid appUid;
    TInt uidLen = sizeof(TInt32);
    TInt seekLen = sizeof(TInt32) + sizeof(TInt32);
    User::LeaveIfError(aHandleToFile.Seek(ESeekStart, seekLen));
    TPckg<TInt32> uid1(appUid.iUid);
    User::LeaveIfError(aHandleToFile.Read(uid1, uidLen));

    if (uid1.Length() != uidLen)
        {
        RDEBUG("**** ERROR - uid length inconsistency - underflow");
        User::Leave(KErrUnderflow);
        }

    RDEBUG_2("	-> returning SIS UID: %d", appUid.iUid );
    return appUid;
    }

//  End of File