upnp/upnpstack/upnputils/src/upnpfileutils.cpp
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/upnputils/src/upnpfileutils.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,631 @@
+/** @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