diff -r 000000000000 -r dd21522fd290 codhandler/codeng/src/CodUtil.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +// ================= 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& 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* 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; + }