codhandler/codeng/src/CodUtil.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/codhandler/codeng/src/CodUtil.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,628 @@
+/*
+* Copyright (c) 2002 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: 
+*      Implementation of class CodUtil.   
+*      
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "CodUtil.h"
+#include "CodLogger.h"
+#include "CodPanic.h"
+#include <uri8.h>
+#include <utf.h>
+#include <CharConv.h>
+#include <f32file.h>
+#include <commdb.h>
+#include <ApSelect.h>
+#include <BodyPart.h>
+#include <AiwGenericParam.h>
+#include <caf/caf.h>
+
+// ================= CONSTANTS =======================
+
+/// Conversion buffer size.
+LOCAL_D const TInt KCodConversionBufferSize = 256;
+/// Blank IP address.
+_LIT( KCodBlankIpAdress, "0.0.0.0" );
+/// Zero width non-breaking space character.
+LOCAL_D const TUint16 KZeroWidthNbsp = 0xfeff;
+/// cid: scheme.
+_LIT8( KCodCidScheme, "cid" );
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ----------------------------------------------------------
+// CodUtil::CanOpenL()
+// ----------------------------------------------------------
+//
+EXPORT_C TBool CodUtil::CanOpenL( const TDesC& aFname )
+    {
+    CLOG(( ECodEng, 4, _L("-> CodUtil::CanOpenL <%S>"), &aFname ));
+    __ASSERT_DEBUG( aFname.Length(), CodPanic( ECodInternal ) );
+    TBool canOpen( EFalse );
+    using namespace ContentAccess;
+    CVirtualPath* vPath = CVirtualPath::NewL( aFname, KDefaultContentObject );
+    CleanupStack::PushL( vPath );
+    TInt err;
+    CData* data = NULL;
+    // 'No right' style errors leave, need to TRAP.
+    TRAP( err, data = CData::NewL( *vPath, EPeek, EContentShareReadOnly ) );
+    // Note, 'data' not pushed. No leaving calls below.
+    if ( !err &&
+                 (
+                 !data->EvaluateIntent( EPlay ) ||
+                 !data->EvaluateIntent( EView ) ||
+                 !data->EvaluateIntent( EExecute )
+                 )
+       )
+        {
+        canOpen = ETrue;
+        }
+    delete data;
+    CleanupStack::PopAndDestroy( vPath );
+    CLOG(( ECodEng, 4, _L("<- CodUtil::CanOpenL (%d)"), canOpen ));
+    return canOpen;
+    }
+
+// ----------------------------------------------------------
+// CodUtil::CanOpenL()
+// ----------------------------------------------------------
+//
+EXPORT_C TBool CodUtil::CanOpenL( RFile& aFile )
+    {
+    CLOG(( ECodEng, 4, _L("-> CodUtil::CanOpenL (RFile)") ));
+    TBool canOpen( EFalse );
+    using namespace ContentAccess;
+    TInt err;
+    CData* data = NULL;
+    // 'No right' style errors leave, need to TRAP.
+    TRAP( err, data = CData::NewL( aFile, KDefaultContentObject, EPeek ) );
+    // Note, 'data' not pushed. No leaving calls below.
+    if ( !err &&
+                 (
+                 !data->EvaluateIntent( EPlay ) ||
+                 !data->EvaluateIntent( EView ) ||
+                 !data->EvaluateIntent( EExecute )
+                 )
+       )
+        {
+        canOpen = ETrue;
+        }
+    delete data;
+    CLOG(( ECodEng, 4, _L("<- CodUtil::CanOpenL (%d)"), canOpen ));
+    return canOpen;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::GetIntParam()
+// ---------------------------------------------------------
+//
+EXPORT_C void CodUtil::GetIntParam
+        (
+        TInt& aParam,
+        TGenericParamId aSemanticId,
+        const CAiwGenericParamList& aParams
+        )
+    {
+    TInt index = 0;
+    const TAiwGenericParam* param =
+        aParams.FindFirst( index, aSemanticId, EVariantTypeTInt32 );
+    if ( param )
+        {
+        aParam = param->Value().AsTInt32();
+        CLOG(( ECodEng, 4, _L("CodUtil::GetIntParam id(%d) value(%d)"), \
+            aSemanticId, aParam ));
+        }
+    }
+
+// ---------------------------------------------------------
+// CodUtil::GetUint32Param()
+// ---------------------------------------------------------
+//
+EXPORT_C void CodUtil::GetUint32Param
+        (
+        TUint32& aParam,
+        TGenericParamId aSemanticId,
+        const CAiwGenericParamList& aParams
+        )
+    {
+    TInt index = 0;
+    const TAiwGenericParam* param =
+        aParams.FindFirst( index, aSemanticId, EVariantTypeTInt32 );
+    if ( param )
+        {
+        aParam = STATIC_CAST( TUint32, param->Value().AsTInt32() );
+        CLOG(( ECodEng, 4, _L("CodUtil::GetUint32Param id(%d) value(%d)"), \
+            aSemanticId, aParam ));
+        }
+    }
+
+// ---------------------------------------------------------
+// CodUtil::GetBoolParam()
+// ---------------------------------------------------------
+//
+EXPORT_C void CodUtil::GetBoolParam
+        (
+        TBool& aParam,
+        TGenericParamId aSemanticId,
+        const CAiwGenericParamList& aParams
+        )
+    {
+    TInt index = 0;
+    const TAiwGenericParam* param =
+        aParams.FindFirst( index, aSemanticId, EVariantTypeTInt32 );
+    if ( param )
+        {
+        aParam = STATIC_CAST( TBool, param->Value().AsTInt32() );
+        CLOG(( ECodEng, 4, _L("CodUtil::GetBoolParam id(%d) value(%d)"), \
+            aSemanticId, aParam ));
+        }
+    }
+
+// ---------------------------------------------------------
+// CodUtil::GetDesParamLC()
+// ---------------------------------------------------------
+//
+EXPORT_C void CodUtil::GetDesParamLC
+        (
+        TPtrC8& aParam,
+        TGenericParamId aSemanticId,
+        const CAiwGenericParamList& aParams
+        )
+    {
+    TInt index = 0;
+    HBufC8* buf = NULL;
+    // First check 8 bit variant.
+    const TAiwGenericParam* param =
+        aParams.FindFirst( index, aSemanticId, EVariantTypeDesC8 );
+    if ( param )
+        {
+        aParam.Set( param->Value().AsData() );
+        CLOG(( ECodEng, 4, \
+            _L8("CodUtil::GetDesParamLC 8-bit id(%d) value<%S>)"), \
+            aSemanticId, &aParam ));
+        }
+    else
+        {
+        // No 8-bit, check 16-bit.
+        param = aParams.FindFirst( index, aSemanticId, EVariantTypeDesC );
+        if ( param )
+            {
+            buf = ConvertL( param->Value().AsDes() );   // No leave until push.
+            aParam.Set( *buf );
+            CLOG(( ECodEng, 4, \
+                _L8("CodUtil::GetDesParamLC 16-bit id(%d) value<%S>)"), \
+                aSemanticId, &aParam ));
+            }
+        }
+    CleanupStack::PushL( buf ); // May be NULL.
+    }
+
+// ---------------------------------------------------------
+// CodUtil::GetDesParam()
+// ---------------------------------------------------------
+//
+EXPORT_C void CodUtil::GetDesParam
+        (
+        TPtrC& aParam,
+        TGenericParamId aSemanticId,
+        const CAiwGenericParamList& aParams
+        )
+    {
+    TInt index = 0;
+    const TAiwGenericParam* param =
+        aParams.FindFirst( index, aSemanticId, EVariantTypeDesC );
+    if ( param )
+        {
+        aParam.Set( param->Value().AsDes() );
+        CLOG(( ECodEng, 4, \
+            _L8("CodUtil::GetDesParam 16-bit id(%d) value<%S>)"), \
+            aSemanticId, &aParam ));
+        }
+    }
+
+// ---------------------------------------------------------
+// CodUtil::IsCidSchemeL()
+// ---------------------------------------------------------
+//
+TBool CodUtil::IsCidSchemeL( const TDesC8& aUrl )
+    {
+    TUriParser8 uri;
+    User::LeaveIfError( uri.Parse( aUrl ) );
+    return uri.Extract( EUriScheme ).Compare( KCodCidScheme ) == 0;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::PartByCidL()
+// ---------------------------------------------------------
+//
+CBodyPart* CodUtil::PartByCidL
+( const RPointerArray<CBodyPart>& aParts, const TDesC8& aUrl )
+    {
+    CBodyPart* part = NULL;
+    TUriParser8 uri;
+    User::LeaveIfError( uri.Parse( aUrl ) );
+    __ASSERT_DEBUG( uri.Extract( EUriScheme ).Compare( KCodCidScheme ) == 0,
+        CodPanic( ECodInternal ) ); // Expecting CID scheme!
+    CUri8* cUri = CUri8::NewLC( uri );
+    cUri->RemoveComponentL( EUriScheme );
+    TPtrC8 cid( cUri->Uri().UriDes() );
+    for ( TInt i = 0; i < aParts.Count(); i++ )
+        {
+        if ( !aParts[i]->ContentID().Compare( cid ) )
+            {
+            part = aParts[i];
+            break;
+            }
+        }
+    CleanupStack::PopAndDestroy( cUri );
+    return part;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::FileNameFromUrl()
+// ---------------------------------------------------------
+//
+TPtrC8 CodUtil::FileNameFromUrl( const TDesC8& aUrl )
+    {
+    TPtrC8 ptr;
+    TUriParser8 uri; 
+    if ( uri.Parse( aUrl ) == KErrNone )
+        {
+        ptr.Set( uri.Extract( EUriPath ) );
+        TInt slash = ptr.LocateReverse( TChar('/') );
+        if( slash >= 0 )
+            {
+            // We have a slash - keep only what is after it.
+            // Position 'slash + 1' can always be passed to Mid(); length is
+            // one greater than any resulting index. (If last character is
+            // a slash, we get an empty string as expected.)
+            ptr.Set( ptr.Mid( slash + 1 ) );
+            }
+        }
+    return ptr;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::AbsoluteUrlLC()
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC8* CodUtil::AbsoluteUrlLC
+( const TDesC8& aBase, const TDesC8& aUrl )
+    {
+    HBufC8* absUrl;
+    TUriParser8 url;
+    User::LeaveIfError( url.Parse( aUrl ) );
+    if ( url.IsPresent( EUriScheme ) )
+        {
+        // aUrl is already absolute, use it "as-is".
+        absUrl = aUrl.AllocLC();
+        }
+    else
+        {
+        // aUrl is relative, resolve it against the aBase.
+        TUriParser8 base;
+        User::LeaveIfError( base.Parse( aBase ) );
+        CUri8* resolved = CUri8::ResolveL( base, url );
+        CleanupStack::PushL( resolved );
+        absUrl = resolved->Uri().UriDes().AllocL();     // Not pushed here...
+        CleanupStack::PopAndDestroy( resolved );        // (no leaving here)
+        CleanupStack::PushL( absUrl );                  // ...only here.
+        }
+    return absUrl;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertToUcs2L()
+// ---------------------------------------------------------
+//
+HBufC16* CodUtil::ConvertToUcs2L
+( const TDesC8& aSrc, const TDesC8& aEncoding, RFs& aFs )
+    {
+    CLOG(( ECodEng | ECharset, 2, _L("-> CodUtil::ConvertToUcs2L") ));
+    CCnvCharacterSetConverter* conv = CCnvCharacterSetConverter::NewLC();
+    CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* charsets =
+        CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC( aFs );
+    TUint id = 0;
+    if ( aEncoding.Length() )
+        {
+        // Encoding is specified, use it.
+        CLOG(( ECodEng | ECharset, 4, _L8("charset name given <%S>"), \
+            &aEncoding ));
+        id = conv->ConvertStandardNameOfCharacterSetToIdentifierL
+            ( aEncoding, aFs );
+        CLOG(( ECodEng | ECharset, 4, _L("charset id 0x%x"), id ));
+        }
+    else 
+        {
+        // Autodetect.
+        TInt confidence = 0;
+        conv->AutoDetectCharacterSetL( confidence, id, *charsets, aSrc );
+        CLOG(( ECodEng | ECharset, 4, \
+            _L("detected charset id 0x%x confidence 0x%x"), id, confidence ));
+        if ( confidence == 0 || id == 0 )
+            {
+            // Failed to detect.
+            User::Leave( KErrNotSupported );
+            }
+        }
+
+    HBufC16* ucs2buffer = NULL;
+    TBool resultOnStack = EFalse;
+
+    // If id is 0 then we don't know what encoding the file is or it is
+    // already UCS2.
+    if ( id == 0 )
+        {
+        // If the source is too small we don't even have a unicode header or
+        // have a header with no data so just leave.
+        if ( aSrc.Length() < 3 )
+            {
+            User::Leave( KErrCorrupt );
+            }
+        
+        const TUint8* srcData = aSrc.Ptr();
+        if ( srcData[0] == 0xFF && srcData[1] == 0xFE )
+            {
+            // Little endian, good, just drop the unicode header and return
+            // the rest.
+            TPtrC result( (TUint16*)(srcData + 2) );
+            ucs2buffer = result.AllocL();
+            }
+        else if ( srcData[0] == 0xFE && srcData[1] == 0xFF )
+            {
+            // Big endian, we don't support it.
+            User::Leave( KErrNotSupported );
+            }
+        else
+            {
+            // No Unicode header, assume little endian-ness.
+            TPtrC result( (TUint16*)srcData );
+            ucs2buffer = result.AllocL();
+            }
+        }
+    else 
+        {
+        HBufC16* buffer = HBufC::NewLC( KCodConversionBufferSize );
+        TPtr16 ptr( buffer->Des() );
+        // Prepare conversion for the given charset ID.
+        conv->PrepareToConvertToOrFromL( id, *charsets, aFs );
+
+        TInt state = 0;
+        TInt remaining = conv->ConvertToUnicode( ptr, aSrc, state );
+        while ( remaining >= 0 )
+            {
+            if ( ucs2buffer == NULL )
+                {
+                ucs2buffer = HBufC::NewLC( ptr.Length() );
+                resultOnStack = ETrue;
+                }
+            else
+                {
+                __ASSERT_DEBUG( resultOnStack, CodPanic( ECodInternal ));
+                // This may change the address of ucs2buffer so we need to put
+                // it on the cleanup stack again!!
+                ucs2buffer = ucs2buffer->ReAllocL
+                    ( ucs2buffer->Length() + ptr.Length() );
+                CleanupStack::Pop();    // old ucs2buffer
+                CleanupStack::PushL( ucs2buffer );  // possibly new copy
+                }
+            TPtr16 ucs2ptr( ucs2buffer->Des() );
+            ucs2ptr.Append( ptr );
+            if ( remaining > 0 )
+                {
+                // Try to convert all remaining characters.
+                ptr.Zero();
+                remaining = conv->ConvertToUnicode
+                    ( ptr, aSrc.Right( remaining ), state );
+                }
+            else
+                {
+                break;
+                }
+            }
+
+        if ( resultOnStack )
+            {
+            CleanupStack::Pop();    // ucs2buffer
+            resultOnStack = EFalse;
+            }
+
+        CleanupStack::PopAndDestroy( buffer );
+        }
+
+    if ( resultOnStack )
+        {
+        CleanupStack::Pop();        // ucs2buffer
+        }
+
+    CleanupStack::PopAndDestroy( 2 );   // charsets, conv
+
+    // Check if first character is a Zero-width nbsp.
+    TPtrC16 ptr( ucs2buffer->Des() );
+    if ( ptr.Length() >= 1 && ptr[0] == KZeroWidthNbsp )
+        {
+        // First character is a Zero-width NBSP. This character is used as
+        // BOM in some encodings and should not be present at this point.
+        // But we are tolerant and remove it.
+        // (Not expecting big-endianness here.)
+        CLOG(( ECodEng | ECharset, 4, _L("dropping BOM"), id ));
+        HBufC16* temp = ucs2buffer;
+        CleanupStack::PushL( temp );
+        ucs2buffer = ptr.Mid( 1 ).AllocL();
+        CleanupStack::PopAndDestroy();  // temp
+        }
+
+    CLOG(( ECodEng | ECharset, 2, _L("<- CodUtil::ConvertToUcs2L") ));
+    return ucs2buffer;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertUcs2ToUtf8L()
+// ---------------------------------------------------------
+//
+HBufC8* CodUtil::ConvertUcs2ToUtf8L( const TDesC& aUcs2Src )
+    {
+    HBufC8* utf8buffer = NULL;
+    TBool resultOnStack = EFalse;
+    HBufC8* buffer = HBufC8::NewLC( KCodConversionBufferSize );
+    TPtr8 ptr( buffer->Des() );
+    TInt remaining =
+        CnvUtfConverter::ConvertFromUnicodeToUtf8( ptr, aUcs2Src );
+    while ( remaining >= 0 )
+        {
+        if ( utf8buffer == NULL )
+            {
+            utf8buffer = HBufC8::NewLC( ptr.Length() );
+            resultOnStack = ETrue;
+            }
+        else
+            {
+            __ASSERT_DEBUG( resultOnStack, CodPanic( ECodInternal ) );
+            // This may change the address of utf8buffer so we need to put it
+            // on the cleanup stack again!!
+            utf8buffer = utf8buffer->ReAllocL
+                ( utf8buffer->Length() + ptr.Length() );
+            CleanupStack::Pop();    // old utf8buffer
+            CleanupStack::PushL( utf8buffer );  // possibly new copy
+            }
+        TPtr8 utf8ptr( utf8buffer->Des() );
+        utf8ptr.Append( ptr );
+        if ( remaining > 0 )
+            {
+            // Try to convert all remaining characters.
+            ptr.Zero();
+            remaining = CnvUtfConverter::ConvertFromUnicodeToUtf8
+                ( ptr, aUcs2Src.Right( remaining ) );
+            }
+        else
+            {
+            break;
+            }
+        }
+    
+    if ( resultOnStack )
+        {
+        CleanupStack::Pop();    // utf8buffer
+        }
+    CleanupStack::PopAndDestroy( buffer );
+    return utf8buffer;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertLC()
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC8* CodUtil::ConvertLC( const TDesC& aDes )
+    {
+    HBufC8* buf = HBufC8::NewLC( aDes.Length() );
+    buf->Des().Copy( aDes );
+    return buf;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertLC()
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CodUtil::ConvertLC( const TDesC8& aDes )
+    {
+    HBufC* buf = HBufC::NewLC( aDes.Length() );
+    buf->Des().Copy( aDes );
+    return buf;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertL()
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC8* CodUtil::ConvertL( const TDesC& aDes )
+    {
+    HBufC8* buf = HBufC8::NewL( aDes.Length() );
+    buf->Des().Copy( aDes );
+    return buf;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ConvertL()
+// ---------------------------------------------------------
+//
+EXPORT_C HBufC* CodUtil::ConvertL( const TDesC8& aDes )
+    {
+    HBufC* buf = HBufC::NewL( aDes.Length() );
+    buf->Des().Copy( aDes );
+    return buf;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::ApCountL()
+// ---------------------------------------------------------
+//
+TUint32 CodUtil::ApCountL()
+    {
+    TUint32 count( 0 );
+    CCommsDatabase* cdb = CCommsDatabase::NewL( EDatabaseTypeIAP );
+    CleanupStack::PushL( cdb );
+    CApSelect* apSel = CApSelect::NewLC
+        (
+        *cdb,
+        KEApIspTypeAll,
+        EApBearerTypeAll,
+        KEApSortUidAscending
+        );
+    count = apSel->Count();
+    CleanupStack::PopAndDestroy( 2 );   // apSel, cdb
+    return count;
+    }
+
+// ---------------------------------------------------------
+// CodUtil::WapGatewayL()
+// ---------------------------------------------------------
+//
+HBufC8* CodUtil::WapGatewayL( TUint32 aIap )
+    {
+    HBufC8* gateway8 = NULL;
+
+    // Open a CommDB database server session.
+    // This has to be local and initialised every time or we get
+    // strange access denied leaves happening.
+    CCommsDatabase* cdb = CCommsDatabase::NewL( EDatabaseTypeIAP );
+    CleanupStack::PushL( cdb );
+
+    // Now access the commdb to see whether we have an associated
+    // WAP AP and if so determine the gateway that we are using.
+    TPtrC wapApTable( WAP_IP_BEARER );
+    TPtrC wapApIapCol( WAP_IAP );
+    CCommsDbTableView* view =
+        cdb->OpenViewMatchingUintLC( wapApTable, wapApIapCol, aIap );
+    TInt err = view->GotoFirstRecord();
+    if ( !err )
+        {
+        // There is a matching WAP AP table entry, does it have a
+        // valid gateway?
+        TPtrC wapApGwCol( WAP_GATEWAY_ADDRESS );
+        HBufC* gateway16 = view->ReadLongTextLC( wapApGwCol );
+        if ( gateway16->Compare( KCodBlankIpAdress ) )
+            {
+            // There is a valid WAP gateway.
+            gateway8 = ConvertL( *gateway16 );  // Not pushed, no leave below.
+            }
+        CleanupStack::PopAndDestroy( gateway16 );
+        }
+    CleanupStack::PopAndDestroy( 2 );   // view, cdb
+    return gateway8;
+    }