#include "DBusClient.h"
#include "rule_validator.h"
-#define KEY_TEMPLATE "templates"
-#define KEY_NAME "name"
-#define KEY_OPTION TYPE_OPTION_STR
-#define KEY_ATTR TYPE_ATTR_STR
#define KEY_KEY "key"
-#define KEY_TYPE "type"
-#define KEY_MIN "min"
-#define KEY_MAX "max"
-#define KEY_VALUES "values"
#define KEY_REF "ref"
typedef std::map<std::string, ctx::Json> template_map_t;
static int string_to_int(std::string str);
static bool check_value_int(ctx::Json& tmpl, std::string key, int value);
static bool check_value_string(ctx::Json& tmpl, std::string key, std::string value);
+static bool check_value_enum(ctx::Json& tmpl, std::string key, std::string value);
static ctx::Json get_template(std::string name);
+static bool check_template_int(ctx::Json& elem);
+static bool check_template_string(ctx::Json& elem);
+static bool check_template_enum(ctx::Json& elem);
+static std::string get_data_type(ctx::Json& elem, std::string& key);
+static bool is_equal_type(std::string& type1, std::string& type2);
int string_to_int(std::string str)
{
// No option needed
ctx::Json opt_tmpl;
- tmpl.get(NULL, KEY_OPTION, &opt_tmpl);
+ tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl);
std::list<std::string> opt_keys;
IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false);
IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false);
ctx::Json opt_tmpl;
- tmpl.get(NULL, KEY_OPTION, &opt_tmpl);
+ tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl);
// Err: Item with no option
std::list<std::string> opt_keys;
IF_FAIL_RETURN(opt_keys.size() > 0, false);
// Err: Invalid option key or Invalid value type
- std::string t_type;
- bool ret = opt_tmpl.get(key.c_str(), KEY_TYPE, &t_type);
- IF_FAIL_RETURN(ret && t_type == TYPE_INT_STR, false);
+ std::string t_type = get_data_type(opt_tmpl, key);
+ IF_FAIL_RETURN(t_type == TYPE_INT_STR, false);
// Err: Inappropriate value
// a. normal case
- ret = check_value_int(opt_tmpl, key, value);
+ bool ret = check_value_int(opt_tmpl, key, value);
IF_FAIL_RETURN(ret, false);
return true;
IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false);
ctx::Json opt_tmpl;
- tmpl.get(NULL, KEY_OPTION, &opt_tmpl);
+ tmpl.get(NULL, TYPE_OPTION_STR, &opt_tmpl);
// Err: ';' for SQL injection
IF_FAIL_RETURN(value.find(';') == std::string::npos, false);
IF_FAIL_RETURN(opt_keys.size() > 0, false);
// Err: Invalid option key or Invalid value type
- std::string t_type;
- bool ret = opt_tmpl.get(key.c_str(), KEY_TYPE, &t_type);
- IF_FAIL_RETURN(ret && t_type == TYPE_STRING_STR, false);
+ std::string t_type = get_data_type(opt_tmpl, key);
+ IF_FAIL_RETURN(t_type == TYPE_STRING_STR || t_type == TYPE_ENUM_STR, false);
// Err: Inappropriate value
// a. spacial case
- if ((name == CT_CONDITION_APP_USE_FREQUENCY || name == CT_CONDITION_COMMUNICATION_FREQUENCY
+ if (t_type == TYPE_STRING_STR && (name == CT_CONDITION_APP_USE_FREQUENCY || name == CT_CONDITION_COMMUNICATION_FREQUENCY
|| name == CT_CONDITION_MUSIC_PLAYBACK_FREQUENCY || name == CT_CONDITION_VIDEO_PLAYBACK_FREQUENCY)
&& key == CONTEXT_TRIGGER_TIME_OF_DAY) {
std::size_t found = value.find("-");
}
// b. normal case
- ret = check_value_string(opt_tmpl, key, value);
- IF_FAIL_RETURN(ret, false);
+ bool ret;
+ if (t_type == TYPE_STRING_STR) {
+ ret = check_value_string(opt_tmpl, key, value);
+ } else if (t_type == TYPE_ENUM_STR) {
+ ret = check_value_enum(opt_tmpl, key, value);
+ }
- return true;
+ return ret;
}
// called by context_trigger_rule_entry_add_comparison_int()
IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false);
ctx::Json attr_tmpl;
- tmpl.get(NULL, KEY_ATTR, &attr_tmpl);
+ tmpl.get(NULL, TYPE_ATTR_STR, &attr_tmpl);
// Err: Invalid attribute key or Invalid value type
- std::string t_type;
- bool ret = attr_tmpl.get(key.c_str(), KEY_TYPE, &t_type);
- IF_FAIL_RETURN(ret && t_type == TYPE_INT_STR, false);
+ std::string t_type = get_data_type(attr_tmpl, key);
+ IF_FAIL_RETURN(t_type == TYPE_INT_STR, false);
// Err: Invalid operator for the value
// a. normal case
- ret = is_valid_operator(TYPE_INT_STR, op);
+ bool ret = is_valid_operator(TYPE_INT_STR, op);
IF_FAIL_RETURN(ret, false);
// b. special case
if (name == CT_EVENT_TIME && key == CONTEXT_TRIGGER_TIME_OF_DAY) {
IF_FAIL_RETURN(tmpl != ctx::Json(EMPTY_JSON_OBJECT), false);
ctx::Json attr_tmpl;
- tmpl.get(NULL, KEY_ATTR, &attr_tmpl);
+ tmpl.get(NULL, TYPE_ATTR_STR, &attr_tmpl);
// Err: ';' for SQL injection
IF_FAIL_RETURN(value.find(';') == std::string::npos, false);
- // Err: Invalid attribute key or Invalid value type
- std::string t_type;
- bool ret = attr_tmpl.get(key.c_str(), KEY_TYPE, &t_type);
- IF_FAIL_RETURN(ret && t_type == TYPE_STRING_STR, false);
+ // Err: Invalid option key or Invalid value type
+ std::string t_type = get_data_type(attr_tmpl, key);
+ IF_FAIL_RETURN(t_type == TYPE_STRING_STR || t_type == TYPE_ENUM_STR, false);
// Err: Invalid operator for the value
- ret = is_valid_operator(TYPE_STRING_STR, op);
+ bool ret = is_valid_operator(t_type, op);
IF_FAIL_RETURN(ret, false);
// Err: Inappropriate value
// a. normal case
- ret = check_value_string(attr_tmpl, key, value);
- IF_FAIL_RETURN(ret, false);
+ if (t_type == TYPE_STRING_STR) {
+ ret = check_value_string(attr_tmpl, key, value);
+ IF_FAIL_RETURN(ret, false);
+ } else if (t_type == TYPE_ENUM_STR) {
+ ret = check_value_enum(attr_tmpl, key, value);
+ IF_FAIL_RETURN(ret, false);
+ }
return true;
}
{
int min, max;
- if (tmpl.get(key.c_str(), KEY_MIN, &min)) {
+ if (tmpl.get(key.c_str(), CT_CUSTOM_MIN, &min)) {
IF_FAIL_RETURN(value >= min, false);
}
- if (tmpl.get(key.c_str(), KEY_MAX, &max)) {
+ if (tmpl.get(key.c_str(), CT_CUSTOM_MAX, &max)) {
IF_FAIL_RETURN(value <= max, false);
}
bool check_value_string(ctx::Json& tmpl, std::string key, std::string value)
{
- // case1: any value is accepted
- if (tmpl.getSize(key.c_str(), KEY_VALUES) <= 0)
- return true;
+ return true;
+}
- // case2: check acceptable value
+bool check_value_enum(ctx::Json& tmpl, std::string key, std::string value)
+{
std::string t_val;
- for (int i = 0; tmpl.getAt(key.c_str(), KEY_VALUES, i, &t_val); i++) {
+ for (int i = 0; tmpl.getAt(key.c_str(), CT_CUSTOM_ENUM, i, &t_val); i++) {
if (t_val == value)
return true;
}
ctx::Json detailed_tmpl;
tmpl.get(NULL, type.c_str(), &detailed_tmpl);
- std::string dt;
- bool ret = detailed_tmpl.get(key.c_str(), KEY_TYPE, &dt);
- IF_FAIL_RETURN(ret, false);
+ std::string dt = get_data_type(detailed_tmpl, key);
+ IF_FAIL_RETURN(dt == TYPE_INT_STR || dt == TYPE_STRING_STR || dt == TYPE_ENUM_STR, false);
ctx::Json temp;
- temp.set(NULL, KEY_NAME, name);
+ temp.set(NULL, CT_CUSTOM_NAME, name);
temp.set(NULL, KEY_KEY, key);
- temp.set(NULL, KEY_TYPE, dt);
+ temp.set(NULL, CT_CUSTOM_TYPE, dt);
temp.set(NULL, KEY_REF, ref_data);
if (type == TYPE_OPTION_STR) {
- jref->append(NULL, KEY_OPTION, temp);
+ jref->append(NULL, TYPE_OPTION_STR, temp);
} else if (type == TYPE_ATTR_STR) {
- jref->append(NULL, KEY_ATTR, temp);
+ jref->append(NULL, TYPE_ATTR_STR, temp);
} else {
return false;
}
return true;;
}
+std::string get_data_type(ctx::Json& elem, std::string& key)
+{
+ std::string data_type;
+ bool ret = elem.get(key.c_str(), CT_CUSTOM_TYPE, &data_type);
+ if (!ret) {
+ int size = elem.getSize(key.c_str(), CT_CUSTOM_ENUM);
+ IF_FAIL_RETURN(size > 0, "");
+ data_type = TYPE_ENUM_STR;
+ }
+ IF_FAIL_RETURN(data_type == TYPE_INT_STR || data_type == TYPE_STRING_STR || data_type == TYPE_ENUM_STR, "");
+
+ return data_type;
+}
+
// called by context_trigger_rule_entry_add_comparison()
-std::string ctx::rule_validator::get_data_type(std::string type, std::string name, std::string key)
+std::string ctx::rule_validator::get_data_type_from_template(std::string type, std::string name, std::string key)
{
ctx::Json tmpl = get_template(name);
IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, "");
ctx::Json detailed_tmpl;
tmpl.get(NULL, type.c_str(), &detailed_tmpl);
- std::string dt;
- bool ret = detailed_tmpl.get(key.c_str(), KEY_TYPE, &dt);
- IF_FAIL_RETURN(ret, "");
-
- return dt;
+ return get_data_type(detailed_tmpl, key);
}
// called by context_trigger_rule_add_entry()
std::map<std::string, std::string> type_map;
ctx::Json ref_data;
- for (int i = 0; ref_info.getAt(NULL, KEY_OPTION, i, &ref_data); i++) {
+ for (int i = 0; ref_info.getAt(NULL, TYPE_OPTION_STR, i, &ref_data); i++) {
std::string ref_key;
ref_data.get(NULL, KEY_REF, &ref_key);
std::string cond_type;
- ref_data.get(NULL, KEY_TYPE, &cond_type);
+ ref_data.get(NULL, CT_CUSTOM_TYPE, &cond_type);
if (type_map.count(ref_key) == 0) {
- type_map[ref_key] = get_data_type(TYPE_ATTR_STR, name, ref_key); // "", if invalid key
+ type_map[ref_key] = get_data_type_from_template(TYPE_ATTR_STR, name, ref_key); // "", if invalid key
}
// Err: Invalid key or Value type not matched
- if (cond_type != type_map[ref_key])
- return false;
+ IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false);
}
- for (int i = 0; ref_info.getAt(NULL, KEY_ATTR, i, &ref_data); i++) {
+ for (int i = 0; ref_info.getAt(NULL, TYPE_ATTR_STR, i, &ref_data); i++) {
std::string ref_key;
ref_data.get(NULL, KEY_REF, &ref_key);
std::string cond_type;
- ref_data.get(NULL, KEY_TYPE, &cond_type);
+ ref_data.get(NULL, CT_CUSTOM_TYPE, &cond_type);
if (type_map.count(ref_key) == 0) {
- type_map[ref_key] = get_data_type(TYPE_ATTR_STR, name, ref_key); // "", if invalid key
+ type_map[ref_key] = get_data_type_from_template(TYPE_ATTR_STR, name, ref_key); // "", if invalid key
}
// Err: Invalid key or Value type not matched
- if (cond_type != type_map[ref_key])
- return false;
+ IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false);
}
return true;
}
+bool is_equal_type(std::string& type1, std::string& type2)
+{
+ // This function regards TYPE_ENUM_STR as TYPE_STRING_STR for referential data
+ if (type1 == type2) {
+ return true;
+ }
+
+ if ((type1 == TYPE_STRING_STR || type1 == TYPE_ENUM_STR) && (type2 == TYPE_STRING_STR || type2 == TYPE_ENUM_STR)) {
+ return true;
+ }
+
+ return false;
+}
+
bool ctx::rule_validator::is_valid_operator(std::string type, std::string op)
{
if (op == CONTEXT_TRIGGER_EQUAL_TO || op == CONTEXT_TRIGGER_NOT_EQUAL_TO) {
for (std::list<std::string>::iterator it = keys.begin(); it != keys.end(); it++) {
std::string key = *it;
- std::string type;
- ret = attr_template.get(key.c_str(), CT_CUSTOM_TYPE, &type);
- IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: type missing");
- IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT || type == CT_CUSTOM_STRING, false, _E, "Custom template: invalid data type");
+ std::string type = get_data_type(attr_template, key);
+ IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT || type == CT_CUSTOM_STRING || type == CT_CUSTOM_ENUM,
+ false, _E, "Custom template: invalid data type");
ctx::Json elem;
attr_template.get(NULL, key.c_str(), &elem);
- std::list<std::string> elem_keys;
- elem.getKeys(&elem_keys);
-
- for (std::list<std::string>::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) {
- std::string elem_key = *it2;
- if (elem_key == CT_CUSTOM_MIN || elem_key == CT_CUSTOM_MAX) {
- IF_FAIL_RETURN_TAG(type == CT_CUSTOM_INT, false, _E, "Custom template: integer type support min, max");
-
- int val;
- ret = attr_template.get(key.c_str(), elem_key.c_str(), &val);
- IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get integer type value");
- } else if (elem_key == CT_CUSTOM_VALUES) {
- IF_FAIL_RETURN_TAG(type == CT_CUSTOM_STRING, false, _E, "Custom template: string type support values");
-
- int size = attr_template.getSize(key.c_str(), CT_CUSTOM_VALUES);
- if (size > 0) {
- std::string val_str;
- for (int i = 0; i < size; i++) {
- ret = attr_template.getAt(key.c_str(), CT_CUSTOM_VALUES, i, &val_str);
- IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get string type value");
- }
- }
- } else {
- IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key");
+ if (type == CT_CUSTOM_INT) {
+ ret = check_template_int(elem);
+ IF_FAIL_RETURN(ret, false);
+ } else if (type == CT_CUSTOM_STRING) {
+ ret = check_template_string(elem);
+ IF_FAIL_RETURN(ret, false);
+ } else if (type == CT_CUSTOM_ENUM) {
+ ret = check_template_enum(elem);
+ IF_FAIL_RETURN(ret, false);
+ }
+ }
+
+ return true;
+}
+
+bool check_template_int(ctx::Json& elem)
+{
+ std::list<std::string> elem_keys;
+ elem.getKeys(&elem_keys);
+
+ bool min;
+ bool max;
+ int min_val;
+ int max_val;
+
+ for (std::list<std::string>::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) {
+ std::string elem_key = *it2;
+ if (elem_key == CT_CUSTOM_MIN) {
+ min = elem.get(NULL, elem_key.c_str(), &min_val);
+ IF_FAIL_RETURN_TAG(min, false, _E, "Custom template: failed to get integer type value");
+ } else if (elem_key == CT_CUSTOM_MAX) {
+ max = elem.get(NULL, elem_key.c_str(), &max_val);
+ IF_FAIL_RETURN_TAG(max, false, _E, "Custom template: failed to get integer type value");
+ } else {
+ IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key");
+ }
+ }
+
+ if (min && max) {
+ IF_FAIL_RETURN_TAG(min_val <= max_val, false, _E, "Custom template: invalid min, max value");
+ }
+
+ return true;
+}
+
+bool check_template_string(ctx::Json& elem)
+{
+ std::list<std::string> elem_keys;
+ elem.getKeys(&elem_keys);
+
+ for (std::list<std::string>::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) {
+ std::string elem_key = *it2;
+ _D("SOM TEST >>> elem key (%s)", elem_key.c_str());
+ IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key");
+ }
+
+ return true;
+}
+
+bool check_template_enum(ctx::Json& elem)
+{
+ std::list<std::string> elem_keys;
+ elem.getKeys(&elem_keys);
+
+ for (std::list<std::string>::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) {
+ std::string elem_key = *it2;
+
+ if (elem_key == CT_CUSTOM_ENUM) {
+ int size = elem.getSize(NULL, CT_CUSTOM_ENUM);
+ IF_FAIL_RETURN_TAG(size > 0, false, _E, "Custom template: invalid enum");
+
+ std::string val_str;
+ for (int i = 0; i < size; i++) {
+ bool ret = elem.getAt(NULL, CT_CUSTOM_ENUM, i, &val_str);
+ IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get string type value");
}
+ } else {
+ IF_FAIL_RETURN_TAG(elem_key == CT_CUSTOM_TYPE, false, _E, "Custom template: invalid key");
}
}