cbs/CbsServer/ServerSrc/CCbsReceiverHelper.cpp
changeset 0 ff3b6d0fd310
child 19 7d48bed6ce0c
equal deleted inserted replaced
-1:000000000000 0:ff3b6d0fd310
       
     1 /*
       
     2 * Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This module contains the implementation of CCbsReceiverHelper class
       
    15 *                member functions.
       
    16 *
       
    17 *                CCbsReceiverHelper gets the messages from the receiver and
       
    18 *                sends them to the database. All received messages are
       
    19 *                sent to CCbsReceiverHelper instance by CCbsRecEtel.
       
    20 *                This class makes subscription and existence checks
       
    21 *                to these messages and also implements topic detection feature.
       
    22 *
       
    23 */
       
    24 
       
    25 
       
    26 // INCLUDE FILES
       
    27 #include <barsc.h>              // Resource access
       
    28 #include <barsread.h>           // Resource access
       
    29 
       
    30 #include <CbsServer.rsg>
       
    31 
       
    32 #include "CbsCommon.h"
       
    33 #include "CbsUtils.h"
       
    34 #include "CbsServerPanic.h"
       
    35 #include "CCbsServer.h"
       
    36 #include "CCbsReceiverHelper.h"
       
    37 #include "CCbsDbImp.H"
       
    38 #include "CCbsDbImpSettings.H"
       
    39 #include "CCbsDbImpTopicList.h"
       
    40 #include "CCbsDbImpTopicMessages.h"
       
    41 #include "CCbsDbImpTopicCollection.h"
       
    42 #include "CCbsRecMessage.h"
       
    43 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    44 #include <viewcli.h>            // View server access
       
    45 #else
       
    46 #include <viewclipartner.h>
       
    47 #endif
       
    48 #include <AknNotifyStd.h>       // ECellBroadcastNotification
       
    49 #include <AknSoftNotifier.h>    // Soft Notification API
       
    50 #include <e32property.h>
       
    51 #include <coreapplicationuisdomainpskeys.h>
       
    52 #include <NcnListDomainPSKeys.h>
       
    53 
       
    54 #include <data_caging_path_literals.hrh>
       
    55 #include "CbsLogger.h"
       
    56 
       
    57 #include <centralrepository.h>  // for local variation
       
    58 #include "cbsinternalcrkeys.h"  // for local variation
       
    59 #include "cbsvariant.hrh"       // for local variation
       
    60 
       
    61 // CONSTANTS
       
    62 
       
    63 // UID of CBS UI application
       
    64 #define KUidCbsUiappDef 0x101F4CD3
       
    65 const TUid KUidCbsUiappApp = { KUidCbsUiappDef };
       
    66 
       
    67 const TInt KCbsImmediateMessageIdInt = 313;
       
    68 const TUid KCbsImmediateMessageId = { KCbsImmediateMessageIdInt };
       
    69 
       
    70 const TInt KCbsMessageTone  = 2; // See SharedDataKeysVariant.h or NcnListInternalPSKeys.h
       
    71 
       
    72 // DATA TYPES
       
    73 // CbsUi application view ID's
       
    74 enum TCbsUiViewIds
       
    75     {
       
    76     ECbsUiTopicViewId = 1,
       
    77     ECbsUiTopicListViewId,
       
    78     ECbsUiListAppColumnViewId,
       
    79     ECbsUiMsgViewId,            //message view id
       
    80     ECbsUiAddFromIndexViewId,
       
    81     ECbsUiSettingsViewId
       
    82     };
       
    83 
       
    84 // These values specify a range of accepted topic number values (inclusive).
       
    85 const TUint KMinTopicNumber = 1;     // 000 is not accepted.
       
    86 const TUint KMaxTopicNumber = 999;
       
    87 
       
    88 // LOCAL FUNCTION PROTOTYPES
       
    89 LOCAL_C void ParseMessageFormatL(
       
    90     TLex& aLex, CCbsDbImpTopicCollection& aCollection );
       
    91 LOCAL_C void ParseIndexElementIntroL(
       
    92     TLex& aLex, CCbsDbImpTopicCollection& aCollection );
       
    93 LOCAL_C void ParseServiceIntroL(
       
    94     TLex& aLex, CCbsDbImpTopicCollection& aCollection );
       
    95 LOCAL_C void ParseMessageIdL(
       
    96     TLex& aLex, TUint& aMessageId );
       
    97 LOCAL_C void ParseSubIndexIntroL(
       
    98     TLex& aLex );
       
    99 LOCAL_C void ParseSubIndexIdL(
       
   100     TLex& aLex );
       
   101 LOCAL_C void ParseNameCharactersCrLfL(
       
   102     TLex& aLex, TPtrC& aName );
       
   103 
       
   104 // ==================== LOCAL FUNCTIONS ====================
       
   105 
       
   106 // -----------------------------------------------------------------------------
       
   107 // ParseMessageFormatL
       
   108 // Parses an index message.
       
   109 // Returns: None
       
   110 // -----------------------------------------------------------------------------
       
   111 //
       
   112 LOCAL_C void ParseMessageFormatL(
       
   113     TLex& aLex,
       
   114     CCbsDbImpTopicCollection& aCollection )
       
   115     {
       
   116     TInt identitiesCount( 0 );
       
   117     while ( !aLex.Eos() )
       
   118         {
       
   119         ParseIndexElementIntroL( aLex, aCollection );
       
   120         identitiesCount++;
       
   121         }
       
   122 
       
   123     if ( identitiesCount == 0 )
       
   124         {
       
   125         User::Leave( KErrCorrupt );
       
   126         }
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // ParseIndexElementIntroL
       
   131 // Parses part of an index message.
       
   132 // Returns: None
       
   133 // -----------------------------------------------------------------------------
       
   134 //
       
   135 LOCAL_C void ParseIndexElementIntroL(
       
   136     TLex& aLex,
       
   137     CCbsDbImpTopicCollection& aCollection )
       
   138     {
       
   139     TBool hasSubIndexId( EFalse );
       
   140 
       
   141     // subindex-id (optional for service-intro)
       
   142     if ( aLex.Peek().IsAlpha() )
       
   143         {
       
   144         hasSubIndexId = ETrue;
       
   145         ParseSubIndexIdL( aLex );
       
   146         }
       
   147 
       
   148     // subindex-intro | service-intro
       
   149     // We'll take a peek to discover, which one
       
   150     if ( hasSubIndexId && aLex.Peek() == EKeySpace )
       
   151         {
       
   152         ParseSubIndexIntroL( aLex );
       
   153         }
       
   154     else
       
   155         {
       
   156         ParseServiceIntroL( aLex, aCollection );
       
   157         }
       
   158     }
       
   159 
       
   160 // -----------------------------------------------------------------------------
       
   161 // ParseServiceIntroL
       
   162 // Parses part of an index message.
       
   163 // Returns: None
       
   164 // -----------------------------------------------------------------------------
       
   165 //
       
   166 LOCAL_C void ParseServiceIntroL(
       
   167     TLex& aLex,
       
   168     CCbsDbImpTopicCollection& aCollection )
       
   169     {
       
   170     // We'll store the results here
       
   171     TCbsDbTopicIdentity identity;
       
   172 
       
   173     // message-id
       
   174     TUint messageId;
       
   175     ParseMessageIdL( aLex, messageId );
       
   176     identity.iNumber = TUint16( messageId );
       
   177 
       
   178     // delimeter
       
   179     TChar delimeter( aLex.Get() );
       
   180     if ( delimeter != ' ' && delimeter != '.' )
       
   181         {
       
   182         User::Leave( KErrCorrupt );
       
   183         }
       
   184 
       
   185     // service-name
       
   186     TPtrC serviceName;
       
   187     ParseNameCharactersCrLfL( aLex, serviceName );
       
   188     // drop crlf
       
   189     serviceName.Set( serviceName.Left( serviceName.Length()-2 ) );
       
   190 
       
   191     // If the delimeter is ' ', store the identity. Otherwise
       
   192     // it only refers to a subindex page, so we skip it
       
   193     if ( delimeter == ' ' )
       
   194         {
       
   195         // Copy max. KCbsDbTopicNameLength characters
       
   196         identity.iName = serviceName.Left( KCbsDbTopicNameLength );
       
   197         // Store the topic identity into the database
       
   198         aCollection.AddTopicIdentityL( identity );
       
   199         }
       
   200     }
       
   201 
       
   202 // -----------------------------------------------------------------------------
       
   203 // ParseMessageIdL
       
   204 // Parses part of an index message.
       
   205 // Returns: None
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 LOCAL_C void ParseMessageIdL(
       
   209     TLex& aLex,
       
   210     TUint& aMessageId )
       
   211     {
       
   212     if ( aLex.Val( aMessageId ) != KErrNone
       
   213         || aMessageId < KMinTopicNumber
       
   214         || aMessageId > KMaxTopicNumber )
       
   215         {
       
   216         User::Leave( KErrCorrupt );
       
   217         }
       
   218     }
       
   219 
       
   220 // -----------------------------------------------------------------------------
       
   221 // ParseSubIndexIntroL
       
   222 // Parses part of an index message.
       
   223 // subindex-intro = " " subindex-name crlf
       
   224 // subindex-name  = name-character+
       
   225 // Returns: None
       
   226 // -----------------------------------------------------------------------------
       
   227 //
       
   228 LOCAL_C void ParseSubIndexIntroL(
       
   229     TLex& aLex )
       
   230     {
       
   231     if ( aLex.Get() != EKeySpace )
       
   232         {
       
   233         User::Leave( KErrCorrupt );
       
   234         }
       
   235 
       
   236     // subindex-name crlf
       
   237     TPtrC subIndexName;
       
   238     ParseNameCharactersCrLfL( aLex, subIndexName );
       
   239     }
       
   240 
       
   241 // -----------------------------------------------------------------------------
       
   242 // ParseSubIndexIdL
       
   243 // Parses part of an index message.
       
   244 // subindex-id = subindex-character+
       
   245 // Returns: None
       
   246 // -----------------------------------------------------------------------------
       
   247 //
       
   248 LOCAL_C void ParseSubIndexIdL(
       
   249     TLex& aLex )
       
   250     {
       
   251     // check that there is at least one subindex-character
       
   252     if ( !aLex.Peek().IsAlpha() )
       
   253         {
       
   254         User::Leave( KErrCorrupt );
       
   255         }
       
   256 
       
   257     // subindex-id
       
   258     while ( aLex.Peek().IsAlpha() )
       
   259         {
       
   260         aLex.Inc();
       
   261         }
       
   262     }
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // ParseNameCharactersCrLfL
       
   266 // Parses part of an index message.
       
   267 // name-character+ crlf
       
   268 // Returns: None
       
   269 // -----------------------------------------------------------------------------
       
   270 //
       
   271 LOCAL_C void ParseNameCharactersCrLfL(
       
   272     TLex& aLex,
       
   273     TPtrC& aName )
       
   274     {
       
   275     aLex.Mark();
       
   276 
       
   277     // check that we have at least one name-character
       
   278     TChar currCharacter( aLex.Get() );
       
   279     if( currCharacter == EKeyLineFeed
       
   280         || currCharacter == EKeyEnter
       
   281         || currCharacter == 0 )
       
   282         {
       
   283         User::Leave( KErrCorrupt );
       
   284         }
       
   285 
       
   286     // scan until LF or EOS
       
   287     while( currCharacter != EKeyLineFeed && currCharacter != 0 )
       
   288         {
       
   289         currCharacter = aLex.Get();
       
   290         }
       
   291 
       
   292     // CR-LF is ok, EOS is not
       
   293     if( currCharacter == EKeyLineFeed )
       
   294         {
       
   295         aName.Set( aLex.MarkedToken() );
       
   296         }
       
   297     else
       
   298         {
       
   299         User::Leave( KErrCorrupt );
       
   300         }
       
   301     }
       
   302 
       
   303 // ================= MEMBER FUNCTIONS =======================
       
   304 
       
   305 // -----------------------------------------------------------------------------
       
   306 // CCbsReceiverHelper::CCbsReceiverHelper
       
   307 // C++ default constructor can NOT contain any code, that
       
   308 // might leave.
       
   309 // -----------------------------------------------------------------------------
       
   310 //
       
   311 CCbsReceiverHelper::CCbsReceiverHelper(
       
   312     CCbsDbImp& aDatabase )
       
   313     : iDatabase( aDatabase )
       
   314     {
       
   315     }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CCbsReceiverHelper::ConstructL
       
   319 // Symbian 2nd phase constructor can leave.
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 void CCbsReceiverHelper::ConstructL()
       
   323     {
       
   324     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::ConstructL()");
       
   325 
       
   326     iVwsSession = CVwsSessionWrapper::NewL();
       
   327 
       
   328     // Array for SIM Topic numbers. This way we know which topics
       
   329     // to delete also from the SIM card (when deleting all topics).
       
   330     iSimTopics = new ( ELeave ) CArrayFixFlat<TInt>( 1 );
       
   331     
       
   332     // Fetch local variation bits from CenRep    
       
   333     CRepository* repository = CRepository::NewL( KCRUidCbsVariation );    
       
   334     TInt err = repository->Get( KCbsVariationFlags, iLVBits );
       
   335     if ( err )
       
   336         {
       
   337         iLVBits = 0;
       
   338         }  
       
   339     CBSLOGSTRING2("CBSSERVER: CCbsRecEtel::ConstructL(): CenRep error: %d", err );
       
   340     delete repository;
       
   341 
       
   342     CBSLOGSTRING("CBSSERVER: <<< CCbsReceiverHelper::ConstructL()");
       
   343     }
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CCbsReceiverHelper::NewL
       
   347 // Two-phased constructor.
       
   348 // -----------------------------------------------------------------------------
       
   349 //
       
   350 CCbsReceiverHelper* CCbsReceiverHelper::NewL(
       
   351     CCbsDbImp& aDatabase )
       
   352     {
       
   353     // Normal two phase construction.
       
   354     CCbsReceiverHelper* self = new ( ELeave ) CCbsReceiverHelper( aDatabase );
       
   355     CleanupStack::PushL( self );
       
   356     self->ConstructL();
       
   357     CleanupStack::Pop();
       
   358     return self;
       
   359     }
       
   360 
       
   361 // Destructor
       
   362 CCbsReceiverHelper::~CCbsReceiverHelper()
       
   363     {
       
   364     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::~CCbsReceiverHelper()");
       
   365 
       
   366     delete iSimTopics;
       
   367     delete iVwsSession;
       
   368 
       
   369     CBSLOGSTRING("CBSSERVER: <<< CCbsReceiverHelper::~CCbsReceiverHelper()");
       
   370     }
       
   371 
       
   372 // -----------------------------------------------------------------------------
       
   373 // CCbsReceiverHelper::CCbsReceiverHelper
       
   374 // Processes a message received by the receiver.
       
   375 //
       
   376 // This function is called when a message is received.
       
   377 //
       
   378 // Assumptions;
       
   379 // 1.  The message doesn't have it's permanent or read
       
   380 //     flags raised - method leaves with KErrNotSupported
       
   381 //     if this is the case.
       
   382 // 2.  If an index message (root or subindex) is passed as
       
   383 //     a parameter, the language indication prefix, if any,
       
   384 //     has been removed before HandleReceivedMessageL() is called.
       
   385 //
       
   386 // Assumption (2) holds because language indications are removed
       
   387 // by Receiver module in an instance of CCbsRecDecoder.
       
   388 // Message may not be accepted if it is somehow invalid
       
   389 // or the reception has been disabled.
       
   390 // This function also handles the detection of new topics
       
   391 // and the processing of an index message.
       
   392 // (other items were commented in a header).
       
   393 // -----------------------------------------------------------------------------
       
   394 //
       
   395 void CCbsReceiverHelper::HandleReceivedMessageL(
       
   396     CCbsMessage& aMessage )
       
   397     {
       
   398     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::HandleReceivedMessageL()");
       
   399 
       
   400     if ( aMessage.IsIndexMessage() )
       
   401         {
       
   402         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Index msg.");
       
   403 
       
   404         // It is assumed that a language indication prefix,
       
   405         // if any, has already been removed from the message.
       
   406         aMessage.RemoveIndexHeaderL();
       
   407 
       
   408         TBool isChildSubindex( aMessage.IsChildSubindex() );
       
   409 
       
   410         // Parse the index message
       
   411         HandleIndexMessageL( aMessage.Contents(), isChildSubindex );
       
   412 
       
   413         // Child subindex messages won't be displayed to the user.
       
   414         if ( isChildSubindex )
       
   415             {
       
   416             return;
       
   417             }
       
   418         }
       
   419 
       
   420     TUint16 topicNumber( aMessage.TopicNumber() );
       
   421     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): topic number: %d.", topicNumber );
       
   422 
       
   423     TCbsDbTopic topic;
       
   424     iDatabase.TopicListL().FindTopicByNumberL( topicNumber, topic );
       
   425     CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): iDatabase.TopicListL().FindTopicByNumberL(..) called OK." );
       
   426 
       
   427     // If subscribed, handle the message
       
   428     if ( topic.iSubscribed )
       
   429         {
       
   430         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Topic subscribed, processing." );
       
   431 
       
   432         // Create and initialize message
       
   433         TCbsDbMessage message;
       
   434 
       
   435         TTime now;
       
   436         now.UniversalTime();
       
   437         message.iDateTime = now.Int64();
       
   438         message.iKey = aMessage.Key();
       
   439         message.iLanguage = aMessage.Language();
       
   440         message.iLength = aMessage.Contents().Length();
       
   441         message.iPermanent = EFalse;
       
   442         message.iRead = EFalse;
       
   443         TPtrC ptr( aMessage.Contents() );
       
   444 
       
   445         iDatabase.TopicMessagesL().AddMessageL( topicNumber, message, ptr );
       
   446         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Msg added OK." );
       
   447 
       
   448         if ( aMessage.RequiresImmediateDisplay() )
       
   449             {
       
   450             CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Calling LaunchMessageImmediateDisplay()... " );
       
   451 
       
   452             // If the operator indicates that this message must be displayed
       
   453             // immediately, request a view switch of CBS UI application.
       
   454             LaunchMessageImmediateDisplay( message );
       
   455 
       
   456             CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): LaunchMessageImmediateDisplay() called OK." );
       
   457             }
       
   458         else if ( topic.iHotmarked )
       
   459             {
       
   460             // The message is of a hotmarked topic => Show a soft notification.
       
   461             CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Calling LaunchMessageSoftNotification()... " );
       
   462             LaunchMessageSoftNotificationL( ETrue );
       
   463             CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): LaunchMessageSoftNotification() called OK." );
       
   464             }
       
   465         } // if ( topic.iSubscribed )
       
   466     else
       
   467         {
       
   468         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::HandleReceivedMessageL(): Topic NOT subscribed, msg not processed." );
       
   469         }
       
   470 
       
   471     CBSLOGSTRING("CBSSERVER: <<< CCbsReceiverHelper::HandleReceivedMessageL()");
       
   472     }
       
   473 
       
   474 // -----------------------------------------------------------------------------
       
   475 // CCbsReceiverHelper::CheckForNewTopicL
       
   476 // Checks if aMessage's topic is in the topic list.
       
   477 //
       
   478 // If the topic detection is enabled and the topic of this
       
   479 // message is not in the topic list, the topic is added
       
   480 // to the list. The method will then return ETrue.
       
   481 // Otherwise EFalse is returned.
       
   482 // (other items were commented in a header).
       
   483 // -----------------------------------------------------------------------------
       
   484 //
       
   485 TBool CCbsReceiverHelper::CheckForNewTopicL(
       
   486     const CCbsMessage& aMessage )
       
   487     {
       
   488     // Check if the topic detection is on and if so, add topic if the topic
       
   489     // is a new topic.
       
   490     TBool detection;
       
   491     TBool result( EFalse );
       
   492 
       
   493     iDatabase.SettingsL().GetTopicDetectionStatus( detection );
       
   494 
       
   495     if ( detection && HandleTopicDetectedL( aMessage.TopicNumber() ) )
       
   496         {
       
   497         // If a new topic added, we do not send the message to
       
   498         // the database so return ETrue.
       
   499         result = ETrue;
       
   500         }
       
   501     else
       
   502         {
       
   503         // Topic detection disabled or topic already in the database
       
   504         result = EFalse;
       
   505         }
       
   506 
       
   507     return result;
       
   508     }
       
   509 
       
   510 // -----------------------------------------------------------------------------
       
   511 // CCbsReceiverHelper::CheckForSubscriptionAndExistenceL
       
   512 // Checks if the topic of this message is listed and subscribed.
       
   513 // Returns ETrue only if the message does not exist in the
       
   514 // database and the message's topic is subscribed.
       
   515 // (other items were commented in a header).
       
   516 // -----------------------------------------------------------------------------
       
   517 //
       
   518 TBool CCbsReceiverHelper::CheckForSubscriptionAndExistenceL(
       
   519     const CCbsMessage& aMessage )
       
   520     {
       
   521     // Check if the message belongs to some subscribed topic.
       
   522     TCbsDbTopic topic;
       
   523     TUint16 topicNumber( 0 );
       
   524 
       
   525     // Index messages are stored in topic 0.
       
   526     if ( !aMessage.IsIndexMessage() )
       
   527         {
       
   528         topicNumber = aMessage.TopicNumber();
       
   529         }
       
   530 
       
   531     TRAPD( errorCode, iDatabase.TopicListL().FindTopicByNumberL( topicNumber, topic ) );
       
   532 
       
   533     if ( errorCode == KErrNotFound )
       
   534         {
       
   535         return EFalse;
       
   536         }
       
   537     User::LeaveIfError( errorCode );
       
   538 
       
   539     return topic.iSubscribed;
       
   540     }
       
   541 
       
   542 // -----------------------------------------------------------------------------
       
   543 // CCbsReceiverHelper::LanguageOfMessageSubscribedL
       
   544 // Checks if aMessage's language has been subscribed by the user.
       
   545 // ETrue is returned either if the language specified has been
       
   546 // subscribed, message language is "Other" or the user has
       
   547 // prefers to receive messages of all languages.
       
   548 // (other items were commented in a header).
       
   549 // -----------------------------------------------------------------------------
       
   550 //
       
   551 TBool CCbsReceiverHelper::LanguageOfMessageSubscribedL(
       
   552     const CCbsMessage& aMessage )
       
   553     {
       
   554     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::LanguageOfMessageSubscribedL" );
       
   555 
       
   556     TCbsDbLanguages languages;
       
   557     iDatabase.SettingsL().GetLanguages( languages );
       
   558 
       
   559     if ( aMessage.Language() < 0 || aMessage.Language() >= ECbsCount )
       
   560         {
       
   561         return EFalse;
       
   562         }
       
   563 
       
   564     TCbsDbLanguage language( aMessage.Language() );
       
   565     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::LanguageOfMessageSubscribedL: language: %d.", language );
       
   566 
       
   567     TBool subscribed( languages.iLanguages[ECbsAll] ||
       
   568         languages.iLanguages[ECbsOther] && language == ECbsOther ||
       
   569         !languages.iLanguages[ECbsOther] && languages.iLanguages[language] );
       
   570 
       
   571     CBSLOGSTRING2("CBSSERVER: <<< CCbsReceiverHelper::LanguageOfMessageSubscribedL, returning %d.", subscribed );
       
   572     return subscribed;
       
   573     }
       
   574 
       
   575 // ---------------------------------------------------------
       
   576 // AddSimTopicL()
       
   577 //
       
   578 // Adds the given topic (aNumber, aName) into the DB.
       
   579 // ---------------------------------------------------------
       
   580 void CCbsReceiverHelper::AddSimTopicL( 
       
   581     const TUint aNumber,
       
   582     const TDesC& aName )
       
   583     {
       
   584     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::AddSimTopicL()");
       
   585 
       
   586     TCbsDbTopic topic;
       
   587     if ( aName == KNullDesC )       // Topic name not given, use "SIM topics".
       
   588         {
       
   589         // Establish file server session.
       
   590         RFs fs;
       
   591         User::LeaveIfError( fs.Connect() );
       
   592         CleanupClosePushL( fs );
       
   593 
       
   594         // Open localized resource file.
       
   595         RResourceFile resourceFile;
       
   596         CbsUtils::FindAndOpenDefaultResourceFileLC(
       
   597             fs, resourceFile ); // on CS
       
   598 
       
   599         // Read "SIM topic"-string.
       
   600         TResourceReader reader;
       
   601         reader.SetBuffer( resourceFile.AllocReadLC(
       
   602             R_TEXT_SIM_TOPIC ) ); // on CS
       
   603 
       
   604         HBufC* text = reader.ReadHBufCL();
       
   605         topic.iName = *text;
       
   606         CleanupStack::PopAndDestroy(3);  // fs, resourceFile, readerBuf
       
   607 
       
   608         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::AddSimTopicL(): Topic name read from resources.");
       
   609         }
       
   610     else // Use the given topic name.
       
   611         {
       
   612         topic.iName = aName;
       
   613         }
       
   614 
       
   615     topic.iNumber = TUint16( aNumber );
       
   616     topic.iHotmarked = EFalse;
       
   617     topic.iProtected = EFalse;
       
   618     
       
   619     // Variated feature    
       
   620     if ( iLVBits & KCbsLVFlagTopicSubscription )
       
   621         {
       
   622         topic.iSubscribed = ETrue;
       
   623         }
       
   624     else
       
   625         {
       
   626         topic.iSubscribed = EFalse;
       
   627         }
       
   628 
       
   629     // Leaves, if the topic already exists, so we trap that
       
   630     // error. All other errors are passed as a normal leave.
       
   631     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::AddSimTopicL(): Topic %d from SIM to topic list...", topic.iNumber );
       
   632     // Try to add topic to topic list, topic not detected automatically
       
   633     TRAPD( err, iDatabase.TopicListL().AddTopicL( topic, EFalse ) );
       
   634     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::AddSimTopicL(): AddTopicL() TRAPped error: %d.", err );
       
   635 
       
   636     if( err != KErrAlreadyExists && err != KErrArgument )
       
   637         {
       
   638         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::AddSimTopicL(): Leave if error != -11 || -6");
       
   639         User::LeaveIfError( err );
       
   640         }
       
   641 
       
   642     // Append to SIM Topic array
       
   643     iSimTopics->AppendL( topic.iNumber );
       
   644     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::AddSimTopicL(): Topic %d appended to array.", topic.iNumber ); 
       
   645     
       
   646     // Leave so that caller is informed e.g. if topic already exists
       
   647     User::LeaveIfError( err );
       
   648     CBSLOGSTRING("CBSSERVER: <<< CCbsReceiverHelper::AddSimTopicL()" );
       
   649     
       
   650     }
       
   651 
       
   652 // -----------------------------------------------------------------------------
       
   653 // CCbsReceiverHelper::SimTopics
       
   654 // Returns topics currently added from the SIM card.
       
   655 // (other items were commented in a header).
       
   656 // -----------------------------------------------------------------------------
       
   657 //
       
   658 CArrayFixFlat<TInt>& CCbsReceiverHelper::SimTopics() const
       
   659     {
       
   660     return *iSimTopics;
       
   661     }
       
   662 
       
   663 // -----------------------------------------------------------------------------
       
   664 // CCbsReceiverHelper::DeleteFromSimTopicCache
       
   665 // Deletes the topic number from local SIM Topic array.
       
   666 // (other items were commented in a header).
       
   667 // -----------------------------------------------------------------------------
       
   668 //
       
   669 void CCbsReceiverHelper::DeleteFromSimTopicCache( const TUint16 aNumber )
       
   670     {
       
   671     CBSLOGSTRING("CBSSERVER: >>> CCbsReceiverHelper::DeleteFromSimTopicCache()");
       
   672     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): Topic number: %d", aNumber );
       
   673     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): Topic count in cache (1): %d", iSimTopics->Count() );
       
   674 
       
   675     // Check if this topic is a SIM Topic (can be found in the array)
       
   676     TKeyArrayFix key( 0, ECmpTUint16 );
       
   677     TInt index;
       
   678     TUint16 topicNumber( aNumber );
       
   679     TInt result( iSimTopics->FindIsq( topicNumber, key, index ) );
       
   680 
       
   681     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): FindIsq() result: %d", result );
       
   682     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): FindIsq() result, position: %d", index );
       
   683 
       
   684     // Delete the topic from the array
       
   685     if ( result == KErrNone )
       
   686         {
       
   687         CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): Topic no. %d found from cache.", aNumber );
       
   688         iSimTopics->Delete( index );
       
   689         CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): Topic deleted from cache, index: %d", index );
       
   690         iSimTopics->Compress();
       
   691         CBSLOGSTRING("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): SIM Topic array compressed.");
       
   692         }
       
   693 
       
   694     CBSLOGSTRING2("CBSSERVER: CCbsReceiverHelper::DeleteFromSimTopicCache(): Topic count in cache (2): %d", iSimTopics->Count() );
       
   695     CBSLOGSTRING("CBSSERVER: <<< CCbsReceiverHelper::DeleteFromSimTopicCache()");
       
   696     }
       
   697 
       
   698 // -----------------------------------------------------------------------------
       
   699 // CCbsReceiverHelper::Database
       
   700 // Returns a reference to the CCbsDbImp instance.
       
   701 // If a topic of the same number already exists
       
   702 // in DB, does nothing.
       
   703 // (other items were commented in a header).
       
   704 // -----------------------------------------------------------------------------
       
   705 //
       
   706 CCbsDbImp& CCbsReceiverHelper::Database() const
       
   707     {
       
   708     return iDatabase;
       
   709     }
       
   710 
       
   711 // -----------------------------------------------------------------------------
       
   712 // CCbsReceiverHelper::TopicsDetected
       
   713 // Returns the number of detected topics.
       
   714 // (other items were commented in a header).
       
   715 // -----------------------------------------------------------------------------
       
   716 //
       
   717 TUint CCbsReceiverHelper::TopicsDetected() const
       
   718     {
       
   719     return iTopicsDetected;
       
   720     }
       
   721 
       
   722 // -----------------------------------------------------------------------------
       
   723 // CCbsReceiverHelper::ClearTopicsDetectedCounter
       
   724 // Sets the counter for detected topics to zero.
       
   725 // (other items were commented in a header).
       
   726 // -----------------------------------------------------------------------------
       
   727 //
       
   728 void CCbsReceiverHelper::ClearTopicsDetectedCounter()
       
   729     {
       
   730     // Clear the variable indicating the amount of detected topics.
       
   731     iTopicsDetected = 0;
       
   732     }
       
   733 
       
   734 // -----------------------------------------------------------------------------
       
   735 // CCbsReceiverHelper::HandleTopicDetectedL
       
   736 // Handles detected topic.
       
   737 // (other items were commented in a header).
       
   738 // -----------------------------------------------------------------------------
       
   739 //
       
   740 TBool CCbsReceiverHelper::HandleTopicDetectedL(
       
   741     const TCbsDbTopicNumber& iTopicNumber )
       
   742     {
       
   743     // Create new topic and initialise it.
       
   744     TCbsDbTopic topic;
       
   745     topic.iNumber = iTopicNumber;
       
   746     topic.iName = KNullDesC;
       
   747     topic.iProtected = EFalse;
       
   748     topic.iSubscribed = EFalse;
       
   749     topic.iHotmarked = EFalse;
       
   750 
       
   751     TBool result( ETrue );
       
   752 
       
   753     // Try to add the topic. If succeeded,
       
   754     // increase counter iTopicsDetected.
       
   755     TRAPD( error, iDatabase.TopicListL().AddTopicL( topic, ETrue ) );
       
   756 
       
   757     if ( error == KErrAlreadyExists )
       
   758         {
       
   759         result = EFalse;
       
   760         }
       
   761     else if ( error != KErrNone && error != KErrAlreadyExists )
       
   762         {
       
   763         User::Leave( error );
       
   764         }
       
   765     else
       
   766         {
       
   767         // Update the detected topics counter
       
   768         iTopicsDetected++;
       
   769         }
       
   770     return result;
       
   771     }
       
   772 
       
   773 // -----------------------------------------------------------------------------
       
   774 // CCbsReceiverHelper::HandleIndexMessageL
       
   775 // Processes an index message and builds a new topic collection
       
   776 // (other items were commented in a header).
       
   777 // -----------------------------------------------------------------------------
       
   778 //
       
   779 void CCbsReceiverHelper::HandleIndexMessageL(
       
   780     const TDesC& aContents,
       
   781     const TBool aIsChildSubIndex )
       
   782     {
       
   783     // Previous topic identities are cleared if a root index message
       
   784     // is received.
       
   785     if ( !aIsChildSubIndex )
       
   786         {
       
   787         iDatabase.TopicCollectionL().Clear();
       
   788         }
       
   789     // Parses topic identities from the index message.
       
   790     // The identities are stored in the current topic collection.
       
   791     // If the index message is corrupt, it should still be stored,
       
   792     // so trap the error.
       
   793     TLex lex( aContents );
       
   794     TRAPD( error, ParseMessageFormatL( lex, iDatabase.TopicCollectionL() ) );
       
   795     switch ( error )
       
   796         {
       
   797         case KErrNone:
       
   798             // If the message all went fine, apply.
       
   799             // The topic identities are written into persistent memory.
       
   800             iDatabase.TopicCollectionL().Apply();
       
   801             break;
       
   802 
       
   803         case KErrCorrupt:
       
   804             // Do not react on corrupt messages.
       
   805             break;
       
   806 
       
   807         default:
       
   808             // All other errors will prevent saving the message.
       
   809             User::Leave( error );
       
   810             break;
       
   811         }
       
   812     }
       
   813 
       
   814 // -----------------------------------------------------------------------------
       
   815 // CCbsReceiverHelper::ParseTopicIdentitiesL
       
   816 // Parses all topic identities from aText which is assumed to be
       
   817 // an index message's content.
       
   818 // (other items were commented in a header).
       
   819 // -----------------------------------------------------------------------------
       
   820 //
       
   821 void CCbsReceiverHelper::ParseTopicIdentitiesL(
       
   822         const TDesC& aText )
       
   823     {
       
   824     // Create a lexer and pass it to the parser
       
   825     TLex lex( aText );
       
   826 
       
   827     ParseMessageFormatL( lex, iDatabase.TopicCollectionL() );
       
   828     }
       
   829 
       
   830 // -----------------------------------------------------------------------------
       
   831 // CCbsReceiverHelper::LaunchMessageSoftNotificationL
       
   832 // Requests to launch a soft notification.
       
   833 // (other items were commented in a header).
       
   834 // -----------------------------------------------------------------------------
       
   835 //
       
   836 void CCbsReceiverHelper::LaunchMessageSoftNotificationL( const TBool aPlayTone )
       
   837     {
       
   838     TInt numberOfHotMsgs( 0 );
       
   839     numberOfHotMsgs = iDatabase.TopicListL().UnreadHotmarkedMessageCount();
       
   840 
       
   841     CAknSoftNotifier* notifier = CAknSoftNotifier::NewLC(); // on CS
       
   842 
       
   843     TurnLightsOn();
       
   844 
       
   845     if ( aPlayTone )
       
   846         {
       
   847         PlayCbsTone();
       
   848         }
       
   849 
       
   850     notifier->SetNotificationCountL( ECellBroadcastNotification, numberOfHotMsgs );
       
   851     CleanupStack::PopAndDestroy( notifier );
       
   852     }
       
   853 
       
   854 // -----------------------------------------------------------------------------
       
   855 // CCbsReceiverHelper::LaunchMessageImmediateDisplay
       
   856 // Requests to show the message immediately.
       
   857 // (other items were commented in a header).
       
   858 // -----------------------------------------------------------------------------
       
   859 //
       
   860 void CCbsReceiverHelper::LaunchMessageImmediateDisplay(
       
   861     const TCbsDbMessage& aMessage )
       
   862     {
       
   863     TUid uiViewUid( TUid::Uid( ECbsUiMsgViewId ) );
       
   864     TVwsViewId id( KUidCbsUiappApp, uiViewUid );
       
   865     TPckgBuf<TCbsMessageHandle> pckg( aMessage.iHandle );
       
   866 
       
   867     // Ignore result value.
       
   868     iVwsSession->CreateActivateViewEvent( id, KCbsImmediateMessageId, pckg );
       
   869     }
       
   870 
       
   871 // -----------------------------------------------------------------------------
       
   872 // CCbsReceiverHelper::TurnLightsOn
       
   873 // Turns lights on
       
   874 // -----------------------------------------------------------------------------
       
   875 //
       
   876 void CCbsReceiverHelper::TurnLightsOn()
       
   877     {
       
   878      // Change the bit on and off. SysAp will detect that
       
   879      // the lights should be switched on for the specified time.
       
   880      RProperty::Set(KPSUidCoreApplicationUIs, KLightsControl, ELightsOn);
       
   881      RProperty::Set(KPSUidCoreApplicationUIs, KLightsControl, ELightsOff);
       
   882     }
       
   883 
       
   884 // -----------------------------------------------------------------------------
       
   885 // CCbsReceiverHelper::PlayCbsTone
       
   886 // Plays a tone
       
   887 // -----------------------------------------------------------------------------
       
   888 //
       
   889 void CCbsReceiverHelper::PlayCbsTone()
       
   890     {
       
   891     RProperty::Define( KPSUidNcnList, KNcnPlayAlertTone, RProperty::EInt,
       
   892         ECapability_None , ECapabilityWriteDeviceData );
       
   893     RProperty::Set( KPSUidNcnList, KNcnPlayAlertTone, KCbsMessageTone );
       
   894     }
       
   895 
       
   896 // ================= OTHER EXPORTED FUNCTIONS ==============
       
   897 
       
   898 //  End of File
       
   899