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_class_private.cc
     20 //
     21 //   General Description:Contains the implementations of the methods of
     22 //                       DMNode class.
     23 //------------------------------------------------------------------------
     24 
     25 #include "dm_tree_util.h"
     26 #include "dm_tree_plugin_root_node_class.H"
     27 #include "xpl_Logger.h"
     28 #include "dm_uri_utils.h"
     29 #include "SyncML_DM_Archive.H"
     30 #include "dmprofile.h"
     31 #include "dm_tree_plugin_util.H"
     32 #include "dm_tree_default_interior_node_class.H"
     33 #include "dm_tree_class.H"
     34 
     35 //------------------------------------------------------------------------
     36 //                          GLOBAL VARIABLES
     37 //------------------------------------------------------------------------
     38 DMTree               dmTreeObj;
     39 
     40 //------------------------------------------------------------------------
     41 //
     42 // FUNCTION        : GetLastSegmentOfURI
     43 //
     44 // DESCRIPTION     : This function will return the starting location
     45 //                   of the last segment of the URI.
     46 //
     47 // ARGUMENTS PASSED: UINT8 *pbURI
     48 // RETURN VALUE    : UINT8 *
     49 //                       - Pointer to starting location of last segment
     50 // PRE-CONDITIONS  : Input parameter SHOULD NOT BE NULL.
     51 // POST-CONDITIONS :
     52 // IMPORTANT NOTES :
     53 // REQUIREMENT #   : N/A The methods in this file are private methods
     54 //                   internal to DMTNM implementation
     55 //------------------------------------------------------------------------
     56 BOOLEAN DMTree::GetLastSegmentOfURI( DMString& strURI, DMString& strLastSegment )
     57 {
     58     if (!strURI.GetBuffer())
     59         return FALSE;
     60 
     61   char* szLastSlash = DmStrrchr( strURI.GetBuffer(), SYNCML_DM_FORWARD_SLASH );
     62 
     63   if ( !szLastSlash )
     64     return FALSE;
     65 
     66   *szLastSlash = 0;
     67 
     68   strLastSegment = ++szLastSlash;
     69   return TRUE;
     70 }
     71 
     72 //------------------------------------------------------------------------
     73 //
     74 // FUNCTION        : IsValidServer
     75 //
     76 // DESCRIPTION     : This function will check the access type and the
     77 //                   ACL permissions of the node.
     78 //
     79 //
     80 // ARGUMENTS PASSED:
     81 
     82 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
     83 //                    - It returns SYNCML_DM_SUCCESS if the AccessType is set
     84 //                      and the ACL permisssion is there for the requested
     85 //                      operation.
     86 //                    - It returns SYNCML_DM_COMMAND_NOT_ALLOWED if the
     87 //                      Accesstype is not for the requested operation.
     88 //                    - It returns SYNCML_DM_PERMISSION_FAILED if the ACL
     89 //                      permission is not for the requested operation
     90 //                    - It returns SYNCML_DM_COMMAND_NOT_IMPLEMENTED if
     91 //                      the command is not implemented by the client.
     92 // PRE-CONDITIONS  :
     93 // POST-CONDITIONS :
     94 // IMPORTANT NOTES :
     95 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
     96 //------------------------------------------------------------------------
     97 SYNCML_DM_RET_STATUS_T DMTree::IsValidServer(CPCHAR pURI,
     98                                          SYNCML_DM_ACCESS_TYPE_T accessType,
     99                                          SYNCML_DM_REQUEST_TYPE_T eRequestType,
    100                                          BOOLEAN bCheckAccess,
    101                                          BOOLEAN bIsCheckLocal,
    102                                          DMMetaPCharVector* pChildDependNodes /*=NULL*/)
    103 {
    104 
    105   if (pURI == NULL)
    106   {
    107       //XPL_LOG_DM_TMN_Debug(("DMTree::IsValidServer: pURI is null \n"));
    108       return SYNCML_DM_COMMAND_FAILED;
    109   }
    110 
    111   if ( eRequestType != SYNCML_DM_REQUEST_TYPE_SERVER )
    112   {
    113      //XPL_LOG_DM_TMN_Debug(("DMTree::IsValidServer: Request type is not SYNCML_DM_REQUEST_TYPE_SERVER \n"));
    114      bIsCheckLocal = FALSE;
    115   }
    116 
    117   if ( !m_oACLObj.IsPermitted( pURI,
    118                                GetServerId(),
    119                                (SYNCML_DM_ACL_PERMISSIONS_T)accessType,
    120                                bIsCheckLocal) )
    121   {
    122      XPL_LOG_DM_TMN_Debug(("DMTree::IsValidServer: permission failed \n"));
    123      return SYNCML_DM_PERMISSION_FAILED;
    124   }
    125 
    126   if ( accessType !=  SYNCML_DM_GET_ACCESS_TYPE && bCheckAccess )
    127   {
    128       if( !m_oMDFObj.VerifyAccessType(pURI,accessType, pChildDependNodes) )
    129       {
    130         XPL_LOG_DM_TMN_Debug(("DMTree::IsValidServer: access not allowed \n"));
    131         return (SYNCML_DM_COMMAND_NOT_ALLOWED);
    132       }
    133   }
    134 
    135   return SYNCML_DM_SUCCESS;
    136 }
    137 
    138 
    139 //------------------------------------------------------------------------
    140 //
    141 // FUNCTION        : GetChildren
    142 //
    143 // DESCRIPTION     : This function gives the list of childs of the node
    144 //
    145 //
    146 // ARGUMENTS PASSED: DMNode *psNode
    147 //                   DMString & strChildren
    148 //                       - contains childs each child seperated by '/'
    149 //
    150 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    151 //                     - It returns SYNCML_DM_SUCCESS if the function return
    152 //                       the childs.
    153 //                     - It returns SYNCML_DM_COMMAND_FAILED if the
    154 //                       pointer psNode is NULL.
    155 // PRE-CONDITIONS  :
    156 // POST-CONDITIONS :
    157 // IMPORTANT NOTES :
    158 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
    159 //------------------------------------------------------------------------
    160 SYNCML_DM_RET_STATUS_T DMTree::GetChildren(
    161     CPCHAR szURI,
    162     const DMNode *psNode,
    163     SYNCML_DM_REQUEST_TYPE_T eRequestType,
    164     DMString& strChildren ) const
    165 {
    166     DMMetaDataManager & m_oMDFObj =  dmTreeObj.GetMetaDataManager();
    167     BOOLEAN bIsLocal = FALSE;
    168 
    169     DMString strChildrenOPI;
    170 
    171     strChildren = NULL;
    172 
    173     if( !psNode )
    174     return SYNCML_DM_COMMAND_FAILED;
    175 
    176     psNode = psNode->pcFirstChild;
    177 
    178     while(psNode)
    179     {
    180         bIsLocal = FALSE;
    181         if ( eRequestType ==  SYNCML_DM_REQUEST_TYPE_SERVER )
    182         {
    183               DMString szChildURI(szURI);
    184 
    185               szChildURI += "/";
    186               szChildURI += psNode->abNodeName;
    187               bIsLocal = m_oMDFObj.IsLocal(szChildURI);
    188         }
    189         if ( !bIsLocal )
    190         {
    191             strChildren += psNode->abNodeName;
    192 
    193             if ( psNode->pcNextSibling )
    194                 strChildren += "/";
    195         }
    196         strChildrenOPI += psNode->abNodeName;
    197 
    198         if ( psNode->pcNextSibling )
    199             strChildrenOPI += "/";
    200 
    201         psNode = psNode->pcNextSibling;
    202   }
    203 
    204   // DP: Overlay plugin support
    205   if ( m_ptrCacheOPI != NULL )
    206   {
    207     m_oMDFObj.UpdateChildrenList( szURI, strChildrenOPI );
    208   }
    209 
    210   return SYNCML_DM_SUCCESS;
    211 }
    212 
    213 
    214 
    215 //------------------------------------------------------------------------
    216 //
    217 // FUNCTION        : GetChildrenCount
    218 //
    219 // DESCRIPTION     : This function gives the number of childs of the node
    220 //
    221 //
    222 // ARGUMENTS PASSED: DMNode *psNode
    223 //
    224 // RETURN VALUE    : childs count
    225 // PRE-CONDITIONS  :
    226 // POST-CONDITIONS :
    227 // IMPORTANT NOTES :
    228 //------------------------------------------------------------------------
    229 UINT16 DMTree::GetChildrenCount(const DMNode *psNode)const
    230 {
    231   int childCount = 0;
    232 
    233   if( !psNode )
    234     return 0;
    235 
    236   psNode = psNode->pcFirstChild;
    237 
    238   while(psNode)
    239   {
    240      childCount++;
    241      psNode = psNode->pcNextSibling;
    242   }
    243 
    244   return childCount;
    245 }
    246 
    247 //------------------------------------------------------------------------
    248 //
    249 // FUNCTION        : FindNodeByURI
    250 //
    251 // DESCRIPTION     : This functions returns the pointer to DMNode of the
    252 //                   the last segment of the URI. This function will use
    253 //                   both Depth First Search and Breadth First Search
    254 //                   traversal algorithms to search.
    255 //
    256 //
    257 // ARGUMENTS PASSED: UINT8* pbURI - Contails the URI
    258 // RETURN VALUE    : DMNode*
    259 //                      - It returns NULL if the node was NOT found
    260 //                        in the tree.
    261 //                      - It returns Pointer to the DMNode if it finds
    262 //                        the node in the tree.
    263 // PRE-CONDITIONS  :
    264 // POST-CONDITIONS :
    265 // IMPORTANT NOTES :
    266 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
    267 //------------------------------------------------------------------------
    268 DMNode* DMTree::FindNodeByURI(CPCHAR pbURI)
    269 {
    270   XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: Enter. pbURI=%s\n",pbURI));
    271   DMString strURI = pbURI;
    272   char *szURI = strURI.GetBuffer();
    273 
    274   const char *pbURISegment = NULL;
    275   DMNode *psFindNode  = NULL;
    276   DMNode *pParentCopy = NULL;
    277 
    278 #ifdef LOB_SUPPORT
    279   // Is a cached ESD
    280   psFindNode = GetESN(pbURI);
    281   if (psFindNode != NULL)
    282   {
    283     XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: this is a cached ESD\n"));
    284     return psFindNode;
    285   }
    286 #endif
    287   // last access time for pArchive
    288   XPL_CLK_CLOCK_T currentTime = m_currentTime; // use cached value if available
    289   if (currentTime==0)
    290     currentTime = XPL_CLK_GetClock();
    291 
    292   // reset OPI cache
    293   m_ptrCacheOPI = NULL;
    294   m_oOPICacheData.metaNodeID = -1; // metanode ID is set later only for PI node
    295 
    296   while ( m_oOPICacheData.aPD.size() )
    297     m_oOPICacheData.aPD.remove(0);    // function "remove" does not free buffer in contrast to "removeall"
    298 
    299   psFindNode  = m_psRoot;
    300 
    301   pbURISegment = GetURISegment(&szURI);
    302   while(psFindNode != NULL && pbURISegment)
    303   {
    304     //XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: szURI=%s, pbURISegment=%s\n",szURI, pbURISegment));
    305     //XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: m_psRoot.abNodeName=%s\n",m_psRoot->abNodeName.GetBuffer()));
    306     // This functions will seach for the segment in the siblings linked
    307     // list
    308     pParentCopy = psFindNode;
    309 
    310     psFindNode = FindNodeInNextSiblingsList(psFindNode, pbURISegment);
    311     if(psFindNode == NULL) {
    312       pParentCopy = pParentCopy->pcParentOfNode;
    313       if ( pParentCopy && LoadSkeletonParentArchive(pParentCopy) ) {
    314         psFindNode = FindNodeInNextSiblingsList(pParentCopy->pcFirstChild, pbURISegment);
    315       }
    316 
    317       if ( !psFindNode )
    318       {
    319         if (szURI == NULL && m_ptrCacheOPI != NULL )
    320        {
    321                psFindNode = GetOPINode( pbURI );
    322 #ifdef LOB_SUPPORT
    323             if(psFindNode != NULL && m_oMDFObj.IsESN( pbURI ))
    324             SetESNCache(pbURI ,psFindNode);
    325 #endif
    326                 XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: find node from OPI cache \n"));
    327         return psFindNode;
    328         }
    329         XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: can not find the node \n"));
    330         return (NULL);
    331       }
    332     }
    333 
    334     // OPI
    335     //XPL_LOG_DM_TMN_Debug(("DMTree::FindNodeByURI: Check if the node is a OverlayPI \n"));
    336     if ( psFindNode->IsOverlayPI() )
    337     {
    338       m_ptrCacheOPI = psFindNode->getOverlayPI();
    339       // reset data again for case overlapped opi
    340       while ( m_oOPICacheData.aPD.size() )
    341         m_oOPICacheData.aPD.remove(0);    // function "remove" does not free buffer in contrast to "removeall"
    342     }
    343 
    344     if ( psFindNode->IsOverlayPIData() && psFindNode->getOverlayPIData())
    345       m_oOPICacheData.aPD.push_back( *psFindNode->getOverlayPIData());
    346 
    347     // OPI synchronization support
    348     if ( m_ptrCacheOPI != NULL && !psFindNode->opiSyncNotNeeded() )
    349       CheckOpiSync( psFindNode, strURI.GetBuffer(), pbURISegment );
    350 
    351     pbURISegment = GetURISegment(&szURI);
    352     // If the pbURISegment is NULL means then it has processed the
    353     // full URI and got the DMNode pointer for the last segment of
    354     // the URI.
    355     // For plugin Proxy node, use the proxy node for ALL subtree.
    356     if ((pbURISegment == NULL) || (pbURISegment[0] == '\0') || (psFindNode->isPlugin())) {
    357 
    358         if ( psFindNode->IsSkeletonNode() && psFindNode->pArchive )
    359           psFindNode->pArchive->deserialize(this);
    360 
    361         // e50024
    362         // Update last access time of the archive
    363         DMNode * pNode = psFindNode;
    364 
    365         while ( pNode ) {
    366             if ( pNode->pArchive ) {
    367                 pNode->pArchive->setLastAccessedTime(currentTime);
    368                 break;
    369             }
    370             pNode = pNode->pcParentOfNode;
    371         }
    372 #ifdef LOB_SUPPORT
    373     if(psFindNode != NULL && m_oMDFObj.IsESN( pbURI ))
    374             SetESNCache(pbURI ,psFindNode);
    375 #endif
    376 
    377         return (psFindNode);
    378     }
    379 
    380     // If the URI segment is NOT NULL then we have look into
    381     // the childs list of the current node because previous URI
    382     // segment will become the parent of the current URI segment.
    383     if ( !psFindNode->pcFirstChild )
    384       LoadSkeletonParentArchive( psFindNode );
    385 
    386     psFindNode = psFindNode->pcFirstChild;
    387   }
    388 
    389   if (szURI == NULL && m_ptrCacheOPI != NULL )
    390  {     psFindNode = GetOPINode( pbURI );
    391 
    392 #ifdef LOB_SUPPORT
    393     if(psFindNode != NULL && m_oMDFObj.IsESN( pbURI ))
    394             SetESNCache(pbURI ,psFindNode);
    395 #endif
    396     return psFindNode;
    397   }
    398   return (NULL);
    399 }
    400 
    401 //------------------------------------------------------------------------
    402 //
    403 // FUNCTION        : ParseACL
    404 //
    405 // DESCRIPTION     : This function will parse the ACL according the BNF
    406 //                   defined in FSRS.
    407 //
    408 // ARGUMENTS PASSED: UINT8* pACL
    409 //                      - ACL value
    410 //
    411 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    412 //                      - It returns SYNCML_DM_COMMAND_FAILED in case
    413 //                        if there is any failure.
    414 //                      - It returns SYNCML_DM_SUCCESS in case if the ACL value
    415 //                        parsed successfully.
    416 //                      - It returns SYNCML_DM_DEVICE_FULL in case if the
    417 //                        device is out of memory.
    418 //
    419 // PRE-CONDITIONS  :
    420 // POST-CONDITIONS :
    421 // IMPORTANT NOTES :
    422 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
    423 //------------------------------------------------------------------------
    424 SYNCML_DM_RET_STATUS_T DMTree::ParseACL(UINT8* pACL)
    425 {
    426   UINT8 *pbStartingPosOfCmd = NULL;
    427   UINT8 *pbACL = NULL, *pNew;
    428 
    429   // oCommandsInACL variable is used to decide whether to add "&" to the
    430   // ACL value or not while parsing the ACL. Assume that if the server
    431   // has fired an ACL value like ACL = Add=ServerA&Get=ServerB then after
    432   // processing "ADD".
    433   // BOOLEAN oCommandsInACL = FALSE;
    434 
    435   SYNCML_DM_RET_STATUS_T wReturnCode = SYNCML_DM_SUCCESS;
    436 
    437   XPL_LOG_DM_TMN_Debug(("Entered DMTree::ParseACL \n"));
    438 
    439   if(pACL == NULL)
    440     return (SYNCML_DM_SUCCESS);
    441 
    442   if(pACL[0] == '\0')
    443     return (SYNCML_DM_COMMAND_FAILED);
    444 
    445   pNew = pbACL = (UINT8*) DmAllocMem((sizeof(UINT8) * (DmStrlen((const char*)pACL) + 1)));
    446   if (!pbACL)
    447       return SYNCML_DM_DEVICE_FULL;
    448 
    449   DmStrcpy((char*)pbACL, (const char*)pACL);
    450   pbStartingPosOfCmd = (UINT8*)pbACL;
    451 
    452   while(*pbACL != '\0')
    453   {
    454     pbACL = (UINT8*)DmStrchr((CPCHAR)pbACL, SYNCML_DM_EQUAL_TO);
    455 
    456     if(pbACL == NULL)
    457     {
    458       XPL_LOG_DM_TMN_Debug(("Invalid ACL String \n"));
    459       DmFreeMem(pNew);
    460       return (SYNCML_DM_COMMAND_FAILED);
    461     }
    462     *pbACL = '\0';
    463 
    464     // Here we are checking for the first character to reduce
    465     // the time.
    466     if(pbStartingPosOfCmd[0] == SYNCML_DM_ASCII_CAPITAL_R)
    467     {
    468       // We have already compared "R" and now we have to check if it is
    469       // "eplace".
    470       if(DmStrcmp((CPCHAR)&pbStartingPosOfCmd[1], SYNCML_DM_EPLACE))
    471           wReturnCode = SYNCML_DM_COMMAND_FAILED;
    472       else
    473       {
    474           pbStartingPosOfCmd += REPLACE_CMD_LENGTH_IN_ACL;
    475           pbStartingPosOfCmd = (UINT8*) DmStrchr((CPCHAR)pbStartingPosOfCmd, SYNCML_DM_AMPERSAND);
    476           if ( !pbStartingPosOfCmd )
    477             break;
    478           pbStartingPosOfCmd++;
    479       }
    480     }
    481     else
    482     if(pbStartingPosOfCmd[0] == SYNCML_DM_ASCII_CAPITAL_G)
    483     {
    484       if(DmStrcmp((CPCHAR)&pbStartingPosOfCmd[1], SYNCML_DM_ET))
    485           wReturnCode = SYNCML_DM_COMMAND_FAILED;
    486       else
    487       {
    488           pbStartingPosOfCmd += GET_CMD_LENGTH_IN_ACL;
    489           pbStartingPosOfCmd = (UINT8*) DmStrchr((CPCHAR)pbStartingPosOfCmd, SYNCML_DM_AMPERSAND);
    490           if ( !pbStartingPosOfCmd )
    491             break;
    492           pbStartingPosOfCmd++;
    493       }
    494     }
    495     else
    496     if(pbStartingPosOfCmd[0] == SYNCML_DM_ASCII_CAPITAL_A)
    497     {
    498       if(DmStrcmp((CPCHAR)&pbStartingPosOfCmd[1], SYNCML_DM_DD))
    499           wReturnCode = SYNCML_DM_COMMAND_FAILED;
    500       else
    501       {
    502           pbStartingPosOfCmd += ADD_CMD_LENGTH_IN_ACL;
    503           pbStartingPosOfCmd = (UINT8*) DmStrchr((CPCHAR)pbStartingPosOfCmd, SYNCML_DM_AMPERSAND);
    504           if ( !pbStartingPosOfCmd )
    505             break;
    506           pbStartingPosOfCmd++;
    507       }
    508     }
    509     else
    510     if(pbStartingPosOfCmd[0] == SYNCML_DM_ASCII_CAPITAL_D)
    511     {
    512         if(DmStrcmp((CPCHAR)&pbStartingPosOfCmd[1], SYNCML_DM_ELETE))
    513             wReturnCode = SYNCML_DM_COMMAND_FAILED;
    514         else
    515         {
    516             pbStartingPosOfCmd += DELETE_CMD_LENGTH_IN_ACL;
    517             pbStartingPosOfCmd = (UINT8*) DmStrchr((CPCHAR)pbStartingPosOfCmd, SYNCML_DM_AMPERSAND);
    518             if ( !pbStartingPosOfCmd )
    519                 break;
    520             pbStartingPosOfCmd++;
    521         }
    522     }
    523     else
    524     if(pbStartingPosOfCmd[0] == SYNCML_DM_ASCII_CAPITAL_E)
    525     {
    526       if(DmStrcmp((CPCHAR)&pbStartingPosOfCmd[1], SYNCML_DM_XEC))
    527           wReturnCode = SYNCML_DM_COMMAND_FAILED;
    528       else
    529       {
    530           pbStartingPosOfCmd += EXEC_CMD_LENGTH_IN_ACL;
    531           pbStartingPosOfCmd = (UINT8*) DmStrchr((CPCHAR)pbStartingPosOfCmd, SYNCML_DM_AMPERSAND);
    532           if ( !pbStartingPosOfCmd )
    533             break;
    534           pbStartingPosOfCmd++;
    535       }
    536     }
    537     else
    538     {
    539         wReturnCode = SYNCML_DM_COMMAND_FAILED;
    540     }
    541 
    542     pbACL = pbStartingPosOfCmd;
    543   }
    544 
    545   DmFreeMem(pNew);
    546   return wReturnCode;
    547 }
    548 
    549 
    550 
    551 //------------------------------------------------------------------------
    552 //
    553 // FUNCTION        : FindNodeInNextSiblingsList
    554 //
    555 // DESCRIPTION     : This function will search for the URI Segment in
    556 //                   the siblings list. If the node was found then it
    557 //                   returns the DMNode pointer otherwise it returns NULL.
    558 //
    559 //
    560 // ARGUMENTS PASSED: const DMNode *psFindNode
    561 //                      - Starting position of the siblings linked list.
    562 //                   const UINT8 *pbURISegment
    563 //                      - Contains the URI segment.
    564 // RETURN VALUE    : DMNode*
    565 //                      - It returns DMNode pointer if the node was found.
    566 //                      - NULL if the node was NOT found.
    567 //
    568 // PRE-CONDITIONS  : pbURISegment SHOULD NOT BE NULL.
    569 // POST-CONDITIONS :
    570 // IMPORTANT NOTES :
    571 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
    572 //------------------------------------------------------------------------
    573 DMNode* DMTree::FindNodeInNextSiblingsList(DMNode *psFindNode,
    574                                            CPCHAR pbURISegment) const
    575 {
    576   DMNode *psCurNode = psFindNode;
    577 
    578   while(psCurNode != NULL)
    579   {
    580     if(DmStrcmp(psCurNode->abNodeName, pbURISegment) == 0)
    581       return (psCurNode);
    582 
    583     psCurNode = psCurNode->pcNextSibling;
    584   }
    585 
    586   return (NULL);
    587 }
    588 
    589 //------------------------------------------------------------------------
    590 //
    591 // FUNCTION        : InsertNodeIntoNextSiblingsList
    592 //
    593 // DESCRIPTION     : This function will insert the node into the siblings
    594 //                   list and before inserting the node it checks if the
    595 //                   node already existed or NOT. if the node already
    596 //                   existed then it will add the node into the siblings
    597 //                   list.
    598 //
    599 //
    600 // ARGUMENTS PASSED: DMNode *psNextSiblingStartNode
    601 //                      - Starting position of the siblings linked list.
    602 //                   DMNode *psInsertNode
    603 //                      - Inserting node pointer.
    604 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    605 //                      - It returns SYNCML_DM_SUCCESS if the functions inserts
    606 //                        the node successfully into the siblings list.
    607 //                      - It returns SYNCML_DM_TARGET_ALREADY_EXISTS the
    608 //                        node already existed in the siblings list.
    609 //
    610 // PRE-CONDITIONS  : Input parameters SHOULD NOT BE NULL.
    611 // POST-CONDITIONS :
    612 // IMPORTANT NOTES :
    613 // REQUIREMENT #   : ESR-DMTNM00xx-m in SYNCML-DM-ENGINE-FSRS-02101010
    614 //------------------------------------------------------------------------
    615 SYNCML_DM_RET_STATUS_T DMTree::InsertNodeIntoNextSiblingsList(
    616                                DMNode *psNextSiblingStartNode,
    617                                DMNode *psInsertNode)
    618 {
    619   XPL_LOG_DM_TMN_Debug(("Entered DMTree::InsertNodeIntoNextSiblingsList \n"));
    620   while(psNextSiblingStartNode->pcNextSibling != NULL)
    621   {
    622     if(DmStrcmp((CPCHAR)psNextSiblingStartNode->abNodeName,
    623               (CPCHAR)psInsertNode->abNodeName) == 0)
    624     {
    625       XPL_LOG_DM_TMN_Debug(("Node Already exists in the Tree \n"));
    626       return (SYNCML_DM_TARGET_ALREADY_EXISTS);
    627     }
    628 
    629     psNextSiblingStartNode = psNextSiblingStartNode->pcNextSibling;
    630   }
    631 
    632   if(DmStrcmp((CPCHAR)psNextSiblingStartNode->abNodeName,
    633             (CPCHAR)psInsertNode->abNodeName) == 0)
    634   {
    635     XPL_LOG_DM_TMN_Debug(("Node Already exists in the Tree \n"));
    636     return (SYNCML_DM_TARGET_ALREADY_EXISTS);
    637   }
    638 
    639   psInsertNode->pcParentOfNode = psNextSiblingStartNode->pcParentOfNode;
    640   psNextSiblingStartNode->pcNextSibling = psInsertNode;
    641   return (SYNCML_DM_SUCCESS);
    642 }
    643 
    644 //------------------------------------------------------------------------
    645 //
    646 // FUNCTION        : IsValidSegment
    647 //
    648 // DESCRIPTION     : This function checks if the URI segment is valid.
    649 //
    650 //
    651 // ARGUMENTS PASSED: UINT8 *pbSegment
    652 //                      - Pointer to the URI segment.
    653 //                   UINT8 bSegmentLength
    654 //                      - Length of the pbSegment.
    655 // RETURN VALUE    : BOOLEAN
    656 //                      - It returns TRUE if the URI segment is valid
    657 //                        otherwise it returns FALSE.
    658 // PRE-CONDITIONS  :
    659 // POST-CONDITIONS :
    660 // IMPORTANT NOTES :
    661 // REQUIREMENT #   :
    662 //------------------------------------------------------------------------
    663 BOOLEAN DMTree::IsValidSegment(CPCHAR pbSegment, UINT8 bSegmentLength)
    664 {
    665   if((pbSegment == NULL) ||
    666      (bSegmentLength == 0) ||
    667      (bSegmentLength > GetMaxPathSegmentLength()) )
    668     return (FALSE);
    669 
    670   while (bSegmentLength != 0)
    671   {
    672     bSegmentLength--;  //decrementing to indicate character processed
    673 
    674     if ((pbSegment[0] == '/') || (pbSegment[0] == '?') || (pbSegment[0] == 0))
    675       return FALSE;
    676 
    677     pbSegment++;
    678   }
    679 
    680   return TRUE;
    681 }
    682 
    683 //------------------------------------------------------------------------
    684 //
    685 // FUNCTION        : DeleteNode
    686 //
    687 // DESCRIPTION     : This function performs ACL check for children nodes of deleting node
    688 //                   This function will use DFS algorithm to traverse the
    689 //                   tree.
    690 //
    691 // ARGUMENTS PASSED:
    692 //                   psDeletingNode - Pointer to the deleting node.
    693 //                   pbURI -  Pointer the deleting node URI.
    694 //
    695 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    696 //
    697 // PRE-CONDITIONS  : psDeletingNode pointer SHOULD NEVER be NULL.
    698 // POST-CONDITIONS :
    699 // IMPORTANT NOTES :
    700 // REQUIREMENT #     :
    701 //------------------------------------------------------------------------
    702 
    703 SYNCML_DM_RET_STATUS_T
    704 DMTree::CheckDeleteForNode(DMNode *psDeletingNode,
    705                                         CPCHAR pbURI)
    706 {
    707 
    708     XPL_LOG_DM_TMN_Debug(("Entered DMTree::CheckDeleteForNode \n"));
    709 
    710     if( !psDeletingNode )
    711         return SYNCML_DM_FAIL;
    712 
    713     DMBuffer aRelativeBuffer;
    714     DMBuffer aAbsoluteBuffer;
    715 
    716     char * abRelativeURI = (char*)aRelativeBuffer.allocate(GetMaxTotalPathLength());
    717     if(abRelativeURI == NULL)
    718         return SYNCML_DM_DEVICE_FULL;
    719 
    720     char * abAbsoluteURI = (char*)aAbsoluteBuffer.allocate(GetMaxTotalPathLength());
    721     if(abAbsoluteURI == NULL)
    722         return SYNCML_DM_DEVICE_FULL;
    723 
    724     UINT16 wRelativeURILength = 0;
    725     BOOLEAN bFlag = TRUE;
    726     DMNode *psTemp = NULL;
    727     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    728 
    729     wRelativeURILength = (UINT16)DmSprintf(abRelativeURI, "%s",pbURI);
    730 
    731     psTemp = psDeletingNode;
    732     psTemp = psTemp->pcFirstChild;
    733 
    734     if( !psTemp )
    735         return dm_stat;
    736 
    737     while(psTemp != psDeletingNode)
    738     {
    739         if(bFlag == TRUE)
    740         {
    741             if(psTemp->pcFirstChild)
    742             {
    743                 wRelativeURILength = (UINT16)DmSprintf(abRelativeURI,"%s/%s",abRelativeURI,(CPCHAR)psTemp->abNodeName);
    744                 psTemp = psTemp->pcFirstChild;
    745             }
    746             else
    747                 bFlag = FALSE;
    748         }
    749         else
    750         {
    751             DmSprintf(abAbsoluteURI, "%s/%s",abRelativeURI,(CPCHAR)psTemp->abNodeName);
    752 
    753             if(psTemp->pcNextSibling)
    754             {
    755                 psTemp = psTemp->pcNextSibling;
    756                 bFlag = TRUE;
    757             }
    758             else
    759             {
    760                 while((abRelativeURI[wRelativeURILength] != SYNCML_DM_FORWARD_SLASH) &&
    761                          (wRelativeURILength > 0))
    762                 {
    763                     --wRelativeURILength;
    764                 }
    765                 abRelativeURI[wRelativeURILength] = '\0';
    766                 psTemp = psTemp->pcParentOfNode;
    767             }
    768 
    769             dm_stat = IsValidServer((CPCHAR)abAbsoluteURI,
    770                                                SYNCML_DM_DELETE_ACCESS_TYPE,
    771                                                SYNCML_DM_REQUEST_TYPE_SERVER,
    772                                                FALSE,
    773                                                FALSE);
    774 
    775             if ( dm_stat != SYNCML_DM_SUCCESS)
    776                 break;
    777 
    778        }
    779     }
    780 
    781     return dm_stat;
    782 
    783 }
    784 
    785 
    786 //------------------------------------------------------------------------
    787 //
    788 // FUNCTION        : DeleteNode
    789 //
    790 // DESCRIPTION     : This function will perform deleting of subtree
    791 //
    792 // ARGUMENTS PASSED:
    793 //                   psDeletingNode - Pointer to the deleting node.
    794 //                   pbURI - Pointer the deleting node URI.
    795 //                   aDeletedChildren - Vector of deleted children nodes
    796 //
    797 // RETURN VALUE    : SYNCML_DM_RET_STATUS_T
    798 //
    799 // PRE-CONDITIONS  : psDeletingNode pointer SHOULD NEVER be NULL.
    800 // POST-CONDITIONS :
    801 // IMPORTANT NOTES :
    802 // REQUIREMENT #   :
    803 //------------------------------------------------------------------------
    804 
    805 SYNCML_DM_RET_STATUS_T
    806 DMTree::DeleteNode(DMNode *psDeletingNode,
    807                              CPCHAR pbURI,
    808                              DMStringVector & aDeletedChildren)
    809 {
    810     XPL_LOG_DM_TMN_Debug(("Entered DMTree::DeleteNode \n"));
    811 
    812     if( !psDeletingNode )
    813         return SYNCML_DM_FAIL;
    814 
    815     DMBuffer aRelativeBuffer;
    816     DMBuffer aAbsoluteBuffer;
    817 
    818     char * abRelativeURI = (char*)aRelativeBuffer.allocate(GetMaxTotalPathLength());
    819     if(abRelativeURI == NULL)
    820         return SYNCML_DM_DEVICE_FULL;
    821 
    822     char * abAbsoluteURI = (char*)aAbsoluteBuffer.allocate(GetMaxTotalPathLength());
    823     if(abAbsoluteURI == NULL)
    824         return SYNCML_DM_DEVICE_FULL;
    825 
    826     UINT16 wRelativeURILength = 0;
    827     BOOLEAN bFlag = TRUE;
    828     // TRUE  1st exploration of the node, continue with 1st subnode
    829     // FALSE node completely explored, should contine with sibling
    830 
    831     DMNode *psTemp = NULL;
    832     DMNode *psRemovingNode = NULL;
    833     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    834 
    835     wRelativeURILength = (UINT16)DmSprintf(abRelativeURI, "%s",pbURI);
    836     psTemp = psDeletingNode;
    837     psTemp = psTemp->pcFirstChild;
    838 
    839     // When the processing of all the nodes is over then psTemp will
    840     // become NULL.
    841     if (psTemp)
    842     {
    843         // The processing of subtree is over when psTemp equals to
    844         // psDeletingNode
    845         while(psTemp != psDeletingNode)
    846         {
    847             // exploration of the node
    848 
    849             if(bFlag == TRUE)
    850             {
    851                 if(psTemp->pcFirstChild)
    852                 {
    853                     // In case if the bOperation is SYNCML_TNM_DELETE_NODE then we
    854                     // have to build URI. This will become relative URI
    855                     // because there are childs for current node. For the
    856                     // Childs it will become the relative URI.
    857 
    858                     wRelativeURILength = (UINT16)DmSprintf(abRelativeURI,"%s/%s",abRelativeURI,(CPCHAR)psTemp->abNodeName);
    859 
    860                     // Here we are doing depth first search
    861                     psTemp = psTemp->pcFirstChild;
    862                 }   // End of if (psTemp->pcFirstChild)
    863                 else
    864                 {
    865                     // 1st exploration of current node is finished
    866                     // go to 2nd exploration of the current node
    867                     bFlag = FALSE;
    868                 }
    869             }   // End of if (bFlag == TRUE)
    870             else
    871             {
    872                 // If it has come to this condition means psTemp does NOT
    873                 // have any childs. So we can process this node and
    874                 // move to the next sibling if there are any otherwise
    875                 // we can move the pointer to the Parent.
    876 
    877                 DmSprintf(abAbsoluteURI, "%s/%s",abRelativeURI,(CPCHAR)psTemp->abNodeName);
    878 
    879                 //exploration of the node, should continue with sibling
    880                 if(psTemp->pcNextSibling)
    881                 {
    882                     psRemovingNode = psTemp;
    883                     psTemp = psTemp->pcNextSibling;
    884                     // goto 1st exploration of the sibling (now current)
    885                     bFlag = TRUE;
    886                 }
    887                 else
    888                 {
    889                     // exploration of the node, should continue if
    890                     // there is no sibling
    891 
    892                     // If there are no siblings we are moving to parent
    893                     // so we can remove the last node segment in the Relative
    894                     // URI because we have process psTemp and curent psTemp
    895                     // does NOT have any childs and we have to move the pointer
    896                     // to the parent because there could be some more siblings
    897                     // on the parent siblings list.
    898                     while((abRelativeURI[wRelativeURILength] != SYNCML_DM_FORWARD_SLASH) &&
    899                              (wRelativeURILength > 0))
    900                     {
    901                         --wRelativeURILength;
    902                     }
    903                     abRelativeURI[wRelativeURILength] = '\0';
    904 
    905                     psRemovingNode = psTemp;
    906                     psTemp = psTemp->pcParentOfNode;
    907                 }// End of else of if(psTemp->pcNextSibling)
    908 
    909                 dm_stat = m_oMDFObj.VerifyDeleteParameters(psRemovingNode,(CPCHAR)abAbsoluteURI);
    910                 if(dm_stat  != SYNCML_DM_SUCCESS)
    911                     return dm_stat;
    912 #ifdef LOB_SUPPORT
    913                 LogDeleteForESN(psRemovingNode);
    914 #endif
    915 
    916                 // In this case first we have to call plug-in.Delete
    917                 // if this plug-in.Delete return SYNCML_DM_SUCCESS then
    918                 // it will delete the node from the tree.
    919                 dm_stat = psRemovingNode->Delete(abAbsoluteURI);
    920 
    921                 if(dm_stat != SYNCML_DM_SUCCESS)
    922                     return dm_stat;
    923 
    924                 psRemovingNode->pcParentOfNode->pcFirstChild = psRemovingNode->pcNextSibling;
    925                 delete psRemovingNode;
    926                 psRemovingNode = NULL;
    927                 aDeletedChildren.push_back(DMString(abAbsoluteURI));
    928 
    929                 m_oACLObj.Delete(abAbsoluteURI);
    930         }// End of else of if (bFlag == TRUE)
    931       }// End of while (psTemp != psDeletingNode)
    932     }// End of if(psTemp)
    933 
    934     // Contains pointer to the parent of the deleting node.
    935     DMNode *psParentNode = NULL;
    936     // Contains previous node pointer to the directly referenced deleting node.
    937     DMNode *psPrevNode = NULL;
    938     // Contais pointer to the first child in the deleting node silings list.
    939     DMNode *psListNode = NULL;
    940 
    941     psParentNode = psDeletingNode->pcParentOfNode;
    942     psListNode = psParentNode->pcFirstChild;
    943 
    944     // This while stores the previous pointer to the deleting node.
    945     while(psListNode)
    946     {
    947         if(psListNode == psDeletingNode)
    948             break;
    949         psPrevNode = psListNode;
    950         psListNode = psListNode->pcNextSibling;
    951     }
    952 
    953     if(psListNode == psDeletingNode)
    954     {
    955         XPL_LOG_DM_TMN_Debug(("Deleting node: %s \n", pbURI));
    956         dm_stat = m_oMDFObj.VerifyDeleteParameters(psDeletingNode,(CPCHAR)pbURI);
    957         if(dm_stat != SYNCML_DM_SUCCESS)
    958             return dm_stat;
    959 
    960 #ifdef LOB_SUPPORT
    961         LogDeleteForESN(psDeletingNode);
    962 #endif
    963         dm_stat = psDeletingNode->Delete( pbURI );
    964 
    965         if (dm_stat != SYNCML_DM_SUCCESS)
    966             return dm_stat;
    967 
    968         if (psPrevNode != NULL)
    969         {
    970             // If previous node is not equals to NULL then we will
    971             // set the deleting node next pointer to the next node
    972             // pointer of previous node
    973             psPrevNode->pcNextSibling = psDeletingNode->pcNextSibling;
    974         }
    975         else
    976         {
    977             // If the previous node is NOT there mean then deleting
    978             // node is first child in the siblings list.
    979             psParentNode->pcFirstChild = psDeletingNode->pcNextSibling;
    980         }
    981         delete psDeletingNode;
    982         psDeletingNode = NULL;
    983     }
    984 
    985 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
    986     if (psParentNode != NULL)
    987     {
    988        // Set timestamp and version number for parent Node
    989        // Use parentURI's URI.
    990        psParentNode->wTStamp=XPL_CLK_GetClock();
    991        psParentNode->wVerNo ++;
    992     }
    993 #endif
    994 
    995     return dm_stat;
    996 }
    997 
    998 
    999 
   1000 //------------------------------------------------------------------------
   1001 //
   1002 // FUNCTION        : DeleteNodesFromTree
   1003 //
   1004 // DESCRIPTION     : This function will delete all the nodes in the tree.
   1005 //
   1006 //
   1007 // ARGUMENTS PASSED:
   1008 //
   1009 //
   1010 // RETURN VALUE    :
   1011 //
   1012 // PRE-CONDITIONS  :
   1013 // POST-CONDITIONS :
   1014 // IMPORTANT NOTES :
   1015 // REQUIREMENT #   :
   1016 //------------------------------------------------------------------------
   1017 void
   1018 DMTree::DeleteNodesFromTree(DMNode * psStartNode)
   1019 {
   1020 
   1021 
   1022   BOOLEAN oFlag = TRUE; // This variable is used to explore the child
   1023 
   1024   DMNode *psCurrent = psStartNode;
   1025 
   1026   XPL_LOG_DM_TMN_Debug(("Entered DMTree::DeleteNodesFromTree \n"));
   1027 
   1028   if (psStartNode != m_psRoot)
   1029   {
   1030       //detach the node.
   1031       DetachNodeFromTree(psStartNode);
   1032   }
   1033 
   1034   if (psCurrent != NULL)
   1035   {
   1036     psCurrent = psCurrent->pcFirstChild;
   1037     if (psCurrent)
   1038     {
   1039       while (psCurrent != psStartNode)
   1040       {
   1041         // exploration of the node
   1042         if (oFlag == TRUE)
   1043         {
   1044           if (psCurrent->pcFirstChild)
   1045           {
   1046             //Here we are doing depth first search
   1047             psCurrent = psCurrent->pcFirstChild;
   1048           }
   1049           else
   1050           {
   1051             // exploration of node is finished
   1052             // start the exploration of the next node
   1053             oFlag = FALSE;
   1054           }
   1055         }// End of if(oFlag == TRUE)
   1056         else
   1057         {
   1058           //exploration of the node, should continue with sibling
   1059           if (psCurrent->pcNextSibling)
   1060           {
   1061             DMNode* psTemp = psCurrent;
   1062             psCurrent = psCurrent->pcNextSibling;
   1063             delete psTemp;
   1064             psTemp = NULL;
   1065             // goto 1st exploration of the sibling (now current)
   1066             oFlag = TRUE;
   1067           }
   1068           else
   1069           {
   1070             // exploration of the node, should continue if
   1071             // there is no sibling
   1072             DMNode* psTemp = psCurrent;
   1073             psCurrent = psCurrent->pcParentOfNode;
   1074             delete psTemp;
   1075             psTemp = NULL;
   1076           }
   1077         }// End of else
   1078       }// End of while(psCurrent)
   1079 
   1080       //Now delete psStartNode
   1081       {
   1082          XPL_LOG_DM_TMN_Debug(("Delete root %s\n", (const char*)psStartNode->abNodeName));
   1083          delete psStartNode;
   1084          //Fix the node links for parent nodes etc.
   1085       }
   1086     }// End of if(psCurrent)
   1087     else
   1088     {
   1089       XPL_LOG_DM_TMN_Debug(("Delete root %s\n", (const char*)psStartNode->abNodeName));
   1090       delete psStartNode;
   1091       //Fix the node links for parent nodes etc.
   1092     }
   1093   }// End of if(psCurrent != NULL)
   1094 
   1095   if (psStartNode==m_psRoot)
   1096   {
   1097       m_psRoot = NULL;
   1098   }
   1099 }
   1100 
   1101 SYNCML_DM_RET_STATUS_T
   1102 DMTree::CheckDeleteForPluginNodes(SYNCML_DM_REQUEST_TYPE_T eRequestType,
   1103                                                                    CPCHAR pbURI,
   1104                                                                    DMNode *psProxyNode,
   1105                                                                    DMStringVector & aChildren)
   1106 {
   1107     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
   1108 
   1109     if (!psProxyNode->isPlugin())
   1110         return SYNCML_DM_PERMISSION_FAILED;
   1111 
   1112     PDmtAPIPluginTree tree;
   1113     dm_stat = ((DMPluginRootNode*)psProxyNode)->GetTree(tree);
   1114 
   1115     if ( dm_stat != SYNCML_DM_SUCCESS )
   1116         return dm_stat;
   1117 
   1118     CPCHAR pPluginURI= ((DMPluginRootNode*)psProxyNode)->GetPluginURI(pbURI);
   1119 
   1120    // Proxy root node should not be deleted
   1121     if(DmStrlen(pPluginURI) == 0)
   1122         return SYNCML_DM_PERMISSION_FAILED;
   1123 
   1124     PDmtNode ptrNode;
   1125 
   1126     dm_stat = tree->GetNode(pPluginURI, ptrNode);
   1127     if (dm_stat == SYNCML_DM_SUCCESS)
   1128            dm_stat = CheckDeleteForPluginNode(eRequestType,pbURI, ptrNode, aChildren, TRUE);
   1129 
   1130     return dm_stat;
   1131 }
   1132 
   1133 SYNCML_DM_RET_STATUS_T
   1134 DMTree::CheckDeleteForPluginNode(SYNCML_DM_REQUEST_TYPE_T eRequestType,
   1135                                                  CPCHAR pbURI,
   1136                                                  PDmtNode ptrNode,
   1137                                                  DMStringVector & aChildren,
   1138                                                  BOOLEAN bIsParent)
   1139 {
   1140     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
   1141     if ( !bIsParent )
   1142         aChildren.push_back(DMString(pbURI));
   1143     if (ptrNode->IsLeaf())
   1144     {
   1145          dm_stat = IsValidServer( pbURI,
   1146                                            SYNCML_DM_DELETE_ACCESS_TYPE,
   1147                                            eRequestType,
   1148                                            FALSE,
   1149                                            TRUE);
   1150     }
   1151     else
   1152     {
   1153         DMVector<PDmtNode> vecNodes;
   1154 
   1155         dm_stat = ptrNode->GetChildNodes(vecNodes);
   1156         if ( dm_stat == SYNCML_DM_SUCCESS )
   1157         {
   1158             for (INT32 i = 0; i < vecNodes.size(); i++)
   1159             {
   1160                 DMString nodeName;
   1161 
   1162                 dm_stat = vecNodes[i]->GetNodeName(nodeName);
   1163                 if( dm_stat != SYNCML_DM_SUCCESS )
   1164                     return dm_stat;
   1165 
   1166                 DMString uri = pbURI;
   1167                 uri += "/";
   1168                 uri += nodeName;
   1169                 dm_stat = CheckDeleteForPluginNode(eRequestType,uri.c_str(),vecNodes[i],aChildren,FALSE);
   1170                 if( dm_stat != SYNCML_DM_SUCCESS )
   1171                     return dm_stat;
   1172             }
   1173         }
   1174     }
   1175     return dm_stat;
   1176 }
   1177 
   1178 BOOLEAN DMTree::GetPluginURI(CPCHAR szURI, DMString& strURI, DMString& strShortURI ) const
   1179 {
   1180   if ( !szURI )
   1181     return FALSE;
   1182 
   1183   if ( szURI[0] != '.' )
   1184     strURI = "./";
   1185   else
   1186     strURI = NULL;
   1187 
   1188   strURI += szURI;
   1189 
   1190   const char* szShortURI = strURI;
   1191   const char* szQuestionPos = DmStrrchr( szShortURI, SYNCML_DM_FORWARD_SLASH);
   1192 
   1193   if( !szQuestionPos )
   1194     szQuestionPos = DmStrrchr( szShortURI, SYNCML_DM_QUESTION_MARK);
   1195   else
   1196     szQuestionPos = DmStrrchr( szQuestionPos, SYNCML_DM_QUESTION_MARK);
   1197 
   1198   if( szQuestionPos )
   1199     strShortURI.assign( szShortURI, szQuestionPos - szShortURI );
   1200   else
   1201     strShortURI = strURI;
   1202 
   1203   return TRUE;
   1204 }
   1205 
   1206 void DMTree::UnloadArchive(DMNode * psStartNode )
   1207 {
   1208   ResetOPICache();
   1209 #ifdef LOB_SUPPORT
   1210   ResetESNCache();
   1211 #endif
   1212   // unload archive performed in 2 steps:
   1213   // 1. find all child archives and converting path to them to "skeleton"
   1214   // 2. unload remaining stuff.
   1215   DMNode* pNode = psStartNode->pcFirstChild;
   1216 
   1217   if ( !pNode ){
   1218     DeleteNodesFromTree( psStartNode );
   1219     return;
   1220   }
   1221 
   1222   // traverse sub-tree
   1223   while ( pNode != psStartNode ){
   1224     BOOLEAN bSkipChildren = FALSE;
   1225     if ( pNode->pArchive ) {
   1226       bSkipChildren = TRUE;
   1227       pNode->ConvertPathToSkeleton( psStartNode );
   1228     }
   1229 
   1230     if ( !bSkipChildren && pNode->pcFirstChild )
   1231       pNode = pNode->pcFirstChild;
   1232     else if ( pNode->pcNextSibling )
   1233       pNode = pNode->pcNextSibling;
   1234     else {
   1235       while ( pNode != psStartNode ) {
   1236         pNode = pNode->pcParentOfNode;
   1237 
   1238         if ( pNode != psStartNode && pNode->pcNextSibling ){
   1239           pNode = pNode->pcNextSibling;
   1240           break;
   1241         }
   1242       }
   1243     }
   1244   }
   1245 
   1246 
   1247   // traverse sub-tree again and free all "non-skeleton" nodes:
   1248   pNode = psStartNode->pcFirstChild;
   1249 
   1250   while ( pNode != psStartNode ){
   1251     BOOLEAN bSkipChildren = FALSE;
   1252     BOOLEAN bDelete = FALSE;
   1253     if ( pNode->pArchive ) {
   1254       bSkipChildren = TRUE;
   1255     } else if ( !pNode->IsSkeletonNode() )
   1256       bDelete = TRUE;
   1257 
   1258     DMNode *pNodeDelete = pNode;
   1259 
   1260     if ( !bSkipChildren && !bDelete && pNode->pcFirstChild )
   1261       pNode = pNode->pcFirstChild;
   1262     else if ( pNode->pcNextSibling )
   1263       pNode = pNode->pcNextSibling;
   1264     else{
   1265       while ( pNode != psStartNode ) {
   1266         pNode = pNode->pcParentOfNode;
   1267 
   1268         if ( pNode != psStartNode && pNode->pcNextSibling ){
   1269           pNode = pNode->pcNextSibling;
   1270           break;
   1271         }
   1272       }
   1273     }
   1274 
   1275     if ( bDelete ) {
   1276       DeleteNodesFromTree( pNodeDelete );
   1277     }
   1278   }
   1279 
   1280   psStartNode->m_nFlags |= DMNode::enum_NodeSkeleton;
   1281 }
   1282 
   1283 BOOLEAN DMTree::LoadSkeletonParentArchive( DMNode* pNode )
   1284 {
   1285   while ( pNode ) {
   1286     if ( pNode->pArchive ) {
   1287       if ( pNode->IsSkeletonNode() )
   1288         return ( (pNode->pArchive->deserialize(this) == SYNCML_DM_SUCCESS) ? TRUE : FALSE );
   1289 
   1290       return FALSE; // parent node already loaded
   1291     }
   1292     pNode = pNode->pcParentOfNode;
   1293   }
   1294   return FALSE;
   1295 }
   1296 
   1297 
   1298 /*
   1299 This function returns fantom node for OPI if confirmed by MDF
   1300 */
   1301 DMNode* DMTree::GetOPINode( CPCHAR szURI )
   1302 {
   1303   CPCHAR szID = NULL;
   1304   SYNCML_DM_ACCESS_TYPE_T  wAccessType = 0;
   1305   SYNCML_DM_FORMAT_T nNodeFormat = 0;
   1306 
   1307   if ( !m_oMDFObj.VerifyOPINode(szURI, szID, wAccessType, nNodeFormat) )
   1308     return NULL;
   1309 
   1310   if ( szID )
   1311     m_oOPICacheData.metaNodeID = DmAtol(szID);
   1312 
   1313   if ( m_pOPINode && m_pOPINode->GetPlugin() != m_ptrCacheOPI ){
   1314     delete m_pOPINode;
   1315     m_pOPINode = NULL;
   1316   }
   1317 
   1318   if ( !m_pOPINode )
   1319     m_pOPINode = new DMOverlayDataPluginNode( m_ptrCacheOPI );
   1320 
   1321   if ( m_pOPINode )
   1322     m_pOPINode->SetNodeAttributes( wAccessType, nNodeFormat );
   1323 
   1324   return m_pOPINode;
   1325 }
   1326 
   1327 
   1328 void DMTree::ResetOPICache()
   1329 {
   1330   delete m_pOPINode;
   1331   m_pOPINode = NULL;
   1332   m_ptrCacheOPI = NULL;
   1333 }
   1334 
   1335 SYNCML_DM_RET_STATUS_T  DMTree::OnOPiDelete( CPCHAR szURI )
   1336 {
   1337   // in case the overlay plugin library is not loaded
   1338   // to account for edge case where the plugin ini file does not have entry or has
   1339   // incorrect entry for the overlay plugin library
   1340   if (m_ptrCacheOPI == NULL) {
   1341     return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1342   }
   1343 
   1344   // notify opi about "data" node to be deleted
   1345   PDmtAPIPluginTree ptrPluginTree;
   1346   CPCHAR szPath = m_ptrCacheOPI->GetPath();
   1347 
   1348   SYNCML_DM_RET_STATUS_T dm_stat = m_ptrCacheOPI->GetTree(szPath, ptrPluginTree);
   1349 
   1350   if ( dm_stat != SYNCML_DM_SUCCESS )
   1351     return dm_stat;
   1352 
   1353   if ( ptrPluginTree != NULL )
   1354   {
   1355     dm_stat = ptrPluginTree->OnDelete( szURI );
   1356 
   1357     return dm_stat;
   1358   }
   1359 
   1360   return SYNCML_DM_FAIL; // unlikely case, since if tree is null, plug-in should return an error
   1361 }
   1362 
   1363 SYNCML_DM_RET_STATUS_T  DMTree::OnOPiAdd( CPCHAR szURI, DmtOverlayPluginData& data )
   1364 {
   1365 
   1366   // in case the overlay plugin library is not loaded
   1367   // to account for edge case where the plugin ini file does not have entry or has
   1368   // incorrect entry for the overlay plugin library
   1369   if (m_ptrCacheOPI == NULL) {
   1370     return SYNCML_DM_FEATURE_NOT_SUPPORTED;
   1371   }
   1372 
   1373   // notify opi about "data" node to be deleted
   1374   PDmtAPIPluginTree ptrPluginTree;
   1375   CPCHAR szPath = m_ptrCacheOPI->GetPath();
   1376 
   1377   SYNCML_DM_RET_STATUS_T dm_stat = m_ptrCacheOPI->GetTree(szPath, ptrPluginTree);
   1378 
   1379   if ( dm_stat != SYNCML_DM_SUCCESS )
   1380     return dm_stat;
   1381 
   1382   if ( ptrPluginTree != NULL )
   1383   {
   1384     dm_stat = ptrPluginTree->OnAdd( szURI, data );
   1385 
   1386     return dm_stat;
   1387   }
   1388 
   1389   return SYNCML_DM_FAIL; // unlikely case, since if tree is null, plug-in should return an error
   1390 }
   1391 
   1392 
   1393 void DMTree::CheckOpiSync( DMNode* pNode, char* szURI, const char* szLastSegment )
   1394 {
   1395   if ( pNode->opiSyncMayNeeded() )
   1396   {
   1397     // sync state unknown - mdf data required
   1398     // restore URI
   1399     char* s = szURI;
   1400 
   1401     while ( s < szLastSegment )
   1402     {
   1403       if ( *s == 0 )
   1404         *s = SYNCML_DM_FORWARD_SLASH;
   1405       s++;
   1406     }
   1407 
   1408     if ( !m_oMDFObj.IsOPiDataParent( szURI ) )
   1409     {
   1410       pNode->addFlags( DMNode::enum_NodeOPISyncNotNeeded);
   1411       return;
   1412     }
   1413     pNode->addFlags( DMNode::enum_NodeOPISyncNeeded);
   1414   }
   1415 
   1416   if ( pNode->opiInSync() )
   1417     return; // up-to-date
   1418 
   1419   // perform sync
   1420   OpiSync( pNode, szURI );
   1421 
   1422   pNode->addFlags( DMNode::enum_NodeOPISyncUptodate );
   1423 }
   1424 
   1425 void DMTree::OpiSync( DMNode* pNode, const char* szURI )
   1426 {
   1427   // in case the overlay plugin library is not loaded
   1428   // to account for edge case where the plugin ini file does not have entry or has
   1429   // incorrect entry for the overlay plugin library
   1430   if (m_ptrCacheOPI == NULL) {
   1431     return;
   1432   }
   1433 
   1434   // get tree
   1435   PDmtAPIPluginTree ptrPluginTree;
   1436   CPCHAR szPath = m_ptrCacheOPI->GetPath();
   1437 
   1438   SYNCML_DM_RET_STATUS_T dm_stat = m_ptrCacheOPI->GetTree(szPath, ptrPluginTree);
   1439 
   1440   if ( dm_stat != SYNCML_DM_SUCCESS || ptrPluginTree == NULL )
   1441     return ;
   1442 
   1443   // fill in sync data
   1444   DMVector<DmtOverlayPluginSyncData> data;
   1445 
   1446   DMNode* pChild = pNode->pcFirstChild;
   1447 
   1448   while ( pChild )
   1449   {
   1450     data.push_back(DmtOverlayPluginSyncData());
   1451 
   1452     DmtOverlayPluginSyncData& item = data[data.size()-1];
   1453 
   1454     item.m_nStatus = DmtOverlayPluginSyncData::enum_StatusUnchanged;
   1455     item.m_strNodeName = pChild->abNodeName;
   1456 
   1457     if ( pChild->getOverlayPIData() )
   1458       item.m_oData = *pChild->getOverlayPIData();
   1459 
   1460     pChild = pChild->pcNextSibling;
   1461   }
   1462 
   1463   dm_stat = ptrPluginTree->Synchronize( szURI, data );
   1464 
   1465   if ( dm_stat != SYNCML_DM_SUCCESS )
   1466     return;
   1467 
   1468   for ( int i = 0; i < data.size(); i++ )
   1469   {
   1470     if ( data[i].m_nStatus == DmtOverlayPluginSyncData::enum_StatusUnchanged )
   1471       continue;
   1472 
   1473     if ( data[i].m_nStatus == DmtOverlayPluginSyncData::enum_StatusAdded )
   1474     {
   1475       // create a node
   1476       DMNode* pNewNode = new DMOverlayPINode( m_ptrCacheOPI, data[i].m_strNodeName,
   1477           data[i].m_oData );
   1478 
   1479       if ( !pNewNode )
   1480         return; // sync failed
   1481 
   1482       pNewNode->pcParentOfNode = pNode;
   1483 
   1484       if(pNode->pcFirstChild)
   1485       {
   1486         // if the current addind node is NOT the first child of the
   1487         // parent then insert the node in the siblings list.
   1488         InsertNodeIntoNextSiblingsList(pNode->pcFirstChild,pNewNode);
   1489       }
   1490       else
   1491       {
   1492           // if the current adding node is the first child of the
   1493           // parent then assign adding node pointer tp parent first
   1494           // child pointer.
   1495         pNode->pcFirstChild = pNewNode;;
   1496       }
   1497     }
   1498 
   1499     if ( data[i].m_nStatus == DmtOverlayPluginSyncData::enum_StatusDeleted )
   1500     { // find and delete the node
   1501       pChild = pNode->pcFirstChild;
   1502 
   1503       while ( pChild )
   1504       {
   1505         if ( pChild->abNodeName == data[i].m_strNodeName )
   1506         {
   1507           DeleteNodesFromTree( pChild );
   1508           break;
   1509         }
   1510 
   1511         pChild = pChild->pcNextSibling;
   1512       }
   1513 
   1514     }
   1515   }
   1516 }
   1517 #ifdef LOB_SUPPORT
   1518 void  DMTree::ResetESNCache()
   1519 {
   1520     m_pESN = NULL;
   1521     m_strESNPath= NULL;
   1522 }
   1523 void  DMTree::SetESNCache( CPCHAR szURI , DMNode* pESN)
   1524 {
   1525     m_strESNPath = szURI;
   1526     m_pESN = pESN;
   1527 }
   1528 DMNode*  DMTree::GetESN( CPCHAR szURI )
   1529 {
   1530     if(m_pESN != NULL)
   1531     {
   1532         if (DmStrcmp((CPCHAR)m_strESNPath.c_str(), szURI) == 0 )
   1533             return     m_pESN;
   1534     }
   1535     return NULL;
   1536 }
   1537 void  DMTree::RemoveESNCache(CPCHAR szURI)
   1538 {
   1539     if(m_pESN != NULL)
   1540     {    if (DmStrncmp((CPCHAR)m_strESNPath.c_str(), szURI, DmStrlen(szURI)) == 0 )
   1541             ResetESNCache();
   1542     }
   1543 }
   1544 //------------------------------------------------------------------------
   1545 //
   1546 // FUNCTION        : LogDeleteForESN
   1547 //
   1548 // DESCRIPTION     : This function logs delete command for an ESN.
   1549 //
   1550 //
   1551 // ARGUMENTS PASSED: DMNode - node to be removed
   1552 
   1553 //
   1554 // RETURN VALUE    : error code if failed, "DM_SUCCESS" otherwise
   1555 // PRE-CONDITIONS  :
   1556 // POST-CONDITIONS :
   1557 // IMPORTANT NOTES :
   1558 //------------------------------------------------------------------------
   1559 void  DMTree::LogDeleteForESN(DMNode *psDeletingNode)
   1560 {
   1561   BOOLEAN  IsESN = psDeletingNode->IsESN();
   1562    if(IsESN)
   1563    {
   1564         DMDefaultESN *tempESN = reinterpret_cast< DMDefaultESN *>(psDeletingNode);
   1565         SyncML_DM_Archive * pArchive=GetArchive(psDeletingNode);
   1566         if(pArchive != NULL)
   1567         {    SyncML_Commit_Log *commitLog = pArchive->GetCommitLogHandler();
   1568             if(commitLog != NULL)
   1569             {
   1570                   DMString targetFileName  = tempESN->GetOriginalInternalFileName();
   1571                    if(targetFileName != NULL)
   1572                     commitLog->logCommand(SYNCML_DM_DELETE, NULL, targetFileName.c_str());
   1573             }
   1574         }
   1575    }
   1576 }
   1577 #endif
   1578 
   1579 //------------------------------------------------------------------------
   1580 //
   1581 // FUNCTION        : SetOPINodeData
   1582 //
   1583 // DESCRIPTION     : This function sets Overlay plug-in data for multi-node
   1584 //
   1585 //
   1586 // ARGUMENTS PASSED: szURI - node uri
   1587 //            oData - new data
   1588 //
   1589 // RETURN VALUE    : error code if failed, "DM_SUCCESS" otherwise
   1590 // PRE-CONDITIONS  :
   1591 // POST-CONDITIONS :
   1592 // IMPORTANT NOTES :
   1593 //------------------------------------------------------------------------
   1594 SYNCML_DM_RET_STATUS_T DMTree::SetOPINodeData( CPCHAR szURI, const DmtOverlayPluginData& oData )
   1595 {
   1596   DMNode* pNode = FindNodeByURI(szURI);
   1597 
   1598   if ( !pNode || !pNode->IsOverlayPIData() || !pNode->getOverlayPIData() )
   1599     return SYNCML_DM_INVALID_PARAMETER;
   1600 
   1601   *pNode->getOverlayPIData() = oData;
   1602   return SYNCML_DM_SUCCESS;
   1603 }
   1604 
   1605 
   1606 //------------------------------------------------------------------------
   1607 // FUNCTION        : CheckForIndirectUpdates
   1608 // DESCRIPTION     : This function checks all child/depend nodes
   1609 //                   and for all of them ponting to current uri
   1610 //                   issues "indirect" update
   1611 // ARGUMENTS PASSED: szURI - currently updated uri
   1612 //                   asChildDepend - list of "child/depend" constraints for
   1613 //                                   parent nodes
   1614 //                   inNode - currently updated node
   1615 // RETURN VALUE    : void
   1616 // PRE-CONDITIONS  : called from tree update function
   1617 // POST-CONDITIONS : none
   1618 // IMPORTANT NOTES :
   1619 // REQUIREMENT #   :
   1620 //------------------------------------------------------------------------
   1621 void DMTree::CheckForIndirectUpdates( CPCHAR szURI, const DMMetaPCharVector& asChildDepend, DMNode* inNode )
   1622 {
   1623   // check if provided nodes
   1624   for ( int i = 0; i < asChildDepend.size(); i++ )
   1625   {
   1626     DMToken oChild(TRUE,asChildDepend[i],SYNCML_DM_COMMA);
   1627 
   1628     if ( !oChild.getBuffer() )
   1629         return ; //low memory condition
   1630 
   1631     const char* szChild = oChild.nextSegment();
   1632 
   1633     while ( szChild )
   1634     {
   1635  //     if ( m_oPluginManager.IsCommitPluginMounted(szChild) == TRUE )
   1636       CheckURIForIndirectUpdates( szChild, szURI, inNode);
   1637 
   1638       szChild = oChild.nextSegment();
   1639     }
   1640   }
   1641 }
   1642 
   1643 //------------------------------------------------------------------------
   1644 // FUNCTION        : CheckURIForIndirectUpdates
   1645 // DESCRIPTION     : This function checks one child/depend uri
   1646 //                   and if it ponts to the current uri
   1647 //                   issues "indirect" update
   1648 // ARGUMENTS PASSED: szURI - currently updated uri
   1649 //                   szChild - "child/depend" constraint
   1650 //                   inNode - currently updated node
   1651 // RETURN VALUE    : void
   1652 // PRE-CONDITIONS  : called from CheckForIndirectUpdates function
   1653 // POST-CONDITIONS : none
   1654 // IMPORTANT NOTES :
   1655 // REQUIREMENT #   :
   1656 //------------------------------------------------------------------------
   1657 void DMTree::CheckURIForIndirectUpdates( CPCHAR szChild, CPCHAR szURI, DMNode* inNode )
   1658 {
   1659   // node can have '*' inside, so we have to traverse all posible nodes to look for corresponding values
   1660   CPCHAR szStarPos = DmStrstr(szChild, "*");
   1661   if ( !szStarPos )
   1662   {
   1663     DMGetData  oReturnData;
   1664     SYNCML_DM_RET_STATUS_T res = Get(szChild, oReturnData, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   1665 
   1666     if ( res == SYNCML_DM_SUCCESS  && DmStrstr( szURI, oReturnData.getCharData() ) != NULL )
   1667     {
   1668          LogEvent(SYNCML_DM_EVENT_INDIRECT, szChild);
   1669     }
   1670 
   1671     return;
   1672   }
   1673 
   1674   if ( szStarPos == szChild )
   1675     return; // incorect uri - '*' first symbol
   1676 
   1677   DMString strParent( szChild, szStarPos-szChild-1);
   1678 
   1679   DMGetData  oData;
   1680   SYNCML_DM_RET_STATUS_T res = Get(strParent, oData, SYNCML_DM_REQUEST_TYPE_INTERNAL);
   1681 
   1682   if ( res != SYNCML_DM_SUCCESS  )
   1683     return; // node probably does not exist
   1684 
   1685   DMToken oChild(FALSE, oData.getCharData(), '/' );
   1686 
   1687   const char* szNextChild = oChild.nextSegment();
   1688 
   1689   while ( szNextChild )
   1690   {
   1691     DMString strURI( szChild, szStarPos-szChild); // 'parent' with '/' at the end
   1692     strURI += szNextChild;
   1693     strURI += (szStarPos+1); // the rest after '*'
   1694 
   1695     CheckURIForIndirectUpdates( strURI, szURI, inNode );
   1696 
   1697     szNextChild = oChild.nextSegment();
   1698   }
   1699 
   1700 }
   1701 
   1702 
   1703 //------------------------------------------------------------------------
   1704 // FUNCTION        : IsUriEnabled
   1705 // DESCRIPTION     : This function checks if URI is blocked
   1706 // ARGUMENTS PASSED: szURI - currently updated uri
   1707 // RETURN VALUE    : TRUE/FALSE
   1708 // PRE-CONDITIONS  : called from Add/Replace/Delete/Get functions
   1709 // POST-CONDITIONS : none
   1710 // IMPORTANT NOTES :
   1711 // REQUIREMENT #   :
   1712 //------------------------------------------------------------------------
   1713 BOOLEAN
   1714 DMTree::IsUriEnabled(CPCHAR szURI) const
   1715 {
   1716      BOOLEAN bIsEnabled;
   1717      bIsEnabled = m_oTreeMountObj.IsMountPointEnabled(szURI);
   1718      if ( bIsEnabled == FALSE )
   1719           return FALSE;
   1720 
   1721      bIsEnabled =  m_oPluginManager.IsMountPointEnabled(szURI);
   1722     if ( bIsEnabled == FALSE )
   1723           return FALSE;
   1724 
   1725     if ( DmIsDMAccNodePath(szURI) ==  SYNCML_DM_FEATURE_NOT_SUPPORTED )
   1726         return FALSE;
   1727 
   1728 
   1729     if ( szURI!=NULL && DmStrstr( szURI, "/DevDetail/Ext/OMA_PoC" )!=NULL )
   1730     {
   1731         CPCHAR bit = ::XPL_DM_GetEnv(SYNCML_DM_FEATURE_ID_POC_PROVISION_VIA_OMADM);
   1732         if (bit!=NULL && bit[0]=='0' && bit[1]==0)
   1733         {
   1734             const DMString & sessionName = GetServerId();
   1735             DMString dmProfleNodeName;
   1736             if ((sessionName != "DM_OMACP") && (sessionName != "localhost") &&
   1737                 ((DMTree*)this)->GetParentOfKeyValue (sessionName,
   1738                                                   ::XPL_DM_GetEnv( SYNCML_DM_NODENAME_SERVERID ),
   1739                                                   ::XPL_DM_GetEnv( SYNCML_DM_DMACC_ROOT_PATH ),
   1740                                                   dmProfleNodeName))
   1741             {
   1742                 return FALSE;
   1743             }
   1744         }
   1745     }
   1746 
   1747     return TRUE;
   1748 }
   1749 
   1750 BOOLEAN
   1751 DMTree::VerifyArchiveReadAccess(CPCHAR szURI)
   1752 {
   1753     BOOLEAN result = TRUE;
   1754     SyncML_DM_Archive* archive = this->GetArchiver().getArchiveByURI(szURI);
   1755     if (archive != NULL) {
   1756         result = archive->verifyPermission(XPL_FS_RDONLY_MODE);
   1757     }
   1758     return result;
   1759 }
   1760 
   1761 BOOLEAN
   1762 DMTree::VerifyArchiveWriteAccess(CPCHAR szURI)
   1763 {
   1764     BOOLEAN result = TRUE;
   1765     SyncML_DM_Archive* archive = this->GetArchiver().getArchiveByURI(szURI);
   1766     if (archive != NULL) {
   1767         result = archive->verifyPermission(XPL_FS_RDWR_MODE);
   1768     }
   1769     return result;
   1770 }
   1771