cbs/CbsServer/ServerSrc/Ccbsrecdecoder.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:11:09 +0200
changeset 0 ff3b6d0fd310
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* 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