summaryrefslogtreecommitdiff
path: root/main/sorcery.c
diff options
context:
space:
mode:
authorGeorge Joseph <george.joseph@fairview5.com>2014-11-21 17:49:39 +0000
committerGeorge Joseph <george.joseph@fairview5.com>2014-11-21 17:49:39 +0000
commit4394e0431c81e80741273e4f3f63be4137716ff5 (patch)
treec53b605fe5fe54bb7d2d8768d476bff8f64b7437 /main/sorcery.c
parentd663e045f5613ba5b0620a3bb6f3f0fe0c35b1dc (diff)
sorcery: Make is_object_field_registered handle field names that are regexes.
As a result of https://reviewboard.asterisk.org/r/3305, res_sorcery_realtime was tossing database fields that didn't have an exact match to a sorcery registered field. This broke the ability to use regexes as field names which manifested itself as a failure of res_pjsip_phoneprov_provider which uses this capability. It also broke handling of fields that start with '@' in realtime but I don't think anyone noticed. This patch does the following... * Modifies ast_sorcery_fields_register to pre-compile the name regex. * Modifies ast_sorcery_is_object_field_registered to test the regex if it exists instead of doing an exact strcmp. * Modifies res_pjsip_phoneprov_provider with a few tweaks to get it to work with realtime. Tested-by: George Joseph Review: https://reviewboard.asterisk.org/r/4185/ ........ Merged revisions 428543 from http://svn.asterisk.org/svn/asterisk/branches/12 ........ Merged revisions 428544 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@428545 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/sorcery.c')
-rw-r--r--main/sorcery.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/main/sorcery.c b/main/sorcery.c
index 9ddf77020..f732d6ee4 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -140,6 +140,9 @@ struct ast_sorcery_object_field {
/*! \brief Name of the field */
char name[MAX_OBJECT_FIELD];
+ /*! \brief The compiled name regex if name is a regex */
+ regex_t *name_regex;
+
/*! \brief Callback function for translation of a single value */
sorcery_field_handler handler;
@@ -869,18 +872,41 @@ void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char
object_type->diff = diff;
}
+static void sorcery_object_field_destructor(void *obj)
+{
+ struct ast_sorcery_object_field *object_field = obj;
+
+ if (object_field->name_regex) {
+ regfree(object_field->name_regex);
+ }
+}
+
int ast_sorcery_object_fields_register(struct ast_sorcery *sorcery, const char *type, const char *regex, aco_option_handler config_handler, sorcery_fields_handler sorcery_handler)
{
+#define MAX_REGEX_ERROR_LEN 128
RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
+ int rc;
- if (!object_type || !object_type->type.item_alloc || !config_handler || !(object_field = ao2_alloc(sizeof(*object_field), NULL))) {
+ if (!object_type || !object_type->type.item_alloc || !config_handler
+ || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
return -1;
}
ast_copy_string(object_field->name, regex, sizeof(object_field->name));
object_field->multiple_handler = sorcery_handler;
+ if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
+ return -1;
+ }
+
+ if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
+ char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
+ regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
+ ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
+ return -1;
+ }
+
ao2_link(object_type->fields, object_field);
__aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
@@ -1926,6 +1952,20 @@ struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sor
return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
}
+static int is_registered_cb(void *obj, void *arg, int flags)
+{
+ struct ast_sorcery_object_field *object_field = obj;
+ char *name = arg;
+ int rc = 0;
+
+ if (object_field->name_regex
+ && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
+ rc = CMP_MATCH | CMP_STOP;
+ }
+
+ return rc;
+}
+
int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
const char *field_name)
{
@@ -1935,6 +1975,11 @@ int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type
ast_assert(object_type != NULL);
object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
+
+ if (!object_field) {
+ object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
+ }
+
if (!object_field) {
res = 0;
}