--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omaprovisioning/pnputil/src/PnpUtilImpl.cpp Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,1066 @@
+/*
+* Copyright (c) 2004-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: PnpUtil implementation
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32math.h>
+#include <mmtsy_names.h>
+#include <asymmetric.h> // For RInteger
+#include <3des.h> // For C3DES
+#include <centralrepository.h> // link against centralrepository.lib
+
+#include "PnpUtilImpl.h"
+#include "PnpUtilLogger.h"
+#include "PnpUtilPrivateCRKeys.h" // Central repository keys
+
+
+// CONSTANTS
+
+const TInt KMaxModulusLength = 300;
+const TInt KMaxPublicExponentLength = 10;
+
+_LIT8(K3DesKey, "111111111111111111111111");
+
+// Default token validity time
+const TInt KTokenValidityTime = 600;
+const TInt KTokenLength = 4;
+// C3DESEncryptor and C3DESDecryptor require the buffer to be more than 4 characters
+// (8 characters seems to be enough)
+const TInt KTokenLengthDuringStorage = 8;
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CPnpUtilImpl::ConstructL()
+ {
+ LOGSTRING( "Enter to CPnpUtilImpl::ConstructL()" );
+
+ User::LeaveIfError( iServer.Connect() );
+ LOGSTRING( "CPnpUtilImpl::ConstructL() 2" );
+ User::LeaveIfError( iServer.LoadPhoneModule( KMmTsyModuleName ) );
+ LOGSTRING( "CPnpUtilImpl::ConstructL() 3" );
+ User::LeaveIfError( iPhone.Open( iServer, KMmTsyPhoneName ) );
+ LOGSTRING( "CPnpUtilImpl::ConstructL() 4" );
+ User::LeaveIfError( iPhone.Initialise() );
+
+ LOGSTRING( "CPnpUtilImpl::ConstructL() 5" );
+
+ iRepository = CRepository::NewL( KCRUidPnpUtil );
+
+#ifndef __WINS__ // calling C3DESEncryptor::NewL crashes emulator
+ iEncryptor = C3DESEncryptor::NewL( K3DesKey );
+ iDecryptor = C3DESDecryptor::NewL( K3DesKey );
+#endif
+
+ LOGSTRING( "Exit from CPnpUtilImpl::ConstructL()" );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::NewLC
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CPnpUtilImpl* CPnpUtilImpl::NewLC()
+ {
+ LOGSTRING("CPnpUtilImpl::NewLC");
+ CPnpUtilImpl* self = new (ELeave) CPnpUtilImpl();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::CPnpUtilImpl
+// -----------------------------------------------------------------------------
+//
+CPnpUtilImpl::CPnpUtilImpl()
+ {
+ LOGSTRING("CPnpUtilImpl()");
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::~CPnpUtilImpl
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CPnpUtilImpl::~CPnpUtilImpl()
+ {
+ LOGSTRING( "~CPnpUtilImpl" );
+ delete iRepository;
+ iPhone.Close();
+ iServer.Close();
+#ifndef __WINS__
+ delete iEncryptor;
+ delete iDecryptor;
+#endif
+ LOGSTRING( "~CPnpUtilImpl - done" );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::Version
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::Version( TDes& aVersion )
+ {
+ LOGSTRING( "CPnpUtilImpl::Version" );
+
+ // There is now a separate dll for HDC so there is no need to
+ // read the version string from a database, we may use
+ // a hard-coded value instead.
+
+ _LIT( KTempVersion, "NPnP-MSS60-1.01" );
+
+ // Max length is KMaxVersionStringLength
+ if( KTempVersion().Length() > aVersion.MaxLength() )
+ {
+ return KErrArgument;
+ }
+ aVersion.Copy( KTempVersion );
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::CreateNewToken
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::CreateNewToken(TUint32 aTimeout, TInt& aToken)
+ {
+ LOGSTRING("CPnpUtilImpl::CreateNewToken");
+ TInt value(0);
+ // Get current time
+ TTime t;
+ t.HomeTime();
+ TInt64 time = t.Int64();
+
+ // Create timeout
+ if( aTimeout > 9999 )
+ {
+ LOGSTRING("too long timeout - KErrArgument");
+ return KErrArgument;
+ }
+
+ // Deadline = currenttime + (atimeout * 1000000)
+ TInt64 deadline = time + TInt64((TInt)aTimeout) * TInt64(1000000);
+ TBuf<21> num; // 20 is max length for 64 bit integer (radix 10)
+ num.AppendNum(deadline);
+ LOGSTRING("WriteDeadline");
+ LOGTEXT(num);
+
+ // Store deadline
+ TInt result = iRepository->Set( KPnPUtilDeadline, num );
+ if( result != KErrNone )
+ {
+ LOGSTRING2("Storing deadline failed: %i", result);
+ return result;
+ }
+
+ value = Math::Rand(time);
+ value %= (9999 - 1001);
+ value += 1001;
+
+ LOGSTRING2( "New Token: %i", value );
+
+ // KTokenLength is too small for the buffer length because C3DESEncryptor/C3DESDecryptor
+ // cannot handle small buffers
+ TBuf8<KTokenLengthDuringStorage> tokenBuf;
+ tokenBuf.AppendNum( value );
+ tokenBuf.AppendNum( 1234 );
+ // Encrypt
+#ifndef __WINS__
+ iEncryptor->Transform( tokenBuf );
+#endif
+
+ // Save token
+ result = iRepository->Set( KPnPUtilToken, tokenBuf );
+
+ aToken = value;
+
+ LOGSTRING("CPnpUtilImpl::CreateNewToken - done");
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::GetTokenValidityTime
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::GetTokenValidityTime()
+ {
+ LOGSTRING("CPnpUtilImpl::GetTokenValidityTime");
+ return KTokenValidityTime;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::GetTokenValue
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::GetTokenValue(TInt& aToken)
+ {
+ LOGSTRING("Enter CPnpUtilImpl::GetTokenValue");
+
+ // Check deadline
+ TBuf<21> num;
+ LOGSTRING("ReadDeadline");
+
+ TInt result = iRepository->Get( KPnPUtilDeadline, num );
+ if( result != KErrNone )
+ {
+ return KErrCorrupt;
+ }
+
+ LOGTEXT(num);
+ TLex l(num);
+ TInt64 deadline(0);
+ if( l.Val(deadline)!= KErrNone )
+ {
+ return KErrCorrupt;
+ }
+ // Check validity time
+ TTime t;
+ t.HomeTime();
+ if( t > deadline )
+ {
+ TTimeIntervalSeconds seconds(0);
+ t.SecondsFrom( deadline, seconds );
+ LOGSTRING2( "Token validity expired: %is ago", seconds.Int() );
+ return KErrTimedOut;
+ }
+
+ LOGSTRING("Token not expired");
+
+ // Get token
+ // KTokenLength is too small for the buffer length because C3DESEncryptor/C3DESDecryptor
+ // cannot handle small buffers
+ TBuf8<KTokenLengthDuringStorage> tokenBuf;
+ result = iRepository->Get( KPnPUtilToken, tokenBuf );
+
+ if( result != KErrNone )
+ {
+ LOGSTRING2( "Error %i when trying to read token value", result );
+ return result;
+ }
+
+ LOGSTRING("Tokenbuf:");
+ LOGTEXT( tokenBuf );
+
+#ifndef __WINS__
+ iDecryptor->Transform( tokenBuf );
+#endif
+
+ TInt token(0);
+ TLex8 parser( tokenBuf.Left( KTokenLength ) );
+ parser.Val( token );
+
+ if( token < 1 || token > 9999)
+ {
+ return KErrCorrupt;
+ }
+
+ LOGSTRING("Token OK");
+ LOGSTRING2("Token: %i", token);
+
+ aToken = token;
+
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::CreateNewNonceL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::CreateNewNonceL( const TUint /*aTimeOut*/, TDes8& aNonce )
+ {
+ LOGSTRING("CPnpUtilImpl::CreateNewNonceL");
+ if( aNonce.MaxLength() < KNonceLength )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ TBuf8<KNonceLength> buffer;
+
+ TTime time;
+ time.HomeTime();
+ TInt64 seed = time.Int64();
+ for( TInt i(0); i < KNonceLength; i++ )
+ {
+ TChar character( RandomCharacter( seed ) );
+ buffer.Append( character );
+ }
+
+ LOGSTRING("New Nonce:");
+ LOGTEXT( buffer );
+ aNonce.Copy( buffer );
+
+ // Encrypt
+#ifndef __WINS__
+ iEncryptor->Transform( buffer );
+#endif
+
+ // Save the nonce
+ User::LeaveIfError( iRepository->Set( KPnPUtilNonce, buffer ) );
+
+ LOGSTRING("CPnpUtilImpl::CreateNewNonceL - done");
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::GetNonceValidityTimeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::GetNonceValidityTimeL()
+ {
+ // Not used
+ User::Leave( KErrNotSupported );
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::GetNonceL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::GetNonceL( TDes8& aNonce )
+ {
+ LOGSTRING("CPnpUtilImpl::GetNonceL");
+
+ if( aNonce.MaxLength() < KNonceLength )
+ {
+ User::Leave( KErrArgument );
+ }
+ TBuf8<KNonceLength> buffer;
+
+ User::LeaveIfError( iRepository->Get( KPnPUtilNonce, buffer) );
+
+ // Decrypt
+#ifndef __WINS__
+ if( buffer.Length() > 0 )
+ {
+ LOGTEXT( buffer );
+ iDecryptor->Transform( buffer );
+ }
+#endif
+
+ LOGSTRING("Nonce:");
+ LOGTEXT( buffer );
+ aNonce.Copy( buffer );
+
+ LOGSTRING("CPnpUtilImpl::GetNonceL - done");
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::RandomCharacter
+// -----------------------------------------------------------------------------
+//
+TUint CPnpUtilImpl::RandomCharacter( TInt64& aSeed )
+ {
+ // Create random number value for token
+ TInt value = Math::Rand( aSeed );
+ if( value < 0 )
+ {
+ value = -value;
+ }
+ value %= 61; // [0,61]
+ value += 48; // [48,109]
+ // split the range to ranges [48,57],[65,90] and [97,122]
+ // that is: the ascii codes for numbers from 0 to 9,
+ // capital alphabets from A to Z and alphabets from a to z
+ if( value > 57 )
+ {
+ value += 8; // [65,90]
+ if( value > 90 )
+ {
+ value += 6; // [97,122]
+ }
+ }
+ return value;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::GetKeyInfoL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::GetKeyInfoL( TDes8& aKeyInfo )
+ {
+ LOGSTRING("CPnpUtilImpl::GetKeyInfoL");
+ if( aKeyInfo.MaxLength() < KMaxKeyInfoLength )
+ {
+ User::Leave( KErrArgument );
+ }
+ // read keyinfo from cenrep
+ TBuf<KMaxKeyInfoLength> buffer;
+ User::LeaveIfError( iRepository->Get( KPnPUtilKeyInfo, buffer) );
+ aKeyInfo.Copy( buffer );
+ LOGSTRING("CPnpUtilImpl::GetKeyInfoL - done");
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::VerifySignatureL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CPnpUtilImpl::VerifySignatureL(
+ const TDesC8& aDigestValue, const TDesC8& aSignatureValue,
+ const TDesC8& aData, const TDesC8& aNonce )
+ {
+ LOGSTRING( "CPnpUtilImpl::VerifySignatureL" );
+ LOGTEXT( aDigestValue );
+
+ HBufC8* sendersDigest = DecodeBase64LC( aDigestValue );
+ LOGSTRING( "senders digest:" );
+ LogAsASCIIHexL( *sendersDigest );
+
+ HBufC8* sendersSignature = DecodeBase64LC( aSignatureValue );
+ LOGSTRING( "senders signature:" );
+ LogAsASCIIHexL( *sendersSignature );
+
+
+ // Read Modulus and PublicExponent from Cenrep
+ LOGSTRING( "Read Modulus and PublicExponent from Cenrep" );
+ TBuf<KMaxModulusLength> bufferMod;
+ TBuf<KMaxPublicExponentLength> bufferExp;
+ User::LeaveIfError( iRepository->Get( KPnPUtilModulus, bufferMod) );
+ User::LeaveIfError( iRepository->Get( KPnPUtilPublicExponent, bufferExp) );
+
+ TBuf8<KMaxModulusLength> bufferMod8;
+ TBuf8<KMaxPublicExponentLength> bufferExp8;
+ bufferMod8.Copy( bufferMod );
+ bufferExp8.Copy( bufferExp );
+
+ LOGSTRING( "Pack modulus and exponent" );
+ // Look for (lousy/faulty) documentation for RInteger from the 2.1 SDK
+ HBufC8* modulusBuf = PackLC( bufferMod8 );
+ HBufC8* exponentBuf = PackLC( bufferExp8 );
+
+ RInteger modulus = RInteger::NewL( *modulusBuf );
+ RInteger exponent = RInteger::NewL( *exponentBuf );
+
+ CRSAPublicKey* publicKey = CRSAPublicKey::NewLC( modulus, exponent );
+ CRSAPKCS1v15Verifier* rsaVerifier = CRSAPKCS1v15Verifier::NewLC( *publicKey );
+
+ RInteger rsaSignatureInteger = RInteger::NewL( *sendersSignature );
+ CRSASignature* signature = CRSASignature::NewLC( rsaSignatureInteger );
+
+ // Verify the digest against the signature
+ TBool verified = rsaVerifier->VerifyL( *sendersDigest, *signature );
+
+ // These are not needed anymore, destroy
+ CleanupStack::PopAndDestroy( signature );
+ CleanupStack::PopAndDestroy( rsaVerifier );
+ CleanupStack::PopAndDestroy( publicKey );
+ CleanupStack::PopAndDestroy( exponentBuf );
+ CleanupStack::PopAndDestroy( modulusBuf );
+ CleanupStack::PopAndDestroy( sendersSignature );
+
+
+ if( verified ) // Signature was verified
+ {
+ LOGSTRING( "Signature Verified" );
+
+ // ...Yep, verify also digest
+ verified = VerifyDigestL( *sendersDigest, aData, aNonce );
+ if( verified )
+ {
+ LOGSTRING( "Digest Verified" );
+ }
+ else
+ {
+ LOGSTRING( "Digest NOT verified" );
+ }
+ }
+ else
+ {
+ // ...Nope, do not check the digest, verify already failed anyways
+ LOGSTRING( "Signature NOT verified" );
+ }
+
+ CleanupStack::PopAndDestroy( sendersDigest );
+
+ LOGSTRING( "CPnpUtilImpl::VerifySignatureL - done" );
+ return verified;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::VerifyDigestL
+// -----------------------------------------------------------------------------
+//
+TBool CPnpUtilImpl::VerifyDigestL(
+ const TDesC8& aSendersDigest, const TDesC8& aData, const TDesC8& aNonce )
+ {
+ LOGSTRING( "VerifyDigestL" );
+ LOGTEXT( aData );
+ LOGTEXT( aNonce );
+
+ CSHA1* sha1 = CSHA1::NewL();
+ CleanupStack::PushL( sha1 );
+
+ HBufC8* dataToBeHashed = HBufC8::NewLC( aData.Length() + aNonce.Length() + 1 );
+ TPtr8 dataToBeHashedPtr = dataToBeHashed->Des();
+ _LIT8( KColon, ":" );
+ dataToBeHashedPtr.Append( aNonce );
+ dataToBeHashedPtr.Append( KColon );
+ dataToBeHashedPtr.Append( aData );
+
+ LOGSTRING( "nonce:data" );
+ LogAsASCIIHexL( *dataToBeHashed );
+
+ TPtrC8 hash = sha1->Final( *dataToBeHashed );
+ LOGSTRING( "computed hash:" );
+ LOGTEXT( hash );
+ LogAsASCIIHexL( hash );
+
+ LOGSTRING( "senders hash:" );
+ LogAsASCIIHexL( aSendersDigest );
+ TBool verified( EFalse );
+ if( hash.Compare( aSendersDigest ) == 0 )
+ {
+ verified = ETrue;
+ }
+ CleanupStack::PopAndDestroy( dataToBeHashed );
+ CleanupStack::PopAndDestroy( sha1 );
+ return verified;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::LogAsASCIIHexL
+// -----------------------------------------------------------------------------
+//
+void CPnpUtilImpl::LogAsASCIIHexL( const TDesC8& aDesc )
+ {
+ HBufC8* asciiHexBuf = HBufC8::NewLC( aDesc.Length() * 2 );
+ TPtr8 asciiHexBufPtr = asciiHexBuf->Des();
+ TBuf8<2> asciiHex;
+ // binary to ascii (hex)
+ _LIT8( KAsciiHexFormat, "%02X" );
+ TUint8 val;
+ for( TInt i=0; i<aDesc.Length(); i++ )
+ {
+ val = aDesc[i];
+ asciiHex.Format( KAsciiHexFormat, val );
+ asciiHexBufPtr.Append( asciiHex );
+ }
+
+#ifdef _DEBUG
+ for( TInt j(0); j < asciiHexBufPtr.Length(); j += 128 )
+ {
+ TPtrC8 logText = asciiHexBufPtr.Mid(j); // print in 128 byte chunks
+ LOGTEXT( logText );
+ }
+#endif
+
+ CleanupStack::PopAndDestroy( asciiHexBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::DecodeBase64LC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CPnpUtilImpl::DecodeBase64LC( const TDesC8& aBase64EncodedDesc )
+ {
+ TInt lenght = aBase64EncodedDesc.Length();
+ HBufC8* decoded = HBufC8::NewLC( lenght );
+ TPtr8 decodedPtr = decoded->Des();
+
+ if( lenght % 4 != 0 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ for( TInt i(0); i < lenght - 1; i++ )
+ {
+ // The last two character may be zero characters ('=')
+ if( aBase64EncodedDesc[i] == '=' )
+ {
+ if( i < lenght - 2 || aBase64EncodedDesc[i+1] != '=' )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ return decoded;
+ }
+ else if( aBase64EncodedDesc[i+1] == '=' )
+ {
+ if( i < lenght - 2 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ return decoded;
+ }
+
+ TChar character( DecodeCharL( aBase64EncodedDesc[i] ) );
+ TChar nextCharacter( DecodeCharL( aBase64EncodedDesc[i + 1] ) );
+
+ switch( i % 4 )
+ {
+ case 0:
+ {
+ TChar shiftedChar(
+ ( character << 2 ) | // bits 0 to 5 of the first character
+ ( ( nextCharacter & 0x30 ) >> 4 ) ); // bits 4 to 5 of the second character
+ decodedPtr.Append( shiftedChar );
+ }
+ break;
+ case 1:
+ {
+ TChar shiftedChar(
+ ( character << 4 ) | // 0 to 3
+ ( ( nextCharacter & 0x3C ) >> 2 ) ); // 2 to 5
+ decodedPtr.Append( shiftedChar );
+ }
+ break;
+ case 2:
+ {
+ TChar shiftedChar(
+ ( ( character & 0x03 ) << 6 ) | // bits 0 to 1
+ ( nextCharacter & 0x3F ) ); // bits 0 to 5
+ decodedPtr.Append( shiftedChar );
+ }
+ break;
+ default: /* case 3, skip */
+ break;
+ }
+ }
+ return decoded;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::DecodeCharL
+// -----------------------------------------------------------------------------
+//
+TChar CPnpUtilImpl::DecodeCharL( const TChar aCharacter )
+ {
+ TChar decodedChar('A');
+
+ if( aCharacter >= 'A' && aCharacter <= 'Z' )
+ {
+ decodedChar = aCharacter - 'A';
+ }
+ else if( aCharacter >= 'a' && aCharacter <= 'z' )
+ {
+ decodedChar = aCharacter - 'a' + 26;
+ }
+ else if( aCharacter >= '0' && aCharacter <= '9' )
+ {
+ decodedChar = aCharacter - '0' + 52;
+ }
+ else if( aCharacter == '+' )
+ {
+ decodedChar = 62;
+ }
+ else if( aCharacter == '/' )
+ {
+ decodedChar = 63;
+ }
+ else if( aCharacter != '=' )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ return decodedChar;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::PackLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CPnpUtilImpl::PackLC( const TDesC8& aHex ) const
+ {
+ HBufC8* bin = HBufC8::NewLC( aHex.Length() / 2 );
+ TPtr8 binPtr( bin->Des() );
+ for( TInt i(0); i < aHex.Length() / 2; i++ )
+ {
+ TLex8 lex( aHex.Mid( i * 2, 2 ) );
+ TUint8 byte(0);
+ User::LeaveIfError( lex.Val( byte, EHex ) );
+ binPtr.Append( TUint8( byte ) );
+ }
+ return bin;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::Imsi
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::ImsiL(RMobilePhone::TMobilePhoneSubscriberId& aImsi) const
+ {
+ // Get IMSI
+ TRequestStatus status;
+ iPhone.GetSubscriberId( status, aImsi );
+ User::WaitForRequest( status );
+ User::LeaveIfError( status.Int() );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::FetchHomeNetworkInfoL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::FetchHomeNetworkInfoL()
+ {
+ LOGSTRING( "FetchHomeNetworkInfoL");
+
+ // Get home (sim) MCC&MNC info
+ RMobilePhone::TMobilePhoneNetworkInfoV1 info;
+ RMobilePhone::TMobilePhoneNetworkInfoV1Pckg infoPckg( info );
+#ifndef __WINS__
+ TRequestStatus status( KRequestPending );
+ iPhone.GetHomeNetwork( status, infoPckg );
+ User::WaitForRequest( status );
+ User::LeaveIfError( status.Int() );
+#else
+ info.iCountryCode.Copy( _L("244") );
+ info.iNetworkId.Copy( _L("05") );
+#endif
+
+ RMobilePhone::TMobilePhoneNetworkIdentity formattedMnc;
+ FormatMncCodeL( info.iCountryCode, info.iNetworkId, formattedMnc );
+ SetHomeMncL( formattedMnc );
+ SetHomeMccL( info.iCountryCode );
+
+ LOGSTRING( "FetchHomeNetworkInfoL - done");
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::FetchNetworkInfoL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::FetchNetworkInfoL()
+ {
+ LOGSTRING( "FetchNetworkInfoL");
+
+ // Get current (network) MCC&MNC info
+ TRequestStatus status;
+ LOGSTRING( "FetchNetworkInfoL 1");
+ RMobilePhone::TMobilePhoneNetworkInfoV1 info;
+ RMobilePhone::TMobilePhoneNetworkInfoV1Pckg infoPckg( info );
+ LOGSTRING( "FetchNetworkInfoL 2");
+ status = KErrNone;
+ LOGSTRING( "FetchNetworkInfoL 3");
+
+ iPhone.GetCurrentNetwork( status, infoPckg );
+
+ LOGSTRING( "FetchNetworkInfoL 4");
+ User::WaitForRequest( status );
+ LOGSTRING( "FetchNetworkInfoL 5");
+ User::LeaveIfError( status.Int() );
+ LOGSTRING( "FetchNetworkInfoL 6");
+
+ RMobilePhone::TMobilePhoneNetworkIdentity formattedMnc;
+ FormatMncCodeL( info.iCountryCode, info.iNetworkId, formattedMnc );
+ LOGSTRING( "FetchNetworkInfoL 7");
+ SetNetworkMncL( formattedMnc );
+ LOGSTRING( "FetchNetworkInfoL 8");
+ SetNetworkMccL( info.iCountryCode );
+
+ LOGSTRING( "FetchNetworkInfoL - done");
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::HomeMccL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const RMobilePhone::TMobilePhoneNetworkCountryCode CPnpUtilImpl::HomeMccL() const
+ {
+ RMobilePhone::TMobilePhoneNetworkIdentity mcc;
+ User::LeaveIfError( iRepository->Get( KPnPUtilHomeMcc, mcc ) );
+ LOGSTRING2( "HomeMccL %S", &mcc );
+
+ return mcc;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::SetHomeMccL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::SetHomeMccL( const RMobilePhone::TMobilePhoneNetworkCountryCode aMcc )
+ {
+ LOGSTRING2( "SetHomeMccL %S", &aMcc );
+ User::LeaveIfError( iRepository->Set( KPnPUtilHomeMcc, aMcc ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::HomeMncL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const RMobilePhone::TMobilePhoneNetworkIdentity CPnpUtilImpl::HomeMncL() const
+ {
+ RMobilePhone::TMobilePhoneNetworkIdentity mnc;
+ User::LeaveIfError( iRepository->Get( KPnPUtilHomeMnc, mnc ) );
+ LOGSTRING2( "HomeMncL %S", &mnc );
+ return mnc;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::SetHomeMncL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::SetHomeMncL( const RMobilePhone::TMobilePhoneNetworkIdentity aMnc )
+ {
+ LOGSTRING2( "SetHomeMncL %S", &aMnc );
+ User::LeaveIfError( iRepository->Set( KPnPUtilHomeMnc, aMnc ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::NetworkMccL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const RMobilePhone::TMobilePhoneNetworkCountryCode CPnpUtilImpl::NetworkMccL() const
+ {
+ RMobilePhone::TMobilePhoneNetworkIdentity mcc;
+ User::LeaveIfError( iRepository->Get( KPnPUtilNetworkMcc, mcc ) );
+ LOGSTRING2( "NetworkMccL %S", &mcc );
+ return mcc;
+ }
+
+EXPORT_C void CPnpUtilImpl::SetNetworkMccL( const RMobilePhone::TMobilePhoneNetworkCountryCode aMcc )
+ {
+ LOGSTRING2( "SetNetworkMccL %S", &aMcc );
+ User::LeaveIfError( iRepository->Set( KPnPUtilNetworkMcc, aMcc ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::NetworkMncL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const RMobilePhone::TMobilePhoneNetworkIdentity CPnpUtilImpl::NetworkMncL() const
+ {
+ RMobilePhone::TMobilePhoneNetworkIdentity mnc;
+ User::LeaveIfError( iRepository->Get( KPnPUtilNetworkMnc, mnc ) );
+ LOGSTRING2( "NetworkMncL %S", &mnc );
+ return mnc;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::NetworkMncL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::SetNetworkMncL( const RMobilePhone::TMobilePhoneNetworkIdentity aMnc )
+ {
+ LOGSTRING2( "SetNetworkMncL %S", &aMnc );
+ User::LeaveIfError( iRepository->Set( KPnPUtilNetworkMnc, aMnc ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::RegisteredInHomeNetworkL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CPnpUtilImpl::RegisteredInHomeNetworkL()
+ {
+ // Get registeration status
+ TRequestStatus status;
+ RMobilePhone::TMobilePhoneRegistrationStatus regstatus;
+ iPhone.GetNetworkRegistrationStatus(status, regstatus);
+ User::WaitForRequest( status );
+ User::LeaveIfError( status.Int() );
+ return (regstatus == RMobilePhone::ERegisteredOnHomeNetwork);
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::OperatorLongNameL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::OperatorLongName(RMobilePhone::TMobilePhoneNetworkLongName& aName)
+ {
+ // Get home (sim) MCC&MNC info
+ TRequestStatus status;
+ RMobilePhone::TMobilePhoneNetworkInfoV1 info;
+ RMobilePhone::TMobilePhoneNetworkInfoV1Pckg infoPckg( info );
+ status = KErrNone;
+ iPhone.GetHomeNetwork( status, infoPckg );
+ User::WaitForRequest( status );
+ aName.Zero();
+ aName.Append( info.iLongName );
+ return status.Int();
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::StoreAccessPoint
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CPnpUtilImpl::StoreAccessPoint(TUint32 /*aAP*/)
+ {
+ // Not used
+ return KErrNotSupported;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::FetchAccessPoint
+// -----------------------------------------------------------------------------
+//
+TInt CPnpUtilImpl::FetchAccessPoint(TUint32& /*aAP*/)
+ {
+ // Not used
+ return KErrNotSupported;
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::FormatMncCodeL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CPnpUtilImpl::FormatMncCodeL(
+ const RMobilePhone::TMobilePhoneNetworkCountryCode aMcc,
+ const RMobilePhone::TMobilePhoneNetworkIdentity aUnformattedMnc,
+ RMobilePhone::TMobilePhoneNetworkIdentity& aFormattedMnc ) const
+ {
+ LOGSTRING("FormatMncCodeL");
+ LOGTEXT( aMcc );
+ LOGTEXT( aUnformattedMnc );
+
+ RMobilePhone::TMobilePhoneNetworkIdentity formattedMnc;
+
+ // Check that codes only contain valid characters
+ TInt mncValue(0);
+ TInt mccValue(0);
+
+ TLex mncParser( aUnformattedMnc );
+ TInt err = mncParser.Val( mncValue );
+ if( err != KErrNone )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ TLex mccParser( aMcc );
+ err = mccParser.Val( mccValue );
+ if( err != KErrNone )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // In N7610 the MNC given by RMobilePhone::GetHomeNetwork is
+ // always three digits
+ // But for example in N6630 the MNC seems to be correctly formatted
+
+ // The initial value is the given MNC:
+ formattedMnc.Copy( aUnformattedMnc );
+
+ // Reformat only if needed
+ if( aUnformattedMnc.Length() == 3 )
+ {
+ // Assume two digits, exceptions follow
+ formattedMnc.Copy( aUnformattedMnc.Left(2) );
+
+ if( aMcc.Compare( _L("302") ) == 0 ||
+ aMcc.Compare( _L("346") ) == 0 ||
+ aMcc.Compare( _L("348") ) == 0 ||
+ aMcc.Compare( _L("356") ) == 0 ||
+ aMcc.Compare( _L("365") ) == 0 ||
+ aMcc.Compare( _L("376") ) == 0 ||
+ aMcc.Compare( _L("467") ) == 0 ||
+ aMcc.Compare( _L("732") ) == 0 )
+ {
+ // MNC should be three digits
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ else if( aMcc.Compare( _L("310") ) == 0 )
+ {
+ // MNC is always three digits in this case
+ // For example: 000, 011, 110, 020, 200, ...
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ else if( aMcc.Compare( _L("311") ) == 0 )
+ {
+ // 3 digit (USA) some exceptions
+
+ // See previous case for comments
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+
+ else if( aMcc.Compare( _L("338") ) == 0 )
+ {
+ // 2 digit, but 3 digit if 180 (JAM)
+ if( aUnformattedMnc.Compare( _L("180") ) == 0 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("342") ) == 0 )
+ {
+ // 2 digit, but 3 digit if larger than 51
+ if( mncValue >= 510 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("344") ) == 0 )
+ {
+ // 2 digit, but 3 digit if larger than 31
+ if( mncValue >= 310 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("352") ) == 0 )
+ {
+ // 2 digit, but 3 digit if smaller than 29
+ if( mncValue < 300 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("358") ) == 0 )
+ {
+ // 2 digit, but 3 digit if smaller than 20
+ if( mncValue < 300 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("360") ) == 0 )
+ {
+ // 2 digit, but 3 digit if 110
+ if( aUnformattedMnc.Compare( _L("110") ) == 0 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("362") ) == 0 )
+ {
+ // 2 digit, but 3 digit if larger than 92
+ if( mncValue >= 920 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("366") ) == 0 )
+ {
+ // 2 digit, but 3 digit if 110
+ if( aUnformattedMnc.Compare( _L("110") ) == 0 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ else if( aMcc.Compare( _L("722") ) == 0 )
+ {
+ // 2 digit, but 3 digit if 310
+ if( aUnformattedMnc.Compare( _L("310") ) == 0 )
+ {
+ formattedMnc.Copy( aUnformattedMnc );
+ }
+ }
+ }
+ aFormattedMnc.Copy( formattedMnc );
+ }
+
+// -----------------------------------------------------------------------------
+// CPnpUtilImpl::RESERVED_FUNC
+// -----------------------------------------------------------------------------
+//
+void CPnpUtilImpl::RESERVED_FUNC()
+ {
+ LOGSTRING("RESERVED_FUNC")
+ }
+
+// End of File