diff options
Diffstat (limited to '')
-rw-r--r-- | src/util/dict_inline.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/util/dict_inline.c b/src/util/dict_inline.c new file mode 100644 index 0000000..72339b2 --- /dev/null +++ b/src/util/dict_inline.c @@ -0,0 +1,150 @@ +/*++ +/* NAME +/* dict_inline 3 +/* SUMMARY +/* dictionary manager interface for inline table +/* SYNOPSIS +/* #include <dict_inline.h> +/* +/* DICT *dict_inline_open(name, open_flags, dict_flags) +/* const char *name; +/* int open_flags; +/* int dict_flags; +/* DESCRIPTION +/* dict_inline_open() opens a read-only, in-memory table. +/* Example: "\fBinline:{\fIkey_1=value_1, ..., key_n=value_n\fR}". +/* The longer form with { key = value } allows values that +/* contain whitespace or comma. +/* SEE ALSO +/* dict(3) generic dictionary manager +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <string.h> + +/* Utility library. */ + +#include <msg.h> +#include <mymalloc.h> +#include <stringops.h> +#include <dict.h> +#include <dict_ht.h> +#include <dict_inline.h> + +/* Application-specific. */ + +/* dict_inline_open - open inline table */ + +DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) +{ + DICT *dict; + char *cp, *saved_name = 0; + size_t len; + char *nameval, *vname, *value; + const char *err = 0; + char *free_me = 0; + int count = 0; + + /* + * Clarity first. Let the optimizer worry about redundant code. + */ +#define DICT_INLINE_RETURN(x) do { \ + DICT *__d = (x); \ + if (saved_name != 0) \ + myfree(saved_name); \ + if (free_me != 0) \ + myfree(free_me); \ + return (__d); \ + } while (0) + + /* + * Sanity checks. + */ + if (open_flags != O_RDONLY) + DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, + open_flags, dict_flags, + "%s:%s map requires O_RDONLY access mode", + DICT_TYPE_INLINE, name)); + + /* + * UTF-8 syntax check. + */ + if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags) + && allascii(name) == 0 + && valid_utf8_string(name, strlen(name)) == 0) + DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, + open_flags, dict_flags, + "bad UTF-8 syntax: \"%s:%s\"; " + "need \"%s:{name=value...}\"", + DICT_TYPE_INLINE, name, + DICT_TYPE_INLINE)); + + /* + * Parse the table into its constituent name=value pairs. + */ + if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0 + || *(cp = saved_name = mystrndup(name + 1, len - 2)) == 0) + DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, + open_flags, dict_flags, + "bad syntax: \"%s:%s\"; " + "need \"%s:{name=value...}\"", + DICT_TYPE_INLINE, name, + DICT_TYPE_INLINE)); + + /* + * Reuse the "internal" dictionary type. + */ + dict = dict_open3(DICT_TYPE_HT, name, open_flags, dict_flags); + dict_type_override(dict, DICT_TYPE_INLINE); + while ((nameval = mystrtokq(&cp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { + if (nameval[0] == CHARS_BRACE[0]) + err = free_me = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP); + if (err != 0 || (err = split_qnameval(nameval, &vname, &value)) != 0) + break; + + if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) != 0) { + VSTRING *base64_buf; + + if ((base64_buf = dict_file_to_b64(dict, value)) == 0) { + err = free_me = dict_file_get_error(dict); + break; + } + value = vstring_str(base64_buf); + } + /* No duplicate checks. See comments in dict_thash.c. */ + dict->update(dict, vname, value); + count += 1; + } + if (err != 0 || count == 0) { + dict->close(dict); + DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, + open_flags, dict_flags, + "%s: \"%s:%s\"; " + "need \"%s:{name=%s...}\"", + err != 0 ? err : "empty table", + DICT_TYPE_INLINE, name, + DICT_TYPE_INLINE, + (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ? + "filename" : "value")); + } + dict->owner.status = DICT_OWNER_TRUSTED; + + dict_file_purge_buffers(dict); + DICT_INLINE_RETURN(DICT_DEBUG (dict)); +} |