mmsengine/mmsserversettings/src/mmssettings.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
child 57 ebe688cedc25
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2004-2007 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:  mmssettings implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19    
       
    20 // INCLUDE FILES   
       
    21 #include <centralrepository.h>
       
    22 #include <msvids.h>
       
    23 #include <msvapi.h>
       
    24 #include <messaginginternalcrkeys.h>
       
    25 
       
    26 // USERINCLUDE FILES
       
    27 #include "mmssettings.h"
       
    28 #include "mmsconst.h"
       
    29 #include "mmserrors.h"
       
    30 #include "MmsEnginePrivateCRKeys.h"
       
    31 #include "mmsdebuglogging.h"
       
    32 #include "mmsmessagestoreutils.h"
       
    33 #include "mmsconninit.h"
       
    34 #include "mmsversion.h"
       
    35 
       
    36 // EXTERNAL DATA STRUCTURES
       
    37 
       
    38 // EXTERNAL FUNCTION PROTOTYPES  
       
    39 
       
    40 // CONSTANTS
       
    41 _LIT( KMmsApplicationFolder, "MmsApplication");
       
    42 // MACROS
       
    43 
       
    44 // LOCAL CONSTANTS AND MACROS
       
    45 const TInt KMmsSettingsVersion = 30; // secure version
       
    46 const TInt KMmsSecondsInAnHour = 3600;
       
    47 #ifdef __WINS__
       
    48 const TInt KMmsRowBufferLength = 128;
       
    49 #endif
       
    50 
       
    51 
       
    52 // MODULE DATA STRUCTURES
       
    53 
       
    54 // LOCAL FUNCTION PROTOTYPES
       
    55 
       
    56 // ============================== LOCAL FUNCTIONS ==============================
       
    57 
       
    58 // ============================== MEMBER FUNCTIONS =============================
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CMmsSettings::CMmsSettings
       
    62 // C++ default constructor can NOT contain any code, that
       
    63 // might leave.
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 CMmsSettings::CMmsSettings()   
       
    67     {
       
    68 #ifdef __WINS__
       
    69     iLocalModeInDir = KMmsDefaultLocalModeDir;
       
    70     iLocalModeOutDir = KMmsDefaultLocalModeDir;    
       
    71 #else
       
    72     iLocalModeDir = NULL;
       
    73 #endif
       
    74     }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CMmsSettings::ConstructL
       
    78 // Symbian 2nd phase constructor can leave.
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 void CMmsSettings::ConstructL()
       
    82     {
       
    83     LOG(_L("CMmsSettings::ConstructL"));
       
    84     Reset();
       
    85     
       
    86     // member iMmsRepository is created only when needed    
       
    87 #ifdef __WINS__
       
    88     ReadLocalModeDirectoriesL();
       
    89 #endif // __WINS__
       
    90     }
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CMmsSettings::NewL
       
    94 // Two-phased constructor.
       
    95 // -----------------------------------------------------------------------------
       
    96 //
       
    97 EXPORT_C CMmsSettings* CMmsSettings::NewL()
       
    98     {
       
    99     CMmsSettings* self = new ( ELeave ) CMmsSettings;
       
   100     CleanupStack::PushL( self );
       
   101     self->ConstructL();
       
   102     CleanupStack::Pop( self );
       
   103     return self;
       
   104     }
       
   105     
       
   106 // -----------------------------------------------------------------------------
       
   107 // Destructor
       
   108 // -----------------------------------------------------------------------------
       
   109 //
       
   110 CMmsSettings::~CMmsSettings()
       
   111     {
       
   112     LOG(_L("~CMmsSettings"));
       
   113     delete iMmsRepository;
       
   114    
       
   115 #ifndef __WINS__
       
   116     // local mode directory is a pointer in hardware only
       
   117     delete iLocalModeDir;
       
   118 #endif    
       
   119     iAccesspointArray.Close();
       
   120     }
       
   121 
       
   122 // -----------------------------------------------------------------------------
       
   123 // Reset
       
   124 // -----------------------------------------------------------------------------
       
   125 //
       
   126 EXPORT_C void CMmsSettings::Reset()
       
   127     {
       
   128     LOG(_L("CMmsSettings::Reset"));
       
   129     iSettingsVersion =        KMmsSettingsVersion;
       
   130     
       
   131     // This is the version number to be used if none is found from
       
   132     // central repository, or if the value in central repository is illegal
       
   133     iMmsVersion = KMmsDefaultVersion;
       
   134     
       
   135     iDefaultServiceId =       KMsvNullIndexEntryId;
       
   136     iNotificationFolderId =   KMsvNullIndexEntryId;
       
   137     iMMBoxFolderId =          KMsvNullIndexEntryId;
       
   138     iApplicationFolderId =    KMsvNullIndexEntryId;
       
   139     iAccesspointArray.Reset();
       
   140     iReceivingModeHome =      EMmsReceivingAutomatic;
       
   141     iReceivingModeForeign =   EMmsReceivingManual;
       
   142     iAcceptPersonal =         ETrue;
       
   143     iAcceptAdvertisement =    ETrue;
       
   144     iAcceptInformational =    ETrue;
       
   145     iAcceptAnonymous =        ETrue;
       
   146     iDeliveryReportWanted =   KMmsNo;
       
   147     iDeliveryReportAllowed =  KMmsYes;
       
   148     iReadReplyReportWanted =  KMmsNo;
       
   149     iReadReplyReportAllowed = ETrue;
       
   150     iMessageClass =           EMmsClassPersonal;
       
   151     iExpiryInterval =         0;
       
   152     iSenderVisibility =       EMmsSenderVisibilityDefault;
       
   153     iMessagePriority =        EMmsPriorityNormal;
       
   154     iMaxSendSize =            KMmsMaxSendSize;
       
   155     iMaxReceiveSize =         KMmsMaxReceiveSize;
       
   156     iImageWidth =             0;
       
   157     iImageHeight =            0;
       
   158     iMoveToSent =             ETrue;
       
   159     iLogEmailRecipients =     EFalse;
       
   160     iExpiryOvershoot =        KMmsExpiryOvershoot;
       
   161     iCreationMode =           EMmsCreationModeWarning;
       
   162     iFetchOverride =          EFalse;
       
   163     iShowSentTime =           EFalse;
       
   164     
       
   165 #ifdef __WINS__
       
   166     iLocalMode =              ETrue;
       
   167 #else
       
   168     iLocalMode =              EFalse;
       
   169     delete iLocalModeDir;
       
   170     iLocalModeDir = NULL;
       
   171 #endif // __WINS__
       
   172     
       
   173     }
       
   174 
       
   175 // -----------------------------------------------------------------------------
       
   176 // CopyL
       
   177 // -----------------------------------------------------------------------------
       
   178 //
       
   179 EXPORT_C void CMmsSettings::CopyL( const CMmsSettings& aMmsSettings )
       
   180     {
       
   181     LOG(_L("CMmsSettings::Copy"));
       
   182 #ifdef __WINS__
       
   183     iLocalModeInDir  = aMmsSettings.iLocalModeInDir;
       
   184     iLocalModeOutDir = aMmsSettings.iLocalModeOutDir;
       
   185 #else
       
   186     iLocalModeDir = NULL;
       
   187     if ( aMmsSettings.iLocalModeDir )
       
   188         {
       
   189         iLocalModeDir = aMmsSettings.iLocalModeDir->AllocL();
       
   190         }
       
   191 #endif
       
   192     iSettingsVersion = aMmsSettings.SettingsVersion();
       
   193     iMmsVersion = aMmsSettings.MmsVersion();
       
   194     iDefaultServiceId = aMmsSettings.Service();
       
   195     iNotificationFolderId = aMmsSettings.NotificationFolder();
       
   196     iMMBoxFolderId = aMmsSettings.MMBoxFolder();
       
   197     iApplicationFolderId = aMmsSettings.ApplicationFolder();      
       
   198     iReceivingModeHome = aMmsSettings.ReceivingModeHome(); 
       
   199     iReceivingModeForeign = aMmsSettings.ReceivingModeForeign();
       
   200     iAcceptPersonal = aMmsSettings.AcceptPersonalMessages();
       
   201     iAcceptAdvertisement = aMmsSettings.AcceptAdvertisementMessages();
       
   202     iAcceptInformational = aMmsSettings.AcceptInformationalMessages();
       
   203     iAcceptAnonymous = aMmsSettings.AcceptAnonymousMessages();
       
   204     iDeliveryReportWanted = aMmsSettings.DeliveryReportWanted();
       
   205     iDeliveryReportAllowed = aMmsSettings.DeliveryReportSendingAllowed();
       
   206     iReadReplyReportWanted = aMmsSettings.ReadReplyReportWanted();
       
   207     iReadReplyReportAllowed = aMmsSettings.ReadReplyReportSendingAllowed();
       
   208     iMessageClass = aMmsSettings.MessageClass();
       
   209     iExpiryInterval = aMmsSettings.ExpiryInterval();
       
   210     iSenderVisibility = aMmsSettings.SenderVisibility();
       
   211     iMessagePriority = aMmsSettings.MessagePriority();
       
   212     iMaxSendSize = aMmsSettings.MaximumSendSize();
       
   213     iMaxReceiveSize = aMmsSettings.MaximumReceiveSize();
       
   214     iImageWidth = aMmsSettings.ImageWidth();
       
   215     iImageHeight = aMmsSettings.ImageHeight();
       
   216     iMoveToSent = aMmsSettings.MoveToSent();
       
   217     iLogEmailRecipients = aMmsSettings.LogEmailRecipients();
       
   218     iExpiryOvershoot = aMmsSettings.ExpiryOvershoot();    
       
   219     iCreationMode = aMmsSettings.CreationMode();
       
   220     iFetchOverride = aMmsSettings.FetchOverride();
       
   221     iLocalMode = aMmsSettings.LocalMode();
       
   222     iShowSentTime = aMmsSettings.ShowSentTime();
       
   223 
       
   224     LOG(_L("- removing old ap array"));
       
   225     iAccesspointArray.Reset();
       
   226     
       
   227     for( TInt index = 0; index < aMmsSettings.AccessPointCount(); index++ )
       
   228         {
       
   229         LOG2(_L("- copying index %d"), index );
       
   230         User::LeaveIfError( 
       
   231             iAccesspointArray.Append( aMmsSettings.AccessPoint( index ) ) );        
       
   232         }
       
   233     }
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // LoadSettingsL
       
   237 // -----------------------------------------------------------------------------
       
   238 //
       
   239 EXPORT_C void CMmsSettings::LoadSettingsL()
       
   240     {
       
   241     LOG(_L("CMmsSettings::LoadSettingsL"));
       
   242 
       
   243     // Connect CenRep if needed
       
   244     if( !iMmsRepository )
       
   245         {
       
   246         iMmsRepository = ConnectCenRepL( KUidMmsServerMtm );
       
   247         }
       
   248         
       
   249     // default values for any keys that are not found in CenRep    
       
   250     Reset();
       
   251 
       
   252     //
       
   253     // Start reading the settings
       
   254     // If reading of a setting fails -> original value will remain
       
   255     //
       
   256     LOG(_L("- loading regular settings"));
       
   257     TInt temp = 0;
       
   258     TInt retval = 0;
       
   259     
       
   260     // Following are stored as integer codes
       
   261     retval = iMmsRepository->Get( KMmsEngineSettingsVersion, temp );
       
   262     if( retval == KErrNone ) iSettingsVersion = temp;
       
   263     retval = iMmsRepository->Get( KMmsEngineDefaultServiceId, temp );
       
   264     if( retval == KErrNone ) iDefaultServiceId = (TMsvId) temp;
       
   265     retval = iMmsRepository->Get( KMmsEngineNotificationFolderId, temp );
       
   266     if( retval == KErrNone ) iNotificationFolderId = (TMsvId) temp;
       
   267     retval = iMmsRepository->Get( KMmsEngineMMBoxFolderId, temp );
       
   268     if( retval == KErrNone ) iMMBoxFolderId = (TMsvId) temp;
       
   269     retval = iMmsRepository->Get( KMmsEngineApplicationFolderId, temp );
       
   270     if( retval == KErrNone ) iApplicationFolderId = (TMsvId) temp;
       
   271     retval = iMmsRepository->Get( KMmsEngineReceivingModeHome, temp );
       
   272     if( retval == KErrNone ) iReceivingModeHome = temp;
       
   273     retval = iMmsRepository->Get( KMmsEngineReceivingModeForeign, temp );
       
   274     if( retval == KErrNone ) iReceivingModeForeign = temp;
       
   275     retval = iMmsRepository->Get( KMmsEngineMessageClass, temp );
       
   276     if( retval == KErrNone ) iMessageClass = temp;
       
   277     retval = iMmsRepository->Get( KMmsEngineMessagePriority, temp );
       
   278     if( retval == KErrNone ) iMessagePriority = temp;
       
   279     // change expiry interval from hours to seconds
       
   280     retval = iMmsRepository->Get( KMmsEngineExpiryInterval, temp );
       
   281     if( retval == KErrNone ) iExpiryInterval = temp * KMmsSecondsInAnHour;
       
   282     retval = iMmsRepository->Get( KMmsEngineExpiryOvershoot, temp );
       
   283     if( retval == KErrNone ) iExpiryOvershoot = temp;
       
   284     retval = iMmsRepository->Get( KMmsEngineSenderVisibility, temp );
       
   285     if( retval == KErrNone ) iSenderVisibility = temp;
       
   286     retval = iMmsRepository->Get( KMmsEngineMaximumSendSize, temp );
       
   287     if( retval == KErrNone ) iMaxSendSize = temp;
       
   288     retval = iMmsRepository->Get( KMmsEngineMaximumReceiveSize, temp );
       
   289     if( retval == KErrNone ) iMaxReceiveSize = temp;
       
   290     retval =  iMmsRepository->Get( KMmsEngineImageWidth, temp );
       
   291     if( retval == KErrNone ) iImageWidth = temp;
       
   292     retval = iMmsRepository->Get( KMmsEngineImageHeight, temp );
       
   293     if( retval == KErrNone ) iImageHeight = temp;
       
   294 	retval = iMmsRepository->Get( KMmsEngineCreationMode, temp );
       
   295 	if( retval == KErrNone ) iCreationMode = temp;
       
   296     retval = iMmsRepository->Get( KMmsEngineDeliveryReportWanted, temp );
       
   297     if( retval == KErrNone ) iDeliveryReportWanted = temp;
       
   298     retval = iMmsRepository->Get( KMmsEngineDeliveryReportSendingAllowed, temp );
       
   299     if( retval == KErrNone ) iDeliveryReportAllowed = temp;
       
   300     retval = iMmsRepository->Get( KMmsEngineReadReplyReportWanted, temp );
       
   301     if( retval == KErrNone ) iReadReplyReportWanted = temp;
       
   302 	// Following are stored as boolean
       
   303     retval = iMmsRepository->Get( KMmsEngineReadReplyReportSendingAllowed, temp );
       
   304     if( retval == KErrNone ) iReadReplyReportAllowed = temp;
       
   305     retval = iMmsRepository->Get( KMmsEngineLogEmailRecipients, temp );
       
   306     if( retval == KErrNone ) iLogEmailRecipients = temp;
       
   307     retval = iMmsRepository->Get( KMmsEngineAllowPersonal, temp );
       
   308     if( retval == KErrNone ) iAcceptPersonal = temp;
       
   309     retval = iMmsRepository->Get( KMmsEngineAllowAdvertisement, temp );
       
   310     if( retval == KErrNone ) iAcceptAdvertisement = temp;
       
   311     retval = iMmsRepository->Get( KMmsEngineAllowInformational, temp );
       
   312     if( retval == KErrNone ) iAcceptInformational = temp;
       
   313     retval = iMmsRepository->Get( KMmsEngineAllowAnonymous, temp );
       
   314     if( retval == KErrNone ) iAcceptAnonymous = temp;
       
   315     retval = iMmsRepository->Get( KMmsEngineLocalMode, temp );
       
   316     if( retval == KErrNone ) iLocalMode = temp;
       
   317     retval = iMmsRepository->Get( KMmsEngineShowSentTime, temp );
       
   318     if ( retval == KErrNone )
       
   319         {
       
   320         iShowSentTime = temp;
       
   321         }
       
   322       
       
   323     // MMS encapsulation version variation is in central repository
       
   324     // We check limits to prevent someone trying to define illegal values
       
   325     retval = iMmsRepository->Get( KMmsOmaEncapsulationVersion, temp );
       
   326     if ( retval == KErrNone &&
       
   327         temp >= KMmsMinimumSupportedVersion &&
       
   328         temp <= KMmsMaximumSupportedVersion )
       
   329         {
       
   330         iMmsVersion = temp;
       
   331         }
       
   332  
       
   333     
       
   334 	// This setting is always created and maintained "on the fly"
       
   335     iFetchOverride = EFalse;
       
   336 
       
   337     // AP settings are very important:
       
   338     //   if some key/value is not found, a leave will occur.
       
   339     iAccesspointArray.Reset();
       
   340     TInt arrayLength = 0;
       
   341     TInt value = 0;
       
   342     // cannot leave even if error: if no access points, count is 0
       
   343     retval = iMmsRepository->Get( KMmsEngineAccessPointCount, arrayLength ) ;
       
   344     if ( retval == KErrNotFound )
       
   345         {
       
   346         SaveSetting( KMmsEngineAccessPointCount, 0 );
       
   347         }
       
   348     LOG2(_L("- Loading AP array of length %d"), arrayLength );
       
   349     for( TInt index = 0; index < arrayLength; index++ )
       
   350         {
       
   351         retval = iMmsRepository->Get( KMmsAccesspointArrayBase + index, value ) ;
       
   352         if ( retval == KErrNone )
       
   353             {
       
   354             // If we are out of memory, appending the element may fail.
       
   355             User::LeaveIfError( iAccesspointArray.Append( value ) );
       
   356             // array index is safe if the appending succeeded
       
   357             LOG3(_L("- array[%d] == %d"), index, iAccesspointArray[ index ] );
       
   358             }
       
   359         else
       
   360             {
       
   361             LOG3(_L("- Loading AP array item %d returned error %d"), index, retval );
       
   362             }
       
   363         }
       
   364     // Clean up
       
   365     delete iMmsRepository;
       
   366     iMmsRepository = NULL;
       
   367 
       
   368     //
       
   369     // Read MoveToSent setting from general messaging repository
       
   370     //
       
   371     LOG(_L("- Reading SentItemsInUse key from different repository"));
       
   372     TRAP( retval, iMmsRepository = ConnectCenRepL( KCRUidMuiuSettings ) );
       
   373     if( retval == KErrNone && iMmsRepository )
       
   374         {
       
   375         retval = iMmsRepository->Get( KMuiuSentItemsInUse, temp );
       
   376         if( retval == KErrNone )
       
   377             {
       
   378             iMoveToSent = temp;
       
   379             }                
       
   380         }
       
   381     // Clean up
       
   382     delete iMmsRepository;
       
   383     iMmsRepository = NULL;
       
   384 
       
   385     LOG(_L("- settings loaded"));
       
   386     
       
   387 #ifdef _DEBUG
       
   388     DebugLogSettings();
       
   389 #endif
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // SaveSettingsL
       
   394 // -----------------------------------------------------------------------------
       
   395 //
       
   396 EXPORT_C void CMmsSettings::SaveSettingsL()
       
   397     {
       
   398     LOG(_L("CMmsSettings::SaveSettingsL"));
       
   399     
       
   400     // Connect CenRep if needed
       
   401     if( !iMmsRepository )
       
   402         {
       
   403         iMmsRepository = ConnectCenRepL( KUidMmsServerMtm );
       
   404         }
       
   405         
       
   406     // MMS Encapsulation version is read-only, cannot be saved.    
       
   407 
       
   408     SaveSetting( KMmsEngineDefaultServiceId, iDefaultServiceId );
       
   409     SaveSetting( KMmsEngineNotificationFolderId, iNotificationFolderId );
       
   410     SaveSetting( KMmsEngineMMBoxFolderId, iMMBoxFolderId );
       
   411     SaveSetting( KMmsEngineApplicationFolderId, iApplicationFolderId );
       
   412     SaveSetting( KMmsEngineReceivingModeHome, iReceivingModeHome );
       
   413     SaveSetting( KMmsEngineReceivingModeForeign, iReceivingModeForeign );
       
   414     SaveSetting( KMmsEngineMessageClass, iMessageClass );
       
   415     SaveSetting( KMmsEngineMessagePriority, iMessagePriority );
       
   416     // Change expiry interval from seconds to hours
       
   417     SaveSetting( KMmsEngineExpiryInterval, iExpiryInterval / KMmsSecondsInAnHour );
       
   418     SaveSetting( KMmsEngineSenderVisibility, iSenderVisibility );
       
   419     SaveSetting( KMmsEngineImageWidth, iImageWidth );
       
   420     SaveSetting( KMmsEngineImageHeight, iImageHeight );
       
   421     SaveSetting( KMmsEngineCreationMode, iCreationMode );
       
   422     SaveSetting( KMmsEngineDeliveryReportWanted, iDeliveryReportWanted );
       
   423     SaveSetting( KMmsEngineDeliveryReportSendingAllowed, iDeliveryReportAllowed );
       
   424     SaveSetting( KMmsEngineReadReplyReportWanted, iReadReplyReportWanted );
       
   425     SaveSetting( KMmsEngineReadReplyReportSendingAllowed, iReadReplyReportAllowed );
       
   426     SaveSetting( KMmsEngineLogEmailRecipients, iLogEmailRecipients );
       
   427     SaveSetting( KMmsEngineAllowPersonal, iAcceptPersonal );
       
   428     SaveSetting( KMmsEngineAllowAdvertisement, iAcceptAdvertisement );
       
   429     SaveSetting( KMmsEngineAllowInformational, iAcceptInformational );
       
   430     SaveSetting( KMmsEngineAllowAnonymous, iAcceptAnonymous );
       
   431     SaveSetting( KMmsEngineLocalMode, iLocalMode );
       
   432 
       
   433     // AP array
       
   434     SaveAccesspointArrayL();
       
   435 
       
   436     // Clean up
       
   437     delete iMmsRepository;
       
   438     iMmsRepository = NULL;
       
   439     
       
   440     LOG(_L("- saving OK"));
       
   441     }
       
   442 
       
   443 // -----------------------------------------------------------------------------
       
   444 // AccessPoint
       
   445 // -----------------------------------------------------------------------------
       
   446 //
       
   447 EXPORT_C TInt32 CMmsSettings::AccessPoint( TInt aIndex ) const
       
   448     {
       
   449     if( aIndex < 0 || aIndex >= iAccesspointArray.Count() )
       
   450         {
       
   451         return KErrNotFound;
       
   452         }
       
   453     return iAccesspointArray[ aIndex ];
       
   454     }
       
   455 
       
   456 // -----------------------------------------------------------------------------
       
   457 // SaveSetting
       
   458 //
       
   459 // This internal method must be called under condition that connection
       
   460 // to CenRep exists
       
   461 //
       
   462 // -----------------------------------------------------------------------------
       
   463 //
       
   464 void CMmsSettings::SaveSetting( TUint32 aKey, TInt aValue )
       
   465     {
       
   466     // If the setting does not exist, it is automatically created
       
   467     // It will never return "KErrNotFound"
       
   468     // On failure the repository is unmodified.
       
   469     // The saving will fail if capacity is not sufficient.
       
   470     TInt retval = iMmsRepository->Set( aKey, aValue );
       
   471     if( retval != KErrNone ) // retval is also not equal to KErrNotFound
       
   472         {
       
   473         LOG3( _L("-ERROR saving setting %d: %d"), aKey, retval );
       
   474         }
       
   475     }
       
   476 
       
   477 // -----------------------------------------------------------------------------
       
   478 // SaveAccesspointArrayL
       
   479 //
       
   480 // This internal method must be called under condition that connection
       
   481 // to CenRep exists
       
   482 //
       
   483 // -----------------------------------------------------------------------------
       
   484 //
       
   485 void CMmsSettings::SaveAccesspointArrayL()
       
   486     {
       
   487     LOG(_L("CMmsSettings::SaveAccesspointArrayL"));
       
   488     
       
   489     // Compare array lengths in CenRep and in memory
       
   490     TInt origCRArrayCount = 0;
       
   491     User::LeaveIfError( iMmsRepository->Get( KMmsEngineAccessPointCount, origCRArrayCount ) );
       
   492     TInt localArrayCount = iAccesspointArray.Count();
       
   493     // If CenRep array is longer -> delete extra elements from it
       
   494     for( TInt index = localArrayCount; index < origCRArrayCount; index++ )
       
   495         {
       
   496         LOG(_L("- deleting extra element from CenRep"));
       
   497         iMmsRepository->Delete( KMmsAccesspointArrayBase + index );
       
   498         }
       
   499         
       
   500     // Now arrays have the same length OR localarray is longer
       
   501     // (i.e. elements have been added)
       
   502 
       
   503     // Save new array length to CenRep
       
   504     LOG2(_L("- saving AP array of length (%d)"), localArrayCount );
       
   505     SaveSetting( KMmsEngineAccessPointCount, localArrayCount );
       
   506     
       
   507     // Save the array itself
       
   508     for( TInt index = 0; index < localArrayCount; index++ )
       
   509         {
       
   510         SaveSetting( KMmsAccesspointArrayBase + index, (TInt)iAccesspointArray[ index ] ); 
       
   511         LOG3(_L("- saved array[%d] with value %d"), index, iAccesspointArray[ index ]);
       
   512         }
       
   513     }
       
   514 
       
   515 // -----------------------------------------------------------------------------
       
   516 // ValidateSettings
       
   517 // -----------------------------------------------------------------------------
       
   518 //
       
   519 EXPORT_C TInt CMmsSettings::ValidateSettings()
       
   520     {
       
   521     LOG(_L("CMmsSettings::ValidateSettings"));
       
   522     //
       
   523     // Check basic settings and return error if something is NOK
       
   524     //
       
   525     if( iExpiryInterval < 0 || 
       
   526         iExpiryInterval > KMmsMaxExpiry )
       
   527         {
       
   528         LOG(_L("- NOK: iExpiryInterval"));
       
   529         return KMmsErrorInvalidSettings;
       
   530         }
       
   531     if( iSenderVisibility != 0 &&
       
   532         ( iSenderVisibility < EMmsMinimumSenderVisibility || 
       
   533           iSenderVisibility > EMmsMaximumSenderVisibility ) )
       
   534         {
       
   535         LOG(_L("- NOK: iSenderVisibility"));
       
   536         return KMmsErrorInvalidSettings;
       
   537         }
       
   538 
       
   539     if( iDeliveryReportWanted != KMmsYes && 
       
   540         iDeliveryReportWanted != KMmsNo )
       
   541         {
       
   542         LOG(_L("- NOK: iDeliveryReportWanted"));
       
   543         return KMmsErrorInvalidSettings;
       
   544         }
       
   545     if( iDeliveryReportAllowed != KMmsYes && 
       
   546         iDeliveryReportAllowed != KMmsNo )
       
   547         {
       
   548         LOG(_L("- NOK: iDeliveryReportAllowed"));
       
   549         return KMmsErrorInvalidSettings;
       
   550         }
       
   551     if( iReadReplyReportWanted != KMmsYes && 
       
   552         iReadReplyReportWanted != KMmsNo )
       
   553         {
       
   554         LOG(_L("- NOK: iReadReplyReportWanted"));
       
   555         return KMmsErrorInvalidSettings;
       
   556         }
       
   557     if( iReceivingModeHome < EMmsReceivingMin || 
       
   558         iReceivingModeHome > EMmsReceivingMax )
       
   559         {
       
   560         LOG(_L("- NOK: iReceivingModeHome"));
       
   561         return KMmsErrorInvalidSettings;
       
   562         }
       
   563     if( iReceivingModeForeign < EMmsReceivingMin ||
       
   564         iReceivingModeForeign > EMmsReceivingMax )
       
   565         {
       
   566         LOG(_L("- NOK: iReceivingModeForeign"));
       
   567         return KMmsErrorInvalidSettings;
       
   568         }
       
   569     if( iMessagePriority < EMmsMinimumPriority || 
       
   570         iMessagePriority > EMmsMaximumPriority )
       
   571         {
       
   572         LOG(_L("- NOK: iMessagePriority"));
       
   573         return KMmsErrorInvalidSettings;
       
   574         }
       
   575     if( iMessageClass < EMmsMimimumMessageClass ||
       
   576         iMessageClass > EMmsMaximumMessageClass )
       
   577         {
       
   578         LOG(_L("- NOK: iMessageClass"));
       
   579         return KMmsErrorInvalidSettings;
       
   580         }
       
   581         
       
   582     //
       
   583     // Check AP Array (not checked in localmode)
       
   584     //
       
   585     TInt error = KErrNone;
       
   586     if( !LocalMode() )
       
   587         {
       
   588         if( iAccesspointArray.Count() == 0 )
       
   589             {
       
   590             LOG(_L("- NOK: AP array length == 0"));
       
   591             error = KMmsErrorNoWAPAccessPoint;
       
   592             }
       
   593         else // AP array not empty:
       
   594             {
       
   595             
       
   596             // Accesspoint array is checked by CMmsConnectionInitiator
       
   597             // All defined accesspoints should contain proper values in CommDb
       
   598             
       
   599             for( TInt index = 0; index < iAccesspointArray.Count(); index++ )
       
   600                 {
       
   601                 TUint32 ap = 0;
       
   602                 HBufC* serverUri = NULL;
       
   603                 HBufC8* proxyAddress = NULL;
       
   604                 TBool proxyInUse = EFalse;
       
   605                 TRAP( error, CMmsConnectionInitiator::GetParametersL(
       
   606                     (TUint32)iAccesspointArray[ index ],
       
   607                     ap,
       
   608                     serverUri,
       
   609                     proxyInUse,
       
   610                     proxyAddress ) );
       
   611                 if( error == KErrNone ) // call did not leave                   
       
   612                     {
       
   613                     if ( ap == 0 )
       
   614                         {
       
   615                         error = KMmsErrorAP1Invalid;
       
   616                         }
       
   617                     else if ( !serverUri )
       
   618                         {
       
   619                         error = KMmsErrorNoURI1;
       
   620                         }
       
   621                     else if ( serverUri->Length() == 0 )
       
   622                         {
       
   623                         error = KMmsErrorNoURI1;
       
   624                         }
       
   625                     else
       
   626                         {
       
   627                         // keep LINT happy.
       
   628                         }
       
   629                     }
       
   630                 if( serverUri )
       
   631                     {
       
   632                     delete serverUri;
       
   633                     }
       
   634                 if( proxyAddress )
       
   635                     {
       
   636                     delete proxyAddress;
       
   637                     }
       
   638                 if( error != KErrNone )
       
   639                     {
       
   640                     return error;
       
   641                     }
       
   642                 } // for loop
       
   643             }
       
   644         }
       
   645     return error;
       
   646     }
       
   647         
       
   648 // -----------------------------------------------------------------------------
       
   649 // RestoreFactorySettingsL
       
   650 // -----------------------------------------------------------------------------
       
   651 
       
   652 EXPORT_C void CMmsSettings::RestoreFactorySettingsL(
       
   653     CMsvSession& aSession, TMmsFactorySettingsLevel /* aLevel */  )
       
   654     {
       
   655     LOG(_L("CMmsSettings::RestoreFactorySettingsL "));
       
   656         
       
   657     // Connect CenRep
       
   658     if( !iMmsRepository )
       
   659         {
       
   660         iMmsRepository = ConnectCenRepL( KUidMmsServerMtm );
       
   661         }
       
   662 
       
   663     // Reset the repository
       
   664     LOG(_L("- reseting repository"));
       
   665     iMmsRepository->Reset();
       
   666     
       
   667     CreateNewServiceL( aSession );
       
   668     
       
   669     // LoadSettings resets any undefined values to hard-coded defaults
       
   670     LoadSettingsL();
       
   671     
       
   672 #ifdef __WINS__
       
   673 	// Connect CenRep
       
   674     if( !iMmsRepository )
       
   675         {
       
   676         iMmsRepository = ConnectCenRepL( KUidMmsServerMtm );
       
   677         }
       
   678     iLocalMode = ETrue;
       
   679     SaveSetting( KMmsEngineLocalMode, iLocalMode );
       
   680 #endif // __WINS__    
       
   681     
       
   682     // Clean up
       
   683     delete iMmsRepository;
       
   684     iMmsRepository = NULL;
       
   685     }
       
   686 
       
   687 // -----------------------------------------------------------------------------
       
   688 // AddAccessPointL
       
   689 // -----------------------------------------------------------------------------
       
   690 //
       
   691 EXPORT_C void CMmsSettings::AddAccessPointL( TUint32 aAccessPointId, TInt aIndex )
       
   692     {
       
   693     LOG3(_L("CMmsSettings::AddAccessPointL: array[%d] = %d"), aIndex, aAccessPointId );
       
   694     // Basic checks for the arguments
       
   695     // aAccessPoint can't be negative as it is TUint32
       
   696     if( aIndex < 0 || aAccessPointId == 0)
       
   697         {
       
   698         LOG(_L("- KErrArgument"));
       
   699         User::Leave( KErrArgument );
       
   700         }
       
   701         
       
   702     // If index points past the current array, insert new id as last one
       
   703     TInt count = iAccesspointArray.Count();
       
   704     if( aIndex > count )
       
   705         {
       
   706         LOG(_L("- index too big, adjusting.."));
       
   707         aIndex = count;
       
   708         }
       
   709 
       
   710     // If the same reference already exists, ignore adding and just return
       
   711     for(TInt index = 0; index < count; index++ )
       
   712         {
       
   713         if( iAccesspointArray[ index ] == aAccessPointId )
       
   714             {
       
   715             LOG(_L("- reference already in the array, not adding."));
       
   716             return;
       
   717             }
       
   718         }
       
   719     
       
   720     // Add
       
   721     iAccesspointArray.Insert( aAccessPointId, aIndex );
       
   722     }
       
   723 
       
   724 // -----------------------------------------------------------------------------
       
   725 // DeleteAccessPointL
       
   726 // -----------------------------------------------------------------------------
       
   727 //
       
   728 EXPORT_C void CMmsSettings::DeleteAccessPointL( TInt aIndex )
       
   729     {
       
   730     LOG2(_L("CMmsSettings::DeleteAccessPointL: array[%d]"), aIndex );
       
   731     if( aIndex >= 0 && aIndex < iAccesspointArray.Count() )
       
   732         {
       
   733         iAccesspointArray.Remove( aIndex );
       
   734         }
       
   735     else
       
   736         {
       
   737         LOG(_L("- KErrArgument"));
       
   738         User::Leave( KErrArgument );
       
   739         }
       
   740     }
       
   741 
       
   742 // -----------------------------------------------------------------------------
       
   743 // CreateNewServiceL
       
   744 // -----------------------------------------------------------------------------
       
   745 //
       
   746 EXPORT_C void CMmsSettings::CreateNewServiceL( CMsvSession& aSession )
       
   747     {
       
   748     LOG(_L("CMmsSettings::CreateNewServiceL"));
       
   749     TMsvId newId = KMsvRootIndexEntryId;
       
   750 
       
   751     // Connect CenRep if needed
       
   752     if( !iMmsRepository )
       
   753         {
       
   754         iMmsRepository = ConnectCenRepL( KUidMmsServerMtm );
       
   755         }
       
   756 
       
   757 #ifdef __WINS__
       
   758     // In WINS, localmode is the default
       
   759     TInt retval = iMmsRepository->Set( KMmsEngineLocalMode, ETrue );
       
   760     if( retval != KErrNone )
       
   761         {
       
   762         LOG(_L("-ERROR: Could not set localmode ON"));
       
   763         }
       
   764     SetLocalMode( ETrue );
       
   765 #endif // __WINS__    
       
   766 
       
   767     // Create utility class to handle message store operations
       
   768     CMmsMessageStoreUtils* messageStoreUtils = CMmsMessageStoreUtils::NewL( aSession );
       
   769     CleanupStack::PushL( messageStoreUtils ); // ***
       
   770     
       
   771     const TInt KMmsMaxTries = 50; // Just to keep Codescanner happy
       
   772     TInt maxTries = KMmsMaxTries;
       
   773     TBool done( EFalse );
       
   774     TInt error = KErrNone;
       
   775     while ( maxTries && !done )
       
   776         {
       
   777         error = iMmsRepository->StartTransaction( CRepository::EReadWriteTransaction );
       
   778         if ( error == KErrNone )
       
   779             {
       
   780             // Handle service entry
       
   781             iMmsRepository->CleanupCancelTransactionPushL();
       
   782             newId = messageStoreUtils->CreateServiceEntryL();
       
   783             iDefaultServiceId = newId;
       
   784             error =  iMmsRepository->Set( KMmsEngineDefaultServiceId, (TInt)newId );
       
   785             LOG2(_L("- Service entry created: %d"), newId );
       
   786         
       
   787             // Handle notification folder
       
   788             if ( error == KErrNone )
       
   789                 {
       
   790                 newId = messageStoreUtils->CreateFolderEntryL( KMMSNotificationFolder );
       
   791                 iNotificationFolderId = newId;
       
   792                 error = iMmsRepository->Set( KMmsEngineNotificationFolderId, (TInt)newId );
       
   793                 LOG2(_L("- Notification folder created: %d"), newId );
       
   794                 }
       
   795 
       
   796             // Handle mmbox folder
       
   797             if ( error == KErrNone )
       
   798                 {
       
   799                 newId = messageStoreUtils->CreateFolderEntryL( KMmsMmboxFolder );
       
   800                 iMMBoxFolderId = newId;
       
   801                 error = iMmsRepository->Set( KMmsEngineMMBoxFolderId, (TInt)newId );
       
   802                 LOG2(_L("- MMBox folder created: %d"), newId );
       
   803                 }
       
   804 
       
   805             // Handle application folder
       
   806             if ( error == KErrNone )
       
   807                 {
       
   808                 newId = messageStoreUtils->CreateFolderEntryL( KMmsApplicationFolder );
       
   809                 iApplicationFolderId = newId;
       
   810                 error = iMmsRepository->Set( KMmsEngineApplicationFolderId, (TInt)newId );
       
   811                 LOG2(_L("- Application folder created: %d"), newId );
       
   812                 }
       
   813             TUint32 keyInfo = 0; 
       
   814             CleanupStack::Pop(); // CleanupCancelTransactionPushL
       
   815             TInt commitError = KErrNone;
       
   816             commitError = iMmsRepository->CommitTransaction( keyInfo );
       
   817             if ( error == KErrNone && commitError == KErrNone )
       
   818                 {
       
   819                 done = ETrue;
       
   820                 }
       
   821             else
       
   822                 {
       
   823                 LOG3(_L("- error and commit error: %d %d"), error, commitError );
       
   824                 maxTries--;
       
   825                 }
       
   826             }
       
   827         else
       
   828             {
       
   829             // Another thread or process is probably trying simultaneous access.
       
   830             // Wait a little bit and retry.
       
   831             LOG2(_L("- Start transaction returned error: %d"), error );
       
   832             maxTries--;
       
   833             const TInt KMmsCreateServiceWait = 300000;  // 0.3 seconds
       
   834             User::After( KMmsCreateServiceWait );
       
   835             }
       
   836         }
       
   837 
       
   838     // Clean up
       
   839     CleanupStack::PopAndDestroy( messageStoreUtils );
       
   840     delete iMmsRepository;
       
   841     iMmsRepository = NULL;
       
   842     User::LeaveIfError( error );
       
   843     }
       
   844 
       
   845 // -----------------------------------------------------------------------------
       
   846 // CreateFolderEntryL
       
   847 // -----------------------------------------------------------------------------
       
   848 //
       
   849 EXPORT_C TInt CMmsSettings::CreateFolderEntryL( 
       
   850     CMsvSession& aSession, TMsvId aParentFolder, const TDesC& aFolderName, TMsvId& aFolderId )
       
   851     {
       
   852     CMmsMessageStoreUtils* messageStoreUtils = CMmsMessageStoreUtils::NewL( aSession );
       
   853     CleanupStack::PushL( messageStoreUtils );
       
   854     
       
   855     TInt error = messageStoreUtils->CreateFolderEntryL( aParentFolder, aFolderName, aFolderId );
       
   856     
       
   857     CleanupStack::PopAndDestroy( messageStoreUtils );
       
   858     return error;    
       
   859     }
       
   860 
       
   861 // -----------------------------------------------------------------------------
       
   862 // FolderEntryL
       
   863 // -----------------------------------------------------------------------------
       
   864 //    
       
   865 EXPORT_C TMsvId CMmsSettings::FolderEntryL(
       
   866     CMsvSession& aSession, TMsvId aParentFolder, const TDesC& aFolderName )
       
   867     {
       
   868     CMmsMessageStoreUtils* messageStoreUtils = CMmsMessageStoreUtils::NewL( aSession );
       
   869     CleanupStack::PushL( messageStoreUtils );
       
   870     
       
   871     TMsvId folderId = messageStoreUtils->FolderEntryL( aParentFolder, aFolderName );
       
   872     
       
   873     CleanupStack::PopAndDestroy( messageStoreUtils );
       
   874     return folderId;
       
   875         
       
   876     }
       
   877 
       
   878 // -----------------------------------------------------------------------------
       
   879 // ConnectCenRepL
       
   880 // -----------------------------------------------------------------------------
       
   881 //
       
   882 CRepository* CMmsSettings::ConnectCenRepL( const TUid aRepositoryId )
       
   883     {
       
   884     CRepository* repository = NULL;
       
   885     repository = CRepository::NewL( aRepositoryId );
       
   886     return repository;
       
   887     }
       
   888 
       
   889 #ifdef __WINS__ // following code is for testing/development purposes
       
   890 // ---------------------------------------------------------
       
   891 // ReadLocalModeDirectoriesL
       
   892 //
       
   893 // ---------------------------------------------------------
       
   894 //
       
   895 void CMmsSettings::ReadLocalModeDirectoriesL()
       
   896     {
       
   897     LOG(_L("CMmsSettings::ReadLocalModeDirectoriesL"));
       
   898     // Establish FileSystem connection
       
   899     RFs fs;
       
   900     User::LeaveIfError( fs.Connect() ); // ***
       
   901     CleanupClosePushL( fs );
       
   902 
       
   903     // Create readstream
       
   904     RFileReadStream reader;
       
   905     TInt err = reader.Open( fs, KMmsLocalModeConfigFile, EFileShareReadersOnly );
       
   906     if( err != KErrNone )
       
   907         {
       
   908         CleanupStack::PopAndDestroy( &fs ); // close fs
       
   909         return;
       
   910         }
       
   911     else
       
   912         {
       
   913         CleanupClosePushL( reader ); // ***
       
   914         }
       
   915     
       
   916     // Start reading data
       
   917     TChar delim = 0x000A;
       
   918     TBuf<KMmsRowBufferLength> rowBuffer;
       
   919     FOREVER
       
   920         {
       
   921         TRAP( err, reader.ReadL( rowBuffer, delim ) );
       
   922         if( err == KErrEof )
       
   923             {
       
   924             CleanupStack::PopAndDestroy( &reader ); // close reader
       
   925             CleanupStack::PopAndDestroy( &fs ); // close fs
       
   926             return;
       
   927             }
       
   928         TInt length = rowBuffer.Length();
       
   929         if( length > 2 )
       
   930             {
       
   931             // Check for comment line
       
   932             if( rowBuffer[0] == 0x0023 ) // 0x23 == '#'
       
   933                 {
       
   934                 continue;
       
   935                 }
       
   936             // Check for start of file (BOM)
       
   937             if( rowBuffer[0] == 0xFEFF )
       
   938                 {
       
   939                 rowBuffer.Delete( 0, 1 );
       
   940                 length = rowBuffer.Length();
       
   941                 }
       
   942             // Drop CR+LF from the end of line
       
   943             rowBuffer.Delete( length - 2, 2 );
       
   944             // Trim spaces
       
   945             rowBuffer.Trim();
       
   946   
       
   947             TInt separatorPosition = 0;
       
   948             separatorPosition = rowBuffer.Find( _L("=") );
       
   949             if( separatorPosition > 0 )
       
   950                 {
       
   951                 if( rowBuffer.Left( separatorPosition ).CompareF( KMmsLocalmodeInDirectory ) == 0 )
       
   952                     {
       
   953                     iLocalModeInDir = rowBuffer.Mid( separatorPosition+1 );
       
   954                     }
       
   955                 if( rowBuffer.Left( separatorPosition ).CompareF( KMmsLocalmodeOutDirectory )
       
   956                     == 0 )
       
   957                     {
       
   958                     iLocalModeOutDir = rowBuffer.Mid( separatorPosition+1 );
       
   959                     }
       
   960                 }
       
   961             }
       
   962         }
       
   963     CleanupStack::PopAndDestroy( &reader ); // close reader
       
   964     CleanupStack::PopAndDestroy( &fs ); // close fs
       
   965     }
       
   966 #endif // __WINS__
       
   967 
       
   968 #ifdef _DEBUG // Following is only for testing purposes
       
   969 void CMmsSettings::DebugLogSettings()
       
   970     {
       
   971     // Log goes to logs\mmssettings\settings.txt
       
   972     LOG(_L("SETTINGS CONTENT:"));
       
   973     LOG2(_L("    iSettingsVersion = %d"), iSettingsVersion);
       
   974     LOG3(_L("    iMmsVersion = %d.%d"), ( iMmsVersion & 0xF0 ) >> 4, iMmsVersion & 0x0F );
       
   975     LOG2(_L("    iDefaultServiceId =     %d"), iDefaultServiceId);
       
   976     LOG2(_L("    iNotificationFolderId = %d"), iNotificationFolderId);
       
   977     LOG2(_L("    iMMBoxFolderId =        %d"), iMMBoxFolderId);
       
   978     LOG2(_L("    iApplicationFolderId = %d"), iApplicationFolderId);
       
   979     LOG2(_L("    iAccesspointArray len = %d"), iAccesspointArray.Count());
       
   980     LOG2(_L("    iReceivingModeHome = %d"), iReceivingModeHome);
       
   981     LOG2(_L("    iReceivingModeForeign = %d"), iReceivingModeForeign);
       
   982     LOG2(_L("    iAcceptPersonal = %d"), iAcceptPersonal);
       
   983     LOG2(_L("    iAcceptAdvertisement = %d"), iAcceptAdvertisement);
       
   984     LOG2(_L("    iAcceptInformational = %d"), iAcceptInformational);
       
   985     LOG2(_L("    iAcceptAnonymous = %d"), iAcceptAnonymous);
       
   986     LOG2(_L("    iDeliveryReportWanted = %d"), iDeliveryReportWanted);
       
   987     LOG2(_L("    iDeliveryReportAllowed = %d"), iDeliveryReportAllowed);
       
   988     LOG2(_L("    iReadReplyReportWanted = %d"), iReadReplyReportWanted);
       
   989     LOG2(_L("    iReadReplyReportAllowed = %d"), iReadReplyReportAllowed);
       
   990     LOG2(_L("    iMessageClass = %d"), iMessageClass);
       
   991     LOG2(_L("    iExpiryInterval = %d"), iExpiryInterval);
       
   992     LOG2(_L("    iSenderVisibility = %d"), iSenderVisibility);
       
   993     LOG2(_L("    iMessagePriority = %d"), iMessagePriority);
       
   994     LOG2(_L("    iMaxSendSize = %d"), iMaxSendSize);
       
   995     LOG2(_L("    iMaxReceiveSize = %d"), iMaxReceiveSize);
       
   996     LOG2(_L("    iImageWidth = %d"), iImageWidth);
       
   997     LOG2(_L("    iImageHeight = %d"), iImageHeight);
       
   998     LOG2(_L("    iMoveToSent = %d"), iMoveToSent);
       
   999     LOG2(_L("    iLogEmailRecipients = %d"), iLogEmailRecipients);
       
  1000     LOG2(_L("    iExpiryOvershoot = %d"), iExpiryOvershoot);
       
  1001     LOG2(_L("    iCreationMode = %d"), iCreationMode);
       
  1002     LOG2(_L("    iFetchOverride = %d"), iFetchOverride);
       
  1003     LOG2(_L("    iShowSentTime = %d"), iShowSentTime);
       
  1004     }
       
  1005 #endif // _DEBUG
       
  1006 
       
  1007 // =========================== OTHER EXPORTED FUNCTIONS ========================
       
  1008 
       
  1009 //  End of File