diff --git a/obuspa/patches/0006-contains-expression.patch b/obuspa/patches/0006-contains-expression.patch new file mode 100644 index 000000000..f57233efb --- /dev/null +++ b/obuspa/patches/0006-contains-expression.patch @@ -0,0 +1,121 @@ +Index: obuspa-9.0.4.11/src/core/expr_vector.c +=================================================================== +--- obuspa-9.0.4.11.orig/src/core/expr_vector.c ++++ obuspa-9.0.4.11/src/core/expr_vector.c +@@ -58,6 +58,7 @@ char *expr_op_2_str[kExprOp_Max] = + "<", // kExprOp_LessThan + ">", // kExprOp_GreaterThan + "=", // kExprOp_Equals ++ "~=", // kExprOp_Contains + }; + + +@@ -482,6 +483,15 @@ char *SplitOnOperator(char *buf, expr_op + *op = '\0'; + return &op[2]; + } ++ ++ // Exit if found the "~=" operator ++ op = strstr(buf, "~="); ++ if (op != NULL) ++ { ++ *p_op = kExprOp_Contains; ++ *op = '\0'; ++ return &op[2]; ++ } + + // Exit if found the "<" operator + op = strchr(buf, '<'); +Index: obuspa-9.0.4.11/src/core/path_resolver.c +=================================================================== +--- obuspa-9.0.4.11.orig/src/core/path_resolver.c ++++ obuspa-9.0.4.11/src/core/path_resolver.c +@@ -1481,7 +1481,7 @@ int ResolveUniqueKey(char *resolved, cha + char temp[MAX_DM_PATH]; + bool is_match; + bool is_ref_match; +- expr_op_t valid_ops[] = {kExprOp_Equal, kExprOp_NotEqual, kExprOp_LessThanOrEqual, kExprOp_GreaterThanOrEqual, kExprOp_LessThan, kExprOp_GreaterThan}; ++ expr_op_t valid_ops[] = {kExprOp_Equal, kExprOp_NotEqual, kExprOp_LessThanOrEqual, kExprOp_GreaterThanOrEqual, kExprOp_LessThan, kExprOp_GreaterThan, kExprOp_Contains}; + unsigned short permission_bitmask; + + // Exit if unable to find the end of the unique key +@@ -1815,6 +1815,67 @@ int DoUniqueKeysMatch(int index, search_ + } + USP_ASSERT(gge->value != NULL); // GROUP_GET_VECTOR_GetValues() should have set an error message if the vendor hook didn't set a value for the parameter + ++ if (ec->op == kExprOp_Contains) { ++ // NOTE: There is no "list" flag defined for the key parameter, which should be a limitation at the moment. ++ // The code below assumes comma-separated values in the key parameter value for the "contains" operator ++ char *list_copy = USP_STRDUP(gge->value); ++ char *saveptr; ++ char *token; ++ bool found = false; ++ ++ // Split the list and compare each element ++ token = strtok_r(list_copy, ",", &saveptr); ++ while (token != NULL) ++ { ++ // Trim whitespace from token ++ TEXT_UTILS_TrimBuffer(token); ++ ++ // Compare based on type ++ if (type_flags & (DM_INT | DM_UINT | DM_ULONG | DM_LONG | DM_DECIMAL)) ++ { ++ err = DM_ACCESS_CompareNumber(token, kExprOp_Equal, ec->value, &result); ++ } ++ else if (type_flags & DM_BOOL) ++ { ++ err = DM_ACCESS_CompareBool(token, kExprOp_Equal, ec->value, &result); ++ } ++ else if (type_flags & DM_DATETIME) ++ { ++ err = DM_ACCESS_CompareDateTime(token, kExprOp_Equal, ec->value, &result); ++ } ++ else ++ { ++ // Default string comparison ++ err = DM_ACCESS_CompareString(token, kExprOp_Equal, ec->value, &result); ++ } ++ ++ if (err != USP_ERR_OK) ++ { ++ USP_FREE(list_copy); ++ return err; ++ } ++ ++ if (result) ++ { ++ found = true; ++ break; ++ } ++ ++ token = strtok_r(NULL, ",", &saveptr); ++ } ++ ++ USP_FREE(list_copy); ++ ++ // Exit if element not found in list ++ if (!found) ++ { ++ return USP_ERR_OK; ++ } ++ ++ // Skip the normal comparison since we already handled it ++ continue; ++ } ++ + // Determine the function to call to perform the comparison + if (type_flags & (DM_INT | DM_UINT | DM_ULONG | DM_LONG | DM_DECIMAL)) + { +Index: obuspa-9.0.4.11/src/include/usp_api.h +=================================================================== +--- obuspa-9.0.4.11.orig/src/include/usp_api.h ++++ obuspa-9.0.4.11/src/include/usp_api.h +@@ -105,6 +105,7 @@ typedef enum + kExprOp_LessThan, // '<' + kExprOp_GreaterThan, // '>' + kExprOp_Equals, // '=' ++ kExprOp_Contains, // '~=' + + kExprOp_Max + } expr_op_t;