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 Header Name: dm_ua_handlecommand.cc 20 21 General Description: Implementation of SyncML toolkit callback functions. 22 23 ==================================================================================================*/ 24 25 #include "dmstring.h" 26 #include "dmStringUtil.h" 27 #include "dm_tree_util.h" 28 #include "xpl_dm_Manager.h" 29 #include "dm_ua_handlecommand.h" 30 #include "dmProcessScriptSession.h" 31 #include "dmServerSession.h" 32 #include "dm_security.h" 33 #include "dmLockingHelper.h" 34 #include "SYNCML_DM_DisplayAlert.H" 35 #include "SYNCML_DM_ConfirmAlert.H" 36 #include "SYNCML_DM_TextInputAlert.H" 37 #include "SYNCML_DM_SingleChoiceAlert.H" 38 #include "SYNCML_DM_MultipleChoiceAlert.H" 39 #include "xpl_Logger.h" 40 41 #include "xlttags.h" 42 43 extern "C" { 44 #include "smlerr.h" 45 #include "xpt-b64.h" 46 } 47 48 /*================================================================================================== 49 TYPEDEFS 50 ==================================================================================================*/ 51 /* Note that the order of this table MUST match the order of the SYNCML_DM_COMMAND_T enum in 52 * syncml_dm_data_types.h 53 */ 54 static const CPCHAR dm_command_name_table[] = { 55 "", //SYNCML_DM_NO_COMMAND 56 "Add", //SYNCML_DM_ADD 57 "Delete", //SYNCML_DM_DELETE 58 "Replace", //SYNCML_DM_REPLACE 59 "Get", //SYNCML_DM_GET 60 "Rename", //SYNCML_DM_RENAME 61 "Exec", //SYNCML_DM_EXEC 62 "Copy", //SYNCML_DM_COPY 63 "Alert", //SYNCML_DM_ALERT 64 "SyncHdr", //SYNCML_DM_HEADER 65 "Status", //SYNCML_DM_STATUS 66 "Atomic", //SYNCML_DM_ATOMIC 67 "Sequence" //SYNCML_DM_SEQUENCE 68 }; 69 70 static SYNCML_DM_BuildPackage *pDmBuildPackage; 71 static DMProcessScriptSession *pDmMgmtSessionObj; 72 73 /* Since SyncHdr STATUS doesn't get constructed until the receiving package's STATUS command is 74 * handled, we need to save synchdr_dm_stat when the starting message is handled. Keep it until 75 * SyncHdr STATUS is constructed. */ 76 static SYNCML_DM_RET_STATUS_T synchdr_dm_stat = SYNCML_DM_SUCCESS; 77 78 static SYNCML_DM_CHAL_TYPE_T s_nSrvSecLevel = SYNCML_DM_CHAL_UNDEFINED; 79 80 /*================================================================================================== 81 LOCAL FUNCTION PROTOTYPES 82 ==================================================================================================*/ 83 84 85 /*================================================================================================== 86 LOCAL FUNCTIONS 87 ==================================================================================================*/ 88 static inline SYNCML_DM_RET_STATUS_T SyncML2DMCode( const char* szSyncMLCode ) 89 { 90 SYNCML_DM_RET_STATUS_T nRet = DmAtoi( szSyncMLCode ); 91 92 if ( nRet == 200 ) 93 return SYNCML_DM_SUCCESS; 94 95 return nRet; 96 } 97 98 99 100 /*================================================================================================== 101 FUNCTIONS 102 ==================================================================================================*/ 103 104 /*================================================================================================== 105 FUNCTION : SetMetaData 106 107 DESCRIPTION : The utility function to set up the meta data. 108 109 ARGUMENT PASSED : p_meta_info 110 OUTPUT PARAMETER: pp_type 111 p_format 112 RETURN VALUE : SML_ERR_OK or ERR code 113 IMPORTANT NOTES : 114 115 116 ==================================================================================================*/ 117 SYNCML_DM_RET_STATUS_T SetMetaData(SmlPcdataPtr_t p_meta_data, 118 DMBuffer& pp_type, 119 SYNCML_DM_FORMAT_T *p_format) 120 { 121 SmlMetInfMetInfPtr_t p_meta_info; 122 CPCHAR p_temp_content; 123 124 /* Setup OUTPUT parameter type and format. If p_meta_data is not set, assign default value 125 to OUTPUT parameters, type as "text/plain", format as "chr". */ 126 if (p_meta_data != NULL) 127 { 128 if (p_meta_data->content != NULL) 129 { 130 if ( SML_PCDATA_EXTENSION != p_meta_data->contentType && 131 SML_EXT_METINF != p_meta_data->extension ) 132 { 133 *p_format = SYNCML_DM_FORMAT_CHR; 134 pp_type.assign("text/plain"); 135 } 136 else 137 { 138 p_meta_info = (SmlMetInfMetInfPtr_t)p_meta_data->content; 139 if ((p_meta_info->format != NULL) && 140 (p_meta_info->format->length != 0)) 141 { 142 p_temp_content = (CPCHAR)p_meta_info->format->content; 143 *p_format = DMTree::ConvertFormatStr(p_temp_content); 144 } 145 else 146 { 147 /* If there is no format information, set p_format as default format "chr" */ 148 *p_format = SYNCML_DM_FORMAT_CHR; 149 } 150 /* Set p_temp_type to the passed in type */ 151 if((p_meta_info->type != NULL) && (p_meta_info->type->length != 0)) 152 { 153 pp_type.assign((UINT8*)p_meta_info->type->content,p_meta_info->type->length); 154 } 155 else 156 { 157 /* If there is no type information, set the type as 'text/plain' */ 158 pp_type.assign("text/plain"); 159 } 160 } 161 } 162 } 163 else 164 { 165 *p_format = SYNCML_DM_FORMAT_CHR; 166 pp_type.assign("text/plain"); 167 } 168 169 if ( pp_type.getBuffer() == NULL ) 170 return SYNCML_DM_DEVICE_FULL; 171 172 return SYNCML_DM_SUCCESS; 173 } 174 175 176 /*================================================================================================== 177 FUNCTION : SetExecResultsData 178 179 DESCRIPTION : The utility function to set up the results data for Exec command. 180 181 ARGUMENT PASSED : p_passedin_result_item. p_target_uri 182 p_exec_ret_data 183 OUTPUT PARAMETER: p_passedin_result_item 184 185 RETURN VALUE : SML_ERR_OK or ERR code 186 IMPORTANT NOTES : 187 188 189 ==================================================================================================*/ 190 Ret_t 191 SetExecResultsData(SmlItemPtr_t p_passedin_result_item, 192 CPCHAR pURI, 193 const DMString & execResults) 194 { 195 Ret_t sml_ret_stat = SML_ERR_OK; 196 char data_size_str[UINT32_TYPE_STR_SIZE_10]; 197 198 199 p_passedin_result_item->source = smlAllocSource(); 200 if ( p_passedin_result_item->source == NULL ) 201 return SYNCML_DM_FAIL; 202 203 pDmBuildPackage->BuildPcData(p_passedin_result_item->source->locURI, SML_PCDATA_STRING, 204 SML_EXT_UNDEFINED,DmStrlen(pURI),(UINT8*)pURI); 205 206 /* Convert the dwRetDataSize to a string */ 207 DmSprintf(data_size_str, "%d", execResults.length()); 208 p_passedin_result_item->meta = smlAllocPcdata(); 209 if ( p_passedin_result_item->meta == NULL ) 210 { 211 return SYNCML_DM_FAIL; 212 } 213 214 215 pDmBuildPackage->BuildMetaInfo( 216 p_passedin_result_item->meta, 217 NULL, NULL, NULL, 218 (UINT8*)data_size_str, 219 NULL, NULL, NULL, NULL); 220 221 /* Set the p_passedin_result_item->data */ 222 /* Client construct <Data> element no matter there are data from GET command or not. */ 223 p_passedin_result_item->data = smlAllocPcdata(); 224 if ( p_passedin_result_item->data == NULL ) 225 { 226 return SYNCML_DM_FAIL; 227 } 228 229 pDmBuildPackage->BuildPcData(p_passedin_result_item->data, SML_PCDATA_STRING, 230 SML_EXT_UNDEFINED,execResults.length(),(UINT8*)execResults.c_str()); 231 return sml_ret_stat; 232 } 233 234 235 static SYNCML_DM_RET_STATUS_T SaveStatus(UINT8 *p_CmdRefData, 236 UINT8 *p_CmdName, 237 UINT8 *p_SourceRefData, 238 UINT8 *p_TargetRefData, 239 UINT16 status_Code, 240 const DMStringVector* responses, 241 SYNCML_DM_USER_DATA_T *pUserData ) 242 { 243 SmlStatusPtr_t pStatus = pDmBuildPackage->AllocateStatus( 244 p_CmdRefData, p_CmdName, p_SourceRefData, p_TargetRefData, NULL, 245 status_Code, responses ); 246 247 if ( !pStatus ) 248 return SYNCML_DM_FAIL; 249 250 pUserData->aStatuses.push_back((UINT32)pStatus); 251 return SYNCML_DM_SUCCESS; 252 } 253 254 255 static SYNCML_DM_RET_STATUS_T 256 SaveCommandRefStatus(UINT8 *p_CmdRefData, 257 UINT8 *p_CmdName, 258 SmlItemPtr_t pCommandItem, 259 SYNCML_DM_RET_STATUS_T status_Code, 260 SYNCML_DM_USER_DATA_T *pUserData ) 261 { 262 263 UINT8 *p_SourceRefData = NULL; 264 UINT8 *p_TargetRefData = NULL; 265 SmlStatusPtr_t pStatus = NULL; 266 267 if(pCommandItem->target != NULL && pCommandItem->target->locURI != NULL) 268 p_TargetRefData = (UINT8 *)pCommandItem->target->locURI->content; 269 else 270 { 271 if ( status_Code == SYNCML_DM_SUCCESS ) 272 status_Code = SYNCML_DM_BAD_REQUEST; 273 } 274 275 if (pCommandItem->source != NULL && pCommandItem->source->locURI != NULL) 276 p_SourceRefData = (UINT8*)pCommandItem->source->locURI->content; 277 278 return SaveStatus(p_CmdRefData, 279 p_CmdName, 280 p_SourceRefData, 281 p_TargetRefData, 282 status_Code, 283 NULL, 284 pUserData); 285 286 if ( !pStatus ) 287 return SYNCML_DM_FAIL; 288 289 pUserData->aStatuses.push_back((UINT32)pStatus); 290 return SYNCML_DM_SUCCESS; 291 } 292 293 static SYNCML_DM_RET_STATUS_T SaveResult(CPCHAR pStrTargetUri, 294 CPCHAR p_CmdIdRef, 295 DMGetData *p_get_ret_data, 296 BOOLEAN is_ThisGetStructResult, 297 BOOLEAN isFirstGetStruct, 298 BOOLEAN isThisGetPropResult, 299 SYNCML_DM_USER_DATA_T *pUserData, 300 UINT8 type, // exec/get/getstruct 301 const SYNCML_DM_GET_ON_LIST_RET_DATA_T& oGetStructData ) 302 { 303 SmlResultsPtr_t p_results = NULL; 304 SmlPcdataPtr_t p_data = NULL; 305 SYNCML_DM_RET_STATUS_T nRes = SYNCML_DM_SUCCESS; 306 CPCHAR p_target_uri = pStrTargetUri; 307 308 #ifdef TNDS_SUPPORT 309 SmlPcdata_t pcData; 310 if ( type == SYNCML_DM_RESULT_VALUE::Enum_Result_GetTnds ) 311 { 312 p_target_uri = oGetStructData._pbURI; 313 nRes = pDmBuildPackage->AllocateTndsResult(pStrTargetUri, p_get_ret_data, oGetStructData, &pcData); 314 if ( nRes == SYNCML_DM_SUCCESS ) 315 { 316 p_data = &pcData; 317 } 318 } 319 #endif 320 321 nRes = pDmBuildPackage->AllocateResult( p_results, p_target_uri, 322 p_CmdIdRef, p_get_ret_data, 323 is_ThisGetStructResult, isFirstGetStruct, 324 isThisGetPropResult, NULL, p_data); 325 326 if ( nRes != SYNCML_DM_SUCCESS ) 327 { 328 if ( NULL != p_results ) 329 { 330 smlFreeResults(p_results); 331 p_results = NULL; 332 } 333 return nRes; 334 } 335 336 pUserData->aResults.push_back( SYNCML_DM_RESULT_VALUE( type, p_results, 337 oGetStructData, p_CmdIdRef, 338 (CPCHAR)pDmBuildPackage->GetMsgRef()) ); 339 return nRes; 340 } 341 342 static SYNCML_DM_RET_STATUS_T AtomicRollback (VoidPtr_t userData) 343 { 344 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 345 SYNCML_DM_RET_STATUS_T retStatus=SYNCML_DM_FAIL; 346 347 if( !pUserData->rollback ) 348 { 349 retStatus = dmTreeObj.GetLockContextManager().ReleaseIDInternal( SYNCML_DM_LOCKID_CURRENT, SYNCML_DM_ROLLBACK); 350 351 pUserData->pAtomicStatus.status = SYNCML_DM_ATOMIC_FAILED; 352 353 if (retStatus != SYNCML_DM_SUCCESS) 354 retStatus = SYNCML_DM_ATOMIC_ROLLBACK_FAILED; 355 else 356 retStatus = SYNCML_DM_ATOMIC_ROLLBACK_OK; 357 358 for ( int i = 0; i <pUserData->oStatus.size(); i++ ) 359 pUserData->oStatus[i].status = retStatus; 360 361 pUserData->rollback = TRUE; 362 } 363 return retStatus; 364 } 365 366 367 static void SequenceStatus(VoidPtr_t userData, SYNCML_DM_RET_STATUS_T status) 368 { 369 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 370 371 if ( pUserData->IsSequence() ) 372 { 373 if ( status != SYNCML_DM_SUCCESS ) 374 pUserData->sequenceFailed = TRUE; 375 } 376 } 377 378 static void CheckAuthorization( SmlCredPtr_t pCred ) 379 { 380 DMClientServerCreds *pClientServerCreds = pDmMgmtSessionObj->GetClientServerCreds(); 381 SmlMetInfMetInfPtr_t pMeta = NULL; 382 383 // check default required level 384 if ( s_nSrvSecLevel == SYNCML_DM_CHAL_UNDEFINED ) 385 { 386 CPCHAR szStr = XPL_DM_GetEnv(SYNCML_DM_SECURITY_LEVEL); 387 if ( !szStr ) 388 s_nSrvSecLevel = SYNCML_DM_CHAL_BASIC; 389 else { 390 s_nSrvSecLevel = DmAtoi(szStr); 391 392 if ( s_nSrvSecLevel < SYNCML_DM_CHAL_NONE || 393 s_nSrvSecLevel > SYNCML_DM_CHAL_HMAC ) 394 s_nSrvSecLevel = SYNCML_DM_CHAL_BASIC; 395 } 396 } 397 398 if ( pClientServerCreds->ServerChalType <= SYNCML_DM_CHAL_NONE ) 399 pClientServerCreds->SetPrefServerAuth(s_nSrvSecLevel); // use default only if it's not set yet 400 401 if ( pClientServerCreds->ServerChalType == SYNCML_DM_CHAL_HMAC ) 402 return; // authorization performed in onStatus handler 403 404 // if none - just authorize at once, but if server provides credentials - verify it 405 if ( pClientServerCreds->ServerChalType == SYNCML_DM_CHAL_NONE ) 406 pDmMgmtSessionObj->SetSecStateSrv( TRUE ); 407 408 if ( !pCred || !pCred->data || !pCred->meta) 409 return; // no credentials 410 411 const char* szType = NULL; 412 const char* szData = NULL; 413 414 szData = (const char*)pCred->data->content; 415 416 if ( pCred->meta->contentType == SML_PCDATA_EXTENSION && 417 pCred->meta->extension == SML_EXT_METINF ){ 418 pMeta = (SmlMetInfMetInfPtr_t)pCred->meta->content; 419 420 if ( pMeta && pMeta->type && pMeta->type->contentType == SML_PCDATA_STRING ) 421 szType = (const char*)pMeta->type->content; 422 } 423 424 if ( !szType || !szData ) 425 return; 426 427 SYNCMLDM_SEC_CREDENTIALS_T *pGenCred = NULL; 428 429 if ( DmStrcmp(szType, SYNCML_AUTH_BASIC) == 0 ) 430 { 431 if ( pClientServerCreds->ServerChalType > SYNCML_DM_CHAL_BASIC) 432 return; // basic is not allowed 433 434 pClientServerCreds->SetPrefServerAuth(SYNCML_DM_CHAL_BASIC); // use basic after that for this session 435 436 SYNCMLDM_BASIC_SEC_INFO_T basicSecInfo; 437 438 basicSecInfo.pb_password = (UINT8*)pClientServerCreds->pServerPW.c_str(); 439 basicSecInfo.pb_user_name_or_server_id = (UINT8*)pClientServerCreds->pServerId.c_str(); 440 441 pGenCred = syncmldm_sec_build_basic_cred(&basicSecInfo); 442 } 443 else 444 if ( DmStrcmp(szType, SYNCML_AUTH_MD5) == 0 ) 445 { 446 if ( pClientServerCreds->ServerChalType > SYNCML_DM_CHAL_MD5) 447 return; // MD5 digest is not allowed 448 449 pClientServerCreds->SetPrefServerAuth( SYNCML_DM_CHAL_MD5 ); // use MD5 after that for this session 450 451 SYNCMLDM_MD5_SEC_INFO_T md5SecInfo; 452 UINT8 decodedNonce[MAX_BIN_NONCE_LEN]; 453 UINT32 encodedNonceLen; 454 UINT32 decodedNonceLen; 455 456 /* The ClientNonce string is b64 encoded and must be decoded now.*/ 457 encodedNonceLen = DmStrlen((const char *)pClientServerCreds->pServerNonce); 458 decodedNonceLen = base64Decode((unsigned char *)decodedNonce, 459 MAX_BIN_NONCE_LEN, 460 (unsigned char*)pClientServerCreds->pServerNonce.c_str(), 461 (unsigned long*)&encodedNonceLen); 462 md5SecInfo.pb_user_name_or_server_id = (UINT8*)pClientServerCreds->pServerId.c_str(); 463 md5SecInfo.pb_password = (UINT8*)pClientServerCreds->pServerPW.c_str(); 464 md5SecInfo.pb_nonce = decodedNonce; 465 md5SecInfo.o_encode_base64 = FALSE; 466 if ( pMeta->format ) 467 md5SecInfo.o_encode_base64 = TRUE; 468 md5SecInfo.w_nonce_length = decodedNonceLen; 469 470 pGenCred = syncmldm_sec_build_md5_cred(&md5SecInfo); 471 } 472 473 if ( !pGenCred ) 474 return; 475 476 if ( memcmp(szData, (const char*)pGenCred->ab_credential_string, pGenCred->w_credential_string_length) == 0 ) 477 pDmMgmtSessionObj->SetSecStateSrv( TRUE ); 478 else 479 pDmMgmtSessionObj->SetSecStateSrv( FALSE ); 480 481 DmFreeMem(pGenCred); 482 } 483 484 /*================================================================================================== 485 FUNCTION : HandleEndMessage 486 487 DESCRIPTION : This method calls SyncML Toolkit smlEndMessage to add the Final element in the 488 SyncBody for the sending message. 489 ARGUMENT PASSED : id 490 userData 491 final 492 OUTPUT PARAMETER: 493 RETURN VALUE : SML_ERR_OK or ERR code 494 IMPORTANT NOTES : 495 496 497 ==================================================================================================*/ 498 499 Ret_t 500 HandleEndMessage (InstanceID_t id, 501 VoidPtr_t userData, 502 Boolean_t final) 503 { 504 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 505 SYNCML_DM_RET_STATUS_T ret_stat = SYNCML_DM_SUCCESS; 506 BOOLEAN isLastChunk = FALSE; 507 508 // Is session aborted? 509 if( pDmMgmtSessionObj->IsSessionAborted()) 510 return SYNCML_DM_SUCCESS; 511 512 // put cahced statuses (if any) 513 while ( ret_stat == SYNCML_DM_SUCCESS && pUserData->aStatuses.size() > 0 ) { 514 ret_stat = pDmBuildPackage->BuildStatus( (SmlStatusPtr_t)pUserData->aStatuses[0] ); 515 if ( ret_stat == SYNCML_DM_SUCCESS ){ 516 smlFreeStatus((SmlStatusPtr_t)pUserData->aStatuses[0]); 517 pUserData->aStatuses.remove(0); 518 } 519 } 520 // Large Object delivery 521 #ifdef LOB_SUPPORT 522 if( !pDmBuildPackage->LargeObjectSendNextChunk(ret_stat, isLastChunk)) 523 #endif 524 { 525 #ifdef LOB_SUPPORT 526 if(ret_stat != SYNCML_DM_SUCCESS) 527 { pUserData->aResults.remove(0); 528 isLastChunk = FALSE; 529 } 530 #endif 531 532 // pur cached results 533 while ( ret_stat == SYNCML_DM_SUCCESS && pUserData->aResults.size() > 0 ) { 534 // Large Object delivery 535 #ifdef LOB_SUPPORT 536 if(!isLastChunk) 537 ret_stat = pDmBuildPackage->LargeObjectSendFirstChunk(pUserData->aResults[0]); 538 isLastChunk = FALSE; 539 #else 540 // try to insert result first 541 ret_stat = pDmBuildPackage->BuildResultsCommand(pUserData->aResults[0]._pGetExecResult); 542 #endif 543 if ( ret_stat == SYNCML_DM_RESULTS_TOO_LARGE ) 544 break; 545 #ifndef LOB_SUPPORT 546 smlFreeResults( pUserData->aResults[0]._pGetExecResult ); pUserData->aResults[0]._pGetExecResult= NULL; 547 #endif 548 549 if ( pUserData->aResults[0]._type == SYNCML_DM_RESULT_VALUE::Enum_Result_GetStruct || 550 pUserData->aResults[0]._type == SYNCML_DM_RESULT_VALUE::Enum_Result_GetStructData ) 551 { 552 ret_stat = dmTreeObj.GetListNextItem(pUserData->aResults[0]._oGetStructPos); 553 554 if (ret_stat == SYNCML_DM_SUCCESS && pUserData->aResults[0]._oGetStructPos.psRetData ) { 555 ret_stat = pDmBuildPackage->AllocateResult( 556 pUserData->aResults[0]._pGetExecResult, 557 pUserData->aResults[0]._oGetStructPos._pbURI, 558 pUserData->aResults[0]._cmdRef, 559 pUserData->aResults[0]._oGetStructPos.psRetData, 560 pUserData->aResults[0]._type == SYNCML_DM_RESULT_VALUE::Enum_Result_GetStruct, 561 FALSE, FALSE, 562 pUserData->aResults[0]._msgID, NULL ); 563 564 565 delete pUserData->aResults[0]._oGetStructPos.psRetData; 566 pUserData->aResults[0]._oGetStructPos.psRetData = NULL; 567 if(ret_stat != SYNCML_DM_SUCCESS) 568 pUserData->aResults.remove(0); 569 570 continue; // write more data 571 } 572 } 573 pUserData->aResults.remove(0); 574 } 575 } 576 pDmBuildPackage->EndSyncmlDoc( ret_stat != SYNCML_DM_RESULTS_TOO_LARGE ); 577 pDmBuildPackage->Cleanup(); 578 579 return SML_ERR_OK; 580 } 581 582 583 /*================================================================================================== 584 FUNCTION : VerifyProtocolVersion 585 586 DESCRIPTION : 587 ARGUMENT PASSED : pContent 588 OUTPUT PARAMETER: 589 RETURN VALUE : SYNCML_DM_SUCCESS or SYNCML_DM_FAIL code 590 IMPORTANT NOTES : 591 592 593 ==================================================================================================*/ 594 SYNCML_DM_RET_STATUS_T 595 VerifyProtocolVersion( SmlSyncHdrPtr_t pContent) 596 { 597 if ( dmTreeObj.IsVersion_12() ) 598 { 599 /* Verify that the presentation protocol is what we support. */ 600 if (DmStrcmp((const char *)pContent->version->content, SYNCML_REP_PROTOCOL_VERSION_1_2) != 0) 601 return SYNCML_DM_FAIL; 602 /* Verify that the DM protocol is what we support. */ 603 if (DmStrcmp((const char *)pContent->proto->content, SYNCML_DM_PROTOCOL_VERSION_1_2) != 0) 604 return SYNCML_DM_FAIL; 605 } 606 else 607 { 608 /* Verify that the presentation protocol is what we support. */ 609 if (DmStrcmp((const char *)pContent->version->content, SYNCML_REP_PROTOCOL_VERSION_1_1) != 0) 610 return SYNCML_DM_FAIL; 611 /* Verify that the DM protocol is what we support. */ 612 if (DmStrcmp((const char *)pContent->proto->content, SYNCML_DM_PROTOCOL_VERSION_1_1) != 0) 613 return SYNCML_DM_FAIL; 614 } 615 return SYNCML_DM_SUCCESS; 616 617 618 } 619 620 /*================================================================================================== 621 FUNCTION : HandleStartMessage 622 623 DESCRIPTION : This function should analyze SyncHeader data from received DM document, and build 624 responding SyncML header. 625 ARGUMENT PASSED : id 626 userData 627 pContent 628 OUTPUT PARAMETER: 629 RETURN VALUE : SML_ERR_OK or ERR code 630 IMPORTANT NOTES : 631 632 633 ==================================================================================================*/ 634 Ret_t 635 HandleStartMessage (InstanceID_t id, 636 VoidPtr_t userData, 637 SmlSyncHdrPtr_t pContent) 638 { 639 640 SYNCML_DM_RET_STATUS_T ret_stat; 641 UINT32 temp_max_msg_size; 642 SmlMetInfMetInfPtr_t p_temp_meta_info; 643 DMString strRespUri; 644 UINT16 server_session_id; 645 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 646 647 /* Reset the synchdr_dm_stat for this message.*/ 648 synchdr_dm_stat = SYNCML_DM_SUCCESS; 649 650 /* Get the Session Object.*/ 651 pDmMgmtSessionObj = pUserData->pSessionMng; 652 pDmBuildPackage = pUserData->pPkgBuilder; 653 // ignore session ID when processing XML script 654 if(pDmMgmtSessionObj->IsProcessScript() == FALSE) 655 { 656 // Verify that this is the same session, hex string 657 if(pDmBuildPackage->IsSessionId() == TRUE) 658 { 659 // Verify that this is the same session, hex string 660 server_session_id = DmStrtol((const char *)pContent->sessionID->content, NULL, 16 ); 661 } 662 else 663 { 664 // Verify that this is the same session, dec string 665 server_session_id = DmStrtol((const char *)pContent->sessionID->content, NULL, 10 ); 666 } 667 668 if (server_session_id != pDmMgmtSessionObj->GetServerSessionId()) 669 { 670 smlFreeSyncHdr(pContent); 671 return SML_ERR_XLT_INVAL_SYNCML_DOC; 672 } 673 } 674 675 ret_stat = VerifyProtocolVersion(pContent); 676 if ( ret_stat != SYNCML_DM_SUCCESS ) 677 { 678 smlFreeSyncHdr(pContent); 679 return SML_ERR_XLT_INVAL_SYNCML_DOC; 680 } 681 682 /* Create the BuildPackage object instance. */ 683 pDmBuildPackage->Init(pUserData->pSessionMng); 684 685 /* If respURI exists, call transport API to set the URI. */ 686 if ((pContent->respURI != NULL) && (pContent->respURI->length != 0)) 687 { 688 /* Copy over the response URI */ 689 strRespUri.assign((const char *)pContent->respURI->content, pContent->respURI->length); 690 if(strRespUri.Encode() == FALSE) 691 synchdr_dm_stat = SYNCML_DM_PROCESSING_ERROR; 692 693 /* Call the MgmtSessionObj to set the response URI */ 694 ret_stat = pDmMgmtSessionObj->SetURI(strRespUri.c_str() ); 695 if (ret_stat != SYNCML_DM_SUCCESS) 696 { 697 synchdr_dm_stat = SYNCML_DM_PROCESSING_ERROR; 698 } 699 } 700 701 /* If the MaxMsgSize is sent by the server, when it's greater than our MaxMsgSize, don't need 702 to do anything; if it's smaller than our MaxMsgSize, set our MaxMsgSize to the new value. */ 703 if ((pContent->meta != NULL) && (pContent->meta->content != NULL)) 704 { 705 p_temp_meta_info = (SmlMetInfMetInfPtr_t)pContent->meta->content; 706 if ((p_temp_meta_info->maxmsgsize != NULL) && 707 (p_temp_meta_info->maxmsgsize->length != 0)) 708 { 709 temp_max_msg_size = DmAtoi((const char *)p_temp_meta_info->maxmsgsize->content); 710 /* If the Server MaxMsgSize is smaller than what we have, reset our MaxMessageSize */ 711 if (temp_max_msg_size < pDmBuildPackage->GetMaxMessageSize()) 712 { 713 pDmBuildPackage->SetMaxMessageSize(temp_max_msg_size); 714 } 715 } 716 #ifdef LOB_SUPPORT 717 if ((p_temp_meta_info->maxobjsize != NULL) && 718 (p_temp_meta_info->maxobjsize->length != 0)) 719 { 720 temp_max_msg_size = DmAtoi((const char *)p_temp_meta_info->maxobjsize->content); 721 /* If the Server MaxObjSize is smaller than what we have, reset our MaxObjectSize */ 722 if (pDmBuildPackage->GetMaxObjectSize()==0 || temp_max_msg_size < pDmBuildPackage->GetMaxObjectSize()) 723 { 724 pDmBuildPackage->SetMaxObjectSize(temp_max_msg_size); 725 } 726 } 727 #endif 728 } 729 730 /* Build up the SyncML document header */ 731 ret_stat = pDmBuildPackage->BuildStartSyncHdr(pContent,FALSE); 732 if (ret_stat != SYNCML_DM_SUCCESS) 733 { 734 synchdr_dm_stat = SYNCML_DM_BAD_REQUEST; 735 smlFreeSyncHdr(pContent); 736 return SML_ERR_UNSPECIFIC; 737 } 738 739 CheckAuthorization( pContent->cred ); 740 741 742 if ( pDmMgmtSessionObj->IsServerAuthorized()) 743 pDmMgmtSessionObj->ResetServerRetryCount(); 744 745 if( pDmMgmtSessionObj->IsProcessScript() ) 746 { 747 ret_stat = pDmBuildPackage->BuildFinishSyncHdr(SYNCML_DM_CHAL_NONE); 748 if (ret_stat != SYNCML_DM_SUCCESS) 749 { 750 synchdr_dm_stat = SYNCML_DM_BAD_REQUEST; 751 smlFreeSyncHdr(pContent); 752 return SML_ERR_UNSPECIFIC; 753 } 754 } 755 /* We need to check the source and target URI and set the dm_stat to the correct status before 756 we free the pContent.*/ 757 if ((pContent->target->locURI == NULL) || (pContent->source->locURI == NULL) || 758 (pContent->target->locURI->length == 0) || (pContent->source->locURI->length == 0)) 759 { 760 synchdr_dm_stat = SYNCML_DM_PERMISSION_FAILED; 761 } 762 763 /* Free the memory */ 764 smlFreeSyncHdr(pContent); 765 766 return SML_ERR_OK; 767 } 768 769 770 771 /*================================================================================================== 772 FUNCTION : PrepareCommandItem 773 774 DESCRIPTION : Check if command should be skipped and decode item URI 775 776 ARGUMENT PASSED : 777 userData 778 pContent 779 command 780 OUTPUT PARAMETER: 781 RETURN VALUE : SML_ERR_OK or ERR code 782 IMPORTANT NOTES : 783 784 785 ==================================================================================================*/ 786 static SYNCML_DM_RET_STATUS_T 787 PrepareCommandItem (SmlItemPtr_t pCommandItem, 788 SYNCML_DM_USER_DATA_T *pUserData, 789 DMString & strCommandUri ) 790 { 791 792 BOOLEAN res; 793 794 if ( pUserData->IsCommandSkipped() ) 795 return SYNCML_DM_NOT_EXECUTED; 796 797 if ((pCommandItem->target == NULL) || (pCommandItem->target->locURI == NULL)) 798 return SYNCML_DM_BAD_REQUEST; 799 800 res = strCommandUri.assign((CPCHAR)pCommandItem->target->locURI->content, 801 pCommandItem->target->locURI->length); 802 if ( res == FALSE ) 803 return SYNCML_DM_DEVICE_FULL; 804 805 if(strCommandUri.Decode() == FALSE) 806 return SYNCML_DM_BAD_REQUEST; 807 808 return SYNCML_DM_SUCCESS; 809 810 } 811 812 /*================================================================================================== 813 FUNCTION : ProcessStatus 814 815 DESCRIPTION : Process status of operationd 816 817 ARGUMENT PASSED : 818 userData 819 pContent 820 command 821 OUTPUT PARAMETER: 822 RETURN VALUE : SML_ERR_OK or ERR code 823 IMPORTANT NOTES : 824 825 826 ==================================================================================================*/ 827 828 static SYNCML_DM_RET_STATUS_T 829 ProcessStatus (SYNCML_DM_RET_STATUS_T dm_stat, 830 VoidPtr_t userData, 831 UINT8 * p_CmdRefData, 832 SmlItemPtr_t pCommandItem, 833 SYNCML_DM_COMMAND_T command) 834 { 835 836 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 837 SYNCML_DM_RET_STATUS_T ret_stat = SYNCML_DM_SUCCESS; 838 839 if ( pCommandItem == NULL ) 840 return SYNCML_DM_FAIL; 841 842 843 UINT8 *pTargetURL = NULL; 844 //Fix for Upmerge CR# LIBoo12975 845 if((pCommandItem->target != NULL) && (pCommandItem->target->locURI != NULL)) 846 { 847 if(command == SYNCML_DM_GET) 848 { 849 DMString strTargetEncode; 850 strTargetEncode = DMString((const char *)pCommandItem->target->locURI->content, (int)pCommandItem->target->locURI->length); 851 if(strTargetEncode.Encode() == FALSE) 852 { 853 return SYNCML_DM_FAIL; 854 } 855 pTargetURL = (UINT8 *)strTargetEncode.c_str(); 856 } 857 else 858 { 859 pTargetURL = (UINT8 *)pCommandItem->target->locURI->content; 860 } 861 } 862 863 UINT8* pSourceURL = NULL; 864 pSourceURL = (UINT8*)(pCommandItem->source != NULL ? pCommandItem->source->locURI->content : NULL); 865 866 if( pDmMgmtSessionObj->GetInAtomicCommand() ) 867 { 868 #ifdef DM_ATOMIC_SUPPORTED 869 // Save the data for the status and results 870 if(dm_stat != SYNCML_DM_SUCCESS && !pUserData->rollback) 871 AtomicRollback(userData); 872 #endif 873 pUserData->oStatus.push_back( SYNCML_DM_STATUS_DATA_T( 874 (CPCHAR)p_CmdRefData, 875 dm_command_name_table[command], 876 (CPCHAR)pSourceURL, 877 (CPCHAR)pTargetURL, 878 dm_stat) ); 879 880 } 881 else 882 { 883 ret_stat = SaveCommandRefStatus((UINT8 *)p_CmdRefData, 884 (UINT8 *)dm_command_name_table[command], 885 pCommandItem, 886 dm_stat, 887 pUserData ); 888 889 } 890 891 return ret_stat; 892 893 } 894 895 #ifdef TNDS_SUPPORT 896 SYNCML_DM_RET_STATUS_T ProcessTndsNode( SYNCML_DM_COMMAND_T command, 897 SmlDmTndNodeListPtr_t p_nodelist, 898 const DMString &parentURI, 899 const DMString &targetURI) 900 { 901 SYNCML_DM_RET_STATUS_T ret = SYNCML_DM_SUCCESS; 902 DMAddData oCommandData; 903 while ( NULL != p_nodelist && ret == SYNCML_DM_SUCCESS) 904 { 905 SmlDmTndNodePtr_t p_tnd_node = p_nodelist->node; 906 if ( p_tnd_node != NULL ) 907 { 908 // node name 909 DMString nodeName; 910 nodeName = (CPCHAR)p_tnd_node->nodename->content; 911 KCDBG("ProcessTndsNode: node name = %s", nodeName.c_str()); 912 913 // node format and type 914 SYNCML_DM_FORMAT_T nodeFormat = SYNCML_DM_FORMAT_NODE; 915 DMString nodeType = "text/plain", nodeValue = ""; 916 if ( p_tnd_node->rtprops != NULL ) 917 { 918 if ( p_tnd_node->rtprops->format != NULL ) 919 { 920 nodeFormat = DMTree::ConvertFormatStr((CPCHAR)p_tnd_node->rtprops->format->value->content); 921 if ( (nodeFormat == SYNCML_DM_FORMAT_BIN) && (nodeName == DM_AAUTHDATA) ) 922 { 923 nodeFormat = SYNCML_DM_FORMAT_CHR; 924 } 925 } 926 if ( p_tnd_node->rtprops->type != NULL ) 927 { 928 if ( p_tnd_node->rtprops->type->mime != NULL ) 929 { 930 nodeType = (CPCHAR)p_tnd_node->rtprops->type->mime->content; 931 } 932 else if ( p_tnd_node->rtprops->type->ddfname != NULL ) 933 { 934 nodeType = (CPCHAR)p_tnd_node->rtprops->type->ddfname->content; 935 } 936 } 937 } 938 KCDBG("ProcessTndsNode: nodeType = %s", nodeType.c_str()); 939 940 DMString nodeTargetURI; 941 if ( ( nodeType == MNG_OBJID_DMACC1 ) || (nodeType == MNG_OBJID_DMACC2) ) 942 { 943 KCDBG("ProcessTndsNode: modified Target URI"); 944 nodeTargetURI = DM_DMACC_1_2_URI; // TNDS is defined for 1.2 only 945 } 946 947 // calculate node path 948 DMString nodePath; 949 if (!nodeTargetURI.empty()) 950 { 951 nodePath = nodeTargetURI + "/"; 952 } 953 else 954 { 955 nodePath = parentURI + "/"; 956 } 957 958 if ( p_tnd_node->path != NULL ) 959 { 960 DMString path = (CPCHAR)p_tnd_node->path->content; 961 nodePath = nodeTargetURI + "/" + path + "/"; 962 } 963 nodePath += nodeName; 964 KCDBG("ProcessTndsNode: node path = %s", nodePath.c_str()); 965 966 // node value 967 if ( p_tnd_node->value != NULL ) 968 { 969 if ( DmStrncmp((CPCHAR)p_tnd_node->value->content, DM_INBOX, strlen(DM_INBOX)) == 0 ) 970 { 971 nodeValue = (CPCHAR)p_tnd_node->value->content + strlen(DM_INBOX) + 1; 972 } 973 else 974 { 975 nodeValue = (CPCHAR)p_tnd_node->value->content; 976 } 977 } 978 979 // Construct Add/Replace Data 980 oCommandData.clear(); 981 oCommandData.m_oURI.assign(nodePath.c_str()); 982 oCommandData.m_nFormat = nodeFormat; 983 oCommandData.m_oMimeType.assign(nodeType.c_str()); 984 oCommandData.m_oData.assign(nodeValue.c_str()); 985 986 // Add/Replace node in DMT 987 if ( command == SYNCML_DM_ADD ) 988 { 989 KCDBG("ProcessTndsNode: command == ADD"); 990 ret = dmTreeObj.Add(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 991 // Interior node exist 992 if ( nodeFormat == SYNCML_DM_FORMAT_NODE && ret == SYNCML_DM_TARGET_ALREADY_EXISTS ) 993 { 994 ret = SYNCML_DM_SUCCESS; 995 } 996 } 997 else 998 { 999 KCDBG("ProcessTndsNode: command == REPLACE"); 1000 ret = dmTreeObj.Replace(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 1001 } 1002 1003 // Process children node 1004 if ( ret == SYNCML_DM_SUCCESS ) 1005 { 1006 if (nodeTargetURI.empty()) 1007 { 1008 ret = ProcessTndsNode(command, p_tnd_node->nodelist, nodePath, targetURI); 1009 } 1010 else 1011 { 1012 ret = ProcessTndsNode(command, p_tnd_node->nodelist, nodePath, nodeTargetURI); 1013 } 1014 } 1015 else 1016 { 1017 KCDBG("Failed to handle TNDS node: %s, format: %d, value: %s, status:%d\n", nodePath.c_str(), nodeFormat, nodeValue.c_str(), ret); 1018 } 1019 } 1020 1021 // Process sibling node 1022 p_nodelist = p_nodelist->next; 1023 } 1024 1025 return ret; 1026 } 1027 1028 SYNCML_DM_RET_STATUS_T ProcessTndsCommand( 1029 SYNCML_DM_COMMAND_T command, 1030 VoidPtr_t userData, 1031 DMAddData & oCommand, 1032 DMCommandType cmdType, 1033 SmlItemPtr_t p_command_item) 1034 { 1035 DMString dataStr; 1036 if ( NULL == p_command_item->data || NULL == p_command_item->data->content ) 1037 { 1038 return SML_ERR_UNSPECIFIC; 1039 } 1040 if ( SML_PCDATA_EXTENSION != p_command_item->data->contentType && 1041 SML_EXT_DMTND != p_command_item->data->extension ) 1042 { 1043 return SML_ERR_UNSPECIFIC; 1044 } 1045 1046 SmlDmTndPtr_t p_tnd_info = NULL; 1047 p_tnd_info = (SmlDmTndPtr_t)p_command_item->data->content; 1048 if ( oCommand.m_oURI.compare(DM_INBOX) ) 1049 { 1050 oCommand.m_oURI.assign("."); 1051 } 1052 1053 SYNCML_DM_RET_STATUS_T dm_stat=dmTreeObj.GetLockContextManager().ReleaseIDInternal(SYNCML_DM_LOCKID_CURRENT, SYNCML_DM_ATOMIC); 1054 1055 if ( dm_stat != SYNCML_DM_SUCCESS && dm_stat != SYNCML_DM_FEATURE_NOT_SUPPORTED ) 1056 { 1057 return SML_ERR_UNSPECIFIC; 1058 } 1059 1060 /* Remember that we are in an Atomic command.*/ 1061 bool bIsInAtomic = pDmMgmtSessionObj->GetInAtomicCommand(); 1062 1063 pDmMgmtSessionObj->SetInAtomicCommand(TRUE); 1064 1065 SmlDmTndNodeListPtr_t p_nodelist = p_tnd_info->nodelist; 1066 DMString path = (CPCHAR)oCommand.m_oURI.getBuffer(); 1067 if ( oCommand.m_oURI.getBuffer()[0] == '/' ) 1068 { 1069 DMString tmpPath = "."; 1070 path = tmpPath + path; 1071 } 1072 dm_stat = ProcessTndsNode(command, p_nodelist, path.c_str(), path.c_str()); 1073 if ( dm_stat != SYNCML_DM_SUCCESS && dm_stat != SYNCML_DM_FEATURE_NOT_SUPPORTED ) 1074 { 1075 // Roll back TNDS objects 1076 AtomicRollback(userData); 1077 } 1078 1079 pDmMgmtSessionObj->SetInAtomicCommand(bIsInAtomic); 1080 return dm_stat; 1081 } 1082 #endif // TNDS_SUPPORT 1083 1084 /*================================================================================================== 1085 FUNCTION : ProcessCommand 1086 1087 DESCRIPTION : Process ADD?REPLACE command 1088 1089 This function will perform the following operations: 1090 1) Call DMTree::Add() or DMTree::Replace() function to perform ADD command on the DM tree. 1091 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1092 return status for each ADD command performed. 1093 ARGUMENT PASSED : id 1094 userData 1095 pContent 1096 command 1097 OUTPUT PARAMETER: 1098 RETURN VALUE : SML_ERR_OK or ERR code 1099 IMPORTANT NOTES : 1100 1101 1102 ==================================================================================================*/ 1103 Ret_t ProcessCommand (InstanceID_t id, 1104 VoidPtr_t userData, 1105 SmlAddPtr_t pContent, 1106 SYNCML_DM_COMMAND_T command) 1107 { 1108 Ret_t sml_ret_stat = SML_ERR_OK; 1109 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 1110 SYNCML_DM_RET_STATUS_T ret_stat = SYNCML_DM_SUCCESS; 1111 SmlItemListPtr_t p_command_list_item; 1112 SmlItemPtr_t p_command_item; 1113 DMBuffer oCommandType; 1114 SYNCML_DM_FORMAT_T commandFormat; 1115 1116 DMAddData oCommandData; 1117 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1118 1119 /* Get the data we need to work on */ 1120 p_command_list_item = pContent->itemList; 1121 p_command_item = p_command_list_item->item; 1122 1123 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::ProcessCommand command=%d", command)); 1124 1125 if ( command == SYNCML_DM_ADD ) 1126 dm_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_ADD); 1127 else 1128 dm_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_REPLACE); 1129 1130 if (dm_stat != SYNCML_DM_SUCCESS) 1131 { 1132 ret_stat = ProcessStatus (dm_stat, 1133 userData, 1134 (UINT8*)pContent->cmdID->content, 1135 p_command_item, 1136 command); 1137 /* Free the memeory we allocated (p_plugin_add), and passed in (pContent). */ 1138 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1139 return SML_ERR_OK; 1140 } 1141 1142 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 1143 * any management commands */ 1144 1145 /* Fill in meta data when meta data info is defined outside of the ITEM in the receiving 1146 package. 1147 if meta data is not set, default format "chr" and type "text/plain" will be filled. */ 1148 dm_stat = SetMetaData(pContent->meta, oCommandType, &commandFormat); 1149 if ( dm_stat != SYNCML_DM_SUCCESS ) 1150 { 1151 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1152 return SML_ERR_UNSPECIFIC; 1153 } 1154 1155 /* Make sure we are not in an atomic and the Server is authenticated before performing any 1156 * DM commands.*/ 1157 if (pDmMgmtSessionObj->IsAuthorized()) 1158 { 1159 /* Loop on every ADD ITEM */ 1160 while (p_command_item != NULL) 1161 { 1162 oCommandData.clear(); 1163 1164 // perform operation 1165 1166 while ( TRUE ) 1167 { 1168 DMString tempURI; 1169 dm_stat = PrepareCommandItem (p_command_item, 1170 pUserData, 1171 tempURI); 1172 if ( dm_stat != SYNCML_DM_SUCCESS ) 1173 break; 1174 1175 oCommandData.m_oURI.assign(tempURI); 1176 1177 if(oCommandData.m_oURI.getBuffer() == NULL) 1178 { 1179 dm_stat = SYNCML_DM_DEVICE_FULL; 1180 break; 1181 } 1182 1183 /* Set the meta data for ADD/REPLACE command if it's defined for each ITEM */ 1184 1185 if (p_command_item->meta != NULL) 1186 { 1187 dm_stat = SetMetaData(p_command_item->meta, oCommandData.m_oMimeType, &oCommandData.m_nFormat); 1188 if ( dm_stat != SYNCML_DM_SUCCESS ) 1189 break; 1190 } 1191 else 1192 { 1193 /* This particular item does not have meta data, so we need to use the meta data 1194 * from outside the command. 1195 */ 1196 oCommandData.m_oMimeType = oCommandType; 1197 if ( oCommandData.getType() == NULL ) 1198 { 1199 dm_stat = SYNCML_DM_DEVICE_FULL; 1200 break; 1201 } 1202 oCommandData.m_nFormat = commandFormat; 1203 } 1204 1205 #ifdef TNDS_SUPPORT 1206 /* Handle TNDS object */ 1207 if ( oCommandData.m_oMimeType.compare(SYNCML_CONTENT_TYPE_DM_TNDS_XML, strlen(SYNCML_CONTENT_TYPE_DM_TNDS_XML)) || 1208 oCommandData.m_oMimeType.compare(SYNCML_CONTENT_TYPE_DM_TNDS_WBXML, strlen(SYNCML_CONTENT_TYPE_DM_TNDS_WBXML)) ) 1209 { 1210 dm_stat = ProcessTndsCommand( command, 1211 userData, 1212 oCommandData, 1213 command == SYNCML_DM_ADD ? 1214 DM_COMMAND_ADD : 1215 DM_COMMAND_REPLACE, 1216 p_command_item); 1217 } 1218 else 1219 { 1220 #endif // TNDS_SUPPORT 1221 1222 #ifdef LOB_SUPPORT 1223 1224 if(pDmBuildPackage->IsProcessingLargeObject()) 1225 { 1226 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::ProcessCommand processing lob\n")); 1227 if ( command == SYNCML_DM_ADD ) 1228 dm_stat = pDmBuildPackage->LargeObjectRecvNextChunk(oCommandData, 1229 DM_COMMAND_ADD, 1230 p_command_item); 1231 else 1232 dm_stat = pDmBuildPackage->LargeObjectRecvNextChunk(oCommandData, 1233 DM_COMMAND_REPLACE, 1234 p_command_item); 1235 1236 1237 } 1238 else 1239 { 1240 XPL_LOG_DM_TMN_Debug(("not processing large obj\n")); 1241 if ( command == SYNCML_DM_ADD ) 1242 dm_stat = pDmBuildPackage->LargeObjectRecvFirstChunk(oCommandData, 1243 DM_COMMAND_ADD, 1244 p_command_item); 1245 else 1246 dm_stat = pDmBuildPackage->LargeObjectRecvFirstChunk(oCommandData, 1247 DM_COMMAND_REPLACE, 1248 p_command_item); 1249 1250 } 1251 #else // LOB_SUPPORT 1252 1253 /* Call TNM module to perform ADD command */ 1254 #ifdef DM_ATOMIC_SUPPORTED 1255 if ( command == SYNCML_DM_ADD ) { 1256 XPL_LOG_DM_TMN_Debug(("about to add atomic supported\n")); 1257 dm_stat = dmTreeObj.Add(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 1258 XPL_LOG_DM_TMN_Debug(("add atomic supported dm_stat=%d\n", dm_stat)); 1259 } 1260 else 1261 dm_stat = dmTreeObj.Replace(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 1262 #else // DM_ATOMIC_SUPPORTED 1263 if ( pDmMgmtSessionObj->GetInAtomicCommand() ) 1264 dm_stat = SYNCML_DM_COMMAND_FAILED; 1265 else 1266 { 1267 if ( command == SYNCML_DM_ADD ) { 1268 XPL_LOG_DM_TMN_Debug(("about to add atomic not supported\n")); 1269 dm_stat = dmTreeObj.Add(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 1270 XPL_LOG_DM_TMN_Debug(("add atomic not supported dm_stat=%d\n", dm_stat)); 1271 } 1272 else 1273 dm_stat = dmTreeObj.Replace(oCommandData,SYNCML_DM_REQUEST_TYPE_SERVER); 1274 } 1275 #endif // DM_ATOMIC_SUPPORTED 1276 #endif // LOB_SUPPORT 1277 1278 #ifdef TNDS_SUPPORT 1279 } 1280 #endif // TNDS_SUPPORT 1281 1282 SequenceStatus(userData, dm_stat); 1283 1284 break; 1285 } 1286 1287 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::ProcessCommand dm_stat=%d, command=%d\n",dm_stat, command)); 1288 1289 ret_stat = ProcessStatus (dm_stat, 1290 userData, 1291 (UINT8*)pContent->cmdID->content, 1292 p_command_item, 1293 command); 1294 if (ret_stat != SYNCML_DM_SUCCESS) 1295 { 1296 sml_ret_stat = SML_ERR_UNSPECIFIC; 1297 break; 1298 } 1299 1300 if (p_command_list_item->next != NULL) 1301 { 1302 p_command_list_item = p_command_list_item->next; 1303 p_command_item = p_command_list_item->item; 1304 } 1305 else 1306 p_command_item = NULL; 1307 } /* End of while */ 1308 } /* !inAtomicCommand && dmSecState */ 1309 else /* dmSecState not authenticated */ 1310 { 1311 /* Call the toolkit to construct the STATUS for ADD command */ 1312 ret_stat = SaveCommandRefStatus((UINT8 *)pContent->cmdID->content, 1313 (UINT8 *)dm_command_name_table[command], 1314 p_command_item, 1315 pDmMgmtSessionObj->GetNotAuthorizedStatus(), 1316 pUserData ); 1317 if (ret_stat != SYNCML_DM_SUCCESS) 1318 sml_ret_stat = SML_ERR_UNSPECIFIC; 1319 } 1320 /* Free the memeory we allocated (p_plugin_add), and passed in (pContent). */ 1321 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1322 1323 return sml_ret_stat; 1324 } 1325 1326 1327 1328 /*================================================================================================== 1329 FUNCTION : HandleAddCommand 1330 1331 DESCRIPTION : When the ADD element is processed from the received message, this callback 1332 function will be called. 1333 1334 This function will perform the following operations: 1335 1) Call DMTree::Add() function to perform ADD command on the DM tree. 1336 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1337 return status for each ADD command performed. 1338 ARGUMENT PASSED : id 1339 userData 1340 pContent 1341 OUTPUT PARAMETER: 1342 RETURN VALUE : SML_ERR_OK or ERR code 1343 IMPORTANT NOTES : 1344 1345 1346 ==================================================================================================*/ 1347 Ret_t HandleAddCommand (InstanceID_t id, VoidPtr_t userData, SmlAddPtr_t pContent) 1348 { 1349 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleAdd enter")); 1350 return ProcessCommand(id, userData, pContent,SYNCML_DM_ADD); 1351 } 1352 1353 /*================================================================================================== 1354 FUNCTION : HandleCopyCommand 1355 1356 DESCRIPTION : When the COPY element is processed from the received message, this callback 1357 function will be called. 1358 1359 This function will perform the following operations: 1360 1) Set DM status as SYNCML_DM_FEATURE_NOT_SUPPORTED. 1361 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1362 return status for each COPY command performed. 1363 ARGUMENT PASSED : id 1364 userData 1365 pContent 1366 OUTPUT PARAMETER: 1367 RETURN VALUE : SML_ERR_OK or ERR code 1368 IMPORTANT NOTES : 1369 1370 1371 ==================================================================================================*/ 1372 Ret_t 1373 HandleCopyCommand (InstanceID_t id, 1374 VoidPtr_t userData, 1375 SmlCopyPtr_t pContent) 1376 { 1377 Ret_t sml_ret_stat = SML_ERR_OK; 1378 SYNCML_DM_RET_STATUS_T ret_stat; 1379 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1380 1381 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 1382 * any management commands */ 1383 1384 /* Call the toolkit to construct the STATUS for COPY command */ 1385 ret_stat = SaveStatus( 1386 (UINT8 *)pContent->cmdID->content, 1387 (UINT8 *)dm_command_name_table[SYNCML_DM_COPY], 1388 NULL, 1389 NULL, 1390 SYNCML_DM_FEATURE_NOT_SUPPORTED, 1391 NULL, 1392 pUserData); 1393 1394 if (ret_stat != SYNCML_DM_SUCCESS) 1395 { 1396 sml_ret_stat = SML_ERR_UNSPECIFIC; 1397 } 1398 1399 /* Free the memory of pContent. */ 1400 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1401 1402 return sml_ret_stat; 1403 } 1404 1405 1406 /*================================================================================================== 1407 FUNCTION : HandleDeleteCommand 1408 1409 DESCRIPTION : When the DELETE element is processed from the received message, this callback 1410 function will be called. 1411 1412 This function will perform the following operations: 1413 1) Call DMTree::Delete() function to perform DELETE command on the DM tree. 1414 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1415 return status for each DELETE command performed. 1416 ARGUMENT PASSED : id 1417 userData 1418 pContent 1419 OUTPUT PARAMETER: 1420 RETURN VALUE : SML_ERR_OK or ERR code 1421 IMPORTANT NOTES : 1422 1423 1424 ==================================================================================================*/ 1425 Ret_t 1426 HandleDeleteCommand (InstanceID_t id, 1427 VoidPtr_t userData, 1428 SmlDeletePtr_t pContent) 1429 { 1430 Ret_t sml_ret_stat = SML_ERR_OK; 1431 SYNCML_DM_RET_STATUS_T dm_stat = 0; 1432 SYNCML_DM_RET_STATUS_T ret_stat = 0; 1433 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1434 1435 SmlItemListPtr_t p_delete_list_item; 1436 SmlItemPtr_t p_delete_item; 1437 1438 p_delete_list_item = pContent->itemList; 1439 p_delete_item = p_delete_list_item->item; 1440 1441 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleDelete enter")); 1442 1443 ret_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_REPLACE); 1444 1445 if (ret_stat != SYNCML_DM_SUCCESS) 1446 { 1447 ret_stat = ProcessStatus (dm_stat, 1448 userData, 1449 (UINT8*)pContent->cmdID->content, 1450 p_delete_item, 1451 SYNCML_DM_DELETE); 1452 /* Free the memory of pContent and p_target_uri. */ 1453 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1454 return SML_ERR_OK; 1455 } 1456 1457 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 1458 * any management commands */ 1459 1460 /* Make sure we are not in an atomic and the Server is authenticated before performing any 1461 * DM commands.*/ 1462 if (pDmMgmtSessionObj->IsAuthorized()) 1463 { 1464 /* Loop on each DELETE item */ 1465 while (p_delete_item != NULL) { 1466 1467 1468 // perform operation 1469 while ( true ) 1470 { 1471 DMString strDeleteUri; 1472 dm_stat = PrepareCommandItem (p_delete_item, 1473 pUserData, 1474 strDeleteUri); 1475 if ( dm_stat != SYNCML_DM_SUCCESS ) 1476 break; 1477 1478 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleDelete uri=%s\n", strDeleteUri.c_str())); 1479 1480 #ifdef DM_ATOMIC_SUPPORTED 1481 dm_stat = dmTreeObj.Delete (strDeleteUri.c_str(),SYNCML_DM_REQUEST_TYPE_SERVER ); 1482 #else 1483 if ( pDmMgmtSessionObj->GetInAtomicCommand() ) 1484 dm_stat = SYNCML_DM_COMMAND_FAILED; 1485 else 1486 dm_stat = dmTreeObj.Delete (strDeleteUri.c_str(),SYNCML_DM_REQUEST_TYPE_SERVER ); 1487 #endif 1488 SequenceStatus(userData, dm_stat); 1489 break; 1490 } 1491 1492 ret_stat = ProcessStatus (dm_stat, 1493 userData, 1494 (UINT8*)pContent->cmdID->content, 1495 p_delete_item, 1496 SYNCML_DM_DELETE); 1497 if (ret_stat != SYNCML_DM_SUCCESS) 1498 { 1499 sml_ret_stat = SML_ERR_UNSPECIFIC; 1500 break; 1501 } 1502 1503 /* Move to the next item on the list */ 1504 if (p_delete_list_item->next != NULL) { 1505 p_delete_list_item = p_delete_list_item->next; 1506 p_delete_item = p_delete_list_item->item; 1507 } 1508 else 1509 p_delete_item = NULL; 1510 } /* End of while */ 1511 } /* !inAtomicCommand && dmSecState */ 1512 else /* dmSecState not authenticated */ 1513 { 1514 ret_stat = SaveCommandRefStatus( 1515 (UINT8 *)pContent->cmdID->content, 1516 (UINT8 *)dm_command_name_table[SYNCML_DM_DELETE], 1517 p_delete_item, 1518 pDmMgmtSessionObj->GetNotAuthorizedStatus(), 1519 pUserData ); 1520 if (ret_stat != SYNCML_DM_SUCCESS) 1521 { 1522 sml_ret_stat = SML_ERR_UNSPECIFIC; 1523 } 1524 } 1525 1526 /* Free the memory of pContent and p_target_uri. */ 1527 smlFreeGeneric((SmlGenericCmdPtr_t)pContent); 1528 1529 return sml_ret_stat; 1530 } 1531 1532 1533 /*================================================================================================== 1534 FUNCTION : ProcessAlertCommand 1535 1536 DESCRIPTION : When the ALERT element is processed from the received message, this callback 1537 function will be called. 1538 1539 This function will perform the following operations: 1540 1) Process alert via XPL. 1541 return status for each ALERT command performed. 1542 ARGUMENT PASSED : id 1543 userData 1544 pContent 1545 OUTPUT PARAMETER: 1546 RETURN VALUE : SML_ERR_OK or ERR code 1547 IMPORTANT NOTES : 1548 1549 1550 ==================================================================================================*/ 1551 static SYNCML_DM_RET_STATUS_T 1552 ProcessAlertCommand (VoidPtr_t userData, 1553 SmlAlertPtr_t pContent, 1554 SYNCML_DM_Alert * pAlert, 1555 DMStringVector & responses) 1556 { 1557 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1558 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 1559 1560 if ( pAlert == NULL ) 1561 return SYNCML_DM_FAIL; 1562 1563 if ( pUserData->IsCommandSkipped() || pDmMgmtSessionObj->IsSessionAborted() ) 1564 return SYNCML_DM_NOT_EXECUTED; 1565 1566 pAlert->parse(pContent); 1567 dm_stat = pAlert->show(); 1568 switch ( dm_stat ) 1569 { 1570 case SYNCML_DM_SESSION_CANCELED: 1571 pDmMgmtSessionObj->SetSessionAborted(); 1572 return SYNCML_DM_SUCCESS; 1573 1574 case SYNCML_DM_SUCCESS: 1575 dm_stat = pAlert->processResponse(responses,&pUserData->alertState); 1576 break; 1577 1578 default: 1579 pUserData->alertState = SYNCML_DM_ALERT_CANCEL; 1580 break; 1581 } 1582 1583 return dm_stat; 1584 1585 } 1586 1587 1588 /*================================================================================================== 1589 FUNCTION : HandleAlertCommand 1590 1591 DESCRIPTION : When the ALERT element is processed from the received message, this callback 1592 function will be called. 1593 1594 This function will perform the following operations: 1595 1) Check the ALERT value, set the DM status accordingly. 1596 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1597 return status for each ALERT command performed. 1598 ARGUMENT PASSED : id 1599 userData 1600 pContent 1601 OUTPUT PARAMETER: 1602 RETURN VALUE : SML_ERR_OK or ERR code 1603 IMPORTANT NOTES : 1604 1605 1606 ==================================================================================================*/ 1607 Ret_t 1608 HandleAlertCommand (InstanceID_t id, 1609 VoidPtr_t userData, 1610 SmlAlertPtr_t pContent) 1611 { 1612 Ret_t sml_ret_stat = SML_ERR_OK; 1613 SYNCML_DM_RET_STATUS_T ret_stat = 0; 1614 SYNCML_DM_RET_STATUS_T dm_stat = 0; 1615 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1616 DMStringVector responses; // holds all the user responses 1617 1618 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 1619 * any management commands */ 1620 1621 if (pDmMgmtSessionObj->IsAuthorized()) 1622 { 1623 1624 UINT32 alert_code_value; 1625 1626 /* Get the data we need to work on */ 1627 1628 alert_code_value = DmAtoi((const char *)pContent->data->content); 1629 1630 /* Please refer syncml_dm_represent_v111_20021002.pdf section 8 */ 1631 switch (alert_code_value) 1632 { 1633 case DM_ALERT_SERVER_INITIATED_MGMT: 1634 case DM_ALERT_CLIENT_INITIATED_MGMT: 1635 case DM_ALERT_NEXT_MESSAGE: 1636 dm_stat = SYNCML_DM_SUCCESS; 1637 break; 1638 1639 case DM_ALERT_SESSION_ABORT: 1640 pDmMgmtSessionObj->SetSessionAborted(); 1641 dm_stat = SYNCML_DM_SUCCESS; 1642 break; 1643 1644 // handle user interaction alerts 1645 case DM_ALERT_DISPLAY: 1646 { 1647 if ( !VerifyAlertItems(pContent) ) 1648 { 1649 XPL_LOG_DM_TMN_Debug(("HandleAlertCommand, alert command items incorrect.")); 1650 dm_stat = SYNCML_DM_INCOMPLETE_COMMAND; 1651 } 1652 else { 1653 SYNCML_DM_DisplayAlert displayAlert; 1654 dm_stat = ProcessAlertCommand(userData,pContent,&displayAlert,responses); 1655 } 1656 } 1657 break; 1658 1659 case DM_ALERT_CONTINUE_OR_ABORT: 1660 { 1661 if ( !VerifyAlertItems(pContent) ) 1662 { 1663 XPL_LOG_DM_TMN_Debug(("HandleAlertCommand, alert command items incorrect.")); 1664 dm_stat = SYNCML_DM_INCOMPLETE_COMMAND; 1665 } 1666 else { 1667 SYNCML_DM_ConfirmAlert confirmAlert; 1668 dm_stat = ProcessAlertCommand(userData,pContent,&confirmAlert,responses); 1669 } 1670 } 1671 break; 1672 1673 case DM_ALERT_TEXT_INPUT: 1674 { 1675 if ( !VerifyAlertItems(pContent) ) 1676 { 1677 XPL_LOG_DM_TMN_Debug(("HandleAlertCommand, alert command items incorrect.")); 1678 dm_stat = SYNCML_DM_INCOMPLETE_COMMAND; 1679 } 1680 else { 1681 SYNCML_DM_TextInputAlert textInputAlert; 1682 dm_stat = ProcessAlertCommand(userData,pContent,&textInputAlert,responses); 1683 } 1684 } 1685 break; 1686 1687 case DM_ALERT_SINGLE_CHOICE: 1688 { 1689 SYNCML_DM_SingleChoiceAlert singleChoiceAlert; 1690 dm_stat = ProcessAlertCommand(userData,pContent,&singleChoiceAlert,responses); 1691 } 1692 break; 1693 1694 case DM_ALERT_MULTIPLE_CHOICE: 1695 { 1696 SYNCML_DM_MultipleChoiceAlert multipleChoiceAlert; 1697 dm_stat = ProcessAlertCommand(userData,pContent,&multipleChoiceAlert,responses); 1698 } 1699 break; 1700 1701 default: 1702 dm_stat = SYNCML_DM_FEATURE_NOT_SUPPORTED; /* Optional feature not supported */ 1703 break; 1704 } 1705 1706 if(pDmMgmtSessionObj->GetInAtomicCommand()) 1707 { 1708 #ifdef DM_ATOMIC_SUPPORTED 1709 // Save the data for the status and results 1710 if ( dm_stat != SYNCML_DM_SUCCESS && dm_stat != SYNCML_DM_FEATURE_NOT_SUPPORTED ) 1711 AtomicRollback(userData); 1712 #endif 1713 pUserData->oStatus.push_back( 1714 SYNCML_DM_STATUS_DATA_T((const char*)pContent->cmdID->content, 1715 dm_command_name_table[SYNCML_DM_ALERT], 1716 NULL, 1717 NULL, 1718 dm_stat, 1719 &responses) ); 1720 } 1721 else 1722 { 1723 ret_stat = SaveStatus((UINT8 *)pContent->cmdID->content, 1724 (UINT8 *)dm_command_name_table[SYNCML_DM_ALERT], 1725 NULL, 1726 NULL, 1727 dm_stat, 1728 &responses, 1729 pUserData ); 1730 if (ret_stat != SYNCML_DM_SUCCESS) 1731 { 1732 sml_ret_stat = SML_ERR_UNSPECIFIC; 1733 } 1734 } 1735 } 1736 else 1737 { 1738 1739 ret_stat = SaveStatus( 1740 (UINT8 *)pContent->cmdID->content, 1741 (UINT8 *)dm_command_name_table[SYNCML_DM_ALERT], 1742 NULL, 1743 NULL, 1744 pDmMgmtSessionObj->GetNotAuthorizedStatus(), 1745 &responses, 1746 pUserData ); 1747 if (ret_stat != SYNCML_DM_SUCCESS) 1748 sml_ret_stat = SML_ERR_UNSPECIFIC; 1749 } 1750 1751 /* Free the memory of the pContent */ 1752 smlFreeAlert(pContent); 1753 1754 return sml_ret_stat; 1755 } 1756 1757 1758 /*================================================================================================== 1759 FUNCTION : HandleExecCommand 1760 1761 DESCRIPTION : When the EXEC element is processed from the received message, this callback 1762 function will be called. 1763 1764 This function will perform the following operations: 1765 1) Call DMTree::Exec() function to perform EXEC command on the DM tree. 1766 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1767 return status for each EXEC command performed. 1768 ARGUMENT PASSED : id 1769 userData 1770 pContent 1771 OUTPUT PARAMETER: 1772 RETURN VALUE : SML_ERR_OK or ERR code 1773 IMPORTANT NOTES : 1774 1775 1776 ==================================================================================================*/ 1777 Ret_t 1778 HandleExecCommand (InstanceID_t id, 1779 VoidPtr_t userData, 1780 SmlExecPtr_t pContent) 1781 { 1782 SYNCML_DM_RET_STATUS_T dm_stat=SYNCML_DM_SUCCESS; 1783 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1784 1785 SYNCML_DM_RET_STATUS_T ret_stat = 0; 1786 SYNCML_DM_URI_RESULT_T dm_uri_result = 0; 1787 SmlItemPtr_t p_exec_item; 1788 DMString strExecUri; 1789 DMString strOriExecUri; 1790 1791 DMString execResults; 1792 DMString execData; 1793 1794 p_exec_item = pContent->item; 1795 1796 ret_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_EXEC); 1797 1798 if (ret_stat != SYNCML_DM_SUCCESS) 1799 { 1800 smlFreeExec((SmlExecPtr_t)pContent); 1801 return SML_ERR_OK; 1802 } 1803 1804 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 1805 * any management commands */ 1806 1807 /* Make sure we are not in an atomic and the Server is authenticated before performing any 1808 * DM commands.*/ 1809 if (pDmMgmtSessionObj->GetInAtomicCommand() == FALSE && 1810 pDmMgmtSessionObj->IsAuthorized()) 1811 { 1812 1813 if ((p_exec_item->target == NULL) || (p_exec_item->target->locURI == NULL)) 1814 { 1815 smlFreeExec((SmlExecPtr_t)pContent); 1816 return SML_ERR_UNSPECIFIC; 1817 } 1818 1819 strExecUri.assign((CPCHAR)p_exec_item->target->locURI->content,p_exec_item->target->locURI->length); 1820 1821 strOriExecUri = strExecUri; 1822 if(strExecUri.Decode() == FALSE) 1823 { 1824 smlFreeExec((SmlExecPtr_t)pContent); 1825 return SML_ERR_UNSPECIFIC; 1826 } 1827 /* Fill the data for p_exec_data */ 1828 if (p_exec_item->data != NULL && p_exec_item->data->length > 0) 1829 { 1830 execData.assign((CPCHAR)p_exec_item->data->content,p_exec_item->data->length); 1831 if ( execData == NULL ) 1832 { 1833 smlFreeExec((SmlExecPtr_t)pContent); 1834 return SML_ERR_UNSPECIFIC; 1835 } 1836 } 1837 1838 const char* szCorrelator = NULL; 1839 1840 if ( pContent->correlator && pContent->correlator->contentType == SML_PCDATA_STRING ) 1841 szCorrelator = (const char*)pContent->correlator->content; 1842 1843 1844 /* Validate the URI */ 1845 dm_uri_result = dmTreeObj.URIValidateAndParse(strExecUri); 1846 switch (dm_uri_result) 1847 { 1848 case SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY: 1849 case SYNCML_DM_COMMAND_INVALID_URI: 1850 case SYNCML_DM_COMMAND_URI_TOO_LONG: 1851 dm_stat = SYNCML_DM_BAD_REQUEST; 1852 break; 1853 1854 default: 1855 1856 // schen link error, code is not there 1857 // dm_stat = SYNCML_DM_FEATURE_NOT_SUPPORTED; 1858 dm_stat = dmTreeObj.Exec(strExecUri.c_str(), execData, execResults, szCorrelator); 1859 SequenceStatus(userData, dm_stat); 1860 break; 1861 } 1862 1863 } 1864 else 1865 if (pDmMgmtSessionObj->GetInAtomicCommand()) 1866 { 1867 AtomicRollback(userData); 1868 /* We don't apply commands within the Atomic.*/ 1869 dm_stat = SYNCML_DM_COMMAND_FAILED; 1870 } 1871 else 1872 dm_stat = pDmMgmtSessionObj->GetNotAuthorizedStatus(); 1873 1874 UINT8 *p_TargetRefData = NULL; 1875 if(p_exec_item->target != NULL && p_exec_item->target->locURI != NULL){ 1876 p_TargetRefData = (UINT8 *)p_exec_item->target->locURI->content; 1877 } 1878 1879 if (0 == DmStrcmp((char *)p_TargetRefData, FDR_URI)) 1880 { 1881 /* Build tha status with item tag for the EXEC command for FDR*/ 1882 ret_stat = SaveStatus((UINT8 *)pContent->cmdID->content, 1883 (UINT8 *)dm_command_name_table[SYNCML_DM_EXEC], 1884 NULL, 1885 p_TargetRefData, 1886 dm_stat, 1887 NULL, 1888 pUserData ); 1889 } 1890 else 1891 { 1892 /* Build tha status for the EXEC command */ 1893 ret_stat = SaveStatus((UINT8 *)pContent->cmdID->content, 1894 (UINT8 *)dm_command_name_table[SYNCML_DM_EXEC], 1895 NULL, 1896 NULL, 1897 dm_stat, 1898 NULL, 1899 pUserData ); 1900 1901 } 1902 1903 if (dm_stat == SYNCML_DM_SUCCESS && execResults.length() ) 1904 { 1905 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleExecCommand, inside success chk\n")); 1906 SmlResultsPtr_t p_results=NULL; /* To hold RESULTS structure */ 1907 SmlItemPtr_t p_results_item; /* To hold GET results item */ 1908 SmlItemListPtr_t p_results_list_item; /* To hold GET results list */ 1909 1910 // Allocate the memory for p_results 1911 p_results = smlAllocResults(); 1912 1913 if ( !p_results ) 1914 { 1915 smlFreeExec((SmlExecPtr_t)pContent); 1916 return SML_ERR_UNSPECIFIC; 1917 } 1918 1919 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleExecCommand, before buildpcdata\n")); 1920 pDmBuildPackage->BuildPcData(p_results->cmdRef, 1921 SML_PCDATA_STRING, 1922 SML_EXT_UNDEFINED, 1923 DmStrlen((char *)pContent->cmdID->content), 1924 (UINT8*)pContent->cmdID->content); 1925 1926 1927 /* Fill in item fileds */ 1928 p_results_list_item = p_results->itemList; 1929 1930 p_results_item = p_results_list_item->item; 1931 ret_stat = SetExecResultsData( p_results_item, strOriExecUri, execResults); 1932 pUserData->aResults.push_back( 1933 SYNCML_DM_RESULT_VALUE( SYNCML_DM_RESULT_VALUE::Enum_Result_Exec, p_results, 1934 SYNCML_DM_GET_ON_LIST_RET_DATA_T(), (CPCHAR)pContent->cmdID->content, 1935 (const char*)pDmBuildPackage->GetMsgRef()) ); 1936 } 1937 1938 1939 if (ret_stat != SYNCML_DM_SUCCESS) 1940 { 1941 smlFreeExec((SmlExecPtr_t)pContent); 1942 return SML_ERR_UNSPECIFIC; 1943 } 1944 1945 smlFreeExec((SmlExecPtr_t)pContent); 1946 1947 XPL_LOG_DM_TMN_Debug(("dm_ua_handlecommand::HandleExecCommand leaving\n")); 1948 return SML_ERR_OK; 1949 } 1950 1951 1952 /*================================================================================================== 1953 FUNCTION : HandleGetCommand 1954 1955 DESCRIPTION : When the GET element is processed from the received message, this callback 1956 function will be called. 1957 1958 This function will perform the following operations: 1959 1) Call DMTree::Get() function to perform GET command on the DM tree. 1960 2) Call BuildResultsCommand() to build the results from GET command. 1961 3) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 1962 return status for each GET command performed. 1963 ARGUMENT PASSED : id 1964 userData 1965 pContent 1966 OUTPUT PARAMETER: 1967 RETURN VALUE : SML_ERR_OK or ERR code 1968 IMPORTANT NOTES : 1969 1970 1971 ==================================================================================================*/ 1972 Ret_t 1973 HandleGetCommand (InstanceID_t id, 1974 VoidPtr_t userData, 1975 SmlGetPtr_t pContent) 1976 { 1977 DMString strTargetUri; 1978 Ret_t sml_ret_stat = SML_ERR_OK; 1979 SYNCML_DM_RET_STATUS_T dm_stat = 0; 1980 SYNCML_DM_RET_STATUS_T ret_stat = 0; 1981 DMGetData getData; 1982 1983 /* p_get_struct_data is OUTPUT parameter of dmTreeObj.InitListAndGetListFirstItem call. We 1984 need to initialize it as NULL before we pass it to the call, p_get_struct_data could not 1985 be set if the return is not SUCCESS. */ 1986 1987 SYNCML_DM_GET_ON_LIST_RET_DATA_T p_get_struct_data; 1988 SYNCML_DM_URI_RESULT_T dm_uri_result = 0; 1989 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 1990 1991 SmlItemPtr_t p_get_item; 1992 SmlItemListPtr_t p_get_list_item; 1993 1994 pDmMgmtSessionObj->IncCommandCount(); 1995 1996 /* Point the GET item to the correct spot */ 1997 p_get_list_item = pContent->itemList; 1998 p_get_item = p_get_list_item->item; 1999 2000 dm_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_GET); 2001 if (dm_stat != SYNCML_DM_SUCCESS) 2002 { 2003 ret_stat = ProcessStatus (dm_stat, 2004 userData, 2005 (UINT8*)pContent->cmdID->content, 2006 p_get_item, 2007 SYNCML_DM_GET); 2008 /* Free the memory */ 2009 smlFreeGetPut(pContent); 2010 return SML_ERR_OK; 2011 } 2012 2013 /* Make sure we are not in an atomic and the Server is authenticated before performing any 2014 * DM commands.*/ 2015 if (pDmMgmtSessionObj->GetInAtomicCommand() == FALSE && 2016 pDmMgmtSessionObj->IsAuthorized()) 2017 { 2018 2019 while (p_get_item != NULL) 2020 { /* Loop through each GET ITEM */ 2021 2022 getData.clear(); 2023 while ( true ) 2024 { 2025 DMString strTargetUri; 2026 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::HandleGet, uri=%s\n", strTargetUri.c_str())); 2027 dm_stat = PrepareCommandItem (p_get_item, 2028 pUserData, 2029 strTargetUri); 2030 if ( dm_stat != SYNCML_DM_SUCCESS ) 2031 break; 2032 2033 /* Validete the URI */ 2034 dm_uri_result = dmTreeObj.URIValidateAndParse((char*)strTargetUri.c_str()); 2035 switch (dm_uri_result) { 2036 case SYNCML_DM_COMMAND_INVALID_URI: 2037 case SYNCML_DM_COMMAND_ON_UNKNOWN_PROPERTY: 2038 case SYNCML_DM_COMMAND_URI_TOO_LONG: 2039 dm_stat = SYNCML_DM_BAD_REQUEST; 2040 break; 2041 2042 case SYNCML_DM_COMMAND_ON_NODE: 2043 case SYNCML_DM_COMMAND_ON_ACL_PROPERTY: 2044 case SYNCML_DM_COMMAND_ON_FORMAT_PROPERTY: 2045 case SYNCML_DM_COMMAND_ON_NAME_PROPERTY: 2046 case SYNCML_DM_COMMAND_ON_SIZE_PROPERTY: 2047 case SYNCML_DM_COMMAND_ON_TYPE_PROPERTY: 2048 case SYNCML_DM_COMMAND_ON_TITLE_PROPERTY: 2049 case SYNCML_DM_COMMAND_ON_TSTAMP_PROPERTY: 2050 case SYNCML_DM_COMMAND_ON_VERNO_PROPERTY: 2051 dm_stat = dmTreeObj.Get(strTargetUri.c_str(), getData,SYNCML_DM_REQUEST_TYPE_SERVER); 2052 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::HandleGet, dmTreeObj.Get=%d", dm_stat)); 2053 if (dm_stat == SYNCML_DM_SUCCESS) 2054 { 2055 dm_stat = SaveResult( strTargetUri, (const char *)pContent->cmdID->content, 2056 &getData, FALSE, FALSE, 2057 (dm_uri_result == SYNCML_DM_COMMAND_ON_NODE ? FALSE : TRUE), 2058 pUserData, SYNCML_DM_RESULT_VALUE::Enum_Result_Get, 2059 p_get_struct_data ); 2060 } 2061 break; 2062 2063 case SYNCML_DM_COMMAND_LIST_STRUCT: 2064 case SYNCML_DM_COMMAND_LIST_STRUCTDATA: 2065 case SYNCML_DM_COMMAND_LIST_TNDS: 2066 /* Call TNM to get the first item on the Get Struct results list */ 2067 { 2068 DMGetData * pGetData = NULL; 2069 DMString strTargetUriNoQuery(strTargetUri); 2070 2071 // remove query from URI 2072 char *psQPos = DmStrstr(strTargetUri, SYNCML_DM_LIST); 2073 if (psQPos != NULL) 2074 { 2075 strTargetUriNoQuery.assign(strTargetUri.c_str(), psQPos - strTargetUri.c_str()); 2076 } 2077 2078 dm_stat = dmTreeObj.InitListAndGetListFirstItem(strTargetUriNoQuery, 2079 SYNCML_DM_GET_ON_LIST_STRUCT, 2080 p_get_struct_data); 2081 2082 if (dm_stat == SYNCML_DM_SUCCESS) 2083 { 2084 UINT8 type = 0; 2085 if ( dm_uri_result == SYNCML_DM_COMMAND_LIST_STRUCT ) 2086 { 2087 type = SYNCML_DM_RESULT_VALUE::Enum_Result_GetStruct; 2088 } 2089 else if ( dm_uri_result == SYNCML_DM_COMMAND_LIST_STRUCTDATA ) 2090 { 2091 type = SYNCML_DM_RESULT_VALUE::Enum_Result_GetStructData; 2092 } 2093 else if ( dm_uri_result == SYNCML_DM_COMMAND_LIST_TNDS ) 2094 { 2095 type = SYNCML_DM_RESULT_VALUE::Enum_Result_GetTnds; 2096 } 2097 else 2098 { 2099 dm_stat = SYNCML_DM_BAD_REQUEST; 2100 break; 2101 } 2102 pGetData = p_get_struct_data.psRetData; p_get_struct_data.psRetData = NULL; 2103 dm_stat = SaveResult( strTargetUriNoQuery.c_str(), (CPCHAR)pContent->cmdID->content, 2104 pGetData, 2105 dm_uri_result == SYNCML_DM_COMMAND_LIST_STRUCT, 2106 type != SYNCML_DM_RESULT_VALUE::Enum_Result_GetTnds, 2107 FALSE, 2108 pUserData, 2109 type, 2110 p_get_struct_data); 2111 if ( pGetData ) 2112 delete pGetData; 2113 } 2114 else 2115 /* Free the memory of p_passedin_get_struct_data */ 2116 pDmBuildPackage->FreeGetStructData(p_get_struct_data); 2117 } 2118 break; 2119 default: 2120 dm_stat = SYNCML_DM_FEATURE_NOT_SUPPORTED; 2121 break; 2122 2123 } // end switch 2124 break; 2125 2126 } 2127 ret_stat = ProcessStatus (dm_stat, 2128 userData, 2129 (UINT8*)pContent->cmdID->content, 2130 p_get_item, 2131 SYNCML_DM_GET); 2132 if (ret_stat != SYNCML_DM_SUCCESS) 2133 { 2134 sml_ret_stat = SML_ERR_UNSPECIFIC; 2135 break; 2136 } 2137 2138 /* Move to the next item */ 2139 if (p_get_list_item->next != NULL) 2140 { 2141 p_get_list_item = p_get_list_item->next; 2142 p_get_item = p_get_list_item->item; 2143 } 2144 else 2145 p_get_item = NULL; 2146 } /* End of while */ 2147 2148 } 2149 else 2150 { /* !inAtomicCommand && dmSecState */ /* inAtomicCommand == TRUE || dmSecState not authenticated */ 2151 2152 if (pDmMgmtSessionObj->GetInAtomicCommand() == TRUE) 2153 { 2154 AtomicRollback(userData); 2155 dm_stat = SYNCML_DM_COMMAND_FAILED; /* We don't apply commands within the Atomic.*/ 2156 } 2157 else 2158 dm_stat = pDmMgmtSessionObj->GetNotAuthorizedStatus(); 2159 2160 ret_stat = SaveCommandRefStatus( 2161 (UINT8 *)pContent->cmdID->content, 2162 (UINT8 *)dm_command_name_table[SYNCML_DM_GET], 2163 p_get_item, 2164 dm_stat, 2165 pUserData); 2166 if (ret_stat != SYNCML_DM_SUCCESS) 2167 sml_ret_stat = SML_ERR_UNSPECIFIC; 2168 } 2169 2170 /* Free the memory */ 2171 smlFreeGetPut(pContent); 2172 pContent = NULL; 2173 2174 return (sml_ret_stat); 2175 } 2176 2177 2178 /*================================================================================================== 2179 FUNCTION : HandleReplaceCommand 2180 2181 DESCRIPTION : When the REPLACE element is processed from the received message, this callback 2182 function will be called. 2183 2184 This function will perform the following operations: 2185 1) Call DMTree::Replace() function to perform REPLACE command on the DM 2186 tree. 2187 2) Call SYNCML_DM_BuildPackage::BuildStatus() to build up the staus command with 2188 return status for each REPLACE command performed. 2189 ARGUMENT PASSED : id 2190 userData 2191 pContent 2192 OUTPUT PARAMETER: 2193 RETURN VALUE : SML_ERR_OK or ERR code 2194 IMPORTANT NOTES : 2195 2196 2197 ==================================================================================================*/ 2198 Ret_t 2199 HandleReplaceCommand (InstanceID_t id, 2200 VoidPtr_t userData, 2201 SmlReplacePtr_t pContent) 2202 { 2203 return ProcessCommand(id, userData, pContent,SYNCML_DM_REPLACE); 2204 } 2205 2206 2207 /*================================================================================================== 2208 FUNCTION : HandleStartSequenceCommand 2209 2210 DESCRIPTION : When the SEQUENCE element is processed from the received message, this callback 2211 function will be called. 2212 2213 This function will perform the following operations: 2214 2215 ARGUMENT PASSED : id 2216 userData 2217 pContent 2218 OUTPUT PARAMETER: 2219 RETURN VALUE : SML_ERR_OK or ERR code 2220 IMPORTANT NOTES : 2221 2222 2223 ==================================================================================================*/ 2224 Ret_t 2225 HandleStartSequenceCommand(InstanceID_t id, 2226 VoidPtr_t userData, 2227 SmlSequencePtr_t pContent) 2228 { 2229 Ret_t sml_ret_stat = SML_ERR_OK; 2230 SYNCML_DM_RET_STATUS_T ret_stat; 2231 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 2232 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 2233 2234 ret_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_SEQUENCE_START); 2235 2236 if (ret_stat != SYNCML_DM_SUCCESS) 2237 { 2238 /* Free the memory of pContent. Toolkit use same API to free the memory for atomic and 2239 sequence */ 2240 smlFreeAtomic((SmlAtomicPtr_t)pContent); 2241 return SML_ERR_OK; 2242 } 2243 pUserData->StartSequence(); 2244 2245 if (pDmMgmtSessionObj->IsAuthorized()) 2246 dm_stat = SYNCML_DM_SUCCESS; 2247 else 2248 dm_stat = pDmMgmtSessionObj->GetNotAuthorizedStatus(); 2249 2250 pDmMgmtSessionObj->IncCommandCount(); /* This variable is used to check if syncml document has 2251 * any management commands */ 2252 2253 /* Call the toolkit to construct the STATUS for SEQUENCE command */ 2254 ret_stat = SaveStatus( 2255 (UINT8 *)pContent->cmdID->content, 2256 (UINT8 *)dm_command_name_table[SYNCML_DM_SEQUENCE], 2257 NULL, 2258 NULL, 2259 dm_stat, 2260 NULL, 2261 pUserData ); 2262 2263 if (ret_stat != SYNCML_DM_SUCCESS) 2264 { 2265 sml_ret_stat = SML_ERR_UNSPECIFIC; 2266 } 2267 2268 /* Free the memory of pContent. Toolkit use same API to free the memory for atomic and 2269 sequence */ 2270 smlFreeAtomic((SmlAtomicPtr_t)pContent); 2271 2272 return sml_ret_stat; 2273 } 2274 2275 /*================================================================================================== 2276 FUNCTION : HandleEndSequenceCommand 2277 2278 DESCRIPTION : When the SEQUENCE element is processed from the received message, this callback 2279 function will be called. 2280 2281 This function will perform the following operations: 2282 2283 ARGUMENT PASSED : id 2284 userData 2285 OUTPUT PARAMETER: 2286 RETURN VALUE : SML_ERR_OK or ERR code 2287 IMPORTANT NOTES : 2288 2289 2290 ==================================================================================================*/ 2291 Ret_t 2292 HandleEndSequenceCommand(InstanceID_t id, 2293 VoidPtr_t userData) 2294 { 2295 /* We don't need to do anything special for the End Sequence.*/ 2296 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 2297 2298 if(pUserData) 2299 pUserData->EndSequence(); 2300 return SML_ERR_OK; 2301 } 2302 2303 2304 2305 /*================================================================================================== 2306 FUNCTION : HandleStartAtomicCommand 2307 2308 DESCRIPTION : When the ATOMIC element is processed from the received message, this callback 2309 function will be called. 2310 2311 This function will perform the following operations: 2312 2313 ARGUMENT PASSED : id 2314 userData 2315 pContent 2316 OUTPUT PARAMETER: 2317 RETURN VALUE : SML_ERR_OK or ERR code 2318 IMPORTANT NOTES : 2319 2320 2321 ==================================================================================================*/ 2322 Ret_t 2323 HandleStartAtomicCommand(InstanceID_t id, 2324 VoidPtr_t userData, 2325 SmlAtomicPtr_t pContent) 2326 { 2327 Ret_t sml_ret_stat = SML_ERR_OK; 2328 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 2329 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 2330 2331 dm_stat = pDmBuildPackage->GenerateAlertForLOB(DM_COMMAND_ATOMIC_START); 2332 2333 if (dm_stat != SYNCML_DM_SUCCESS) 2334 { 2335 smlFreeAtomic(pContent ); 2336 return SML_ERR_OK; 2337 } 2338 2339 if (pDmMgmtSessionObj->IsAuthorized()) 2340 { 2341 if(pDmMgmtSessionObj->GetInAtomicCommand()) 2342 { // nested atomics are not allowed 2343 SaveStatus((UINT8 *)pContent->cmdID->content, 2344 (UINT8 *)dm_command_name_table[SYNCML_DM_ATOMIC], 2345 NULL, 2346 NULL, 2347 SYNCML_DM_COMMAND_FAILED, 2348 NULL, 2349 pUserData); 2350 smlFreeAtomic(pContent ); 2351 return sml_ret_stat; 2352 } 2353 2354 dm_stat=dmTreeObj.GetLockContextManager().ReleaseIDInternal(SYNCML_DM_LOCKID_CURRENT, SYNCML_DM_ATOMIC); 2355 2356 if ( dm_stat != SYNCML_DM_SUCCESS && dm_stat != SYNCML_DM_FEATURE_NOT_SUPPORTED ) 2357 { 2358 smlFreeAtomic(pContent ); 2359 return SML_ERR_UNSPECIFIC; 2360 } 2361 2362 /* Remember that we are in an Atomic command.*/ 2363 pDmMgmtSessionObj->SetInAtomicCommand(TRUE); 2364 2365 // Save the data for the status 2366 pUserData->pAtomicStatus.bValueSet = TRUE; 2367 pUserData->pAtomicStatus.pCmdId = (CPCHAR)pContent->cmdID->content; 2368 pUserData->pAtomicStatus.pCmdName = dm_command_name_table[SYNCML_DM_ATOMIC]; 2369 pUserData->pAtomicStatus.status = dm_stat; 2370 } 2371 else 2372 { 2373 dm_stat = SaveStatus((UINT8 *)pContent->cmdID->content, 2374 (UINT8 *)dm_command_name_table[SYNCML_DM_ATOMIC], 2375 NULL, 2376 NULL, 2377 pDmMgmtSessionObj->GetNotAuthorizedStatus(), 2378 NULL, 2379 pUserData); 2380 if (dm_stat != SYNCML_DM_SUCCESS) 2381 sml_ret_stat = SML_ERR_UNSPECIFIC; 2382 } 2383 smlFreeAtomic(pContent ); 2384 return sml_ret_stat; 2385 } 2386 2387 2388 /*================================================================================================== 2389 FUNCTION : HandleEndAtomicCommand 2390 2391 DESCRIPTION : When the End ATOMIC element is processed from the received message, this callback 2392 function will be called. 2393 2394 This function will perform the following operations: 2395 2396 ARGUMENT PASSED : id 2397 userData 2398 OUTPUT PARAMETER: 2399 RETURN VALUE : SML_ERR_OK or ERR code 2400 IMPORTANT NOTES : 2401 2402 2403 ==================================================================================================*/ 2404 Ret_t 2405 HandleEndAtomicCommand(InstanceID_t id, 2406 VoidPtr_t userData) 2407 { 2408 Ret_t sml_ret_stat = SML_ERR_OK; 2409 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 2410 SYNCML_DM_RET_STATUS_T retStatus=SYNCML_DM_SUCCESS; 2411 2412 if (pDmMgmtSessionObj->IsAuthorized()) 2413 { 2414 pDmMgmtSessionObj->SetInAtomicCommand(FALSE); 2415 2416 if ( !pUserData->rollback ) 2417 { 2418 retStatus=dmTreeObj.GetLockContextManager().ReleaseIDInternal(SYNCML_DM_LOCKID_CURRENT, SYNCML_DM_COMMIT); 2419 2420 if ( retStatus != SYNCML_DM_SUCCESS && retStatus != SYNCML_DM_FEATURE_NOT_SUPPORTED) 2421 return SML_ERR_UNSPECIFIC; 2422 } 2423 2424 /* We are now out of the Atomic command.*/ 2425 UINT8 *p_SourceRefData = !pUserData->pAtomicStatus.pSource.empty() ? 2426 (UINT8 *)(pUserData->pAtomicStatus.pSource.c_str()) : NULL; 2427 UINT8 *p_TargetRefData = !pUserData->pAtomicStatus.pTarget.empty() ? 2428 (UINT8 *)pUserData->pAtomicStatus.pTarget.c_str() : NULL; 2429 2430 retStatus = SaveStatus((UINT8 *)pUserData->pAtomicStatus.pCmdId.c_str(), 2431 (UINT8 *)pUserData->pAtomicStatus.pCmdName.c_str(), 2432 p_SourceRefData, 2433 p_TargetRefData, 2434 pUserData->pAtomicStatus.status, 2435 NULL, 2436 pUserData); 2437 2438 if (retStatus != SYNCML_DM_SUCCESS) 2439 sml_ret_stat = SML_ERR_UNSPECIFIC; 2440 2441 for ( int i = 0; i <pUserData->oStatus.size(); i++ ) 2442 { 2443 const SYNCML_DM_STATUS_DATA_T& ptrStatus = pUserData->oStatus[i]; 2444 2445 UINT8 *p_SourceRefData = !ptrStatus.pSource.empty() ? 2446 (UINT8 *)(ptrStatus.pSource.c_str()) : NULL; 2447 retStatus = SaveStatus((UINT8 *)ptrStatus.pCmdId.c_str(), 2448 (UINT8 *)ptrStatus.pCmdName.c_str(), 2449 p_SourceRefData, 2450 (UINT8 *)ptrStatus.pTarget.c_str(), 2451 ptrStatus.status, 2452 &ptrStatus.responses, 2453 pUserData); 2454 2455 if (retStatus != SYNCML_DM_SUCCESS) 2456 sml_ret_stat = SML_ERR_UNSPECIFIC; 2457 } 2458 2459 pUserData->EndAtomic(); 2460 } 2461 2462 return sml_ret_stat; 2463 } 2464 2465 2466 /*================================================================================================== 2467 FUNCTION : HandleStatusCommand 2468 2469 DESCRIPTION : When the STATUS element is processed from the received message, this callback 2470 function will be called. 2471 2472 This function will perform the following operations: 2473 1) Check the status code. 2474 2) Call TNMTree::Replace() to replace the nonce value. 2475 3) Update the UserAgent's Security state based on the client authentication 2476 status received from the server. 2477 4) Call SYNCML_DM_BuildPackage::BuildFinishSyncHdr() to finish our SyncHdr 2478 5) Determine if we need to Challenge the server 2479 6) Call SYNCML_DM_BuildPackage::BuildStatus() to build up our first status 2480 which contains our server authentication disposition. 2481 2482 ARGUMENT PASSED : id 2483 userData 2484 pContent 2485 OUTPUT PARAMETER: 2486 RETURN VALUE : SML_ERR_OK or ERR code 2487 IMPORTANT NOTES : 2488 2489 2490 ==================================================================================================*/ 2491 Ret_t 2492 HandleStatusCommand (InstanceID_t id, 2493 VoidPtr_t userData, 2494 SmlStatusPtr_t pContent) 2495 { 2496 SYNCML_DM_USER_DATA_T *pUserData = (SYNCML_DM_USER_DATA_T *)userData; 2497 Ret_t sml_ret_stat = SML_ERR_OK; 2498 SYNCML_DM_RET_STATUS_T ret_stat; 2499 SYNCML_DM_RET_STATUS_T local_dm_stat = SYNCML_DM_SUCCESS; 2500 UINT8 *pClientNonce = NULL; 2501 UINT8 *pServerNonce = NULL; 2502 UINT8 *p_auth = NULL; 2503 SYNCML_DM_RET_STATUS_T clientAuthStatus; 2504 SYNCML_DM_RET_STATUS_T serverStatus; 2505 SYNCML_DM_CHAL_TYPE_T serverChalType = SYNCML_DM_CHAL_NONE; 2506 UINT8 command_id_str[UINT16_TYPE_STR_SIZE_5] = "0"; 2507 /* command_id_str reference should be "0" for header */ 2508 DM_CHALLENGE_T *pClientChal = NULL; 2509 DMClientServerCreds *pClientServerCreds; 2510 SYNCML_DM_SEC_STATE_FLAG_T currSecState; 2511 SYNCMLDM_NONCE_STRING_INFO_T *pNonceStruct = NULL; 2512 SYNCMLDM_NONCE_GENERATE_PARAMETER_INFO_T nonceInfo; 2513 SmlMetInfMetInfPtr_t p_meta_info = NULL; 2514 2515 /* First check if this status is for the "SyncHdr".*/ 2516 if (DmStrncmp((char *)pContent->cmd->content, SYNCML_SYNCHDR, pContent->cmd->length) == 0) 2517 { 2518 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::handleStatusCommand, synchdr command ref:%s\n\n", (char*)pContent->cmdRef->content)); 2519 /* Get the Client and Server Cred info and current Security state.*/ 2520 pClientServerCreds = pDmMgmtSessionObj->GetClientServerCreds(); 2521 currSecState = pDmMgmtSessionObj->GetSecState(); 2522 2523 // DP: if we have postponed nonce - save it 2524 if ( pUserData->bNonceGenerated ) 2525 { 2526 pUserData->bNonceGenerated = FALSE; 2527 if ( pClientServerCreds && pClientServerCreds->pServerNonce ) 2528 { 2529 if ( dmTreeObj.IsVersion_12() ) 2530 pClientServerCreds->SaveServerAttribute(DM_AAUTHDATA, pClientServerCreds->pServerNonce); 2531 else 2532 pClientServerCreds->SaveServerAttribute(DM_SERVERNONCE, pClientServerCreds->pServerNonce); 2533 } 2534 } 2535 2536 /* We must check the new Status value from the Server in case our Security State changed.*/ 2537 p_auth = (UINT8 *)DmAllocMem(pContent->data->length+1); 2538 if ( p_auth == NULL ) 2539 return SYNCML_DM_DEVICE_FULL; 2540 DmStrncpy((char *)p_auth, 2541 (const char *)pContent->data->content, 2542 pContent->data->length); 2543 p_auth[pContent->data->length] = '\0'; 2544 2545 /* We always need to check the clientAuthStatus since we send creds on every message.*/ 2546 clientAuthStatus = SyncML2DMCode((char *)p_auth); 2547 DmFreeMem(p_auth); 2548 2549 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::handleStatusCommand, synchdr command clientAuthStatus: %d\n\n", clientAuthStatus)); 2550 2551 if (clientAuthStatus == SYNCML_DM_AUTHENTICATION_REQUIRED) 2552 { 2553 return clientAuthStatus; 2554 } 2555 2556 /* Update the client retry count */ 2557 if (clientAuthStatus == SYNCML_DM_AUTHENTICATION_ACCEPTED || 2558 clientAuthStatus == SYNCML_DM_SUCCESS) 2559 { 2560 /* Reset client retry count when client is authenticated */ 2561 pDmMgmtSessionObj->SetClientRetryCount(0); 2562 2563 // Save authPref value if needed 2564 pClientServerCreds->SaveAuthPref(); 2565 } 2566 else 2567 { 2568 /* Increment the retry count when client is not authenticated.*/ 2569 pDmMgmtSessionObj->IncClientRetryCount(); 2570 } 2571 2572 /* Update the security state with the client authentication status. Note that we only 2573 * check for cases that cause a change in the SecurityState. 2574 */ 2575 switch (currSecState) 2576 { 2577 case DM_CLIENT_NO_SERVER_NO_AUTH: 2578 if (clientAuthStatus == SYNCML_DM_AUTHENTICATION_ACCEPTED || 2579 clientAuthStatus == SYNCML_DM_SUCCESS) 2580 { 2581 currSecState = DM_CLIENT_Y_SERVER_NO_AUTH; 2582 } 2583 break; 2584 2585 case DM_CLIENT_NO_SERVER_Y_AUTH: 2586 if (clientAuthStatus == SYNCML_DM_AUTHENTICATION_ACCEPTED || 2587 clientAuthStatus == SYNCML_DM_SUCCESS) 2588 { 2589 currSecState = DM_BOTH_CLIENT_SERVER_AUTH; 2590 } 2591 break; 2592 2593 case DM_CLIENT_Y_SERVER_NO_AUTH: 2594 if (clientAuthStatus != SYNCML_DM_AUTHENTICATION_ACCEPTED && 2595 clientAuthStatus != SYNCML_DM_SUCCESS) 2596 { 2597 currSecState = DM_CLIENT_NO_SERVER_NO_AUTH; 2598 } 2599 break; 2600 2601 case DM_BOTH_CLIENT_SERVER_AUTH: 2602 if (clientAuthStatus != SYNCML_DM_AUTHENTICATION_ACCEPTED && 2603 clientAuthStatus != SYNCML_DM_SUCCESS) 2604 { 2605 currSecState = DM_CLIENT_NO_SERVER_Y_AUTH; 2606 } 2607 break; 2608 } 2609 2610 /* Update the UserAgent Security state in case it changed.*/ 2611 pDmMgmtSessionObj->SetSecState(currSecState); 2612 2613 if ((pContent->chal != NULL) && (pContent->chal->meta != NULL)) 2614 { 2615 /* We were challenged in the SyncHdr, so we need to build our creditials in the package.*/ 2616 if (currSecState == DM_CLIENT_NO_SERVER_NO_AUTH || 2617 currSecState == DM_CLIENT_NO_SERVER_Y_AUTH) 2618 { 2619 /* If the client has not been authenticated yet, increment the commandCount so 2620 * we'll still respond even if there are no other operational commmands. 2621 * But if the client has already been authenticated, then we won't increment since 2622 * this may be the end of the session. In that case, the nonce will be used 2623 * in the next session. 2624 */ 2625 pDmMgmtSessionObj->IncCommandCount(); 2626 } 2627 2628 p_meta_info = (sml_metinf_metinf_s *)pContent->chal->meta->content; 2629 2630 /* Check the Type.*/ 2631 if (p_meta_info->type != NULL) 2632 { 2633 /* Check which type of challenge was sent.*/ 2634 if (smlLibStrncmp((char *)p_meta_info->type->content, SYNCML_AUTH_MAC, 2635 p_meta_info->type->length) == 0) 2636 { 2637 /* We received a challenge for HMAC-MD5.*/ 2638 serverChalType = SYNCML_DM_CHAL_HMAC; 2639 } 2640 else if (smlLibStrncmp((char *)p_meta_info->type->content, SYNCML_AUTH_MD5, 2641 p_meta_info->type->length) == 0) 2642 { 2643 /* We received a challenge for MD5.*/ 2644 serverChalType = SYNCML_DM_CHAL_MD5; 2645 } 2646 else 2647 { 2648 /* We received a challenge for Basic security.*/ 2649 serverChalType = SYNCML_DM_CHAL_BASIC; 2650 } 2651 } 2652 2653 // DP switch to new auth type if needed 2654 if ( dmTreeObj.IsVersion_12() ) 2655 { 2656 local_dm_stat = pClientServerCreds->SetPrefClientAuth(serverChalType); 2657 if ( local_dm_stat != SYNCML_DM_SUCCESS ) 2658 { 2659 pDmMgmtSessionObj->SetClientRetryCount(MAX_AUTH_RETRY+1); 2660 } 2661 } 2662 /* Get the nextnonce sent to us from the server.*/ 2663 if (p_meta_info->nextnonce != NULL) 2664 { 2665 pClientNonce = (UINT8 *)DmAllocMem(p_meta_info->nextnonce->length + 1); 2666 if ( pClientNonce == NULL ) 2667 return SYNCML_DM_DEVICE_FULL; 2668 memcpy(pClientNonce, 2669 p_meta_info->nextnonce->content, 2670 p_meta_info->nextnonce->length); 2671 pClientNonce[p_meta_info->nextnonce->length] = '\0'; 2672 2673 /* Save the new ClientNonce in the Tree.*/ 2674 if ( dmTreeObj.IsVersion_12() ) 2675 local_dm_stat = pClientServerCreds->SaveClientAttribute(DM_AAUTHDATA, (CPCHAR)pClientNonce); 2676 else 2677 local_dm_stat = pClientServerCreds->SaveClientAttribute(DM_CLIENTNONCE, (CPCHAR)pClientNonce); 2678 /* Note that we continue even if we failed to store the clientNonce.*/ 2679 pClientServerCreds->pClientNonce = (const char*)pClientNonce; 2680 DmFreeMem(pClientNonce); 2681 2682 /* Note that we continue even if we failed to store the clientNonce.*/ 2683 } 2684 } /* If chal != NULL */ 2685 2686 /* Call the method to finish our SyncHdr and start the toolkit message.*/ 2687 ret_stat = pDmBuildPackage->BuildFinishSyncHdr(serverChalType); 2688 if (ret_stat != SYNCML_DM_SUCCESS) 2689 { 2690 sml_ret_stat = SML_ERR_UNSPECIFIC; 2691 synchdr_dm_stat = SYNCML_DM_BAD_REQUEST; 2692 } 2693 2694 /* Determine if we need to challenge the server. Note that we will challange 2695 * the Server even if it has already been authenticated (hmac/md5 only).*/ 2696 if ( (currSecState == DM_CLIENT_NO_SERVER_NO_AUTH || 2697 currSecState == DM_CLIENT_Y_SERVER_NO_AUTH) && 2698 pClientServerCreds->ServerChalType > SYNCML_DM_CHAL_BASIC ) 2699 { // generate new nonce if required 2700 DMGetData devID; 2701 /* First we need to generate a new nextNonce for the server.*/ 2702 nonceInfo.pb_user_name = (UINT8*)pClientServerCreds->pClientUserName.c_str(); 2703 nonceInfo.pb_password = (UINT8*)pClientServerCreds->pServerPW.c_str(); 2704 nonceInfo.pb_server_id = (UINT8*)pClientServerCreds->pServerId.c_str(); 2705 2706 dmTreeObj.Get(DM_DEV_INFO_DEVID_URI, devID,SYNCML_DM_REQUEST_TYPE_INTERNAL); 2707 2708 pNonceStruct = syncmldm_sec_generate_nonce(&nonceInfo,devID.getCharData()); 2709 if ( pNonceStruct == NULL ) 2710 { 2711 return SYNCML_DM_COMMAND_FAILED; 2712 } 2713 2714 /* Copy the new Server Nonce.*/ 2715 pServerNonce = (UINT8 *)DmAllocMem(pNonceStruct->w_nonce_string_length + 1); 2716 if ( pServerNonce == NULL ) 2717 { 2718 DmFreeMem(pNonceStruct); 2719 return SYNCML_DM_DEVICE_FULL; 2720 } 2721 memcpy(pServerNonce, pNonceStruct->ab_nonce_string, 2722 pNonceStruct->w_nonce_string_length); 2723 pServerNonce[pNonceStruct->w_nonce_string_length] = '\0'; 2724 2725 /* Store the new ServerNonce in the Tree.*/ 2726 // DP: don't save nonce in the tree yet, since server answer can be empty packet and 2727 // we can end session without sending it to the server 2728 pUserData->bNonceGenerated = TRUE; 2729 DmFreeMem(pNonceStruct); 2730 2731 /* Note we continue even if we failed to store the serverNonce.*/ 2732 pClientServerCreds->pServerNonce = (const char*)pServerNonce; 2733 DmFreeMem(pServerNonce); 2734 } 2735 2736 if (currSecState == DM_CLIENT_NO_SERVER_NO_AUTH || 2737 currSecState == DM_CLIENT_Y_SERVER_NO_AUTH || 2738 pClientServerCreds->ServerChalType >= SYNCML_DM_CHAL_MD5 ) { // no authenticated or needs chal 2739 /* Setup the Client Challenge information.*/ 2740 pClientChal = (DM_CHALLENGE_T *)DmAllocMem(sizeof(DM_CHALLENGE_T)); 2741 if ( pClientChal == NULL ) 2742 { 2743 return SYNCML_DM_DEVICE_FULL; 2744 } 2745 2746 if ( pClientServerCreds->ServerChalType == SYNCML_DM_CHAL_HMAC ) 2747 pClientChal->pChalType = (UINT8 *) SYNCML_AUTH_MAC; 2748 else if ( pClientServerCreds->ServerChalType == SYNCML_DM_CHAL_MD5 ) 2749 pClientChal->pChalType = (UINT8 *) SYNCML_AUTH_MD5; 2750 else 2751 pClientChal->pChalType = (UINT8 *) SYNCML_AUTH_BASIC; 2752 2753 pClientChal->pChalFormat = (UINT8 *)SYNCML_B64; 2754 pClientChal->pChalNonce = pClientServerCreds->ServerChalType >= SYNCML_DM_CHAL_MD5 ? 2755 (UINT8*)pClientServerCreds->pServerNonce.c_str() : NULL; 2756 } 2757 2758 /* Set the Server's authentication status.*/ 2759 if (currSecState == DM_CLIENT_NO_SERVER_NO_AUTH || 2760 currSecState == DM_CLIENT_Y_SERVER_NO_AUTH) 2761 synchdr_dm_stat = pDmMgmtSessionObj->GetNotAuthorizedStatus(); 2762 2763 /* Now that our SyncHdr is header is closed, we need to create our first status. 2764 * Call the toolkit to construct STATUS for SyncHdr */ 2765 SmlStatusPtr_t pStatus = pDmBuildPackage->AllocateStatus( 2766 command_id_str, 2767 (UINT8 *)dm_command_name_table[SYNCML_DM_HEADER], 2768 NULL, /* Source URI, it's not needed for SyncHdr STATUS */ 2769 NULL, /* Target URI, it's not needed for SyncHdr STATUS */ 2770 pClientChal, 2771 synchdr_dm_stat, NULL ); 2772 if ( pStatus ) { 2773 ret_stat = pDmBuildPackage->BuildStatus( pStatus ); 2774 smlFreeStatus(pStatus); 2775 } 2776 else 2777 ret_stat = SYNCML_DM_FAIL; 2778 2779 DmFreeMem(pClientChal); 2780 2781 if (ret_stat != SYNCML_DM_SUCCESS) 2782 { 2783 sml_ret_stat = SML_ERR_UNSPECIFIC; 2784 } 2785 } /* SyncHdr check */ 2786 2787 /* Check if this Status is for our "Replace" command (Our DevInfo) */ 2788 else if (DmStrncmp((char *)pContent->cmd->content, SYNCML_REPLACE, pContent->cmd->length) == 0) 2789 { 2790 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::handleStatusCommand, replace command ref:%s\n\n", (char*)pContent->cmdRef->content)); 2791 /* Determine the serverStatus for our DevInfo.*/ 2792 p_auth = (UINT8 *)DmAllocMem(pContent->data->length+1); 2793 if ( p_auth == NULL ) 2794 { 2795 return SYNCML_DM_DEVICE_FULL; 2796 } 2797 DmStrncpy((char *)p_auth, 2798 (const char *)pContent->data->content, 2799 pContent->data->length); 2800 p_auth[pContent->data->length] = '\0'; 2801 serverStatus = SyncML2DMCode((char *)p_auth); 2802 DmFreeMem(p_auth); 2803 2804 /* We only resend the DevInfo in the case of Authentication failure.*/ 2805 if (serverStatus == SYNCML_DM_UNAUTHORIZED) 2806 { 2807 /* Call the method to build our DevInfo into the REPLACE command for this package. */ 2808 ret_stat = pDmBuildPackage->BuildReplaceCommand(); 2809 if (ret_stat != SYNCML_DM_SUCCESS) 2810 { 2811 sml_ret_stat = SML_ERR_UNSPECIFIC; 2812 } 2813 } 2814 else if (serverStatus == SYNCML_DM_AUTHENTICATION_REQUIRED) 2815 { 2816 return serverStatus; 2817 } 2818 } /* Replace check */ 2819 2820 /* Check if this Status is for our "Alert" command (Our SessionDirection) */ 2821 else if (DmStrncmp((char *)pContent->cmd->content, SYNCML_ALERT, pContent->cmd->length) == 0 && 2822 DmStrncmp((char *)pContent->cmdRef->content, "1", pContent->cmdRef->length) == 0) 2823 { 2824 XPL_LOG_DM_TMN_Debug(("\ninside dm_ua_handlecommand::handleStatusCommand, alert command ref:%s\n\n", (char*)pContent->cmdRef->content)); 2825 /* Determine the serverStatus for our Alert (Session Direction).*/ 2826 p_auth = (UINT8 *)DmAllocMem(pContent->data->length+1); 2827 if ( p_auth == NULL ) 2828 { 2829 return SYNCML_DM_DEVICE_FULL; 2830 } 2831 DmStrncpy((char *)p_auth, 2832 (const char *)pContent->data->content, 2833 pContent->data->length); 2834 p_auth[pContent->data->length] = '\0'; 2835 serverStatus = SyncML2DMCode((char *)p_auth); 2836 DmFreeMem(p_auth); 2837 2838 /* We only resend the DevInfo in the case of Authentication failure.*/ 2839 if (serverStatus == SYNCML_DM_UNAUTHORIZED) 2840 { 2841 /* Call the method to build our DevInfo into the REPLACE command for this package. */ 2842 ret_stat = pDmBuildPackage->BuildAlertCommand(pDmBuildPackage->getDirection(), NULL, NULL); 2843 if (ret_stat != SYNCML_DM_SUCCESS) 2844 { 2845 sml_ret_stat = SML_ERR_UNSPECIFIC; 2846 } 2847 /* Call the method to build 1226 command for this package. */ 2848 ret_stat = pDmBuildPackage->BuildAlert1226Command(); 2849 if (ret_stat != SYNCML_DM_SUCCESS) 2850 { 2851 sml_ret_stat = SML_ERR_UNSPECIFIC; 2852 } 2853 } 2854 else if (serverStatus == SYNCML_DM_AUTHENTICATION_REQUIRED) 2855 { 2856 return serverStatus; 2857 } 2858 } /* Replace check */ 2859 2860 /* Free the memory we allocated. */ 2861 smlFreeStatus(pContent); 2862 2863 return sml_ret_stat; 2864 } 2865 2866 bool VerifyAlertItems(SmlAlertPtr_t pContent) 2867 { 2868 if ( pContent == NULL ) 2869 { 2870 return false; 2871 } 2872 2873 // Verify first alert item is not NULL. 2874 SmlItemListPtr_t p_alert_list_item; 2875 p_alert_list_item = pContent->itemList; 2876 if (p_alert_list_item == NULL) 2877 { 2878 return false; 2879 } 2880 2881 SmlItemPtr_t p_alert_item; 2882 p_alert_item = p_alert_list_item->item; 2883 if (p_alert_item == NULL) 2884 { 2885 return false; 2886 } 2887 2888 // Verify second alert item is not NULL. 2889 p_alert_list_item = p_alert_list_item->next; 2890 if (p_alert_list_item == NULL) 2891 { 2892 return false; 2893 } 2894 2895 p_alert_item = p_alert_list_item->item; 2896 if (p_alert_item == NULL) 2897 { 2898 return false; 2899 } 2900 2901 // Verify no more than 2 items are specified in alert. 2902 p_alert_list_item = p_alert_list_item->next; 2903 if (p_alert_list_item != NULL) 2904 { 2905 return false; 2906 } 2907 2908 return true; 2909 } 2910