diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-07-07 15:02:09 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-07-07 15:02:09 -0400 |
commit | 3e875d39e2a3d606f411abdfa13cfc7b585afa38 (patch) | |
tree | e19069e1b80ce5f3adad58856e85e87210687ffa /src | |
parent | 4a0ba6a0782d07fb6bcdd386a5c7ae5141a0c90b (diff) | |
download | slapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.tar.gz slapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.tar.xz slapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.zip |
- teach "merge" to merge lists of values in addition to single values
- deref: return a list of values
- referral: return a list of values
- drop "echo" and "list" (the latter subsumed by "merge")
Diffstat (limited to 'src')
-rw-r--r-- | src/format.c | 670 |
1 files changed, 220 insertions, 450 deletions
diff --git a/src/format.c b/src/format.c index f36ff81..c5fa1ab 100644 --- a/src/format.c +++ b/src/format.c @@ -64,6 +64,28 @@ static int format_expand(struct plugin_state *state, char ***ref_attrs, struct format_inref_attr ***inref_attrs); +static char * +xstrndup(const char *start, size_t length) +{ + char *ret, *end; + end = memchr(start, '\0', length); + if (end != NULL) { + length = end - start; + } + ret = malloc(length + 1); + if (ret != NULL) { + memcpy(ret, start, length); + ret[length] = '\0'; + } + return ret; +} + +static char * +xstrndupp(const char *start, const char *end) +{ + return xstrndup(start, end - start); +} + char ** format_dup_attr_list(char **attr_list) { @@ -450,46 +472,6 @@ format_parse_args(struct plugin_state *state, const char *args, return 0; } -/* Echo the parameter text. */ -static int -format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *group, const char *set, - const char *args, const char *disallowed, - char *outbuf, int outbuf_len, struct format_choice **outbuf_choices, - char ***ref_attrs, struct format_inref_attr ***inref_attrs) -{ - int ret, i, argc, len; - char **argv; - ret = format_parse_args(state, args, &argc, &argv); - if (ret != 0) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "echo: error parsing arguments\n"); - return -EINVAL; - } - if (argc < 1) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "echo: requires at least one argument\n"); - format_free_parsed_args(argv); - return -EINVAL; - } - for (i = 0, ret = 0; i < argc; i++) { - /* Get the length of this argument. */ - len = strlen(argv[i]); - /* Check that we've got space for this argument. */ - if (ret + len > outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "echo: out of space\n"); - return -ENOBUFS; - } - /* Append the text of the argument. */ - memcpy(outbuf + ret, argv[i], len); - ret += len; - } - format_free_parsed_args(argv); - return ret; -} - /* Choose the first value of the attribute in the entry. */ static int format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, @@ -542,88 +524,9 @@ format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return ret; } -/* Create a list of the values of the attributes which are passed as arguments, - * joined by a separator given as the first argument. */ -static int -format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *group, const char *set, - const char *args, const char *disallowed, - char *outbuf, int outbuf_len, struct format_choice **outbuf_choices, - char ***ref_attrs, struct format_inref_attr ***inref_attrs) -{ - int ret, i, j, slen, count, argc; - Slapi_ValueSet *values; - Slapi_Value *value; - char **argv, *actual_attr; - const struct berval *val; - int disposition, buffer_flags; - ret = format_parse_args(state, args, &argc, &argv); - if (ret != 0) { - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "list: error parsing arguments\n"); - return -EINVAL; - } - for (i = 1, ret = 0, count = 0; i < argc; i++) { - /* Get the list of values for this attribute. */ - if (slapi_vattr_values_get(e, argv[i], &values, &disposition, - &actual_attr, 0, - &buffer_flags) != 0) { - continue; - } - for (j = slapi_valueset_first_value(values, &value); - j != -1; - j = slapi_valueset_next_value(values, j, &value)) { - /* Get the length of the value. */ - val = slapi_value_get_berval(value); - /* Check if we have space for the value. */ - if (ret + val->bv_len > (unsigned int) outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "list: out of space\n"); - slapi_vattr_values_free(&values, &actual_attr, - buffer_flags); - format_free_parsed_args(argv); - return -ENOBUFS; - } - /* If the value is empty, skip it. */ - if (val->bv_len == 0) { - continue; - } - /* If we've already added values, add the separator. */ - if (count > 0) { - /* Get the length of the separator. */ - slen = strlen(argv[0]); - /* Check if we have space for the separator. */ - if ((ret + val->bv_len + slen) > - (unsigned int) outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "list: out of space\n"); - slapi_vattr_values_free(&values, - &actual_attr, - buffer_flags); - format_free_parsed_args(argv); - return -ENOBUFS; - } - /* Copy in the separator. */ - memcpy(outbuf + ret, argv[0], slen); - ret += slen; - } - /* Copy in the value. */ - memcpy(outbuf + ret, val->bv_val, val->bv_len); - ret += val->bv_len; - count++; - } - /* Free the value set for this attribute. */ - slapi_vattr_values_free(&values, &actual_attr, buffer_flags); - } - format_free_parsed_args(argv); - return ret; -} - -/* Look up the entry matching a DN stored in the attribute named by the second - * argument, pull out the values for the attribute named by the third - * argument, and create a list separated by the first argument. */ +/* Look up the entries matching DNs stored in the attribute named by the first + * argument, pull out the values for the attribute named by the second + * argument, and return a list of those values. */ static int format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *group, const char *set, @@ -632,14 +535,14 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, struct format_choice **outbuf_choices, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { - int i, j, slen, ret, count, argc; + int i, j, slen, ret, argc; Slapi_Entry *ref; Slapi_DN *refdn; Slapi_ValueSet *ref_values, *values; Slapi_Value *ref_value, *value; int disposition, ref_disposition, buffer_flags, ref_buffer_flags; char **argv, *attrs[3], *actual_attr, *actual_ref_attr; - const char *sep, *cref; + const char *cref; const struct berval *val; char *ref_attr, *target_attr; struct berval **choices; @@ -649,52 +552,38 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, "deref: error parsing arguments\n"); return -EINVAL; } + if (argc != 2) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "deref: requires two arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } if (outbuf_choices == NULL) { - if (argc != 3) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "deref: requires 3 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; - } - sep = argv[0]; - ref_attr = argv[1]; - target_attr = argv[2]; - } else { - if (argc != 2) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "deref: requires 2 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; - } - sep = NULL; - ref_attr = argv[0]; - target_attr = argv[1]; + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "deref: returns a list, but a list " + "would not be appropriate\n"); + format_free_parsed_args(argv); + return -EINVAL; } + ref_attr = argv[0]; + target_attr = argv[1]; /* Note that the attribute in this entry refers to other entries. */ if (ref_attrs != NULL) { backend_shr_add_strlist(ref_attrs, ref_attr); } - /* Get the names of the reference attribute. */ + /* Get the values of the reference attribute from this entry. */ if (slapi_vattr_values_get(e, ref_attr, &ref_values, &ref_disposition, &actual_ref_attr, 0, &ref_buffer_flags) != 0) { - /* No references. */ + /* No references means we're done. */ format_free_parsed_args(argv); - if (outbuf_choices == NULL) { - return 0; - } else { - return -ENOENT; - } + return 0; } /* Retrieve these attributes from the referred-to entries. */ attrs[0] = ref_attr; attrs[1] = target_attr; attrs[2] = NULL; /* Iterate through the names of the referred-to entries. */ - ret = 0; - count = 0; choices = NULL; for (i = slapi_valueset_first_value(ref_values, &ref_value); i != -1; @@ -708,7 +597,7 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, if (refdn == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "deref: internal error reading " + "deref: internal error parsing name " "\"%s\"\n", cref); continue; } @@ -738,61 +627,13 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, for (j = slapi_valueset_first_value(values, &value); j != -1; j = slapi_valueset_next_value(values, j, &value)) { - /* Get the length of the value. */ + /* Get the value. */ val = slapi_value_get_berval(value); - /* Check if there's space for the value. */ - if (ret + val->bv_len > (unsigned int) outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "deref: out of space\n"); - slapi_vattr_values_free(&values, - &actual_attr, - buffer_flags); - slapi_entry_free(ref); - slapi_vattr_values_free(&ref_values, - &actual_ref_attr, - ref_buffer_flags); - format_free_parsed_args(argv); - return -ENOBUFS; - } /* If the value is empty, skip it. */ if (val->bv_len == 0) { continue; } - /* If we're keeping a list of choices, just add it to - * the list of values we've retrieved and keep going. */ - if (outbuf_choices != NULL) { - format_add_bv_list(&choices, val); - continue; - } - /* If we need to, add the separator. */ - if (count > 0) { - /* Get the length of the separator. */ - slen = strlen(sep); - /* Check if there's space for the separator. */ - if ((ret + val->bv_len + slen) > - (unsigned int) outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "deref: out of space\n"); - slapi_vattr_values_free(&values, - &actual_attr, - buffer_flags); - slapi_entry_free(ref); - slapi_vattr_values_free(&ref_values, - &actual_ref_attr, - ref_buffer_flags); - format_free_parsed_args(argv); - return -ENOBUFS; - } - /* Append the separator. */ - memcpy(outbuf + ret, sep, slen); - ret += slen; - } - /* Append the value. */ - memcpy(outbuf + ret, val->bv_val, val->bv_len); - ret += val->bv_len; - count++; + format_add_bv_list(&choices, val); } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); slapi_entry_free(ref); @@ -801,54 +642,29 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, &actual_ref_attr, ref_buffer_flags); format_free_parsed_args(argv); - if (outbuf_choices != NULL) { - if (choices != NULL) { - if (format_count_bv_list(choices) == 1) { - /* Return this value directly. */ - if (choices[0]->bv_len > - (unsigned int) outbuf_len) { - ret = -ENOSPC; - format_free_bv_list(choices); - } else { - memcpy(outbuf, choices[0]->bv_val, - choices[0]->bv_len); - ret = choices[0]->bv_len; - format_free_bv_list(choices); - } - } else { - /* Return the values we found. */ - format_add_choice(outbuf_choices, outbuf, - choices); - format_free_bv_list(choices); - } - } else { - /* Return a no-result error. */ - ret = -ENOENT; - } + /* Return any values we found. */ + if (choices != NULL) { + format_add_choice(outbuf_choices, outbuf, choices); + format_free_bv_list(choices); } - return ret; + return 0; } -/* Look up entries in the map named by the second argument, which have this - * entry's DN stored in the attribute named by the third argument, pull out the - * values for the attribute named by the fourth argument, and create a list - * separated by the first argument. */ +/* Look up entries in the set named by the first argument, which have this + * entry's DN stored in the attribute named by the second argument, pull out + * the values for the attribute named by the third argument, and return a list + * of those values. */ struct format_referred_cbdata { struct plugin_state *state; - char *attr, *separator; - char *outbuf; - int outbuf_len; - struct format_choice **outbuf_choices; + char *attr; struct berval **choices; - int count; - int ret; }; static int format_referred_entry_cb(Slapi_Entry *e, void *callback_data) { Slapi_ValueSet *values; Slapi_Value *value; - int i, disposition, buffer_flags, len, slen; + int i, disposition, buffer_flags; char *actual_attr; const struct berval *val; struct format_referred_cbdata *cbdata; @@ -866,7 +682,7 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) 0, &buffer_flags) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, - "referred: no values for \"%s\" in \"%s\"?\n", + "referred: no values for \"%s\" in \"%s\"\n", cbdata->attr, slapi_entry_get_ndn(e)); return 0; } @@ -875,39 +691,19 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) i = slapi_valueset_next_value(values, i, &value)) { /* Pull up the value. */ val = slapi_value_get_berval(value); - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "referred: got %d bytes of \"%.*s\"\n", - val->bv_len, val->bv_len, val->bv_val); - /* If we're keeping a list of choices, just add it to the list - * of values we've retrieved and keep going. */ - if (cbdata->outbuf_choices != NULL) { - format_add_bv_list(&cbdata->choices, val); + if (val->bv_len == 0) { continue; } - /* Check if there's space for the value. */ - slen = strlen(cbdata->separator); - if ((val->bv_len + (cbdata->count ? slen : 0)) > - (unsigned int) cbdata->outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "referred: out of space\n"); - slapi_vattr_values_free(&values, - &actual_attr, - buffer_flags); - cbdata->ret = -ENOBUFS; - return -1; - } - /* Store the value. */ - if (cbdata->count > 0) { - memcpy(cbdata->outbuf, cbdata->separator, slen); - } - memcpy(cbdata->outbuf + (cbdata->count ? slen : 0), - val->bv_val, val->bv_len); - len = val->bv_len + (cbdata->count ? slen : 0); - cbdata->outbuf += len; - cbdata->outbuf_len -= len; - cbdata->count++; + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "referred: got %d-byte value for \"%s\"\n", + val->bv_len, actual_attr); + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "referred: got \"%.*s\" for \"%s\"\n", + val->bv_len, val->bv_val, actual_attr); + /* Add it to the list of values we've retrieved. */ + format_add_bv_list(&cbdata->choices, val); } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); return 0; @@ -922,7 +718,7 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, { int i, ret, argc; Slapi_PBlock *local_pb; - char **argv, *attrs[2], *filter, *tndn, *sep, *attr, *other_attr; + char **argv, *attrs[2], *filter, *tndn, *attr, *other_attr; char *other_set, *set_filter, **set_bases, *use_filter; struct format_referred_cbdata cbdata; @@ -932,35 +728,22 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, "referred: error parsing arguments\n"); return -EINVAL; } + if (argc != 3) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referred: requires 3 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } if (outbuf_choices == NULL) { - if (argc != 4) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "referred: requires 4 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; - } - sep = argv[0]; - other_set = argv[1]; - other_attr = argv[2]; - attr = argv[3]; - } else { - if (argc != 3) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "referred: requires 3 arguments\n"); - format_free_parsed_args(argv); - return -EINVAL; - } - sep = NULL; - other_set = argv[0]; - other_attr = argv[1]; - attr = argv[2]; + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referred: returns a list, but a list would " + "not be appropriate here\n"); + format_free_parsed_args(argv); + return -EINVAL; } - - /* Build the attribute list. */ - attrs[0] = attr; - attrs[1] = NULL; + other_set = argv[0]; + other_attr = argv[1]; + attr = argv[2]; /* Set up to search for matches. */ local_pb = slapi_pblock_new(); @@ -972,15 +755,10 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, } cbdata.state = state; cbdata.attr = attr; - cbdata.separator = sep; - cbdata.outbuf = outbuf; - cbdata.outbuf_len = outbuf_len; - cbdata.outbuf_choices = outbuf_choices; cbdata.choices = NULL; - cbdata.count = 0; - cbdata.ret = 0; - /* Retrieve the map-specific paramters. */ + /* Retrieve the set-specific paramaters to determine which entries to + * examine. */ set_filter = NULL; set_bases = NULL; backend_get_set_config(state, group, other_set, @@ -990,6 +768,10 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, state->plugin_desc->spd_id, "no search bases defined for \"%s\"/\"%s\"?\n", group, other_set); + backend_free_set_config(set_bases, set_filter); + slapi_pblock_destroy(local_pb); + format_free_parsed_args(argv); + return 0; } /* Note that the attribute in this map refers to this entry. */ @@ -998,6 +780,8 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, other_set, other_attr); } + /* Escape the current entry's DN in case it's necessary, and build a + * search filter. */ tndn = format_escape_for_filter(slapi_entry_get_ndn(e)); if (tndn == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -1008,30 +792,31 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, format_free_parsed_args(argv); return -ENOMEM; } - - /* Now just search through the entries used for the map. */ use_filter = set_filter ? set_filter : "(objectClass=*)"; + filter = malloc(strlen(use_filter) + strlen(other_attr) + + strlen(tndn) + 7); + if (filter == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referred: out of memory\n"); + backend_free_set_config(set_bases, set_filter); + slapi_pblock_destroy(local_pb); + format_free_parsed_args(argv); + return -ENOMEM; + } + sprintf(filter, "(&(%s=%s)%s)", other_attr, tndn, use_filter); + free(tndn); + + /* Search through the entries used for the set. */ + attrs[0] = attr; + attrs[1] = NULL; for (i = 0; (set_bases != NULL) && (set_bases[i] != NULL); i++) { - /* Build the search filter. */ - filter = malloc(strlen(use_filter) + strlen(other_attr) + - strlen(tndn) + 7); - if (filter == NULL) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "referred: out of memory\n"); - backend_free_set_config(set_bases, set_filter); - slapi_pblock_destroy(local_pb); - format_free_parsed_args(argv); - return -ENOMEM; - } - sprintf(filter, "(&(%s=%s)%s)", other_attr, tndn, use_filter); /* Set up the search. */ slapi_search_internal_set_pb(local_pb, set_bases[i], LDAP_SCOPE_SUB, filter, attrs, FALSE, NULL, NULL, state->plugin_identity, 0); - /* Let the callback do the work. */ + /* Let the callback do the work of saving a value. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "searching under \"%s\" for \"%s\"\n", @@ -1040,49 +825,23 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, NULL, format_referred_entry_cb, NULL); - free(filter); - /* If the callback left an error code for us, then stop. */ - if (cbdata.ret != 0) { - break; - } } - free(tndn); + free(filter); - if (outbuf_choices != NULL) { - if (cbdata.choices != NULL) { - if (format_count_bv_list(cbdata.choices) == 1) { - /* Return this value directly. */ - if (cbdata.choices[0]->bv_len > - (unsigned int) outbuf_len) { - cbdata.ret = -ENOSPC; - format_free_bv_list(cbdata.choices); - } else { - memcpy(outbuf, - cbdata.choices[0]->bv_val, - cbdata.choices[0]->bv_len); - cbdata.ret = cbdata.choices[0]->bv_len; - format_free_bv_list(cbdata.choices); - } - } else { - /* Return the values we found. */ - format_add_choice(outbuf_choices, outbuf, - cbdata.choices); - format_free_bv_list(cbdata.choices); - } - } else { - /* Return a no-result error. */ - cbdata.ret = -ENOENT; - } + /* Return any values we found. */ + if (cbdata.choices != NULL) { + format_add_choice(outbuf_choices, outbuf, cbdata.choices); + format_free_bv_list(cbdata.choices); } backend_free_set_config(set_bases, set_filter); slapi_pblock_destroy(local_pb); format_free_parsed_args(argv); - return cbdata.ret ? cbdata.ret : cbdata.outbuf - outbuf; + return 0; } -/* Evaluate each argument, after the first, in turn, and merge them, using the - * first argument as a separator. */ +/* Evaluate each argument's list of results, after the first, in turn, and + * merge them, using the first argument as a separator. */ static int format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, const char *group, const char *set, @@ -1091,9 +850,12 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, struct format_choice **outbuf_choices, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { - int ret, i, argc, len, slen, count; - char **argv; + int ret, i, j, argc, len, slen, count; + unsigned int *lengths; + char **argv, **values; + const char *sep; struct format_choice *these_choices; + ret = format_parse_args(state, args, &argc, &argv); if (ret != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -1106,51 +868,59 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, format_free_parsed_args(argv); return -EINVAL; } - slen = strlen(argv[0]); + sep = argv[0]; + slen = strlen(sep); for (i = 1, ret = 0, count = 0; i < argc; i++) { /* Expand this argument. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "merge: expanding ->%s<-\n", argv[i]); these_choices = NULL; - len = format_expand(state, pb, e, group, set, - argv[i], disallowed, - outbuf + ret + (count ? slen : 0), - outbuf_len - (ret + (count ? slen : 0)), - &these_choices, - ref_attrs, inref_attrs); - if (len < 0) { + values = format_get_data_set(state, e, group, set, + argv[i], disallowed, + ref_attrs, inref_attrs, + &lengths); + if (values == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "merge: error expanding ->%s<-: %s\n", - argv[i], strerror(-len)); - format_free_parsed_args(argv); - return len; + "merge: no values for ->%s<-\n", + argv[i]); + continue; } - /* If it didn't expand to anything, just keep going. */ - if (len == 0) { - if (these_choices == NULL) { - /* No choices, ignore this expression. */ + for (j = 0; values[j] != NULL; j++) { + /* Check for a non-empty value. */ + if (lengths[j] == 0) { continue; - } else { - /* Make note of the choices, and accept a - * zero-length value as a placeholder. */ - format_append_choice(outbuf_choices, - these_choices); } + /* Check if there's space for this value. */ + if (ret + lengths[j] + (count ? slen : 0) > + (unsigned int) outbuf_len) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "merge: out of space\n"); + format_free_data_set(values, lengths); + format_free_parsed_args(argv); + return -ENOBUFS; + } + /* Log this value. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "merge: got %d-byte value for ->%s<\n", + lengths[j], argv[i]); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "merge: got %.*s for ->%s<\n", + lengths[j], values[j], argv[i]); + /* If this isn't the first result, fill in the + * separator. Then fill in the value. */ + if (count > 0) { + memcpy(outbuf + ret, sep, slen); + ret += slen; + } + memcpy(outbuf + ret, values[j], lengths[j]); + ret += lengths[j]; + count++; } - /* Log this value. */ - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "merge: expanded ->%s<- to ->%.*s<-\n", - argv[i], len, - outbuf + ret + (count ? slen : 0)); - /* If we filled in a result, and we had more than one in there - * already, fill in the separator. */ - if (count > 0) { - memcpy(outbuf + ret, argv[0], slen); - } - ret += (len + (count ? slen : 0)); - count++; + format_free_data_set(values, lengths); } format_free_parsed_args(argv); return ret; @@ -1177,8 +947,7 @@ format_match_generic(struct plugin_state *state, { Slapi_ValueSet *values; Slapi_Value *value; - const char *cvalue; - char *actual_attr, **argv, **matches, *plugin_id; + char *cvalue, *actual_attr, **argv, **matches, *plugin_id, *defaults[2]; int i, count, argc, disposition, buffer_flags; int ret, len; @@ -1210,9 +979,11 @@ format_match_generic(struct plugin_state *state, for (i = slapi_valueset_first_value(values, &value); i != -1; i = slapi_valueset_next_value(values, i, &value)) { - cvalue = slapi_value_get_string(value); + cvalue = xstrndup(slapi_value_get_string(value), + slapi_value_get_length(value)); matches[count] = match_fn(argv[1], cvalue, argv + 2); + free(cvalue); if (matches[count] != NULL) { count++; } @@ -1226,48 +997,71 @@ format_match_generic(struct plugin_state *state, switch (count) { case 0: /* No matches. */ + free(matches); if ((default_arg >= 0) && (argv[default_arg] != NULL)) { /* Try to store the default. */ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "%s: no matching values for " "\"%s\", using default value \"%s\"\n", fnname, argv[1], argv[default_arg]); - len = strlen(argv[default_arg]); - if (len > outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, - "%s: out of space\n", fnname); - free(matches); - format_free_parsed_args(argv); - return -ENOBUFS; + if (outbuf_choices != NULL) { + /* Return the default value as a list. */ + defaults[0] = argv[default_arg]; + defaults[1] = NULL; + format_add_choice_str(outbuf_choices, outbuf, + defaults); + len = 0; + } else { + /* Store the default directly in the buffer. */ + len = strlen(argv[default_arg]); + if (len > outbuf_len) { + slapi_log_error(SLAPI_LOG_PLUGIN, + plugin_id, + "%s: out of space\n", + fnname); + format_free_parsed_args(argv); + return -ENOBUFS; + } + memcpy(outbuf, argv[default_arg], len); } - memcpy(outbuf, argv[default_arg], len); } else { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "%s: no matching values for " "\"%s\", and no default value\n", fnname, argv[1]); - free(matches); format_free_parsed_args(argv); return -ENOENT; } break; case 1: /* Single result. */ - len = strlen(matches[0]); - if (len > outbuf_len) { - slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, - "%s: out of space\n", fnname); - free(matches[0]); - free(matches); - format_free_parsed_args(argv); - return -ENOBUFS; + if (outbuf_choices != NULL) { + /* Return the one match as a list. */ + format_add_choice_str(outbuf_choices, outbuf, matches); + len = 0; + } else { + /* Store the one match directly in the buffer. */ + len = strlen(matches[0]); + if (len > outbuf_len) { + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, + "%s: out of space\n", fnname); + free(matches[0]); + free(matches); + format_free_parsed_args(argv); + return -ENOBUFS; + } + memcpy(outbuf, matches[0], len); } - memcpy(outbuf, matches[0], len); break; default: - if (outbuf_choices == NULL) { + if (outbuf_choices != NULL) { + /* Record the set of matching values as choices at this + * location. */ + format_add_choice_str(outbuf_choices, outbuf, matches); + len = 0; + } else { /* Too many matches to store. */ - if (argv[default_arg] != NULL) { + if ((default_arg >= 0) && (argv[default_arg] != NULL)) { slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, "%s: too many matching values " "for \"%s\", using default " @@ -1293,11 +1087,6 @@ format_match_generic(struct plugin_state *state, "%s: too many matching values " "for \"%s\", and no default " "value\n", fnname, argv[1]); - if (values != NULL) { - slapi_vattr_values_free(&values, - &actual_attr, - buffer_flags); - } for (i = 0; i < count; i++) { free(matches[i]); } @@ -1305,11 +1094,6 @@ format_match_generic(struct plugin_state *state, format_free_parsed_args(argv); return -ENOENT; } - } else { - /* Record the set of matching values as choices at this - * location. */ - format_add_choice_str(outbuf_choices, outbuf, matches); - len = 0; } break; } @@ -1516,9 +1300,7 @@ format_lookup_fn(const char *fnname) char ***ref_attrs, struct format_inref_attr ***inref_attrs); } fns[] = { - {"echo", format_echo}, {"first", format_first}, - {"list", format_list}, {"deref", format_deref}, {"referred", format_referred}, {"merge", format_merge}, @@ -1612,6 +1394,9 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, i = slapi_valueset_next_value(value_set, i, &value)) { val = slapi_value_get_berval(value); + if (val->bv_len == 0) { + continue; + } d = format_check_disallowed(val, disallowed); if (d == NULL) { @@ -1658,27 +1443,6 @@ format_find_closer(const char *pair, const char *pattern) return NULL; } -static char * -xstrndup(const char *start, size_t length) -{ - char *ret, *end; - end = memchr(start, '\0', length); - if (end != NULL) { - length = end - start; - } - ret = malloc(length + 1); - if (ret != NULL) { - memcpy(ret, start, length); - ret[length] = '\0'; - } - return ret; -} -static char * -xstrndupp(const char *start, const char *end) -{ - return xstrndup(start, end - start); -} - /* Trim off prefixes or suffixes which match the given patterns, free the * original, and return the result. */ static struct berval @@ -2366,6 +2130,12 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, "choice: %d at %d\n", this_choice->values[i]->bv_len, this_choice->offset - template); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "choice: %.*s at %d\n", + this_choice->values[i]->bv_len, + this_choice->values[i]->bv_val, + this_choice->offset - template); } combinations *= this_choice->n_values; } |