--- /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;
+ }