2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <context_trigger_types_internal.h>
19 #include <package_manager.h>
21 #include "RuleManager.h"
22 #include "ContextMonitor.h"
26 #define RULE_TABLE "context_trigger_rule"
29 using namespace ctx::trigger;
31 static int __stringToInt(std::string str)
34 std::istringstream convert(str);
42 static std::string __intToString(int i)
44 std::ostringstream convert;
46 std::string str = convert.str();
50 RuleManager::RuleManager()
54 RuleManager::~RuleManager()
56 // Release rule instances
57 _D("Release rule instances");
58 for (auto it = __ruleMap.begin(); it != __ruleMap.end(); ++it) {
59 Rule* rule = static_cast<Rule*>(it->second);
61 int error = rule->stop();
62 if (error != ERR_NONE) {
63 _E("Failed to stop rule%d", it->first);
71 bool RuleManager::init()
76 // Create tables into db (rule, template)
77 std::string q1 = std::string("status INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL,")
78 + "package_id TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '',"
79 + "details TEXT DEFAULT '' NOT NULL";
80 ret = __dbManager.createTableSync(RULE_TABLE, q1.c_str(), NULL);
81 IF_FAIL_RETURN_TAG(ret, false, _E, "Create rule table failed");
83 // Before re-enable rules, handle uninstalled app's rules
84 if (__getUninstalledApp() > 0) {
85 error = __clearRuleOfUninstalledPackage(true);
86 IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Failed to remove uninstalled apps' rules while initialization");
88 ret = __reenableRule();
93 void RuleManager::handleRuleOfUninstalledPackage(std::string pkgId)
95 __uninstalledPackages.insert(pkgId);
96 __clearRuleOfUninstalledPackage();
99 int RuleManager::__getUninstalledApp(void)
101 // Return number of uninstalled apps
102 std::string q1 = "SELECT DISTINCT package_id FROM context_trigger_rule";
104 std::vector<Json> record;
105 bool ret = __dbManager.executeSync(q1.c_str(), &record);
106 IF_FAIL_RETURN_TAG(ret, -1, _E, "Query package ids of registered rules failed");
108 std::vector<Json>::iterator vecEnd = record.end();
109 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
112 elem.get(NULL, "package_id", &pkgId);
114 if (isUninstalledPackage(pkgId)) {
115 __uninstalledPackages.insert(pkgId);
119 return __uninstalledPackages.size();
122 bool RuleManager::isUninstalledPackage(std::string pkgId)
124 IF_FAIL_RETURN_TAG(!pkgId.empty(), false, _D, "Empty package id");
126 package_info_h pkgInfo;
127 int error = package_manager_get_package_info(pkgId.c_str(), &pkgInfo);
129 if (error == PACKAGE_MANAGER_ERROR_NONE) {
130 package_info_destroy(pkgInfo);
131 } else if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
132 // Uninstalled package found
133 _D("Uninstalled package found: %s", pkgId.c_str());
136 _E("Failed to get package info(%s): %d", pkgId.c_str(), error);
142 int RuleManager::__clearRuleOfUninstalledPackage(bool isInit)
144 if (__uninstalledPackages.size() <= 0) {
151 _D("Clear uninstalled packages' rule started");
153 std::string pkgList = "(";
154 std::set<std::string>::iterator it = __uninstalledPackages.begin();
155 pkgList += "package_id = '" + *it + "'";
157 for (; it != __uninstalledPackages.end(); ++it) {
158 pkgList += " OR package_id = '" + *it + "'";
162 // After event received, disable all the enabled rules of uninstalled apps
164 std::string q1 = "SELECT row_id FROM context_trigger_rule WHERE status = 2 and (";
168 std::vector<Json> record;
169 ret = __dbManager.executeSync(q1.c_str(), &record);
170 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query enabled rules of uninstalled packages");
172 std::vector<Json>::iterator vecEnd = record.end();
173 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
176 elem.get(NULL, "row_id", &ruleId);
177 error = disableRule(ruleId);
178 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rule");
180 _D("Uninstalled packages' rules are disabled");
183 // Delete rules of uninstalled packages from DB
184 std::string q2 = "DELETE FROM context_trigger_rule WHERE " + pkgList;
185 std::vector<Json> dummy;
186 ret = __dbManager.executeSync(q2.c_str(), &dummy);
187 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to remove rules from db");
188 _D("Uninstalled packages' rules are deleted from db");
190 __uninstalledPackages.clear();
195 int RuleManager::pauseRuleWithItem(std::string& subject)
197 std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=2) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
198 std::vector<Json> record;
199 bool ret = __dbManager.executeSync(q.c_str(), &record);
200 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query row_ids to be paused");
201 IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
203 _D("Pause rules related to %s", subject.c_str());
204 std::vector<Json>::iterator vecEnd = record.end();
205 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
208 elem.get(NULL, "row_id", &rowId);
210 int error = pauseRule(rowId);
211 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rules using custom item");
217 int RuleManager::resumeRuleWithItem(std::string& subject)
219 std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=1) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
220 std::vector<Json> record;
221 bool ret = __dbManager.executeSync(q.c_str(), &record);
222 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query paused rule ids failed");
223 IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
225 _D("Resume rules related to %s", subject.c_str());
227 std::vector<Json>::iterator vecEnd = record.end();
228 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
231 elem.get(NULL, "row_id", &rowId);
233 int error = enableRule(rowId);
234 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to resume rule");
240 bool RuleManager::__reenableRule(void)
243 std::string q = "SELECT row_id FROM context_trigger_rule WHERE status = 2";
245 std::vector<Json> record;
246 bool ret = __dbManager.executeSync(q.c_str(), &record);
247 IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_ids of enabled rules failed");
248 IF_FAIL_RETURN_TAG(record.size() > 0, true, _D, "No rule to re-enable");
250 _D(YELLOW("Re-enable rule started"));
254 std::vector<Json>::iterator vecEnd = record.end();
255 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
258 elem.get(NULL, "row_id", &rowId);
260 error = enableRule(rowId);
261 if (error == ERR_NOT_SUPPORTED) {
262 qRowId += "(row_id = " + __intToString(rowId) + ") OR ";
263 } else if (error != ERR_NONE) {
264 _E("Re-enable rule%d failed(%d)", rowId, error);
267 IF_FAIL_RETURN(!qRowId.empty(), true);
268 qRowId = qRowId.substr(0, qRowId.length() - 4);
270 // For rules which is failed to re-enable
271 std::string qUpdate = "UPDATE context_trigger_rule SET status = 1 WHERE " + qRowId;
272 std::vector<Json> record2;
273 ret = __dbManager.executeSync(qUpdate.c_str(), &record2);
274 IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update rules as paused");
279 bool RuleManager::__ruleDataArrElemEquals(Json& lElem, Json& rElem)
281 std::string lKey, rKey;
282 lElem.get(NULL, CT_RULE_DATA_KEY, &lKey);
283 rElem.get(NULL, CT_RULE_DATA_KEY, &rKey);
284 if (lKey.compare(rKey))
287 int lValCnt, rValCnt, lValOpCnt, rValOpCnt;
288 lValCnt = lElem.getSize(NULL, CT_RULE_DATA_VALUE_ARR);
289 rValCnt = rElem.getSize(NULL, CT_RULE_DATA_VALUE_ARR);
290 lValOpCnt = lElem.getSize(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR);
291 rValOpCnt = rElem.getSize(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR);
292 if (!((lValCnt == rValCnt) && (lValCnt == lValOpCnt) && (lValCnt && rValOpCnt)))
296 std::string lOp, rOp;
297 lElem.get(NULL, CT_RULE_DATA_KEY_OPERATOR, &lOp);
298 rElem.get(NULL, CT_RULE_DATA_KEY_OPERATOR, &rOp);
299 if (lOp.compare(rOp))
303 for (int i = 0; i < lValCnt; i++) {
305 std::string lVal, lValOp;
306 lElem.getAt(NULL, CT_RULE_DATA_VALUE_ARR, i, &lVal);
307 lElem.getAt(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR, i, &lValOp);
309 for (int j = 0; j < lValCnt; j++) {
310 std::string rVal, rValOp;
311 rElem.getAt(NULL, CT_RULE_DATA_VALUE_ARR, j, &rVal);
312 rElem.getAt(NULL, CT_RULE_DATA_VALUE_OPERATOR_ARR, j, &rValOp);
314 if (!lVal.compare(rVal) && !lValOp.compare(rValOp)) {
326 bool RuleManager::__ruleItemEquals(Json& lItem, Json& rItem)
329 std::string lItemName, rItemName;
330 lItem.get(NULL, CT_RULE_EVENT_ITEM, &lItemName);
331 rItem.get(NULL, CT_RULE_EVENT_ITEM, &rItemName);
332 if (lItemName.compare(rItemName))
336 Json lOption, rOption;
337 lItem.get(NULL, CT_RULE_EVENT_OPTION, &lOption);
338 rItem.get(NULL, CT_RULE_EVENT_OPTION, &rOption);
339 if (lOption != rOption)
342 int lDataArrCnt, rDataArrCnt;
343 lDataArrCnt = lItem.getSize(NULL, CT_RULE_DATA_ARR);
344 rDataArrCnt = rItem.getSize(NULL, CT_RULE_DATA_ARR);
345 if (lDataArrCnt != rDataArrCnt)
348 // Compare item operator;
349 if (lDataArrCnt > 1) {
350 std::string lOp, rOp;
351 lItem.get(NULL, CT_RULE_EVENT_OPERATOR, &lOp);
352 rItem.get(NULL, CT_RULE_EVENT_OPERATOR, &rOp);
353 if (lOp.compare(rOp))
357 for (int i = 0; i < lDataArrCnt; i++) {
360 lItem.getAt(NULL, CT_RULE_DATA_ARR, i, &lElem);
362 for (int j = 0; j < lDataArrCnt; j++) {
364 rItem.getAt(NULL, CT_RULE_DATA_ARR, j, &rElem);
366 if (__ruleDataArrElemEquals(lElem, rElem)) {
378 bool RuleManager::__ruleEquals(Json& lRule, Json& rRule)
382 lRule.get(NULL, CT_RULE_EVENT, &lEvent);
383 rRule.get(NULL, CT_RULE_EVENT, &rEvent);
384 if (!__ruleItemEquals(lEvent, rEvent))
387 // Compare conditions
388 int lCondCnt, rCondCnt;
389 lCondCnt = lRule.getSize(NULL, CT_RULE_CONDITION);
390 rCondCnt = rRule.getSize(NULL, CT_RULE_CONDITION);
391 if (lCondCnt != rCondCnt)
395 std::string lOp, rOp;
396 lRule.get(NULL, CT_RULE_OPERATOR, &lOp);
397 rRule.get(NULL, CT_RULE_OPERATOR, &rOp);
398 if (lOp.compare(rOp))
402 for (int i = 0; i < lCondCnt; i++) {
405 lRule.getAt(NULL, CT_RULE_CONDITION, i, &lCond);
407 for (int j = 0; j < lCondCnt; j++) {
409 rRule.getAt(NULL, CT_RULE_CONDITION, j, &rCond);
411 if (__ruleItemEquals(lCond, rCond)) {
421 Json lAction, rAction;
422 lRule.get(NULL, CT_RULE_ACTION, &lAction);
423 rRule.get(NULL, CT_RULE_ACTION, &rAction);
424 if (lAction != rAction)
430 int64_t RuleManager::__getDuplicatedRuleId(std::string pkgId, Json& rule)
432 std::string q = "SELECT row_id, description, details FROM context_trigger_rule WHERE package_id = '";
436 std::vector<Json> record;
437 bool ret = __dbManager.executeSync(q.c_str(), &record);
438 IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_id, details by package id failed");
441 rule.get(NULL, CT_RULE_DETAILS, &rDetails);
443 rule.get(NULL, CT_RULE_DESCRIPTION, &rDesc);
444 std::vector<Json>::iterator vecEnd = record.end();
446 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
451 elem.get(NULL, "details", &dStr);
454 if (__ruleEquals(rDetails, details)) {
456 elem.get(NULL, "row_id", &rowId);
458 // Description comparison
460 elem.get(NULL, "description", &desc);
461 if (rDesc.compare(desc)) {
462 // Only description is changed
463 std::string qUpdate = "UPDATE context_trigger_rule SET description='" + rDesc + "' WHERE row_id = " + __intToString(rowId);
465 std::vector<Json> dummy;
466 ret = __dbManager.executeSync(qUpdate.c_str(), &dummy);
468 _D("Rule%lld description is updated", rowId);
470 _W("Failed to update description of rule%lld", rowId);
481 int RuleManager::__verifyRule(Json& rule, const char* creator)
484 rule.get(NULL, CT_RULE_DETAILS, &details);
486 std::string eventName;
487 rule.get(CT_RULE_DETAILS "." CT_RULE_EVENT, CT_RULE_EVENT_ITEM, &eventName);
489 ContextMonitor* ctxMonitor = ContextMonitor::getInstance();
490 IF_FAIL_RETURN_TAG(ctxMonitor, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
492 IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(eventName), ERR_NOT_SUPPORTED, _I, "Event(%s) is not supported", eventName.c_str());
495 if (!ctxMonitor->isAllowed(creator, eventName.c_str())) {
496 _W("Permission denied for '%s'", eventName.c_str());
497 return ERR_PERMISSION_DENIED;
502 for (int i = 0; rule.getAt(CT_RULE_DETAILS, CT_RULE_CONDITION, i, &it); i++) {
503 std::string condName;
504 it.get(NULL, CT_RULE_CONDITION_ITEM, &condName);
506 IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(condName), ERR_NOT_SUPPORTED, _I, "Condition(%s) is not supported", condName.c_str());
508 if (!ctxMonitor->isAllowed(creator, condName.c_str())) {
509 _W("Permission denied for '%s'", condName.c_str());
510 return ERR_PERMISSION_DENIED;
517 int RuleManager::addRule(std::string creator, const char* pkgId, Json rule, Json* ruleId)
522 // Check if all items are supported && allowed to access
523 int err = __verifyRule(rule, creator.c_str());
524 IF_FAIL_RETURN(err == ERR_NONE, err);
526 // Check if duplicated rule exits
527 if ((rid = __getDuplicatedRuleId(pkgId, rule)) > 0) {
529 ruleId->set(NULL, CT_RULE_ID, rid);
530 _D("Duplicated rule found");
534 // Insert rule to rule table, get rule id
536 std::string description;
538 rule.get(NULL, CT_RULE_DESCRIPTION, &description);
539 rule.get(NULL, CT_RULE_DETAILS, &details);
540 record.set(NULL, "creator", creator);
542 record.set(NULL, "package_id", pkgId);
544 record.set(NULL, "description", description);
546 // Handle timer event
547 trigger::timer::handleTimerEvent(details);
549 record.set(NULL, "details", details.str());
550 ret = __dbManager.insertSync(RULE_TABLE, record, &rid);
551 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Insert rule to db failed");
554 ruleId->set(NULL, CT_RULE_ID, rid);
556 _D("Add rule%d succeeded", (int)rid);
561 int RuleManager::removeRule(int ruleId)
565 // Delete rule from DB
566 std::string query = "DELETE FROM 'context_trigger_rule' where row_id = ";
567 query += __intToString(ruleId);
569 std::vector<Json> record;
570 ret = __dbManager.executeSync(query.c_str(), &record);
571 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Remove rule from db failed");
573 _D("Remove rule%d succeeded", ruleId);
578 int RuleManager::enableRule(int ruleId)
582 std::vector<Json> record;
583 std::vector<Json> dummy;
587 std::string idStr = __intToString(ruleId);
591 // Get rule Json by rule id;
592 query = "SELECT details, package_id FROM context_trigger_rule WHERE row_id = ";
594 error = (__dbManager.executeSync(query.c_str(), &record))? ERR_NONE : ERR_OPERATION_FAILED;
595 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Query rule by rule id failed");
597 record[0].get(NULL, "details", &tmp);
599 record[0].get(NULL, "package_id", &pkgId);
601 // Create a rule instance
602 rule = new(std::nothrow) Rule(ruleId, jRule, pkgId.c_str(), this);
603 IF_FAIL_RETURN_TAG(rule, ERR_OUT_OF_MEMORY, _E, "Failed to create rule instance");
606 error = rule->start();
607 IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Failed to start rule%d", ruleId);
609 // Update db to set 'enabled'
610 query = "UPDATE context_trigger_rule SET status = 2 WHERE row_id = ";
612 error = (__dbManager.executeSync(query.c_str(), &dummy))? ERR_NONE : ERR_OPERATION_FAILED;
613 IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Update db failed");
615 // Add rule instance to __ruleMap
616 __ruleMap[ruleId] = rule;
618 _D(YELLOW("Enable Rule%d succeeded"), ruleId);
628 int RuleManager::disableRule(int ruleId)
633 auto it = __ruleMap.find(ruleId);
634 bool paused = (it == __ruleMap.end());
636 // For 'enabled' rule, not 'paused'
639 Rule* rule = static_cast<Rule*>(it->second);
640 error = rule->stop();
641 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
643 // Remove rule instance from __ruleMap
648 // Update db to set 'disabled' // TODO skip while clear uninstalled rule
649 std::string query = "UPDATE context_trigger_rule SET status = 0 WHERE row_id = ";
650 query += __intToString(ruleId);
651 std::vector<Json> record;
652 ret = __dbManager.executeSync(query.c_str(), &record);
653 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
655 _D(YELLOW("Disable Rule%d succeeded"), ruleId);
659 int RuleManager::pauseRule(int ruleId)
664 auto it = __ruleMap.find(ruleId);
665 IF_FAIL_RETURN_TAG(it != __ruleMap.end(), ERR_OPERATION_FAILED, _E, "Rule instance not found");
668 Rule* rule = static_cast<Rule*>(it->second);
669 error = rule->stop();
670 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
672 // Update db to set 'paused'
673 std::string query = "UPDATE context_trigger_rule SET status = 1 WHERE row_id = ";
675 query += __intToString(ruleId);
676 std::vector<Json> record;
677 ret = __dbManager.executeSync(query.c_str(), &record);
678 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
680 // Remove rule instance from __ruleMap
684 _D(YELLOW("Pause Rule%d"), ruleId);
688 int RuleManager::checkRule(std::string pkgId, int ruleId)
691 std::string q = "SELECT package_id FROM context_trigger_rule WHERE row_id =";
692 q += __intToString(ruleId);
694 std::vector<Json> record;
695 bool ret = __dbManager.executeSync(q.c_str(), &record);
696 IF_FAIL_RETURN_TAG(ret, false, _E, "Query package id by rule id failed");
698 if (record.size() == 0) {
703 record[0].get(NULL, "package_id", &p);
705 if (p.compare(pkgId) == 0) {
712 bool RuleManager::isRuleEnabled(int ruleId)
714 std::string q = "SELECT status FROM context_trigger_rule WHERE row_id =";
715 q += __intToString(ruleId);
717 std::vector<Json> record;
718 bool ret = __dbManager.executeSync(q.c_str(), &record);
719 IF_FAIL_RETURN_TAG(ret, false, _E, "Query enabled by rule id failed");
722 record[0].get(NULL, "status", &status);
724 return (status != 0);
727 int RuleManager::getRuleById(std::string pkgId, int ruleId, Json* requestResult)
729 std::string q = "SELECT description FROM context_trigger_rule WHERE (package_id = '";
731 q += "') and (row_id = ";
732 q += __intToString(ruleId);
735 std::vector<Json> record;
736 bool ret = __dbManager.executeSync(q.c_str(), &record);
737 IF_FAIL_RETURN_TAG(ret, false, _E, "Query rule by rule id failed");
739 if (record.size() == 0) {
741 } else if (record.size() != 1) {
742 return ERR_OPERATION_FAILED;
745 std::string description;
746 record[0].get(NULL, "description", &description);
748 (*requestResult).set(NULL, CT_RULE_ID, ruleId);
749 (*requestResult).set(NULL, CT_RULE_DESCRIPTION, description);
754 int RuleManager::getRuleIds(std::string pkgId, Json* requestResult)
756 (*requestResult) = "{ \"" CT_RULE_ARRAY_ENABLED "\" : [ ] , \"" CT_RULE_ARRAY_DISABLED "\" : [ ] }";
758 std::string q = "SELECT row_id, status FROM context_trigger_rule WHERE (package_id = '";
762 std::vector<Json> record;
763 bool ret = __dbManager.executeSync(q.c_str(), &record);
764 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query rules failed");
766 std::vector<Json>::iterator vecEnd = record.end();
767 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
772 elem.get(NULL, "row_id", &id);
773 elem.get(NULL, "status", &status);
776 (*requestResult).append(NULL, CT_RULE_ARRAY_ENABLED, __stringToInt(id));
777 } else if (status == 0) {
778 (*requestResult).append(NULL, CT_RULE_ARRAY_DISABLED, __stringToInt(id));