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