From: Somin Kim Date: Thu, 31 Aug 2017 04:16:24 +0000 (+0900) Subject: Cherry pick from devel/tizen (Version 1.0.5) X-Git-Tag: submit/tizen/20170904.032954^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F90%2F146890%2F2;p=platform%2Fcore%2Fapi%2Fcontext.git Cherry pick from devel/tizen (Version 1.0.5) Fix custom fact validation Fix coding rule [trigger] Added template verification [Trigger] Set trigger rule(sched job) as persistent trigger: set the lower/upper bound of int comparisons considering its logical type trigger: Implement rule info validators on ContextItem trigger: implement API functions using the internal job scheduler API Add custom context name checker (regex) trigger: define API handle structures and static util functions trigger: add the skeleton of the class CustomTemplate, which is used to validate custom facts trigger: add the skeleton of the class ContextItem, which is used to verify event and condition items trigger: add PrivilegeChecker trigger: remove the legacy trigger API implementation Change-Id: Ic088b30db291e293f3ca088769499f40e73d1f38 Signed-off-by: Somin Kim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a8d060..97e5d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,9 @@ INCLUDE(GNUInstallDirs) SET(target ${PROJECT_NAME}) # Dependencies -SET(DEPS "gio-2.0 jsoncpp bundle pkgmgr-info capi-base-common capi-appfw-app-control") +SET(DEPS "gio-2.0 jsoncpp bundle aul pkgmgr-info capi-base-common capi-appfw-app-control") +SET(DEPS "${DEPS} cynara-creds-self cynara-session cynara-client") SET(DEPS "${DEPS} context-app-history-client context-job-scheduler-client") -SET(DEPS "${DEPS} context-common-legacy") # Source Lists FILE(GLOB_RECURSE SRCS src/*.cpp) diff --git a/include/context_trigger.h b/include/context_trigger.h index 173caca..b3780c1 100644 --- a/include/context_trigger.h +++ b/include/context_trigger.h @@ -22,9 +22,8 @@ * @{ */ -#include +#include #include -#include #ifdef __cplusplus extern "C" { diff --git a/packaging/capi-context.spec b/packaging/capi-context.spec index b71ab52..e4dba6c 100644 --- a/packaging/capi-context.spec +++ b/packaging/capi-context.spec @@ -1,6 +1,6 @@ Name: capi-context Summary: Tizen Context Framework Native API -Version: 1.0.4 +Version: 1.0.5 Release: 1 Group: Service Framework/Context License: Apache-2.0 @@ -9,18 +9,17 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(jsoncpp) -#BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-appfw-app-control) +BuildRequires: pkgconfig(cynara-creds-self) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(cynara-client) BuildRequires: pkgconfig(context-app-history-client) BuildRequires: pkgconfig(context-job-scheduler-client) -# Legacy support -BuildRequires: pkgconfig(context-common-legacy) -Requires: context-agent - # Backward compatibility Provides: context diff --git a/src/trigger/ComparisonConverter.cpp b/src/trigger/ComparisonConverter.cpp deleted file mode 100644 index 3d73626..0000000 --- a/src/trigger/ComparisonConverter.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include "ComparisonConverter.h" - -using namespace ctx; - -ComparisonConverter::ComparisonConverter(const char* type, CtxJson1& info) : - __completed(false), - __size(0), - __logicalOp(TRIG_RULE_LOGICAL_DISJUNCTION), - __type(type), - __info(info.str()), - __result(EMPTY_JSON_OBJECT) -{ - __info.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &__key); - __info.get(NULL, OLD_TRIG_RULE_KEY_OPERATOR, &__logicalOp); - __size = __info.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); -} - -int ComparisonConverter::getResult(CtxJson1* result) -{ - if (__result == EMPTY_JSON_OBJECT) - return ERR_INVALID_RULE; - - *result = __result.str(); - - return ERR_NONE; -} - -void ComparisonConverter::__convertComparison() -{ - IF_FAIL_VOID(!__convertEmptyComparison()); - IF_FAIL_VOID(!__convertSingleComparison()); - IF_FAIL_VOID(!__convertMultipleComparison()); - - _E("Failed to convert comparison as new format"); -} - -bool ComparisonConverter::__convertEmptyComparison() -{ - IF_FAIL_RETURN(__size == 0, false); - - CtxJson1 temp = EMPTY_JSON_OBJECT; - __result.set(NULL, __key.c_str(), temp); - - return true; -} - -bool ComparisonConverter::__convertSingleComparison() -{ - IF_FAIL_RETURN(__size == 1, false); - - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, 0, &op); - - __setConvertedOperator(op); - __setComparisonValue(); - - return true; -} - -bool ComparisonConverter::__convertMultipleComparison() -{ - IF_FAIL_RETURN(__size > 1, false); - - if (__checkOneOf()) { - return true; - } else if (__checkNoneOf()) { - return true; - } else if (__checkEtc()) { - return true; - } - - return false; -} - -bool ComparisonConverter::__checkOneOf() -{ - // Or of {==, ...} - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); - IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_EQUAL_TO), false); - - __setConvertedOperator(TRIG_RULE_OP_ONE_OF); - __setComparisonValueArray(); - - return true; -} - -bool ComparisonConverter::__checkNoneOf() -{ - // And of {!=, ...} - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); - IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_NOT_EQUAL_TO), false); - - __setConvertedOperator(TRIG_RULE_OP_NONE_OF); - __setComparisonValueArray(); - - return true; -} - -bool ComparisonConverter::__checkEtc() -{ - return false; -} - -void ComparisonConverter::__setConvertedOperator(std::string op) -{ - __result.set(__key.c_str(), TRIG_RULE_KEY_OPERATOR, op); -} - -void ComparisonConverter::__setComparisonValue() -{ - std::string valStr; - int val; - - if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &valStr)) { - __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); - } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &val)) { - __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, val); - } -} - -void ComparisonConverter::__setComparisonValueArray() -{ - std::string valStr; - int val; - // TODO sort - for (int i = 0; i < __size; i++) { - if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &valStr)) { - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); - } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val)) { - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val); - } - } -} - diff --git a/src/trigger/ComparisonConverter.h b/src/trigger/ComparisonConverter.h deleted file mode 100644 index 9cde85c..0000000 --- a/src/trigger/ComparisonConverter.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CONTEXT_COMPARISON_CONVERTER_H_ -#define _CONTEXT_COMPARISON_CONVERTER_H_ - -#include -#include "TriggerOldRuleTypes.h" - -namespace ctx { - - class ComparisonConverter { - public: - virtual ~ComparisonConverter() {}; - - int getResult(CtxJson1* result); - - protected: - bool __completed; - int __size; - std::string __logicalOp; - std::string __type; - CtxJson1 __info; - CtxJson1 __result; - std::string __key; - - ComparisonConverter(const char* type, CtxJson1& info); - void __convertComparison(); - virtual int __getOperatorCount(std::string op) = 0; - virtual bool __checkEtc(); - void __setConvertedOperator(std::string op); - - private: - bool __convertEmptyComparison(); - bool __convertSingleComparison(); - bool __convertMultipleComparison(); - bool __checkOneOf(); - bool __checkNoneOf(); - void __setComparisonValue(); - void __setComparisonValueArray(); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/ContextItem.cpp b/src/trigger/ContextItem.cpp new file mode 100644 index 0000000..7943d4a --- /dev/null +++ b/src/trigger/ContextItem.cpp @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "PrivilegeChecker.h" +#include "ContextItem.h" + +#define CTX_SCHED_URI_ALARM CTX_SCHED_URI_PREFIX "event/time" +#define CTX_SCHED_URI_CALL CTX_SCHED_URI_PREFIX "state/email" +#define CTX_SCHED_URI_EMAIL CTX_SCHED_URI_PREFIX "event/email" +#define CTX_SCHED_URI_MESSAGE CTX_SCHED_URI_PREFIX "event/message" +#define CTX_SCHED_URI_APP_FREQ CTX_SCHED_URI_PREFIX "stats/app" +#define CTX_SCHED_URI_COMM_FREQ CTX_SCHED_URI_PREFIX "stats/comm" +#define CTX_SCHED_URI_MUSIC_FREQ CTX_SCHED_URI_PREFIX "stats/music" +#define CTX_SCHED_URI_VIDEO_FREQ CTX_SCHED_URI_PREFIX "stats/video" + +#define URI(x) CTX_SCHED_URI_##x +#define NAME(x) CTX_SCHED_ATTR_NAME_##x + +ContextItem::ContextItem(int cx) : + __context(cx), + __uri(NULL) +{ +} + +bool ContextItem::allowed() +{ + return PrivilegeChecker::hasPrivilege(__getPrivilege()); +} + +bool ContextItem::isValid(ctx_sched_job_context_h jobContext) +{ + IF_FAIL_RETURN(jobContext, false); + + struct MandatoryEntry { + const char* uri; + std::vector attributes; + }; + + static std::vector mandatories = { + { URI(ALARM), {NAME(TIME_OF_DAY)} }, + { URI(GEOFENCE), {NAME(PLACE_ID)} }, + { URI(APP_FREQ), {CONTEXT_TRIGGER_APP_ID} } + //TODO + }; + + const char* serialized = ctx_sched_job_context_serialize(jobContext); + IF_FAIL_RETURN(serialized, false); + + Json::Value jCtx; + + try { + Json::Reader reader; + if (!reader.parse(serialized, jCtx)) { + _E("Parsing failed"); + return false; + } + } catch (const Json::Exception& e) { + _E("Exception: %s", e.what()); + return false; + } + + IF_FAIL_RETURN(jCtx.isMember("Attribute"), false); + + Json::Value& attributes = jCtx["Attribute"]; + + for (auto& entry : mandatories) { + if (!STR_EQ(entry.uri, getUri())) + continue; + + for (auto& mandatoryAttr : entry.attributes) { + // The mandatory attribute should be exist + if (!attributes.isMember(mandatoryAttr)) + return false; + + // If exist, at least one target value needs to be designated + if (attributes[mandatoryAttr]["Target"].size() == 0) + return false; + } + + return true; + } + + return true; +} + +bool ContextItem::isValidData(const char* attribute) +{ + return (isValidData(attribute, 1) || isValidData(attribute, static_cast(NULL))); +} + +bool ContextItem::isValidData(const char* attribute, int value) +{ + static std::vector attributeRanges = { + { URI(ALARM), NAME(TIME_OF_DAY), 0, 1439 }, + { URI(TIME), NAME(TIME_OF_DAY), 0, 1439 }, + { URI(TIME), NAME(DAY_OF_MONTH), 1, 31 }, + { URI(BATTERY), NAME(IS_CHARGING), 0, 1 }, + { URI(CHARGER), NAME(IS_CONNECTED), 0, 1 }, + { URI(EARJACK), NAME(IS_CONNECTED), 0, 1 }, + { URI(USB), NAME(IS_CONNECTED), 0, 1 }, + { URI(POWERSAVE), NAME(IS_ENABLED), 0, 1 } + //TODO: unsupported items + }; + + _D("Verify %s, %d", attribute, value); + + return __isValid(attributeRanges, attribute, value); +} + +bool ContextItem::isValidData(const char* attribute, const char* value) +{ + static std::vector attributeValues = { + { URI(ALARM), NAME(DAY_OF_WEEK), {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Weekday", "Weekend"} }, + { URI(TIME), NAME(DAY_OF_WEEK), {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Weekday", "Weekend"} }, + { URI(BATTERY), NAME(LEVEL), {"Empty", "Critical", "Low", "Normal", "High", "Full"} }, + { URI(GEOFENCE), NAME(EVENT), {"In", "Out"} }, + { URI(GPS), NAME(STATE), {"Disabled", "Searching", "Connected"} }, + { URI(EARJACK), NAME(TYPE), {"Normal", "Headset", "Bluetooth"} }, + { URI(WIFI), NAME(STATE), {"Disabled", "Unconnected", "Connected"} }, + { URI(WIFI), NAME(BSSID), {} }, + { URI(STATIONARY), NAME(EVENT), {"Detected"} }, + { URI(WALKING), NAME(EVENT), {"Detected"} }, + { URI(RUNNING), NAME(EVENT), {"Detected"} }, + { URI(IN_VEHICLE), NAME(EVENT), {"Detected"} }, + { URI(CONTACTS_DB), NAME(EVENT), {"Changed"} }, + { URI(CONTACTS_DB), NAME(TYPE), {"MyProfile", "Person"} } + //TODO: unsupported items + }; + + _D("Verify %s, %s", attribute, value); + + return __isValid(attributeValues, attribute, value); +} + +bool ContextItem::isValidOption(const char* attribute) +{ + return (isValidOption(attribute, 1) || isValidOption(attribute, static_cast(NULL))); +} + +bool ContextItem::isValidOption(const char* attribute, int value) +{ + static std::vector attributeRanges = { + { URI(GEOFENCE), NAME(PLACE_ID), 1, INT_MAX } + //TODO: unsupported items + }; + + _D("Verify %s, %d", attribute, value); + + return __isValid(attributeRanges, attribute, value); +} + +bool ContextItem::isValidOption(const char* attribute, const char* value) +{ + static std::vector attributeValues = { + { URI(STATIONARY), NAME(ACCURACY), {"Low", "Normal", "High"} }, + { URI(WALKING), NAME(ACCURACY), {"Low", "Normal", "High"} }, + { URI(RUNNING), NAME(ACCURACY), {"Low", "Normal", "High"} }, + { URI(IN_VEHICLE), NAME(ACCURACY), {"Low", "Normal", "High"} } + //TODO: unsupported items + }; + + _D("Verify %s, %s", attribute, value); + + return __isValid(attributeValues, attribute, value); +} + +bool ContextItem::__isValid(const std::vector& attributeRanges, const char* attribute, int value) +{ + for (auto& range : attributeRanges) { + if (!STR_EQ(range.uri, getUri())) + continue; + + if (!STR_EQ(range.attribute, attribute)) + continue; + + if (value < range.min || value > range.max) + return false; + + return true; + } + + return false; +} + +bool ContextItem::__isValid(const std::vector& attributeValues, const char* attribute, const char* value) +{ + for (auto& values : attributeValues) { + if (!STR_EQ(values.uri, getUri())) + continue; + + if (!STR_EQ(values.attribute, attribute)) + continue; + + // NULL value is a wildcard + if (!value) + return true; + + // Accept any strings + if (values.values.empty()) + return true; + + auto it = std::find_if(values.values.begin(), values.values.end(), + [&value](const char* validValue)->bool { + return STR_EQ(value, validValue); + }); + + if (it == values.values.end()) + return false; + + return true; + } + + return false; +} + +EventItem::EventItem(int event) : + ContextItem(event) +{ +} + +bool EventItem::deprecated() +{ + switch (__context) { + case CONTEXT_TRIGGER_EVENT_TIME: + case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: + case CONTEXT_TRIGGER_EVENT_CALL: + case CONTEXT_TRIGGER_EVENT_EMAIL: + case CONTEXT_TRIGGER_EVENT_MESSAGE: + return true; + default: + return false; + } +} + +const char* EventItem::getUri() +{ + static const std::map uriMap = { + {CONTEXT_TRIGGER_EVENT_TIME, URI(ALARM)}, + {CONTEXT_TRIGGER_EVENT_BATTERY, URI(BATTERY)}, + {CONTEXT_TRIGGER_EVENT_CHARGER, URI(CHARGER)}, + {CONTEXT_TRIGGER_EVENT_GPS, URI(GPS)}, + {CONTEXT_TRIGGER_EVENT_HEADPHONE, URI(EARJACK)}, + {CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE, URI(POWERSAVE)}, + {CONTEXT_TRIGGER_EVENT_USB, URI(USB)}, + {CONTEXT_TRIGGER_EVENT_WIFI, URI(WIFI)}, + {CONTEXT_TRIGGER_EVENT_CALL, URI(CALL)}, + {CONTEXT_TRIGGER_EVENT_EMAIL, URI(EMAIL)}, + {CONTEXT_TRIGGER_EVENT_MESSAGE, URI(MESSAGE)}, + {CONTEXT_TRIGGER_EVENT_CONTACTS, URI(CONTACTS_DB)}, + {CONTEXT_TRIGGER_EVENT_ACTIVITY_STATIONARY, URI(STATIONARY)}, + {CONTEXT_TRIGGER_EVENT_ACTIVITY_WALKING, URI(WALKING)}, + {CONTEXT_TRIGGER_EVENT_ACTIVITY_RUNNING, URI(RUNNING)}, + {CONTEXT_TRIGGER_EVENT_ACTIVITY_IN_VEHICLE, URI(IN_VEHICLE)}, + {CONTEXT_TRIGGER_EVENT_PLACE, URI(GEOFENCE)} + }; + + if (__uri) return __uri; + + auto it = uriMap.find(__context); + + if (it == uriMap.end()) + return NULL; + + return (__uri = it->second); +} + +const char* EventItem::__getPrivilege() +{ + if (CONTEXT_TRIGGER_EVENT_TIME == __context) + return "http://tizen.org/privilege/alarm.set"; + + if (CONTEXT_TRIGGER_EVENT_WIFI == __context) + return "http://tizen.org/privilege/network.get"; + + if (CONTEXT_TRIGGER_EVENT_CALL == __context) + return "http://tizen.org/privilege/telephony"; + + if (CONTEXT_TRIGGER_EVENT_MESSAGE == __context) + return "http://tizen.org/privilege/message.read"; + + if (CONTEXT_TRIGGER_EVENT_CONTACTS == __context) + return "http://tizen.org/privilege/contact.read"; + + if (CONTEXT_TRIGGER_EVENT_PLACE == __context) + return "http://tizen.org/privilege/location"; + + return NULL; +} + +ConditionItem::ConditionItem(int cond) : + ContextItem(cond) +{ +} + +bool ConditionItem::deprecated() +{ + switch (__context) { + case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: + case CONTEXT_TRIGGER_CONDITION_CALL: + case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: + return true; + default: + return false; + } +} + +const char* ConditionItem::getUri() +{ + static const std::map uriMap = { + {CONTEXT_TRIGGER_CONDITION_TIME, URI(TIME)}, + {CONTEXT_TRIGGER_CONDITION_BATTERY, URI(BATTERY)}, + {CONTEXT_TRIGGER_CONDITION_CHARGER, URI(CHARGER)}, + {CONTEXT_TRIGGER_CONDITION_GPS, URI(GPS)}, + {CONTEXT_TRIGGER_CONDITION_HEADPHONE, URI(EARJACK)}, + {CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE, URI(POWERSAVE)}, + {CONTEXT_TRIGGER_CONDITION_USB, URI(USB)}, + {CONTEXT_TRIGGER_CONDITION_WIFI, URI(WIFI)}, + {CONTEXT_TRIGGER_CONDITION_CALL, URI(CALL)}, + {CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY, URI(APP_FREQ)}, + {CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY, URI(COMM_FREQ)}, + {CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY, URI(MUSIC_FREQ)}, + {CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY, URI(VIDEO_FREQ)} + }; + + if (__uri) return __uri; + + auto it = uriMap.find(__context); + + if (it == uriMap.end()) + return NULL; + + return (__uri = it->second); +} + +const char* ConditionItem::__getPrivilege() +{ + if (CONTEXT_TRIGGER_CONDITION_WIFI == __context) + return "http://tizen.org/privilege/network.get"; + + if (CONTEXT_TRIGGER_CONDITION_CALL == __context) + return "http://tizen.org/privilege/telephony"; + + if (CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY == __context) + return "http://tizen.org/privilege/apphistory.read"; + + if (CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY == __context) + return "http://tizen.org/privilege/callhistory.read"; + + if (CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY == __context) + return "http://tizen.org/privilege/mediahistory.read"; + + if (CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY == __context) + return "http://tizen.org/privilege/mediahistory.read"; + + return NULL; +} diff --git a/src/trigger/ContextItem.h b/src/trigger/ContextItem.h new file mode 100644 index 0000000..dd555b9 --- /dev/null +++ b/src/trigger/ContextItem.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_TRIGGER_CONTEXT_ITEM_H__ +#define __CONTEXT_TRIGGER_CONTEXT_ITEM_H__ + +#include +#include + + +class ContextItem { +public: + virtual ~ContextItem() {} + + virtual bool deprecated() = 0; + virtual const char* getUri() = 0; + + bool allowed(); + + bool isValid(ctx_sched_job_context_h jobContext); + + bool isValidData(const char* attribute); + bool isValidData(const char* attribute, int value); + bool isValidData(const char* attribute, const char* value); + + bool isValidOption(const char* attribute); + bool isValidOption(const char* attribute, int value); + bool isValidOption(const char*, const char* value); + +protected: + ContextItem(int cx); + + int __context; + const char* __uri; + +private: + virtual const char* __getPrivilege() = 0; + + struct IntAttributeRange { + const char* uri; + const char* attribute; + int min; + int max; + }; + + struct StrAttributeValues { + const char* uri; + const char* attribute; + std::vector values; + }; + + bool __isValid(const std::vector& attributeRanges, const char* attribute, int value); + bool __isValid(const std::vector& attributeValues, const char* attribute, const char* value); +}; + + +class EventItem : public ContextItem { +public: + EventItem(int event); + + bool deprecated(); + const char* getUri(); + +private: + const char* __getPrivilege(); +}; + + +class ConditionItem : public ContextItem { +public: + ConditionItem(int cond); + + bool deprecated(); + const char* getUri(); + +private: + const char* __getPrivilege(); +}; + + +#endif /* __CONTEXT_TRIGGER_CONTEXT_ITEM_H__ */ diff --git a/src/trigger/CustomTemplate.cpp b/src/trigger/CustomTemplate.cpp new file mode 100644 index 0000000..93031eb --- /dev/null +++ b/src/trigger/CustomTemplate.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "CustomTemplate.h" + +#define CT_KEY_MIN "minimum" +#define CT_KEY_MAX "maximum" +#define CT_KEY_TYPE "type" +#define CT_TYPE_INTEGER "integer" +#define CT_TYPE_STRING "string" +#define CT_TYPE_ENUM "enum" +#define CT_TYPE_DOUBLE "double" + +static std::list __instances; + +CustomTemplate::CustomTemplate(const std::string& name, const Json::Value& templateJson) : + __name(name), + __templateJson(templateJson) +{ +} + +const std::string& CustomTemplate::getName() const +{ + return __name; +} + +int CustomTemplate::match(const std::string& fact) +{ + // true if the given fact is valid w.r.t. the template + Json::Reader reader; + Json::Value factJson; + + // Error: Invalid Json + if (!reader.parse(fact, factJson)) { + _E("Fact: invalid json"); + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + // Error: Invalid fact + IF_FAIL_RETURN_TAG(isValidFact(__templateJson, factJson), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid fact"); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +bool CustomTemplate::isValidFact(const Json::Value& tmplJson, const Json::Value& factJson) +{ + Json::Value::Members keys = factJson.getMemberNames(); + + std::string dataType; + for (auto& key : keys) { + // Get type + if (tmplJson[key].isMember(CT_TYPE_ENUM)) { + dataType = CT_TYPE_ENUM; + } else if (tmplJson[key].isMember(CT_KEY_TYPE)) { + dataType = tmplJson[key][CT_KEY_TYPE].asString(); + } + + if (dataType == CT_TYPE_INTEGER) { + IF_FAIL_RETURN_TAG(factJson[key].isInt(), false, _E, "Custom fact: Invalid data type"); + + int val = factJson[key].asInt(); + if (tmplJson[key].isMember(CT_KEY_MIN)) { + IF_FAIL_RETURN_TAG(val >= tmplJson[key][CT_KEY_MIN].asInt(), false, _E, "Custom fact: Invalid value"); + } + if (tmplJson[key].isMember(CT_KEY_MAX)) { + IF_FAIL_RETURN_TAG(val <= tmplJson[key][CT_KEY_MAX].asInt(), false, _E, "Custom fact: Invalid value"); + } + } else if (dataType == CT_TYPE_STRING) { + IF_FAIL_RETURN_TAG(factJson[key].isString(), false, _E, "Custom fact: Invalid data type"); + } else if (dataType == CT_TYPE_ENUM) { + IF_FAIL_RETURN_TAG(factJson[key].isString(), false, _E, "Custom fact: Invalid data type"); + + std::string val = factJson[key].asString(); + + bool found = false; + for (unsigned int i = 0; i < tmplJson[key][CT_TYPE_ENUM].size(); i++) { + std::string tmplValue = tmplJson[key][CT_TYPE_ENUM][i].asString(); + if (tmplValue == val) + found = true; + } + IF_FAIL_RETURN_TAG(found, false, _E, "Custom fact: Invalid value"); + } else { + _E("Custom fact: Invalid data type"); + return false; + } + } + return true; +} + +bool CustomTemplate::isValidTemplate(const Json::Value& tmplJson) +{ + bool success = false; + Json::Value::Members keys = tmplJson.getMemberNames(); + + std::string dataType; + for (auto& key : keys) { + // Get type + if (tmplJson[key].isMember(CT_TYPE_ENUM)) { + success = tmplJson[key][CT_TYPE_ENUM].isArray(); + IF_FAIL_RETURN_TAG(success, false, _E, "Invalid template"); + dataType = CT_TYPE_ENUM; + } else if (tmplJson[key].isMember(CT_KEY_TYPE)) { + dataType = tmplJson[key][CT_KEY_TYPE].asString(); + IF_FAIL_RETURN_TAG(dataType == CT_TYPE_INTEGER || dataType == CT_TYPE_STRING, + false, _E, "Invalid template"); + } + + if (dataType == CT_TYPE_INTEGER) { + success = checkTemplateInt(tmplJson[key]); + IF_FAIL_RETURN(success, false); + } else if (dataType == CT_TYPE_STRING) { + success = checkTemplateString(tmplJson[key]); + IF_FAIL_RETURN(success, false); + } else if (dataType == CT_TYPE_ENUM) { + success = checkTemplateEnum(tmplJson[key]); + IF_FAIL_RETURN(success, false); + } + } + + return true; +} + +bool CustomTemplate::checkTemplateInt(const Json::Value& elem) +{ + bool min = false; + bool max = false; + int minVal = 0; + int maxVal = 0; + + Json::Value::Members elemKeys = elem.getMemberNames(); + + for (auto& elemKey : elemKeys) { + if (elemKey == CT_KEY_MIN) { + min = true; + minVal = elem[elemKey].asInt(); + } else if (elemKey == CT_KEY_MAX) { + max = true; + maxVal = elem[elemKey].asInt(); + } else { + IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key"); + } + } + + if (min && max) { + IF_FAIL_RETURN_TAG(minVal <= maxVal, false, _E, "Invalid min, max value"); + } + + return true; +} + +bool CustomTemplate::checkTemplateString(const Json::Value& elem) +{ + Json::Value::Members elemKeys = elem.getMemberNames(); + + for (auto& elemKey : elemKeys) { + IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key"); + } + + return true; +} + +bool CustomTemplate::checkTemplateEnum(const Json::Value& elem) +{ + Json::Value::Members elemKeys = elem.getMemberNames(); + + for (auto& elemKey : elemKeys) { + if (elemKey == CT_TYPE_ENUM) { + IF_FAIL_RETURN_TAG(!elem[CT_TYPE_ENUM].empty(), false, _E, "Invalid enum"); + + for (unsigned int i = 0; i < elem[CT_TYPE_ENUM].size(); i++) { + IF_FAIL_RETURN_TAG(elem[CT_TYPE_ENUM][i].isString(), false, _E, "Enum value sholud be string"); + } + } else { + IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key"); + } + } + + return true; +} + +int CustomTemplate::add(const std::string& name, const std::string& attrTmpl) +{ + static std::regex nameRegex(R"~(^[\w-\._\/]+$)~", std::regex::optimize); + IF_FAIL_RETURN_TAG(std::regex_match(name, nameRegex), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Invalid name"); + + Json::Reader reader; + Json::Value tmplJson; + + // Error: Invalid Json + if (!reader.parse(attrTmpl, tmplJson)) { + _E("Template: invalid json"); + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + // Error: already exist + CustomTemplate* tmpl = get(name); + if (tmpl) { + if (tmplJson == tmpl->__templateJson) { + return CONTEXT_TRIGGER_ERROR_NONE; + } else { + _E("Template already exists"); + return CONTEXT_TRIGGER_ERROR_DATA_EXIST; + } + } + + // Error: Invalid template + IF_FAIL_RETURN_TAG(isValidTemplate(tmplJson), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); + + __instances.emplace_back(name, tmplJson); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +void CustomTemplate::remove(const std::string& name) +{ + __instances.remove_if( + [&name](const CustomTemplate& tmpl)->bool { + return tmpl.getName() == name; + }); +} + +CustomTemplate* CustomTemplate::get(const std::string& name) +{ + for (auto& tmpl : __instances) { + if (tmpl.getName() == name) + return &tmpl; + } + + return NULL; +} diff --git a/src/trigger/CustomTemplate.h b/src/trigger/CustomTemplate.h new file mode 100644 index 0000000..2bbf579 --- /dev/null +++ b/src/trigger/CustomTemplate.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_TRIGGER_CUSTOM_TEMPLATE_H__ +#define __CONTEXT_TRIGGER_CUSTOM_TEMPLATE_H__ + +#include +#include +#include +#include + +class CustomTemplate { +public: + CustomTemplate(const std::string& name, const Json::Value& templateJson); + + const std::string& getName() const; + int match(const std::string& fact); + + static int add(const std::string& name, const std::string& attrTmpl); + static void remove(const std::string& name); + static CustomTemplate* get(const std::string& name); + + static bool isValidTemplate(const Json::Value& tmplJson); + static bool checkTemplateInt(const Json::Value& elem); + static bool checkTemplateString(const Json::Value& elem); + static bool checkTemplateEnum(const Json::Value& elem); + static bool isValidFact(const Json::Value& tmplJson, const Json::Value& factJson); + + +private: + std::string __name; + Json::Value __templateJson; +}; + +#endif diff --git a/src/trigger/IntComparisonConverter.cpp b/src/trigger/IntComparisonConverter.cpp deleted file mode 100644 index 9f1a4e5..0000000 --- a/src/trigger/IntComparisonConverter.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include "IntComparisonConverter.h" - -using namespace ctx; - -IntComparisonConverter::IntComparisonConverter(CtxJson1 info) : - ComparisonConverter(TRIG_TMPL_TYPE_INTEGER, info) -{ - if (__size >= 2) { - for (int i = 0; i < __size; i++) { - int val; - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val); - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); - - __insertComparisonInfo(op, val); - } - __sort(); - } - - __convertComparison(); -} - -void IntComparisonConverter::__insertComparisonInfo(std::string op, int val) -{ - IntComparisonMap::iterator it = __map.find(op); - if (it == __map.end()) { - IntList list; - list.push_back(val); - __map[op] = list; - } else { - it->second.push_back(val); - } -} - -void IntComparisonConverter::__sort() -{ - for (IntComparisonMap::iterator it = __map.begin(); it != __map.end(); it++) { - it->second.sort(); - } -} - -int IntComparisonConverter::__getOperatorCount(std::string op) -{ - return __map[op].size(); -} - -int IntComparisonConverter::__getMaxValue(std::string op) -{ - return __map[op].back(); -} - -int IntComparisonConverter::__getMinValue(std::string op) -{ - return __map[op].front(); -} - -bool IntComparisonConverter::__checkEtc() -{ - // Simple version in, notIn - IF_FAIL_RETURN(!__checkIn(), true); - IF_FAIL_RETURN(!__checkNotIn(), true); - - return false; -} - - -bool IntComparisonConverter::__checkIn() -{ - // And of { >= min, <= max } - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); - IF_FAIL_RETURN(__size == 2, false); - IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO) == 1 - && __getOperatorCount(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO) == 1, false); - - int maxOfGE = __getMaxValue(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO); - int minOfLE = __getMinValue(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO); - IF_FAIL_RETURN(maxOfGE <= minOfLE, false); - - __setConvertedOperator(TRIG_RULE_OP_IN); - __setComparisonValue(maxOfGE, minOfLE); - - return true; -} - -bool IntComparisonConverter::__checkNotIn() -{ - // Or of { < min, > max } - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); - IF_FAIL_RETURN(__size == 2, false); - IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN) == 1 - && __getOperatorCount(TRIG_RULE_OP_LESS_THAN) == 1, false); - - int maxOfL = __getMaxValue(TRIG_RULE_OP_LESS_THAN); - int minOfG = __getMinValue(TRIG_RULE_OP_GREATER_THAN); - IF_FAIL_RETURN(maxOfL <= minOfG, false); - - __setConvertedOperator(TRIG_RULE_OP_NOT_IN); - __setComparisonValue(maxOfL, minOfG); - - return true; -} - -void IntComparisonConverter::__setComparisonValue(int val1, int val2) -{ - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val1); - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val2); -} - diff --git a/src/trigger/IntComparisonConverter.h b/src/trigger/IntComparisonConverter.h deleted file mode 100644 index f18cd2b..0000000 --- a/src/trigger/IntComparisonConverter.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CONTEXT_INT_COMPARISON_CONVERTER_H_ -#define _CONTEXT_INT_COMPARISON_CONVERTER_H_ - -#include -#include -#include "ComparisonConverter.h" - -namespace ctx { - - class IntComparisonConverter : public ComparisonConverter { - typedef std::list IntList; // Integer value list - typedef std::map IntComparisonMap; // { operator, IntList } - - public: - IntComparisonConverter(CtxJson1 info); - ~IntComparisonConverter() {}; - - private: - IntComparisonMap __map; - - void __insertComparisonInfo(std::string op, int val); - void __sort(); - int __getMaxValue(std::string op); - int __getMinValue(std::string op); - - bool __checkIn(); - bool __checkNotIn(); - void __setComparisonValue(int val1, int val2); - /* From CompariconConverter */ - int __getOperatorCount(std::string op); - bool __checkEtc(); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_INT_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/PrivilegeChecker.cpp b/src/trigger/PrivilegeChecker.cpp new file mode 100644 index 0000000..fe39067 --- /dev/null +++ b/src/trigger/PrivilegeChecker.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "PrivilegeChecker.h" + +#define CACHE_SIZE 10 + +static GMutex __cynaraMutex; + +PrivilegeChecker::PrivilegeChecker() : + __client(NULL), + __session(NULL), + __user(NULL), + __cynara(NULL) +{ + cynara_creds_self_get_client(CLIENT_METHOD_DEFAULT, &__client); + cynara_creds_self_get_user(USER_METHOD_DEFAULT, &__user); + + __session = cynara_session_from_pid(getpid()); + + if (!__client || !__user || !__session) { + _E("Self credentialing failed"); + return; + } + + cynara_configuration* conf = NULL; + int err = cynara_configuration_create(&conf); + IF_FAIL_VOID_TAG(err == CYNARA_API_SUCCESS, _E, "Cynara configuration creation failed"); + + err = cynara_configuration_set_cache_size(conf, CACHE_SIZE); + if (err != CYNARA_API_SUCCESS) { + _E("Cynara cache size set failed"); + cynara_configuration_destroy(conf); + return; + } + + err = cynara_initialize(&__cynara, conf); + cynara_configuration_destroy(conf); + if (err != CYNARA_API_SUCCESS) { + _E("Cynara initialization failed"); + __cynara = NULL; + return; + } + + _I("Cynara initialized"); +} + +PrivilegeChecker::~PrivilegeChecker() +{ + g_free(__client); + g_free(__session); + g_free(__user); + + if (__cynara) + cynara_finish(__cynara); +} + +bool PrivilegeChecker::hasPrivilege(const char* privil) +{ + if (!privil) + return true; + + ctx::ScopeMutex sm(&__cynaraMutex); + + static PrivilegeChecker checker; + + return checker.__hasPrivilege(privil); +} + +bool PrivilegeChecker::__hasPrivilege(const char* privil) +{ + IF_FAIL_RETURN_TAG(__cynara, false, _E, "Cynara not initialized"); + int ret = cynara_check(__cynara, __client, __session, __user, privil); + _D("Check %s -> %d", privil, ret); + return (ret == CYNARA_API_ACCESS_ALLOWED); +} diff --git a/src/trigger/PrivilegeChecker.h b/src/trigger/PrivilegeChecker.h new file mode 100644 index 0000000..3e272da --- /dev/null +++ b/src/trigger/PrivilegeChecker.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_TRIGGER_PRIVILEGE_CHECKER_H__ +#define __CONTEXT_TRIGGER_PRIVILEGE_CHECKER_H__ + +#include +#include + +class PrivilegeChecker { +public: + static bool hasPrivilege(const char* privil); + +private: + PrivilegeChecker(); + ~PrivilegeChecker(); + + bool __hasPrivilege(const char* privil); + + char* __client; + char* __session; + char* __user; + cynara* __cynara; +}; + +#endif /* __CONTEXT_TRIGGER_PRIVILEGE_CHECKER_H__ */ diff --git a/src/trigger/StringComparisonConverter.cpp b/src/trigger/StringComparisonConverter.cpp deleted file mode 100644 index f4c1757..0000000 --- a/src/trigger/StringComparisonConverter.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include "StringComparisonConverter.h" - -using namespace ctx; - -StringComparisonConverter::StringComparisonConverter(CtxJson1 info) : - ComparisonConverter(TRIG_TMPL_TYPE_STRING, info) -{ - if (__size >= 2) { - for (int i = 0; i < __size; i++) { - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); - - __map[op]++; - } - } - - __convertComparison(); -} - - -int StringComparisonConverter::__getOperatorCount(std::string op) -{ - return __map[op]; -} - diff --git a/src/trigger/StringComparisonConverter.h b/src/trigger/StringComparisonConverter.h deleted file mode 100644 index 69fb110..0000000 --- a/src/trigger/StringComparisonConverter.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CONTEXT_STRING_COMPARISON_CONVERTER_H_ -#define _CONTEXT_STRING_COMPARISON_CONVERTER_H_ - -#include -#include -#include "ComparisonConverter.h" - -namespace ctx { - - class StringComparisonConverter : public ComparisonConverter { - typedef std::map StringComparisonMap; - - public: - StringComparisonConverter(CtxJson1 info); - ~StringComparisonConverter() {}; - - private: - StringComparisonMap __map; - - /* From CompariconConverter */ - int __getOperatorCount(std::string op); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_STRING_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/TriggerOldRuleTypes.h b/src/trigger/TriggerOldRuleTypes.h deleted file mode 100644 index fe85d67..0000000 --- a/src/trigger/TriggerOldRuleTypes.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ -#define _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ - -/* Old Rule Keys */ -#define OLD_TRIG_RULE_KEY_EVENT "EVENT" -#define OLD_TRIG_RULE_KEY_EVENT_ITEM "ITEM_NAME" -#define OLD_TRIG_RULE_KEY_EVENT_OPERATOR "ITEM_OPERATOR" -#define OLD_TRIG_RULE_KEY_EVENT_OPTION "OPTION" -#define OLD_TRIG_RULE_KEY_OPERATOR "OPERATOR" -#define OLD_TRIG_RULE_KEY_CONDITION "CONDITION" -#define OLD_TRIG_RULE_KEY_CONDITION_ITEM "ITEM_NAME" -#define OLD_TRIG_RULE_KEY_CONDITION_OPERATOR "ITEM_OPERATOR" -#define OLD_TRIG_RULE_KEY_CONDITION_OPTION "OPTION" -#define OLD_TRIG_RULE_KEY_DATA_ARR "DATA_ARR" -#define OLD_TRIG_RULE_KEY_DATA_KEY "DATA_KEY" -#define OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR "DATA_KEY_OPERATOR" -#define OLD_TRIG_RULE_KEY_DATA_VALUE_ARR "DATA_VALUE_ARR" -#define OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR "DATA_VALUE_OPER_ARR" - -#endif /* _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ */ diff --git a/src/trigger/context_trigger.cpp b/src/trigger/context_trigger.cpp index de50622..730bbac 100644 --- a/src/trigger/context_trigger.cpp +++ b/src/trigger/context_trigger.cpp @@ -14,362 +14,445 @@ * limitations under the License. */ -//#include -//#include +#include +#include +#include +#include +#include + #include -#include -#include +#include #include + +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include "TriggerOldRuleTypes.h" -#include "rule_validator.h" -#include "rule_util.h" - -#define TRIGGER_DEPRECATED_FUNCTION_MSG "DEPRECATION WARNING: %s is deprecated and will be removed from next release." -#define TRIGGER_DEPRECATED_EVENT_MSG "DEPRECATION WARNING: This event is deprecated and will be removed from next release." -#define TRIGGER_DEPRECATED_CONDITION_MSG "DEPRECATION WARNING: This condition is deprecated and will be removed from next release." - -//#define DOUBLE_PRECISION 2 -#define TYPE_EVENT 1 -#define TYPE_CONDITION 2 -#define TYPE_OPTION TRIG_TMPL_KEY_OPTION -#define TYPE_ATTRIBUTE TRIG_TMPL_KEY_ATTRIBUTE -#define OLD_INITIAL_ENTRY "{ \"" OLD_TRIG_RULE_KEY_DATA_ARR "\" : [ ] }" -#define INITIAL_REF "{ \"" TRIG_TMPL_KEY_OPTION "\" : [ ], \"" TRIG_TMPL_KEY_ATTRIBUTE "\" : [ ] }" -#define INITIAL_RULE \ -"{ \"" TRIG_RULE_KEY_DESCRIPTION "\" : \"\", \"" TRIG_RULE_KEY_EVENT "\" : { }, \"" TRIG_RULE_KEY_CONDITION "\" : [ ], \"" \ -TRIG_RULE_KEY_ACTION "\" : { }, \"" _TRIG_RULE_KEY_EXTRA "\": { } }" -#define INITIAL_ENTRY "{ \"" TRIG_RULE_KEY_OPTION "\": { }, \"" TRIG_RULE_KEY_COMPARISON "\" : { } }" - -static ctx::DBusClient __dbusClient; - -static int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); -static int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); -static std::string convert_event_to_string(context_trigger_event_e item); -static std::string convert_condition_to_string(context_trigger_condition_e item); -static std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type); -static std::string get_custom_item_subject(const char* provider, const char* item); -static bool event_is_deprecated(context_trigger_event_e item); -static bool condition_is_deprecated(context_trigger_condition_e item); - -//static std::string int_to_string(int value); -//static std::string double_to_string(int value); + +#include "PrivilegeChecker.h" +#include "ContextItem.h" +#include "CustomTemplate.h" + +#define _DEPRECATED_FUNC _W("DEPRECATION WARNING: %s is deprecated and will be removed from next release.", __FUNCTION__) +#define _DEPRECATED_EVENT(id) _W("DEPRECATION WARNING: This event (%d) is deprecated and will be removed from next release.", (id)) +#define _DEPRECATED_COND(id) _W("DEPRECATION WARNING: This condition (%d) is deprecated and will be removed from next release.", (id)) + +#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, E_NO_MEM, _E, E_STR_ALLOC) +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, E_PARAM, _E, "Parameter null") +#define INIT_SCHED IF_FAIL_RETURN_TAG(__scheduler.get(), E_SUPPORT, _E, "Job scheduler is not supported") +#define SCHED __scheduler.get() + +#define PKG_ID_LENGTH 128 + +enum EntryCategory { + CATEGORY_EVENT = 1, + CATEGORY_CONDITION = 2 +}; + +enum class OpType { + UNDEFINED = 0, + EQ, // equals to + NE, // not equals to + GT, // greater than + GE, // greater than or equals to + LT, // less than + LE // less than or equals to +}; typedef struct _context_trigger_rule_s { - ctx::CtxJson1 jold_rule; - ctx::CtxJson1 jrule; // description, event{}, condition[], action{}, _extra{} - ctx::CtxJson1 jref; - - _context_trigger_rule_s() { - jold_rule = EMPTY_JSON_OBJECT; - jrule = INITIAL_RULE; - jref = INITIAL_REF; + ctx_sched_job_h job; + bool readOnly; + bool hasEvent; + bool hasAction; + std::set conditions; + + _context_trigger_rule_s() : + job(NULL), readOnly(false), hasEvent(false), hasAction(false) + { + ctx_sched_job_create_on_demand(&job); + } + + _context_trigger_rule_s(ctx_sched_job_h j) : + job(j), readOnly(true), hasEvent(true), hasAction(true) + { + } + + ~_context_trigger_rule_s() + { + ctx_sched_job_destroy(job); } } _context_trigger_rule_h; + typedef struct _context_trigger_rule_entry_s { + int category; int type; - ctx::CtxJson1 jentry; - ctx::CtxJson1 jref; + std::string uri; + ctx_sched_job_context_h jobContext; + + struct Bound { + bool conjunction; + int gt; + int ge; + int lt; + int le; + + Bound(bool conj) : + conjunction(conj) + { + if (conj) { + gt = INT_MIN; + ge = INT_MIN; + lt = INT_MAX; + le = INT_MAX; + } else { + gt = INT_MAX; + ge = INT_MAX; + lt = INT_MIN; + le = INT_MIN; + } + } + }; - _context_trigger_rule_entry_s(int t): type(t) { - jentry = OLD_INITIAL_ENTRY; + std::map attributes; - if (t == TYPE_CONDITION) { - jref = INITIAL_REF; - } + _context_trigger_rule_entry_s(int c, int t, const char* u) : + category(c), type(t), uri(u), jobContext(NULL) + { + if (category == CATEGORY_EVENT) + ctx_sched_job_trigger_create(uri.c_str(), &jobContext); + else + ctx_sched_job_requirement_create(uri.c_str(), false, &jobContext); + } + + ~_context_trigger_rule_entry_s() + { + ctx_sched_job_context_destroy(jobContext); } } _context_trigger_rule_entry_h; -// Add a rule -SO_EXPORT int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id) + +namespace { + class Scheduler { + private: + ctx_sched_h __scheduler; + + public: + Scheduler() : __scheduler(NULL) {} + + ~Scheduler() + { + ctx_sched_destroy(__scheduler); + } + + ctx_sched_h get() + { + if (__scheduler == NULL) + ctx_sched_create(&__scheduler); + + return __scheduler; + } + }; +} + +static OpType __getOpType(const char* opStr) { - _D("BEGIN"); - ASSERT_NOT_NULL(rule && rule_id); + if (STR_EQ(opStr, CONTEXT_TRIGGER_EQUAL_TO)) + return OpType::EQ; - // Err: No event - if (!ctx::rule_util::isEventSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + if (STR_EQ(opStr, CONTEXT_TRIGGER_NOT_EQUAL_TO)) + return OpType::NE; - // Err: No action - if (!ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + if (STR_EQ(opStr, CONTEXT_TRIGGER_GREATER_THAN)) + return OpType::GT; - // If condition size isn't greater than 1, update logical operator as default - if ((rule->jrule).getSize(NULL, TRIG_RULE_KEY_CONDITION) <= 1) { - (rule->jrule).set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, TRIG_RULE_LOGICAL_CONJUNCTION); - } + if (STR_EQ(opStr, CONTEXT_TRIGGER_GREATER_THAN_OR_EQUAL_TO)) + return OpType::GE; - ctx::CtxJson1 jrule_id; - int error = __dbusClient.write(SUBJ_TRIGGER_ADD, rule->jrule, &jrule_id); + if (STR_EQ(opStr, CONTEXT_TRIGGER_LESS_THAN)) + return OpType::LT; - if (error == ERR_NONE) { - jrule_id.get(NULL, TRIG_KEY_RULE_ID, rule_id); - } + if (STR_EQ(opStr, CONTEXT_TRIGGER_LESS_THAN_OR_EQUAL_TO)) + return OpType::LE; + + return OpType::UNDEFINED; +} + +static std::string __get_custom_uri(std::string name, std::string provider) +{ + std::string uri("http://"); + uri += provider + "/context/custom/" + name; + return uri; +} + +static const char* __get_pkg_id() +{ + static char pkgId[PKG_ID_LENGTH] = {0}; + + if (strlen(pkgId) > 0) + return pkgId; + + aul_app_get_pkgid_bypid(getpid(), pkgId, PKG_ID_LENGTH); + + if (strlen(pkgId) > 0) + return pkgId; + + return NULL; +} + +static ContextItem* __get_context_item(context_trigger_rule_entry_h entry) +{ + ContextItem* contextItem = NULL; + + if (entry->category == CATEGORY_EVENT) + contextItem = new(std::nothrow) EventItem(entry->type); + else + contextItem = new(std::nothrow) ConditionItem(entry->type); - return error; + if (!contextItem) + _E_ALLOC; + + return contextItem; } -// Remove a rule -SO_EXPORT int context_trigger_remove_rule(int rule_id) +static Scheduler __scheduler; + + +EXPORT_API int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id) { - _D("BEGIN"); + INIT_SCHED; + ASSERT_NOT_NULL(rule && rule_id); + + int err = ctx_sched_add_job(SCHED, rule->job, rule_id); + + if (err == E_PARAM) + return E_INV_RULE; + + return err; +} + +EXPORT_API int context_trigger_remove_rule(int rule_id) +{ + INIT_SCHED; if (rule_id <= 0) return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); - int error = __dbusClient.write(SUBJ_TRIGGER_REMOVE, jrule_id, NULL); + int err = ctx_sched_remove_job(SCHED, rule_id); - if (error == ERR_ALREADY_STARTED) { // Rule is still enabled. + if (err == E_RULE_ON) return CONTEXT_TRIGGER_ERROR_RULE_ENABLED; - } else if (error == ERR_NO_DATA) { + else if (err == E_PARAM) return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - return error; + return err; } -// Enable a rule -SO_EXPORT int context_trigger_enable_rule(int rule_id) +EXPORT_API int context_trigger_enable_rule(int rule_id) { - _D("BEGIN"); + INIT_SCHED; if (rule_id <= 0) return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); + int err = ctx_sched_start_job(SCHED, rule_id); - int req_id; // Useless in context_trigger - int error = __dbusClient.subscribe(SUBJ_TRIGGER_ENABLE, jrule_id, &req_id, NULL); - - if (error == ERR_NO_DATA) { + if (err == E_PARAM) return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - return error; + return err; } -// Disable a rule -SO_EXPORT int context_trigger_disable_rule(int rule_id) +EXPORT_API int context_trigger_disable_rule(int rule_id) { - _D("BEGIN"); + INIT_SCHED; if (rule_id <= 0) return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); - int error = __dbusClient.write(SUBJ_TRIGGER_DISABLE, jrule_id, NULL); + int err = ctx_sched_stop_job(SCHED, rule_id); - if (error == ERR_NO_DATA) { + if (err == E_PARAM) return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - return error; + return err; +} + +static bool __foreach_job_cb(ctx_sched_h scheduler, ctx_sched_job_h job, void *user_data) +{ + auto jobs = static_cast*>(user_data); + jobs->push_back(job); + return true; } -SO_EXPORT int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count) +EXPORT_API int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(enabled_rule_ids && enabled_rule_count && disabled_rule_ids && disabled_rule_count); - int req_id; - ctx::CtxJson1 data_read; - int error = __dbusClient.readSync(SUBJ_TRIGGER_GET_RULE_IDS, NULL, &req_id, &data_read); + std::vector jobs; - if (error != ERR_NONE) { - return error; + int err = ctx_sched_foreach_job(SCHED, __foreach_job_cb, &jobs); + + if (err == E_NO_DATA) { + *enabled_rule_ids = NULL; + *enabled_rule_count = 0; + *disabled_rule_ids = NULL; + *disabled_rule_count = 0; + return E_NONE; } - // Enabled rules - int* e_arr = NULL; - *enabled_rule_count = data_read.getSize(NULL, TRIG_KEY_ENABLED_IDS); + IF_FAIL_RETURN(IS_SUCCESS(err), err); - if (*enabled_rule_count > 0) { - e_arr = static_cast(g_malloc((*enabled_rule_count) * sizeof(int))); - IF_FAIL_RETURN_TAG(e_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + std::vector startedJobIds; + std::vector stoppedJobIds; - int id; - for (int i = 0; data_read.getAt(NULL, TRIG_KEY_ENABLED_IDS, i, &id); i++) { - *(e_arr + i) = id; - } + for (auto& job : jobs) { + bool started = false; + int jobId = 0; + + ctx_sched_job_is_started(job, &started); + ctx_sched_job_get_id(job, &jobId); + ctx_sched_job_destroy(job); + + if (started) + startedJobIds.push_back(jobId); + else + stoppedJobIds.push_back(jobId); } - *enabled_rule_ids = e_arr; - // Disabled rules - int* d_arr = NULL; - *disabled_rule_count = data_read.getSize(NULL, TRIG_KEY_DISABLED_IDS); + *enabled_rule_count = startedJobIds.size(); - if (*disabled_rule_count > 0) { - d_arr = static_cast(g_malloc((*disabled_rule_count) * sizeof(int))); - IF_FAIL_RETURN_TAG(d_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + if (*enabled_rule_count > 0) + *enabled_rule_ids = static_cast(g_memdup(startedJobIds.data(), startedJobIds.size() * sizeof(int))); + else + *enabled_rule_ids = NULL; - int id; - for (int i = 0; data_read.getAt(NULL, TRIG_KEY_DISABLED_IDS, i, &id); i++) { - *(d_arr + i) = id; - } - } - *disabled_rule_ids = d_arr; + *disabled_rule_count = stoppedJobIds.size(); - return error; -} + if (*disabled_rule_count > 0) + *disabled_rule_ids = static_cast(g_memdup(stoppedJobIds.data(), stoppedJobIds.size() * sizeof(int))); + else + *disabled_rule_ids = NULL; + return E_NONE; +} -SO_EXPORT int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule) +EXPORT_API int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(rule); if (rule_id <= 0) return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - ctx::CtxJson1 option; - option.set(NULL, TRIG_KEY_RULE_ID, rule_id); + ctx_sched_job_h job = NULL; - int req_id; - ctx::CtxJson1 data_read; - int error = __dbusClient.readSync(SUBJ_TRIGGER_GET, option, &req_id, &data_read); + int err = ctx_sched_get_job(SCHED, rule_id, &job); - if (error == ERR_NO_DATA) { + if (err == E_PARAM) return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } else if (error != ERR_NONE) { - return error; - } + else if (err != E_NONE) + return err; - *rule = new(std::nothrow) _context_trigger_rule_h(); - (*rule)->jrule = data_read; + *rule = new(std::nothrow) _context_trigger_rule_h(job); + if (*rule == NULL) { + _E_ALLOC; + ctx_sched_job_destroy(job); + return E_NO_MEM; + } - return ERR_NONE; + return E_NONE; } -// Rule creation -SO_EXPORT int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule) +EXPORT_API int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule) { - _D("BEGIN"); ASSERT_NOT_NULL(rule); - - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); *rule = new(std::nothrow) _context_trigger_rule_h(); - (*rule)->jold_rule.set(NULL, OLD_TRIG_RULE_KEY_OPERATOR, logical_str); + ASSERT_ALLOC(*rule); + if ((*rule)->job == NULL) { + _E_ALLOC; + delete *rule; + return E_NO_MEM; + } - (*rule)->jrule.set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, logical_str); + ctx_sched_job_set_disjunction((*rule)->job, logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION); + ctx_sched_job_set_persistent((*rule)->job, true); - return ERR_NONE; + return E_NONE; } -// Rule deletion -SO_EXPORT int context_trigger_rule_destroy(context_trigger_rule_h rule) +EXPORT_API int context_trigger_rule_destroy(context_trigger_rule_h rule) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(rule); + delete rule; - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } - -SO_EXPORT int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry) +static int __set_event(context_trigger_rule_h rule, context_trigger_rule_entry_h event) { - _D("BEGIN"); - ASSERT_NOT_NULL(rule && entry); + IF_FAIL_RETURN(event->jobContext, E_PARAM); + IF_FAIL_RETURN_TAG(!rule->hasEvent, E_INV_RULE, _E, "The rule already has the event"); - // Check if rule handle is created - ctx::CtxJson1 extra; - bool ret = (rule->jrule).get(NULL, _TRIG_RULE_KEY_EXTRA, &extra); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER); + EventItem contextItem(event->type); + IF_FAIL_RETURN_TAG(contextItem.isValid(event->jobContext), E_INV_RULE, _E, "Incomplete event"); - if (entry->type == TYPE_EVENT) { - // Err: More than one event - ctx::CtxJson1 elem; - if ((rule->jold_rule).get(NULL, OLD_TRIG_RULE_KEY_EVENT, &elem)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(event->jobContext); + ASSERT_ALLOC(dup); - // Err: Check if all the mandatory options are added - ret = ctx::rule_validator::check_option(entry->jentry); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Err: If referential conditions are registered priviously, check them - std::string ename; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); - ret = ctx::rule_validator::check_referential_data(ename, rule->jref); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - ctx::CtxJson1 temp = (entry->jentry).str(); - ret = (rule->jold_rule).set(NULL, OLD_TRIG_RULE_KEY_EVENT, temp); - - int error = ctx::rule_util::setEvent(entry->jentry, &(rule->jrule)); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add event entry"); - } else if (entry->type == TYPE_CONDITION) { - // Err: Condition without comparison data - if ((entry->jentry).getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) < 1) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + int err = ctx_sched_job_add_trigger(rule->job, dup); + if (IS_FAILED(err)) { + ctx_sched_job_context_destroy(dup); + return err; + } - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - int val_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); - int op_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR); + rule->hasEvent = true; - // Err: Condition without comparison data - if (val_arr_size != op_arr_size || val_arr_size < 1 || op_arr_size < 1) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + return E_NONE; +} - // Err: Check if all the mandatory options are added - ret = ctx::rule_validator::check_option(entry->jentry); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // If event is already added .... - std::string ename; - ret = (rule->jold_rule).get(OLD_TRIG_RULE_KEY_EVENT, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); - if (ret) { - // Err: Check referential information if exists - ret = ctx::rule_validator::check_referential_data(ename, entry->jref); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - } else { - // If not, copy referential information to rule entry - ctx::CtxJson1 info; - for (int j = 0; (entry->jref).getAt(NULL, TYPE_OPTION, j, &info); j++) { - (rule->jref).append(NULL, TYPE_OPTION, info); - } - - for (int j = 0; (entry->jref).getAt(NULL, TYPE_ATTRIBUTE, j, &info); j++) { - (rule->jref).append(NULL, TYPE_ATTRIBUTE, info); - } - } - } +static int __add_condition(context_trigger_rule_h rule, context_trigger_rule_entry_h condition) +{ + IF_FAIL_RETURN(condition->jobContext, E_PARAM); - ctx::CtxJson1 temp = (entry->jentry).str(); - ret = (rule->jold_rule).append(NULL, OLD_TRIG_RULE_KEY_CONDITION, temp); + bool exist = (rule->conditions.find(condition->uri) != rule->conditions.end()); + IF_FAIL_RETURN_TAG(!exist, E_INV_RULE, _E, "The same condition exists"); - ctx::rule_util::addCondition(entry->jentry, &(rule->jrule)); - } else { - // Entry is not created - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + ConditionItem contextItem(condition->type); + IF_FAIL_RETURN_TAG(contextItem.isValid(condition->jobContext), E_INV_RULE, _E, "Incomplete condition"); + + ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(condition->jobContext); + ASSERT_ALLOC(dup); + + int err = ctx_sched_job_add_requirement(rule->job, dup); + if (IS_FAILED(err)) { + ctx_sched_job_context_destroy(dup); + return err; } - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } -static bool is_call_operation(app_control_h app_control) +EXPORT_API int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry) +{ + ASSERT_NOT_NULL(rule && entry); + IF_FAIL_RETURN_TAG(!rule->readOnly, E_PARAM, + _E, "A rule acquired by context_trigger_get_rule_by_id() is not allowed to be modified."); + + if (entry->category == CATEGORY_EVENT) + return __set_event(rule, entry); + else + return __add_condition(rule, entry); +} + +static bool __is_call_operation(app_control_h ctrl) { char *op = NULL; - int err = app_control_get_operation(app_control, &op); - IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _W, "Getting operation of app control failed"); + int err = app_control_get_operation(ctrl, &op); + IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _E, "Getting operation of app control failed"); bool ret = STR_EQ(op, APP_CONTROL_OPERATION_CALL); g_free(op); @@ -377,830 +460,500 @@ static bool is_call_operation(app_control_h app_control) return ret; } -SO_EXPORT int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control) +static bool __is_ui_app(app_control_h ctrl) { - _D("BEGIN"); - ASSERT_NOT_NULL(rule && app_control); - int error; + char* appId = NULL; + int err = app_control_get_app_id(ctrl, &appId); - // Privilege check - error = __dbusClient.call(METHOD_CHK_PRIV_APPLAUNCH); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); + IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id"); - if (is_call_operation(app_control)) { - error = __dbusClient.call(METHOD_CHK_PRIV_CALL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); - } + pkgmgrinfo_appinfo_h appInfo; + err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo); + g_free(appId); + + IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app"); + + char *appType = NULL; + pkgmgrinfo_appinfo_get_component_type(appInfo, &appType); - // Err: if action arleady exists - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + bool ret = STR_EQ(appType, "uiapp"); + + pkgmgrinfo_appinfo_destroy_appinfo(appInfo); + + return ret; +} + +EXPORT_API int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control) +{ + INIT_SCHED; + ASSERT_NOT_NULL(rule && app_control); + + if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/appmanager.launch")) { + _E("Privilege denied"); + return E_ACCESS; } - // Err: service app - char* app_id = NULL; - error = app_control_get_app_id(app_control, &app_id); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); - - pkgmgrinfo_appinfo_h app_info; - error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); - g_free(app_id); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); - - // Service apps are not allowed to be launched (Mobile & Wearable) - char *app_type = NULL; - pkgmgrinfo_appinfo_get_component_type(app_info, &app_type); - if (!strcmp(app_type, "svcapp")) { - _E("Service application is restricted"); - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + if (__is_call_operation(app_control) && + !PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/call")) { + _E("Privilege denied"); + return E_ACCESS; } - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - // Set app control - bundle* appctl_bundle = NULL; - error = app_control_to_bundle(app_control, &appctl_bundle); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); + IF_FAIL_RETURN_TAG(__is_ui_app(app_control), E_INV_RULE, _E, "Invalid app-control"); - bundle_raw* appctl_raw; - int raw_length; - error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); + bundle* bn = NULL; + app_control_export_as_bundle(app_control, &bn); + IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed"); - std::string appctl_str = reinterpret_cast(appctl_raw); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_APP_LAUNCH, TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL, appctl_str); - bundle_free_encoded_rawdata(&appctl_raw); + int ret = ctx_sched_job_set_app_control(rule->job, bn); - return CONTEXT_TRIGGER_ERROR_NONE; + if (ret == E_NONE) + rule->hasAction = true; + + return ret; } -SO_EXPORT int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, const char* title, const char* content, const char* icon_path, app_control_h app_control) +static bool __is_valid_app_control(app_control_h ctrl) { - _D("BEGIN"); - ASSERT_NOT_NULL(rule && title && content); + if (!ctrl) return true; - // Privilege check - int error = __dbusClient.call(METHOD_CHK_PRIV_NOTIFICATION); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); + char* appId = NULL; + int err = app_control_get_app_id(ctrl, &appId); + IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id"); - // if action arleady exists - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + pkgmgrinfo_appinfo_h appInfo; + err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo); + g_free(appId); + IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app"); - // Err: App control check - if (app_control) { - char* app_id = NULL; - error = app_control_get_app_id(app_control, &app_id); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); - - pkgmgrinfo_appinfo_h app_info; - error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); - g_free(app_id); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); + pkgmgrinfo_appinfo_destroy_appinfo(appInfo); - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - } + return true; +} - // Set title, content - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_TITLE, title); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_CONTENT, content); +EXPORT_API int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, + const char* title, const char* content, const char* icon_path, app_control_h app_control) +{ + INIT_SCHED; + ASSERT_NOT_NULL(rule && title && content); - // Set icon path - if (icon_path) { - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_ICON_PATH, icon_path); + if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/notification")) { + _E("Privilege denied"); + return E_ACCESS; } - // Set app control - if (app_control) { - bundle* appctl_bundle = NULL; - error = app_control_to_bundle(app_control, &appctl_bundle); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); + IF_FAIL_RETURN_TAG(__is_valid_app_control(app_control), E_INV_RULE, _E, "Invalid app-control"); - bundle_raw* appctl_raw; - int raw_length; - error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); + bundle* bn = NULL; + if (app_control) { + app_control_export_as_bundle(app_control, &bn); + IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed"); + } - std::string appctl_str = reinterpret_cast(appctl_raw); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_APP_CONTROL, appctl_str); + int ret = ctx_sched_job_set_notification(rule->job, title, content, icon_path, bn); - bundle_free_encoded_rawdata(&appctl_raw); - } + if (ret == E_NONE) + rule->hasAction = true; - return CONTEXT_TRIGGER_ERROR_NONE; + return ret; } //LCOV_EXCL_START -SO_EXPORT int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule, +EXPORT_API int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule, const char *bus_name, const char *object_path, const char *interface_name, const char *method_name, GVariant *param) { ASSERT_NOT_NULL(rule && bus_name && object_path && interface_name && method_name); + IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action"); - /* if action arleady exists */ - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - /* Set basic dbus method call info */ - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_NAME, bus_name); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_OBJECT, object_path); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_INTERFACE, interface_name); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_METHOD, method_name); + int ret = ctx_sched_job_set_dbus(rule->job, bus_name, object_path, interface_name, method_name, param); - /* Set the parameters */ - if (param) - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_PARAMETER, param); + if (ret == E_NONE) + rule->hasAction = true; - return CONTEXT_TRIGGER_ERROR_NONE; + return ret; } //LCOV_EXCL_STOP -// Set description -SO_EXPORT int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description) +EXPORT_API int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description) { - _D("BEGIN"); - ASSERT_NOT_NULL(rule); - - (rule->jrule).set(NULL, TRIG_RULE_KEY_DESCRIPTION, description); + ASSERT_NOT_NULL(rule && description); + IF_FAIL_RETURN(strlen(description) > 0, E_PARAM); - return CONTEXT_TRIGGER_ERROR_NONE; + return ctx_sched_job_set_user_data(rule->job, description, strlen(description) + 1); } -// Get rule description -SO_EXPORT int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description) +EXPORT_API int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description) { - _D("BEGIN"); ASSERT_NOT_NULL(rule && description); - std::string val; - (rule->jrule).get(NULL, TRIG_RULE_KEY_DESCRIPTION, &val); + char* val = NULL; + size_t len = 0; + int err = ctx_sched_job_get_user_data(rule->job, &val, &len); + IF_FAIL_RETURN(IS_SUCCESS(err), err); + IF_FAIL_RETURN(val, E_NONE); - *description = strdup(val.c_str()); + *description = val; - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } -// Event creation -SO_EXPORT int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +EXPORT_API int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); - if (event_is_deprecated(event_item)) { - _W(TRIGGER_DEPRECATED_EVENT_MSG); - } + EventItem contextItem(event_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item); - std::string eitem_str = convert_event_to_string(event_item); - if (eitem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + if (contextItem.deprecated()) + _DEPRECATED_EVENT(event_item); - int error = context_trigger_rule_event_create_internal(eitem_str.c_str(), logical_type, entry); - return error; -} + IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied"); -SO_EXPORT int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(event_item && provider && entry); + bool supported = false; + ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), &supported); + IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Event-%d is not supported", event_item); - // Err: Invalid provider - pkgmgrinfo_pkginfo_h pkg_info; - int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); - pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, event_item, contextItem.getUri()); + ASSERT_ALLOC(*entry); - std::string subject = get_custom_item_subject(provider, event_item); - error = context_trigger_rule_event_create_internal(subject.c_str(), logical_type, entry, true); + ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION)); - return error; + return E_NONE; } -int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +static bool __is_valid_pkg_id(const char* pkgId) { - _D("BEGIN"); - ASSERT_NOT_NULL(event_item); - - // Err: Invalid logical operator - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + IF_FAIL_RETURN(pkgId, false); - int error = ctx::rule_validator::request_template(event_item, is_custom); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); + pkgmgrinfo_pkginfo_h pkgInfo; + int err = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, getuid(), &pkgInfo); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkgInfo); - *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_EVENT); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, event_item); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, logical_str); - - return CONTEXT_TRIGGER_ERROR_NONE; + return (PMINFO_R_OK == err); } -// Event availability check -SO_EXPORT int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported) +EXPORT_API int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - _D("BEGIN"); - ASSERT_NOT_NULL(supported); + INIT_SCHED; + ASSERT_NOT_NULL(event_item && provider && entry); + IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); - if (event_is_deprecated(event_item)) { - _W(TRIGGER_DEPRECATED_EVENT_MSG); - } + std::string uri = __get_custom_uri(event_item, provider); - *supported = false; + bool registered = false; + ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, ®istered); + IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", event_item); - std::string eitem_str = convert_event_to_string(event_item); - if (eitem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, 0, uri.c_str()); + ASSERT_ALLOC(*entry); - int error = __dbusClient.isSupported(eitem_str); + return E_NONE; +} - if (error == ERR_NONE) - *supported = true; +EXPORT_API int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported) +{ + INIT_SCHED; + ASSERT_NOT_NULL(supported); - if (error == ERR_NOT_SUPPORTED) - return ERR_NONE; + EventItem contextItem(event_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item); - return error; + return ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), supported); } -// Condition creation -SO_EXPORT int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +EXPORT_API int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); - if (condition_is_deprecated(condition_item)) { - _W(TRIGGER_DEPRECATED_CONDITION_MSG); - } + ConditionItem contextItem(condition_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item); - std::string citem_str = convert_condition_to_string(condition_item); - if (citem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + if (contextItem.deprecated()) + _DEPRECATED_COND(condition_item); - int error = context_trigger_rule_condition_create_internal(citem_str.c_str(), logical_type, entry); - return error; -} + IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied"); -SO_EXPORT int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(condition_item && provider && entry); + bool supported = false; + ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), &supported); + IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Condition-%d is not supported", condition_item); - // Err: Invalid provider - pkgmgrinfo_pkginfo_h pkg_info; - int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); - pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, condition_item, contextItem.getUri()); + ASSERT_ALLOC(*entry); - std::string subject = get_custom_item_subject(provider, condition_item); - error = context_trigger_rule_condition_create_internal(subject.c_str(), logical_type, entry, true); - return error; + ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION)); + + return E_NONE; } -int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +EXPORT_API int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) { - _D("BEGIN"); - ASSERT_NOT_NULL(condition_item); + INIT_SCHED; + ASSERT_NOT_NULL(condition_item && provider && entry); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); + IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + std::string uri = __get_custom_uri(condition_item, provider); - int error = ctx::rule_validator::request_template(condition_item, is_custom); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); + bool registered = false; + ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, ®istered); + IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", condition_item); - *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_CONDITION); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, condition_item); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, logical_str); + *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, 0, uri.c_str()); + ASSERT_ALLOC(*entry); - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } -// Condition availability check -SO_EXPORT int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported) +EXPORT_API int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(supported); - if (condition_is_deprecated(condition_item)) { - _W(TRIGGER_DEPRECATED_CONDITION_MSG); - } - - *supported = false; - - std::string citem_str = convert_condition_to_string(condition_item); - if (citem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = __dbusClient.isSupported(citem_str); - - if (error == ERR_NONE) - *supported = true; + ConditionItem contextItem(condition_item); + IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item); - if (error == ERR_NOT_SUPPORTED) - return ERR_NONE; - - return error; + return ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), supported); } -// Rule data deletion -SO_EXPORT int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry) +EXPORT_API int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(entry); + delete entry; - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } -SO_EXPORT int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value) +EXPORT_API int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value) { - _D("BEGIN"); ASSERT_NOT_NULL(entry && option_key); - bool ret = true; - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - ret = ctx::rule_validator::check_option_int(name, option_key, value); - if (!ret) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); + bool valid = contextItem->isValidOption(option_key, value); + delete contextItem; + IF_FAIL_RETURN(valid, E_INV_RULE); - return CONTEXT_TRIGGER_ERROR_NONE; + ctx_sched_job_context_prepare_attribute_int(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, option_key, value); } -SO_EXPORT int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value) +EXPORT_API int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value) { - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); + _DEPRECATED_FUNC; ASSERT_NOT_NULL(entry && option_key && value); - bool ret = true; - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - ret = ctx::rule_validator::check_option_string(name, option_key, value); - if (!ret) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); + bool valid = contextItem->isValidOption(option_key, value); + delete contextItem; + IF_FAIL_RETURN(valid, E_INV_RULE); - return CONTEXT_TRIGGER_ERROR_NONE; + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, value); } -SO_EXPORT int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key) +EXPORT_API int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key) { - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); + _DEPRECATED_FUNC; ASSERT_NOT_NULL(entry && option_key && event_data_key); + IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE); - // Err: Only conditin can reference data from event - if (entry->type != TYPE_CONDITION) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + ConditionItem contextItem(entry->type); + IF_FAIL_RETURN(contextItem.isValidOption(option_key), E_INV_RULE); - // Err: Check if key is valid - bool ret = ctx::rule_validator::check_valid_key(TYPE_OPTION, name, option_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Set reference information - ret = ctx::rule_validator::set_ref_info(TYPE_OPTION, &(entry->jref), name, option_key, event_data_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key); + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, event_data_key); +} - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); +static bool __is_member_key(context_trigger_rule_entry_h entry, const char* key) +{ + if (entry->attributes.find(key) != entry->attributes.end()) { + _D("'%s' found", key); + return true; + } - return CONTEXT_TRIGGER_ERROR_NONE; + _D("'%s' not found", key); + return false; } -SO_EXPORT int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key) +EXPORT_API int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key) { - _D("BEGIN"); ASSERT_NOT_NULL(entry && key); + IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM); - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); - // Err: Check if key is valid - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Err: Comparison key is already added - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - // Err: Comparison key is already added - if (elem_item.compare(key) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } + bool valid = contextItem->isValidData(key); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(!__is_member_key(entry, key), E_INV_RULE); - ctx::CtxJson1 data; - data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, key); - data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR, logical_str); - (entry->jentry).append(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, data); + entry->attributes.emplace(key, logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION); - return CONTEXT_TRIGGER_ERROR_NONE; + return E_NONE; } -static int context_trigger_rule_entry_add_comparison_string_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, std::string value) +EXPORT_API int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key) { - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - - if (elem_item.compare(key) == 0) { - std::string elem_val; - std::string elem_op; - for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { - elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); - - // Err: Duplicated - if (elem_val.compare(value) == 0 && elem_op.compare(op) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value.c_str()); - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); - (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); + _DEPRECATED_FUNC; + ASSERT_NOT_NULL(entry && key && op && event_data_key); + IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE); - return CONTEXT_TRIGGER_ERROR_NONE; - } - } + ConditionItem contextItem(entry->type); + IF_FAIL_RETURN(contextItem.isValidData(key), E_INV_RULE); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); - // Comparison key not exist - return CONTEXT_TRIGGER_ERROR_NO_DATA; -} + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key); -static int context_trigger_rule_entry_add_comparison_int_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, int value) -{ - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - - if (elem_item.compare(key) == 0) { - int elem_val; - std::string elem_op; - for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { - elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); - - // Err: Duplicated - if (elem_val == value && elem_op.compare(op) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value); - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); - (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, event_data_key); - return CONTEXT_TRIGGER_ERROR_NONE; - } - } + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, event_data_key); - // Comparison key not exist - return CONTEXT_TRIGGER_ERROR_NO_DATA; + _E("Invalid operator"); + return E_INV_RULE; } -SO_EXPORT int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key) +EXPORT_API int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value) { - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); - ASSERT_NOT_NULL(entry && key && op && event_data_key); + ASSERT_NOT_NULL(entry && key && op); - // Err: Only condition can reference data from event - if (entry->type != TYPE_CONDITION) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + bool valid = contextItem->isValidData(key, value); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); - // Err: Check if key is valid - bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + ctx_sched_job_context_prepare_attribute_int(entry->jobContext, key); - // Err: Invalid operator - std::string type = ctx::rule_validator::get_data_type_from_template(TYPE_ATTRIBUTE, name, key); - ret = ctx::rule_validator::is_valid_operator(type, op); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, key, value); - int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); - IF_FAIL_RETURN(error == ERR_NONE, error); + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_int(entry->jobContext, key, value); - // Set reference information - ret = ctx::rule_validator::set_ref_info(TYPE_ATTRIBUTE, &(entry->jref), name, key, event_data_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); + _context_trigger_rule_entry_s::Bound& bound = entry->attributes.find(key)->second; - return CONTEXT_TRIGGER_ERROR_NONE; -} + if (__getOpType(op) == OpType::GT) { + if (bound.conjunction) bound.gt = std::max(bound.gt, value); + else bound.gt = std::min(bound.gt, value); + return ctx_sched_job_context_attribute_set_gt_int(entry->jobContext, key, bound.gt); + } -SO_EXPORT int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op); + if (__getOpType(op) == OpType::GE) { + if (bound.conjunction) bound.ge = std::max(bound.ge, value); + else bound.ge = std::min(bound.ge, value); + return ctx_sched_job_context_attribute_set_ge_int(entry->jobContext, key, bound.ge); + } - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + if (__getOpType(op) == OpType::LT) { + if (bound.conjunction) bound.lt = std::min(bound.lt, value); + else bound.lt = std::max(bound.lt, value); + return ctx_sched_job_context_attribute_set_lt_int(entry->jobContext, key, bound.lt); + } - bool ret = ctx::rule_validator::check_comparison_int(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + if (__getOpType(op) == OpType::LE) { + if (bound.conjunction) bound.le = std::min(bound.le, value); + else bound.le = std::max(bound.le, value); + return ctx_sched_job_context_attribute_set_le_int(entry->jobContext, key, bound.le); + } - int error = context_trigger_rule_entry_add_comparison_int_internal(entry, key, op, value); - return error; + _E("Invalid operator"); + return E_INV_RULE; } -/* -SO_EXPORT int context_trigger_rule_entry_add_comparison_double(context_trigger_rule_entry_h entry, const char* key, const char* op, double value) + +EXPORT_API int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value) { - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op); + ASSERT_NOT_NULL(entry && key && op && value); - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + ContextItem* contextItem = __get_context_item(entry); + IF_FAIL_RETURN(contextItem, E_FAILED); - // TODO: check_comparison_double() - bool ret = ctx::rule_validator::check_comparison_double(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + bool valid = contextItem->isValidData(key, value); + delete contextItem; + IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter"); + IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA); - int error = context_trigger_rule_entry_add_comparison_internal(entry, key, op, double_to_string(value)); - return error; -} -*/ -SO_EXPORT int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op && value); + ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key); - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + if (__getOpType(op) == OpType::EQ) + return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, value); - bool ret = ctx::rule_validator::check_comparison_string(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + if (__getOpType(op) == OpType::NE) + return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, value); - int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, value); - return error; + _E("Invalid operator"); + return E_INV_RULE; } -SO_EXPORT int context_trigger_custom_register(const char* name, const char* attr_template) +EXPORT_API int context_trigger_custom_register(const char* name, const char* attr_template) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(name && attr_template); - // Err: Invalid CtxJson1 - ctx::CtxJson1 jattr_template = attr_template; - IF_FAIL_RETURN_TAG(jattr_template.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Failed to parse template"); + int error = CustomTemplate::add(name, attr_template); + IF_FAIL_RETURN_TAG(error == E_NONE, error, _E, "Failed to add template"); - // Err: Invalid template - bool ret = ctx::rule_validator::is_valid_template(jattr_template); - IF_FAIL_RETURN_TAG(ret, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_ADD); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); - data.set(NULL, TRIG_TMPL_KEY_ATTRIBUTE, jattr_template); + std::string uri = __get_custom_uri(name, pkgId); - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add custom item: %#x", error); + int err = ctx_sched_custom_register(SCHED, uri.c_str()); + IF_FAIL_RETURN(err == E_NONE, E_FAILED); - return error; + return E_NONE; } -SO_EXPORT int context_trigger_custom_unregister(const char* name) +EXPORT_API int context_trigger_custom_unregister(const char* name) { - _D("BEGIN"); + INIT_SCHED; ASSERT_NOT_NULL(name); - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_REMOVE); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); + CustomTemplate* customTemplate = CustomTemplate::get(name); + IF_FAIL_RETURN_TAG(customTemplate, E_SUPPORT, _E, "Unknown custom name"); - ctx::CtxJson1 subj; - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, &subj); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to remove custom item: %#x", error); + CustomTemplate::remove(name); - std::string subject; - subj.get(NULL, TRIG_TMPL_KEY_SUBJECT, &subject); - ctx::rule_validator::remove_template(subject); + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); - return error; -} + std::string uri = __get_custom_uri(name, pkgId); -SO_EXPORT int context_trigger_custom_publish(const char* name, const char* fact) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(name && fact); - - // Err: Invalid CtxJson1 - ctx::CtxJson1 jfact = fact; - IF_FAIL_RETURN_TAG(jfact.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Cannot parse fact CtxJson1"); - - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_PUBLISH); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); - data.set(NULL, TRIG_CUSTOM_KEY_FACT, jfact); + ctx_sched_custom_unregister(SCHED, uri.c_str()); - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to publish custom data"); - - return error; + return E_NONE; } -std::string convert_event_to_string(context_trigger_event_e item) +EXPORT_API int context_trigger_custom_publish(const char* name, const char* fact) { - std::string str; - switch (item) { - case CONTEXT_TRIGGER_EVENT_TIME: - str = SUBJ_STATE_ALARM; - break; - case CONTEXT_TRIGGER_EVENT_BATTERY: - str = SUBJ_STATE_BATTERY; - break; - case CONTEXT_TRIGGER_EVENT_CHARGER: - str = SUBJ_STATE_CHARGER; - break; - case CONTEXT_TRIGGER_EVENT_GPS: - str = SUBJ_STATE_GPS; - break; - case CONTEXT_TRIGGER_EVENT_HEADPHONE: - str = SUBJ_STATE_HEADPHONE; - break; - case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: - str = SUBJ_STATE_PSMODE; - break; - case CONTEXT_TRIGGER_EVENT_USB: - str = SUBJ_STATE_USB; - break; - case CONTEXT_TRIGGER_EVENT_WIFI: - str = SUBJ_STATE_WIFI; - break; - case CONTEXT_TRIGGER_EVENT_CALL: - str = SUBJ_STATE_CALL; - break; - case CONTEXT_TRIGGER_EVENT_EMAIL: - str = SUBJ_STATE_EMAIL; - break; - case CONTEXT_TRIGGER_EVENT_MESSAGE: - str = SUBJ_STATE_MESSAGE; - break; - case CONTEXT_TRIGGER_EVENT_CONTACTS: - str = SUBJ_STATE_CONTACTS; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_STATIONARY: - str = SUBJ_ACTIVITY_STATIONARY; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_WALKING: - str = SUBJ_ACTIVITY_WALKING; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_RUNNING: - str = SUBJ_ACTIVITY_RUNNING; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_IN_VEHICLE: - str = SUBJ_ACTIVITY_IN_VEHICLE; - break; - case CONTEXT_TRIGGER_EVENT_PLACE: - str = SUBJ_PLACE_GEOFENCE; - break; - default: - break; - } - return str; -} + INIT_SCHED; + ASSERT_NOT_NULL(name && fact); -std::string convert_condition_to_string(context_trigger_condition_e item) -{ - std::string str; - switch (item) { - case CONTEXT_TRIGGER_CONDITION_TIME: - str = SUBJ_STATE_TIME; - break; - case CONTEXT_TRIGGER_CONDITION_BATTERY: - str = SUBJ_STATE_BATTERY; - break; - case CONTEXT_TRIGGER_CONDITION_CHARGER: - str = SUBJ_STATE_CHARGER; - break; - case CONTEXT_TRIGGER_CONDITION_GPS: - str = SUBJ_STATE_GPS; - break; - case CONTEXT_TRIGGER_CONDITION_HEADPHONE: - str = SUBJ_STATE_HEADPHONE; - break; - case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: - str = SUBJ_STATE_PSMODE; - break; - case CONTEXT_TRIGGER_CONDITION_USB: - str = SUBJ_STATE_USB; - break; - case CONTEXT_TRIGGER_CONDITION_WIFI: - str = SUBJ_STATE_WIFI; - break; - case CONTEXT_TRIGGER_CONDITION_CALL: - str = SUBJ_STATE_CALL; - break; - case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: - str = SUBJ_APP_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: - str = SUBJ_SOCIAL_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: - str = SUBJ_MUSIC_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: - str = SUBJ_VIDEO_FREQUENCY; - break; - default: - break; - } - return str; -} + CustomTemplate* customTemplate = CustomTemplate::get(name); + IF_FAIL_RETURN_TAG(customTemplate, E_SUPPORT, _E, "Unknown custom name"); -std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type) -{ - std::string str; - switch (logical_type) { - case CONTEXT_TRIGGER_LOGICAL_CONJUNCTION: - str = TRIG_RULE_LOGICAL_CONJUNCTION; - break; - case CONTEXT_TRIGGER_LOGICAL_DISJUNCTION: - str = TRIG_RULE_LOGICAL_DISJUNCTION; - break; - default: - break; - } - return str; -} + int error = customTemplate->match(fact); + IF_FAIL_RETURN_TAG(error == E_NONE, error, _E, "Failed to publish fact"); -std::string get_custom_item_subject(const char* provider, const char* item) -{ - std::string subject_name = std::string(TRIG_CUSTOM_PREFIX TRIG_SUBJECT_SEPERATOR) + provider + std::string(TRIG_SUBJECT_SEPERATOR) + item; - return subject_name; -} + const char* pkgId = __get_pkg_id(); + IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required"); -bool event_is_deprecated(context_trigger_event_e item) -{ - bool ret = false; - switch (item) { - case CONTEXT_TRIGGER_EVENT_TIME: - case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: - case CONTEXT_TRIGGER_EVENT_CALL: - case CONTEXT_TRIGGER_EVENT_EMAIL: - case CONTEXT_TRIGGER_EVENT_MESSAGE: - ret = true; - break; - default: - break; - } - return ret; -} - -bool condition_is_deprecated(context_trigger_condition_e item) -{ - bool ret = false; - switch (item) { - case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: - case CONTEXT_TRIGGER_CONDITION_CALL: - case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: - ret = true; - break; - default: - break; - } - return ret; -} + std::string uri = __get_custom_uri(name, pkgId); -/* -std::string int_to_string(int value) -{ - std::ostringstream ostr; - ostr << value; - return ostr.str(); + return ctx_sched_publish_context_json(SCHED, uri.c_str(), fact); } - -std::string double_to_string(int value) -{ - std::ostringstream ostr; - ostr.imbue(std::locale("C")); - ostr << std::setprecision(DOUBLE_PRECISION) << std::fixed << value; - return ostr.str(); -}*/ diff --git a/src/trigger/rule_util.cpp b/src/trigger/rule_util.cpp deleted file mode 100644 index f57de01..0000000 --- a/src/trigger/rule_util.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "rule_validator.h" -#include "rule_util.h" -#include "ComparisonConverter.h" -#include "IntComparisonConverter.h" -#include "StringComparisonConverter.h" - -using namespace ctx; - -static bool __handleTimerEvent(CtxJson1& event); -static int __arrangeDayOfWeek(CtxJson1& dayInfo); - -int ctx::rule_util::setEvent(CtxJson1& entry, CtxJson1* rule) -{ - CtxJson1 tempEvent; - std::string subject; - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &subject); - - CtxJson1 option; - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPTION, &option); - tempEvent.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); - - CtxJson1 elem; - for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - CtxJson1 newElem; - - std::string key; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); - - std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); - - ComparisonConverter* converter = NULL; - if (type == TRIG_TMPL_TYPE_INTEGER) { - converter = new(std::nothrow) IntComparisonConverter(elem); - } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { - converter = new(std::nothrow) StringComparisonConverter(elem); - } - IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); - converter->getResult(&newElem); - - CtxJson1 detail; - newElem.get(NULL, key.c_str(), &detail); - - std::string path = subject + "." + TRIG_RULE_KEY_COMPARISON; - tempEvent.set(path.c_str(), key.c_str(), detail); - delete converter; - } - - // Handle Timer Event - if (subject.compare(SUBJ_STATE_ALARM) == 0) { - IF_FAIL_RETURN(__handleTimerEvent(tempEvent), ERR_INVALID_RULE); - } - - rule->set(NULL, TRIG_RULE_KEY_EVENT, tempEvent); - - // Save event entry's logical to extra info (default and) - std::string eventOp = TRIG_RULE_LOGICAL_CONJUNCTION; - if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, &eventOp); - } - rule->set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_EVENT_LOGICAL_OP, eventOp); - - return ERR_NONE; -} - -int ctx::rule_util::addCondition(CtxJson1& entry, CtxJson1* rule) -{ - CtxJson1 tempCond; - std::string subject; - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &subject); - - CtxJson1 option; - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPTION, &option); - tempCond.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); - - CtxJson1 elem; - for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - CtxJson1 newElem; - - std::string key; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); - - std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); - - ComparisonConverter* converter = NULL; - if (type == TRIG_TMPL_TYPE_INTEGER) { - converter = new(std::nothrow) IntComparisonConverter(elem); - } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { - converter = new(std::nothrow) StringComparisonConverter(elem); - } - IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); - converter->getResult(&newElem); - - tempCond.set(subject.c_str(), TRIG_RULE_KEY_COMPARISON, newElem); - delete converter; - } - - rule->append(NULL, TRIG_RULE_KEY_CONDITION, tempCond); - - // Save event entry's logical to extra info (default and) - std::string condOp = TRIG_RULE_LOGICAL_CONJUNCTION; - if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, &condOp); - } - rule->append(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_CONDITION_LOGICAL_OP, condOp); - - return ERR_NONE; -} - -bool __handleTimerEvent(CtxJson1& event) -{ - CtxJson1 alarmComp; - bool ret = event.get(SUBJ_STATE_ALARM, TRIG_RULE_KEY_COMPARISON, &alarmComp); - IF_FAIL_RETURN_TAG(ret, false, _E, "Invalid EVENT_TIME event"); - - // Day processing - CtxJson1 dayInfo; - bool daySpecified = alarmComp.get(NULL, KEY_DAY_OF_WEEK, &dayInfo); - - if (daySpecified) { - CtxJson1 newDayInfo; - newDayInfo.set(NULL, TRIG_RULE_KEY_OPERATOR, TRIG_RULE_OP_ONE_OF); - - int dow = __arrangeDayOfWeek(dayInfo); - IF_FAIL_RETURN_TAG(dow > 0, false, _E, "Invalid DayOfWeek info for EVENT_TIME"); - - for (int i = 0 ; i < DAYS_PER_WEEK; i++) { - int d = 0x01 << i; - if (dow & d) { - std::string day = TimerManager::dowToStr(d); - newDayInfo.append(NULL, TRIG_RULE_KEY_VALUE, day); - - // Copy details as option - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, day); - } - } - event.set(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_COMPARISON, KEY_DAY_OF_WEEK, newDayInfo); - } else { - // If DayOfWeek is not specified, regard it as Mon ~ Sun - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_MON); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_TUE); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_WED); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_THU); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_FRI); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SAT); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SUN); - } - - // Time processing - CtxJson1 timeInfo; - alarmComp.get(NULL, KEY_TIME_OF_DAY, &timeInfo); - - int time; - std::string timeOp; - timeInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &timeOp); - - if (timeOp == TRIG_RULE_OP_EQUAL_TO) { - timeInfo.get(NULL, TRIG_RULE_KEY_VALUE, &time); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); - } else if (timeOp == TRIG_RULE_OP_ONE_OF) { - for (int i = 0; timeInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &time); i++) { - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); - } - } - - return true; -} - -int __arrangeDayOfWeek(CtxJson1& dayInfo) -{ - std::string dayOp; - if (!dayInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &dayOp)) { - return TimerManager::dowToInt(DOW_EVERYDAY); - } - - int result = 0; - if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO || dayOp == TRIG_RULE_OP_NOT_IN) { - result = TimerManager::dowToInt(DOW_EVERYDAY); - } - - int dow; - std::string day; - if (dayOp == TRIG_RULE_OP_EQUAL_TO) { - dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); - dow = TimerManager::dowToInt(day); - result |= dow; - } else if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO) { - dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); - dow = TimerManager::dowToInt(day); - dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; - result &= dow; - } else if (dayOp == TRIG_RULE_OP_ONE_OF) { - for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { - dow = TimerManager::dowToInt(day); - result |= dow; - } - } else if (dayOp == TRIG_RULE_OP_NONE_OF) { - for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { - dow = TimerManager::dowToInt(day); - dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; - result &= dow; - } - } - - _D("Requested day of week (%#x)", result); - return result; -} - -bool ctx::rule_util::isEventSet(CtxJson1& rule) -{ - ctx::CtxJson1 event; - if (rule.get(NULL, TRIG_RULE_KEY_EVENT, &event)) { - if (event != EMPTY_JSON_OBJECT) { - return true; - } - } - - return false; -} - -bool ctx::rule_util::isActionSet(CtxJson1& rule) -{ - ctx::CtxJson1 action; - if (rule.get(NULL, TRIG_RULE_KEY_ACTION, &action)) { - if (action != EMPTY_JSON_OBJECT) { - return true; - } - } - - return false; -} diff --git a/src/trigger/rule_util.h b/src/trigger/rule_util.h deleted file mode 100644 index d4443bb..0000000 --- a/src/trigger/rule_util.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __CONTEXT_RULE_UTIL_H__ -#define __CONTEXT_RULE_UTIL_H__ - -#include - -namespace ctx { - - namespace rule_util { - - int setEvent(CtxJson1& entry, CtxJson1* rule); - int addCondition(CtxJson1& entry, CtxJson1* rule); - bool isEventSet(CtxJson1& rule); - bool isActionSet(CtxJson1& rule); - - } -} /* namespace ctx */ - -#endif /* __CONTEXT_RULE_UTIL_H__ */ diff --git a/src/trigger/rule_validator.cpp b/src/trigger/rule_validator.cpp deleted file mode 100644 index 6f37448..0000000 --- a/src/trigger/rule_validator.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "DBusClient.h" -#include "TriggerOldRuleTypes.h" -#include "rule_validator.h" - -using namespace ctx; - -#define RULE_VALIDATOR_COND_NAME "name" -#define RULE_VALIDATOR_KEY "key" -#define RULE_VALIDATOR_TYPE "type" -#define RULE_VALIDATOR_REF "ref" - -typedef std::map template_map_t; -template_map_t template_map; // - -static int string_to_int(std::string str); -static bool check_value_int(CtxJson1& tmpl, std::string key, int value); -static bool check_value_string(CtxJson1& tmpl, std::string key, std::string value); -static bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value); -static CtxJson1 get_template(std::string name); -static bool check_template_int(CtxJson1& elem); -static bool check_template_string(CtxJson1& elem); -static bool check_template_enum(CtxJson1& elem); -static std::string get_data_type(CtxJson1& elem, std::string& key); -static bool is_equal_type(std::string& type1, std::string& type2); - -int string_to_int(std::string str) -{ - int i; - std::istringstream convert(str); - - if (!(convert >> i)) - i = 0; - - return i; -} - -CtxJson1 get_template(std::string name) -{ - rule_validator::request_template(name); - return template_map[name]; -} - -int rule_validator::request_template(std::string name, bool mandatory) -{ - if (!mandatory) { - template_map_t::iterator it = template_map.find(name); - IF_FAIL_RETURN(it == template_map.end(), ERR_NONE); - } - - // Request template - CtxJson1 request; - request.set(NULL, TRIG_TMPL_KEY_SUBJECT, name); - - int req_id; - CtxJson1 tmpl; - DBusClient dbusClient; - int error = dbusClient.readSync(SUBJ_TRIGGER_GET_TEMPLATE, request, &req_id, &tmpl); - if (error == ERR_NOT_SUPPORTED) { - template_map.erase(name); - _E("Failed to get request: not supported"); - return ERR_NOT_SUPPORTED; - } - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get request"); - - template_map[name] = tmpl; - - return ERR_NONE; -} - -void rule_validator::remove_template(std::string name) -{ - template_map.erase(name); -} - -// called by context_trigger_rule_add_entry() -bool rule_validator::check_option(CtxJson1& item) -{ - std::string name; - item.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - // No option needed - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - if (opt_keys.size() <= 0) { - return true; - } - - // Err: Check if mandatory option is missed - std::string val_str; - int val; - if (name == SUBJ_PLACE_GEOFENCE) { - if (!(item.get(OLD_TRIG_RULE_KEY_EVENT_OPTION, CONTEXT_TRIGGER_PLACE_ID, &val))) - return false; - } else if (name == SUBJ_APP_FREQUENCY) { - if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_APP_ID, &val_str))) - return false; - } else if (name == SUBJ_SOCIAL_FREQUENCY) { - if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_ADDRESS, &val_str))) - return false; - } - - return true; -} - -// called by context_trigger_rule_entry_add_option_int() -bool rule_validator::check_option_int(std::string name, std::string key, int value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - // Err: Item with no option - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - IF_FAIL_RETURN(opt_keys.size() > 0, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(opt_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); - - // Err: Inappropriate value - // a. normal case - bool ret = check_value_int(opt_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - - return true; -} - -// called by context_trigger_rule_entry_add_option_string() -bool rule_validator::check_option_string(std::string name, std::string key, std::string value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - // Err: ';' for SQL injection - IF_FAIL_RETURN(value.find(';') == std::string::npos, false); - - // Err: Item with no option - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - IF_FAIL_RETURN(opt_keys.size() > 0, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(opt_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); - - // Err: Inappropriate value - // a. spacial case - if (t_type == TRIG_TMPL_TYPE_STRING && (name == SUBJ_APP_FREQUENCY || name == SUBJ_SOCIAL_FREQUENCY - || name == SUBJ_MUSIC_FREQUENCY || name == SUBJ_VIDEO_FREQUENCY) - && key == CONTEXT_TRIGGER_TIME_OF_DAY) { - std::size_t found = value.find("-"); - if (found == std::string::npos) { - return false; - } - - int t1 = string_to_int(value.substr(0, found-1)); - int t2 = string_to_int(value.substr(found+1, value.length()-1)); - - if (!(t1 >= 0 && t1 < 24) || !(t2 >= 0 && t2 < 24)) { - return false; - } - - if (t1 >= t2) { - return false; - } - - return true; - } - - // b. normal case - bool ret = false; - if (t_type == TRIG_TMPL_TYPE_STRING) { - ret = check_value_string(opt_tmpl, key, value); - } else if (t_type == TRIG_TMPL_TYPE_ENUM) { - ret = check_value_enum(opt_tmpl, key, value); - } - - return ret; -} - -// called by context_trigger_rule_entry_add_comparison_int() -bool rule_validator::check_comparison_int(std::string name, std::string key, std::string op, int value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 attr_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); - - // Err: Invalid attribute key or Invalid value type - std::string t_type = get_data_type(attr_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); - - // Err: Invalid operator for the value - // a. normal case - bool ret = is_valid_operator(TRIG_TMPL_TYPE_INTEGER, op); - IF_FAIL_RETURN(ret, false); - // b. special case - if (name == SUBJ_STATE_ALARM && key == CONTEXT_TRIGGER_TIME_OF_DAY) { - IF_FAIL_RETURN(op == CONTEXT_TRIGGER_EQUAL_TO, false); - } - - // Err: Inappropriate value - // a. normal case - ret = check_value_int(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - - return true; -} - -// called by context_trigger_rule_entry_add_comparison_string() -bool rule_validator::check_comparison_string(std::string name, std::string key, std::string op, std::string value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != CtxJson1(EMPTY_JSON_OBJECT), false); - - CtxJson1 attr_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); - - // Err: ';' for SQL injection - IF_FAIL_RETURN(value.find(';') == std::string::npos, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(attr_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); - - // Err: Invalid operator for the value - bool ret = is_valid_operator(t_type, op); - IF_FAIL_RETURN(ret, false); - - // Err: Inappropriate value - // a. normal case - if (t_type == TRIG_TMPL_TYPE_STRING) { - ret = check_value_string(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - } else if (t_type == TRIG_TMPL_TYPE_ENUM) { - ret = check_value_enum(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - } - - return true; -} - -bool rule_validator::check_valid_key(std::string type, std::string name, std::string key) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - // Err: Invalid key - CtxJson1 tmp; - bool ret = tmpl.get(type.c_str(), key.c_str(), &tmp); - IF_FAIL_RETURN(ret, false); - - return true; -} - -bool check_value_int(CtxJson1& tmpl, std::string key, int value) -{ - int min, max; - - if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MIN, &min)) { - IF_FAIL_RETURN(value >= min, false); - } - - if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MAX, &max)) { - IF_FAIL_RETURN(value <= max, false); - } - - return true; -} - -bool check_value_string(CtxJson1& tmpl, std::string key, std::string value) -{ - return true; -} - -bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value) -{ - std::string t_val; - for (int i = 0; tmpl.getAt(key.c_str(), TRIG_TMPL_TYPE_ENUM, i, &t_val); i++) { - if (t_val == value) - return true; - } - - return false; -} - -// called by context_trigger_rule_entry_add_comparison() -// called by context_trigger_rule_entry_add_option() -bool rule_validator::set_ref_info(std::string type, CtxJson1* jref, std::string name, std::string key, std::string ref_data) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 detailed_tmpl; - tmpl.get(NULL, type.c_str(), &detailed_tmpl); - - std::string dt = get_data_type(detailed_tmpl, key); - IF_FAIL_RETURN(dt == TRIG_TMPL_TYPE_INTEGER || dt == TRIG_TMPL_TYPE_STRING || dt == TRIG_TMPL_TYPE_ENUM, false); - - CtxJson1 temp; - temp.set(NULL, RULE_VALIDATOR_COND_NAME, name); - temp.set(NULL, RULE_VALIDATOR_KEY, key); - temp.set(NULL, RULE_VALIDATOR_TYPE, dt); - temp.set(NULL, RULE_VALIDATOR_REF, ref_data); - - if (type == TRIG_TMPL_KEY_OPTION) { - jref->append(NULL, TRIG_TMPL_KEY_OPTION, temp); - } else if (type == TRIG_TMPL_KEY_ATTRIBUTE) { - jref->append(NULL, TRIG_TMPL_KEY_ATTRIBUTE, temp); - } else { - return false; - } - - return true;; -} - -std::string get_data_type(CtxJson1& elem, std::string& key) -{ - std::string data_type; - bool ret = elem.get(key.c_str(), TRIG_TMPL_KEY_TYPE, &data_type); - if (!ret) { - int size = elem.getSize(key.c_str(), TRIG_TMPL_TYPE_ENUM); - IF_FAIL_RETURN(size > 0, ""); - data_type = TRIG_TMPL_TYPE_ENUM; - } - IF_FAIL_RETURN(data_type == TRIG_TMPL_TYPE_INTEGER || data_type == TRIG_TMPL_TYPE_STRING || data_type == TRIG_TMPL_TYPE_ENUM, ""); - - return data_type; -} - -// called by context_trigger_rule_entry_add_comparison() -std::string rule_validator::get_data_type_from_template(std::string type, std::string name, std::string key) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, ""); - - CtxJson1 detailed_tmpl; - tmpl.get(NULL, type.c_str(), &detailed_tmpl); - - return get_data_type(detailed_tmpl, key); -} - -// called by context_trigger_rule_add_entry() -bool rule_validator::check_referential_data(std::string name, CtxJson1& ref_info) -{ - std::map type_map; - - CtxJson1 ref_data; - for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_OPTION, i, &ref_data); i++) { - std::string ref_key; - ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); - std::string cond_type; - ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); - - if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key - } - - // Err: Invalid key or Value type not matched - IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); - } - - for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_ATTRIBUTE, i, &ref_data); i++) { - std::string ref_key; - ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); - std::string cond_type; - ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); - - if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key - } - - // Err: Invalid key or Value type not matched - 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 TRIG_TMPL_TYPE_ENUM as TRIG_TMPL_TYPE_STRING for referential data - if (type1 == type2) { - return true; - } - - if ((type1 == TRIG_TMPL_TYPE_STRING || type1 == TRIG_TMPL_TYPE_ENUM) && (type2 == TRIG_TMPL_TYPE_STRING || type2 == TRIG_TMPL_TYPE_ENUM)) { - return true; - } - - return false; -} - -bool rule_validator::is_valid_operator(std::string type, std::string op) -{ - if (op == CONTEXT_TRIGGER_EQUAL_TO || op == CONTEXT_TRIGGER_NOT_EQUAL_TO) { - return true; - } - - if (type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_DOUBLE) { - if (op == CONTEXT_TRIGGER_GREATER_THAN || op == CONTEXT_TRIGGER_GREATER_THAN_OR_EQUAL_TO || - op == CONTEXT_TRIGGER_LESS_THAN || op == CONTEXT_TRIGGER_LESS_THAN_OR_EQUAL_TO) { - return true; - } - } - - return false; -} - -// For custom item template -bool rule_validator::is_valid_template(CtxJson1& attr_template) -{ - IF_FAIL_RETURN_TAG(attr_template != EMPTY_JSON_OBJECT, false, _E, "Custom template: empty CtxJson1"); - - bool ret; - std::list keys; - attr_template.getKeys(&keys); - - for (std::list::iterator it = keys.begin(); it != keys.end(); it++) { - std::string key = *it; - - std::string type = get_data_type(attr_template, key); - IF_FAIL_RETURN_TAG(type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM, - false, _E, "Custom template: invalid data type"); - - CtxJson1 elem; - attr_template.get(NULL, key.c_str(), &elem); - if (type == TRIG_TMPL_TYPE_INTEGER) { - ret = check_template_int(elem); - IF_FAIL_RETURN(ret, false); - } else if (type == TRIG_TMPL_TYPE_STRING) { - ret = check_template_string(elem); - IF_FAIL_RETURN(ret, false); - } else if (type == TRIG_TMPL_TYPE_ENUM) { - ret = check_template_enum(elem); - IF_FAIL_RETURN(ret, false); - } - } - - return true; -} - -bool check_template_int(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - bool min = false; - bool max = false; - int min_val = 0; - int max_val = 0; - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - if (elem_key == TRIG_TMPL_KEY_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 == TRIG_TMPL_KEY_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 == TRIG_TMPL_KEY_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(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); - } - - return true; -} - -bool check_template_enum(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - - if (elem_key == TRIG_TMPL_TYPE_ENUM) { - int size = elem.getSize(NULL, TRIG_TMPL_TYPE_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, TRIG_TMPL_TYPE_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 == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); - } - } - - return true; -} diff --git a/src/trigger/rule_validator.h b/src/trigger/rule_validator.h deleted file mode 100644 index 688a295..0000000 --- a/src/trigger/rule_validator.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __CONTEXT_RULE_VALIDATOR_H__ -#define __CONTEXT_RULE_VALIDATOR_H__ - -#include - -namespace ctx { - namespace rule_validator { - - int request_template(std::string name, bool mandatory = false); - void remove_template(std::string name); - bool check_option(ctx::CtxJson1 &item); - bool check_option_int(std::string name, std::string key, int value); - bool check_option_string(std::string name, std::string key, std::string value); - bool check_option_reference(std::string event, ctx::CtxJson1 &item); - bool check_comparison_int(std::string name, std::string key, std::string op, int value); - bool check_comparison_string(std::string name, std::string key, std::string op, std::string value); - bool check_valid_key(std::string type, std::string name, std::string key); - - bool set_ref_info(std::string type, ctx::CtxJson1 *jref, std::string name, std::string key, std::string ref_key); - std::string get_data_type_from_template(std::string type, std::string name, std::string key); - bool check_referential_data(std::string name, ctx::CtxJson1 &ref_info); - bool is_valid_operator(std::string type, std::string op); - - bool is_valid_template(ctx::CtxJson1& attr_template); - } -} /* namespace ctx */ - -#endif /* __CONTEXT_RULE_VALIDATOR_H__ */