diff options
-rw-r--r-- | src/format.c | 674 | ||||
-rw-r--r-- | src/format.h | 14 |
2 files changed, 449 insertions, 239 deletions
diff --git a/src/format.c b/src/format.c index 2b20305..f36ff81 100644 --- a/src/format.c +++ b/src/format.c @@ -51,7 +51,7 @@ struct format_choice { char *offset; int n_values; - char **values; + struct berval **values; struct format_choice *next; }; @@ -69,6 +69,7 @@ format_dup_attr_list(char **attr_list) { return backend_shr_dup_strlist(attr_list); } + void format_free_attr_list(char **attr_list) { @@ -110,6 +111,7 @@ format_dup_inref_attrs(struct format_inref_attr **attrs) } return ret; } + void format_add_inref_attrs(struct format_inref_attr ***attrs, const char *group, const char *set, @@ -159,6 +161,114 @@ format_free_inref_attrs(struct format_inref_attr **attrs) } } +static void * +xmemdup(char *region, int size) +{ + char *ret; + ret = malloc(size + 1); + if (ret != NULL) { + if (size > 0) { + memcpy(ret, region, size); + } + ret[size] = '\0'; + } + return ret; +} + +static int +format_count_bv_list(struct berval **bvlist) +{ + int i; + if (bvlist != NULL) { + for (i = 0; bvlist[i] != NULL; i++) { + continue; + } + return i; + } + return 0; +} + +static void +format_free_bv_list(struct berval **bvlist) +{ + int i; + if (bvlist != NULL) { + for (i = 0; bvlist[i] != NULL; i++) { + free(bvlist[i]->bv_val); + free(bvlist[i]); + } + free(bvlist); + } +} +static struct berval ** +format_dup_bv_list(struct berval **bvlist) +{ + struct berval **ret, *bv; + int i; + ret = NULL; + if (bvlist != NULL) { + for (i = 0; bvlist[i] != NULL; i++) { + continue; + } + ret = malloc((i + 1) * sizeof(struct berval *)); + if (ret != NULL) { + for (i = 0; bvlist[i] != NULL; i++) { + ret[i] = malloc(sizeof(struct berval)); + if (ret[i] != NULL) { + bv = bvlist[i]; + ret[i]->bv_val = xmemdup(bv->bv_val, + bv->bv_len); + ret[i]->bv_len = bv->bv_len; + } + } + ret[i] = NULL; + } + } + return ret; +} +static void +format_add_bv_list(struct berval ***bvlist, const struct berval *bv) +{ + struct berval **list; + int i; + if (bvlist == NULL) { + return; + } + if (*bvlist != NULL) { + for (i = 0; (*bvlist)[i] != NULL; i++) { + continue; + } + } else { + i = 0; + } + list = malloc((i + 2) * sizeof(struct berval *)); + if (list != NULL) { + if (i > 0) { + memcpy(list, *bvlist, i * sizeof(struct berval *)); + } + list[i] = malloc(sizeof(struct berval)); + if (list[i] != NULL) { + list[i]->bv_val = xmemdup(bv->bv_val, bv->bv_len); + if (list[i]->bv_val != NULL) { + list[i]->bv_len = bv->bv_len; + list[i + 1] = NULL; + *bvlist = list; + } else { + free(list[i]); + free(list); + format_free_bv_list(*bvlist); + *bvlist = NULL; + } + } else { + format_free_bv_list(*bvlist); + *bvlist = NULL; + } + } else { + format_free_bv_list(*bvlist); + *bvlist = NULL; + } +} + /* Maintain "choices" lists. */ static void format_retarget_choicesp(struct format_choice **choices, char *oldt, char *newt) @@ -178,9 +288,10 @@ static void format_free_choices(struct format_choice *choices) { struct format_choice *next; + int i; while (choices != NULL) { next = choices->next; - backend_shr_free_strlist(choices->values); + format_free_bv_list(choices->values); free(choices); choices = next; } @@ -213,21 +324,24 @@ format_append_choice(struct format_choice **choices, } } static void -format_add_choice(struct format_choice **choices, char *offset, char **values) +format_add_choice(struct format_choice **choices, char *offset, + struct berval **values) { struct format_choice *choice; + unsigned int size; int i; + char *p; if (values != NULL) { choice = malloc(sizeof(*choice)); if (choice != NULL) { choice->offset = offset; - choice->values = backend_shr_dup_strlist(values); choice->next = NULL; + for (i = 0; values[i] != NULL; i++) { + continue; + } + choice->n_values = i; + choice->values = format_dup_bv_list(values); if (choice->values != NULL) { - for (i = 0; choice->values[i] != NULL; i++) { - continue; - } - choice->n_values = i; format_append_choice(choices, choice); } else { free(choice); @@ -235,6 +349,43 @@ format_add_choice(struct format_choice **choices, char *offset, char **values) } } } +static struct berval ** +format_strlist_to_bv_list(char **values) +{ + struct berval **val; + int i; + char *p; + if (values != NULL) { + for (i = 0; values[i] != NULL; i++) { + continue; + } + val = malloc(sizeof(struct berval *) * (i + 1)); + if (val != NULL) { + for (i = 0; values[i] != NULL; i++) { + val[i] = malloc(sizeof(struct berval)); + if (val[i] != NULL) { + p = values[i]; + val[i]->bv_val = xmemdup(p, strlen(p)); + if (val[i] != NULL) { + val[i]->bv_len = strlen(p); + } + } + } + val[i] = NULL; + return val; + } + } + return NULL; +} +static void +format_add_choice_str(struct format_choice **choices, char *offset, + char **values) +{ + struct berval **vals; + vals = format_strlist_to_bv_list(values); + format_add_choice(choices, offset, vals); + format_free_bv_list(vals); +} /* Parse an argument string into an array of arguments. */ static void @@ -351,8 +502,8 @@ format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, int ret, i, len, argc; Slapi_ValueSet *values; Slapi_Value *value; + const struct berval *val; char **argv, *actual_attr; - const char *cvalue; int disposition, buffer_flags; ret = format_parse_args(state, args, &argc, &argv); if (argc != 1) { @@ -368,18 +519,17 @@ format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, i = slapi_valueset_first_value(values, &value); if (i != -1) { /* Get the length of the value. */ - cvalue = slapi_value_get_string(value); - len = strlen(cvalue); + val = slapi_value_get_berval(value); /* Check if we have space for the value. */ - if (ret + len > outbuf_len) { + if (ret + val->bv_len > (unsigned int) outbuf_len) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "first: out of space\n"); ret = -ENOBUFS; } else { /* Copy in the value. */ - memcpy(outbuf + ret, cvalue, len); - ret += len; + memcpy(outbuf + ret, val->bv_val, val->bv_len); + ret += val->bv_len; } } else { /* No such attribute. */ @@ -401,11 +551,11 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, char *outbuf, int outbuf_len, struct format_choice **outbuf_choices, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { - int ret, i, j, len, slen, count, argc; + int ret, i, j, slen, count, argc; Slapi_ValueSet *values; Slapi_Value *value; char **argv, *actual_attr; - const char *cvalue; + const struct berval *val; int disposition, buffer_flags; ret = format_parse_args(state, args, &argc, &argv); if (ret != 0) { @@ -424,10 +574,9 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, j != -1; j = slapi_valueset_next_value(values, j, &value)) { /* Get the length of the value. */ - cvalue = slapi_value_get_string(value); - len = strlen(cvalue); + val = slapi_value_get_berval(value); /* Check if we have space for the value. */ - if (ret + len > outbuf_len) { + 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"); @@ -437,7 +586,7 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return -ENOBUFS; } /* If the value is empty, skip it. */ - if (len == 0) { + if (val->bv_len == 0) { continue; } /* If we've already added values, add the separator. */ @@ -445,7 +594,8 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, /* Get the length of the separator. */ slen = strlen(argv[0]); /* Check if we have space for the separator. */ - if (ret + len + slen > outbuf_len) { + 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"); @@ -460,8 +610,8 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, ret += slen; } /* Copy in the value. */ - memcpy(outbuf + ret, cvalue, len); - ret += len; + memcpy(outbuf + ret, val->bv_val, val->bv_len); + ret += val->bv_len; count++; } /* Free the value set for this attribute. */ @@ -482,15 +632,17 @@ 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, len, slen, ret, count, argc; + int i, j, slen, ret, count, 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, *cvalue, *cref; - char *ref_attr, *target_attr, **choices; + const char *sep, *cref; + const struct berval *val; + char *ref_attr, *target_attr; + struct berval **choices; ret = format_parse_args(state, args, &argc, &argv); if (ret != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -587,10 +739,9 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, j != -1; j = slapi_valueset_next_value(values, j, &value)) { /* Get the length of the value. */ - cvalue = slapi_value_get_string(value); - len = strlen(cvalue); + val = slapi_value_get_berval(value); /* Check if there's space for the value. */ - if (ret + len > outbuf_len) { + 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"); @@ -605,13 +756,13 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return -ENOBUFS; } /* If the value is empty, skip it. */ - if (len == 0) { + 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) { - backend_shr_add_strlist(&choices, cvalue); + format_add_bv_list(&choices, val); continue; } /* If we need to, add the separator. */ @@ -619,7 +770,8 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, /* Get the length of the separator. */ slen = strlen(sep); /* Check if there's space for the separator. */ - if (ret + len + slen > outbuf_len) { + 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"); @@ -638,8 +790,8 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, ret += slen; } /* Append the value. */ - memcpy(outbuf + ret, cvalue, len); - ret += len; + memcpy(outbuf + ret, val->bv_val, val->bv_len); + ret += val->bv_len; count++; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); @@ -651,9 +803,24 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, format_free_parsed_args(argv); if (outbuf_choices != NULL) { if (choices != NULL) { - /* Return the values we found. */ - format_add_choice(outbuf_choices, outbuf, choices); - backend_shr_free_strlist(choices); + 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; @@ -672,7 +839,7 @@ struct format_referred_cbdata { char *outbuf; int outbuf_len; struct format_choice **outbuf_choices; - char **choices; + struct berval **choices; int count; int ret; }; @@ -683,7 +850,7 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) Slapi_Value *value; int i, disposition, buffer_flags, len, slen; char *actual_attr; - const char *cvalue; + const struct berval *val; struct format_referred_cbdata *cbdata; cbdata = callback_data; @@ -707,26 +874,21 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) i != -1; i = slapi_valueset_next_value(values, i, &value)) { /* Pull up the value. */ - cvalue = slapi_value_get_string(value); - if (cvalue == NULL) { - continue; - } - len = strlen(cvalue); - if (len == 0) { - continue; - } + val = slapi_value_get_berval(value); slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, - "referred: got value \"%s\"\n", cvalue); + "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) { - backend_shr_add_strlist(&cbdata->choices, cvalue); + format_add_bv_list(&cbdata->choices, val); continue; } /* Check if there's space for the value. */ slen = strlen(cbdata->separator); - if (len + (cbdata->count ? slen : 0) > cbdata->outbuf_len) { + 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"); @@ -741,12 +903,10 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data) memcpy(cbdata->outbuf, cbdata->separator, slen); } memcpy(cbdata->outbuf + (cbdata->count ? slen : 0), - cvalue, len); - cbdata->outbuf += (len + (cbdata->count ? slen : 0)); - cbdata->outbuf_len -= (len + (cbdata->count ? slen : 0)); - slapi_log_error(SLAPI_LOG_PLUGIN, - cbdata->state->plugin_desc->spd_id, - "referred: stored value \"%s\"\n", cvalue); + val->bv_val, val->bv_len); + len = val->bv_len + (cbdata->count ? slen : 0); + cbdata->outbuf += len; + cbdata->outbuf_len -= len; cbdata->count++; } slapi_vattr_values_free(&values, &actual_attr, buffer_flags); @@ -890,10 +1050,25 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, if (outbuf_choices != NULL) { if (cbdata.choices != NULL) { - /* Return the values we found. */ - format_add_choice(outbuf_choices, outbuf, - cbdata.choices); - backend_shr_free_strlist(cbdata.choices); + 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; @@ -1133,7 +1308,7 @@ format_match_generic(struct plugin_state *state, } else { /* Record the set of matching values as choices at this * location. */ - format_add_choice(outbuf_choices, outbuf, matches); + format_add_choice_str(outbuf_choices, outbuf, matches); len = 0; } break; @@ -1360,76 +1535,96 @@ format_lookup_fn(const char *fnname) return NULL; } +/* Check for the presence of any character in the disallowed list in the + * passed-in value. */ +static char * +format_check_disallowed(const struct berval *bv, const char *disallowed) +{ + int i; + char *p; + if (disallowed != NULL) { + for (i = 0; disallowed[i] != '\0'; i++) { + p = memchr(bv->bv_val, disallowed[i], bv->bv_len); + if (p != NULL) { + return p; + } + } + } + return NULL; +} /* Retrieve a single value for an attribute. If there are no values, or more * than one, return NULL. If there's more than one, store the values in the * array argument. */ -static char * +static struct berval format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, - const char *attr, const char *disallowed, char ***values) + const char *attr, const char *disallowed, + struct berval ***values) { Slapi_ValueSet *value_set; Slapi_Value *value; - char *ret, *actual_attr, **tmp_values; - const char *cret, *d; + char *ret, *actual_attr; + const char *d; + const struct berval *val; + struct berval bv; int count, disposition, buffer_flags, i, j; + memset(&bv, 0, sizeof(bv)); if (slapi_vattr_values_get(e, (char *) attr, &value_set, &disposition, &actual_attr, 0, &buffer_flags) != 0) { - return NULL; + return bv; } count = slapi_valueset_count(value_set); ret = NULL; if (count == 1) { if (slapi_valueset_first_value(value_set, &value) != -1) { - cret = slapi_value_get_string(value); - if (cret != NULL) { - if ((disallowed != NULL) && - ((d = strpbrk(cret, disallowed)) != NULL)) { - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "value for \"%s\" " - "contains disallowed " - "character \"%c\", " - "ignoring\n", - attr, *d); + val = slapi_value_get_berval(value); + d = format_check_disallowed(val, disallowed); + if (d != NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "value for \"%s\" " + "contains disallowed " + "character \"%c\", " + "ignoring\n", + attr, *d); + } else { + bv.bv_val = xmemdup(val->bv_val, val->bv_len); + if (bv.bv_val != NULL) { + bv.bv_len = val->bv_len; } else { - ret = strdup(cret); + bv.bv_len = 0; } } } } else { if ((count == 0) || (values == NULL)) { + /* Either no results, or too many results with no place + * to put them. */ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, "%d values for \"%s\"\n", count, attr); } else { /* Return the list of values. */ - tmp_values = malloc(sizeof(char *) * (count + 1)); - if (tmp_values != NULL) { - j = 0; + if (values != NULL) { for (i = slapi_valueset_first_value(value_set, &value); i != -1; i = slapi_valueset_next_value(value_set, i, - &value)) { - cret = slapi_value_get_string(value); - if ((disallowed == NULL) || - (strpbrk(cret, - disallowed) == NULL)) { - tmp_values[j++] = strdup(cret); + &value)) { + val = slapi_value_get_berval(value); + d = format_check_disallowed(val, + disallowed); + if (d == NULL) { + format_add_bv_list(values, val); } } - tmp_values[j] = NULL; - *values = backend_shr_dup_strlist(tmp_values); - for (i = 0; tmp_values[i] != NULL; i++) { - free(tmp_values[i]); - } - free(tmp_values); + } else { + bv.bv_len = -EINVAL; } } } slapi_vattr_values_free(&value_set, &actual_attr, buffer_flags); - return ret; + return bv; } /* Find the matching closing marker -- assumes that the first character in @@ -1486,32 +1681,41 @@ xstrndupp(const char *start, const char *end) /* Trim off prefixes or suffixes which match the given patterns, free the * original, and return the result. */ -static char * -format_trim_value(struct plugin_state *state, char *input, +static struct berval +format_trim_value(struct plugin_state *state, struct berval input, const char *shortstart, const char *longstart, const char *shortend, const char *longend, const char *replace, const char *replaceall, const char *replaceval) { - char *ret; - int i, j, k, len; - ret = strdup(input); - len = strlen(input); - if (ret != NULL) { + struct berval ret; + char *buf; + unsigned int i, len; + int j, k; + buf = xmemdup(input.bv_val, input.bv_len); + len = input.bv_len; + if (buf != NULL) { if (shortstart) { - /* The shortest initial substring which matches gets - * skipped. */ - for (i = 0; i <= len; i++) { - memcpy(ret, input, i); - ret[i] = '\0'; - if (fnmatch(shortstart, ret, 0) == 0) { - strcpy(ret, input + i); + /* The shortest initial subsection which matches gets + * trimmed off. */ + for (i = 0; i <= input.bv_len; i++) { + memcpy(buf, input.bv_val, i); + buf[i] = '\0'; + if (fnmatch(shortstart, buf, 0) == 0) { + memcpy(buf, input.bv_val + i, + input.bv_len - i); + buf[input.bv_len - i] = '\0'; + ret.bv_val = buf; + ret.bv_len = input.bv_len - i; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "trim-ss: ->%s<- => " - "->%s<-\n", - input, ret); - free(input); + "trim-ss: ->%.*s<- => " + "->%.*s<-\n", + input.bv_len, + input.bv_val, + ret.bv_len, + ret.bv_val); + free(input.bv_val); return ret; } } @@ -1519,17 +1723,26 @@ format_trim_value(struct plugin_state *state, char *input, if (shortend) { /* The shortest ending substring which matches gets * snipped. */ - for (i = 0; i <= len; i++) { - strcpy(ret, input + len - i); - if (fnmatch(shortend, ret, 0) == 0) { - strcpy(ret, input); - ret[len - i] = '\0'; + for (i = 0; i <= input.bv_len; i++) { + memcpy(buf, + input.bv_val + input.bv_len - i, + i); + buf[i] = '\0'; + if (fnmatch(shortend, buf, 0) == 0) { + memcpy(buf, input.bv_val, + input.bv_len - i); + buf[input.bv_len - i] = '\0'; + ret.bv_val = buf; + ret.bv_len = input.bv_len - i; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "trim-se: ->%s<- => " - "->%s<-\n", - input, ret); - free(input); + "trim-se: ->%.*s<- => " + "->%.*s<-\n", + input.bv_len, + input.bv_val, + ret.bv_len, + ret.bv_val); + free(input.bv_val); return ret; } } @@ -1538,16 +1751,23 @@ format_trim_value(struct plugin_state *state, char *input, /* The longest initial substring which matches gets * skipped. */ for (i = 0; i <= len; i++) { - memcpy(ret, input, (len - i)); - ret[len - i] = '\0'; - if (fnmatch(longstart, ret, 0) == 0) { - strcpy(ret, input + (len - i)); + memcpy(buf, input.bv_val, (input.bv_len - i)); + buf[input.bv_len - i] = '\0'; + if (fnmatch(longstart, buf, 0) == 0) { + memcpy(buf, input.bv_val + i, + input.bv_len - i); + buf[input.bv_len - i] = '\0'; + ret.bv_val = buf; + ret.bv_len = input.bv_len - i; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "trim-ls: ->%s<- => " - "->%s<-\n", - input, ret); - free(input); + "trim-ls: ->%.*s<- => " + "->%.*s<-\n", + input.bv_len, + input.bv_val, + ret.bv_len, + ret.bv_val); + free(input.bv_val); return ret; } } @@ -1556,16 +1776,23 @@ format_trim_value(struct plugin_state *state, char *input, /* The longest ending substring which matches gets * snipped. */ for (i = 0; i <= len; i++) { - strcpy(ret, input + i); - if (fnmatch(longend, ret, 0) == 0) { - strcpy(ret, input); - ret[i] = '\0'; + memcpy(buf, input.bv_val + i, input.bv_len - i); + buf[input.bv_len - i] = '\0'; + if (fnmatch(longend, buf, 0) == 0) { + memcpy(buf, input.bv_val, + input.bv_len - i); + buf[i] = '\0'; + ret.bv_val = buf; + ret.bv_len = input.bv_len - i; slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "trim-le: ->%s<- => " - "->%s<-\n", - input, ret); - free(input); + "trim-le: ->%.*s<- => " + "->%.*s<-\n", + input.bv_len, + input.bv_val, + ret.bv_len, + ret.bv_val); + free(input.bv_val); return ret; } } @@ -1574,65 +1801,12 @@ format_trim_value(struct plugin_state *state, char *input, replaceval = ""; } if (replace) { - /* Every occurrence of the substring which matches gets - * replaced, maybe. */ - free(ret); - ret = malloc(len + strlen(replaceval) + 1); - if (ret == NULL) { - return input; - } - for (i = 0, j = 0; - (i < len) && (replaceval != NULL); - i++, j++) { - strcpy(ret + j, input + i); - for (k = strlen(ret + j); k > 0; k--) { - ret[j + k] = '\0'; - if (fnmatch(replace, ret + j, 0) == 0) { - strcpy(ret + j, replaceval); - strcat(ret + j, input + i + k); - replaceval = NULL; - break; - } - } - } - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "trim-r: ->%s<- => ->%s<-\n", - input, ret); - free(input); - return ret; + /* FIXME */ } if (replaceall) { - /* Every occurrence of the substring which matches gets - * replaced with the replaceval. */ - free(ret); - ret = malloc(len * strlen(replaceval) + 1); - if (ret == NULL) { - return input; - } - for (i = 0, j = 0; - (i < len) && (replaceval != NULL); - i++, j++) { - strcpy(ret + j, input + i); - for (k = strlen(ret + j); k > 0; k--) { - ret[j + k] = '\0'; - if (fnmatch(replaceall, ret + j, - 0) == 0) { - strcpy(ret + j, replaceval); - j += (strlen(replaceval) - 1); - i += (k - 1); - break; - } - } - } - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "trim-r+: ->%s<- => ->%s<-\n", - input, ret); - free(input); - return ret; + /* FIXME */ } - free(ret); + free(buf); } return input; } @@ -1649,8 +1823,9 @@ format_expand_simple(struct plugin_state *state, struct format_choice **outbuf_choices, char ***ref_attrs, struct format_inref_attr ***inref_attrs) { - char *shortstart, *longstart, *shortend, *longend, **value_list; - char *replace, *replaceall, *replaceval, *tmp, *expr, *p; + char *shortstart, *longstart, *shortend, *longend; + struct berval tmp, **values; + char *replace, *replaceall, *replaceval, *expr, *p; const char *attribute, *default_value, *alternate_value; size_t spn; int i; @@ -1737,12 +1912,12 @@ format_expand_simple(struct plugin_state *state, } } /* Retrieve the value. */ - value_list = NULL; - tmp = format_single(state, pb, e, attribute, disallowed, &value_list); - if (tmp == NULL) { + values = NULL; + tmp = format_single(state, pb, e, attribute, disallowed, &values); + if (tmp.bv_val == NULL) { /* The attribute is undefined, or we're treating it as if it * is. */ - if (value_list == NULL) { + if (values == NULL) { if (default_value != NULL) { /* Supply the default value, expanding it if * needed. */ @@ -1760,22 +1935,37 @@ format_expand_simple(struct plugin_state *state, return -ENOENT; } } else { - /* Store nothing in the immediate position, but return - * a note that any of these values would be fine at - * this point in the output string. */ - format_add_choice(outbuf_choices, outbuf, value_list); - backend_shr_free_strlist(value_list); - return 0; + if (alternate_value != NULL) { + /* Supply the alternate value. */ + i = format_expand(state, pb, e, + group, set, + alternate_value, NULL, + outbuf, outbuf_len, + outbuf_choices, + ref_attrs, inref_attrs); + free(expr); + format_free_bv_list(values); + return i; + } else { + /* Store nothing in the immediate position, but + * return a note that any of these values would + * be fine at this point in the output string. + * */ + format_add_choice(outbuf_choices, + outbuf, values); + format_free_bv_list(values); + return 0; + } } } else { - /* There's a value defined. */ + /* There's a suitable single value available. */ if (alternate_value != NULL) { /* Supply the alternate value. */ i = format_expand(state, pb, e, group, set, alternate_value, NULL, outbuf, outbuf_len, outbuf_choices, ref_attrs, inref_attrs); - free(tmp); + free(tmp.bv_val); free(expr); return i; } else { @@ -1786,14 +1976,13 @@ format_expand_simple(struct plugin_state *state, replace, replaceall, replaceval); /* Supply the looked-up value. */ - if (tmp != NULL) { - i = strlen(tmp); - if (i <= outbuf_len) { - memcpy(outbuf, tmp, i); + if (tmp.bv_val != NULL) { + if (tmp.bv_len <= (unsigned int) outbuf_len) { + memcpy(outbuf, tmp.bv_val, tmp.bv_len); } - free(tmp); + free(tmp.bv_val); free(expr); - return i; + return tmp.bv_len; } else { /* No useful value: FAIL. */ free(expr); @@ -2038,7 +2227,8 @@ format_format(struct plugin_state *state, Slapi_Entry *e, const char *group, const char *set, const char *fmt, const char *disallowed, struct format_choice **choices, - char ***ref_attrs, struct format_inref_attr ***inref_attrs) + char ***ref_attrs, struct format_inref_attr ***inref_attrs, + unsigned int *data_length) { Slapi_PBlock *pb; char *buf, *ret, *spd_id; @@ -2066,7 +2256,8 @@ format_format(struct plugin_state *state, Slapi_Entry *e, ref_attrs, inref_attrs); if ((i >= 0) && (i < buflen)) { buf[i] = '\0'; - ret = strdup(buf); + ret = xmemdup(buf, i); + *data_length = i; format_retarget_choicesp(choices, buf, ret); } else { if (i == -ENOBUFS) { @@ -2122,14 +2313,17 @@ format_get_data(struct plugin_state *state, Slapi_Entry *e, const char *group, const char *set, const char *fmt, const char *disallowed, char ***ref_attrs, - struct format_inref_attr ***inref_attrs) + struct format_inref_attr ***inref_attrs, + unsigned int *data_length) { + unsigned int ignored; return format_format(state, e, group, set, fmt, disallowed, - NULL, ref_attrs, inref_attrs); + NULL, ref_attrs, inref_attrs, + data_length ? data_length : &ignored); } void -format_free_data_set(char **data) +format_free_data_set(char **data, unsigned int *data_lengths) { int i; if (data != NULL) { @@ -2138,20 +2332,25 @@ format_free_data_set(char **data) } free(data); } + free(data_lengths); } char ** format_get_data_set(struct plugin_state *state, Slapi_Entry *e, const char *group, const char *set, const char *fmt, const char *disallowed, char ***ref_attrs, - struct format_inref_attr ***inref_attrs) + struct format_inref_attr ***inref_attrs, + unsigned int **data_lengths) { struct format_choice *choices, *this_choice; + struct berval *val; char **ret, *template, *s; - int combinations, groupsize, i, j, k, offset, length, template_len; + int combinations, groupsize, i, j, k, offset, length; + unsigned int template_len; choices = NULL; template = format_format(state, e, group, set, fmt, disallowed, - &choices, ref_attrs, inref_attrs); + &choices, ref_attrs, inref_attrs, + &template_len); if (template == NULL) { format_free_choices(choices); return NULL; @@ -2164,8 +2363,8 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, for (i = 0; i < this_choice->n_values; i++) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "choice: \"%s\" %d\n", - this_choice->values[i], + "choice: %d at %d\n", + this_choice->values[i]->bv_len, this_choice->offset - template); } combinations *= this_choice->n_values; @@ -2174,9 +2373,9 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, format_free_choices(choices); return NULL; } - template_len = strlen(template); ret = malloc((combinations + 1) * sizeof(char *)); - if (ret != NULL) { + *data_lengths = malloc(sizeof(**data_lengths) * combinations); + if ((ret != NULL) && (*data_lengths != NULL)) { /* Work out all of the results. */ for (i = 0, j = 0; i < combinations; i++) { /* First figure out how long this result will be. */ @@ -2187,9 +2386,9 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, this_choice = this_choice->next) { /* Add the length of the value used here. */ groupsize /= this_choice->n_values; - s = this_choice->values[(i / groupsize) % - this_choice->n_values]; - length += strlen(s); + val = this_choice->values[(i / groupsize) % + this_choice->n_values]; + length += val->bv_len; } /* Allocate memory for this result. */ ret[j] = malloc(length + 1); @@ -2211,18 +2410,25 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e, k += length; offset += length; groupsize /= this_choice->n_values; - s = this_choice->values[(i / groupsize) % - this_choice->n_values]; - length = strlen(s); - memcpy(ret[j] + k, s, length); - k += length; + val = this_choice->values[(i / groupsize) % + this_choice->n_values]; + memcpy(ret[j] + k, val->bv_val, val->bv_len); + k += val->bv_len; } /* Copy any part of the template which trails the * choices. */ - strcpy(ret[j] + k, template + offset); + length = template_len - offset; + memcpy(ret[j] + k, template + offset, length); + ret[j][k + length] = '\0'; + (*data_lengths)[j] = k + length; j++; } ret[j] = NULL; + } else { + free(ret); + free(*data_lengths); + ret = NULL; + *data_lengths = NULL; } return ret; } diff --git a/src/format.h b/src/format.h index 3fcf8f9..b3faba9 100644 --- a/src/format.h +++ b/src/format.h @@ -37,15 +37,19 @@ struct format_inref_attr **format_dup_inref_attrs(struct format_inref_attr **); void format_free_data(char *data); char *format_get_data(struct plugin_state *state, struct slapi_entry *e, const char *domain, const char *map, - const char *fmt, const char *disallowed_chars, + const char *fmt, + const char *disallowed_chars, char ***ref_attrs, - struct format_inref_attr ***inref_attrs); -void format_free_data_set(char **data_set); + struct format_inref_attr ***inref_attrs, + unsigned int *data_length); +void format_free_data_set(char **data_set, unsigned int *data_lengths); char **format_get_data_set(struct plugin_state *state, Slapi_Entry *e, const char *domain, const char *map, - const char *fmt, const char *disallowed, + const char *fmt, + const char *disallowed, char ***ref_attrs, - struct format_inref_attr ***inref_attrs); + struct format_inref_attr ***inref_attrs, + unsigned int **data_lengths); char *format_escape_for_filter(const char *unescaped); #endif |