RDK Documentation (Open Sourced RDK Components)
waldb.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2017 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 #include <iostream>
21 #include <string>
22 #include <mutex>
23 #include "waldb.h"
24 #include "tinyxml2.h"
25 #include "stdlib.h"
26 #include "libIBus.h"
27 #include "webpa_parameter.h"
28 #include "hostIf_main.h"
29 #include "hostIf_utils.h"
30 #include "hostIf_tr69ReqHandler.h"
31 #include "safec_lib.h"
32 
33 using namespace tinyxml2;
34 #define MAX_PARAMETER_LENGTH 512
35 #define MAX_DATATYPE_LENGTH 48
36 #define MAX_NUM_PARAMETERS 2048
37 #define INSTANCE_NUMBER_INDICATOR "{i}."
38 #define INSTANCE_CHAR_INDICATOR ".{i}."
39 #define MAX_PARAM_LENGTH TR69HOSTIFMGR_MAX_PARAM_LEN
40 #define BLUETOOTH_DISCOVERED_DEVICE_COUNT_PARAM "Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.DiscoveredDeviceCnt"
41 #define BLUETOOTH_PAIRED_DEVICE_COUNT_PARAM "Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.PairedDeviceCnt"
42 #define BLUETOOTH_CONNECTED_DEVICE_COUNT_PARAM "Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.ConnectedDeviceCnt"
43 #define DEVAPPS_COUNT_PARAM "Device.X_COMCAST-COM_Xcalibur.DevApp.devAppNumAps"
44 
45 /**
46  * @briefGHashTable For holding Parameter count query strings
47  */
48 GHashTable *instanceNumParamHash = NULL;
49 
50 
51 //static void getList(TiXmlNode *pParent,char *paramName,char **ptrParamList,char **pParamDataTypeList,int *paramCount);
52 static XMLNode* getList(XMLNode *pParent,char *paramName,char* currentParam,char **ptrParamList,char **pParamDataTypeList,int *paramCount);
53 static void removeUnnecessaryAttributes(XMLDocument *pParent);
54 void checkforParameterMatch(XMLNode *pParent,char *paramName,int *pMatch,DataModelParam *dmParam);
55 void appendNextObject(char* currentParam, const char* pAttparam);
56 int isParamEndsWithInstance(const char* paramName);
57 void replaceWithInstanceNumber(char *paramName, int instanceNumber);
58 int checkMatchingParameter(const char* attrValue, char* paramName, int* ret);
59 void appendNextObject(char* currentParam, const char* pAttparam);
60 int getNumberofInstances(const char* paramName);
61 
62 
63 #define WEBPA_DATA_MODEL_FILE "/etc/data-model.xml"
64 static void *g_dbhandle = NULL;
65 std::mutex g_db_mutex;
66 
67 /* @brief Loads the data-model xml data
68  *
69  * @filename[in] data-model xml filename (with absolute path)
70  * @dbhandle[out] database handle
71  * @return DB_STATUS
72  */
73 DB_STATUS loadDataModel(void)
74 {
75  DB_STATUS dbRet = DB_FAILURE;
76  XMLDocument *doc = NULL;
77 
78  if(g_dbhandle)
79  return DB_SUCCESS;
80 
81  const std::lock_guard<std::mutex> lock(g_db_mutex);
82 
83  // Load Document model
84  doc = new XMLDocument();
85  if(doc != NULL)
86  {
87  doc->LoadFile(WEBPA_DATA_MODEL_FILE);
88  if( doc->ErrorID() == 0 )
89  {
90  removeUnnecessaryAttributes(doc);
91  g_dbhandle = (void *)doc;
92  // Initialize Number of entity param list
93  initNumEntityParamList();
94  return DB_SUCCESS;
95  }
96  else
97  {
98  return DB_FAILURE;
99  }
100  }
101  return DB_FAILURE;
102 }
103 static void removeUnnecessaryAttributes(XMLDocument *pParent)
104 {
105  XMLNode* pChild;
106  if( pParent->ToElement() == NULL )
107  {
108  for ( pChild = pParent->FirstChild(); pChild != 0; )
109  {
110  if( pChild->ToElement() == NULL )
111  {
112  pChild = pChild->NextSibling();
113  }
114  else
115  {
116  if( !strcmp (pChild->Value(), "object") )
117  break;
118  pChild = pChild->FirstChild();
119  }
120  }
121  }
122  else
123  {
124  pChild = pParent;
125  }
126  while(pChild)
127  {
128  XMLElement* pElement = pChild->ToElement();
129  const XMLAttribute* pAttrib = pElement->FirstAttribute();
130  if(!strcmp(pChild->Value(),"object"))
131  {
132  pElement->DeleteAttribute("minEntries");
133  pElement->DeleteAttribute("addObjIdx");
134  pElement->DeleteAttribute("delObjIdx");
135  XMLNode* param = pChild->FirstChild();
136  if(param != NULL && !strcmp(param->Value(),"parameter"))
137  {
138  while( param )
139  {
140  param->ToElement()->DeleteAttribute("notification");
141  param->ToElement()->DeleteAttribute("maxNotification");
142  param->ToElement()->DeleteAttribute("rebootIdx");
143  param->ToElement()->DeleteAttribute("initIdx");
144  param->ToElement()->DeleteAttribute("setIdx");
145  param=param->NextSibling();
146  }
147  }
148  }
149  pChild = pChild->NextSibling();
150  }
151 }
152 
153 void* getDataModelHandle()
154 {
155  return g_dbhandle;
156 }
157 
158 DB_STATUS checkDataModelStatus()
159 {
160  return (g_dbhandle != NULL)?DB_SUCCESS:DB_FAILURE;
161 }
162 
163 /* @brief Loads the Parameter count query string to memory
164  *
165  * @return void
166  */
167 void initNumEntityParamList()
168 {
169  instanceNumParamHash = g_hash_table_new(g_str_hash, g_str_equal);
170  if(NULL != instanceNumParamHash)
171  {
172  g_hash_table_insert(instanceNumParamHash, (gpointer)"Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.DiscoveredDevice", (gpointer)BLUETOOTH_DISCOVERED_DEVICE_COUNT_PARAM);
173  g_hash_table_insert(instanceNumParamHash,(gpointer) "Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.PairedDevice",(gpointer) BLUETOOTH_PAIRED_DEVICE_COUNT_PARAM);
174  g_hash_table_insert(instanceNumParamHash, (gpointer)"Device.DeviceInfo.X_RDKCENTRAL-COM_xBlueTooth.ConnectedDevice", (gpointer)BLUETOOTH_CONNECTED_DEVICE_COUNT_PARAM);
175  g_hash_table_insert(instanceNumParamHash, (gpointer)"Device.X_COMCAST-COM_Xcalibur.DevApp.devAppTable", (gpointer)DEVAPPS_COUNT_PARAM);
176  }
177 }
178 
179 /**
180  * @brief Get the number of Instances of particular parameter ending with {i}
181  *
182  * @param[in] paramName Name of the Parameter ending with {i}
183  * @param[out] Number of instances present for particular Parameter
184  */
185 int getNumberofInstances(const char* paramName)
186 {
187  int instanceCount = 0;
188  errno_t safec_rc = -1;
189  if(NULL != paramName)
190  {
191  char *position = NULL;
192  char numberOfEntitiesParam[MAX_PARAMETER_LENGTH] = "\0";
193  char parameter[MAX_PARAMETER_LENGTH] = "\0";
194  strncpy(numberOfEntitiesParam,paramName,sizeof(numberOfEntitiesParam) -1);
195  numberOfEntitiesParam[sizeof(numberOfEntitiesParam) -1] = '\0';
196  if(NULL != (position = strstr(numberOfEntitiesParam, INSTANCE_NUMBER_INDICATOR)))
197  {
198  // Check if Parameter is present in numParam Hash List
199  strncpy(parameter,numberOfEntitiesParam,strlen(numberOfEntitiesParam)-5);
200  const char* paramValue = (const char *) g_hash_table_lookup(instanceNumParamHash,parameter);
201  if(NULL != paramValue)
202  {
203  safec_rc=strcpy_s(numberOfEntitiesParam,sizeof(numberOfEntitiesParam),paramValue);
204  if(safec_rc!= EOK)
205  {
206  ERR_CHK(safec_rc);
207  }
208  }
209  else // Normal Parameters Number of Entity param = ParamName + "NumberOfEntries"
210  {
211  safec_rc=strcpy_s(position-1,MAX_PARAMETER_LENGTH-((char *)position - (char*)numberOfEntitiesParam),"NumberOfEntries");
212  if(safec_rc!= EOK)
213  {
214  ERR_CHK(safec_rc);
215  }
216  }
217  // Get the number of instances using getValues
218  WDMP_STATUS *ret ;
219  size_t *retCount = 0;
220  char *getParamList[1];
221  getParamList[0] = (char*) calloc(1,MAX_PARAMETER_LENGTH);
222  strncpy(getParamList[0],numberOfEntitiesParam,MAX_PARAMETER_LENGTH);
223  param_t **parametervalArr = (param_t **) malloc(sizeof(param_t **));
224  if(parametervalArr)
225  {
226  *parametervalArr = NULL; //CID:44089 - Reverse_inull
227  }
228  ret = (WDMP_STATUS *) malloc(sizeof(WDMP_STATUS));
229  retCount = (size_t *) malloc(sizeof(size_t));
230  if(ret == NULL)
231  {
232  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"ret is null\n");
233  return instanceCount;
234  }
235  if(retCount == NULL)
236  {
237  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"ret is null\n");
238  free(ret);
239  return instanceCount;
240  }
241  getValues(const_cast<const char**>(getParamList), 1, &parametervalArr, &retCount,&ret);
242  if( *retCount > 0 && (NULL != parametervalArr) && NULL != (*parametervalArr)[0].value )
243  {
244  instanceCount = strtol(const_cast<const char*>((*parametervalArr)[0].value),NULL,10);
245  }
246  // Lets free all allocated values
247  if(getParamList[0])
248  free(getParamList[0]);
249  if(NULL != parametervalArr && NULL != *parametervalArr)
250  {
251  if((*parametervalArr)[0].value)
252  free((*parametervalArr)[0].value);
253  if((*parametervalArr)[0].name)
254  free((*parametervalArr)[0].name);
255  free(*parametervalArr);
256  }
257  if(NULL != parametervalArr) {
258  free(parametervalArr);
259  }
260  free(ret);
261  free(retCount);
262  }
263  }
264  return instanceCount;
265 }
266 /**
267  * @brief Check if Parameter Name ends with {i}.
268  *
269  * @param[in] paramName Name of the Parameter.
270  * @param[out] retValue 0 if present and 1 if not
271  */
272 int isParamEndsWithInstance(const char* paramName)
273 {
274  int retValue = 1;
275  if(NULL != paramName)
276  {
277  retValue = strcmp(paramName+strlen(paramName)-4,INSTANCE_NUMBER_INDICATOR);
278  }
279  return retValue;
280 }
281 
282 /**
283  * @brief Check if Parameter Name ends with . If yes it is a wild card param
284  *
285  * @param[in] paramName Name of the Parameter.
286  * @param[out] retValue 0 if present and 1 if not
287  */
288 int isWildCardParam(char *paramName)
289 {
290  int isWildCard = 0;
291  if(NULL != paramName)
292  {
293  if(!strcmp(paramName+strlen(paramName)-1,"."))
294  {
295  isWildCard = 1;
296  }
297  }
298  return isWildCard;
299 }
300 /**
301  * @brief If Parameter Name ends with {i}. replace it with instance number eg:- a.{i} to a.1
302  *
303  * @param[in] paramName Name of the Parameter.
304  * @param[in] instanceNumber , The number which we need to replace
305  */
306 void replaceWithInstanceNumber(char *paramName, int instanceNumber)
307 {
308 // errno_t safec_rc = -1;
309  char *position;
310  char number[10];
311 
312  if(!(position = strstr(paramName, INSTANCE_NUMBER_INDICATOR)))
313  return;
314  sprintf(number,"%d.",instanceNumber);
315 
316  //TO DO: paramName size is not predictable, revert to use strcpy
317 #if 0
318  safec_rc=strcpy_s(paramName+(strlen(paramName)-4),MAX_PARAMETER_LENGTH,number);
319  if(safec_rc!= EOK)
320  {
321  ERR_CHK(safec_rc);
322  }
323 #endif
324  strcpy(paramName+(strlen(paramName)-4),number);
325 }
326 
327 /**
328  * @brief Check if the parameter name and current attribute value is matching. This will consider with instance number.
329  * ie "a.b.c.{i}." is matching to "a.b.c.1."
330  *
331  * @param[in] attrValue Current value of the Object with {i} from xml file
332  * @param[in] paramName , Current parameter name from wild card.
333  * @param[in] ret , This will be filled with Instance number if attrValue ends with {i}
334  * @param[out] Status , returns 1 if strings matches and 0 if not
335  */
336 int checkMatchingParameter(const char* attrValue, char* paramName, int* ret)
337 {
338  int i=10;
339  int inst = 0;
340  int status = 0;
341  while(true)
342  {
343  if(!(*attrValue && *paramName && (*attrValue == *paramName)))
344  {
345  *ret =0;
346  if(*attrValue == '{' && *paramName >= 48 && *paramName<=56)
347  {
348  attrValue += 3;
349  while(*paramName && *paramName != '.')
350  {
351  *ret = *ret*i + (*paramName-48);
352  paramName++;
353  inst = *ret;
354  }
355  }
356  else
357  {
358  *ret =0;
359  if(!*paramName)
360  {
361  if(!*attrValue && (*(attrValue-2) == '}'))
362  {
363  *ret = inst;
364  }
365  status = 1;
366  }
367  break;
368  }
369  }
370  attrValue++;
371  paramName++;
372  }
373  return status;
374 }
375 
376 /**
377  * @brief Append the next object name with current Object name,
378  *
379  * @param[in] currentParam , Current Name of the Parameter.
380  * @param[in] pAttparam , Current attribute value from xml
381  */
382 void appendNextObject(char* currentParam, const char* pAttparam)
383 {
384  errno_t safec_rc = -1;
385  while(true)
386  {
387  if(!(*currentParam == *pAttparam) )
388  {
389  // Skip instance numbers
390  if(*pAttparam == '{')
391  {
392  if (*currentParam)
393  {
394  pAttparam += 3;
395  currentParam = strstr(currentParam, ".");
396  }
397  else
398  break;
399  }
400  else
401  break;
402  }
403  if(!*currentParam && !*pAttparam ) break;
404 
405  currentParam++;
406  pAttparam++;
407  }
408  // Copy rest of the un matching strings to currentParam
409  // TO DO: Since the size of the destination buffer is not predictable using strcpy
410  strcpy(currentParam, pAttparam);
411 }
412 /**
413  * @brief Get the list of parameters which is matching with paramName
414  *
415  * @param[in] pParent , The current node in tinyxml node
416  * @param[in] paramName , Wildcard parameter name
417  * @param[in] currentParam , current parameter name replaced {i} with instance num
418  */
419 static XMLNode* getList(XMLNode *pParent,char *paramName,char* currentParam,char **ptrParamList,char **pParamDataTypeList,int *paramCount)
420 {
421  errno_t safec_rc = -1;
422  XMLNode* pChild;
423  const char* maxEntries;
424  int isReccursiveCall = 0;
425  char zeroInstance[MAX_PARAMETER_LENGTH] = "\0";
426 
427  // If parent is Null Return
428  if(!pParent) {
429  return NULL;
430  }
431  // Identify whether the call is recursive or initial call
432  if(!strcmp(currentParam,""))
433  {
434  isReccursiveCall = 0;
435  }
436  else
437  {
438  isReccursiveCall = 1;
439  }
440 
441  // Goto actual Object node ie "Device."
442  if( pParent->ToElement() == NULL )
443  {
444  for ( pChild = pParent->FirstChild(); pChild != 0; )
445  {
446  if( pChild->ToElement() == NULL )
447  {
448  pChild = pChild->NextSibling();
449  }
450  else
451  {
452  if( !strcmp (pChild->Value(), "object") )
453  break;
454  pChild = pChild->FirstChild();
455  }
456  }
457  }
458  else
459  {
460  pChild = pParent;
461  }
462  // Traverse through the nodes and get matching parameters
463  while(pChild)
464  {
465  XMLElement* pElement = pChild->ToElement();
466  const XMLAttribute* pAttrib = pElement->FirstAttribute();
467  int inst = 0;
468  int status = 0;
469  char* endPtr = NULL;
470 
471  // Check if node is an Object
472  if(!strcmp(pChild->Value(),"object"))
473  {
474  // Check if the Object is matching with given input wild card
475  if(strstr(pAttrib->Value(),paramName) || (status = checkMatchingParameter(pAttrib->Value(),paramName,&inst)))
476  {
477  // If the number of instances are 0 then skip this object and go to next sibling
478  if (*zeroInstance && strstr(pAttrib->Value(),zeroInstance))
479  {
480  pChild = pChild->NextSibling();
481  continue;
482  }
483  else if(*zeroInstance)
484  {
485  zeroInstance[0] = '\0';
486  }
487  // If matching found update the current parameter with wild card input string
488  if( status && !isReccursiveCall)
489  {
490  //TO DO: Since currentParam size is not predictable using strcpy
491  strcpy(currentParam, paramName);
492  }
493  // Append if current attribute contains {i} to current param
494  appendNextObject(currentParam, pAttrib->Value());
495  XMLNode* bChild,*sChild;
496  bChild = pChild;
497  // Goto the parameters
498  pChild = pChild->FirstChild();
499 
500  // Object not having any parameter thus go to next Sibling
501  if(NULL == pChild)
502  {
503  pChild = bChild->NextSibling();
504  }
505  maxEntries = pElement->Attribute("maxEntries");
506  // Seems like a {i} instance
507  if(maxEntries && ((!strcmp(maxEntries,"unbounded")) || (strtol(maxEntries,&endPtr, 10) > 1)))
508  {
509  // Make Sure that its ends with {i}
510  if(isParamEndsWithInstance(pAttrib->Value()) == 0 )
511  {
512  int instanceNumber = 0;
513  int i=1;
514  // Get the Number of instances for that attribute
515  int actualInstance = getNumberofInstances(pAttrib->Value());
516  if(inst)
517  {
518  // Check if valid instance count is given in input wild card if not make it as zero, this will skip current branch
519  if(actualInstance >= inst)
520  i = instanceNumber = inst;
521  else
522  instanceNumber = 0;
523  }
524  else
525  {
526  instanceNumber = actualInstance;
527  }
528  sChild = pChild;
529  // Number of instances are > 0 go through each and populate data for each instance
530  char tparaName[MAX_PARAMETER_LENGTH];
531  while(i<=instanceNumber && inst==0)
532  {
533  memset(tparaName, 0,MAX_PARAMETER_LENGTH);
534  int len=strlen(currentParam)-4;
535  safec_rc=strcpy_s(tparaName, MAX_PARAMETER_LENGTH, pChild->Parent()->ToElement()->FirstAttribute()->Value());
536  if(safec_rc != EOK)
537  {
538  ERR_CHK(safec_rc);
539  }
540  // Replace {i} with current instance number and call recursively
541  replaceWithInstanceNumber(currentParam,i);
542  sChild = getList(pChild,tparaName,currentParam,ptrParamList,pParamDataTypeList,paramCount);
543  //TO DO:Since curretParam size is not predictable using strcpy
544  strcpy(currentParam+len, INSTANCE_NUMBER_INDICATOR);
545  i++;
546  }
547  pChild = sChild;
548  // Seems like instance count is empty
549  if (!instanceNumber)
550  {
551  safec_rc=strcpy_s(zeroInstance,MAX_PARAMETER_LENGTH, pAttrib->Value());
552  if(safec_rc != EOK)
553  {
554  ERR_CHK(safec_rc);
555  }
556  pChild = pChild->Parent();
557  }
558  }
559  }
560  }
561  else if(isReccursiveCall) // Tree found once and processed and going to another branch so break
562  {
563  return pChild;
564  }
565  else // Tree not found yet goto next sibling and get it
566  {
567  pChild = pChild->NextSibling();
568  }
569  }
570  // Found the Parameter
571  else if(!strcmp(pChild->Value(),"parameter"))
572  {
573  XMLNode* bChild;
574  // Find all parameters
575  for(bChild = pChild ; pChild ; pChild=pChild->NextSibling() )
576  {
577  if(*paramCount < MAX_NUM_PARAMETERS)
578  {
579  if(strlen(currentParam) > 0)
580  {
581  ptrParamList[*paramCount] = (char *) malloc(MAX_PARAMETER_LENGTH * sizeof(char));
582  pParamDataTypeList[*paramCount] = (char *) malloc(MAX_DATATYPE_LENGTH * sizeof(char));
583  snprintf(ptrParamList[*paramCount],MAX_PARAMETER_LENGTH,"%s%s",currentParam,pChild->ToElement()->FirstAttribute()->Value());
584  strncpy(pParamDataTypeList[*paramCount],pChild->FirstChild()->FirstChild()->Value(),MAX_DATATYPE_LENGTH-1);
585  (*paramCount)++;
586  }
587  }
588  }
589  // Go to next object
590  pChild = bChild->Parent();
591  pChild = pChild->NextSibling();
592  }
593  }
594  return pChild;
595 
596 }
597 /* @brief Returns a parameter list and count given an input paramName with wildcard characters
598  *
599  * @dbhandle[in] database handle to query in to
600  * @paramName[in] parameter name with wildcard(*)
601  * @ParamList[out] parameter list extended by the input wildcard parameter
602  * @ParamDataTypeList[out] parameter data type list extended by the input wildcard parameter
603  * @paramCount[out] parameter count
604  * @return DB_STATUS
605  */
606 DB_STATUS getChildParamNamesFromDataModel(void *dbhandle,char *paramName,char **ParamList,char **ParamDataTypeList,int *paramCount)
607 {
608  char parameterName[MAX_PARAMETER_LENGTH];
609  char currentParam[MAX_PARAMETER_LENGTH] = "\0";
610  strncpy(parameterName,paramName,MAX_PARAMETER_LENGTH-1);
611 
612  if(dbhandle == NULL)
613  return DB_FAILURE;
614 
615  if(isWildCardParam(parameterName))
616  {
617  XMLDocument *doc = (XMLDocument *) dbhandle;
618  getList(doc,parameterName,currentParam,ParamList,ParamDataTypeList,paramCount);
619  if(*paramCount == 0)
620  {
621  return DB_ERR_INVALID_PARAMETER;
622  }
623  }
624  else
625  {
626  return DB_ERR_WILDCARD_NOT_SUPPORTED;
627  }
628  return DB_SUCCESS;
629 }
630 
631 void checkforParameterNameMatch(XMLNode *pParent, const char *ObjectName, const char *paramName, int *pMatch, DataModelParam *dmParam)
632 {
633  if(!pParent)
634  {
635  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"pParent Node is NULL.. returning form checkforAttributeMatch\n");
636  return;
637  }
638 
639  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"checkforAttributeMatch : pParent->Value() : %s\n", pParent->Value());
640  if(pParent->ToElement() != NULL)
641  {
642  XMLElement* pElement = pParent->ToElement();
643  const XMLAttribute* pAttrib = pElement->FirstAttribute();
644  if(!strcmp(pParent->Value(),"parameter") && pAttrib)
645  {
646  char *ParameterName = (char *) malloc(sizeof(char) * MAX_PARAMETER_LENGTH);
647  strncpy(ParameterName,ObjectName,MAX_PARAMETER_LENGTH-1);
648  strncat(ParameterName,pAttrib->Value(),MAX_PARAMETER_LENGTH-1);
649  ParameterName[MAX_PARAMETER_LENGTH-1] = '\0';
650  bool match = !strcmp(ParameterName,paramName);
651  free(ParameterName);
652  if (match)
653  {
654  XMLNode *pSyntaxNode = NULL;
655  XMLNode *pSyntaxChildNode = NULL;
656  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"Match found : Extracting parameter attributes\n");
657  dmParam->objectName = strdup(paramName);
658  if(pElement->Attribute("base") != NULL)
659  dmParam->paramName = strdup(pElement->Attribute("base"));
660  if(pElement->Attribute("bsUpdate") != NULL)
661  dmParam->bsUpdate = strdup(pElement->Attribute("bsUpdate"));
662  if(pElement->Attribute("access") != NULL)
663  dmParam->access = strdup(pElement->Attribute("access"));
664 
665  pSyntaxNode = pElement->FirstChildElement("syntax");
666  for(pSyntaxChildNode = pSyntaxNode->FirstChild(); pSyntaxChildNode != NULL; pSyntaxChildNode = pSyntaxChildNode->NextSibling())
667  {
668  if(!strcmp("default", pSyntaxChildNode->Value()))
669  {
670  XMLElement *pDefaultElement = pSyntaxChildNode->ToElement();
671  dmParam->defaultValue = strdup(pDefaultElement->Attribute("value"));
672  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"Default Value : %s\n", dmParam->defaultValue);
673  }
674  else
675  {
676  dmParam->dataType = strdup(pSyntaxChildNode->Value());
677  }
678  }
679  *pMatch = 1;
680  return;
681  }
682  }
683  }
684 }
685 
686 void checkforObjectMatch(XMLNode *pParent,const char *objectName,int *pMatch,DataModelParam *dmParam)
687 {
688  if(!pParent)
689  {
690  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"pParent Node is NULL.. returning form checkforParameterMatch\n");
691  return;
692  }
693 
694  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"checkforObjectMatch : pParent->Value() : %s\n", pParent->Value());
695  if(pParent->ToElement() != NULL)
696  {
697  XMLElement* pElement = pParent->ToElement();
698  const XMLAttribute* pAttrib = pElement->FirstAttribute();
699  if(!strcmp(pParent->Value(),"object") && pAttrib)
700  {
701  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"Comparing with object : %s\n", pAttrib->Value());
702 
703  if(!strcmp(pAttrib->Value(),objectName))
704  {
705  *pMatch = 1;
706  return;
707  }
708  }
709  }
710 }
711 
712 void checkforParameterMatch(XMLNode *pParent,const char *paramName,int *pMatch,DataModelParam *dmParam)
713 {
714  XMLNode *pChild = NULL;
715  XMLNode *pParam = NULL;
716  if(!pParent)
717  {
718  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"pParent is Null - returning\n");
719  return;
720  }
721  if(!paramName)
722  {
723  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"paramName is Null - returning\n");
724  return;
725  }
726  // Construct Object without parameter from input ParamName
727  std::string *str1 = new std::string(paramName);
728  std::size_t found = str1->find_last_of(".");
729  delete str1;
730 
731  char *paramObject = (char *) malloc(sizeof(char) * MAX_PARAMETER_LENGTH);
732  if(!paramObject)
733  {
734  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF,"paramObject Malloc is Null - returning\n");
735  return;
736  }
737  if(found != std::string::npos)
738  {
739  strncpy(paramObject,paramName,found);
740  paramObject[found]='.';
741  paramObject[found+1]='\0';
742  }
743  else
744  {
745  strncpy(paramObject,paramName,MAX_PARAMETER_LENGTH-1);
746  paramObject[MAX_PARAMETER_LENGTH-1] = '\0';
747  }
748 
749  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"Looking for object : %s\n", paramObject);
750  for(pChild = pParent->FirstChildElement("dm:document")->FirstChildElement("model")->FirstChildElement("object"); pChild != NULL; pChild = pChild->NextSibling())
751  {
752  if(pChild->ToElement() == NULL)
753  continue;
754  else
755  {
756  checkforObjectMatch(pChild,paramObject,pMatch,dmParam);
757  if(*pMatch)
758  {
759  *pMatch = 0;
760  for(pParam = pChild->FirstChild(); pParam != NULL; pParam = pParam->NextSibling())
761  {
762  checkforParameterNameMatch(pParam, paramObject, paramName, pMatch, dmParam);
763  if(*pMatch)
764  goto end;
765  }
766  }
767  }
768  }
769 end:
770  free(paramObject);
771  return;
772 }
773 
774 int getNumberOfDigitsInInstanceNumber(const char* paramName,int position)
775 {
776  int digitCount=0;
777  int len = 0;
778 
779  if(!paramName)
780  return digitCount;
781  len = strlen(paramName);
782  while((position < len) && isdigit(paramName[position]))
783  {
784  digitCount++;
785  position++;
786  }
787  return digitCount;
788 }
789 
790 /* @brief Returns a parameter list and count given an input paramName with wildcard characters
791  *
792  * @filename[in] data-model xml filename (with absolute path)
793  * @dbhandle[out] database handle
794  * @dataType[out] Parameter DataType output
795  * @return DB_STATUS
796  */
797 int getParamInfoFromDataModel(void *dbhandle,const char *paramName, DataModelParam *dmParam)
798 {
799  int Match = 0;
800  int first_i = 0;
801  char *newparamName = NULL;
802  XMLDocument *doc = NULL;
803 
804  const std::lock_guard<std::mutex> lock(g_db_mutex);
805 
806  doc = (XMLDocument *) dbhandle;
807 
808 
809  /* Check if Parameter is one of {i} entriesi ex:Device.WiFi.Radio.1.Status should become Device.WiFi.Radio.{i}.Status */
810  std::string str(paramName);
811  std::size_t found = str.find_first_of("0123456789");
812  if(found != std::string::npos)
813  {
814  /* Check if match happens without a {i} */
815  checkforParameterMatch(doc,paramName,&Match,dmParam);
816  if(Match)
817  return true;
818  int numOfDigits = getNumberOfDigitsInInstanceNumber(paramName,found);
819  first_i = found+1;
820  newparamName =(char *) malloc(sizeof(char) * MAX_PARAMETER_LENGTH);
821  char splitParam[MAX_PARAMETER_LENGTH] = "{i}";
822  if(paramName[found+numOfDigits] == '.' && paramName[found-1] == '.')
823  {
824  strncpy(newparamName,paramName,found);
825  newparamName[found]='\0';
826  strncat(splitParam,str.substr(found+numOfDigits).data(),MAX_PARAMETER_LENGTH-1);
827  splitParam[MAX_PARAMETER_LENGTH-1]='\0';
828  // Check for Parameter Match with first {i}
829  strncat(newparamName,splitParam,MAX_PARAMETER_LENGTH-1);
830  newparamName[MAX_PARAMETER_LENGTH-1]='\0';
831  checkforParameterMatch(doc,(const char*)newparamName,&Match,dmParam);
832  if(Match)
833  goto freeResources;
834  }
835  else
836  {
837  strncpy(newparamName,paramName,found+1);
838  newparamName[found+1]='\0';
839  strncpy(splitParam,paramName+found+1,MAX_PARAMETER_LENGTH);
840  splitParam[MAX_PARAMETER_LENGTH-1]='\0';
841  }
842 
843  // Check if splitParam has a digit
844  std::string str(splitParam);
845  std::size_t found = str.find_first_of("0123456789");
846  if(found != std::string::npos)
847  {
848  strncpy(newparamName,paramName,first_i);
849  newparamName[first_i] = '\0';
850  numOfDigits = getNumberOfDigitsInInstanceNumber(splitParam,found);
851 
852  if(splitParam[found+numOfDigits] == '.' && splitParam[found-1] == '.')
853  {
854  splitParam[found]='\0';
855  strcat(splitParam,"{i}");
856  strncat(splitParam,str.substr(found+numOfDigits).data(),MAX_PARAMETER_LENGTH-1);
857  splitParam[MAX_PARAMETER_LENGTH-1]='\0';
858 
859  strncat(newparamName,splitParam+3,MAX_PARAMETER_LENGTH-1);
860  newparamName[MAX_PARAMETER_LENGTH-1]='\0';
861  checkforParameterMatch(doc,(const char*)newparamName,&Match,dmParam);
862  if(Match)
863  goto freeResources;
864  }
865  else
866  {
867  /* Find if there are more {i} entries */
868  int first_num = found;
869  std::string str(splitParam+first_num+1);
870  std::size_t found = str.find_first_of("0123456789");
871  if(found != std::string::npos)
872  {
873  splitParam[found+first_num]='\0';
874  strcat(splitParam,".{i}");
875  strncat(splitParam,str.substr(found+1).data(),MAX_PARAMETER_LENGTH-1);
876  splitParam[MAX_PARAMETER_LENGTH-1]='\0';
877  //Check for parameter match with second {i}
878  strncat(newparamName,splitParam+3,MAX_PARAMETER_LENGTH-1);
879  newparamName[MAX_PARAMETER_LENGTH-1]='\0';
880  checkforParameterMatch(doc,(const char*)newparamName,&Match,dmParam);
881  if(Match)
882  goto freeResources;
883  }
884  }
885  }
886 
887  if(first_i)
888  newparamName[first_i-1]='\0';
889  strncat(newparamName,splitParam,MAX_PARAMETER_LENGTH-1);
890  newparamName[MAX_PARAMETER_LENGTH-1]='\0';
891  checkforParameterMatch(doc,(const char *)newparamName,&Match,dmParam);
892  }
893  else
894  {
895  checkforParameterMatch(doc, paramName, &Match, dmParam);
896  }
897 freeResources:
898  if (newparamName)
899  {
900  free(newparamName);
901  }
902  return Match;
903 }
904 
905 /**
906  * @brief Get complete list of parameters from data model xml.
907  * @param[in] pParent , The current node in tinyxml node
908  * @param[out] param_list , Complete list of Parameter Name and type
909  * @return DB_STATUS
910  */
911 static DB_STATUS get_complete_parameter_list_from_dml_xml (
912  XMLNode *pInParentXmlNode,
913  char **pOutParamNameList,
914  int *num_of_params)
915 {
916  int params_count = 0;
917  XMLNode* pChild = NULL;
918 
919  char currentParam[MAX_PARAMETER_LENGTH] = "\0";
920  const char *top_node_name = "Device.";
921 
922  // If parent is Null Return
923  if(!pInParentXmlNode) {
924  return DB_FAILURE;
925  }
926 
927 
928  if( pInParentXmlNode->ToElement() == NULL )
929  {
930  for ( pChild = pInParentXmlNode->FirstChild(); pChild != 0; )
931  {
932  if( pChild->ToElement() == NULL )
933  {
934  pChild = pChild->NextSibling();
935  }
936  else
937  {
938  if( !strcmp (pChild->Value(), "object") )
939  break;
940  pChild = pChild->FirstChild();
941  }
942  }
943  }
944  else
945  {
946  pChild = pInParentXmlNode;
947  }
948 
949  // Traverse through the nodes and get matching parameters
950  while(pChild)
951  {
952  XMLElement* pElement = pChild->ToElement();
953  const XMLAttribute* pAttrib = pElement->FirstAttribute();
954 
955  // Check if node is an Object
956  if(!strcmp(pChild->Value(),"object"))
957  {
958  // Check if the Object is matching with given input wild card
959  if(strstr(pAttrib->Value(),top_node_name))
960  {
961  appendNextObject(currentParam, pAttrib->Value());
962  std::string str = pAttrib->Value();
963 
964  if (str.compare(str.size()-5,5,".{i}.") == 0) {
965  if(params_count < MAX_NUM_PARAMETERS)
966  {
967  pOutParamNameList[params_count] = (char *) calloc(MAX_PARAMETER_LENGTH, sizeof(char));
968  snprintf(pOutParamNameList[params_count], MAX_PARAMETER_LENGTH,"%s",pAttrib->Value());
969  params_count++;
970  }
971  }
972  XMLNode* bChild;
973  bChild = pChild;
974  // Goto the parameters
975  pChild = pChild->FirstChild();
976 
977  // Object not having any parameter thus go to next Sibling
978  if(NULL == pChild)
979  {
980  pChild = bChild->NextSibling();
981  }
982  }
983  else // Tree not found yet goto next sibling and get it
984  {
985  pChild = pChild->NextSibling();
986  }
987  }
988  // Found the Parameter
989  else if(!strcmp(pChild->Value(),"parameter"))
990  {
991  XMLNode* bChild;
992  // Find all parameters
993  for(bChild = pChild ; pChild ; pChild=pChild->NextSibling() )
994  {
995  if(params_count < MAX_NUM_PARAMETERS)
996  {
997  if(strlen(currentParam) > 0)
998  {
999  pOutParamNameList[params_count] = (char *) calloc(MAX_PARAMETER_LENGTH, sizeof(char));
1000  snprintf(pOutParamNameList[params_count],MAX_PARAMETER_LENGTH,"%s%s",currentParam,pChild->ToElement()->FirstAttribute()->Value());
1001  params_count++;
1002  }
1003  }
1004  }
1005  // Go to next object
1006  pChild = bChild->Parent();
1007  pChild = pChild->NextSibling();
1008  }
1009  }
1010  *num_of_params = params_count;
1011  return DB_SUCCESS;
1012 
1013 }
1014 
1015 /* @brief Get the complete list of parameter name and data type.
1016  *
1017  * @out_param_list[out] Complete list of Parameter Name and type
1018  * @return DB_STATUS
1019  */
1020 DB_STATUS get_complete_param_list (char **out_param_list, int *out_param_count)
1021 {
1022  DB_STATUS status = DB_SUCCESS;
1023 
1024  XMLDocument *in_xml_doc = (XMLDocument *)getDataModelHandle();
1025 
1026  if(in_xml_doc == NULL)
1027  return DB_FAILURE;
1028  else
1029  {
1030  get_complete_parameter_list_from_dml_xml(in_xml_doc, out_param_list, out_param_count);
1031 
1032  if(out_param_count == 0)
1033  {
1034  return status = DB_FAILURE;
1035  }
1036  }
1037  return status;
1038 }
1039 
1040 void freeDataModelParam(DataModelParam dmParam)
1041 {
1042  if(dmParam.objectName)
1043  free(dmParam.objectName);
1044  if(dmParam.paramName)
1045  free(dmParam.paramName);
1046  if(dmParam.access)
1047  free(dmParam.access);
1048  if(dmParam.dataType)
1049  free(dmParam.dataType);
1050  if(dmParam.defaultValue)
1051  free(dmParam.defaultValue);
1052  if(dmParam.bsUpdate)
1053  free(dmParam.bsUpdate);
1054 }
1055 
1056 /* @brief to test get_complete_param_list.
1057  *
1058  */
1059 void test_get_complete_param_list()
1060 {
1061 
1062  char **pParam_name_list;
1063 
1064  pParam_name_list = (char**) calloc (MAX_NUM_PARAMETERS, sizeof(char*));
1065  int num_of_params = 0;
1066 
1067  if(DB_SUCCESS != loadDataModel())
1068  {
1069  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"Failed to load data-model.xml file\n" );
1070  }
1071 
1072  if(DB_SUCCESS != get_complete_param_list (pParam_name_list, &num_of_params))
1073  {
1074  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"Failed to get complete parameter list.\n");
1075  }
1076 
1077  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"Count = %d \n", num_of_params);
1078  int i = 0;
1079  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"======================================================================\n");
1080  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"Iteration:1 => Starts\n ");
1081  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"======================================================================\n");
1082  for(i=0; i< num_of_params; i++)
1083  {
1084  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF," [%d] Parameter : [(%s)]\n", i +1, pParam_name_list[i]);
1085  free(pParam_name_list[i]);
1086  }
1087  free(pParam_name_list);
1088  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"======================================================================\n");
1089  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"Iteration:1 => Ends\n ");
1090  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"======================================================================\n");
1091  DataModelParam dmParam = {0};
1092 
1093  const char *pParameterName = "Device.WiFi.EndPoint.1.Profile.1.Status";
1094 
1095  if (getParamInfoFromDataModel(g_dbhandle, pParameterName, &dmParam))
1096  {
1097  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "Found Parameter...!!! [%s (%s)]\n ", pParameterName, dmParam.dataType);
1098  }
1099  else {
1100  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "Invalid Parameter : [%s] \n ", pParameterName);
1101  }
1102 
1103  ((XMLDocument *)g_dbhandle)->Clear();
1104 }
__DataModelParam
Definition: waldb.h:39
hostIf_main.h
hostIf_main API.
RDK_LOG
#define RDK_LOG
Definition: rdk_debug.h:258
libIBus.h
RDK IARM-Bus API Declarations.
webpa_parameter.h
getValues
void getValues(const char *paramName[], const unsigned int paramCount, param_t ***paramValArr, size_t **retValCount, WDMP_STATUS **retStatus)
getValues interface returns the parameter values.
Definition: webpa_parameter.cpp:68
isWildCardParam
int isWildCardParam(const char *paramName)
Check if Parameter Name ends with . If yes it is a wild card param.
Definition: webpa_parameter.cpp:732