summaryrefslogtreecommitdiffstats
path: root/src/format.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-26 17:19:26 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-26 17:19:26 -0400
commitcb5d7d97e85557873445d605681f94b1c01858ba (patch)
treeacd11d091baecaec46edb3ad9766b6d8ce2afef6 /src/format.c
parent8bdafe29900349b315bf37da112e1a3f6f680d34 (diff)
downloadslapi-nis-cb5d7d97e85557873445d605681f94b1c01858ba.tar.gz
slapi-nis-cb5d7d97e85557873445d605681f94b1c01858ba.tar.xz
slapi-nis-cb5d7d97e85557873445d605681f94b1c01858ba.zip
- dup_strlist: calculate string list sizes correctly when duplicating them
- expand: we don't need to support simple expressions directly any more - expand: stop using a scratch buffer for expansion - format: reset choice offset pointers when returning them - match_generic: clean up to free the valueset in one place rather than possibly four different places - match_generic: free the whole list of matches if we don't end up using it - single: return values correctly - xstrndup: terminate at the first nul - trim_value: drop support for '!' modifier - get_data_set: return the data we compute
Diffstat (limited to 'src/format.c')
-rw-r--r--src/format.c421
1 files changed, 223 insertions, 198 deletions
diff --git a/src/format.c b/src/format.c
index 7e980fc..d7e570c 100644
--- a/src/format.c
+++ b/src/format.c
@@ -50,9 +50,11 @@
#define MAX_BUFFER_SIZE 0x100000
struct format_choice {
char *offset;
+ int n_values;
char **values;
struct format_choice *next;
};
+
static int format_expand(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
@@ -60,8 +62,7 @@ static int format_expand(struct plugin_state *state,
char *outbuf, int outbuf_len,
struct format_choice **outbuf_choices,
char ***ref_attrs,
- struct format_inref_attr ***inref_attrs,
- bool_t is_simple_expression);
+ struct format_inref_attr ***inref_attrs);
char **
format_dup_attr_list(char **attr_list)
@@ -72,7 +73,7 @@ format_dup_attr_list(char **attr_list)
elements = 0;
if (*attr_list != NULL) {
for (i = 0; attr_list[i] != NULL; i++) {
- length += (strlen(attr_list[i] + 1));
+ length += (strlen(attr_list[i]) + 1);
}
elements = i;
}
@@ -108,7 +109,7 @@ format_add_attr_list(char ***attr_list, const char *value)
if (strcmp(value, (*attr_list)[i]) == 0) {
return;
}
- length += (strlen((*attr_list)[i] + 1));
+ length += (strlen((*attr_list)[i]) + 1);
elements++;
}
}
@@ -167,7 +168,8 @@ format_dup_inref_attrs(struct format_inref_attr **attrs)
ret[j]->map = strdup(attrs[i]->map);
ret[j]->attribute =
strdup(attrs[i]->attribute);
- if ((ret[j]->map != NULL) &&
+ if ((ret[j]->domain != NULL) &&
+ (ret[j]->map != NULL) &&
(ret[j]->attribute != NULL)) {
j++;
}
@@ -227,7 +229,21 @@ format_free_inref_attrs(struct format_inref_attr **attrs)
}
}
-/* Add a new entry to the "choice" list. */
+/* Maintain "choices" lists. */
+static void
+format_retarget_choicesp(struct format_choice **choices, char *oldt, char *newt)
+{
+ struct format_choice *this_choice;
+ int offset;
+ if (choices != NULL) {
+ for (this_choice = *choices;
+ this_choice != NULL;
+ this_choice = this_choice->next) {
+ offset = this_choice->offset - oldt;
+ this_choice->offset = newt + offset;
+ }
+ }
+}
static void
format_free_choices(struct format_choice *choices)
{
@@ -240,6 +256,14 @@ format_free_choices(struct format_choice *choices)
}
}
static void
+format_free_choicesp(struct format_choice **choices)
+{
+ if (choices) {
+ format_free_choices(*choices);
+ *choices = NULL;
+ }
+}
+static void
format_append_choice(struct format_choice **choices,
struct format_choice *choice)
{
@@ -254,18 +278,31 @@ format_append_choice(struct format_choice **choices,
while (here->next != NULL) {
here = here->next;
}
+ choice->next = here->next;
here->next = choice;
}
}
static void
format_add_choice(struct format_choice **choices, char *offset, char **values)
{
- struct format_choice *choice, *here;
- choice = malloc(sizeof(*choice));
- if (choice != NULL) {
- choice->offset = offset;
- choice->values = format_dup_strlist(values);
- format_append_choice(choices, choice);
+ struct format_choice *choice;
+ int i;
+ if (values != NULL) {
+ choice = malloc(sizeof(*choice));
+ if (choice != NULL) {
+ choice->offset = offset;
+ choice->values = format_dup_strlist(values);
+ choice->next = NULL;
+ 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);
+ }
+ }
}
}
@@ -652,7 +689,7 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
-/* Look up entries in the map named by the second argument, which have the
+/* 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. */
@@ -859,7 +896,7 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
backend_free_map_config(map_bases, map_filter);
slapi_pblock_destroy(local_pb);
format_free_parsed_args(argv);
- return cbdata.outbuf - outbuf;
+ return cbdata.ret ? cbdata.ret : cbdata.outbuf - outbuf;
}
/* Evaluate each argument, after the first, in turn, and merge them, using the
@@ -898,7 +935,7 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
outbuf + ret + (count ? slen : 0),
outbuf_len - (ret + (count ? slen : 0)),
&these_choices,
- ref_attrs, inref_attrs, FALSE);
+ ref_attrs, inref_attrs);
if (len < 0) {
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
@@ -1000,6 +1037,7 @@ format_match_generic(struct plugin_state *state,
}
matches[count] = NULL;
}
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
}
/* Make sure matched is either the single match, the default, or NULL
* if we had no default. */
@@ -1016,11 +1054,6 @@ format_match_generic(struct plugin_state *state,
if (len > outbuf_len) {
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
"%s: out of space\n", fnname);
- if (values != NULL) {
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- }
free(matches);
format_free_parsed_args(argv);
return -ENOBUFS;
@@ -1031,11 +1064,6 @@ format_match_generic(struct plugin_state *state,
"%s: no matching values for "
"\"%s\", and no default value\n",
fnname, argv[1]);
- if (values != NULL) {
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- }
free(matches);
format_free_parsed_args(argv);
return -ENOENT;
@@ -1047,11 +1075,6 @@ format_match_generic(struct plugin_state *state,
if (len > outbuf_len) {
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
"%s: out of space\n", fnname);
- if (values != NULL) {
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- }
free(matches[0]);
free(matches);
format_free_parsed_args(argv);
@@ -1075,10 +1098,8 @@ format_match_generic(struct plugin_state *state,
plugin_id,
"%s: out of space\n",
fnname);
- if (values != NULL) {
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
+ for (i = 0; i < count; i++) {
+ free(matches[i]);
}
free(matches);
format_free_parsed_args(argv);
@@ -1110,9 +1131,6 @@ format_match_generic(struct plugin_state *state,
}
break;
}
- if (values != NULL) {
- slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
- }
if (matches != NULL) {
for (i = 0; i < count; i++) {
free(matches[i]);
@@ -1336,7 +1354,8 @@ format_lookup_fn(const char *fnname)
}
/* Retrieve a single value for an attribute. If there are no values, or more
- * than one, fail. */
+ * than one, return NULL. If there's more than one, store the values in the
+ * array argument. */
static char *
format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *attr, const char *disallowed, char ***values)
@@ -1363,7 +1382,8 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
state->plugin_desc->spd_id,
"value for \"%s\" "
"contains disallowed "
- "character %c\n",
+ "character \"%c\", "
+ "ignoring\n",
attr, *d);
} else {
ret = strdup(cret);
@@ -1378,7 +1398,7 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
} else {
/* Return the list of values. */
tmp_values = malloc(sizeof(char *) * (count + 1));
- if (*values != NULL) {
+ if (tmp_values != NULL) {
j = 0;
for (i = slapi_valueset_first_value(value_set,
&value);
@@ -1386,7 +1406,11 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
i = slapi_valueset_next_value(value_set, i,
&value)) {
cret = slapi_value_get_string(value);
- tmp_values[j++] = strdup(cret);
+ if ((disallowed == NULL) ||
+ (strpbrk(cret,
+ disallowed) == NULL)) {
+ tmp_values[j++] = strdup(cret);
+ }
}
tmp_values[j] = NULL;
*values = format_dup_strlist(tmp_values);
@@ -1435,7 +1459,11 @@ format_find_closer(const char *pair, const char *pattern)
static char *
xstrndup(const char *start, size_t length)
{
- char *ret;
+ 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);
@@ -1446,14 +1474,7 @@ xstrndup(const char *start, size_t length)
static char *
xstrndupp(const char *start, const char *end)
{
- char *ret;
- size_t length = end - start;
- ret = malloc(length + 1);
- if (ret != NULL) {
- memcpy(ret, start, length);
- ret[length] = '\0';
- }
- return ret;
+ return xstrndup(start, end - start);
}
/* Trim off prefixes or suffixes which match the given patterns, free the
@@ -1463,33 +1484,13 @@ format_trim_value(struct plugin_state *state, char *input,
const char *shortstart, const char *longstart,
const char *shortend, const char *longend,
const char *replace, const char *replaceall,
- const char *replaceval, const char *forbidden)
+ const char *replaceval)
{
char *ret;
int i, j, k, len;
ret = strdup(input);
len = strlen(input);
if (ret != NULL) {
- if (forbidden) {
- /* Any forbidden character rejects this value. */
- if (strcspn(input, forbidden) != (size_t) len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "trim-f: value \"%s\" contains "
- "forbidden character '%c'\n",
- input,
- input + strcspn(input,
- forbidden));
- free(ret);
- free(input);
- return NULL;
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "trim-f: ->%s<- => ->%s<-\n",
- input, input);
- }
- }
if (shortstart) {
/* The shortest initial substring which matches gets
* skipped. */
@@ -1642,7 +1643,7 @@ format_expand_simple(struct plugin_state *state,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
char *shortstart, *longstart, *shortend, *longend, **value_list;
- char *replace, *replaceall, *replaceval, *forbidden, *tmp, *expr, *p;
+ char *replace, *replaceall, *replaceval, *tmp, *expr, *p;
const char *attribute, *default_value, *alternate_value;
size_t spn;
int i;
@@ -1653,7 +1654,6 @@ format_expand_simple(struct plugin_state *state,
replace = NULL;
replaceall = NULL;
replaceval = NULL;
- forbidden = NULL;
expr = strdup(fmt);
/* It's a simple expression, so evaluate it. Check for substitutions
* and text to be stripped if the magic character occurs before the
@@ -1679,9 +1679,6 @@ format_expand_simple(struct plugin_state *state,
else if (strncmp(p, "/", 1) == 0) {
replace = p + 1;
}
- else if (strncmp(p, "!", 1) == 0) {
- forbidden = p + 1;
- }
expr[spn] = '\0';
if ((replace != NULL) || (replaceall != NULL)) {
replaceval = NULL;
@@ -1747,8 +1744,7 @@ format_expand_simple(struct plugin_state *state,
default_value, NULL,
outbuf, outbuf_len,
outbuf_choices,
- ref_attrs, inref_attrs,
- FALSE);
+ ref_attrs, inref_attrs);
free(expr);
return i;
} else {
@@ -1771,7 +1767,7 @@ format_expand_simple(struct plugin_state *state,
i = format_expand(state, pb, e,
domain, map, alternate_value, NULL,
outbuf, outbuf_len, outbuf_choices,
- ref_attrs, inref_attrs, FALSE);
+ ref_attrs, inref_attrs);
free(tmp);
free(expr);
return i;
@@ -1781,7 +1777,7 @@ format_expand_simple(struct plugin_state *state,
shortstart, longstart,
shortend, longend,
replace, replaceall,
- replaceval, forbidden);
+ replaceval);
/* Supply the looked-up value. */
if (tmp != NULL) {
i = strlen(tmp);
@@ -1801,27 +1797,23 @@ format_expand_simple(struct plugin_state *state,
/* not reached */
}
-/* Recursively expand the expression into the output buffer. adding any entries
- * we visit (other than e) to the list of visited NDNs. If the result will
- * also be an expression, treat the entire result as an attribute specifier and
- * evaluate it, otherwise return it. */
+/* Recursively expand the expression into the output buffer. If the result
+ * will also be an expression, treat the entire result as an attribute
+ * specifier and evaluate it, otherwise return it. */
static int
format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *fmt, const char *disallowed,
char *outbuf, int outbuf_len,
struct format_choice **outbuf_choices,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs,
- bool_t is_simple_expression)
+ char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
- int i, j;
- int exp_used, exp_size, level;
- const char *fmtstart, *fmtend, *match, *attribute;
- char *tmp, *fnname, *spd_id, *p;
- char *expr;
+ int i, j, used;
+ const char *fmtstart, *fmtend, *match, *attribute, *pair;
+ char *subexp, *fnname, *params, *spd_id, *p;
const char *default_value, *alternate_value, *paramstart, *paramend;
char *shortstart, *longstart, *shortend, *longend;
- char *replace, *replaceall, *replaceval, *forbidden;
+ char *replace, *replaceall, *replaceval;
size_t spn;
int (*formatfn)(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
@@ -1833,19 +1825,11 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
struct format_inref_attr ***inref_attrs);
spd_id = state->plugin_desc->spd_id;
- exp_size = outbuf_len * 2;
- expr = malloc(exp_size);
- if (expr == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, spd_id,
- "expansion failed: out of memory\n");
- return -ENOMEM;
- }
/* Expand any subexpressions and call any "functions". */
- level = 0;
i = 0;
j = 0;
- while ((fmt[i] != '\0') && (j < exp_size)) {
+ while ((fmt[i] != '\0') && (j < outbuf_len)) {
switch (fmt[i]) {
case '%':
/* This might be a subexpression, a "function" call, or
@@ -1853,7 +1837,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
switch (fmt[i + 1]) {
case '%':
/* It's just an escaped "%". */
- expr[j++] = '%';
+ outbuf[j++] = '%';
i += 2;
continue;
break;
@@ -1868,67 +1852,64 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
spd_id,
"expansion failed: "
"no closing brace\n");
- free(expr);
return -EINVAL;
} else {
- /* Mark the first character after the
+ /* Track the first character after the
* simple expression. */
fmtend = match + 1;
/* Make a copy of the simple
* expression. */
- tmp = xstrndupp(fmtstart + 2,
- fmtend - 1);
- if (tmp == NULL) {
+ subexp = xstrndupp(fmtstart + 2,
+ fmtend - 1);
+ if (subexp == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
"expansion "
"failed: out "
"of memory\n");
- free(expr);
return -ENOMEM;
}
/* Expand the simple expression. */
- exp_used = format_expand_simple(state,
- pb, e,
- domain,
- map,
- tmp,
- disallowed,
- expr + j,
- exp_size - j,
- outbuf_choices,
- ref_attrs,
- inref_attrs);
- if (exp_used < 0) {
- /* Miscellaneous failure, FAIL.
- */
+ used = format_expand_simple(state,
+ pb, e,
+ domain,
+ map,
+ subexp,
+ disallowed,
+ outbuf + j,
+ outbuf_len - j,
+ outbuf_choices,
+ ref_attrs,
+ inref_attrs);
+ if (used < 0) {
+ /* Some failure, FAIL. */
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
"error "
"expanding "
"expression "
"->%s<-: %s\n",
- tmp,
- strerror(-exp_used));
- free(tmp);
- free(expr);
- return exp_used;
+ subexp,
+ strerror(-used));
+ free(subexp);
+ return used;
}
- free(tmp);
- if (exp_used + j >= exp_size) {
- /* Out of space, FAIL. */
+ free(subexp);
+ subexp = NULL;
+ if (used + j >= outbuf_len) {
+ /* Out of space, or would be,
+ * so return a failure. */
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
"expansion "
"failed: result"
" would be too "
"big\n");
- free(expr);
return -ENOBUFS;
} else {
/* It fit, so keep going. */
i = (match + 1) - fmt;
- j += exp_used;
+ j += used;
}
}
continue;
@@ -1936,7 +1917,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
default:
/* Assume it's a "function" call. Pick out the
* name of the function. */
- paramstart = strpbrk(fmt + i, "{(");
+ paramstart = strpbrk(fmt + i + 1, "{(");
if (paramstart == NULL) {
/* No start? Bad format. */
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -1944,16 +1925,14 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"expansion failed: "
"bad function "
"invocation\n");
- free(expr);
return -EINVAL;
}
if (*paramstart == '{') {
- paramend = format_find_closer("{}",
- paramstart);
+ pair = "{}";
} else {
- paramend = format_find_closer("()",
- paramstart);
+ pair = "()";
}
+ paramend = format_find_closer(pair, paramstart);
if (paramend == NULL) {
/* No matching end? Bad format. */
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -1961,7 +1940,6 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"expansion failed: "
"bad function "
"invocation\n");
- free(expr);
return -EINVAL;
}
fnname = xstrndupp(fmt + i + 1, paramstart);
@@ -1971,19 +1949,17 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
spd_id,
"expansion failed: "
"out of memory\n");
- free(expr);
return -ENOMEM;
}
- /* Isolate the parameter string. */
- tmp = xstrndupp(paramstart + 1, paramend);
- if (tmp == NULL) {
+ /* Pick out the parameter list. */
+ params = xstrndupp(paramstart + 1, paramend);
+ if (params == NULL) {
/* Out of memory, FAIL. */
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
"expansion failed: "
"out of memory\n");
free(fnname);
- free(expr);
return -ENOMEM;
}
/* Find the "function". */
@@ -1996,19 +1972,19 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"named \"%s\" is "
"defined\n", fnname);
free(fnname);
- free(tmp);
- free(expr);
+ free(params);
return -ENOSYS;
}
/* Call the "function". */
- exp_used = (*formatfn)(state, pb, e,
- domain, map,
- tmp, disallowed,
- expr + j, exp_size - j,
- outbuf_choices,
- ref_attrs, inref_attrs);
- free(tmp);
- if (exp_used < 0) {
+ used = (*formatfn)(state, pb, e,
+ domain, map,
+ params, disallowed,
+ outbuf + j, outbuf_len - j,
+ outbuf_choices,
+ ref_attrs, inref_attrs);
+ free(params);
+ params = NULL;
+ if (used < 0) {
/* Error in function, FAIL. */
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
@@ -2016,59 +1992,40 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"failed: function "
"'%s' failed: %s\n",
fnname,
- strerror(-exp_used));
+ strerror(-used));
free(fnname);
- free(expr);
- return exp_used;
+ return used;
}
free(fnname);
- if (exp_used + j >= exp_size) {
- /* We'd be out of space, FAIL. */
+ fnname = NULL;
+ if (used + j >= outbuf_len) {
+ /* We'd be out of space, fail. */
slapi_log_error(SLAPI_LOG_PLUGIN,
spd_id,
"expansion "
"failed: result"
" would be too "
"big\n");
- free(expr);
return -ENOBUFS;
}
i = (paramend - fmt) + 1;
- j += exp_used;
+ j += used;
continue;
break;
}
break;
default:
/* Default is just a literal character. */
- expr[j++] = fmt[i++];
+ outbuf[j++] = fmt[i++];
break;
}
}
- expr[j] = '\0';
+ outbuf[j] = '\0';
- if (is_simple_expression) {
- exp_used = format_expand_simple(state, pb, e, domain, map,
- expr, disallowed,
- outbuf, outbuf_len,
- outbuf_choices,
- ref_attrs, inref_attrs);
- if (exp_used < 0) {
- free(expr);
- return exp_used;
- } else {
- free(expr);
- return j + exp_used;
- }
+ if (j > outbuf_len) {
+ return -ENOBUFS;
} else {
- if (outbuf_len < j) {
- free(expr);
- return -ENOBUFS;
- } else {
- memcpy(outbuf, expr, j);
- free(expr);
- return j;
- }
+ return j;
}
}
@@ -2080,6 +2037,7 @@ format_format(struct plugin_state *state, Slapi_Entry *e,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
Slapi_PBlock *pb;
+ struct format_choice *this_choice;
char *buf, *tmp, *ret, *spd_id;
const char *match, *fmtstart, *fmtend;
int i, buflen, exp_len;
@@ -2100,12 +2058,14 @@ format_format(struct plugin_state *state, Slapi_Entry *e,
return NULL;
}
- i = format_expand(state, pb, e, domain, map, fmt, disallowed,
+ i = format_expand(state, pb, e, domain, map,
+ fmt, disallowed,
buf, buflen, choices,
- ref_attrs, inref_attrs, FALSE);
+ ref_attrs, inref_attrs);
if ((i >= 0) && (i < buflen)) {
buf[i] = '\0';
ret = strdup(buf);
+ format_retarget_choicesp(choices, buf, ret);
} else {
if (i == -ENOBUFS) {
if (buflen < MAX_BUFFER_SIZE) {
@@ -2137,10 +2097,7 @@ format_format(struct plugin_state *state, Slapi_Entry *e,
fmt, slapi_entry_get_ndn(e),
strerror(-i));
}
- if (choices != NULL) {
- format_free_choices(*choices);
- *choices = NULL;
- }
+ format_free_choicesp(choices);
ret = NULL;
}
free(buf);
@@ -2158,7 +2115,6 @@ format_free_data(char *data)
free(data);
}
}
-
char *
format_get_data(struct plugin_state *state, Slapi_Entry *e,
const char *domain, const char *map,
@@ -2173,8 +2129,14 @@ format_get_data(struct plugin_state *state, Slapi_Entry *e,
void
format_free_data_set(char **data)
{
+ int i;
+ if (data != NULL) {
+ for (i = 0; data[i] != NULL; i++) {
+ free(data[i]);
+ }
+ free(data);
+ }
}
-
char **
format_get_data_set(struct plugin_state *state, Slapi_Entry *e,
const char *domain, const char *map,
@@ -2182,18 +2144,81 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs)
{
- struct format_choice *choices;
- char **ret, *template;
+ struct format_choice *choices, *this_choice;
+ char **ret, *template, *s, *p, *q;
+ int combinations, group, nth, i, j, k, offset, length, template_len;
choices = NULL;
- return NULL;
-#if 0
template = format_format(state, e, domain, map, fmt, disallowed,
&choices, ref_attrs, inref_attrs);
if (template == NULL) {
+ format_free_choices(choices);
return NULL;
}
- return NULL;
-#endif
+ /* Figure out how many results we're going to have. */
+ combinations = 1;
+ for (this_choice = choices;
+ this_choice != NULL;
+ this_choice = this_choice->next) {
+ 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],
+ this_choice->offset - template);
+ }
+ combinations *= this_choice->n_values;
+ }
+ template_len = strlen(template);
+ ret = malloc((combinations + 1) * sizeof(char *));
+ if (ret != NULL) {
+ /* Work out all of the results. */
+ for (i = 0, j = 0; i < combinations; i++) {
+ /* First figure out how long this result will be. */
+ group = combinations;
+ length = template_len;
+ for (this_choice = choices;
+ this_choice != NULL;
+ this_choice = this_choice->next) {
+ /* Add the length of the value used here. */
+ group /= this_choice->n_values;
+ s = this_choice->values[(i / group) %
+ this_choice->n_values];
+ length += strlen(s);
+ }
+ /* Allocate memory for this result. */
+ ret[j] = malloc(length + 1);
+ if (ret[j] == NULL) {
+ continue;
+ }
+ /* Build the result's value. */
+ offset = 0;
+ k = 0;
+ group = combinations;
+ for (this_choice = choices;
+ this_choice != NULL;
+ this_choice = this_choice->next) {
+ /* Copy any part of the template that should be
+ * in the result by now. */
+ length = (this_choice->offset - template) -
+ offset;
+ memcpy(ret[j] + k, template + offset, length);
+ k += length;
+ offset += length;
+ group /= this_choice->n_values;
+ s = this_choice->values[(i / group) %
+ this_choice->n_values];
+ length = strlen(s);
+ memcpy(ret[j] + k, s, length);
+ k += length;
+ }
+ /* Copy any part of the template which trails the
+ * choices. */
+ strcpy(ret[j] + k, template + offset);
+ j++;
+ }
+ ret[j] = NULL;
+ }
+ return ret;
}
char *