diff options
author | Pavel Březina <pbrezina@redhat.com> | 2014-04-28 10:54:12 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-05-29 09:08:38 +0200 |
commit | efa6c1f75c4c18bcc148d6e7efd429c2d56499ad (patch) | |
tree | e029f971cc0121605338be6df8cdab46c19017b7 /src/lib/sifp/sss_sifp_parser.c | |
parent | f43c6a9ae2aea13b7a83fd932139f9352efbfcad (diff) | |
download | sssd-efa6c1f75c4c18bcc148d6e7efd429c2d56499ad.tar.gz sssd-efa6c1f75c4c18bcc148d6e7efd429c2d56499ad.tar.xz sssd-efa6c1f75c4c18bcc148d6e7efd429c2d56499ad.zip |
sss_sifp: add support for string dictionary
https://fedorahosted.org/sssd/ticket/2254
Reviewed-by: Sumit Bose <sbose@redhat.com>
Diffstat (limited to 'src/lib/sifp/sss_sifp_parser.c')
-rw-r--r-- | src/lib/sifp/sss_sifp_parser.c | 197 |
1 files changed, 191 insertions, 6 deletions
diff --git a/src/lib/sifp/sss_sifp_parser.c b/src/lib/sifp/sss_sifp_parser.c index 1c1ff80c8..eaa57d8d5 100644 --- a/src/lib/sifp/sss_sifp_parser.c +++ b/src/lib/sifp/sss_sifp_parser.c @@ -20,6 +20,7 @@ #include <dbus/dbus.h> #include <string.h> +#include <dhash.h> #include "lib/sifp/sss_sifp.h" #include "lib/sifp/sss_sifp_private.h" @@ -102,6 +103,149 @@ sss_sifp_get_array_length(DBusMessageIter *iter) return size; } +static void hash_delete_cb(hash_entry_t *item, + hash_destroy_enum type, + void *pvt) +{ + sss_sifp_ctx *ctx = (sss_sifp_ctx*)pvt; + char **values = (char**)(item->value.ptr); + int i; + + if (values == NULL) { + return; + } + + for (i = 0; values[i] != NULL; i++) { + _free(ctx, values[i]); + values[i] = NULL; + } + + _free(ctx, values); + item->value.ptr = NULL; +} + +static sss_sifp_error +sss_sifp_parse_dict(sss_sifp_ctx *ctx, + DBusMessageIter *iter, + hash_table_t *table) +{ + DBusMessageIter dict_iter; + DBusMessageIter array_iter; + sss_sifp_error ret; + hash_key_t table_key; + hash_value_t table_value; + const char *key = NULL; + const char *value = NULL; + char **values = NULL; + unsigned int i; + unsigned int num_values; + int hret; + + dbus_message_iter_recurse(iter, &dict_iter); + + /* get the key */ + check_dbus_arg(&dict_iter, DBUS_TYPE_STRING, ret, done); + dbus_message_iter_get_basic(&dict_iter, &key); + + table_key.type = HASH_KEY_STRING; + table_key.str = sss_sifp_strdup(ctx, key); + if (table_key.str == NULL) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + if (!dbus_message_iter_next(&dict_iter)) { + ret = SSS_SIFP_INTERNAL_ERROR; + goto done; + } + + /* now read the value */ + switch (dbus_message_iter_get_arg_type(&dict_iter)) { + case DBUS_TYPE_STRING: + dbus_message_iter_get_basic(&dict_iter, &value); + values = _alloc_zero(ctx, char *, 2); + if (values == NULL) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + values[0] = sss_sifp_strdup(ctx, value); + if (values[0] == NULL) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + values[1] = NULL; + + ret = SSS_SIFP_OK; + break; + case DBUS_TYPE_ARRAY: + num_values = sss_sifp_get_array_length(&dict_iter); + if (num_values == 0) { + values = NULL; + ret = SSS_SIFP_OK; + goto done; + } + + if (dbus_message_iter_get_element_type(&dict_iter) + != DBUS_TYPE_STRING) { + ret = SSS_SIFP_NOT_SUPPORTED; + goto done; + } + + dbus_message_iter_recurse(&dict_iter, &array_iter); + + values = _alloc_zero(ctx, char*, num_values + 1); + if (values == NULL) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + for (i = 0; i < num_values; i++) { + dbus_message_iter_get_basic(&array_iter, &value); + values[i] = sss_sifp_strdup(ctx, value); + if (values[i] == NULL) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + dbus_message_iter_next(&array_iter); + } + + ret = SSS_SIFP_OK; + break; + default: + ret = SSS_SIFP_NOT_SUPPORTED; + break; + } + + table_value.type = HASH_VALUE_PTR; + table_value.ptr = values; + + hret = hash_enter(table, &table_key, &table_value); + if (hret == HASH_ERROR_NO_MEMORY) { + ret = SSS_SIFP_OUT_OF_MEMORY; + } else if (hret != HASH_SUCCESS) { + ret = SSS_SIFP_INTERNAL_ERROR; + } + +done: + if (table_key.str != NULL) { + _free(ctx, table_key.str); + } + + if (ret != SSS_SIFP_OK) { + if (values != NULL) { + for (i = 0; values[i] != NULL; i++) { + _free(ctx, values[i]); + } + _free(ctx, values); + } + } + + return ret; +} + static sss_sifp_error sss_sifp_parse_basic(sss_sifp_ctx *ctx, DBusMessageIter *iter, @@ -178,6 +322,7 @@ sss_sifp_parse_array(sss_sifp_ctx *ctx, { DBusMessageIter array_iter; sss_sifp_error ret; + int hret; attr->num_values = sss_sifp_get_array_length(iter); dbus_message_iter_recurse(iter, &array_iter); @@ -246,19 +391,57 @@ sss_sifp_parse_array(sss_sifp_ctx *ctx, ret = SSS_SIFP_OK; break; + case DBUS_TYPE_DICT_ENTRY: + attr->type = SSS_SIFP_ATTR_TYPE_STRING_DICT; + if (attr->num_values == 0) { + attr->data.str_dict = NULL; + ret = SSS_SIFP_OK; + goto done; + } + + hret = hash_create_ex(10, &(attr->data.str_dict), 0, 0, 0, 0, + ctx->alloc_fn, ctx->free_fn, ctx->alloc_pvt, + hash_delete_cb, ctx); + if (hret != HASH_SUCCESS) { + ret = SSS_SIFP_OUT_OF_MEMORY; + goto done; + } + + for (i = 0; i < attr->num_values; i++) { + ret = sss_sifp_parse_dict(ctx, &array_iter, attr->data.str_dict); + if (ret != SSS_SIFP_OK) { + _free(ctx, attr->data.str_dict); + goto done; + } + + if (!dbus_message_iter_next(&array_iter) + && i + 1 < attr->num_values) { + ret = SSS_SIFP_INTERNAL_ERROR; + goto done; + } + } + + ret = SSS_SIFP_OK; + break; default: ret = SSS_SIFP_INVALID_ARGUMENT; break; } done: - if (ret != SSS_SIFP_OK && attr->type == SSS_SIFP_ATTR_TYPE_STRING - && attr->data.str != NULL) { - unsigned int i; - for (i = 0; attr->data.str[i] != NULL && i < attr->num_values; i++) { - _free(ctx, attr->data.str[i]); + if (ret != SSS_SIFP_OK) { + if (attr->type == SSS_SIFP_ATTR_TYPE_STRING && attr->data.str != NULL) { + for (unsigned int i = 0; + attr->data.str[i] != NULL && i < attr->num_values; + i++) { + _free(ctx, attr->data.str[i]); + } + _free(ctx, attr->data.str); + } else if (attr->type == SSS_SIFP_ATTR_TYPE_STRING_DICT + && attr->data.str_dict != NULL) { + hash_destroy(attr->data.str_dict); + attr->data.str_dict = NULL; } - _free(ctx, attr->data.str); } return ret; @@ -283,6 +466,8 @@ sss_sifp_parse_variant(sss_sifp_ctx *ctx, } else { /* container types */ switch (type) { + /* case DBUS_TYPE_DICT_ENTRY may only be contained within an array + * in variant */ case DBUS_TYPE_ARRAY: ret = sss_sifp_parse_array(ctx, &variant_iter, attr);; break; |