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