Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //------------------------------------------------------------------------
     18 //
     19 //   Module Name: dm_tree_node_class_public.cc
     20 //
     21 //   General Description: Contains the implementations of the Public
     22 //                        methods of DMNTree class.
     23 //------------------------------------------------------------------------
     24 
     25 #include "dmprofile.h"
     26 #include "dm_tree_util.h"
     27 #include "dmLockingHelper.h"
     28 #include "dm_tree_class.H"
     29 #include "SyncML_DM_Archiver.H"
     30 #include "dm_tree_default_leaf_node_class.H"
     31 #ifdef LOB_SUPPORT
     32 #include "dm_tree_default_ESN_class.H"
     33 #endif
     34 #include "dm_tree_default_interior_node_class.H"
     35 #include "dm_uri_utils.h"
     36 #include "xpl_Logger.h"
     37 #include "dmtTreeImpl.hpp"
     38 #include "dm_tree_plugin_root_node_class.H"
     39 #include "dm_tree_plugin_util.H"
     40 #include "dmtoken.h"
     41 #include "xpl_dm_Manager.h"
     42 
     43 //------------------------------------------------------------------------
     44 //                           LOCAL VARIABLES
     45 //------------------------------------------------------------------------
     46 const UINT8 *DMTree::m_pDataFormatTable[] =
     47 {
     48     (UINT8 *)"null", // SYNCML_DM_FORMAT_NULL
     49     (UINT8 *)"chr",  //SYNCML_DM_FORMAT_CHR,
     50     (UINT8 *)"int",  //SYNCML_DM_FORMAT_INT,
     51     (UINT8 *)"bool", //SYNCML_DM_FORMAT_BOOL,
     52     (UINT8 *)"bin",  //SYNCML_DM_FORMAT_BIN,
     53     (UINT8 *)"node", //SYNCML_DM_FORMAT_NODE,
     54     (UINT8 *)"b64",  //SYNCML_DM_FORMAT_B64,
     55     (UINT8 *)"xml",  //SYNCML_DM_FORMAT_XML,
     56     (UINT8 *)"date", //SYNCML_DM_FORMAT_DATE,
     57     (UINT8 *)"test", //SYNCML_DM_FORMAT_TEST,
     58     (UINT8 *)"time", //SYNCML_DM_FORMAT_TIME,
     59     (UINT8 *)"float",//SYNCML_DM_FORMAT_FLOAT,
     60     (UINT8 *)NULL,   //SYNCML_DM_FORMAT_INVALID
     61 };
     62 
     63 //------------------------------------------------------------------------
     64 // FUNCTION         :   LogEvent
     65 // DESCRIPTION      :   Logging the DELETE command which was executed successfully
     66 // ARGUMENTS PASSED :   pbURI - updated node
     67 //                                  aDeletedChildren - deleted children nodes
     68 // RETURN VALUE     :   SYNCML_DM_RET_STATUS_T
     69 //                      SYNCML_DM_SUCCESS or SYNCML_DM_FAIL if some
     70 //                      failure in logCommand occured
     71 // PRE-CONDITIONS   :   The command was successful
     72 //                      Tree was updated accordingly
     73 // POST-CONDITIONS  :   the Archiver validates the log and will use it
     74 //                      while serializing the tree
     75 //------------------------------------------------------------------------
     76 SYNCML_DM_RET_STATUS_T
     77 DMTree::LogEvent(CPCHAR pbURI, const DMStringVector & aDeletedChildren)
     78 {
     79     SyncML_DM_Archive * pArchive = m_oArchiver.getArchiveByURI(pbURI);
     80 
     81     if (pArchive == NULL)
     82         return SYNCML_DM_FAIL;
     83 
     84     pArchive->setDirty(TRUE);
     85 
     86     return m_oEvtObj.OnNodeDeleted(pArchive, pbURI, aDeletedChildren);
     87 }
     88 
     89 //------------------------------------------------------------------------
     90 // FUNCTION         :   LogEvent
     91 // DESCRIPTION      :   Logging the command which was executed
     92 //                      successfully in the log file
     93 //                      sets the command type, URI and pointer to a copy
     94 //                      of the node and calls the logCommand method of
     95 //                      archiver
     96 // ARGUMENTS PASSED :   commandType ADD/REPLACE/DELETE/RENAME/INDIRECT UPDATE
     97 //                                  pbURI - updated node
     98 //                                  szNewName - new name
     99 // RETURN VALUE     :   SYNCML_DM_RET_STATUS_T
    100 //                      SYNCML_DM_SUCCESS or SYNCML_DM_FAIL if some
    101 //                      failure in logCommand occured
    102 // PRE-CONDITIONS   :   The command was successful
    103 //                      Tree was updated accordingly
    104 // POST-CONDITIONS  :   the Archiver validates the log and will use it
    105 //                      while serializing the tree
    106 //------------------------------------------------------------------------
    107 SYNCML_DM_RET_STATUS_T
    108 DMTree::LogEvent(SYNCML_DM_EVENT_ACTION_T eEvent,
    109                                CPCHAR pbURI,
    110                                CPCHAR szNewName)
    111 {
    112     SyncML_DM_Archive * pArchive = m_oArchiver.getArchiveByURI(pbURI);
    113 
    114     if (pArchive == NULL)
    115         return SYNCML_DM_FAIL;
    116 
    117     pArchive->setDirty(TRUE);
    118 
    119     return m_oEvtObj.OnNodeChanged( pArchive, pbURI, eEvent, szNewName );
    120 }
    121 
    122 //------------------------------------------------------------------------
    123 // FUNCTION         :   LogESNCommandForArchiver
    124 // DESCRIPTION     :   Logging the command which was executed
    125 //                      successfully in the log file
    126 //                      sets the command type, URI and pointer to a copy
    127 //                      of the node and calls the logCommand method of
    128 //                      archiver
    129 // ARGUMENTS PASSED :   pbURI - updated node
    130 //                                  inNode - updated node
    131 // RETURN VALUE     :   SYNCML_DM_RET_STATUS_T
    132 //                      SYNCML_DM_SUCCESS or SYNCML_DM_FAIL if some
    133 //                      failure in logCommand occured
    134 // PRE-CONDITIONS   :   The command was successful
    135 //                      Tree was updated accordingly
    136 // POST-CONDITIONS  :   the Archiver validates the log and will use it
    137 //                      while serializing the tree
    138 //------------------------------------------------------------------------
    139 #ifdef LOB_SUPPORT
    140 SYNCML_DM_RET_STATUS_T
    141 DMTree::LogESNCommandForArchiver(CPCHAR pbURI, DMNode * inNode)
    142 {
    143     SyncML_DM_Archive * pArchive = m_oArchiver.getArchiveByURI(pbURI);
    144     SYNCML_DM_RET_STATUS_T retStatus = SYNCML_DM_SUCCESS;
    145 
    146     if (pArchive == NULL)
    147         return SYNCML_DM_FAIL;
    148 
    149     DMDefaultESN  *tempESN = reinterpret_cast< DMDefaultESN *>(inNode);;
    150     SyncML_Commit_Log *commitLog =  pArchive->GetCommitLogHandler();
    151     if(commitLog != NULL && tempESN->NeedLogging())
    152        retStatus = commitLog->logCommand(SYNCML_DM_REPLACE, tempESN->GetOriginalInternalFileName() , tempESN->GetInternalStorageFileName());
    153 
    154     return retStatus;
    155 }
    156 #endif
    157 
    158 SYNCML_DM_RET_STATUS_T DMTree::ConvertFormat(SYNCML_DM_FORMAT_T format,
    159         DMString & strFormat)
    160 {
    161     strFormat = format >= sizeof(m_pDataFormatTable)/sizeof(int) ?
    162                 NULL : (CPCHAR)m_pDataFormatTable[format];
    163 
    164     if ( strFormat == NULL && format != SYNCML_DM_FORMAT_NULL)
    165         return SYNCML_DM_DEVICE_FULL;
    166     else
    167         return SYNCML_DM_SUCCESS;
    168 }
    169 
    170 SYNCML_DM_FORMAT_T DMTree::ConvertFormatStr(const DMString& formatStr)
    171 {
    172    SYNCML_DM_FORMAT_T bFormat = SYNCML_DM_FORMAT_NODE;
    173 
    174    if (formatStr == "chr" || formatStr == "string")
    175    {
    176       bFormat = SYNCML_DM_FORMAT_CHR;
    177    } else
    178    if (formatStr == "int" )
    179    {
    180       bFormat = SYNCML_DM_FORMAT_INT;
    181    } else
    182    if (formatStr == "bool" )
    183    {
    184       bFormat = SYNCML_DM_FORMAT_BOOL;
    185    } else
    186    if (formatStr == "b64" )
    187    {
    188       bFormat = SYNCML_DM_FORMAT_B64;
    189    } else
    190    if (formatStr == "bin" )
    191    {
    192       bFormat = SYNCML_DM_FORMAT_BIN;
    193    } else
    194    if (formatStr == "node" )
    195    {
    196       bFormat = SYNCML_DM_FORMAT_NODE;
    197    } else
    198    if (formatStr == "xml" )
    199    {
    200       bFormat = SYNCML_DM_FORMAT_XML;
    201    } else
    202    if (formatStr == "date" )
    203    {
    204       bFormat = SYNCML_DM_FORMAT_DATE;
    205    } else
    206    if (formatStr == "time" )
    207    {
    208       bFormat = SYNCML_DM_FORMAT_TIME;
    209    } else
    210    if (formatStr == "float" )
    211    {
    212       bFormat = SYNCML_DM_FORMAT_FLOAT;
    213    } else
    214    if (formatStr == "null" )
    215    {
    216       bFormat = SYNCML_DM_FORMAT_NULL;
    217    }
    218    else
    219    {
    220       bFormat = SYNCML_DM_FORMAT_CHR;  //Cover unknown Meta data format
    221    }
    222 
    223    return bFormat;
    224 }
    225 
    226 BOOLEAN DMTree::ParentExistsForPluginNode(CPCHAR pURI, DMNode *psNode) const
    227 {
    228     DMString strParentURI = pURI, strLastSegment;
    229 
    230     if ( !GetLastSegmentOfURI(strParentURI, strLastSegment) )
    231       return FALSE;
    232 
    233     if ( strParentURI == "." )
    234       return TRUE;
    235 
    236     DMGetData getData;
    237 
    238     if (psNode->Get(strParentURI, getData) != SYNCML_DM_SUCCESS)
    239       return FALSE;
    240 
    241     return TRUE;
    242 }
    243 
    244 
    245 void DMTree::DetachNodeFromTree(DMNode *psDeletingNode)
    246 {
    247     DMNode *psParentNode = NULL;
    248     DMNode *psPrevNode = NULL;
    249     DMNode *psListNode = NULL;
    250 
    251     psParentNode = psDeletingNode->pcParentOfNode;
    252     psListNode = psParentNode->pcFirstChild;
    253 
    254     // This while stores the previous pointer to the deleting node.
    255     while(psListNode)
    256     {
    257        if(psListNode == psDeletingNode)
    258          break;
    259       psPrevNode = psListNode;
    260       psListNode = psListNode->pcNextSibling;
    261     }
    262 
    263     if(psListNode == psDeletingNode)
    264     {
    265        if(psPrevNode != NULL)
    266        {
    267          // If previous node is not equals to NULL then we will
    268          // set the deleting node next pointer to the next node
    269          // pointer of previous node
    270          psPrevNode->pcNextSibling = psDeletingNode->pcNextSibling;
    271        }
    272        else
    273        {
    274          // If the previous node is NOT there mean then deleting
    275          // node is first child in the siblings list.
    276          psParentNode->pcFirstChild =  psDeletingNode->pcNextSibling;
    277        }
    278        psDeletingNode->pcParentOfNode=NULL;
    279        psDeletingNode->pcNextSibling=NULL;
    280 
    281     }// End of if(psListNode == psDeletingNode)
    282 
    283 }
    284 
    285 // DMTree constructor
    286 DMTree::DMTree()
    287   : m_init_status( SYNCML_DM_FAIL ),
    288     m_psRoot( NULL ),
    289     m_wMaxDepth( SYNCML_DM_URI_MAX_DEPTH ),
    290     m_wMaxTotLen( SYNCML_DM_URI_MAX_TOTAL_LENGTH ),
    291     m_wMaxSegLen( SYNCML_DM_URI_MAX_SEGMENT_LENGTH ),
    292     m_nRefCount( 0 ),
    293     m_currentTime( 0 )
    294 {
    295   m_strPrincipal = "";
    296 
    297   m_oOPICacheData.metaNodeID = -1;
    298   m_pOPINode = NULL;
    299   m_bVersion_1_2 = FALSE;
    300 #ifdef LOB_SUPPORT
    301   m_pESN = NULL;
    302   m_strESNPath= "";
    303 #endif
    304 }
    305 
    306 // DMTree destructor
    307 DMTree::~DMTree()
    308 {
    309     DeInit(TRUE);
    310 }
    311 
    312 /*==================================================================================================
    313 FUNCTION        : DMTree::SetServerId
    314 
    315 DESCRIPTION     : This function will set the server Id.
    316 ARGUMENT PASSED : p_ServerId
    317 OUTPUT PARAMETER:
    318 RETURN VALUE    : SYNCML_DM_SUCCESS if success,
    319                   SYNCML_DM_FAIL if allocating memory failed.
    320 IMPORTANT NOTES :
    321 ==================================================================================================*/
    322 SYNCML_DM_RET_STATUS_T
    323 DMTree::SetServerId (CPCHAR p_ServerId)
    324 {
    325   m_strPrincipal = p_ServerId;
    326   return SYNCML_DM_SUCCESS;
    327 }
    328 
    329 /*==================================================================================================
    330 FUNCTION        : DMTree::SetConRef
    331 
    332 DESCRIPTION     : This function will set the ConRef
    333 ARGUMENT PASSED : p_ConRef
    334 OUTPUT PARAMETER:
    335 RETURN VALUE    : SYNCML_DM_SUCCESS if success,
    336                   SYNCML_DM_FAIL if allocating memory failed.
    337 IMPORTANT NOTES :
    338 ==================================================================================================*/
    339 SYNCML_DM_RET_STATUS_T
    340 DMTree::SetConRef (CPCHAR p_ConRef)
    341 {
    342   //m_strPrincipal = p_ConRef;
    343   m_strConRef = p_ConRef;
    344   return SYNCML_DM_SUCCESS;
    345 }
    346 
    347 BOOLEAN DMTree::IsInitialized() const
    348 {
    349     return (SYNCML_DM_SUCCESS == m_init_status);
    350 }
    351 
    352 //------------------------------------------------------------------------
    353 // FUNCTION        : Init
    354 // DESCRIPTION     : The UA calls this method once the syncml task is up
    355 //                   The DMTNM initializes it's data members and also
    356 //                   creates a timer
    357 // ARGUMENTS PASSED: None
    358 // RETURN VALUE    : void
    359 // PRE-CONDITIONS  : syncml task is ready
    360 // POST-CONDITIONS : the Tree obtains a timer handle and resets it's flags
    361 // IMPORTANT NOTES :
    362 //------------------------------------------------------------------------
    363 SYNCML_DM_RET_STATUS_T DMTree::Init()
    364 {
    365 #ifndef DM_NO_LOCKING
    366   DMSingleLock oLock( m_csInitLock );
    367 #endif
    368 
    369   XPL_LOG_Startup();
    370 
    371   SYNCML_DM_RET_STATUS_T result = SYNCML_DM_SUCCESS;
    372 
    373   if ( 0 == m_nRefCount )
    374   {
    375     result = InternalInit();
    376     m_init_status = result;
    377   }
    378 
    379   if( SYNCML_DM_SUCCESS == result )
    380   {
    381     m_nRefCount++;
    382     DM_MEMORY_STATISTICS_WRITE("Initialize\n");
    383   }
    384   else
    385   {
    386     XPL_LOG_DM_TMN_Error(("Initializing failed\n"));
    387 
    388     // DM: reverting to uninitialized state partially initialized object
    389     InternalDeInit();
    390   }
    391 
    392   return result;
    393 }
    394 
    395 SYNCML_DM_RET_STATUS_T DMTree::InternalInit()
    396 {
    397   SYNCML_DM_RET_STATUS_T result = SYNCML_DM_SUCCESS;
    398 
    399   for (;;)
    400   {
    401     DM_PROFILE( "DmMnInit" );
    402 
    403 
    404     if( IsInitialized() )
    405     {
    406       XPL_LOG_DM_TMN_Error(("Already initialized\n"));
    407       result = SYNCML_DM_FAIL;
    408       break;
    409     }
    410 
    411     XPL_LOG_DM_TMN_Debug(("Initializing XPL...\n"));
    412     result = XPL_DM_Init();
    413     if( SYNCML_DM_SUCCESS != result ) break;
    414 
    415     XPL_LOG_DM_TMN_Debug(("Initializing environment...\n"));
    416     if( !m_oEnv.Init() )
    417     {
    418       result = SYNCML_DM_FAIL;
    419       break;
    420     }
    421 
    422     CPCHAR dm_ver = XPL_DM_GetEnv(SYNCML_DM_VERSION);
    423     m_bVersion_1_2 = ( dm_ver && DmStrcmp(dm_ver,SYNCML_REP_PROTOCOL_VERSION_1_2) == 0 );
    424 
    425     XPL_LOG_DM_TMN_Debug(("DM version is %s\nMounting tree...\n", m_bVersion_1_2 ? "1.2" : "1.1.2" ));
    426     DM_PERFORMANCE(DM_INITIALIZE_MOUNT);
    427     result = m_oTreeMountObj.MountTree( &m_oEnv, this );
    428     if( SYNCML_DM_SUCCESS != result ) break;
    429 
    430     XPL_LOG_DM_TMN_Debug(("Initializing MDF and Plugin Manager...\n"));
    431     DM_PERFORMANCE(DM_INITIALIZE_MDF);
    432     result = m_oMDFObj.Init( &m_oEnv, this );
    433     if( SYNCML_DM_SUCCESS != result ) break;
    434 
    435     DM_PERFORMANCE(DM_INITIALIZE_PLUGIN);
    436     result = m_oPluginManager.Init( &m_oEnv, this );
    437     if( SYNCML_DM_SUCCESS != result ) break;
    438 
    439     XPL_LOG_DM_TMN_Debug(("Initializing Archiver and File Manager...\n"));
    440     DM_PERFORMANCE(DM_INITIALIZE_ACRHIVER);
    441     result = m_oArchiver.initArchives( &m_oEnv, this );
    442     if( SYNCML_DM_SUCCESS != result ) break;
    443 
    444     DM_PERFORMANCE(DM_INITIALIZE_FILE);
    445     result = m_oFileManager.Init( this );
    446     if( SYNCML_DM_SUCCESS != result ) break;
    447 
    448     XPL_LOG_DM_TMN_Debug(("Initializing Lock Context Manager and ACL...\n"));
    449     DM_PERFORMANCE(DM_INITIALIZE_LOCK);
    450     result = m_oLockContextManager.Init( this, &m_oFileManager );
    451     if( SYNCML_DM_SUCCESS != result ) break;
    452 
    453     DM_PERFORMANCE(DM_INITIALIZE_ACL);
    454     result = m_oACLObj.Init( &m_oEnv, this );
    455     if( SYNCML_DM_SUCCESS != result ) break;
    456 
    457     DM_PERFORMANCE(DM_INITIALIZE_EVENT);
    458     result = m_oEvtObj.Init( &m_oEnv, this );
    459     if( SYNCML_DM_SUCCESS != result ) break;
    460 
    461     DM_PERFORMANCE(DM_INITIALIZE_LOAD);
    462     // LoadMaxValues();
    463 
    464     if ( DmGetMemFailedFlag() ) // device runs out of memory
    465     {
    466       result = SYNCML_DM_DEVICE_FULL;
    467       break;
    468     }
    469 
    470     result = SYNCML_DM_SUCCESS;
    471     break;
    472   }
    473 
    474   if( SYNCML_DM_SUCCESS == result )
    475   {
    476     XPL_LOG_DM_TMN_Debug(("Initialized successfully\n"));
    477   }
    478   else
    479   {
    480     XPL_LOG_DM_TMN_Error(( "Initialization faled\n" ));
    481   }
    482 
    483   return result;
    484 }
    485 
    486 UINT16 DMTree::GetMaxPathDepth() const
    487 {
    488   return m_wMaxDepth;
    489 }
    490 
    491 UINT16 DMTree::GetMaxTotalPathLength() const
    492 {
    493   return m_wMaxTotLen;
    494 }
    495 
    496 UINT16 DMTree::GetMaxPathSegmentLength() const
    497 {
    498   return m_wMaxSegLen;
    499 }
    500 
    501 void DMTree::LoadMaxValues()
    502 {
    503     // special case for some nodes
    504     int nLock = 0;
    505     {
    506      DMLockingHelper oLock( 0, "./DevDetail/URI", "localhost", SYNCML_DM_LOCK_TYPE_SHARED, FALSE );
    507      nLock = oLock.GetID();
    508 
    509      if ( oLock.IsLockedSuccessfully() )
    510      {
    511         DMNode* pNode = FindNodeByURI("./DevDetail/URI/MaxDepth");
    512 
    513         m_wMaxDepth = readOneWordFromTree(pNode, SYNCML_DM_URI_MAX_DEPTH);
    514 
    515         pNode = FindNodeByURI("./DevDetail/URI/MaxTotLen");
    516 
    517         m_wMaxTotLen = readOneWordFromTree(pNode, SYNCML_DM_URI_MAX_TOTAL_LENGTH);
    518 
    519         pNode = FindNodeByURI("./DevDetail/URI/MaxSegLen");
    520 
    521         m_wMaxSegLen = readOneWordFromTree(pNode, SYNCML_DM_URI_MAX_SEGMENT_LENGTH);
    522 
    523     }
    524    }
    525 
    526    ReleaseLock( nLock );
    527 }
    528 
    529 SYNCML_DM_RET_STATUS_T DMTree::DeInit(BOOLEAN bIsDestructor)
    530 {
    531 #ifndef DM_NO_LOCKING
    532   DMSingleLock oLock( m_csInitLock );
    533 #endif
    534 
    535   if ( m_nRefCount < 1 )
    536   {
    537      if (bIsDestructor == FALSE)
    538      {
    539         XPL_LOG_DM_TMN_Error(("Invalid ref count = %i\n", m_nRefCount ));
    540      }
    541      return SYNCML_DM_FAIL;
    542 
    543   }
    544 
    545   m_nRefCount--;
    546 
    547   XPL_LOG_DM_TMN_Debug(("Uninitializing, ref count = %i\n", m_nRefCount ));
    548 
    549   if ( ( 0 == m_nRefCount ) && IsInitialized() )
    550   {
    551     InternalDeInit();
    552 
    553     DM_MEMORY_STATISTICS_REPORT_LEAKS
    554   }
    555 
    556   XPL_LOG_Shutdown();
    557 
    558   return SYNCML_DM_SUCCESS;
    559 }
    560 
    561 void DMTree::InternalDeInit()
    562 {
    563   XPL_LOG_DM_TMN_Debug(("Uninitializing, releasing locks...\n" ));
    564   m_oLockContextManager.ReleaseAll();
    565 
    566   XPL_LOG_DM_TMN_Debug(("Uninitializing ACL...\n" ));
    567   m_oACLObj.DeInit();
    568 
    569   XPL_LOG_DM_TMN_Debug(("Uninitializing lock context manager...\n" ));
    570   m_oLockContextManager.Destroy();
    571 
    572   XPL_LOG_DM_TMN_Debug(("Uninitializing file manager...\n" ));
    573   m_oFileManager.DeInit();
    574 
    575   XPL_LOG_DM_TMN_Debug(("Uninitializing Archiver...\n" ));
    576   m_oArchiver.deinitArchives();
    577 
    578   XPL_LOG_DM_TMN_Debug(("Uninitializing, reseting cache...\n" ));
    579 #ifdef LOB_SUPPORT
    580   ResetESNCache();
    581 #endif
    582   ResetOPICache();
    583   m_oOPICacheData.aPD.clear();
    584 
    585   XPL_LOG_DM_TMN_Debug(("Uninitializing, deleting nodes...\n" ));
    586   if( m_psRoot )
    587   {
    588     DeleteNodesFromTree( m_psRoot );
    589     m_psRoot = NULL;
    590   }
    591 
    592  XPL_LOG_DM_TMN_Debug(("Uninitializing Plugin manager...\n" ));
    593  m_oPluginManager.DeInit();
    594 
    595   XPL_LOG_DM_TMN_Debug(("Uninitializing MDF...\n" ));
    596   m_oMDFObj.DeInit();
    597 
    598   XPL_LOG_DM_TMN_Debug(("Uninitializing: unmounting trees...\n" ));
    599   m_oTreeMountObj.UnMountTree();
    600 
    601   XPL_LOG_DM_TMN_Debug(("Uninitializing environment...\n" ));
    602   m_oEnv.Done();
    603 
    604   XPL_LOG_DM_TMN_Debug(("Uninitializing XPL...\n" ));
    605   XPL_DM_DeInit();
    606 
    607   m_strPrincipal = "";
    608   m_init_status = SYNCML_DM_FAIL;
    609   XPL_LOG_DM_TMN_Debug(("Uninitializing : succeeded\n" ));
    610 
    611 }
    612 
    613 // force to unload all loaded sub-trees and plug-ins
    614 SYNCML_DM_RET_STATUS_T DMTree::Flush()
    615 {
    616   XPL_LOG_DM_TMN_Debug(("DMTree::Flush\n"));
    617   ResetOPICache();
    618   m_oOPICacheData.aPD.clear();
    619 
    620   if( m_psRoot )
    621   {
    622     DeleteNodesFromTree( m_psRoot );
    623   }
    624 
    625   m_oPluginManager.DeInit();
    626   return m_oPluginManager.Init( &m_oEnv, this );
    627 }
    628 
    629 void DMTree::GetTreeMountEntry (CPCHAR &p_Uri,  CPCHAR& p_TreePath,  UINT16   index) const
    630 {
    631   m_oTreeMountObj.GetTreeMountEntry( p_Uri, p_TreePath, index );
    632 }
    633 
    634 DMPluginManager & DMTree::GetPluginManager()
    635 {
    636   return m_oPluginManager;
    637 }
    638 
    639 SyncML_DM_Archiver& DMTree::GetArchiver()
    640 {
    641   return m_oArchiver;
    642 }
    643 
    644 DMLockContextManager& DMTree::GetLockContextManager()
    645 {
    646   return m_oLockContextManager;
    647 }
    648 
    649 DMSubscriptionManager &  DMTree::GetSubscriptionManager()
    650  {
    651     return m_oEvtObj;
    652  }
    653 
    654 SYNCML_DM_RET_STATUS_T DMTree::ReleaseLock( INT32 nLockID ,SYNCML_DM_COMMAND_T command /* = SYNCML_DM_RELEASE*/)
    655 {
    656   return m_oLockContextManager.ReleaseID( nLockID, command );
    657 }
    658 
    659 
    660 void DMTree::CheckMemoryAging()
    661 {
    662   m_oLockContextManager.CheckMemoryAging();
    663 }
    664 
    665 
    666 SYNCML_DM_RET_STATUS_T DMTree::SaveFile(SYNCML_DM_FILE_TYPE_T eFileType)
    667 {
    668     if ( eFileType == SYNCML_DM_FILE_ACL )
    669         return m_oACLObj.Serialize();
    670     else
    671         return m_oEvtObj.Serialize();
    672 
    673 }
    674 
    675 SYNCML_DM_RET_STATUS_T DMTree::RevertFile(SYNCML_DM_FILE_TYPE_T eFileType)
    676 {
    677     if ( eFileType == SYNCML_DM_FILE_ACL )
    678         return m_oACLObj.Revert();
    679     else
    680         return m_oEvtObj.Revert();
    681 }
    682 
    683 
    684 CPCHAR DMTree::GetWritableFileSystemFullPath( DMString & path )
    685 {
    686   return m_oEnv.GetWFSFullPath( NULL, path );
    687 }
    688 
    689 
    690 SYNCML_DM_RET_STATUS_T
    691 DMTree::SetACL(CPCHAR szURI)
    692 {
    693     //This variable stores the length of the ACL
    694     UINT16   totalLength = 0;
    695     UINT16   length = 0;
    696     DMBuffer oACL;
    697 
    698     length = m_strPrincipal.length();
    699 
    700     totalLength = ADD_CMD_LENGTH_IN_ACL + length + 1 +
    701                        GET_CMD_LENGTH_IN_ACL + length + 1 +
    702                        REPLACE_CMD_LENGTH_IN_ACL + length + 1 +
    703                        DELETE_CMD_LENGTH_IN_ACL + length + 1 +
    704                        EXEC_CMD_LENGTH_IN_ACL + length + 1;
    705 
    706     if ( oACL.allocate(totalLength) == NULL )
    707         return(SYNCML_DM_DEVICE_FULL);
    708 
    709 
    710     oACL.assign(ADD_CMD_IN_ACL);
    711     oACL.append((UINT8*) m_strPrincipal.GetBuffer(),length);
    712     oACL.append((UINT8*)"&",1);
    713 
    714     oACL.append((UINT8*)GET_CMD_IN_ACL,GET_CMD_LENGTH_IN_ACL);
    715     oACL.append((UINT8*)m_strPrincipal.GetBuffer(),length);
    716     oACL.append((UINT8*)"&",1);
    717 
    718     oACL.append((UINT8*)REPLACE_CMD_IN_ACL,REPLACE_CMD_LENGTH_IN_ACL);
    719     oACL.append((UINT8*)m_strPrincipal.GetBuffer(),length);
    720     oACL.append((UINT8*)"&",1);
    721 
    722     oACL.append((UINT8*)DELETE_CMD_IN_ACL,DELETE_CMD_LENGTH_IN_ACL);
    723     oACL.append((UINT8*)m_strPrincipal.GetBuffer(),length);
    724     oACL.append((UINT8*)"&",1);
    725 
    726     oACL.append((UINT8*)EXEC_CMD_IN_ACL,EXEC_CMD_LENGTH_IN_ACL);
    727     oACL.append((UINT8*)m_strPrincipal.GetBuffer(),length);
    728 
    729     m_oACLObj.SetACL(szURI, (CPCHAR)oACL.getBuffer());
    730 
    731     return SYNCML_DM_SUCCESS;
    732 }
    733 
    734 SYNCML_DM_RET_STATUS_T
    735 DMTree::AddAutoNodes(CPCHAR szURI,
    736                                  SYNCML_DM_REQUEST_TYPE_T eRequestType,
    737                                  DMToken & oAutoNodes)
    738 {
    739     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    740 
    741     if ( oAutoNodes.getBuffer() == NULL )
    742         return SYNCML_DM_SUCCESS;
    743 
    744     DMString autoNodeURI;
    745     DMAddData oAddChildren;
    746     CPCHAR sSegment = NULL;
    747 
    748     while ( (sSegment = oAutoNodes.nextSegment()) != NULL )
    749     {
    750         autoNodeURI = szURI;
    751         autoNodeURI += "/";
    752         autoNodeURI += sSegment;
    753 
    754         dm_stat = m_oMDFObj.SetAutoNodeProperty(autoNodeURI,oAddChildren);
    755         if ( dm_stat != SYNCML_DM_SUCCESS )
    756             return dm_stat;
    757 
    758         dm_stat = Add( oAddChildren,eRequestType);
    759         if ( dm_stat != SYNCML_DM_SUCCESS )
    760             return dm_stat;
    761    }
    762 
    763    return dm_stat;
    764 }
    765 
    766 //------------------------------------------------------------------------
    767 // FUNCTION        : Add
    768 // DESCRIPTION     : The UA calls this method to add a node/data in the
    769 //                   tree.The UA need not call URIValidateAndParse
    770 //                   for ADD operation.DMTNM will internally call before
    771 //                   adding
    772 // ARGUMENTS PASSED: SYNCML_DM_PLUGIN_ADD_T *pAdd - pointer to adding node
    773 //                                                  information.
    774 
    775 //If default value then pAdd->bFormat=SYNCML_DM_FORMAT_INVALID
    776 //                                          contains value TRUE.
    777 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    778 //                              - It returns SYNCML_DM_SUCCESS if the plug-in
    779 //                                adds the node succefully.
    780 //                              - It returns SYNCML_DM_DEVICE_FULL if the
    781 //                                device is out of memory.
    782 //                              - It returns SYNCML_DM_COMMAND_NOT_ALLOWED
    783 //                                if the commad is NOT allowed because
    784 //                                Access type and etc.
    785 //                              - It returns SYNCML_DM_TARGET_ALREADY_EXISTS
    786 //                                if the node already exists.
    787 //                              - It returns SYNCML_DM_INVALID_URI
    788 //                                if the node path is not valid for current DMT version
    789 // PRE-CONDITIONS  : The Tree is in memory
    790 // POST-CONDITIONS : the node is added in the tree only if the plug-in
    791 //                   returns SYNCML_DM_SUCCESS
    792 //                   else the object is deleted.
    793 //                   after adding the node successfully,the DMTNM sets the
    794 //                   Name and ACL and Access Type properties.It uses the
    795 //                   access type sent by plug-in.
    796 // IMPORTANT NOTES : PHASE 1 implementation
    797 //------------------------------------------------------------------------
    798 SYNCML_DM_RET_STATUS_T DMTree::Add( DMAddData & oAddData,
    799                                     SYNCML_DM_REQUEST_TYPE_T eRequestType)
    800 {
    801   XPL_LOG_DM_TMN_Debug(("Enter DMTree::Add(DMAddData&, SYNCML_DM_REQUEST_TYPE_T)"));
    802     SYNCML_DM_RET_STATUS_T wReturnStatusCode = AddNodeInternal(oAddData, eRequestType);
    803 
    804     if ( wReturnStatusCode == SYNCML_DM_SUCCESS || wReturnStatusCode != SYNCML_DM_NOT_FOUND )
    805     {
    806        return wReturnStatusCode;
    807     }
    808 
    809     // Add interior node(s) in the chain
    810     DMString strURI = oAddData.getURI();
    811     DMString strLastInteriorNodeAdded = NULL;
    812     DMVector<DMAddData *> interiorNodeList;
    813     DMAddData *pAddInteriorNodeData;
    814     while ( GetLastSegmentOfURI(strURI, strLastInteriorNodeAdded ) )
    815     {
    816        pAddInteriorNodeData = new DMAddData();
    817        if ( NULL == pAddInteriorNodeData )
    818        {
    819           wReturnStatusCode = SYNCML_DM_DEVICE_FULL;
    820           break;
    821        }
    822        pAddInteriorNodeData->m_oURI.assign(strURI.c_str());
    823        pAddInteriorNodeData->m_nFormat = SYNCML_DM_FORMAT_NODE;
    824        wReturnStatusCode = AddNodeInternal(*pAddInteriorNodeData, eRequestType);
    825        if ( wReturnStatusCode == SYNCML_DM_SUCCESS )
    826        {
    827           strLastInteriorNodeAdded = strURI;
    828           XPL_LOG_DM_TMN_Debug(("DMTree::Add: set strLastInteriorNodeAdded=%s\n", strLastInteriorNodeAdded.c_str() ));
    829           pAddInteriorNodeData->clear();
    830           delete pAddInteriorNodeData;
    831           break;
    832        }
    833        interiorNodeList.push_back(pAddInteriorNodeData);
    834     }
    835 
    836     while ( interiorNodeList.size() > 0 )
    837     {
    838        int idx = interiorNodeList.size() - 1;
    839        pAddInteriorNodeData = interiorNodeList[idx];
    840        if ( wReturnStatusCode == SYNCML_DM_SUCCESS )
    841        {
    842           wReturnStatusCode = AddNodeInternal(*pAddInteriorNodeData, eRequestType);
    843        }
    844        pAddInteriorNodeData->clear();
    845        delete pAddInteriorNodeData;
    846        interiorNodeList.remove(idx);
    847     }
    848 
    849     // Add target node again
    850     if ( wReturnStatusCode == SYNCML_DM_SUCCESS )
    851     {
    852        wReturnStatusCode = AddNodeInternal(oAddData, eRequestType);
    853     }
    854 
    855     if ( wReturnStatusCode != SYNCML_DM_SUCCESS && strLastInteriorNodeAdded != NULL )
    856     {
    857        XPL_LOG_DM_TMN_Debug(("DMTree::Add: deleting last added node \n"));
    858        Delete(strLastInteriorNodeAdded.c_str(),SYNCML_DM_REQUEST_TYPE_INTERNAL);
    859     }
    860     return wReturnStatusCode;
    861 }
    862 
    863 SYNCML_DM_RET_STATUS_T DMTree::AddNodeInternal( DMAddData & oAddData,
    864                                                               SYNCML_DM_REQUEST_TYPE_T eRequestType)
    865 {
    866   m_oLockContextManager.OnTreeAccessed();
    867 
    868   DMString strURI;
    869   DMString strPluginURI;  // uri without ?xxx stuff for plugins and so on
    870   SYNCML_DM_RET_STATUS_T wReturnStatusCode;
    871 
    872   if ( !GetPluginURI( oAddData.getURI(), strURI, strPluginURI ) )
    873   {
    874     XPL_LOG_DM_TMN_Debug(("DMTree::Add: GetPluginURI path:%s\n",oAddData.getURI() ));
    875     return SYNCML_DM_COMMAND_FAILED;
    876   }
    877 
    878   XPL_LOG_DM_TMN_Debug(("DMTree::Add: Validating URI:%s\n",strURI.c_str()));
    879   SYNCML_DM_URI_RESULT_T wURIValidateRetCode = URIValidateAndParse( strURI );
    880 
    881   // if wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE
    882   // means the server has fired adding the following commands
    883   // example: ./TestAdd?prop=Format, ./Adding?prop=Type etc.
    884   switch(wURIValidateRetCode)
    885   {
    886     case SYNCML_DM_COMMAND_URI_TOO_LONG:
    887          return(SYNCML_DM_URI_TOO_LONG);
    888     case SYNCML_DM_COMMAND_INVALID_URI:
    889          return(SYNCML_DM_COMMAND_FAILED);
    890     case SYNCML_DM_COMMAND_ON_NODE :
    891           //do nothing here,proceed
    892          break;
    893     default:
    894          return(SYNCML_DM_COMMAND_NOT_ALLOWED);
    895   }
    896 
    897   XPL_LOG_DM_TMN_Debug(("DMTree::Add: Get Node name from:%s\n",strURI.c_str()));
    898   // The last segment of URI contains the node name
    899   DMString strLastSegment;
    900   if ( !GetLastSegmentOfURI(strURI, strLastSegment ) )
    901     return(SYNCML_DM_COMMAND_FAILED);
    902 
    903   // FindNodeByURI() function returns the node pointer
    904   // of the last segment of the node name.
    905   XPL_LOG_DM_TMN_Debug(("DMTree::Add: Check permission to write:%s\n",strURI.c_str()));
    906   // check permission to write
    907   if (!VerifyArchiveWriteAccess(strURI)) {
    908     XPL_LOG_DM_TMN_Error(("archive has no write access for uri %s\n", strURI.c_str()));
    909     return (SYNCML_DM_COMMAND_NOT_ALLOWED);
    910   }
    911 
    912   XPL_LOG_DM_TMN_Debug(("DMTree::Add: Get Parent Node from:%s\n",strURI.c_str()));
    913   DMNode  *psParentNodeOftheAddingNode = FindNodeByURI(strURI);
    914   BOOLEAN bInPlugin = FALSE;
    915 
    916   if (psParentNodeOftheAddingNode &&
    917       psParentNodeOftheAddingNode->isPlugin())
    918   {
    919     bInPlugin = TRUE;
    920   }
    921   else if ( m_ptrCacheOPI != NULL )
    922   {  // OPI support:
    923       DMNode *pNode = FindNodeByURI( strPluginURI );
    924 
    925       if ( pNode && pNode->isPlugin() )
    926       {
    927         psParentNodeOftheAddingNode = pNode;
    928         bInPlugin = TRUE;
    929       }
    930   }
    931 
    932   // If the Parent doesn't exists then FindNodeByURI will return
    933   // NULL and If the parent of the Addind node is a leaf node then we
    934   // SHOULD NOT to create a node under a leaf node.
    935 
    936   if(!bInPlugin &&
    937      ((psParentNodeOftheAddingNode == NULL) ||
    938      (psParentNodeOftheAddingNode->bFormat != SYNCML_DM_FORMAT_NODE)))
    939   {
    940     XPL_LOG_DM_TMN_Debug(("Either the Parent does not exists or the server \
    941                  is trying to add a node under a leaf node \n"));
    942     return psParentNodeOftheAddingNode == NULL ? SYNCML_DM_NOT_FOUND : SYNCML_DM_COMMAND_NOT_ALLOWED;
    943   }
    944 
    945   XPL_LOG_DM_TMN_Debug(("DMTree::Add: Parent Node got successfully\n Check isEnabled\n"));
    946   BOOLEAN bIsEnabled;
    947   bIsEnabled = IsUriEnabled(oAddData.getURI());
    948   if ( bIsEnabled == FALSE )
    949        return SYNCML_DM_FEATURE_NOT_SUPPORTED;
    950 
    951 
    952   XPL_LOG_DM_TMN_Debug(("DMTree::Add: check if the new node already exists\n"));
    953   DMNode *psPluginNode = NULL;
    954    // The following condition is used to checks if the node already
    955    // exists
    956   if (bInPlugin)
    957   {
    958       psPluginNode = psParentNodeOftheAddingNode;
    959 
    960       if (psPluginNode->Find(oAddData.getURI()) == SYNCML_DM_SUCCESS) {
    961            XPL_LOG_DM_TMN_Debug(("DMTree::Add: pluginNode already exists \n"));
    962            return(SYNCML_DM_TARGET_ALREADY_EXISTS);
    963       }
    964   }
    965   else
    966   {
    967       if(FindNodeInNextSiblingsList(psParentNodeOftheAddingNode->pcFirstChild,strLastSegment) != NULL) {
    968           XPL_LOG_DM_TMN_Debug(("DMTree::Add: node already exists \n"));
    969           return(SYNCML_DM_TARGET_ALREADY_EXISTS);
    970       }
    971   }
    972 
    973 
    974   XPL_LOG_DM_TMN_Debug(("DMTree::Add: check access type and ACL permissions\n"));
    975   DMMetaPCharVector asChildDepend;  // array of child/dependend nodes for indirect updates
    976   // check the Access type and ACL permissions.
    977   wReturnStatusCode = IsValidServer(strURI,
    978                                                    SYNCML_DM_ADD_ACCESS_TYPE,
    979                                                    eRequestType,
    980                                                    TRUE,
    981                                                    TRUE,
    982                                                    &asChildDepend);
    983 
    984   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
    985   {
    986     XPL_LOG_DM_TMN_Debug(("DMTree::Add: IsValidServer uri:%s %d\n",strURI.c_str(), wReturnStatusCode));
    987      return(wReturnStatusCode);
    988   }
    989   UINT16 count = GetChildrenCount(psParentNodeOftheAddingNode);
    990   BOOLEAN bOPiDataParent = FALSE; // indicator that plug-in wants to store some data inside
    991 
    992   BOOLEAN bESN = FALSE; // Is an ESN
    993 
    994 #ifdef LOB_SUPPORT
    995     bESN = m_oMDFObj.IsESN(oAddData.getURI() );
    996     oAddData.SetESN(bESN);
    997 #endif
    998   if ( !m_oMDFObj.VerifyChildrenMultiNodesCount(strURI,count, bOPiDataParent) )
    999     return SYNCML_DM_DEVICE_FULL;
   1000 
   1001   DMNode *psAddingNode = NULL;
   1002 
   1003   if (!bInPlugin)
   1004   {
   1005       XPL_LOG_DM_TMN_Debug(("DMTree::Add: not plugin, create node\n"));
   1006       psAddingNode = CreateNodeObj( bOPiDataParent ? SYNCML_DM_FORMAT_NODE_PDATA : oAddData.m_nFormat, bESN, NULL);
   1007 
   1008       if(psAddingNode == NULL)
   1009       {
   1010         XPL_LOG_DM_TMN_Debug(("CreateNodeObj returned NULL pointer \n"));
   1011         return(SYNCML_DM_COMMAND_FAILED);
   1012       }
   1013 
   1014       if ( bOPiDataParent && psAddingNode->getOverlayPIData())
   1015       {
   1016         wReturnStatusCode = OnOPiAdd(oAddData.getURI(), *psAddingNode->getOverlayPIData());
   1017 
   1018         if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1019         {
   1020           XPL_LOG_DM_TMN_Debug(("DMTree::Add: OnOPiAdd uri:%s %d\n",oAddData.getURI(), wReturnStatusCode));
   1021           delete(psAddingNode);
   1022           return(wReturnStatusCode);
   1023         }
   1024 
   1025       }
   1026   }
   1027 
   1028   XPL_LOG_DM_TMN_Debug(("DMTree::Add: check if server has replace permission\n"));
   1029   // This function checks if the server has replace permissions
   1030   SYNCML_DM_RET_STATUS_T wLocalRetStatusCode;
   1031   wLocalRetStatusCode = IsValidServer(strURI,
   1032                                                      SYNCML_DM_REPLACE_ACCESS_TYPE,
   1033                                                      eRequestType,
   1034                                                      FALSE,
   1035                                                      TRUE);
   1036 
   1037   if (!bInPlugin) {
   1038       psAddingNode->abNodeName = strLastSegment;
   1039   }
   1040 
   1041   // If the current connected doesn't have ACL permissions on
   1042   // replace command then we have to give all the ACL command
   1043   // permissions to connected server.
   1044 
   1045   if(wLocalRetStatusCode == SYNCML_DM_PERMISSION_FAILED)
   1046   {
   1047         wLocalRetStatusCode = SetACL(oAddData.getURI());
   1048         if ( wLocalRetStatusCode != SYNCML_DM_SUCCESS )
   1049         {
   1050              delete(psAddingNode);
   1051              return(wLocalRetStatusCode);
   1052         }
   1053   }
   1054 
   1055   DMNode *psTheNode = (bInPlugin) ? psPluginNode : psAddingNode;
   1056   DMToken aAutoNodes(SYNCML_DM_COMMA);
   1057 
   1058   BOOLEAN bNodeGetAccess;
   1059 
   1060   XPL_LOG_DM_TMN_Debug(("DMTree::Add: verify parameters\n"));
   1061   wReturnStatusCode = m_oMDFObj.VerifyAddParameters(psTheNode,oAddData,aAutoNodes,bNodeGetAccess);
   1062 
   1063   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1064   {
   1065     XPL_LOG_DM_TMN_Debug(("MDF check returned failure status code \n"));
   1066     delete psAddingNode;
   1067     return(wReturnStatusCode);
   1068   }
   1069 
   1070   wReturnStatusCode = psTheNode->Add(oAddData);
   1071 
   1072   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1073   {
   1074     XPL_LOG_DM_TMN_Debug(("Plug-in Add returned failure status code \n"));
   1075     delete psAddingNode;
   1076     return wReturnStatusCode;
   1077   }
   1078 
   1079   XPL_LOG_DM_TMN_Debug(("DMTree::Add: setup the links of the node before adding the node into the tree\n"));
   1080   if (!bInPlugin)
   1081   {
   1082         // Setup the links of the node before adding the node into the tree
   1083         if ( bNodeGetAccess == FALSE )
   1084             psAddingNode->addFlags(DMNode::enum_NodeNoGetAccess);
   1085         psAddingNode->pcParentOfNode = psParentNodeOftheAddingNode;
   1086         psAddingNode->pcFirstChild = NULL;
   1087         psAddingNode->bFormat = oAddData.m_nFormat;
   1088 
   1089         if(psParentNodeOftheAddingNode->pcFirstChild)
   1090         {
   1091           // if the current addind node is NOT the first child of the
   1092           // parent then insert the node in the siblings list.
   1093 
   1094           wReturnStatusCode = InsertNodeIntoNextSiblingsList
   1095                               (psParentNodeOftheAddingNode->pcFirstChild,
   1096                                psAddingNode);
   1097         }
   1098         else
   1099         {
   1100           // if the current adding node is the first child of the
   1101           // parent then assign adding node pointer tp parent first
   1102           // child pointer.
   1103 
   1104           psParentNodeOftheAddingNode->pcFirstChild = psAddingNode;
   1105         }
   1106 
   1107 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1108         if ( psParentNodeOftheAddingNode )
   1109         {
   1110            // Set timestamp and version number for parent Node
   1111            // Use parentURI's URI.
   1112            psParentNodeOftheAddingNode->SetTStamp(strURI.c_str(),XPL_CLK_GetClock());
   1113            psParentNodeOftheAddingNode->SetVerNo(strURI.c_str(),psParentNodeOftheAddingNode->GetVerNo(strURI)+1);
   1114         }
   1115 #endif
   1116 
   1117   }
   1118 
   1119   XPL_LOG_DM_TMN_Debug(("DMTree::Add: set time stamp and version number, add auto nodes\n"));
   1120 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1121   if (psAddingNode)
   1122   {
   1123         // Set timestamp and version number for currently added Node
   1124         psAddingNode->SetTStamp(strPluginURI.c_str(),XPL_CLK_GetClock());
   1125         psAddingNode->SetVerNo(strPluginURI.c_str(),0);
   1126   }
   1127 #endif
   1128 
   1129   wReturnStatusCode = AddAutoNodes(oAddData.getURI(), eRequestType, aAutoNodes);
   1130   if ( wReturnStatusCode != SYNCML_DM_SUCCESS )
   1131   {
   1132     Delete(oAddData.getURI(),SYNCML_DM_REQUEST_TYPE_INTERNAL);
   1133     return wReturnStatusCode;
   1134    }
   1135 
   1136 #ifdef LOB_SUPPORT
   1137      if(bESN)
   1138           SetESNCache(oAddData.getURI(), psTheNode);
   1139 #endif
   1140    XPL_LOG_DM_TMN_Debug(("DMTree::Add: log command and send event\n"));
   1141    //Logging the command which was executed successfully in the log file
   1142    LogEvent(SYNCML_DM_EVENT_ADD, oAddData.getURI());
   1143    if ( asChildDepend.size() > 0 )
   1144       CheckForIndirectUpdates( oAddData.getURI(), asChildDepend, psTheNode );
   1145 
   1146    if ( bInPlugin == FALSE &&  oAddData.m_nFormat == SYNCML_DM_FORMAT_NODE &&
   1147         m_ptrCacheOPI )
   1148    {
   1149       DMNode *psPluginFantomNode = new DMPluginRootNode( m_ptrCacheOPI );
   1150 
   1151       if ( psPluginFantomNode == NULL )
   1152         return SYNCML_DM_DEVICE_FULL;
   1153 
   1154       psPluginFantomNode->SetAddedNode(oAddData.getURI());
   1155 
   1156       DMNode::operator delete  (psPluginFantomNode);
   1157    }
   1158 
   1159   XPL_LOG_DM_TMN_Debug(("DMTree::Add: returing\n"));
   1160 
   1161   return(wReturnStatusCode);
   1162 }
   1163 
   1164 //------------------------------------------------------------------------
   1165 // FUNCTION        : Delete
   1166 //
   1167 // DESCRIPTION     : This function deletes the node incase if the directly
   1168 //                   referenced node is an interior node then it deletes
   1169 //                   it childs also. Before deleting the node first it
   1170 //                   checks the ACL incase if the directly referenced node
   1171 //                   is an interior node then it checks the ACL of childs
   1172 //                   also. In case if the ACL permissions are then then
   1173 //                   it calls plug-in.Delete function. If
   1174 //                   plug-in.Delete function returns SUCCESS then this
   1175 //                   function deletes the node from the tree.
   1176 //
   1177 //
   1178 // ARGUMENTS PASSED: UINT32 commandId
   1179 //                   UINT8 itemNumber
   1180 //                   UINT8 *pbURI
   1181 //                        -- URI of the deleting node.
   1182 //                   BOOLEAN isThisAtomic
   1183 //
   1184 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
   1185 //                     - It returns SYNCML_DM_URI_TOO_LONG incase if the
   1186 //                       URI is too long.
   1187 //                     - It returns SYNCML_DM_COMMAND_FAILED incase if the
   1188 //                       URI is invalid like ?prop=Name.
   1189 //                     - It returns SYNCML_DM_NOT_FOUND incase if the
   1190 //                       node does not exists.
   1191 //                     - It returns SYNCML_DM_COMMAND_NOT_ALLOWED incase
   1192 //                       if the referenced node is a permanent node.
   1193 //                     - It returns 206 incase if the this function
   1194 //                       deletes only part of the directly referenced node.
   1195 //                       This mostly happens if the referenced node is
   1196 //                       an interior node.
   1197 //                     - It returns SYNCML_DM_SUCCESS incase this function
   1198 //                       deletes node succefully from the tree.
   1199 //                     - It returns SYNCML_DM_INVALID_URI
   1200 //                       if the node path is not valid for current DMT version
   1201 //
   1202 // PRE-CONDITIONS  :
   1203 // POST-CONDITIONS :
   1204 // IMPORTANT NOTES :
   1205 //------------------------------------------------------------------------
   1206 SYNCML_DM_RET_STATUS_T DMTree::Delete(CPCHAR pbURI,
   1207                                                                  SYNCML_DM_REQUEST_TYPE_T eRequestType)
   1208 {
   1209   m_oLockContextManager.OnTreeAccessed();
   1210 
   1211   DMString strPluginURI;  // uri without ?xxx stuff for plugins and so on
   1212   DMString strURI;
   1213   SYNCML_DM_RET_STATUS_T wReturnStatusCode;
   1214   DMNode *psDeletingNode = NULL;
   1215   SYNCML_DM_RET_STATUS_T wURIValidateRetCode;
   1216   BOOLEAN bInPlugin = FALSE;
   1217 
   1218   if ( !GetPluginURI( pbURI, strURI, strPluginURI ) )
   1219     return SYNCML_DM_COMMAND_FAILED;
   1220 
   1221   // We are maintaing a local of the URI send by the UA
   1222   // because we are going to modify the URI value.
   1223   // This checks for a relative URI if so, force the ./
   1224 
   1225   wURIValidateRetCode = URIValidateAndParse( strURI );
   1226   if(wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE)
   1227   {
   1228     if(wURIValidateRetCode == SYNCML_DM_COMMAND_URI_TOO_LONG)
   1229       return(SYNCML_DM_URI_TOO_LONG);
   1230     else
   1231     {
   1232       XPL_LOG_DM_TMN_Debug(("Invalid URI \n"));
   1233       return(SYNCML_DM_COMMAND_FAILED);
   1234     }
   1235   }
   1236   // check permission to write
   1237   if (!VerifyArchiveWriteAccess(strURI)) {
   1238     XPL_LOG_DM_TMN_Error(("archive has no write access for uri %s\n", strURI.c_str()));
   1239     return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   1240   }
   1241 
   1242   psDeletingNode = FindNodeByURI(strURI);
   1243   BOOLEAN bIsEnabled;
   1244   bIsEnabled = IsUriEnabled(strURI);
   1245 
   1246   // In Node or Parent does NOT exists
   1247   if(psDeletingNode == NULL)
   1248   {
   1249     XPL_LOG_DM_TMN_Debug(("Node not exists in the Tree \n"));
   1250 
   1251     if ( bIsEnabled == FALSE )
   1252           return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1253     else
   1254          return SYNCML_DM_NOT_FOUND;
   1255   }
   1256   else
   1257   {
   1258     if ( bIsEnabled == FALSE )
   1259       return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1260   }
   1261 
   1262   bInPlugin = psDeletingNode->isPlugin();
   1263 
   1264   // Is this the correct position to check this condition
   1265   if(psDeletingNode->isPermanent())
   1266   {
   1267     XPL_LOG_DM_TMN_Debug(("Deleting node is a PERMANENT node \n"));
   1268     return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   1269   }
   1270 
   1271   //YXU if Node is .
   1272   if(psDeletingNode->pcParentOfNode == NULL && !bInPlugin)
   1273   {
   1274     XPL_LOG_DM_TMN_Debug(("Deleting . node is a PERMANENT node \n"));
   1275     return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   1276   }
   1277 
   1278   wReturnStatusCode = IsValidServer(strURI,
   1279                                                    SYNCML_DM_DELETE_ACCESS_TYPE,
   1280                                                    eRequestType,
   1281                                                    TRUE,
   1282                                                    TRUE);
   1283 
   1284   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1285   {
   1286     return(wReturnStatusCode);
   1287   }
   1288 
   1289 
   1290   //This function is checking for the ACL permissions of
   1291   //an interior.
   1292   DMStringVector aChildren;
   1293   if(!bInPlugin &&
   1294      (psDeletingNode->bFormat == SYNCML_DM_FORMAT_NODE) &&
   1295      (psDeletingNode->pcFirstChild != NULL))
   1296   {
   1297      if ( eRequestType == SYNCML_DM_REQUEST_TYPE_SERVER )
   1298          wReturnStatusCode = CheckDeleteForNode(psDeletingNode,strURI);
   1299   }
   1300 
   1301   if (bInPlugin )
   1302   {
   1303     wReturnStatusCode = CheckDeleteForPluginNodes(eRequestType,strURI, psDeletingNode, aChildren);
   1304   }
   1305 
   1306   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1307      return wReturnStatusCode;
   1308 
   1309   //If the all the nodes the has ACL permissions then
   1310   //we have to delete the nodes from the tree after
   1311   //calling Delete of each node. In case of atomic
   1312   //we are not deleting any node from the tree here
   1313   //we are deleting the tree in DataCommit or
   1314   //RollBack function.
   1315 
   1316   SYNCML_DM_FORMAT_T format = psDeletingNode->bFormat;
   1317   if (!bInPlugin)
   1318   {
   1319         if ( psDeletingNode->IsOverlayPIData() && m_ptrCacheOPI != NULL ) // notify plug-in first
   1320         {
   1321           wReturnStatusCode = OnOPiDelete( strURI );
   1322         }
   1323 
   1324         if ( wReturnStatusCode == SYNCML_DM_SUCCESS )
   1325           wReturnStatusCode = DeleteNode(psDeletingNode,strURI,aChildren);
   1326 
   1327   } else
   1328         wReturnStatusCode = psDeletingNode->Delete( strURI );
   1329 
   1330   if ( wReturnStatusCode != SYNCML_DM_SUCCESS )
   1331     return wReturnStatusCode;
   1332 
   1333   if ( bInPlugin == FALSE &&
   1334        format == SYNCML_DM_FORMAT_NODE &&
   1335        m_ptrCacheOPI )
   1336   {
   1337 
   1338          DMNode* psPluginFantomNode = new DMPluginRootNode( m_ptrCacheOPI );
   1339 
   1340          if ( psPluginFantomNode == NULL )
   1341             return SYNCML_DM_DEVICE_FULL;
   1342 
   1343          psPluginFantomNode->RemoveAddedNode(strURI);
   1344 
   1345          DMNode::operator delete  (psPluginFantomNode);
   1346   }
   1347 
   1348 
   1349   m_oACLObj.Delete(strURI);
   1350   LogEvent(pbURI,aChildren);
   1351 
   1352 #ifdef LOB_SUPPORT
   1353    RemoveESNCache(pbURI);
   1354 #endif
   1355 
   1356   return(wReturnStatusCode);
   1357 }
   1358 
   1359 
   1360 //------------------------------------------------------------------------
   1361 // FUNCTION        : Exec
   1362 //
   1363 // DESCRIPTION     : This function execute the node by fist check permission
   1364 //                     - It returns SYNCML_DM_INVALID_URI
   1365 //                       if the node path is not valid for current DMT version
   1366 //------------------------------------------------------------------------
   1367 SYNCML_DM_RET_STATUS_T DMTree::Exec(CPCHAR pbURI,
   1368                                      CPCHAR pExecData,
   1369                                      DMString & oExecResult,
   1370                                      CPCHAR szCorrelator)
   1371 {
   1372   SYNCML_DM_RET_STATUS_T wReturnStatusCode;
   1373 
   1374   m_oLockContextManager.OnTreeAccessed();
   1375 
   1376   XPL_LOG_DM_TMN_Debug(("Entered DMTree::Exec \n"));
   1377 
   1378   if(pbURI == NULL)
   1379   {
   1380     XPL_LOG_DM_TMN_Debug(("DMTree::Exec: pbURI is null\n"));
   1381     return(SYNCML_DM_COMMAND_FAILED);
   1382   }
   1383 
   1384   char *abTempURI = (char*) DmAllocMem(GetMaxTotalPathLength() + 1);
   1385   if(abTempURI == NULL)
   1386   {
   1387      XPL_LOG_DM_TMN_Debug(("DMTree::Exec: abTempURI allocate memory failed\n"));
   1388      return SYNCML_DM_DEVICE_FULL;
   1389   }
   1390 
   1391   abTempURI[0] = '\0';
   1392 
   1393   XPL_LOG_DM_TMN_Debug(("Server fired <Exec> on: %s \n", pbURI));
   1394 
   1395   UINT16 bStringLength = DmStrlen(pbURI);
   1396   // We are maintaing a local of the URI send by the UA
   1397   // because we are going to modify the URI value.
   1398   // This checks for a relative URI if so, force the ./
   1399 
   1400   if(pbURI[0] != SYNCML_DM_DOT)
   1401   {
   1402     abTempURI[0] = SYNCML_DM_DOT;
   1403     abTempURI[1] = SYNCML_DM_FORWARD_SLASH;
   1404     abTempURI[2] = '\0';
   1405     bStringLength += SYNCML_DM_RELATIVE_URI_OFFSET_LENGTH; // For "./"
   1406   }
   1407 
   1408   if(bStringLength > GetMaxTotalPathLength() )
   1409   {
   1410       XPL_LOG_DM_TMN_Debug(("URI Too long \n"));
   1411       DmFreeMem(abTempURI);
   1412       return(SYNCML_DM_URI_TOO_LONG);
   1413   }
   1414 
   1415   DmStrcat(abTempURI, pbURI);
   1416 
   1417   SYNCML_DM_RET_STATUS_T wURIValidateRetCode = URIValidateAndParse(abTempURI);
   1418 
   1419   if(wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE)
   1420   {
   1421     if(wURIValidateRetCode == SYNCML_DM_COMMAND_URI_TOO_LONG)
   1422     {
   1423       XPL_LOG_DM_TMN_Debug(("URI Too long \n"));
   1424       DmFreeMem(abTempURI);
   1425       return(SYNCML_DM_URI_TOO_LONG);
   1426     }
   1427     else
   1428     {
   1429       XPL_LOG_DM_TMN_Debug(("Invalid URI \n"));
   1430       DmFreeMem(abTempURI);
   1431       return(SYNCML_DM_COMMAND_FAILED);
   1432     }
   1433   }
   1434 
   1435   DMNode *psExecNode = FindNodeByURI(abTempURI);
   1436 
   1437   // In Node or Parent does NOT exists
   1438   BOOLEAN bIsEnabled;
   1439   bIsEnabled = IsUriEnabled(abTempURI);
   1440 
   1441   if(psExecNode == NULL)
   1442   {
   1443     XPL_LOG_DM_TMN_Debug(("Node not exists in the Tree \n"));
   1444     DmFreeMem(abTempURI);
   1445     if ( bIsEnabled == FALSE )
   1446        return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1447     else
   1448        return SYNCML_DM_NOT_FOUND;
   1449   }
   1450   else
   1451   {
   1452     if ( bIsEnabled == FALSE )
   1453     {
   1454         DmFreeMem(abTempURI);
   1455         XPL_LOG_DM_TMN_Debug(("DMTree::Exec: Node not enabled! \n"));
   1456         return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1457     }
   1458   }
   1459 
   1460   wReturnStatusCode = IsValidServer(abTempURI,
   1461                                     SYNCML_DM_EXEC_ACCESS_TYPE,
   1462                                     SYNCML_DM_REQUEST_TYPE_SERVER,
   1463                                     TRUE,
   1464                                     TRUE);
   1465 
   1466   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1467   {
   1468     DmFreeMem(abTempURI);
   1469     XPL_LOG_DM_TMN_Debug(("DMTree::Exec: Not valid server! \n"));
   1470     return(wReturnStatusCode);
   1471   }
   1472   XPL_LOG_DM_TMN_Debug(("DMTree::Exec: Execute plugin... \n"));
   1473   if ( pExecData )
   1474      wReturnStatusCode=DmExecutePlugin(abTempURI,pExecData,szCorrelator,oExecResult);
   1475   else
   1476      wReturnStatusCode=DmExecutePlugin(abTempURI,"",szCorrelator,oExecResult);
   1477 
   1478   DmFreeMem(abTempURI);
   1479 
   1480   XPL_LOG_DM_TMN_Debug(("Exec: exec plugin for uri %s, data %s, correlator %s returned %d\n",
   1481                         abTempURI,
   1482                         pExecData ? pExecData : "<NULL>",
   1483                         szCorrelator,
   1484                         wReturnStatusCode));
   1485 
   1486   return(wReturnStatusCode);
   1487 }
   1488 
   1489 
   1490 //------------------------------------------------------------------------
   1491 // FUNCTION        : Get
   1492 // DESCRIPTION     : Get Node value
   1493 // ARGUMENTS PASSED: the URI(target to get)
   1494 //                   the pointer to the structure to return after filling in the value
   1495 // RETURN VALUE    : status code indicating result of the operation
   1496 //                   and the structure filled with the values
   1497 // PRE-CONDITIONS  : ONLY THE DM ENGINE INVOKES THIS,it is an INTERNAL
   1498 //                   METHOD
   1499 // POST-CONDITIONS : The UA is able to retrieve the value through the
   1500 //                   return structure
   1501 // IMPORTANT NOTES :
   1502 //------------------------------------------------------------------------
   1503 SYNCML_DM_RET_STATUS_T DMTree::Get(CPCHAR pbUri,
   1504                                             DMGetData & oReturnData,
   1505                                             SYNCML_DM_REQUEST_TYPE_T eRequestType)
   1506 {
   1507 
   1508   m_oLockContextManager.OnTreeAccessed();
   1509 
   1510   DMNode *psGetNode = NULL;
   1511   SYNCML_DM_URI_RESULT_T  wURIValidateRetCode;
   1512   SYNCML_DM_RET_STATUS_T wReturnStatusCode = SYNCML_DM_SUCCESS;
   1513   DMString strPluginURI;  // uri without ?xxx stuff for plugins and so on
   1514   DMString strURI;
   1515 
   1516   if ( !GetPluginURI( pbUri, strURI, strPluginURI ) )
   1517     return SYNCML_DM_COMMAND_FAILED;
   1518 
   1519   wURIValidateRetCode = URIValidateAndParse( strURI );
   1520   switch(wURIValidateRetCode)
   1521   {
   1522     case SYNCML_DM_COMMAND_INVALID_URI:
   1523           return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   1524 
   1525     case SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY:
   1526            return(SYNCML_DM_FEATURE_NOT_SUPPORTED);
   1527 
   1528     default :
   1529              //not processed immedietely,do nothing
   1530     break;
   1531   }
   1532 
   1533   XPL_LOG_DM_TMN_Debug(("Get %s, %s, %s\n", pbUri, strURI.c_str(), strPluginURI.c_str()));
   1534   // check permission to read
   1535   if (!VerifyArchiveReadAccess(strPluginURI)) {
   1536     XPL_LOG_DM_TMN_Error(("archive has no read access for uri %s\n", strPluginURI.c_str()));
   1537     return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   1538   }
   1539 
   1540   psGetNode = FindNodeByURI( strPluginURI );
   1541 
   1542   BOOLEAN bIsEnabled;
   1543   bIsEnabled = IsUriEnabled(strPluginURI);
   1544   if(psGetNode == NULL) // If this node doesn't exist
   1545   {
   1546     if ( bIsEnabled == FALSE )
   1547         return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1548     else
   1549             return SYNCML_DM_NOT_FOUND;
   1550 
   1551   }
   1552   else
   1553   {
   1554     if ( bIsEnabled == FALSE )
   1555        return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1556   }
   1557 
   1558   if ( eRequestType != SYNCML_DM_REQUEST_TYPE_INTERNAL )
   1559   {
   1560 
   1561     if( psGetNode->IsGetAccess(strPluginURI) == FALSE )
   1562       return     SYNCML_DM_COMMAND_NOT_ALLOWED;
   1563 
   1564     wReturnStatusCode = IsValidServer(strPluginURI,
   1565                                                     SYNCML_DM_GET_ACCESS_TYPE,
   1566                                                     eRequestType,
   1567                                                     TRUE,
   1568                                                     TRUE);
   1569 
   1570     if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1571       return(wReturnStatusCode);
   1572   }
   1573 
   1574   DMString strData;
   1575   SYNCML_DM_FORMAT_T bNodeFormat = SYNCML_DM_FORMAT_CHR;
   1576 #ifdef LOB_SUPPORT
   1577   oReturnData.SetESN(psGetNode->IsESN());
   1578 #endif
   1579 
   1580   switch(wURIValidateRetCode)
   1581   {
   1582     case SYNCML_DM_COMMAND_ON_NODE:
   1583       if(psGetNode->bFormat != SYNCML_DM_FORMAT_NODE)
   1584       {
   1585         return psGetNode->Get(strPluginURI, oReturnData);
   1586       }
   1587       else
   1588       {
   1589         wReturnStatusCode = GetChildren(strPluginURI, psGetNode, eRequestType, strData );
   1590         bNodeFormat = SYNCML_DM_FORMAT_NODE;
   1591       }
   1592     break;
   1593 
   1594     case SYNCML_DM_COMMAND_ON_ACL_PROPERTY:
   1595       m_oACLObj.GetACL(strPluginURI, strData);
   1596       break;
   1597 
   1598     case SYNCML_DM_COMMAND_ON_FORMAT_PROPERTY:
   1599     {
   1600       SYNCML_DM_FORMAT_T dwFormat = 0;
   1601 
   1602       if(psGetNode->bFormat == SYNCML_DM_FORMAT_NODE)
   1603       {
   1604         dwFormat = SYNCML_DM_FORMAT_NODE;
   1605         wReturnStatusCode = SYNCML_DM_SUCCESS;
   1606       }
   1607       else
   1608       {
   1609         wReturnStatusCode = psGetNode->GetFormat(strPluginURI,&dwFormat);
   1610       }
   1611 
   1612       if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   1613         wReturnStatusCode = ConvertFormat(dwFormat,strData);
   1614     }
   1615     break;
   1616 
   1617     case SYNCML_DM_COMMAND_ON_TYPE_PROPERTY:
   1618       wReturnStatusCode = psGetNode->GetType(strPluginURI, strData);
   1619     break;
   1620 
   1621 #ifdef LOB_SUPPORT
   1622     case SYNCML_DM_COMMAND_ON_ESN_PROPERTY:
   1623        {
   1624           char szSize[4];
   1625     BOOLEAN  bESN = FALSE;
   1626     wReturnStatusCode = psGetNode->IsESN(strPluginURI, bESN);
   1627     if(bESN)
   1628               DmSprintf(szSize, "%s", "yes");
   1629     else
   1630               DmSprintf(szSize, "%s", "no");
   1631           strData = szSize;
   1632         }
   1633      break;
   1634 #endif
   1635 
   1636     case SYNCML_DM_COMMAND_ON_SIZE_PROPERTY:
   1637     {
   1638       UINT32 dwSize = 0;
   1639       char szSize[ SIZE_LENGTH + 1 ];
   1640 
   1641       wReturnStatusCode = psGetNode->GetSize(strPluginURI,&dwSize);
   1642 
   1643       if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   1644       {
   1645           DmSprintf(szSize, "%d", dwSize);
   1646           strData = szSize;
   1647       }
   1648     }
   1649     break;
   1650 
   1651     case SYNCML_DM_COMMAND_ON_NAME_PROPERTY:
   1652        wReturnStatusCode = psGetNode->GetName(strPluginURI, strData);
   1653     break;
   1654 
   1655     case SYNCML_DM_COMMAND_ON_TITLE_PROPERTY:
   1656       wReturnStatusCode = psGetNode->GetTitle(strPluginURI, strData);
   1657     break;
   1658 
   1659     case SYNCML_DM_COMMAND_ON_TSTAMP_PROPERTY:
   1660 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1661     {
   1662       char szTimeStamp[ TSTAMP_LENGTH+1 ];
   1663       XPL_CLK_CLOCK_T timestamp=psGetNode->GetTStamp(strPluginURI); //In seconds
   1664       //OK, interface uses milleseconds %lld while internal TStamp uses seconds
   1665       DmSprintf(szTimeStamp, "%lld", (XPL_CLK_LONG_CLOCK_T)timestamp * 1000L);
   1666       strData = szTimeStamp;
   1667     }
   1668 #else
   1669       wReturnStatusCode = SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1670 #endif
   1671     break;
   1672 
   1673     case SYNCML_DM_COMMAND_ON_VERNO_PROPERTY:
   1674 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1675     {
   1676       char szVer[ VERSION_LENGTH + 1 ];
   1677       DmSprintf(szVer, "%d", psGetNode->GetVerNo(strPluginURI));
   1678       strData = szVer;
   1679     }
   1680 #else
   1681       wReturnStatusCode = SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1682 #endif
   1683     break;
   1684 
   1685     default:
   1686       wReturnStatusCode = SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1687     break;
   1688   }// End of switch case
   1689 
   1690   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1691     return wReturnStatusCode;
   1692 
   1693   if(strData[0] == 0 && (psGetNode->bFormat != SYNCML_DM_FORMAT_NODE))
   1694     bNodeFormat = SYNCML_DM_FORMAT_NULL;
   1695   return oReturnData.set(bNodeFormat,strData,strData.length(),NULL);
   1696 }
   1697 
   1698 //------------------------------------------------------------------------
   1699 // FUNCTION        : InternalGetAttributes
   1700 // DESCRIPTION     : This method is called INTERNALLY by the DM Engine(UA)
   1701 //                   to mimic the DM GET operation to get the node attributes.
   1702 // ARGUMENTS PASSED:
   1703 //                   pbURI -- URI of the node.
   1704 //                   attrs -- reference to DmtAttributes object.
   1705 //                   bInternalGet -- whether this is an internal call or not.
   1706 // RETURN VALUE    : status code indicating result of the operation
   1707 //                   and the structure filled with the values
   1708 // PRE-CONDITIONS  : ONLY THE DM ENGINE INVOKES THIS,it is an INTERNAL
   1709 //                   METHOD
   1710 // POST-CONDITIONS : The UA is able to retrieve the value through the
   1711 //                   return structure
   1712 // IMPORTANT NOTES :
   1713 //------------------------------------------------------------------------
   1714 SYNCML_DM_RET_STATUS_T DMTree::GetAttributes(CPCHAR pbUri,
   1715                                                       DmtAttributes& attrs,
   1716                                                       SYNCML_DM_REQUEST_TYPE_T eRequestType)
   1717 {
   1718   m_oLockContextManager.OnTreeAccessed();
   1719 
   1720   DMNode *psGetNode = NULL;
   1721   SYNCML_DM_RET_STATUS_T wURIValidateRetCode;
   1722   SYNCML_DM_RET_STATUS_T wReturnStatusCode = SYNCML_DM_SUCCESS;
   1723   DMString strPluginURI;  // uri without ?xxx stuff for plugins and so on
   1724   DMString strURI;
   1725 
   1726   if ( !GetPluginURI( pbUri, strURI, strPluginURI ) )
   1727     return SYNCML_DM_COMMAND_FAILED;
   1728 
   1729   wURIValidateRetCode = URIValidateAndParse( strURI );
   1730   switch(wURIValidateRetCode)
   1731   {
   1732     case SYNCML_DM_COMMAND_INVALID_URI:
   1733        return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   1734 
   1735     case SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY:
   1736        return(SYNCML_DM_FEATURE_NOT_SUPPORTED);
   1737 
   1738     default :
   1739              //not processed immedietely,do nothing
   1740     break;
   1741   }
   1742 
   1743   psGetNode = FindNodeByURI( strPluginURI );
   1744   if(psGetNode == NULL)
   1745   {
   1746     BOOLEAN bIsEnabled;
   1747     bIsEnabled =  IsUriEnabled(strPluginURI);
   1748     if ( bIsEnabled == FALSE )
   1749         return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1750    else
   1751         return SYNCML_DM_NOT_FOUND;
   1752 
   1753   }
   1754 
   1755 
   1756   if ( eRequestType != SYNCML_DM_REQUEST_TYPE_INTERNAL ) {
   1757     wReturnStatusCode = IsValidServer(strPluginURI,
   1758                                                      SYNCML_DM_GET_ACCESS_TYPE,
   1759                                                      eRequestType,
   1760                                                      TRUE,
   1761                                                      TRUE);
   1762 
   1763     if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1764       return(wReturnStatusCode);
   1765   }
   1766 
   1767   DMString strName, strFormat, strTitle, strType, strAcl;
   1768   UINT32 nVer = 0, nSize = 0;
   1769   INT64 timestamp =0;
   1770 
   1771   if (wURIValidateRetCode == SYNCML_DM_COMMAND_ON_NODE)
   1772   {
   1773      wReturnStatusCode = psGetNode->GetName(strPluginURI, strName);
   1774 
   1775      if (wReturnStatusCode != SYNCML_DM_SUCCESS)
   1776         return(wReturnStatusCode);
   1777 
   1778     SYNCML_DM_FORMAT_T dwFormat = 0;
   1779     if(psGetNode->bFormat == SYNCML_DM_FORMAT_NODE)
   1780     {
   1781        dwFormat = SYNCML_DM_FORMAT_NODE;
   1782        wReturnStatusCode = SYNCML_DM_SUCCESS;
   1783     }
   1784     else
   1785         wReturnStatusCode = psGetNode->GetFormat(strPluginURI, &dwFormat);
   1786 
   1787     if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   1788       wReturnStatusCode = ConvertFormat(dwFormat,strFormat);
   1789     else
   1790       return(wReturnStatusCode);
   1791 
   1792     m_oACLObj.GetACL(strPluginURI, strAcl);
   1793     wReturnStatusCode = psGetNode->GetType(strPluginURI, strType);
   1794     wReturnStatusCode = psGetNode->GetTitle(strPluginURI, strTitle);
   1795     wReturnStatusCode = psGetNode->GetSize(strPluginURI, &nSize);
   1796 
   1797 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1798     timestamp=(JemDate)(psGetNode->GetTStamp(strPluginURI) * 1000L);
   1799     nVer = psGetNode->GetVerNo(strPluginURI);
   1800 #else
   1801     return(SYNCML_DM_FEATURE_NOT_SUPPORTED);
   1802 #endif
   1803 
   1804   }
   1805   else
   1806      return(SYNCML_DM_FEATURE_NOT_SUPPORTED);
   1807 
   1808   return attrs.Set(strName, strFormat, strTitle, strType, nVer, nSize, timestamp, DmtAcl(strAcl));
   1809 
   1810 }
   1811 
   1812 BOOLEAN DMTree::NeedCheckParent( const DMString&         strURI,
   1813                                  DMNode                  *psReplacingNode,
   1814                                  BOOLEAN                 bInPlugin,
   1815                                  SYNCML_DM_FORMAT_T  bFormat,
   1816                                  SYNCML_DM_REQUEST_TYPE_T eRequestType)
   1817 {
   1818   BOOLEAN bCheckParent = FALSE;
   1819   BOOLEAN bContinueChecking = TRUE;
   1820 
   1821   if( bFormat == SYNCML_DM_FORMAT_NODE )
   1822   {
   1823     bContinueChecking = ( IsValidServer( strURI,
   1824                                                   SYNCML_DM_REPLACE_ACCESS_TYPE,
   1825                                                   eRequestType,
   1826                                                   FALSE,
   1827                                                   TRUE) != SYNCML_DM_SUCCESS );
   1828   }
   1829 
   1830   if( bContinueChecking )
   1831   {
   1832     if (!bInPlugin)
   1833     {
   1834       if(psReplacingNode->pcParentOfNode )
   1835       {
   1836         bCheckParent = TRUE;
   1837       }
   1838     }
   1839     else
   1840     {
   1841       if( ParentExistsForPluginNode(strURI, psReplacingNode ) )
   1842       {
   1843         bCheckParent = TRUE;
   1844       }
   1845     }
   1846   }
   1847 
   1848   return bCheckParent;
   1849 }
   1850 
   1851 SYNCML_DM_RET_STATUS_T DMTree::ReplaceACLProperty( const DMString&  strURI,
   1852                                                    BOOLEAN          bInPlugin,
   1853                                                    const DMString&  strPluginURI,
   1854                                                    DMAddData&       oReplaceData,
   1855                                                    DMNode*          psReplacingNode )
   1856 {
   1857   SYNCML_DM_RET_STATUS_T wReturnStatusCode = SYNCML_DM_SUCCESS;
   1858 
   1859   if ( strURI == "." )
   1860      return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   1861 
   1862   if((oReplaceData.m_oData.getSize() == 0))
   1863   {
   1864     m_oACLObj.Delete(strURI);
   1865     LogEvent(SYNCML_DM_EVENT_REPLACE,oReplaceData.getURI());
   1866   }
   1867   else
   1868   {
   1869     char *pACL = NULL;
   1870     oReplaceData.m_oData.copyTo(&pACL);
   1871     if( pACL == NULL)
   1872       return SYNCML_DM_DEVICE_FULL;
   1873 
   1874     wReturnStatusCode = ParseACL((UINT8*)pACL);
   1875     if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   1876     {
   1877        LogEvent(SYNCML_DM_EVENT_REPLACE,oReplaceData.getURI());
   1878        if( oReplaceData.m_oURI.compare(".?prop=ACL") )
   1879        {
   1880           XPL_LOG_DM_TMN_Debug(("Server fired <Replace> on the ACL of a Root node \n"));
   1881           UINT8 *pbADDLoc = NULL;
   1882 
   1883           pbADDLoc = (UINT8*)DmStrstr(pACL, "Add=");
   1884           if(pbADDLoc != NULL)
   1885           {
   1886              pbADDLoc += ADD_CMD_LENGTH_IN_ACL;
   1887              if((pbADDLoc != NULL) && (pbADDLoc[0] != SYNCML_DM_STAR))
   1888              {
   1889                XPL_LOG_DM_TMN_Debug(("Root node Replacing ACL value does NOT have \
   1890                             Add permissions to ALL servers it should Add=* \n"));
   1891 
   1892                if (pACL)
   1893                    DmFreeMem(pACL);
   1894                return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   1895              }
   1896           }
   1897           else
   1898           {
   1899               XPL_LOG_DM_TMN_Debug(("Root node Replacing ACL value does NOT have \
   1900                            Add permissions to. This is NOT allowed according to spec \n"));
   1901 
   1902               if (pACL)
   1903                   DmFreeMem(pACL);
   1904               return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   1905           }
   1906       }
   1907 
   1908       m_oACLObj.SetACL(strURI, pACL);
   1909     }
   1910 
   1911     DmFreeMem(pACL);
   1912   }
   1913 
   1914 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1915   if ( (wReturnStatusCode == SYNCML_DM_SUCCESS) && !bInPlugin && psReplacingNode )
   1916   {
   1917     psReplacingNode->SetTStamp(strPluginURI, XPL_CLK_GetClock());
   1918     psReplacingNode->SetVerNo(strPluginURI, psReplacingNode->GetVerNo(strPluginURI) + 1);
   1919   }
   1920 #endif
   1921 
   1922   return wReturnStatusCode;
   1923 }
   1924 
   1925 SYNCML_DM_RET_STATUS_T DMTree::ReplaceTitleProperty( const DMString&  strURI,
   1926                                                      BOOLEAN          bInPlugin,
   1927                                                      const DMString&  strPluginURI,
   1928                                                      DMAddData&       oReplaceData,
   1929                                                      DMNode*          psReplacingNode )
   1930 {
   1931   if( oReplaceData.m_oData.getSize() == 0)
   1932   {
   1933     psReplacingNode->m_strTitle = "";
   1934     LogEvent(SYNCML_DM_EVENT_REPLACE,oReplaceData.getURI());
   1935   }
   1936   else
   1937   {
   1938     if ( oReplaceData.m_oData.getSize() > SYNCML_DM_MAX_TITLE_LENGTH )
   1939     {
   1940      oReplaceData.m_oData.setSize(SYNCML_DM_MAX_TITLE_LENGTH);
   1941     }
   1942 
   1943     psReplacingNode->SetTitle( strURI, oReplaceData.getCharData());
   1944     LogEvent(SYNCML_DM_EVENT_REPLACE,oReplaceData.getURI());
   1945   }
   1946 
   1947 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   1948   // Update timestamp and increment version number !!
   1949   if( !bInPlugin && psReplacingNode)
   1950   {
   1951      psReplacingNode->SetTStamp(strPluginURI.c_str(),XPL_CLK_GetClock());
   1952      psReplacingNode->SetVerNo(strPluginURI.c_str(),psReplacingNode->GetVerNo(strPluginURI.c_str()) + 1);
   1953   }
   1954 #endif
   1955 
   1956   return SYNCML_DM_SUCCESS;
   1957 }
   1958 
   1959 SYNCML_DM_RET_STATUS_T DMTree::ReplaceNodeInternal( const DMString&        strURI,
   1960                                                     DMAddData&             oReplaceData,
   1961                                                     DMNode*                psReplacingNode,
   1962                                                     DMMetaPCharVector&     asChildDepend )
   1963 {
   1964   SYNCML_DM_RET_STATUS_T  wReturnStatusCode = m_oMDFObj.VerifyReplaceParameters(psReplacingNode,
   1965                                                                                 strURI,
   1966                                                                                 oReplaceData,
   1967                                                                                 NULL);
   1968   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   1969       return(wReturnStatusCode);
   1970 
   1971   wReturnStatusCode = psReplacingNode->Replace( oReplaceData );
   1972 
   1973   if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   1974   {
   1975     LogEvent(SYNCML_DM_EVENT_REPLACE,oReplaceData.getURI());
   1976 
   1977 #ifdef LOB_SUPPORT
   1978     if(psReplacingNode->IsESN())
   1979         LogESNCommandForArchiver(oReplaceData.getURI(),psReplacingNode);
   1980 #endif
   1981 
   1982     if ( asChildDepend.size() > 0 )
   1983       CheckForIndirectUpdates( strURI, asChildDepend, psReplacingNode );
   1984   }
   1985 
   1986   return wReturnStatusCode;
   1987 }
   1988 
   1989 SYNCML_DM_RET_STATUS_T DMTree::PrepareNamePropertyReplace( const DMString&        strURI,
   1990                                                            BOOLEAN                bInPlugin,
   1991                                                            DMAddData&             oReplaceData,
   1992                                                            DMNode*                psReplacingNode )
   1993 {
   1994   if(psReplacingNode->isPermanent())
   1995   {
   1996     XPL_LOG_DM_TMN_Debug(("Server fired <Replace> on the name of a permanent node which is NOT allowed \n"));
   1997     return SYNCML_DM_COMMAND_NOT_ALLOWED;
   1998   }
   1999 
   2000   // For a Replace command on the name of a node, the DMTNM shall
   2001   // first verify that the result of the operation will not cause
   2002   // any inconsistencies in the tree, before it executes the command.
   2003 
   2004   // The following condition is used to check if the node name
   2005   // already existing or not
   2006 
   2007   if( oReplaceData.m_oData.getSize() == 0  )
   2008       return(SYNCML_DM_COMMAND_FAILED);
   2009 
   2010   if( oReplaceData.m_oData.getSize() > GetMaxPathSegmentLength() )
   2011   {
   2012      XPL_LOG_DM_TMN_Debug(("Replacing Name is too long \n"));
   2013      return(SYNCML_DM_REQUEST_ENTITY_TOO_LARGE);
   2014   }
   2015 
   2016   if(IsValidSegment((CPCHAR)oReplaceData.m_oData.getBuffer(),oReplaceData.m_oData.getSize()) == FALSE)
   2017      return(SYNCML_DM_COMMAND_FAILED);
   2018 
   2019   BOOLEAN noParent = FALSE;
   2020   if (bInPlugin) {
   2021      if (!ParentExistsForPluginNode(strURI, psReplacingNode))
   2022           noParent = TRUE;
   2023   } else
   2024       if (psReplacingNode->pcParentOfNode == NULL)
   2025           noParent = TRUE;
   2026 
   2027   if (noParent)
   2028      return(SYNCML_DM_COMMAND_FAILED);
   2029 
   2030   return SYNCML_DM_SUCCESS;
   2031 }
   2032 
   2033 SYNCML_DM_RET_STATUS_T DMTree::CheckReplacingNodeName( DMAddData& oReplaceData,
   2034                                                        DMNode*    psReplacingNode )
   2035 {
   2036   SYNCML_DM_RET_STATUS_T  wReturnStatusCode = SYNCML_DM_SUCCESS;
   2037 
   2038   if ( oReplaceData.m_oData.compare(psReplacingNode->abNodeName) )
   2039   {
   2040     if((psReplacingNode->pcParentOfNode != NULL) &&
   2041         psReplacingNode->pcParentOfNode->abNodeName == "." )
   2042     {
   2043          if( oReplaceData.m_oData.compare("DevDetail") ||
   2044              oReplaceData.m_oData.compare("SyncML") ||
   2045              oReplaceData.m_oData.compare("DevInfo") )
   2046          {
   2047             wReturnStatusCode = SYNCML_DM_COMMAND_NOT_ALLOWED;
   2048          }
   2049          else
   2050          {
   2051            wReturnStatusCode = SYNCML_DM_SUCCESS;
   2052          }
   2053     }
   2054     else
   2055     {
   2056        wReturnStatusCode = SYNCML_DM_SUCCESS;
   2057     }
   2058  }
   2059  else
   2060  {
   2061    wReturnStatusCode = SYNCML_DM_COMMAND_NOT_ALLOWED;
   2062  }
   2063 
   2064   return wReturnStatusCode;
   2065 }
   2066 
   2067 SYNCML_DM_RET_STATUS_T DMTree::FixACL( const DMString& strURI,
   2068                                         DMAddData&      oReplaceData )
   2069 {
   2070   DMString dacl;
   2071   m_oACLObj.GetACL(strURI, dacl);
   2072   if (dacl != "")
   2073   {
   2074     DMString strParentURI = strURI, strLastSegment;
   2075 
   2076     if ( !GetLastSegmentOfURI(strParentURI, strLastSegment) )
   2077       return SYNCML_DM_DEVICE_FULL;
   2078 
   2079     strParentURI += "/";
   2080     strParentURI += (CPCHAR)oReplaceData.getCharData();
   2081 
   2082     m_oACLObj.Delete(strURI);
   2083     m_oACLObj.SetACL( strParentURI, dacl);
   2084   }
   2085 
   2086   return SYNCML_DM_SUCCESS;
   2087 }
   2088 
   2089 SYNCML_DM_RET_STATUS_T DMTree::ReplaceNameProperty( const DMString&         strURI,
   2090                                                      BOOLEAN                bInPlugin,
   2091                                                      const DMString&        strPluginURI,
   2092                                                      DMAddData&             oReplaceData,
   2093                                                      DMNode*                psReplacingNode,
   2094                                                      SYNCML_DM_RET_STATUS_T wURIValidateRetCode )
   2095 {
   2096   XPL_LOG_DM_TMN_Error(("ReplaceNameProperty() called \n"));
   2097   SYNCML_DM_RET_STATUS_T  wReturnStatusCode = PrepareNamePropertyReplace( strURI,
   2098                                                                           bInPlugin,
   2099                                                                           oReplaceData,
   2100                                                                           psReplacingNode );
   2101   XPL_LOG_DM_TMN_Error(("From ReplaceNameProperty(): Call to PrepareNamePropertyReplace() returns %d \n", wReturnStatusCode));
   2102 
   2103   if( SYNCML_DM_SUCCESS != wReturnStatusCode ) return wReturnStatusCode;
   2104 
   2105   if(!bInPlugin && (FindNodeInNextSiblingsList((psReplacingNode->pcParentOfNode)->pcFirstChild,
   2106                                                 oReplaceData.getCharData()) != NULL))
   2107   {
   2108     wReturnStatusCode = CheckReplacingNodeName( oReplaceData,
   2109                                                 psReplacingNode );
   2110     XPL_LOG_DM_TMN_Error(("From ReplaceNameProperty(): Call to CheckReplacingNodeName() returns %d \n", wReturnStatusCode));
   2111   }
   2112   else
   2113   {
   2114     DMString origName;
   2115 
   2116     if((wURIValidateRetCode == SYNCML_DM_COMMAND_ON_NAME_PROPERTY) && !bInPlugin)
   2117     {
   2118       origName = psReplacingNode->abNodeName;
   2119       psReplacingNode->abNodeName = oReplaceData.getCharData();
   2120     }
   2121 
   2122     DMString strParentURI = strURI, strLastSegment;
   2123 
   2124     if ( !GetLastSegmentOfURI(strParentURI, strLastSegment) )
   2125       return SYNCML_DM_DEVICE_FULL;
   2126 
   2127     strParentURI += "/";
   2128     strParentURI += oReplaceData.getCharData();
   2129 
   2130     wReturnStatusCode = m_oMDFObj.VerifyReplaceParameters(psReplacingNode,
   2131                                                          strParentURI,
   2132                                                          oReplaceData,
   2133                                                          origName);
   2134 
   2135     XPL_LOG_DM_TMN_Error(("From ReplaceNameProperty(): Call to VerifyReplaceParameters() returns %d \n", wReturnStatusCode));
   2136 
   2137     if(wURIValidateRetCode == SYNCML_DM_COMMAND_ON_NAME_PROPERTY)
   2138     {
   2139         if (!bInPlugin)
   2140             psReplacingNode->abNodeName = origName;
   2141     }
   2142 
   2143     if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   2144         return(wReturnStatusCode);
   2145 
   2146 
   2147     wReturnStatusCode = psReplacingNode->Rename(strPluginURI,oReplaceData.getCharData());
   2148     XPL_LOG_DM_TMN_Error(("From ReplaceNameProperty(): Call to psReplacingNode->Rename() returns %d \n", wReturnStatusCode));
   2149   }
   2150 
   2151   if(wReturnStatusCode == SYNCML_DM_SUCCESS)
   2152   {
   2153     if (!bInPlugin) {
   2154         psReplacingNode->SetName( oReplaceData.getURI(), oReplaceData.getCharData());
   2155     }
   2156 
   2157     LogEvent(SYNCML_DM_EVENT_RENAME,strURI,oReplaceData.getCharData());
   2158     wReturnStatusCode = FixACL( strURI, oReplaceData );
   2159     XPL_LOG_DM_TMN_Error(("From ReplaceNameProperty(): Call to  FixACL() returns %d \n", wReturnStatusCode));
   2160   }
   2161 
   2162   return wReturnStatusCode;
   2163 }
   2164 
   2165 SYNCML_DM_RET_STATUS_T DMTree::ReplaceProperty( const DMString&         strURI,
   2166                                                 BOOLEAN                bInPlugin,
   2167                                                 const DMString&        strPluginURI,
   2168                                                 DMAddData&             oReplaceData,
   2169                                                 DMNode*                psReplacingNode,
   2170                                                 SYNCML_DM_RET_STATUS_T wURIValidateRetCode )
   2171 {
   2172   SYNCML_DM_RET_STATUS_T  wReturnStatusCode = SYNCML_DM_SUCCESS;
   2173 
   2174   switch( wURIValidateRetCode )
   2175   {
   2176     case SYNCML_DM_COMMAND_ON_NAME_PROPERTY:
   2177     {
   2178       wReturnStatusCode = ReplaceNameProperty( strURI,
   2179                                                bInPlugin,
   2180                                                strPluginURI,
   2181                                                oReplaceData,
   2182                                                psReplacingNode,
   2183                                                wURIValidateRetCode );
   2184       break;
   2185     }
   2186     case SYNCML_DM_COMMAND_ON_ACL_PROPERTY:
   2187     {
   2188       wReturnStatusCode = ReplaceACLProperty( strURI,
   2189                                               bInPlugin,
   2190                                               strPluginURI,
   2191                                               oReplaceData,
   2192                                               psReplacingNode );
   2193       break;
   2194     }
   2195     case SYNCML_DM_COMMAND_ON_TITLE_PROPERTY:
   2196     {
   2197       wReturnStatusCode = ReplaceTitleProperty( strURI,
   2198                                                 bInPlugin,
   2199                                                 strPluginURI,
   2200                                                 oReplaceData,
   2201                                                 psReplacingNode );
   2202       break;
   2203     }
   2204     case SYNCML_DM_COMMAND_ON_FORMAT_PROPERTY:
   2205     case SYNCML_DM_COMMAND_ON_SIZE_PROPERTY:
   2206     case SYNCML_DM_COMMAND_ON_TYPE_PROPERTY:
   2207     case SYNCML_DM_COMMAND_ON_TSTAMP_PROPERTY:
   2208     case SYNCML_DM_COMMAND_ON_VERNO_PROPERTY:
   2209     {
   2210       wReturnStatusCode = SYNCML_DM_COMMAND_NOT_ALLOWED;
   2211       break;
   2212     }
   2213     default:
   2214     {
   2215       wReturnStatusCode = SYNCML_DM_FEATURE_NOT_SUPPORTED;
   2216       break;
   2217     }
   2218   }
   2219 
   2220   return wReturnStatusCode;
   2221 }
   2222 
   2223 //------------------------------------------------------------------------
   2224 //
   2225 // FUNCTION        : Replace
   2226 //
   2227 // DESCRIPTION     : This function first will check the ACL and access type
   2228 //                   and after that if the both permissions are there then
   2229 //                   it will call respective plug-in.Replace.
   2230 //
   2231 // ARGUMENTS PASSED: UINT32 commandId
   2232 //                   UINT8 itemNumber
   2233 //                   SYNCML_DM_PLUGIN_ADD_T *pReplace
   2234 //                      -- Contains the replacing dat and it's format and
   2235 //                         type.
   2236 //                   BOOLEAN moreData
   2237 //                   BOOLEAN isThisAtomic
   2238 //
   2239 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
   2240 //                      -- It returns SYNCML_DM_COMMAND_FAILED in case if
   2241 //                         pReplace is NULL or incase of invalid name if
   2242 //                         the server fire replace on ?prop=Name
   2243 //                      -- It returns SYNCML_DM_COMMAND_INVALID_URI incase
   2244 //                         if the input URI is invalid.
   2245 //                      - It returns SYNCML_DM_INVALID_URI
   2246 //                        if the node path is not valid for current DMT version
   2247 //                      -- It returns SYNCML_DM_URI_TOO_LONG incase
   2248 //                         if the input URI is long.
   2249 //                      -- It returns SYNCML_DM_DEVICE_FULL incase
   2250 //                         if the device is out of memory.
   2251 //                      -- It returns SYNCML_DM_FEATURE_NOT_SUPPORTED
   2252 //                         incase if the server fire replace on ?prop=Title
   2253 //                      -- It returns SYNCML_DM_COMMAND_NOT_ALLOWED incase
   2254 //                         if the command is not allowed on the target.
   2255 //                      -- It returns SYNCML_DM_REQUEST_ENTITY_TOO_LARGE
   2256 //                         incase if the replacing name is large.
   2257 //                      -- It returns SYNCML_DM_SUCCESS incase if the operation
   2258 //                         is success.
   2259 // PRE-CONDITIONS  :
   2260 // POST-CONDITIONS :
   2261 // IMPORTANT NOTES :
   2262 //------------------------------------------------------------------------
   2263 SYNCML_DM_RET_STATUS_T DMTree::Replace( DMAddData & oReplaceData,
   2264                                                                      SYNCML_DM_REQUEST_TYPE_T eRequestType)
   2265 {
   2266   m_oLockContextManager.OnTreeAccessed();
   2267 
   2268   if(oReplaceData.getURI() == NULL)
   2269     return(SYNCML_DM_COMMAND_INVALID_URI);
   2270 
   2271   SYNCML_DM_RET_STATUS_T  wReturnStatusCode = SYNCML_DM_SUCCESS;
   2272   DMString strPluginURI;  // uri without ?xxx stuff for plugins and so on
   2273   DMString strURI;
   2274 
   2275   if ( !GetPluginURI( oReplaceData.getURI(), strURI, strPluginURI ) )
   2276     return SYNCML_DM_COMMAND_FAILED;
   2277 
   2278   SYNCML_DM_RET_STATUS_T wURIValidateRetCode = URIValidateAndParse( strURI );
   2279 
   2280   if((wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE) &&
   2281      (wURIValidateRetCode != SYNCML_DM_COMMAND_ON_ACL_PROPERTY) &&
   2282      (wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NAME_PROPERTY) &&
   2283      (wURIValidateRetCode != SYNCML_DM_COMMAND_ON_TITLE_PROPERTY)
   2284      )    //TStamp VerNo goes here.
   2285     return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   2286 
   2287 
   2288   //This if statement checks for ?prop attribute such that
   2289   // '?' is set to NULL.This is because before sending to plugins
   2290   //?prop=<property_name> must be removed from the URI
   2291   //example if ./SyncML?prop=ACL,we need to send only ./SyncML
   2292 
   2293   if(wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE)
   2294     strURI = strPluginURI;
   2295 
   2296   // check permission to write
   2297   if (!VerifyArchiveWriteAccess(strURI)) {
   2298     XPL_LOG_DM_TMN_Error(("archive has no write access for uri %s\n", strURI.c_str()));
   2299     return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   2300   }
   2301 
   2302   DMNode *psReplacingNode = FindNodeByURI(strURI);
   2303 
   2304   BOOLEAN bIsEnabled;
   2305   bIsEnabled = IsUriEnabled(strURI);
   2306   if(psReplacingNode == NULL) // In this parent doesn't exists
   2307   {
   2308 
   2309     if ( bIsEnabled == FALSE )
   2310     return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   2311     else
   2312         return SYNCML_DM_NOT_FOUND;
   2313 
   2314   }
   2315   else
   2316   {
   2317     if ( bIsEnabled == FALSE )
   2318         return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   2319 
   2320   }
   2321 
   2322   BOOLEAN bInPlugin = FALSE;
   2323 
   2324   if (psReplacingNode->isPlugin())
   2325     bInPlugin = TRUE;
   2326 
   2327   SYNCML_DM_FORMAT_T bFormat;
   2328   psReplacingNode->GetFormat(strURI, &bFormat);
   2329 
   2330   // C23495 Verify replace parameters using DDF information
   2331   //modify the URI sent to plugin by truncating ?prop
   2332   if( ( wURIValidateRetCode != SYNCML_DM_COMMAND_ON_NODE) &&
   2333       ( wURIValidateRetCode != SYNCML_DM_COMMAND_ON_FORMAT_PROPERTY)) //So far engine does not replacing FORMAT
   2334   {
   2335     oReplaceData.m_nFormat = bFormat;
   2336   }
   2337 
   2338   //if (bInPlugin)
   2339     //pReplace->bFormat = bFormat;
   2340 
   2341   //Added this check to first see if REPLACE command is allowed on the
   2342   //TARGET node,only then ACL is checked
   2343 
   2344   DMMetaPCharVector asChildDepend;  // array of child/dependend nodes for indirect updates
   2345 
   2346   if( !m_oMDFObj.VerifyAccessType(strURI,
   2347                                                  SYNCML_DM_REPLACE_ACCESS_TYPE,
   2348                                                  &asChildDepend) )
   2349   {
   2350     XPL_LOG_DM_TMN_Debug(("<Replace> Access type is NOT there \n"));
   2351     return (SYNCML_DM_COMMAND_NOT_ALLOWED);
   2352   }
   2353 
   2354   /**
   2355    * if ACL is being set for a leaf node, then ACL of the parent node
   2356    * (or the parent's parent and so on) is used to enforce the replace operation
   2357    *
   2358    * If ACL is being set for an interior node, then the ACL of that node is
   2359    * checked first and if it does not have replace permission, then the parent
   2360    * node's ACL is checked for enforcement.
   2361    */
   2362   BOOLEAN bCheckParent = FALSE;
   2363 
   2364   if (wURIValidateRetCode == SYNCML_DM_COMMAND_ON_ACL_PROPERTY)
   2365   {
   2366     bCheckParent = NeedCheckParent( strURI,
   2367                                     psReplacingNode,
   2368                                     bInPlugin,
   2369                                     bFormat,
   2370                                     eRequestType);
   2371   }
   2372 
   2373   if( bCheckParent )
   2374   {
   2375     DMString strParentURI = strURI, strLastSegment;
   2376 
   2377     if ( !GetLastSegmentOfURI(strParentURI, strLastSegment) )
   2378       return SYNCML_DM_DEVICE_FULL;
   2379 
   2380     wReturnStatusCode = IsValidServer(strParentURI,
   2381                                                      SYNCML_DM_REPLACE_ACCESS_TYPE,
   2382                                                      eRequestType,
   2383                                                      FALSE,
   2384                                                      TRUE);
   2385   }
   2386   else
   2387   {
   2388     wReturnStatusCode = IsValidServer(strURI,
   2389                                                      SYNCML_DM_REPLACE_ACCESS_TYPE,
   2390                                                      eRequestType,
   2391                                                      FALSE,
   2392                                                      TRUE);
   2393   }
   2394 
   2395   if(wReturnStatusCode != SYNCML_DM_SUCCESS)
   2396     return(wReturnStatusCode);
   2397 
   2398   // The following condition is used check if the server is trying
   2399   //  replace the value of the interior node. which is not possible.
   2400 
   2401   if((bFormat == SYNCML_DM_FORMAT_NODE) &&
   2402      (wURIValidateRetCode == SYNCML_DM_COMMAND_ON_NODE))
   2403   {
   2404     XPL_LOG_DM_TMN_Debug(("Server is trying to replace the value of an interior node which is NOT allowed \n"));
   2405      return(SYNCML_DM_COMMAND_NOT_ALLOWED);
   2406   }
   2407 
   2408   // that means the URI in the Replace command doesn't have
   2409   // any property "?prop=..
   2410 
   2411   if((bFormat != SYNCML_DM_FORMAT_NODE) &&
   2412      (wURIValidateRetCode == SYNCML_DM_COMMAND_ON_NODE))
   2413   {
   2414     wReturnStatusCode = ReplaceNodeInternal( strURI,
   2415                                              oReplaceData,
   2416                                              psReplacingNode,
   2417                                              asChildDepend );
   2418   }
   2419   else
   2420   {
   2421     wReturnStatusCode = ReplaceProperty( strURI,
   2422                                          bInPlugin,
   2423                                          strPluginURI,
   2424                                          oReplaceData,
   2425                                          psReplacingNode,
   2426                                          wURIValidateRetCode );
   2427   }
   2428 
   2429 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
   2430 
   2431   // set timestamp and increment version number
   2432   if ( ( wReturnStatusCode == SYNCML_DM_SUCCESS ) &&
   2433          !bInPlugin &&
   2434          psReplacingNode)
   2435   {
   2436     psReplacingNode->SetTStamp(strPluginURI.c_str(), XPL_CLK_GetClock());
   2437     psReplacingNode->SetVerNo(strPluginURI.c_str(), psReplacingNode->GetVerNo(strPluginURI.c_str()) + 1);
   2438   }
   2439 #endif
   2440 
   2441   return(wReturnStatusCode);
   2442 }
   2443 
   2444 //------------------------------------------------------------------------
   2445 // FUNCTION        : URIValidateAndParse
   2446 // DESCRIPTION     : This method validates URI as per RFC 2 and rules
   2447 //                   specified in TreeNode spec
   2448 //
   2449 // ARGUMENTS PASSED: pbURI :pointer to the URI to be validated
   2450 // RETURN VALUE    : SYNCML_DM_URI_RESULT_T indicating validity of URI
   2451 // PRE-CONDITIONS  :
   2452 // POST-CONDITIONS :
   2453 // IMPORTANT NOTES :
   2454 //------------------------------------------------------------------------
   2455 SYNCML_DM_URI_RESULT_T DMTree::URIValidateAndParse(CPCHAR pbURI) const
   2456 {
   2457   if ( !pbURI )
   2458     return SYNCML_DM_COMMAND_INVALID_URI;
   2459 
   2460   // checks that:
   2461   // length of each segment is less or equal to GetMaxPathSegmentLength()
   2462   // number of segments is equal or less than GetMaxPathDepth()
   2463   int nFullLen = DmStrlen( pbURI );
   2464   const char* szQpos = DmStrchr( pbURI, SYNCML_DM_QUESTION_MARK);
   2465   const char* szPathEnd =  szQpos ? szQpos : pbURI + nFullLen;
   2466   int nSegmentsCount = 1;
   2467   int nSegmentLen = 0;
   2468 
   2469   if ( (szPathEnd - pbURI) > GetMaxTotalPathLength() )
   2470     return SYNCML_DM_COMMAND_URI_TOO_LONG;
   2471 
   2472   if ( (szPathEnd - pbURI) == 0 || (*(szPathEnd -1)) == '/' )
   2473     return SYNCML_DM_COMMAND_INVALID_URI;
   2474 
   2475   while ( pbURI <szPathEnd ) {
   2476     if ( *pbURI == '/' ) { // next segment
   2477       if ( nSegmentLen > GetMaxPathSegmentLength() )
   2478         return SYNCML_DM_COMMAND_URI_TOO_LONG;
   2479 
   2480       if ( !nSegmentLen )
   2481         return SYNCML_DM_COMMAND_INVALID_URI;
   2482 
   2483       nSegmentLen = 0;
   2484       nSegmentsCount++;
   2485 
   2486       if ( nSegmentsCount > GetMaxPathDepth() )
   2487         return SYNCML_DM_COMMAND_URI_TOO_LONG;
   2488 
   2489     } else
   2490       nSegmentLen++;
   2491 
   2492     pbURI++;
   2493   }
   2494 
   2495   // check optional part after '?'
   2496   if ( !szQpos )
   2497     return SYNCML_DM_COMMAND_ON_NODE;
   2498 
   2499 
   2500   if( DmStrstr(szQpos, SYNCML_DM_PROP) != NULL) {
   2501     // 6 is the lenth of the "?prop="
   2502     szQpos += SYNCML_DM_PROP_LENGTH;
   2503 
   2504     if( DmStrcmp( szQpos, "ACL") == 0)
   2505       return SYNCML_DM_COMMAND_ON_ACL_PROPERTY;
   2506 
   2507 #ifdef LOB_SUPPORT
   2508     if( DmStrcmp( szQpos, "ESN") == 0)
   2509       return SYNCML_DM_COMMAND_ON_ESN_PROPERTY;
   2510 #endif
   2511     if(DmStrcmp( szQpos, "Format") == 0)
   2512       return SYNCML_DM_COMMAND_ON_FORMAT_PROPERTY;
   2513 
   2514     if(DmStrcmp( szQpos, "Name") == 0)
   2515       return SYNCML_DM_COMMAND_ON_NAME_PROPERTY;
   2516 
   2517     if(DmStrcmp( szQpos, "Size") == 0)
   2518       return SYNCML_DM_COMMAND_ON_SIZE_PROPERTY;
   2519 
   2520     if(DmStrcmp( szQpos, "VerNo") == 0)
   2521       return SYNCML_DM_COMMAND_ON_VERNO_PROPERTY;
   2522 
   2523     if(DmStrcmp( szQpos, SYNCML_DM_TITLE) == 0)
   2524       return SYNCML_DM_COMMAND_ON_TITLE_PROPERTY;
   2525 
   2526     if(DmStrcmp( szQpos, SYNCML_DM_TYPE) == 0)
   2527       return SYNCML_DM_COMMAND_ON_TYPE_PROPERTY;
   2528 
   2529     if(DmStrcmp( szQpos, SYNCML_DM_TSTAMP) == 0)
   2530       return SYNCML_DM_COMMAND_ON_TSTAMP_PROPERTY;
   2531 
   2532     return SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY;
   2533   }
   2534 
   2535   if (DmStrstr(szQpos, SYNCML_DM_LIST) != NULL) {
   2536 
   2537     // 6 is the lenth of the "?list="
   2538     szQpos += SYNCML_DM_LIST_LENGTH;
   2539 
   2540     if(DmStrcmp(szQpos, SYNCML_DM_STRUCT) == 0)
   2541       return SYNCML_DM_COMMAND_LIST_STRUCT;
   2542 
   2543     if(DmStrcmp(szQpos, SYNCML_DM_STRUCT_DATA) == 0)
   2544       return SYNCML_DM_COMMAND_LIST_STRUCTDATA;
   2545 
   2546     if(DmStrncmp(szQpos,SYNCML_DM_TNDS, 4) == 0)
   2547 #ifdef TNDS_SUPPORT
   2548       return SYNCML_DM_COMMAND_LIST_TNDS;
   2549 #else
   2550       return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   2551 #endif
   2552 
   2553     return SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY;
   2554   }
   2555 
   2556   return(SYNCML_DM_COMMAND_INVALID_URI);
   2557 }
   2558 
   2559 //------------------------------------------------------------------------
   2560 //
   2561 // FUNCTION        : readOneWordFromTree
   2562 //
   2563 // DESCRIPTION     :
   2564 //
   2565 //
   2566 // ARGUMENTS PASSED: None
   2567 // RETURN VALUE    :
   2568 // PRE-CONDITIONS  :
   2569 // POST-CONDITIONS :
   2570 // IMPORTANT NOTES :
   2571 //------------------------------------------------------------------------
   2572 UINT16
   2573 DMTree::readOneWordFromTree(DMNode *pNode, UINT16 defaultValue)
   2574 {
   2575     UINT16 retData = 0;
   2576 
   2577     if ( pNode )
   2578     {
   2579         if ( pNode->getData() && !(pNode->getData()->empty()) )
   2580         {
   2581             retData = DmAtoi((CPCHAR)pNode->getData()->getBuffer());
   2582         }
   2583     }
   2584 
   2585     if(retData == 0)
   2586         retData = defaultValue;
   2587 
   2588     return retData;
   2589 }
   2590 
   2591 // Simplified function for deserialize,
   2592 // does not perform lookup, justcreat a child for given node,
   2593 // reutrns newly created node.
   2594 SYNCML_DM_RET_STATUS_T DMTree::AddNode(DMNode **psNodeObject,
   2595                                        const DMAddNodeProp & oAddNodeProperties,
   2596                                        DMNode* pNewNode )
   2597 {
   2598   DMNode *pParent = *psNodeObject;
   2599   BOOLEAN bUpdateNode = TRUE;
   2600   BOOLEAN bESN = FALSE;
   2601   CPCHAR tmpSt = NULL;
   2602 
   2603   SYNCML_DM_RET_STATUS_T res;
   2604 
   2605   if ( !m_psRoot )
   2606     return SYNCML_DM_FAIL;  // unexpected condition
   2607 
   2608 #ifdef LOB_SUPPORT
   2609  if((oAddNodeProperties.m_nFlags &  DMNode::enum_NodeESN) != 0)
   2610   {    bESN = TRUE;
   2611     tmpSt =oAddNodeProperties.getESNFileName();
   2612   }
   2613 #endif
   2614   // lookup for the node
   2615   DMNode* pChild = pParent ? pParent->GetChildByName(oAddNodeProperties.getName()) : m_psRoot;
   2616 
   2617   if ( !pChild )
   2618   {
   2619     // node does not exist - create it
   2620     pChild = pNewNode ? pNewNode : DMTree::CreateNodeObj(oAddNodeProperties.m_nFormat, bESN, tmpSt);
   2621 
   2622     if ( !pChild )
   2623       return SYNCML_DM_DEVICE_FULL;
   2624 
   2625     // add child:
   2626     pChild->pcParentOfNode = pParent;
   2627 
   2628     if ( pParent ) {
   2629       pChild->pcNextSibling = pParent->pcFirstChild;
   2630       pParent->pcFirstChild = pChild;
   2631     }
   2632   } else {
   2633     if ( pNewNode )
   2634       delete pNewNode;
   2635 
   2636     pNewNode = NULL;
   2637 
   2638     if ( !pChild->IsSkeletonNode() )
   2639       bUpdateNode = FALSE;
   2640   }
   2641 
   2642 
   2643   if ( bUpdateNode )
   2644   {
   2645     res = pChild->set(&oAddNodeProperties);
   2646     if ( res != SYNCML_DM_SUCCESS )
   2647         return res;
   2648    }
   2649 
   2650   *psNodeObject = pChild;
   2651   return SYNCML_DM_SUCCESS;
   2652 }
   2653 
   2654 
   2655 //------------------------------------------------------------------------
   2656 // FUNCTION        : GetParentOfKeyValue
   2657 // DESCRIPTION     : This method returns the name of a parent whose child
   2658 //                   node's name and value of the child node(leaf node)
   2659 //                   are passed
   2660 // ARGUMENTS PASSED: pbValueOfKey pointer to value of leaf node
   2661 //                   pbKey : leaf node's name whose parent's name has to
   2662 //                           be found
   2663 // RETURN VALUE    : UINT8: name of parent node
   2664 //                   NULL if node does not exist
   2665 // PRE-CONDITIONS  : If the node does not exist,parent's name will be
   2666 //                   returned as NULL
   2667 // POST-CONDITIONS :
   2668 // IMPORTANT NOTES :This API is meant to be used when there can be many
   2669 //                  instances of a particular interior node and the UA
   2670 //                  needs to know the name of a parent,given it's child
   2671 //                  name and value
   2672 //------------------------------------------------------------------------
   2673 BOOLEAN DMTree::GetParentOfKeyValue(CPCHAR pbValueOfKey,
   2674                                     CPCHAR pbKey,
   2675                                     CPCHAR pbSubtreeURI,
   2676                                     DMString& strResult )
   2677 {
   2678   DMNode *psFindNode = NULL;
   2679   DMNode *psKeyNode = NULL;
   2680   SYNCML_DM_RET_STATUS_T wRetStausCode = SYNCML_DM_SUCCESS;
   2681   DMGetData getData;
   2682   DMString strPluginURI;
   2683   DMString strURI;
   2684 
   2685   if((pbValueOfKey == NULL) || (pbKey == NULL) || (pbSubtreeURI == NULL))
   2686   {
   2687     XPL_LOG_DM_TMN_Error(("Invalid Parameters\n"));
   2688     return FALSE;
   2689   }
   2690 
   2691   if ( !GetPluginURI( pbSubtreeURI, strURI, strPluginURI ) )
   2692   {
   2693     XPL_LOG_DM_TMN_Error(("cannot parse URI\n"));
   2694     return FALSE;
   2695   }
   2696 
   2697   psFindNode = FindNodeByURI( strURI );
   2698   if(psFindNode == NULL)
   2699   {
   2700     XPL_LOG_DM_TMN_Error(("Node isn't found\n"));
   2701     return FALSE;
   2702   }
   2703 
   2704   psFindNode = psFindNode->pcFirstChild;
   2705 
   2706   while(psFindNode != NULL)
   2707   {
   2708     strURI = pbSubtreeURI;
   2709     strURI += "/";
   2710     strURI += psFindNode->abNodeName;
   2711 
   2712     psKeyNode = FindNodeInNextSiblingsList(psFindNode->pcFirstChild,pbKey);
   2713     if(psKeyNode != NULL)
   2714     {
   2715       strURI += "/";
   2716       strURI += pbKey;
   2717 
   2718       wRetStausCode = psKeyNode->Get(strURI, getData);
   2719 
   2720       if( wRetStausCode == SYNCML_DM_SUCCESS )
   2721       {
   2722         if( getData.m_oData.compare(pbValueOfKey) )
   2723         {
   2724           strResult = psFindNode->abNodeName;
   2725           return TRUE;
   2726         }
   2727       }
   2728     }
   2729     psFindNode = psFindNode->pcNextSibling;
   2730   }// End of while(psFindNode != NULL)
   2731 
   2732   XPL_LOG_DM_TMN_Error(("Node isn't found\n"));
   2733   return FALSE;
   2734 }
   2735 
   2736 //------------------------------------------------------------------------
   2737 //
   2738 // FUNCTION        : InitListAndGetListFirstItem
   2739 //
   2740 // DESCRIPTION     : This function initializes the list and returns first.
   2741 //                   item for GetStruct
   2742 //
   2743 // ARGUMENTS PASSED: UINT8 *pbSegment
   2744 //                      - Pointer to the URI segment.
   2745 //                   SYNCML_DM_GET_ON_LIST_T bGetOnList
   2746 //                      - whether get is ?list=Struct or ?list=StructData
   2747 //                   SYNCML_DM_GET_ON_LIST_RET_DATA_T **ppsReturnData
   2748 //                      - Contains first item
   2749 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
   2750 //                      - It returns SYNCML_DM_COMMAND_FAILED incase if
   2751 //                        the URI is NULL or if root node pointer is NULL
   2752 //                        or if the URI is invalid.
   2753 //                      - It returns SYNCML_DM_DEVICE_FULL if the device
   2754 //                        is out of memory.
   2755 //                      - It returns SYNCML_DM_SUCCESS if the operation is
   2756 //                        success.
   2757 //                      - It returns SYNCML_DM_URI_TOO_LONG if the uri is
   2758 //                        long.
   2759 // PRE-CONDITIONS  :
   2760 // POST-CONDITIONS :
   2761 // IMPORTANT NOTES :
   2762 //------------------------------------------------------------------------
   2763 SYNCML_DM_RET_STATUS_T DMTree::InitListAndGetListFirstItem(
   2764                      CPCHAR pbURI,
   2765                      SYNCML_DM_GET_ON_LIST_T bGetOnList,
   2766                      SYNCML_DM_GET_ON_LIST_RET_DATA_T& ppsReturnData)
   2767 {
   2768   DMString strFullURI;
   2769 
   2770 
   2771   if( !GetPluginURI(pbURI, strFullURI, ppsReturnData.m_strStartURI) || ( m_psRoot == NULL))
   2772   {
   2773     return(SYNCML_DM_COMMAND_FAILED);
   2774   }
   2775 
   2776   ppsReturnData._pbURI = ppsReturnData.m_strStartURI;
   2777   return GetListItemData( ppsReturnData );
   2778 }
   2779 
   2780 SYNCML_DM_RET_STATUS_T DMTree::GetListItemData(SYNCML_DM_GET_ON_LIST_RET_DATA_T& ppsReturnData)
   2781 {
   2782 
   2783   DMGetData * pData = NULL;
   2784   pData = new DMGetData();
   2785 
   2786   if ( pData == NULL )
   2787     return SYNCML_DM_DEVICE_FULL;
   2788 
   2789   ppsReturnData.psRetData = pData;
   2790   SYNCML_DM_RET_STATUS_T nRes = Get(ppsReturnData._pbURI, *pData ,SYNCML_DM_REQUEST_TYPE_SERVER);
   2791 
   2792   if ( nRes == SYNCML_DM_SUCCESS && pData->m_nFormat == SYNCML_DM_FORMAT_NODE )
   2793   {
   2794 
   2795     DMString strChild( pData->getCharData() );
   2796     char* szSlash = (char*)DmStrchr(strChild, '/');
   2797     if ( szSlash )
   2798       *szSlash = 0;
   2799     if ( strChild.empty() )
   2800       ppsReturnData.m_strNextChild = "";
   2801     else {
   2802       ppsReturnData.m_strNextChild = ppsReturnData._pbURI;
   2803       ppsReturnData.m_strNextChild += "/";
   2804       ppsReturnData.m_strNextChild += strChild;
   2805     }
   2806   } else
   2807     ppsReturnData.m_strNextChild = "";
   2808 
   2809   return nRes;
   2810 }
   2811 
   2812 //------------------------------------------------------------------------
   2813 // FUNCTION        : GetListNextItem
   2814 // DESCRIPTION     : The UA calls this to get the entire structure of the
   2815 //                   subtree.The Tree traverses the subtree and returns
   2816 //                   the list of names for which the current server has
   2817 //                   ACL permissions.
   2818 // ARGUMENTS PASSED: dwCommandId command Id
   2819 //                   bItemNumber
   2820 //                   pbURI target URI whose subtree structure has to be
   2821 //                   returned
   2822 //                   ppsReturnData containing linked list of the names
   2823 // RETURN VALUE    : ppsReturnData and SYNCML_DM_RET_STATUS_T
   2824 //                   SYNCML_DM_SUCCESS if successful
   2825 //                   else error specific code indicating failure
   2826 // PRE-CONDITIONS  : None
   2827 // POST-CONDITIONS : None
   2828 // IMPORTANT NOTES : None
   2829 //------------------------------------------------------------------------
   2830 SYNCML_DM_RET_STATUS_T DMTree::GetListNextItem(SYNCML_DM_GET_ON_LIST_RET_DATA_T& ppsReturnData)
   2831 {
   2832 
   2833    XPL_LOG_DM_TMN_Debug(("DMTree:  in the  GetListNextItem() for %s\n",  ppsReturnData._pbURI.c_str()));
   2834 
   2835   // look for the next node -
   2836   // 1. try child
   2837   if ( !ppsReturnData.m_strNextChild.empty() ) {
   2838     ppsReturnData._pbURI = ppsReturnData.m_strNextChild;
   2839     int ret = GetListItemData( ppsReturnData );
   2840 
   2841     //returns only in case of success; otherwise skip this node and going to take another sibbling (do/while loop)
   2842     if( ret == SYNCML_DM_SUCCESS ){
   2843         return ret;
   2844     }
   2845     XPL_LOG_DM_TMN_Error(("DMTree: The function GetListItemData() (1) for %s returns error = %d \n", ppsReturnData._pbURI.c_str(), ret ));
   2846   }
   2847 
   2848   do {
   2849     // 2. try next sibling
   2850     DMString strURI = ppsReturnData._pbURI, strLastSegment;
   2851 
   2852     if ( !GetLastSegmentOfURI( strURI, strLastSegment ) ) // no parent
   2853       return SYNCML_DM_SUCCESS;
   2854 
   2855     // in case of empty node we should not look for sibling...
   2856     if ( strURI.length() < ppsReturnData.m_strStartURI.length() )
   2857       return SYNCML_DM_SUCCESS; // no more items
   2858 
   2859     DMGetData getData;
   2860 
   2861     SYNCML_DM_RET_STATUS_T nRes = Get(strURI, getData,SYNCML_DM_REQUEST_TYPE_SERVER);
   2862 
   2863     if ( nRes != SYNCML_DM_SUCCESS )
   2864       return nRes;
   2865 
   2866     DMString strAllChildren( getData.getCharData() ), strChild;
   2867 
   2868     while ( DmStringParserGetItem( strChild, strAllChildren, '/' ) )
   2869     {
   2870       XPL_LOG_DM_TMN_Debug(("DMTree: strChild =  %s , strAllChildren = %s\n", strChild.c_str(), strAllChildren.c_str() ));
   2871 
   2872       if ( strChild == strLastSegment ) { // found current node - take next
   2873 
   2874         while ( DmStringParserGetItem( strChild, strAllChildren, '/' ) )
   2875         {
   2876           ppsReturnData._pbURI = strURI;
   2877           ppsReturnData._pbURI += "/";
   2878           ppsReturnData._pbURI+= strChild;
   2879           int ret = GetListItemData( ppsReturnData );
   2880 
   2881           //returns only in case of success; otherwise skip this node and going to take another sibbling
   2882           if( ret == SYNCML_DM_SUCCESS ){
   2883                return ret;
   2884           }
   2885           else{
   2886              XPL_LOG_DM_TMN_Error(("DMTree: The function GetListItemData() (2) for %s returns error = %d \n", ppsReturnData._pbURI.c_str(), ret ));
   2887              continue;
   2888           }
   2889         }
   2890         break;
   2891       }
   2892     }
   2893 
   2894     // 3. take parent
   2895     ppsReturnData._pbURI = strURI;
   2896     if ( strURI.length() <= ppsReturnData.m_strStartURI.length() )
   2897       return SYNCML_DM_SUCCESS; // no more items
   2898 
   2899     // goto step 2...
   2900   } while ( 1 );
   2901 }
   2902 
   2903 //------------------------------------------------------------------------
   2904 //
   2905 // FUNCTION        : InitSerializationList
   2906 //
   2907 // DESCRIPTION     : This function will allocate and initialize the values
   2908 //                   of the LIST_STRUCT_OR_STRUCT_DATA_INFO_T psListInfo.
   2909 //
   2910 // ARGUMENTS PASSED:
   2911 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
   2912 //                      - It returns SYNCML_DM_COMMAND_FAILED if the
   2913 //                        root node is NULL.
   2914 //                      - It returns SYNCML_DM_DEVICE_FULL if the device
   2915 //                        is out of memory.
   2916 //                      - It returns SYNCML_DM_SUCCESS if the operation is
   2917 //                        success.
   2918 // PRE-CONDITIONS  :
   2919 // POST-CONDITIONS :
   2920 // IMPORTANT NOTES :
   2921 //------------------------------------------------------------------------
   2922 SYNCML_DM_RET_STATUS_T DMTree::InitSerializationList(DMNode * serializeRoot)
   2923 {
   2924   psListInfo.Clear();
   2925   psListInfo.psCurrent = serializeRoot;
   2926   return(SYNCML_DM_SUCCESS);
   2927 }
   2928 
   2929 //------------------------------------------------------------------------
   2930 //
   2931 // FUNCTION        : GetSerializationListNextItem
   2932 //
   2933 // DESCRIPTION     : This function will return the properties of a node.
   2934 //                   This function will use DFS algorithm to traverse the
   2935 //                   tree.
   2936 //
   2937 //
   2938 // ARGUMENTS PASSED: DMNode *psRetNode the node to serialize next
   2939 //
   2940 // RETURN VALUE    : SYNCML_DM_SERIALIZATION_STATUS_T
   2941 //                      -- It returns SYNCML_DM_SERIALIZATION_FAIL
   2942 //                         if there is any failure.
   2943 //                      -- It returns SYNCML_DM_SERIALIZATION_SUCCESS
   2944 //                         if it can retrieve the properties of a node.
   2945 //                      -- It returns SYNCML_DM_TREE_TRAVERSING_OVER
   2946 //                         in case if the it has visited all the nodes.
   2947 //                         in a tree.
   2948 // PRE-CONDITIONS  :
   2949 // POST-CONDITIONS :
   2950 // IMPORTANT NOTES :
   2951 //------------------------------------------------------------------------
   2952 SYNCML_DM_SERIALIZATION_STATUS_T DMTree::
   2953 GetSerializationListNextItem (DMNode **ppsRetNode, INT32& nEndTagsNumber )
   2954 {
   2955   DMNode *psCurrent = *ppsRetNode;
   2956 
   2957   nEndTagsNumber = 0;
   2958   if ( !psCurrent ) {
   2959       *ppsRetNode = psListInfo.psCurrent;
   2960       return SYNCML_DM_SERIALIZATION_SUCCESS;
   2961   }
   2962 
   2963   // try child first
   2964   DMNode* pChild = psCurrent->pcFirstChild ?
   2965         psCurrent->pcFirstChild->GetNextSerializeItem() : NULL;
   2966 
   2967   if ( pChild ) {
   2968       *ppsRetNode = pChild;
   2969       return SYNCML_DM_SERIALIZATION_SUCCESS;
   2970   }
   2971 
   2972   // look up for sibling of the parent including self
   2973   DMNode *pParent = psCurrent;
   2974 
   2975   while ( pParent != psListInfo.psCurrent ) {
   2976     // try next sibling after that
   2977     DMNode *pNextSibling = pParent->pcNextSibling ?
   2978           pParent->pcNextSibling->GetNextSerializeItem() : NULL;
   2979 
   2980     nEndTagsNumber++; // even sibling required at least one "end" tag
   2981 
   2982     if ( pNextSibling ) {
   2983       *ppsRetNode = pNextSibling;
   2984       return SYNCML_DM_SERIALIZATION_SUCCESS;
   2985     }
   2986 
   2987     // take parent
   2988     pParent = pParent->pcParentOfNode;
   2989   }
   2990 
   2991   // not found
   2992   return SYNCML_DM_TREE_TRAVERSING_OVER;
   2993 }
   2994 
   2995 SyncML_DM_Archive* DMTree::GetArchive(const DMNode * node)
   2996 {
   2997    const DMNode * tmpNode=node;
   2998    while (tmpNode != NULL && tmpNode->pArchive == NULL)
   2999    {
   3000       tmpNode=tmpNode->pcParentOfNode;
   3001    }
   3002 
   3003    return tmpNode ? tmpNode->pArchive : NULL;
   3004 }
   3005 
   3006 DMNode* DMTree::CreateNodeObj( SYNCML_DM_FORMAT_T bFormat, BOOLEAN isESN, CPCHAR pbFileName )
   3007 {
   3008   switch ( bFormat )
   3009   {
   3010     case SYNCML_DM_FORMAT_NODE:
   3011       return(new DMDefaultInteriorNode);
   3012 
   3013     case SYNCML_DM_FORMAT_NODE_PDATA:
   3014       return(new DMOverlayPINode);
   3015 
   3016     default:
   3017 #ifdef LOB_SUPPORT
   3018     if(isESN)
   3019         return( new DMDefaultESN(pbFileName));
   3020     else
   3021 #endif
   3022       return(new DMDefaultLeafNode);
   3023   }
   3024 }
   3025 
   3026 DMNode* DMTree::CreateSkeletonNode( CPCHAR pbURI )
   3027 {
   3028   DMString strURI = pbURI;
   3029   char *szURI = strURI.GetBuffer();
   3030   const char *pbURISegment = GetURISegment(&szURI);
   3031 
   3032   if ( !m_psRoot ) {
   3033     m_psRoot = DMTree::CreateNodeObj(SYNCML_DM_FORMAT_NODE, FALSE, NULL);
   3034 
   3035     if ( !m_psRoot )
   3036       return NULL; // out of memory
   3037 
   3038     m_psRoot->abNodeName = pbURISegment; // it should be "."
   3039     m_psRoot->setFlags( DMNode::enum_NodeSkeleton );
   3040   }
   3041 
   3042   DMNode *psParentNode  = m_psRoot;
   3043 
   3044   pbURISegment = GetURISegment(&szURI);   // skip dot
   3045 
   3046   while( pbURISegment ) {
   3047 
   3048     DMNode *pChild = psParentNode->GetChildByName(pbURISegment);
   3049 
   3050     if ( !pChild ) {
   3051       pChild = DMTree::CreateNodeObj(SYNCML_DM_FORMAT_NODE, FALSE, NULL);
   3052 
   3053       if ( !pChild )
   3054         return NULL; // out of memory
   3055 
   3056       pChild->abNodeName = pbURISegment;
   3057       pChild->setFlags( DMNode::enum_NodeSkeleton );
   3058 
   3059       pChild->pcParentOfNode = psParentNode;
   3060 
   3061       pChild->pcNextSibling = psParentNode->pcFirstChild;
   3062       psParentNode->pcFirstChild = pChild;
   3063     }
   3064 
   3065     psParentNode = pChild;
   3066     pbURISegment = GetURISegment(&szURI);
   3067   }
   3068   return psParentNode;
   3069 }
   3070 
   3071 // function "detaches" old node from the tree and inserts new node in the same place.
   3072 void DMTree::SubstituteNode( DMNode* pOldNode, DMNode* pNewNode )
   3073 {
   3074   // parent
   3075   if ( pOldNode->pcParentOfNode && pOldNode->pcParentOfNode->pcFirstChild == pOldNode )
   3076     pOldNode->pcParentOfNode->pcFirstChild = pNewNode;
   3077 
   3078   // prev sibling
   3079   DMNode *pNode = pOldNode->pcParentOfNode ? pOldNode->pcParentOfNode->pcFirstChild : NULL;
   3080 
   3081   while ( pNode )
   3082   {
   3083     if ( pNode->pcNextSibling == pOldNode )
   3084       pNode->pcNextSibling = pNewNode;
   3085 
   3086     pNode = pNode->pcNextSibling;
   3087   }
   3088 
   3089   // children
   3090   pNode = pOldNode->pcFirstChild;
   3091   while ( pNode )
   3092   {
   3093     pNode->pcParentOfNode = pNewNode;
   3094 
   3095     pNode = pNode->pcNextSibling;
   3096   }
   3097 
   3098 }
   3099 
   3100 /**
   3101  * Get the immediate children of a node based on the desired node type.
   3102  *
   3103  * @author Andy
   3104  * @param uri the URI to the node E.g. ./DevInfo
   3105  * @param childrenMap the map that will hold the URI of the children
   3106  *                    and the children
   3107  * @param nodeType the type of nodes that get store in the map either leaf node
   3108  *                 or interior node
   3109  * @return the status of the operation
   3110  */
   3111 SYNCML_DM_RET_STATUS_T
   3112 DMTree::getChildren( CPCHAR uri,
   3113                                      DMMap<DMString, UINT32>& childrenMap,
   3114                                      DMTNM_NODE_TYPE nodeType,
   3115                                      SYNCML_DM_REQUEST_TYPE_T eRequestType)
   3116 {
   3117   SYNCML_DM_RET_STATUS_T eSuccessCode = SYNCML_DM_SUCCESS;
   3118   DMGetData parentNodeData;
   3119 
   3120   eSuccessCode = Get(uri, parentNodeData,eRequestType);
   3121 
   3122   if (eSuccessCode != SYNCML_DM_SUCCESS)
   3123     return SYNCML_DM_COMMAND_FAILED;
   3124 
   3125   DMString remindStr = parentNodeData.getCharData(); // children names
   3126   DMString tmpStr;
   3127   DMString tmpRootPath = uri;
   3128   DMString tmpChildPath;
   3129   DMString sperator = "/";
   3130   DMGetData * tmpNodeData = NULL;
   3131 
   3132   // loop through children that seperated by forward slash
   3133   while(DmStringParserGetItem(tmpStr, remindStr, '/'))
   3134   {
   3135       tmpChildPath += tmpRootPath;
   3136       tmpChildPath += sperator;
   3137       tmpChildPath += tmpStr;
   3138 
   3139       tmpNodeData = new DMGetData();
   3140       if ( tmpNodeData == NULL )
   3141       {
   3142          dmFreeGetMap(childrenMap);
   3143          return SYNCML_DM_DEVICE_FULL;
   3144       }
   3145 
   3146       eSuccessCode = Get(tmpChildPath.c_str(), *tmpNodeData,eRequestType); // get child node
   3147       if (eSuccessCode != SYNCML_DM_SUCCESS)
   3148       {
   3149           dmFreeGetMap(childrenMap);
   3150           return SYNCML_DM_COMMAND_FAILED;
   3151       }
   3152 
   3153       if (tmpNodeData->m_nFormat == SYNCML_DM_FORMAT_NODE && nodeType == DMTNM_NODE_INTERIOR)
   3154       {
   3155          childrenMap.put(tmpChildPath.c_str(), (UINT32)tmpNodeData);
   3156       }
   3157       else
   3158         if (tmpNodeData->m_nFormat != SYNCML_DM_FORMAT_NODE && nodeType == DMTNM_NODE_LEAF)
   3159         {
   3160            childrenMap.put(tmpChildPath.c_str(), (UINT32)tmpNodeData);
   3161         }
   3162         else // no match
   3163          DMGetData::operator delete (tmpNodeData);
   3164 
   3165      tmpChildPath = NULL;
   3166   }
   3167   return eSuccessCode;
   3168 }
   3169 
   3170 /**
   3171  * Get the immediate leaf children
   3172  *
   3173  * @author Andy
   3174  * @param uri the URI to the node E.g. ./DevInfo
   3175  * @param childrenMap the map that will hold the URI of the children
   3176  *                    and the children
   3177  * @return the status of the operation
   3178  */
   3179 SYNCML_DM_RET_STATUS_T
   3180 DMTree::getLeafChildren( CPCHAR uri,
   3181                                              DMMap<DMString,
   3182                                              UINT32>& childrenMap,
   3183                                              SYNCML_DM_REQUEST_TYPE_T eRequestType)
   3184 {
   3185     return getChildren(uri, childrenMap, DMTNM_NODE_LEAF,eRequestType);
   3186 }
   3187 
   3188 /**
   3189  * Get the immediate interior children
   3190  *
   3191  * @author Andy
   3192  * @param uri the URI to the node E.g. ./DevInfo
   3193  * @param childrenMap the map that will hold the URI of the children
   3194  *                    and the children
   3195  * @return the status of the operation
   3196  */
   3197 SYNCML_DM_RET_STATUS_T
   3198 DMTree::getInteriorChildren( CPCHAR uri,
   3199                                                 DMMap<DMString,
   3200                                                 UINT32>& childrenMap,
   3201                                                 SYNCML_DM_REQUEST_TYPE_T eRequestType)
   3202 {
   3203     return getChildren(uri, childrenMap, DMTNM_NODE_INTERIOR,eRequestType);
   3204 }
   3205 
   3206 /**
   3207  * Set the leaf children with the new set of leaf children.  If the children already
   3208  * exist, replace them.  If the children are new, add them.  If the children were not
   3209  * in the new set of leaf children, remove them.  Since this is a atomic operation,
   3210  * it will roll back to the original state if any of above operations failed,
   3211  *
   3212  * @author Andy
   3213  * @param uri the URI to the node E.g. ./DevInfo
   3214  * @param childrenMap the new set of leaf children
   3215  * @return the status of the operation
   3216  */
   3217 SYNCML_DM_RET_STATUS_T DMTree::setLeafChildren( CPCHAR uri, DMMap<DMString, UINT32>& childrenMap )
   3218 {
   3219 
   3220     DMMap<DMString, UINT32> oldChildrenMap;
   3221     SYNCML_DM_RET_STATUS_T status = SYNCML_DM_SUCCESS;
   3222 
   3223     status = getLeafChildren(uri,
   3224                                  (DMMap<DMString, UINT32>&)oldChildrenMap,
   3225                                  SYNCML_DM_REQUEST_TYPE_API);
   3226 
   3227     if (status != SYNCML_DM_SUCCESS) {
   3228         dmFreeGetMap((DMMap<DMString, UINT32>&)oldChildrenMap);
   3229         return status;
   3230     }
   3231 
   3232     int numOfNewChildren = childrenMap.size();
   3233 
   3234     DMVector<INT8> deleteList;  // mark the delete on a child for rollback
   3235     deleteList.set_size(numOfNewChildren);
   3236     for (int i = 0; i < numOfNewChildren; i++)
   3237     {
   3238         deleteList[i] = CLEAN;
   3239     }
   3240 
   3241     int numOfOldChildren = oldChildrenMap.size();
   3242     // mark the action (add or replace) on a child for rollback
   3243     DMVector<INT8> actionList;
   3244     actionList.set_size(numOfOldChildren);
   3245 
   3246     if (numOfNewChildren != 0)
   3247     {
   3248         for (int i = 0; i < numOfOldChildren; i++)
   3249         {
   3250             actionList[i] = CLEAN;
   3251         }
   3252         status = handleNewChildren(oldChildrenMap,  (DMMap<DMString, UINT32>&)childrenMap,
   3253                                    (INT8*)actionList.get_data(), (INT8*)deleteList.get_data());
   3254     }
   3255     else
   3256     {
   3257         for (int i = 0; i < numOfOldChildren; i++)
   3258         {
   3259             actionList[i] = DIRTY;  //mark DIRTY to delete all old leaf children
   3260         }
   3261     }
   3262 
   3263     if (status == SYNCML_DM_SUCCESS)
   3264     {
   3265         status = handleOldChildren(oldChildrenMap,  (DMMap<DMString, UINT32>&)childrenMap,
   3266                                    (INT8*)actionList.get_data(), (INT8*)deleteList.get_data());
   3267     }
   3268 
   3269     dmFreeGetMap((DMMap<DMString, UINT32>&)oldChildrenMap);
   3270     return status;
   3271 }
   3272 
   3273 /**
   3274  * Loop through the new set of children and compare them with the old set of children
   3275  * If exist in the old set of children, replace them with new value from the new children.
   3276  * If not exist, add them.  Roll back when any of those operation failed.
   3277  *
   3278  * @author Andy
   3279  * @param oldChildrenMap the old set of leaf children
   3280  * @param newChildrenMap the new set of leaf children
   3281  * @param actionList a list that match with the order of the old children in the map. It
   3282  *                   marks REPLACED if the child was replaced and marks DIRTY otherwise.
   3283  *                   This list will be use to replace back the old value when rollback.
   3284  *
   3285  * @param deleteList a list that match with the order of the new children in the map and
   3286  *                   marks DELETED if the child is added.  This list will be use to delete newly
   3287  *                   added node when rollback.
   3288  * @return the status of the operation
   3289  */
   3290 SYNCML_DM_RET_STATUS_T DMTree::handleNewChildren( DMMap<DMString, UINT32> oldChildrenMap,
   3291                                             DMMap<DMString, UINT32>& newChildrenMap,
   3292                                             INT8 actionList[],
   3293                                             INT8 deleteList[] )
   3294 {
   3295     SYNCML_DM_RET_STATUS_T status = SYNCML_DM_SUCCESS;
   3296     INT32 oldIndex = 0;
   3297     INT32 newIndex = 0;
   3298     BOOLEAN found = FALSE;
   3299 
   3300     for ( DMMap<DMString, UINT32>::POS  newIt= newChildrenMap.begin(); newIt < newChildrenMap.end(); newIt++ )
   3301     {
   3302       DMAddData *newData = (DMAddData*)newChildrenMap.get_value( newIt );
   3303 
   3304       // compare the new child with list of old children
   3305       for ( DMMap<DMString, UINT32>::POS oldIt = oldChildrenMap.begin(); oldIt < oldChildrenMap.end(); oldIt++ )
   3306       {
   3307 
   3308          if (actionList[oldIndex] == CLEAN || actionList[oldIndex] != REPLACED)
   3309          {    // if not replaced yet
   3310             const DMString & oldNodeURI = oldChildrenMap.get_key( oldIt );
   3311             if ( oldNodeURI == newData->getURI() ) // new child has the same name as the old child
   3312             {
   3313                status = Replace( *newData, SYNCML_DM_REQUEST_TYPE_API );
   3314                if (status != SYNCML_DM_SUCCESS)
   3315                {
   3316                   SYNCML_DM_RET_STATUS_T rollbackStatus = rollback(oldChildrenMap, newChildrenMap, actionList, deleteList);
   3317                   if (rollbackStatus == SYNCML_DM_SUCCESS)
   3318                      return status;
   3319                   else
   3320                      return rollbackStatus;
   3321                }
   3322                actionList[oldIndex] = REPLACED;     // mark replece for roll back
   3323                found = TRUE;
   3324                break;
   3325             }
   3326             else
   3327             {
   3328               actionList[oldIndex] = DIRTY;         // mark visited
   3329             }
   3330          }
   3331          oldIndex++;
   3332       }
   3333 
   3334       if (!found)
   3335       {
   3336         status = Add( *newData, SYNCML_DM_REQUEST_TYPE_API );
   3337         if (status != SYNCML_DM_SUCCESS)
   3338         {
   3339            SYNCML_DM_RET_STATUS_T rollbackStatus = rollback(oldChildrenMap, newChildrenMap, actionList, deleteList);
   3340            if (rollbackStatus == SYNCML_DM_SUCCESS)
   3341               return status;
   3342            else
   3343               return rollbackStatus;
   3344         }
   3345         deleteList[newIndex] = DELETED;  // mark delete for roll back
   3346       }
   3347       else
   3348       {
   3349         deleteList[newIndex] = DIRTY;    // mark visited
   3350       }
   3351       newIndex++;
   3352       oldIndex = 0;
   3353       found = FALSE;
   3354    }
   3355    return status;
   3356 }
   3357 
   3358 /**
   3359  * Loop through the old set of children and check if it has been replaced.
   3360  * If false, delete the child.  Roll back when fail to delete.
   3361  *
   3362  * @author Andy
   3363  * @param oldChildrenMap the old set of leaf children
   3364  * @param newChildrenMap the new set of leaf children
   3365  * @param actionList a list that match with the order of the old children in the map. It
   3366  *                   marks ADDED if the child was added. This list will be use to add back
   3367  *                   the old value when rollback.
   3368  *
   3369  * @param deleteList a list that match with the order of the new children in the map and
   3370  *                   will be use to delete newly added node when rollback.
   3371  * @return the status of the operation
   3372  */
   3373 SYNCML_DM_RET_STATUS_T DMTree::handleOldChildren( DMMap<DMString, UINT32> oldChildrenMap,
   3374                                             DMMap<DMString, UINT32>& newChildrenMap,
   3375                                             INT8 actionList[],
   3376                                             INT8 deleteList[] )
   3377 {
   3378    SYNCML_DM_RET_STATUS_T status = SYNCML_DM_SUCCESS;
   3379    SYNCML_DM_RET_STATUS_T rollbackStatus = SYNCML_DM_SUCCESS;
   3380    int oldIndex = 0;
   3381 
   3382    for ( DMMap<DMString, UINT32>::POS oldIt = oldChildrenMap.begin(); oldIt < oldChildrenMap.end(); oldIt++ )
   3383    {
   3384       if (actionList[oldIndex] == DIRTY)
   3385       {    // if has not been replaced means the child is not in the new list
   3386           const DMString & oldNodeURI = oldChildrenMap.get_key( oldIt );
   3387           status = Delete( oldNodeURI, SYNCML_DM_REQUEST_TYPE_API );
   3388           if (status != SYNCML_DM_SUCCESS)
   3389           {
   3390              rollbackStatus = rollback(oldChildrenMap, newChildrenMap, actionList, deleteList);
   3391              if (rollbackStatus == SYNCML_DM_SUCCESS)
   3392                 return status;
   3393              else
   3394                 return rollbackStatus;
   3395           }
   3396           actionList[oldIndex] = ADDED;  // mark for add back on roll back
   3397       }
   3398       oldIndex++;
   3399    }
   3400    return status;
   3401 }
   3402 
   3403 /**
   3404  * Rollback operation for SetLeafChildren.  It will replace the replaced children
   3405  * with original values.  It will delete the added children.  It will add back
   3406  * the delete children.
   3407  *
   3408  * @author Andy
   3409  * @param oldChildrenMap the old set of leaf children
   3410  * @param newChildrenMap the new set of leaf children
   3411  * @param actionList a list that match with the order of the old children in the map. It marks
   3412  *                   the children with REPLACED means replace with the children with old children
   3413  *                   It marks children with ADDED means add back the old children to the parent.
   3414  *
   3415  * @param deleteList a list that match with the order of the new children in the map.
   3416  *                   DELETED mark mean delete the child
   3417  * @return the status of the operation
   3418  */
   3419 SYNCML_DM_RET_STATUS_T DMTree::rollback( DMMap<DMString, UINT32> oldChildrenMap,
   3420                                      DMMap<DMString, UINT32>& newChildrenMap,
   3421                                      INT8 actionList[],
   3422                                      INT8 deleteList[] )
   3423 {
   3424    int i = 0;
   3425    SYNCML_DM_RET_STATUS_T retStatus = SYNCML_DM_SUCCESS;
   3426    DMAddData oldData;
   3427 
   3428    // unreplace and add back
   3429    for ( DMMap<DMString, UINT32>::POS oldIt = oldChildrenMap.begin(); oldIt < oldChildrenMap.end(); oldIt++ )
   3430    {
   3431        if (actionList[i] != CLEAN)
   3432        {
   3433            oldData.clear();
   3434            DMGetData* oldGetData = (DMGetData*)oldChildrenMap.get_value( oldIt );
   3435            retStatus = oldData.set(oldChildrenMap.get_key(oldIt),
   3436                                    oldGetData->m_nFormat,
   3437                                    (CPCHAR)oldGetData->m_oData.getBuffer(),
   3438                                    oldGetData->m_oData.getSize(),
   3439                                    oldGetData->getType());
   3440            if (retStatus != SYNCML_DM_SUCCESS)
   3441                    return retStatus;
   3442 
   3443            if (actionList[i] == REPLACED)
   3444            {  // replace back
   3445               retStatus = Replace( oldData, SYNCML_DM_REQUEST_TYPE_API );
   3446               if (retStatus != SYNCML_DM_SUCCESS)
   3447                  return retStatus;
   3448            }
   3449            else
   3450              if (actionList[i] == ADDED)
   3451              { // add back
   3452                 retStatus = Add( oldData, SYNCML_DM_REQUEST_TYPE_API );
   3453                 if (retStatus != SYNCML_DM_SUCCESS)
   3454                    return retStatus;
   3455              }
   3456        }
   3457        else
   3458        {
   3459          break;    // didn't touch the node, so stop over here
   3460        }
   3461        i++;
   3462    }
   3463 
   3464    i = 0;
   3465    // delete added nodes
   3466    for ( DMMap<DMString, UINT32>::POS newIt = newChildrenMap.begin(); newIt < newChildrenMap.end(); newIt++ )
   3467    {
   3468      if (deleteList[i] != CLEAN)
   3469      {
   3470        if (deleteList[i] == DELETED)
   3471        {
   3472          retStatus = Delete(((DMAddData*)newChildrenMap.get_value( newIt ))->getURI(),
   3473                             SYNCML_DM_REQUEST_TYPE_API);
   3474          if (retStatus != SYNCML_DM_SUCCESS)
   3475             return retStatus;
   3476        }
   3477      }
   3478      else
   3479      {
   3480        break; // didn't touch the node, so stop over here
   3481      }
   3482      i++;
   3483    } // end for loop
   3484    return SYNCML_DM_SUCCESS;
   3485 }
   3486 
   3487 
   3488 
   3489 /*==================================================================================================
   3490 Function:    GetSubNodeValue
   3491 
   3492 Description: This method is called to retrieve the a value from beneath the DMAcc node for the
   3493              current Server.)
   3494 ARGUMENT PASSED : pParentName
   3495                   pSubNode
   3496 
   3497 OUTPUT PARAMETER: ppDmaccData
   3498 RETURN VALUE    : SYNCML_DM_SUCCESS or SYNCML_DM_FAIL
   3499 IMPORTANT NOTES : This method assumes the DM Tree is locked and the management session is in
   3500                   progress.
   3501 
   3502 ==================================================================================================*/
   3503 SYNCML_DM_RET_STATUS_T
   3504 DMTree::GetAccNodeValue (CPCHAR       pParentName,
   3505                         CPCHAR       pSubNode,
   3506                         DMGetData &  oAccData)
   3507 {
   3508   return Get( ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ) +
   3509                        DMString( DM_STR_SLASH ) +
   3510                        pParentName +
   3511                        DM_STR_SLASH +
   3512                        pSubNode,
   3513                        oAccData,
   3514                        SYNCML_DM_REQUEST_TYPE_INTERNAL );
   3515 
   3516 }
   3517 
   3518 
   3519 /**
   3520  * Get the default server address information
   3521  *
   3522  * @param pAccProfileName the DMAcc node name
   3523  * @param oAddr the object that will hold the server address
   3524  * @param oAddrType the object that will hold the server address type, valud values are "URI", "IPv4"or "IPv6"
   3525  * @param oPortNbr the object that will hold the port address, pPortNbr.oData.getSize() is zero if PortNbr node not found or not set
   3526  * @return the status of the operation
   3527  **/
   3528 SYNCML_DM_RET_STATUS_T
   3529 DMTree::GetDefAccountAddrInfo(CPCHAR pAccProfileName,
   3530                               DMGetData & oAddr,
   3531                               DMGetData & oAddrType,
   3532                               DMGetData & oPortNbr)
   3533 {
   3534     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_FAIL;
   3535 
   3536     if (  m_bVersion_1_2 == TRUE )
   3537     {
   3538       DMString strNodeURI = ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ) +
   3539                             DMString( DM_STR_SLASH ) +
   3540                             pAccProfileName +
   3541                             DM_STR_SLASH +
   3542                             DM_APPADDR;
   3543 
   3544         DMMap<DMString, UINT32> addrNodesMap;
   3545 
   3546         dm_stat = getInteriorChildren( strNodeURI, addrNodesMap, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3547 
   3548         if (dm_stat != SYNCML_DM_SUCCESS)
   3549       {
   3550            dmFreeGetMap((DMMap<DMString, UINT32>&)addrNodesMap);
   3551            return SYNCML_DM_FAIL;
   3552         }
   3553 
   3554         if( addrNodesMap.size() == 0 )
   3555         {
   3556           dmFreeGetMap((DMMap<DMString, UINT32>&)addrNodesMap);
   3557           return SYNCML_DM_NOT_FOUND;
   3558         }
   3559 
   3560         while ( true )
   3561       {
   3562            DMMap<DMString, UINT32>::POS  iter = addrNodesMap.begin();
   3563            DMString addrNodeName = addrNodesMap.get_key(iter);
   3564 
   3565          addrNodeName += DM_STR_SLASH;
   3566 
   3567            dm_stat = Get( addrNodeName + DM_ADDR, oAddr,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3568            if ( dm_stat != SYNCML_DM_SUCCESS ) {
   3569               break;
   3570            }
   3571 
   3572            // Get the Addr Type
   3573            dm_stat = Get(addrNodeName + DM_ADDRTYPE, oAddrType,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3574            if ( dm_stat != SYNCML_DM_SUCCESS )
   3575            {
   3576                 // session will set to default (1=http) if null
   3577                oAddrType.set(SYNCML_DM_FORMAT_CHR, "1", 1, NULL);
   3578            }
   3579 
   3580            // Get the portNbrs if any is specified
   3581            DMMap<DMString, UINT32>portNbrNodesMap;
   3582            dm_stat = getInteriorChildren( addrNodeName + DM_PORT, portNbrNodesMap, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3583 
   3584            // if there are no child nodes, but this is OK since portNbr is optional
   3585            if ( dm_stat != SYNCML_DM_SUCCESS )
   3586          {
   3587               DMString dummyStr = NULL;
   3588               oPortNbr.set(SYNCML_DM_FORMAT_NULL, dummyStr, 0, NULL);
   3589               dmFreeGetMap((DMMap<DMString, UINT32>&)addrNodesMap);
   3590               return SYNCML_DM_SUCCESS;
   3591            }
   3592 
   3593            // if portNbr node is present, retrieve its value
   3594            iter = portNbrNodesMap.begin();
   3595            DMString portNbrName = portNbrNodesMap.get_key(iter);
   3596 
   3597            dm_stat = Get(portNbrName + DM_STR_SLASH + DM_PORTNBR, oPortNbr,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3598 
   3599            if ( dm_stat != SYNCML_DM_SUCCESS )
   3600          {
   3601               DMString dummyStr = NULL;
   3602               oPortNbr.set(SYNCML_DM_FORMAT_NULL, dummyStr, 0, NULL);
   3603            }
   3604 
   3605            dmFreeGetMap((DMMap<DMString, UINT32>&)addrNodesMap);
   3606            dmFreeGetMap((DMMap<DMString, UINT32>&)portNbrNodesMap);
   3607            return SYNCML_DM_SUCCESS;
   3608         }
   3609 
   3610         // Got here because something went wrong
   3611         dmFreeGetMap((DMMap<DMString, UINT32>&)addrNodesMap);
   3612     }
   3613     else
   3614     {
   3615         /* Fill the pNodeUri with the string "./SyncML/DMAcc/<pAccProfileName>/AppAddr" */
   3616         DMString strNodeURI = ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ) +
   3617                               DMString( DM_STR_SLASH ) +
   3618                               pAccProfileName +
   3619                               DM_STR_SLASH;
   3620 
   3621         dm_stat = Get(strNodeURI + DM_ADDR, oAddr, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3622 
   3623         if ( dm_stat == SYNCML_DM_SUCCESS )
   3624         {
   3625              dm_stat = Get( strNodeURI + DM_ADDRTYPE, oAddrType, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3626              if ( dm_stat == SYNCML_DM_SUCCESS )
   3627              {
   3628                  dm_stat = Get( strNodeURI + DM_PORTNBR, oPortNbr, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3629 
   3630                  if ( SYNCML_DM_NOT_FOUND == dm_stat )
   3631                  {
   3632                      // DM: optional, set to default if not found
   3633                      DMString dummyStr = NULL;
   3634                      oPortNbr.set(SYNCML_DM_FORMAT_NULL, dummyStr, 0, NULL);
   3635                      dm_stat = SYNCML_DM_SUCCESS;
   3636                  }
   3637              }
   3638          }
   3639     }
   3640 
   3641     return dm_stat;
   3642 }
   3643 
   3644 /**
   3645  * Get the server authentication information in the specified DMAcc profile
   3646  *
   3647  * @param pAccProfileName the DMAcc node name
   3648  * @param oAuthType the object that will hold the authentication type
   3649  * @param oAuthName the object that will hold the authentication name
   3650  * @param oAuthSecret the object that will hold the authentication secret
   3651  * @param oAuthData the object that will hold the authentication data
   3652  * @param sAuthDataUri the DMString object that will hold the full server AAuthData (nonce) URI
   3653  * @return the status of the operation
   3654  **/
   3655 SYNCML_DM_RET_STATUS_T
   3656 DMTree::GetServerAuthInfo(CPCHAR pAccProfileName,
   3657                           CPCHAR pAuthType,
   3658                           DMGetData& oAuthName,
   3659                           DMGetData& oAuthSecret,
   3660                           DMGetData& oAuthData,
   3661                           DMString& oAuthDataUri)
   3662 {
   3663     DMGetData oAuthType; // dummy parameter
   3664 
   3665     return this->GetAuthInfo(pAccProfileName,
   3666                              DM_AUTHLEVEL_SRVCRED,
   3667                              pAuthType,
   3668                              oAuthType,
   3669                              oAuthName,
   3670                              oAuthSecret,
   3671                              oAuthData,
   3672                              oAuthDataUri);
   3673 }
   3674 
   3675 /**
   3676  * Get the HTTP authentication information in the specified DMAcc profile
   3677  *
   3678  * @param pAccProfileName the DMAcc node name
   3679  * @param oAuthType the object that will hold the authentication type
   3680  * @param oAuthName the object that will hold the authentication name
   3681  * @param oAuthSecret the object that will hold the authentication secret
   3682  * @param oAuthData the object that will hold the authentication data
   3683  * @return the status of the operation
   3684  **/
   3685 SYNCML_DM_RET_STATUS_T
   3686 DMTree::GetHttpAuthInfo(CPCHAR pAccProfileName,
   3687                           DMGetData& oAuthType,
   3688                           DMGetData& oAuthName,
   3689                           DMGetData& oAuthSecret,
   3690                           DMGetData& oAuthData,
   3691                           DMString& oAuthDataUri)
   3692 {
   3693     return this->GetAuthInfo(pAccProfileName,
   3694                              DM_AUTHLEVEL_HTTP,
   3695                              NULL,
   3696                              oAuthType,
   3697                              oAuthName,
   3698                              oAuthSecret,
   3699                              oAuthData,
   3700                              oAuthDataUri);
   3701 }
   3702 
   3703 /**
   3704  * Get the client authentication information matching the specified authentication type
   3705  *
   3706  * @param pAccProfileName the DMAcc node name
   3707  * @param pAuthType the required client authentication type
   3708  * @param oAuthName the object that will hold the authentication name
   3709  * @param oAuthSecret the object that will hold the authentication secret
   3710  * @param oAuthData the object that will hold the authentication data
   3711  * @param sAuthDataUri the DMString object that will hold the full client AAuthData (nonce) URI
   3712  * @return the status of the operation
   3713  **/
   3714 SYNCML_DM_RET_STATUS_T
   3715 DMTree::GetClientAuthInfo(CPCHAR pAccProfileName,
   3716                           CPCHAR pAuthType,
   3717                           DMGetData& oAuthName,
   3718                           DMGetData& oAuthSecret,
   3719                           DMGetData& oAuthData,
   3720                           DMString& oAuthDataUri,
   3721                           DMGetData& oAuthType)
   3722 {
   3723     return this->GetAuthInfo(pAccProfileName,
   3724                              DM_AUTHLEVEL_CLCRED,
   3725                              pAuthType,
   3726                              oAuthType,
   3727                              oAuthName,
   3728                              oAuthSecret,
   3729                              oAuthData,
   3730                              oAuthDataUri);
   3731 }
   3732 
   3733 /**
   3734  * Get the authentication information matching the specified authentication level and type
   3735  *
   3736  * @param pAccProfileName the DMAcc node name
   3737  * @param pAuthLevel the required authentication level, should be either "CLCRED","SRVCRED","OBEX" or "HTTP"
   3738  * @param pAuthType the required authentication type, should be either "HTTP-BASIC", "HTTP-DIGEST", "TRANSPORT", "HMAC", "DIGEST" or "BASIC". NULL if no specific type is required, then the first node with matching authentication level is returned
   3739  * @param oAuthType the object that will hold the authentication type
   3740  * @param oAuthName the object that will hold the authentication name
   3741  * @param oAuthSecret the object that will hold the authentication secret
   3742  * @param oAuthData the object that will hold the authentication data
   3743  * @param sAuthDataUri the DMString object that will hold the full AAuthData (nonce) URI
   3744  * @return the status of the operation
   3745  **/
   3746 SYNCML_DM_RET_STATUS_T
   3747 DMTree::GetAuthInfo(CPCHAR pAccProfileName,
   3748                     CPCHAR pAuthLevel,
   3749                     CPCHAR pAuthType,
   3750                     DMGetData& oAuthType,
   3751                     DMGetData& oAuthName,
   3752                     DMGetData& oAuthSecret,
   3753                     DMGetData& oAuthData,
   3754                     DMString& oAuthDataUri)
   3755 {
   3756   SYNCML_DM_RET_STATUS_T  dm_stat = SYNCML_DM_FAIL;
   3757   CPCHAR                  szDMAccRootPath = ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH );
   3758 
   3759   oAuthDataUri = NULL;
   3760 
   3761   if ( m_bVersion_1_2 == TRUE )
   3762   {
   3763     /* Fill the pNodeUri with the string "./SyncML/DMAcc/<pAccProfileName>/AppAuth" */
   3764     DMString  strAPPAUTHNodeUri = szDMAccRootPath +
   3765                                    DMString( DM_STR_SLASH ) +
   3766                                    pAccProfileName +
   3767                                    DM_STR_SLASH +
   3768                                    DM_APPAUTH;
   3769 
   3770     DMMap<DMString, UINT32> authNodesMap;
   3771 
   3772     dm_stat = getInteriorChildren( strAPPAUTHNodeUri, authNodesMap,SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3773     // if there are no child nodes, no client authentication nodes are found
   3774     if ( dm_stat != SYNCML_DM_SUCCESS )
   3775     {
   3776       dmFreeGetMap((DMMap<DMString, UINT32>&)authNodesMap);
   3777       return SYNCML_DM_FAIL;
   3778     }
   3779 
   3780     for ( DMMap<DMString, UINT32>::POS iter= authNodesMap.begin();
   3781           iter < authNodesMap.end();
   3782           iter++ )
   3783     {
   3784       dm_stat = SYNCML_DM_FAIL;
   3785 
   3786       DMString  authNodeName = authNodesMap.get_key(iter);
   3787       DMString  strAPPAUTHInstPath = authNodeName + DM_STR_SLASH;
   3788       DMString  authLevelUri(strAPPAUTHInstPath + DM_AAUTHLEVEL);
   3789       DMString  authTypeUri(strAPPAUTHInstPath + DM_AAUTHTYPE);
   3790       DMString  authNameUri(strAPPAUTHInstPath + DM_AAUTHNAME);
   3791       DMString  authSecretUri(strAPPAUTHInstPath + DM_AAUTHSECRET);
   3792       DMString  authDataUri(strAPPAUTHInstPath + DM_AAUTHDATA);
   3793       DMGetData authLevel;
   3794 
   3795       dm_stat = Get(authLevelUri.c_str(), authLevel,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3796 
   3797       if ( ( dm_stat == SYNCML_DM_SUCCESS ) &&
   3798             ( DmStrcmp(authLevel.getCharData(), pAuthLevel) == 0 ) )
   3799       {
   3800         dm_stat = Get(authTypeUri.c_str(), oAuthType,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3801 
   3802         if ( pAuthType == NULL || strlen(pAuthType) == 0 ||
   3803              (oAuthType.getCharData() != NULL && DmStrcmp( oAuthType.getCharData(), pAuthType) == 0) )
   3804         {
   3805           dm_stat = Get(authNameUri.c_str(), oAuthName,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3806 
   3807           if ( dm_stat == SYNCML_DM_SUCCESS )
   3808           {
   3809             dm_stat = Get(authSecretUri.c_str(), oAuthSecret,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3810 
   3811             if ( dm_stat == SYNCML_DM_SUCCESS )
   3812             {
   3813               dm_stat = Get(authDataUri.c_str(), oAuthData,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3814             }
   3815           }
   3816 
   3817           oAuthDataUri = strAPPAUTHInstPath;
   3818           break;
   3819         }
   3820       }
   3821     }
   3822 
   3823     if (0 == oAuthDataUri.length())
   3824     {
   3825       // DM: no matching AUTHINFO is found
   3826       dm_stat = SYNCML_DM_FAIL;
   3827     }
   3828 
   3829     dmFreeGetMap((DMMap<DMString, UINT32>&)authNodesMap);
   3830   }
   3831   else
   3832   {
   3833         DMString strNodeURI = szDMAccRootPath +
   3834                           DMString( DM_STR_SLASH ) +
   3835                           pAccProfileName +
   3836                           DM_STR_SLASH;
   3837 
   3838         DMString authNameUri(strNodeURI);
   3839         DMString authSecretUri(strNodeURI);
   3840         DMString authDataUri(strNodeURI);
   3841         DMString authTypeUri(strNodeURI);
   3842         BOOLEAN bClientAuth = ( DmStrcmp(pAuthLevel,DM_AUTHLEVEL_CLCRED) == 0 );
   3843 
   3844         if ( bClientAuth )
   3845         {
   3846               authTypeUri += DM_AUTHPREF;
   3847               authNameUri += DM_USERNAME;
   3848               authSecretUri += DM_CLIENTPW;
   3849               authDataUri += DM_CLIENTNONCE;
   3850 
   3851               dm_stat = Get(authTypeUri.c_str(), oAuthType,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3852         }
   3853         else
   3854         {
   3855               authNameUri += DM_NAME;
   3856               authSecretUri += DM_SERVERPW;
   3857               authDataUri += DM_SERVERNONCE;
   3858 
   3859               dm_stat = SYNCML_DM_SUCCESS;
   3860         }
   3861 
   3862         if ( dm_stat == SYNCML_DM_SUCCESS  || dm_stat == SYNCML_DM_NOT_FOUND )
   3863         {
   3864             dm_stat = Get(authNameUri.c_str(), oAuthName,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3865 
   3866             if ( dm_stat == SYNCML_DM_SUCCESS )
   3867             {
   3868                 dm_stat = Get(authSecretUri.c_str(), oAuthSecret,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3869                 if ( dm_stat == SYNCML_DM_SUCCESS )
   3870                 {
   3871                     dm_stat = Get(authDataUri.c_str(), oAuthData,  SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3872                 }
   3873             }
   3874         }
   3875 
   3876         oAuthDataUri = strNodeURI;
   3877   }
   3878 
   3879   return dm_stat;
   3880 }
   3881 
   3882 /**
   3883  * Get the authentication type used by the last DM session
   3884  *
   3885  * @param pAccProfileName the DMAcc node name
   3886  * @param oClientAuthType the object that will hold the client authentication type
   3887  * @return the status of the operation
   3888  **/
   3889 SYNCML_DM_RET_STATUS_T
   3890 DMTree::GetLastClientAuthType(CPCHAR pAccProfileName,
   3891                               DMGetData& oClientAuthType)
   3892 {
   3893   return Get( ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ) +
   3894                                     DMString( DM_STR_SLASH ) +
   3895                                     pAccProfileName +
   3896                                     DM_STR_SLASH +
   3897                                     DM_EXT +
   3898                                     DM_STR_SLASH +
   3899                                     DM_LASTCLIENTAUTHTYPE,
   3900               oClientAuthType,
   3901               SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3902 }
   3903 /**
   3904  * Set the authentication type used by the last DM session
   3905  *
   3906  * @param pAccProfileName the DMAcc node name
   3907  * @param pClientAuthType the client authentication type value to set
   3908  * @return the status of the operation
   3909  **/
   3910 SYNCML_DM_RET_STATUS_T
   3911 DMTree::SetLastClientAuthType(CPCHAR pAccProfileName,
   3912                               CPCHAR pClientAuthType)
   3913 {
   3914     DMAddData               oNodeData;
   3915     SYNCML_DM_RET_STATUS_T  dm_stat = SYNCML_DM_SUCCESS;
   3916 
   3917     DMString strEXTURI = ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ) +
   3918                           DMString( DM_STR_SLASH ) +
   3919                           pAccProfileName +
   3920                           DM_STR_SLASH +
   3921                           DM_EXT;
   3922 
   3923     DMString strLastClientAuthURI = strEXTURI +
   3924                                     DM_STR_SLASH +
   3925                                     DM_LASTCLIENTAUTHTYPE;
   3926 
   3927     dm_stat = oNodeData.set( strEXTURI,
   3928                              SYNCML_DM_FORMAT_NODE,
   3929                              NULL,
   3930                              0,
   3931                              "text/plain");
   3932 
   3933     if ( dm_stat == SYNCML_DM_SUCCESS )
   3934     {
   3935       Add(oNodeData, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3936     }
   3937 
   3938     dm_stat = oNodeData.set(strLastClientAuthURI,
   3939                             SYNCML_DM_FORMAT_CHR,
   3940                             pClientAuthType,
   3941                             DmStrlen(pClientAuthType),
   3942                             "text/plain" );
   3943 
   3944     if ( dm_stat == SYNCML_DM_SUCCESS )
   3945     {
   3946         dm_stat = Replace(oNodeData, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3947 
   3948         if ( dm_stat == SYNCML_DM_NOT_FOUND )
   3949         {
   3950           dm_stat = Add(oNodeData, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   3951         }
   3952     }
   3953 
   3954     return dm_stat;
   3955 }
   3956 
   3957 #ifdef LOB_SUPPORT
   3958 /*==============================================================================
   3959 FUNCTION        : IsESN
   3960 
   3961 DESCRIPTION     : Is it a External Storage Node
   3962 
   3963 ARGUMENT PASSED : pNodeValue,
   3964                   nodeLength,
   3965                   pNode
   3966                   pNodeName
   3967 OUTPUT PARAMETER:
   3968 RETURN VALUE    :
   3969 IMPORTANT NOTES :
   3970 ==============================================================================*/
   3971 SYNCML_DM_RET_STATUS_T
   3972 DMTree::IsESN(CPCHAR pbURI, BOOLEAN &isESN)
   3973 {
   3974     DMString strPluginURI;    // uri without ?xxx stuff for plugins and so on
   3975     DMString strURI;
   3976 
   3977     if ( !GetPluginURI( pbURI, strURI, strPluginURI ) )
   3978       return SYNCML_DM_COMMAND_FAILED;
   3979 
   3980     isESN = m_oMDFObj.IsESN( strPluginURI );
   3981     return SYNCML_DM_SUCCESS;
   3982 }
   3983 #endif
   3984 
   3985 DMMetaDataManager& DMTree::GetMetaDataManager()
   3986 {
   3987     return m_oMDFObj;
   3988 }
   3989