summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/format.c674
-rw-r--r--src/format.h14
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