/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:  A class that fetches resources via RFile.
*
*/

#include <e32base.h>
#include <e32std.h>
#include <f32file.h>

#include "FileHandler.h"
#include <leaktracker.h>
#include "Logger.h"

// -----------------------------------------------------------------------------
// CFileHandler::NewL
//
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CFileHandler* CFileHandler::NewL()
    {
    CFileHandler* self = new (ELeave) CFileHandler();
    
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();

    return self;
    }

        
// -----------------------------------------------------------------------------
// CFileHandler::CFileHandler
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CFileHandler::CFileHandler():
        iLeakTracker(CLeakTracker::EFileHandler)
    {
    }
        

// -----------------------------------------------------------------------------
// CFileHandler::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CFileHandler::ConstructL()
    {
    iIdle = CIdle::NewL(CActive::EPriorityIdle);
    }        


// -----------------------------------------------------------------------------
// CFileHandler::~CFileHandler
// Deconstructor.
// -----------------------------------------------------------------------------
//
CFileHandler::~CFileHandler()
    {
    delete iIdle;    
    delete iUrl;
    }


// -----------------------------------------------------------------------------
// CFileHandler::LoadUrl
// 
// Loads the given url -- asynchronously
// -----------------------------------------------------------------------------
//
void CFileHandler::LoadUrlL(const TDesC& aUrl, MLoadObserver& aObserver)
    {
    iUrl = aUrl.AllocL();
    iObserver = &aObserver;

    // To be consistent with other asynchronous UrlHandlers the buffer isn't 
    // processed until after the callstack unrolls.
    iIdle->Start(TCallBack(LoadCompleted, this));
    }


// -----------------------------------------------------------------------------
// CFileHandler::LoadCompleted
// 
// Loads and passes the buffer to the observer.
// -----------------------------------------------------------------------------
//
TInt CFileHandler::LoadCompleted(TAny* aPtr)
    {
    CFileHandler*  self = static_cast<CFileHandler*>(aPtr);    
    HBufC8*        buffer = NULL;

    TRAPD(err, buffer = self->LoadCompletedHelperL());
    
    // Pass the buffer to the observer.    
    self->iObserver->LoadCompleted(err, buffer, KNullDesC, KNullDesC);

    return EFalse;
    }


// -----------------------------------------------------------------------------
// CFileHandler::LoadCompletedHelperL
// 
// Loads and passes the buffer to the observer.
// -----------------------------------------------------------------------------
//
HBufC8* CFileHandler::LoadCompletedHelperL()
    {
    _LIT(KFileScheme, "file://");

    TInt           size;
    HBufC16*       correcttedPath = NULL;
    HBufC8*        buffer = NULL;
    TPtr8          bufferPtr(NULL, 0);

    // Extract the file path from the url.
    TPtr  path(iUrl->Des());

    if (iUrl->Find(KFileScheme) == 0)
        {
        path.Set((TUint16*) iUrl->Ptr() + KFileScheme().Length(), 
                iUrl->Length() - KFileScheme().Length(), iUrl->Length() - 
                KFileScheme().Length());

        correcttedPath = HBufC16::NewLC(path.Length());
        correcttedPath->Des() = path;
        path.Set(correcttedPath->Des());

        for (TInt i = 0; i < path.Length(); i++)
            {
            if (path[i] == '/')
                {
                path[i] = '\\';
                }
            }
        }

    // Otherwise leave as this isn't a file url.
    else
        {
        User::Leave(KErrNotSupported);
        }

    // Open the file.
    RFs    rfs;
    RFile  file;

    User::LeaveIfError(rfs.Connect());
    CleanupClosePushL(rfs);

    User::LeaveIfError(file.Open(rfs, path, EFileRead | EFileShareReadersOnly));
    CleanupClosePushL(file);

    // Read file
    User::LeaveIfError(file.Size(size));
    
    buffer = HBufC8::NewL(size);
    bufferPtr.Set(buffer->Des());

    file.Read(bufferPtr, size);
    
    // Clean up.
    CleanupStack::PopAndDestroy(/*file*/);
    CleanupStack::PopAndDestroy(/*rfs*/);
    CleanupStack::PopAndDestroy(correcttedPath);

    return buffer;
    }
