cbs/CbsServer/ServerSrc/Ccbsrecdecoder.cpp
changeset 0 ff3b6d0fd310
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbs/CbsServer/ServerSrc/Ccbsrecdecoder.cpp	Tue Feb 02 01:11:09 2010 +0200
@@ -0,0 +1,368 @@
+/*
+* Copyright (c) 2003 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:  This module contains the implementation of CCbsRecDecoder class 
+*                member functions.
+*    
+*                CCCbsRecDecoder handles decoding of message contents.
+*
+*                CbsServer receives messages stored in 8-bit descriptors
+*                from ETel. This class converts them into 16-bit descriptors
+*                and decodes the message representation into UCS-2 (which
+*                is used by Symbian OS internally). 
+*
+*/
+
+
+// INCLUDE FILES
+
+#include <e32svr.h>
+#include <charconv.h>
+#include "CbsServerConstants.h"
+#include "CCbsRecDecoder.h"
+#include "CCbsMessage.h"
+#include "CCbsRecMessage.h"
+#include "CCbsRecWcdmaMessage.h"
+#include "CbsLogger.h"
+
+// CONSTANTS
+
+// Max characters in generated unicode 
+const TInt KMaxCharsInGeneratedUnicode = 128;   
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CCbsMcnSession::CCbsMcnSession
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CCbsRecDecoder::CCbsRecDecoder()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::ConstructL()
+    {
+    iConverter = CCnvCharacterSetConverter::NewL();
+    User::LeaveIfError( iFs.Connect() );
+    }     
+
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCbsRecDecoder* CCbsRecDecoder::NewL()
+    {
+    CCbsRecDecoder* self = new(ELeave) CCbsRecDecoder;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+    
+// Destructor
+CCbsRecDecoder::~CCbsRecDecoder()
+    {
+    CBSLOGSTRING("CBSSERVER: >>> CCbsRecDecoder::~CCbsRecDecoder()");    
+    iFs.Close();
+    delete iConverter;
+    CBSLOGSTRING("CBSSERVER: <<< CCbsRecDecoder::~CCbsRecDecoder()");
+    }
+
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::DecodeL
+// Decodes 7-bit, 8-bit and 16-bit representations into UCS-2.
+// If the message has a language indication prefixed
+// in the message body, the indication is removed.
+// Compressed messages are not supported.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::DecodeL( 
+    CCbsMessage& aMessage )
+    {
+    if ( aMessage.IsCompressed() )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // Convert message into plaintext.
+    DoDecodeL( aMessage );
+
+    // 8-bit representation not needed anymore.
+    aMessage.ReleaseEightBitRepresentation();
+
+    // Determine language of this message (from header or content),
+    aMessage.ResolveLanguage();
+
+    // Remove language indication, if present, from message.
+    aMessage.RemoveLanguageIndicationFromBodyL();
+    }
+
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::DoDecodeL
+// Decodes the given message's content. 
+// Decodes aMessage's 7-bit/Unicode representation
+// into internal Unicode representation.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::DoDecodeL( 
+    CCbsMessage& aMessage )
+    {
+    CBSLOGSTRING("CBSSERVER: >>> CCbsRecDecoder::DoDecodeL()");
+    
+    TCbsRecAlphabet alphabet( aMessage.Alphabet() );
+    if ( alphabet == ECbsRecAlphabetDefault || 
+         alphabet == ECbsRecAlphabetUnspecified )
+        {
+        DefaultAlphabetDecodeL( aMessage );
+        }
+    else if ( alphabet == ECbsRecAlphabet8bit )
+        {
+        EightbitAlphabetDecodeL( aMessage );
+        }
+    else
+        {
+        UnicodeDecodeL( aMessage );
+        }
+    CBSLOGSTRING("CBSSERVER: <<< CCbsRecDecoder::DoDecodeL()");
+    }
+    
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::UnicodeDecodeL
+// Decodes 8-bit and Unicode message representations.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::UnicodeDecodeL( 
+    CCbsMessage& aMsg )
+    {
+    CBSLOGSTRING("CBSSERVER: >>> CCbsRecDecoder::UnicodeDecodeL()");
+    
+    TPtrC8 contents( aMsg.Contents8() );
+
+    // Reserve enough space for the actual contents plus
+    // the CR key
+    aMsg.ReserveContentSizeL( contents.Length()+1 );
+
+    // Check if the message is preceded with language.
+    if( aMsg.DCS() == DCS_MPLI_UCS2 )
+        {
+        // The language is encoded as 7-bit USSD. Unpack that
+        // and add CR after the language to match the default
+        // alphabet case.
+        TBuf<3> language;
+        language.Copy( contents.Left(2) );
+        language[1] <<= 1;
+        language[1] |= (language[0] & 0x80) >> 7;
+        language[0] &= 0x7f;
+        language.Append( EKeyEnter );
+        aMsg.AppendContent( language );
+
+        // Skip the language indication
+        contents.Set( contents.Mid(2) );
+        }
+
+    // The rest of the message is UCS2 encoded Unicode. 
+    // Make sure the byte order is correct.
+    HBufC* text = HBufC::NewL( contents.Length() / 2 );
+    CleanupStack::PushL( text );
+
+    TPtr ptr( text->Des() );
+    TInt length( contents.Length() );
+
+    // If the length is an odd number, remove the last character.
+    if ( length & 0x01 )
+        {
+        length -= 1;
+        }
+
+    for ( TInt i( 0 ); i < length; i += 2 )
+        {
+        ptr.Append( ( contents[ i ] << 8 ) + contents[ i + 1 ] );
+        }
+
+    aMsg.AppendContent( RemoveTrailingCR( *text ) );
+    CleanupStack::PopAndDestroy();
+    
+    CBSLOGSTRING("CBSSERVER: <<< CCbsRecDecoder::UnicodeDecodeL()");
+    }
+   
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::DefaultAlphabetDecodeL
+// Decodes 7-bit message representation.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::DefaultAlphabetDecodeL( 
+    CCbsMessage& aMsg )
+    {
+    CBSLOGSTRING("CBSSERVER: >>> CCbsRecDecoder::DefaultAlphabetDecodeL()");
+    
+    // Check that the converter is available
+    CCnvCharacterSetConverter* characterSetConverter = 
+        CCnvCharacterSetConverter::NewLC(); // on CS
+
+    CCnvCharacterSetConverter::TAvailability availability = 
+        characterSetConverter->PrepareToConvertToOrFromL(
+            KCharacterSetIdentifierSms7Bit, iFs );
+
+    if ( availability == CCnvCharacterSetConverter::ENotAvailable )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    // Allocate a buffer for the cleartext message
+    TBuf8< KCbsMaxCharsInPage + 1 > realMsg;
+
+    // Get a pointer to the encoded message
+    TPtrC8 msgPartOfEtelMsg = aMsg.Contents8();
+
+    // Length of the cleartext message.
+    TInt messageLength( ( msgPartOfEtelMsg.Length() * 8 ) / 7 );
+
+    static const TUint mask_table[ 8 ] = 
+			    { 0x7F, 0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F };
+    TUint8  si,di;            // Indexes
+    TInt  tmp_modulo;         // Temporary; to improve efficiency
+    si = 0;
+
+    // The location of the current 7-bit character determines the
+    // action to be taken. Only every 7th character is not divided into
+    // two bytes. All other characters will have to be contructed by
+    // combining bits of two consequent bytes.
+
+    for ( di = 0; di < messageLength; di++ )
+	    {
+	    TUint num2 = 0;
+	    tmp_modulo = di % 8;
+	    switch ( tmp_modulo )
+	        {
+	        case 0:
+		        num2 = msgPartOfEtelMsg[ si ] & 0x7F;
+		        realMsg.Append( num2 );
+		        break;
+	        case 7:
+		        num2 = ( msgPartOfEtelMsg[ si ] >> 1 ) & 0x7F;
+		        realMsg.Append( num2 );
+		        si++;
+		        break;
+	        default:
+	            num2 = msgPartOfEtelMsg[ si ] >> ( 8 - ( tmp_modulo ) );
+	            num2 &= mask_table[ tmp_modulo ];
+	            num2 |= msgPartOfEtelMsg[ si + 1 ] << ( tmp_modulo );
+	            num2 &= 0x7F;
+	            realMsg.Append( num2 );
+	            si++;
+	        break;
+	        }//switch( tmp_modulo )
+	    }//for
+
+    TBuf16<KMaxCharsInGeneratedUnicode> generatedUnicode;
+    TInt state( CCnvCharacterSetConverter::KStateDefault ); // has to be ref.
+    
+    // Remove all trailing control characters from the end of the Cell info msg
+    TBuf8<KCbsMaxCharsInPage> cleanedMsg;
+    if ( aMsg.TopicNumber() == KCellInfoTopic )
+        {
+        cleanedMsg = RemoveTrailingControlChars( realMsg );
+        User::LeaveIfError( characterSetConverter->ConvertToUnicode(
+            generatedUnicode, cleanedMsg, state ) );
+        }
+    else
+        {
+        User::LeaveIfError( characterSetConverter->ConvertToUnicode(
+            generatedUnicode, realMsg, state ) );
+        } 
+    
+    CleanupStack::PopAndDestroy(); // characterSetConverter
+    
+    aMsg.ReserveContentSizeL( messageLength );
+    aMsg.AppendContent( RemoveTrailingCR( generatedUnicode ) );
+    
+    CBSLOGSTRING("CBSSERVER: <<< CCbsRecDecoder::DefaultAlphabetDecodeL()");
+    }
+    
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::EightbitAlphabetDecodeL
+// Decodes 8-bit message representation.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCbsRecDecoder::EightbitAlphabetDecodeL( 
+    CCbsMessage& aMsg )
+    {
+    CBSLOGSTRING("CBSSERVER: >>> CCbsRecDecoder::EightbitAlphabetDecodeL()");
+    
+    // Copy 8-bit representation to 16-bit
+    HBufC* hbuf = HBufC::NewL( aMsg.Contents8().Length() );
+    CleanupStack::PushL( hbuf );
+    
+    TPtr16 ptr16 = hbuf->Des();     
+    ptr16.Copy( aMsg.Contents8() );        
+    
+    // Reserve enough space for the actual contents    
+    aMsg.ReserveContentSizeL( aMsg.Contents8().Length() );  
+    aMsg.AppendContent( RemoveTrailingCR( *hbuf ) );
+    
+    CleanupStack::PopAndDestroy( hbuf );
+    
+    CBSLOGSTRING("CBSSERVER: <<< CCbsRecDecoder::EightbitAlphabetDecodeL()");
+    }
+
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::RemoveTrailingCR
+// Removes the trailing CRs from a message.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC CCbsRecDecoder::RemoveTrailingCR( 
+    const TDesC& aText )
+    {
+    TInt i( aText.Length() );
+    for ( ; i > 0 && aText[ i - 1 ] == EKeyEnter; i-- )
+        {
+        // nothing
+        }
+
+    return aText.Left( i );
+    }
+    
+// -----------------------------------------------------------------------------
+// CCbsRecDecoder::RemoveTrailingControlChars
+// Removes the trailing control characters from a message.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CCbsRecDecoder::RemoveTrailingControlChars( 
+    const TDesC8& aText )
+    {
+    TInt i( aText.Length() );
+    for ( ; i > 0 && ( aText[ i - 1 ] == EKeyEnter || aText[ i - 1 ] == EKeyLineFeed ); i-- )
+        {
+        // nothing
+        }
+
+    return aText.Left( i );
+    }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+//  End of File