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
43extern "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 */
54static 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
70static SYNCML_DM_BuildPackage *pDmBuildPackage;
71static 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. */
76static SYNCML_DM_RET_STATUS_T synchdr_dm_stat = SYNCML_DM_SUCCESS;
77
78static 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==================================================================================================*/
88static 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/*==================================================================================================
105FUNCTION        : SetMetaData
106
107DESCRIPTION     : The utility function to set up the meta data.
108
109ARGUMENT PASSED : p_meta_info
110OUTPUT PARAMETER: pp_type
111                  p_format
112RETURN VALUE    : SML_ERR_OK or ERR code
113IMPORTANT NOTES :
114
115
116==================================================================================================*/
117SYNCML_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/*==================================================================================================
177FUNCTION        : SetExecResultsData
178
179DESCRIPTION     : The utility function to set up the results data for Exec command.
180
181ARGUMENT PASSED : p_passedin_result_item. p_target_uri
182                  p_exec_ret_data
183OUTPUT PARAMETER: p_passedin_result_item
184
185RETURN VALUE    : SML_ERR_OK or ERR code
186IMPORTANT NOTES :
187
188
189==================================================================================================*/
190Ret_t
191SetExecResultsData(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
235static 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
255static SYNCML_DM_RET_STATUS_T
256SaveCommandRefStatus(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
293static 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
342static 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
367static 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
378static 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/*==================================================================================================
485FUNCTION        : HandleEndMessage
486
487DESCRIPTION     : This method calls SyncML Toolkit smlEndMessage to add the Final element in the
488                  SyncBody for the sending message.
489ARGUMENT PASSED : id
490                  userData
491                  final
492OUTPUT PARAMETER:
493RETURN VALUE    : SML_ERR_OK or ERR code
494IMPORTANT NOTES :
495
496
497==================================================================================================*/
498
499Ret_t
500HandleEndMessage (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
522if( !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/*==================================================================================================
584FUNCTION        : VerifyProtocolVersion
585
586DESCRIPTION     :
587ARGUMENT PASSED : pContent
588OUTPUT PARAMETER:
589RETURN VALUE    : SYNCML_DM_SUCCESS or SYNCML_DM_FAIL code
590IMPORTANT NOTES :
591
592
593==================================================================================================*/
594SYNCML_DM_RET_STATUS_T
595VerifyProtocolVersion( 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/*==================================================================================================
621FUNCTION        : HandleStartMessage
622
623DESCRIPTION     : This function should analyze SyncHeader data from received DM document, and build
624                  responding SyncML header.
625ARGUMENT PASSED : id
626                  userData
627                  pContent
628OUTPUT PARAMETER:
629RETURN VALUE    : SML_ERR_OK or ERR code
630IMPORTANT NOTES :
631
632
633==================================================================================================*/
634Ret_t
635HandleStartMessage (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/*==================================================================================================
772FUNCTION        : PrepareCommandItem
773
774DESCRIPTION     : Check if command should be skipped and decode item URI
775
776ARGUMENT PASSED :
777                  userData
778                  pContent
779                  command
780OUTPUT PARAMETER:
781RETURN VALUE    : SML_ERR_OK or ERR code
782IMPORTANT NOTES :
783
784
785==================================================================================================*/
786static SYNCML_DM_RET_STATUS_T
787PrepareCommandItem (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/*==================================================================================================
813FUNCTION        : ProcessStatus
814
815DESCRIPTION     : Process status of operationd
816
817ARGUMENT PASSED :
818                  userData
819                  pContent
820                  command
821OUTPUT PARAMETER:
822RETURN VALUE    : SML_ERR_OK or ERR code
823IMPORTANT NOTES :
824
825
826==================================================================================================*/
827
828static SYNCML_DM_RET_STATUS_T
829ProcessStatus (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
896SYNCML_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
1028SYNCML_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/*==================================================================================================
1085FUNCTION        : ProcessCommand
1086
1087DESCRIPTION     : 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.
1093ARGUMENT PASSED : id
1094                  userData
1095                  pContent
1096                  command
1097OUTPUT PARAMETER:
1098RETURN VALUE    : SML_ERR_OK or ERR code
1099IMPORTANT NOTES :
1100
1101
1102==================================================================================================*/
1103Ret_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/*==================================================================================================
1329FUNCTION        : HandleAddCommand
1330
1331DESCRIPTION     : 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.
1338ARGUMENT PASSED : id
1339                  userData
1340                  pContent
1341OUTPUT PARAMETER:
1342RETURN VALUE    : SML_ERR_OK or ERR code
1343IMPORTANT NOTES :
1344
1345
1346==================================================================================================*/
1347Ret_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/*==================================================================================================
1354FUNCTION        : HandleCopyCommand
1355
1356DESCRIPTION     : 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.
1363ARGUMENT PASSED : id
1364                  userData
1365                  pContent
1366OUTPUT PARAMETER:
1367RETURN VALUE    : SML_ERR_OK or ERR code
1368IMPORTANT NOTES :
1369
1370
1371==================================================================================================*/
1372Ret_t
1373HandleCopyCommand (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/*==================================================================================================
1407FUNCTION        : HandleDeleteCommand
1408
1409DESCRIPTION     : 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.
1416ARGUMENT PASSED : id
1417                  userData
1418                  pContent
1419OUTPUT PARAMETER:
1420RETURN VALUE    : SML_ERR_OK or ERR code
1421IMPORTANT NOTES :
1422
1423
1424==================================================================================================*/
1425Ret_t
1426HandleDeleteCommand (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/*==================================================================================================
1534FUNCTION        : ProcessAlertCommand
1535
1536DESCRIPTION     : 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.
1542ARGUMENT PASSED : id
1543                  userData
1544                  pContent
1545OUTPUT PARAMETER:
1546RETURN VALUE    : SML_ERR_OK or ERR code
1547IMPORTANT NOTES :
1548
1549
1550==================================================================================================*/
1551static SYNCML_DM_RET_STATUS_T
1552ProcessAlertCommand (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/*==================================================================================================
1589FUNCTION        : HandleAlertCommand
1590
1591DESCRIPTION     : 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.
1598ARGUMENT PASSED : id
1599                  userData
1600                  pContent
1601OUTPUT PARAMETER:
1602RETURN VALUE    : SML_ERR_OK or ERR code
1603IMPORTANT NOTES :
1604
1605
1606==================================================================================================*/
1607Ret_t
1608HandleAlertCommand (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/*==================================================================================================
1759FUNCTION        : HandleExecCommand
1760
1761DESCRIPTION     : 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.
1768ARGUMENT PASSED : id
1769                  userData
1770                  pContent
1771OUTPUT PARAMETER:
1772RETURN VALUE    : SML_ERR_OK or ERR code
1773IMPORTANT NOTES :
1774
1775
1776==================================================================================================*/
1777Ret_t
1778HandleExecCommand (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/*==================================================================================================
1953FUNCTION        : HandleGetCommand
1954
1955DESCRIPTION     : 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.
1963ARGUMENT PASSED : id
1964                  userData
1965                  pContent
1966OUTPUT PARAMETER:
1967RETURN VALUE    : SML_ERR_OK or ERR code
1968IMPORTANT NOTES :
1969
1970
1971==================================================================================================*/
1972Ret_t
1973HandleGetCommand (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/*==================================================================================================
2179FUNCTION        : HandleReplaceCommand
2180
2181DESCRIPTION     : 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.
2189ARGUMENT PASSED : id
2190                  userData
2191                  pContent
2192OUTPUT PARAMETER:
2193RETURN VALUE    : SML_ERR_OK or ERR code
2194IMPORTANT NOTES :
2195
2196
2197==================================================================================================*/
2198Ret_t
2199HandleReplaceCommand (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/*==================================================================================================
2208FUNCTION        : HandleStartSequenceCommand
2209
2210DESCRIPTION     : 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
2215ARGUMENT PASSED : id
2216                  userData
2217                  pContent
2218OUTPUT PARAMETER:
2219RETURN VALUE    : SML_ERR_OK or ERR code
2220IMPORTANT NOTES :
2221
2222
2223==================================================================================================*/
2224Ret_t
2225HandleStartSequenceCommand(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/*==================================================================================================
2276FUNCTION        : HandleEndSequenceCommand
2277
2278DESCRIPTION     : 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
2283ARGUMENT PASSED : id
2284                  userData
2285OUTPUT PARAMETER:
2286RETURN VALUE    : SML_ERR_OK or ERR code
2287IMPORTANT NOTES :
2288
2289
2290==================================================================================================*/
2291Ret_t
2292HandleEndSequenceCommand(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/*==================================================================================================
2306FUNCTION        : HandleStartAtomicCommand
2307
2308DESCRIPTION     : 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
2313ARGUMENT PASSED : id
2314                  userData
2315                  pContent
2316OUTPUT PARAMETER:
2317RETURN VALUE    : SML_ERR_OK or ERR code
2318IMPORTANT NOTES :
2319
2320
2321==================================================================================================*/
2322Ret_t
2323HandleStartAtomicCommand(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/*==================================================================================================
2389FUNCTION        : HandleEndAtomicCommand
2390
2391DESCRIPTION     : 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
2396ARGUMENT PASSED : id
2397                  userData
2398OUTPUT PARAMETER:
2399RETURN VALUE    : SML_ERR_OK or ERR code
2400IMPORTANT NOTES :
2401
2402
2403==================================================================================================*/
2404Ret_t
2405HandleEndAtomicCommand(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/*==================================================================================================
2467FUNCTION        : HandleStatusCommand
2468
2469DESCRIPTION     : 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
2482ARGUMENT PASSED : id
2483                  userData
2484                  pContent
2485OUTPUT PARAMETER:
2486RETURN VALUE    : SML_ERR_OK or ERR code
2487IMPORTANT NOTES :
2488
2489
2490==================================================================================================*/
2491Ret_t
2492HandleStatusCommand (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
2866bool 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