upnp/upnpstack/upnputils/src/upnpfileutils.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:12:20 +0200
changeset 0 f5a58ecadc66
permissions -rw-r--r--
Revision: 201003

/** @file
* Copyright (c) 2005-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:  File utils
 *
*/


// INCLUDES
#include <e32base.h>
#include <charconv.h>
#include <f32file.h>
#include <apgcli.h>
#include <apmrec.h>
#include <sysutil.h>
#define KLogFile _L("DLNAWebServer.txt")
#include "upnpcustomlog.h"
#include "upnpcons.h"
#include "upnpfileutils.h"
#include "upnpstring.h"
#include "uri8.h"
#include "in_sock.h"

// ================= MEMBER FUNCTIONS =======================
namespace UpnpFileUtil
    {
    // -----------------------------------------------------------------------------
    // UpnpFileUtil::ReadFileL
    // Reads the specified file and returns a pointer to HBufC8 holding the 
    // information.
    // -----------------------------------------------------------------------------
    //
    EXPORT_C HBufC8* ReadFileL(const TDesC16& aFilename)
        {
        LOGS1("UpnpFileUtil::ReadFileL - File: %S", &aFilename);

        RFs fs;
        HBufC8* buffer = NULL;
        TInt error = fs.Connect();
        if ( error == KErrNone )
            {
            CleanupClosePushL( fs );

            RFile file;
            error = file.Open(fs, aFilename, EFileRead|EFileShareAny );
            if ( error == KErrNone )
                {
                CleanupClosePushL( file );

                TInt fileSize;
                error = file.Size(fileSize);
                if ( error == KErrNone )
                    {
                    buffer = HBufC8::NewLC(fileSize);
                    buffer->Des().SetLength(0);

                    TPtr8 ptr = buffer->Des();
                    error = file.Read( ptr );
                    if ( error == KErrNone )
                        {
                        CleanupStack::Pop( buffer );
                        }
                    else
                        {
                        CleanupStack::PopAndDestroy( buffer );
                        buffer = NULL;
                        }
                    }

                // Close File
                CleanupStack::PopAndDestroy(); 
                }
            else
                {
                LOGS1("UpnpFileUtil::ReadFileL - RFile::Open() failed: %d", error);
                }

            // Close FS
            CleanupStack::PopAndDestroy(); 
            }
        else
            {
            LOGS1("UpnpFileUtil::ReadFileL - RFs::Connect() failed: %d", error );
            }

        // In case of an error, we leave as error would mean that the 
        // file system is down. Shouldn't fail in any other case.
        User::LeaveIfError( error );

        return buffer;
        }

    // -----------------------------------------------------------------------------
    // UpnpFileUtil::GetMimeTypeForFileL
    // - In emulator, checks the filename, and returns mimetype-string depending 
    //   on extension.
    // - In Target device, uses RApaLsSession (Application server) to find out 
    //   file's mime type.
    // -----------------------------------------------------------------------------
    //
    EXPORT_C HBufC8* GetMimeTypeForFileL(const TDesC16& aFilename)
        {
        LOGS1("UpnpFileUtil::GetMimeTypeForFileL - Getting mime type for file: %S", &aFilename);

        HBufC8* mimetype = NULL;

        // Added extra functionality, due to DLNA requirements for XML files mime type.
        // In mime type for xml files there should be explicitly defined used charset
        // and RApaLsSession service doesn't provide such a functionality.

        // Check extension, if its .xml - set mime type to text/xml and check used encoding
        _LIT8(KXmlUtf8, "text/xml; charset=\"utf-8\"");
        TParse parse;
        parse.Set( aFilename, NULL, NULL );
        TBufC16<KMaxName> ext( parse.Ext() );

        if ( ext.FindC( KXml16 ) == 0 && ext.Length() == KXml16().Length() )
            {
            // Extension says that's XML but we check content to be sure and get encoding
            

            mimetype = HBufC8::NewL( KXmlUtf8().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KXmlUtf8() );
            return mimetype;
            }

        // If it's not a XML file then use built-in service.

        RApaLsSession sess;
        TInt error = sess.Connect();
        // We have FS, File and RApaLs open
        if ( error == KErrNone )
            {
            CleanupClosePushL( sess );

            TUid id = TUid::Uid( 0 );

            TDataType type;

            error = sess.AppForDocument( aFilename, id, type );
            if( error == KErrNone && type != TDataType())
                {
                mimetype = HBufC8::NewL( type.Des8().Length() + UpnpString::KLineFeed().Length() );
                mimetype->Des().Append( type.Des8() );
                }
            else
                {
                error = KErrNotFound;
                LOGS1("UpnpFileUtil::GetMimeTypeForFileL - AppForDocument failed: %d", error );
                }

            CleanupStack::PopAndDestroy( &sess );
            }
        else
            {
            LOGS1("UpnpFileUtil::GetMimeTypeForFileL - RFile::Open failed: %d", error );
            }

        if( error != KErrNone)
            {
            mimetype = GetMimeTypeByExtensionL( aFilename );
            }

        LOGS("UpnpFileUtil::GetMimeTypeForFileL - MIME type resolved: " );
        LOGT( mimetype->Des() );

        return mimetype;
        }

    // -----------------------------------------------------------------------------
    // UpnpFileUtil::GetMimeTypeByExtensionL
    // - In emulator, checks the filename, and returns mimetype-string depending 
    //   on extension.
    // - In Target device, uses RApaLsSession (Application server) to find out 
    //   file's mime type.
    // -----------------------------------------------------------------------------
    //
    HBufC8* GetMimeTypeByExtensionL( const TDesC16& aFilename )
        {
        LOGS("UpnpFileUtil::GetMimeTypeForFileL - Starting search by file extension");

        HBufC8* mimetype = NULL;

        TParse parse;

        parse.Set( aFilename, NULL, NULL );

        TBufC16<KMaxName> ext( parse.Ext() );

        // FindC and length calculation is used,
        // beacause compareC does not work for undefined reason  

        if ( ext.FindC( KHtml16 ) == 0 && ext.Length() == KHtml16().Length() )
            {
            mimetype = HBufC8::NewLC( KHtml().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KHtml() );
            }
        else if ( ext.FindC( KXml16 ) == 0 && ext.Length() == KXml16().Length() )
            {
            mimetype = HBufC8::NewLC( KXml().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KXml() );
            }
        else if ( ext.FindC( KTxt16 ) == 0 && ext.Length() == KTxt16().Length() )
            {
            mimetype = HBufC8::NewLC( KTxt().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KTxt() );
            }
        else if ( ( ext.FindC( KJpg16 ) == 0 && ext.Length() == KJpg16().Length() ) ||
                ( ext.FindC( KJpeg16 ) == 0 && ext.Length() == KJpeg16().Length() ) )
            {
            mimetype = HBufC8::NewLC( KJpg().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KJpg() );
            }
        else if ( ext.FindC( KGif16 ) == 0 && ext.Length() == KGif16().Length() )
            {
            mimetype = HBufC8::NewLC( KGif().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KGif() );
            }
        else if ( ext.FindC( KPng16 ) == 0 && ext.Length() == KPng16().Length() )
            {
            mimetype = HBufC8::NewLC( KPng().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KPng() );
            }
        else if ( ( ext.FindC( KMpg16 ) == 0 && ext.Length() == KMpg16().Length() ) ||
                ( ext.FindC( KMpeg16 ) == 0 && ext.Length() == KMpeg16().Length() ) )
            {
            mimetype = HBufC8::NewLC( KMpeg().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KMpeg() );
            }
        else if ( ext.FindC( KAvi16 ) == 0 && ext.Length() == KAvi16().Length() )
            {
            mimetype =HBufC8::NewLC( KAvi().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KAvi() );
            }
        else if ( ext.FindC( KMp316 ) == 0 && ext.Length() == KMp316().Length() )
            {
            mimetype = HBufC8::NewLC( KMp3().Length() );
            mimetype->Des().Zero();
            mimetype->Des().Append( KMp3() );
            }

        // If type was not found, then set empty it here
        if ( !mimetype )
            {
            // We can't return mimetype=NULL;
            
            // Allocate one lenght mime.
            mimetype = HBufC8::NewLC( 1 );
            }
        CleanupStack::Pop( mimetype );

        return mimetype;
        }

    // -----------------------------------------------------------------------------
    // ExtractNumFromIP
    // -----------------------------------------------------------------------------
    //    
    TInt ExtractNumFromIP(TPtrC8 ippart)
        {

        TInt ipdef=KIPNumMin;
        TLex8 lexip = TLex8(ippart);
        TInt errorip = lexip.Val(ipdef);

        if (errorip == KErrNone)
        return ipdef;
        else
        return KErrNotFound;

        }
    // -----------------------------------------------------------------------------
    // Returns drive number
    // -----------------------------------------------------------------------------
    //
    TInt DriveNumberFromPath( const TDesC16& aPath, RFs& aFs )
        {
        TInt drive_num;
        TParse p;
        p.Set( aPath, NULL, NULL );
        TPtrC pointer = p.Drive();
        TLex lineParser( pointer.Ptr() );
        TChar ch = lineParser.Get();

        //sets the default drive or the found value
        if( aFs.CharToDrive( ch, drive_num )<KErrNone )
            {
            drive_num=EDriveC;
            }
        return drive_num;
        }

    // -----------------------------------------------------------------------------
    // ExtractUrlPathHost
    // -----------------------------------------------------------------------------
    //
    TBool ExtractUrlPathHost(const TDesC8& aUrl, TInt& aParseError )
        {
        TUriParser8 up;
        aParseError = up.Parse(aUrl);
        if ( aParseError != KErrNone )
            {
            return EFalse;
            }

        TPtrC8 hostt(up.Extract(EUriHost));
        TInt posOfFirstDot( 0 );
        TInt posOfSecondDot( 0 );
        TInt posOfThirdDot( 0 );

        posOfFirstDot = hostt.FindC( UpnpString::KDot8() );

        //position of the first dot in IP address must be from 1 to 3
        if( (posOfFirstDot < KErrNone ) || ((posOfFirstDot> 3 ) || (posOfFirstDot < 1)))
            {
            return EFalse;
            }
        else
            {
            TPtrC8 ip1;
            ip1.Set( hostt.Left( posOfFirstDot));

            TInt ip1def = ExtractNumFromIP(ip1);

            if ((ip1def> KIPNumMax) || (ip1def < KIPNumMin ))
                {
                return EFalse;
                }

            hostt.Set(hostt.Mid(posOfFirstDot + UpnpString::KDot8().Length()));
            posOfSecondDot = hostt.FindC( UpnpString::KDot8() );

            //position of the dot in IP address must from 1 to 3 starting from the position of former dot
            if( (posOfSecondDot < KErrNone) || ((posOfSecondDot> 3 ) || (posOfSecondDot < 1)))
                {
                return EFalse;
                }
            else
                {
                TPtrC8 ip2;
                ip2.Set( hostt.Left( posOfSecondDot));

                ip1def = ExtractNumFromIP(ip2);

                if ((ip1def == KErrNotFound) || (ip1def> KIPNumMax))
                    {
                    return EFalse;
                    }

                hostt.Set(hostt.Mid(posOfSecondDot + UpnpString::KDot8().Length()));
                posOfThirdDot = hostt.FindC( UpnpString::KDot8() );

                //position of the dot in IP address must from 1 to 3 starting from the position of former dot					
                if( (posOfThirdDot < KErrNone ) || ((posOfThirdDot> 3 ) || (posOfThirdDot < 1)))
                    {
                    return EFalse;
                    }
                else
                    {
                    TPtrC8 ip3;
                    ip3.Set( hostt.Left( posOfThirdDot));

                    ip1def = ExtractNumFromIP(ip3);

                    if ((ip1def == KErrNotFound) || (ip1def> KIPNumMax))
                        {
                        return EFalse;
                        }

                    TPtrC8 ip4;
                    ip4.Set(hostt.Mid(posOfThirdDot + UpnpString::KDot8().Length()));

                    //position of the dot in IP address must from 1 to 3 starting from the position of former dot							
                    if((ip4.Length() < 1) || (ip4.Length()> 3))
                        {
                        return EFalse;
                        }

                    ip1def = ExtractNumFromIP (ip4);

                    if ((ip1def == KErrNotFound) || (ip1def> KIPNumMax))
                        {
                        return EFalse;
                        }
                    else
                        {
                        return ETrue;
                        }

                    }
                }
            }
        }

    // -----------------------------------------------------------------------------
    // ExtractUrlPath
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TPtrC8 ExtractUrlPath(
        const TDesC8& aUrl, TPtrC8& aFilename, TPtrC8& aScheme, TInt& aParseError )
        {

        LOGS("CHttpFolderUrlMatch::ExtractUrlPath()");
        TUriParser8 up;
        aParseError = up.Parse(aUrl);
        if( aParseError != KErrNone)
            {
            return KNullDesC8();
            }
        TPtrC8 path(up.Extract(EUriPath));
        TPtrC8 scheme(up.Extract(EUriScheme));
        TPtrC8 port(up.Extract(EUriPort));
        TPtrC8 host(up.Extract(EUriHost));
        TInt position (0);
        TPtrC8 urlPath;

        if(up.IsPresent(EUriScheme))
            {

            if(scheme.Compare(UpnpHTTP::KSchemeHTTP8()) == 0)
                {
                aScheme.Set(scheme);

                //separator test
                position = aUrl.FindC(UpnpHTTP::KSchemeSeparator());
                if (position != KErrNotFound)
                    {
                    if ((up.IsPresent(EUriHost)) && (host != KNullDesC8()))
                        {
                        if( ExtractUrlPathHost(aUrl, aParseError ) )
                            {
                            TUint portdef(0);
                            TLex8 lex = TLex8(port);
                            TInt error = lex.Val(portdef, EDecimal);
                            if((up.IsPresent(EUriPort)) && (port != KNullDesC8()) && (error == KErrNone) )
                                {
                                urlPath.Set(path);
                                }
                            else
                                {
                                return KNullDesC8();
                                }
                            }
                        else
                            {
                            return KNullDesC8();
                            }
                        }
                    else
                        {
                        return KNullDesC8();
                        }
                    }
                else
                    {
                    return KNullDesC8();
                    }

                }
            else
                {
                return KNullDesC8();
                }
            }
        else
            {
            TInt posOfFirstSlashnohttp( 0 );
            posOfFirstSlashnohttp = path.FindC( UpnpString::KSlash() );

            if( (posOfFirstSlashnohttp < KErrNone ) || (posOfFirstSlashnohttp != 0))
                {
                return KNullDesC8();
                }
            else
                {
                urlPath.Set(aUrl);
                }
            }

        TInt posOfFirstSlash( 0 );
        TInt posOfLastSlash( 0 );
        posOfFirstSlash = urlPath.FindC( UpnpString::KSlash() );

        if( posOfFirstSlash < KErrNone )
            {
            return KNullDesC8();
            }
        else
            {
            TInt posOfTwoSlashes( 0 );
            posOfTwoSlashes = urlPath.FindC(UpnpString::KDoubleSlash());
            if((posOfTwoSlashes == KErrNone ) || (posOfTwoSlashes> KErrNone) )
                {
                return KNullDesC8();
                }
            posOfLastSlash = urlPath.LocateReverse( UpnpString::KSlash()[0] );
            if( posOfLastSlash == posOfFirstSlash )
                {
                aFilename.Set( urlPath.Mid( posOfLastSlash + UpnpString::KSlash().Length()) );
                return KNullDesC8();
                }
            else
                {
                aFilename.Set( urlPath.Mid( posOfLastSlash + UpnpString::KSlash().Length()) );
                urlPath.Set( urlPath.Mid( posOfFirstSlash + UpnpString::KSlash().Length() ) );
                urlPath.Set( urlPath.Left( posOfLastSlash - UpnpString::KSlash().Length() ) );
                return urlPath;

                }
            }
        }

    // -----------------------------------------------------------------------------
    // ExtractUrlPath
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TPtrC8 ExtractUrlPath(const TDesC8& aUrl, TInt& aParseError )
        {
        TPtrC8 fileName;
        TPtrC8 scheme;
        return ExtractUrlPath(aUrl, fileName, scheme, aParseError );
        }
    // -----------------------------------------------------------------------------
    // ExtractUrlPath
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TPtrC8 ExtractUrlPath(const TDesC8& aUrl, TPtrC8& aFilename, TInt& aParseError)
        {
        TPtrC8 scheme;
        return ExtractUrlPath(aUrl, aFilename, scheme, aParseError );
        }

    // -----------------------------------------------------------------------------
    // ConvertUrlToFolder
    // -----------------------------------------------------------------------------
    //
    EXPORT_C HBufC8* SwitchToBackSlashL(const TDesC8& aUrl)
        {
        TInt position( 0 );

        HBufC8* result = HBufC8::NewL(aUrl.Length() + aUrl.Length()/2);

        TPtr8 ptrResult(result->Des());
        ptrResult.Copy(aUrl);

        // replace / with '\\'
        while ( ( position = ptrResult.Locate( UpnpString::KSlash()[0] ) ) != KErrNotFound )
            {
            ptrResult.Replace( position, 1, UpnpString::KDoubleBackSlash() );
            }
        return result;

        }
    // -----------------------------------------------------------------------------
    // ConvertUrlToFolder
    // -----------------------------------------------------------------------------
    //
    EXPORT_C HBufC* SwitchToBackSlashL(const TDesC& aUrl)
        {
        TInt position( 0 );

        HBufC* result = HBufC::NewL(aUrl.Length() + aUrl.Length()/2);

        TPtr ptrResult(result->Des());
        ptrResult.Copy(aUrl);

        // replace / with '\\'
        while ( ( position = ptrResult.Locate( UpnpString::KSlash()[0] ) ) != KErrNotFound )
            {
            ptrResult.Replace( position, 1, UpnpString::KDoubleBackSlash16() );
            }
        return result;

        }
    // -----------------------------------------------------------------------------
    // Checks if the disk is short of the space requested
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TBool CheckDiskSpaceShortL( const TDesC16& aPath, TInt aSize, RFs& aFs )
        {
        TInt drive_num = UpnpFileUtil::DriveNumberFromPath( aPath, aFs );
        return SysUtil::DiskSpaceBelowCriticalLevelL ( &aFs, aSize, drive_num );
        }

    // -----------------------------------------------------------------------------
    // Checks if the disk is short of the space requested
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TBool CheckDiskSpaceShortL( TDriveNumber aDriveNumber, TInt aSize )
        {
        RFs fs;
        User::LeaveIfError( fs.Connect() );
        CleanupClosePushL( fs );
        TBool result = SysUtil::DiskSpaceBelowCriticalLevelL ( &fs, aSize, aDriveNumber );
        CleanupStack::PopAndDestroy( &fs );
        return result;
        }
     
    // -----------------------------------------------------------------------------
    // Parses uri
    // -----------------------------------------------------------------------------
    //
    EXPORT_C TInt ParseUri( const TDesC8& aUrl )
        {
        TUriParser8 up;
        return up.Parse( aUrl );
        }
    

    }

//  End of File