mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
postfix-3.4-20181229
This commit is contained in:
committed by
Viktor Dukhovni
parent
b15570215e
commit
7c27c10eb2
@@ -23917,11 +23917,14 @@ Apologies for any names omitted.
|
|||||||
message to the postscreen_pre_queue_limit. Problem reported
|
message to the postscreen_pre_queue_limit. Problem reported
|
||||||
by Michael Orlitzky. File: proto/POSTSCREEN_README.html.
|
by Michael Orlitzky. File: proto/POSTSCREEN_README.html.
|
||||||
|
|
||||||
20181228
|
20181229
|
||||||
|
|
||||||
|
Explicit maps_file_find() and dict_file_lookup() methods
|
||||||
|
that decode base64 content. Decoding content is not built
|
||||||
|
into the dict->lookup() method, because that would complicate
|
||||||
|
the implementation of map nesting (inline, thash), map
|
||||||
|
composition (pipemap, unionmap), and map proxying. For
|
||||||
|
consistency, decoding base64 file content is also not built
|
||||||
|
into the maps_find() method. Files: util/dict.h.
|
||||||
|
util/dict_file.c, global/maps.[hc], postmap/postmap.c.
|
||||||
|
|
||||||
Cleanup: generic wrapper infrastructure for Postfix maps
|
|
||||||
(dictionaries) that is the basis for UTF8 checks and for
|
|
||||||
base64 decoding of lookup results. Files: global/mkmap_open.c,
|
|
||||||
postmap/postmap.c, util/dict.c, util/dict.h, util/dict_alloc.c,
|
|
||||||
util/dict_file.c, util/dict_open.c, util/dict_pipe.c,
|
|
||||||
util/dict_union.c, util/dict_utf8.c, util/dict_wrapper.c.
|
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
Wish list:
|
Wish list:
|
||||||
|
|
||||||
Add sequence support to dictionary wrappers, and remove
|
With DICT_FLAG_RHS_IS_FILE, should dict_update() open a
|
||||||
ad-hoc decoding from the postmap command. What about invalid
|
file? base64-encode the value?
|
||||||
base64? Warn and skip?
|
|
||||||
|
|
||||||
In smtpd(8) and postscreen(8), set the ehlo_discard_mask
|
In smtpd(8) and postscreen(8), set the ehlo_discard_mask
|
||||||
to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients
|
to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20181228"
|
#define MAIL_RELEASE_DATE "20181229"
|
||||||
#define MAIL_VERSION_NUMBER "3.4"
|
#define MAIL_VERSION_NUMBER "3.4"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@@ -16,6 +16,11 @@
|
|||||||
/* const char *key;
|
/* const char *key;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/*
|
/*
|
||||||
|
/* const char *maps_file_find(maps, key, flags)
|
||||||
|
/* MAPS *maps;
|
||||||
|
/* const char *key;
|
||||||
|
/* int flags;
|
||||||
|
/*
|
||||||
/* MAPS *maps_free(maps)
|
/* MAPS *maps_free(maps)
|
||||||
/* MAPS *maps;
|
/* MAPS *maps;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
@@ -39,6 +44,10 @@
|
|||||||
/* for example, DICT_FLAG_FIXED | DICT_FLAG_PATTERN selects
|
/* for example, DICT_FLAG_FIXED | DICT_FLAG_PATTERN selects
|
||||||
/* dictionaries that have fixed keys or pattern keys.
|
/* dictionaries that have fixed keys or pattern keys.
|
||||||
/*
|
/*
|
||||||
|
/* maps_file_find() implements maps_find() but also decodes
|
||||||
|
/* the base64 lookup result. This requires that the maps are
|
||||||
|
/* opened with DICT_FLAG_SRC_RHS_IS_FILE.
|
||||||
|
/*
|
||||||
/* maps_free() releases storage claimed by maps_create()
|
/* maps_free() releases storage claimed by maps_create()
|
||||||
/* and conveniently returns a null pointer.
|
/* and conveniently returns a null pointer.
|
||||||
/*
|
/*
|
||||||
@@ -189,15 +198,81 @@ const char *maps_find(MAPS *maps, const char *name, int flags)
|
|||||||
maps->title, name);
|
maps->title, name);
|
||||||
msg_warn("%s should return NO RESULT in case of NOT FOUND",
|
msg_warn("%s should return NO RESULT in case of NOT FOUND",
|
||||||
maps->title);
|
maps->title);
|
||||||
maps->error = DICT_ERR_RETRY;
|
maps->error = DICT_ERR_CONFIG;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s: %s: %s = %s", myname, maps->title,
|
msg_info("%s: %s: %s: %s = %.100s%s", myname, maps->title,
|
||||||
*map_name, name, expansion);
|
*map_name, name, expansion,
|
||||||
|
strlen(expansion) > 100 ? "..." : "");
|
||||||
return (expansion);
|
return (expansion);
|
||||||
} else if ((maps->error = dict->error) != 0) {
|
} else if ((maps->error = dict->error) != 0) {
|
||||||
msg_warn("%s:%s lookup error for \"%.100s\"",
|
msg_warn("%s:%s lookup error for \"%s\"",
|
||||||
|
dict->type, dict->name, name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s: %s: %s", myname, maps->title, name, maps->error ?
|
||||||
|
"search aborted" : "not found");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maps_file_find - search a list of dictionaries and base64 decode */
|
||||||
|
|
||||||
|
const char *maps_file_find(MAPS *maps, const char *name, int flags)
|
||||||
|
{
|
||||||
|
const char *myname = "maps_file_find";
|
||||||
|
char **map_name;
|
||||||
|
const char *expansion;
|
||||||
|
DICT *dict;
|
||||||
|
VSTRING *unb64;
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case of return without map lookup (empty name or no maps).
|
||||||
|
*/
|
||||||
|
maps->error = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Temp. workaround, for buggy callers that pass zero-length keys when
|
||||||
|
* given partial addresses.
|
||||||
|
*/
|
||||||
|
if (*name == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
for (map_name = maps->argv->argv; *map_name; map_name++) {
|
||||||
|
if ((dict = dict_handle(*map_name)) == 0)
|
||||||
|
msg_panic("%s: dictionary not found: %s", myname, *map_name);
|
||||||
|
if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) == 0)
|
||||||
|
msg_panic("%s: %s: opened without DICT_FLAG_SRC_RHS_IS_FILE",
|
||||||
|
myname, maps->title);
|
||||||
|
if (flags != 0 && (dict->flags & flags) == 0)
|
||||||
|
continue;
|
||||||
|
if ((expansion = dict_get(dict, name)) != 0) {
|
||||||
|
if (*expansion == 0) {
|
||||||
|
msg_warn("%s lookup of %s returns an empty string result",
|
||||||
|
maps->title, name);
|
||||||
|
msg_warn("%s should return NO RESULT in case of NOT FOUND",
|
||||||
|
maps->title);
|
||||||
|
maps->error = DICT_ERR_CONFIG;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: %s: %s: %s = %.100s%s", myname, maps->title,
|
||||||
|
*map_name, name, expansion,
|
||||||
|
strlen(expansion) > 100 ? "..." : "");
|
||||||
|
if ((unb64 = dict_file_from_b64(dict, expansion)) == 0) {
|
||||||
|
err = dict_file_get_error(dict);
|
||||||
|
msg_warn("table %s:%s: key %s: %s",
|
||||||
|
dict->type, dict->name, name, err);
|
||||||
|
myfree(err);
|
||||||
|
maps->error = DICT_ERR_CONFIG;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (vstring_str(unb64));
|
||||||
|
} else if ((maps->error = dict->error) != 0) {
|
||||||
|
msg_warn("%s:%s lookup error for \"%s\"",
|
||||||
dict->type, dict->name, name);
|
dict->type, dict->name, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ typedef struct MAPS {
|
|||||||
|
|
||||||
extern MAPS *maps_create(const char *, const char *, int);
|
extern MAPS *maps_create(const char *, const char *, int);
|
||||||
extern const char *maps_find(MAPS *, const char *, int);
|
extern const char *maps_find(MAPS *, const char *, int);
|
||||||
|
extern const char *maps_file_find(MAPS *, const char *, int);
|
||||||
extern MAPS *maps_free(MAPS *);
|
extern MAPS *maps_free(MAPS *);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@@ -301,12 +301,7 @@ MKMAP *mkmap_open(const char *type, const char *path,
|
|||||||
*/
|
*/
|
||||||
if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
|
if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
|
||||||
&& DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags))
|
&& DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags))
|
||||||
dict_utf8_wrapper_activate(mkmap->dict);
|
mkmap->dict = dict_utf8_activate(mkmap->dict);
|
||||||
|
|
||||||
/* Insert wrapper for base64 decoding file content. */
|
|
||||||
if ((mkmap->dict->flags & DICT_FLAG_UNB64_ACTIVE) == 0
|
|
||||||
&& (mkmap->dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) != 0)
|
|
||||||
dict_file_wrapper_activate(mkmap->dict);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resume signal delivery if multi-writer safe.
|
* Resume signal delivery if multi-writer safe.
|
||||||
|
@@ -11,4 +11,4 @@ file-2 this-is-file2
|
|||||||
this-is-file1
|
this-is-file1
|
||||||
this-is-file2
|
this-is-file2
|
||||||
postmap: warning: table hash:file_test_map.db: key entry-4: malformed BASE64 value: postmap-entry-4
|
postmap: warning: table hash:file_test_map.db: key entry-4: malformed BASE64 value: postmap-entry-4
|
||||||
postmap: fatal: table hash:file_test_map.db: query error: No such file or directory
|
postmap: fatal: table hash:file_test_map.db: query error
|
||||||
|
@@ -651,34 +651,30 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count,
|
|||||||
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
|
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
|
||||||
dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
|
dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
|
||||||
dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
|
dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
|
||||||
if ((value = dict_get(dicts[n], STR(keybuf))) != 0) {
|
value = ((dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ?
|
||||||
|
dict_file_lookup : dicts[n]->lookup)
|
||||||
|
(dicts[n], STR(keybuf));
|
||||||
|
if (value != 0) {
|
||||||
if (*value == 0) {
|
if (*value == 0) {
|
||||||
msg_warn("table %s:%s: key %s: empty string result is not allowed",
|
msg_warn("table %s:%s: key %s: empty string result is not allowed",
|
||||||
dicts[n]->type, dicts[n]->name, STR(keybuf));
|
dicts[n]->type, dicts[n]->name, STR(keybuf));
|
||||||
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
||||||
dicts[n]->type, dicts[n]->name);
|
dicts[n]->type, dicts[n]->name);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
|
|
||||||
VSTRING *unb64;
|
|
||||||
char *err;
|
|
||||||
|
|
||||||
if ((unb64 = dict_file_from_b64(dicts[n], value)) == 0) {
|
|
||||||
err = dict_file_get_error(dicts[n]);
|
|
||||||
msg_fatal("table %s:%s: key %s: %s",
|
|
||||||
dicts[n]->type, dicts[n]->name,
|
|
||||||
STR(keybuf), err);
|
|
||||||
}
|
|
||||||
value = STR(unb64);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
vstream_printf("%s %s\n", STR(keybuf), value);
|
vstream_printf("%s %s\n", STR(keybuf), value);
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dicts[n]->error)
|
switch (dicts[n]->error) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case DICT_ERR_CONFIG:
|
||||||
|
msg_fatal("table %s:%s: query error",
|
||||||
|
dicts[n]->type, dicts[n]->name);
|
||||||
|
default:
|
||||||
msg_fatal("table %s:%s: query error: %m",
|
msg_fatal("table %s:%s: query error: %m",
|
||||||
dicts[n]->type, dicts[n]->name);
|
dicts[n]->type, dicts[n]->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -752,31 +748,27 @@ static int postmap_query(const char *map_type, const char *map_name,
|
|||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
|
dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
|
||||||
if ((value = dict_get(dict, key)) != 0) {
|
value = ((dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ?
|
||||||
|
dict_file_lookup : dict->lookup) (dict, key);
|
||||||
|
if (value != 0) {
|
||||||
if (*value == 0) {
|
if (*value == 0) {
|
||||||
msg_warn("table %s:%s: key %s: empty string result is not allowed",
|
msg_warn("table %s:%s: key %s: empty string result is not allowed",
|
||||||
map_type, map_name, key);
|
map_type, map_name, key);
|
||||||
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
||||||
map_type, map_name);
|
map_type, map_name);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
|
|
||||||
VSTRING *unb64;
|
|
||||||
char *err;
|
|
||||||
|
|
||||||
if ((unb64 = dict_file_from_b64(dict, value)) == 0) {
|
|
||||||
err = dict_file_get_error(dict);
|
|
||||||
msg_fatal("table %s:%s: key %s: %s",
|
|
||||||
dict->type, dict->name,
|
|
||||||
key, err);
|
|
||||||
}
|
|
||||||
value = STR(unb64);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
vstream_printf("%s\n", value);
|
vstream_printf("%s\n", value);
|
||||||
}
|
}
|
||||||
if (dict->error)
|
switch (dict->error) {
|
||||||
msg_fatal("table %s:%s: query error: %m", dict->type, dict->name);
|
case 0:
|
||||||
|
break;
|
||||||
|
case DICT_ERR_CONFIG:
|
||||||
|
msg_fatal("table %s:%s: query error",
|
||||||
|
dict->type, dict->name);
|
||||||
|
default:
|
||||||
|
msg_fatal("table %s:%s: query error: %m",
|
||||||
|
dict->type, dict->name);
|
||||||
|
}
|
||||||
vstream_fflush(VSTREAM_OUT);
|
vstream_fflush(VSTREAM_OUT);
|
||||||
dict_close(dict);
|
dict_close(dict);
|
||||||
return (value != 0);
|
return (value != 0);
|
||||||
@@ -885,7 +877,6 @@ static void postmap_seq(const char *map_type, const char *map_name,
|
|||||||
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
|
||||||
map_type, map_name);
|
map_type, map_name);
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
|
if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
|
||||||
VSTRING *unb64;
|
VSTRING *unb64;
|
||||||
char *err;
|
char *err;
|
||||||
@@ -900,7 +891,6 @@ static void postmap_seq(const char *map_type, const char *map_name,
|
|||||||
}
|
}
|
||||||
value = STR(unb64);
|
value = STR(unb64);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
vstream_printf("%s %s\n", key, value);
|
vstream_printf("%s %s\n", key, value);
|
||||||
}
|
}
|
||||||
if (dict->error)
|
if (dict->error)
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
/* #include "smtpd.h"
|
/* #include "smtpd.h"
|
||||||
/* #include "smtpd_sasl_proto.h"
|
/* #include "smtpd_sasl_proto.h"
|
||||||
/*
|
/*
|
||||||
/* void smtpd_sasl_auth_cmd(state, argc, argv)
|
/* int smtpd_sasl_auth_cmd(state, argc, argv)
|
||||||
/* SMTPD_STATE *state;
|
/* SMTPD_STATE *state;
|
||||||
/* int argc;
|
/* int argc;
|
||||||
/* SMTPD_TOKEN *argv;
|
/* SMTPD_TOKEN *argv;
|
||||||
|
@@ -40,8 +40,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
|
|||||||
poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \
|
poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \
|
||||||
valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \
|
valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \
|
||||||
extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \
|
extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \
|
||||||
split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c \
|
split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c
|
||||||
dict_wrapper.c
|
|
||||||
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
||||||
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
|
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
|
||||||
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
|
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
|
||||||
@@ -83,8 +82,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
|
|||||||
poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \
|
poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \
|
||||||
valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \
|
valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \
|
||||||
extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \
|
extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \
|
||||||
split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o \
|
split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o
|
||||||
dict_wrapper.o
|
|
||||||
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
|
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
|
||||||
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
|
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
|
||||||
# otherwise it sets the PLUGIN_* macros.
|
# otherwise it sets the PLUGIN_* macros.
|
||||||
@@ -1342,6 +1340,7 @@ dict_ht.o: sys_defs.h
|
|||||||
dict_ht.o: vbuf.h
|
dict_ht.o: vbuf.h
|
||||||
dict_ht.o: vstream.h
|
dict_ht.o: vstream.h
|
||||||
dict_ht.o: vstring.h
|
dict_ht.o: vstring.h
|
||||||
|
dict_inline.cdict_static.o: dict_inline.cdict_static.c
|
||||||
dict_inline.o: argv.h
|
dict_inline.o: argv.h
|
||||||
dict_inline.o: check_arg.h
|
dict_inline.o: check_arg.h
|
||||||
dict_inline.o: dict.h
|
dict_inline.o: dict.h
|
||||||
@@ -1648,18 +1647,6 @@ dict_utf8.o: sys_defs.h
|
|||||||
dict_utf8.o: vbuf.h
|
dict_utf8.o: vbuf.h
|
||||||
dict_utf8.o: vstream.h
|
dict_utf8.o: vstream.h
|
||||||
dict_utf8.o: vstring.h
|
dict_utf8.o: vstring.h
|
||||||
dict_wrapper.o: argv.h
|
|
||||||
dict_wrapper.o: check_arg.h
|
|
||||||
dict_wrapper.o: dict.h
|
|
||||||
dict_wrapper.o: dict_wrapper.c
|
|
||||||
dict_wrapper.o: msg.h
|
|
||||||
dict_wrapper.o: myflock.h
|
|
||||||
dict_wrapper.o: mymalloc.h
|
|
||||||
dict_wrapper.o: stringops.h
|
|
||||||
dict_wrapper.o: sys_defs.h
|
|
||||||
dict_wrapper.o: vbuf.h
|
|
||||||
dict_wrapper.o: vstream.h
|
|
||||||
dict_wrapper.o: vstring.h
|
|
||||||
dir_forest.o: check_arg.h
|
dir_forest.o: check_arg.h
|
||||||
dir_forest.o: dir_forest.c
|
dir_forest.o: dir_forest.c
|
||||||
dir_forest.o: dir_forest.h
|
dir_forest.o: dir_forest.h
|
||||||
@@ -1917,6 +1904,8 @@ load_file.o: vbuf.h
|
|||||||
load_file.o: vstream.h
|
load_file.o: vstream.h
|
||||||
load_file.o: warn_stat.h
|
load_file.o: warn_stat.h
|
||||||
load_lib.o: load_lib.c
|
load_lib.o: load_lib.c
|
||||||
|
load_lib.o: load_lib.h
|
||||||
|
load_lib.o: msg.h
|
||||||
load_lib.o: sys_defs.h
|
load_lib.o: sys_defs.h
|
||||||
lowercase.o: check_arg.h
|
lowercase.o: check_arg.h
|
||||||
lowercase.o: lowercase.c
|
lowercase.o: lowercase.c
|
||||||
|
@@ -640,7 +640,6 @@ static const NAME_MASK dict_mask[] = {
|
|||||||
"utf8_request", DICT_FLAG_UTF8_REQUEST, /* request UTF-8 activation */
|
"utf8_request", DICT_FLAG_UTF8_REQUEST, /* request UTF-8 activation */
|
||||||
"utf8_active", DICT_FLAG_UTF8_ACTIVE, /* UTF-8 is activated */
|
"utf8_active", DICT_FLAG_UTF8_ACTIVE, /* UTF-8 is activated */
|
||||||
"src_rhs_is_file", DICT_FLAG_SRC_RHS_IS_FILE, /* value from file */
|
"src_rhs_is_file", DICT_FLAG_SRC_RHS_IS_FILE, /* value from file */
|
||||||
"unb64_active", DICT_FLAG_UNB64_ACTIVE, /* base64 decode activated */
|
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -93,7 +93,7 @@ typedef struct DICT {
|
|||||||
DICT_OWNER owner; /* provenance */
|
DICT_OWNER owner; /* provenance */
|
||||||
int error; /* last operation only */
|
int error; /* last operation only */
|
||||||
DICT_JMP_BUF *jbuf; /* exception handling */
|
DICT_JMP_BUF *jbuf; /* exception handling */
|
||||||
struct DICT_WRAPPER *wrapper; /* see below */
|
struct DICT_UTF8_BACKUP *utf8_backup; /* see below */
|
||||||
struct VSTRING *file_buf; /* dict_file_to_buf() */
|
struct VSTRING *file_buf; /* dict_file_to_buf() */
|
||||||
struct VSTRING *file_b64; /* dict_file_to_b64() */
|
struct VSTRING *file_b64; /* dict_file_to_b64() */
|
||||||
} DICT;
|
} DICT;
|
||||||
@@ -133,7 +133,6 @@ extern DICT *dict_debug(DICT *);
|
|||||||
#define DICT_FLAG_UTF8_ACTIVE (1<<20) /* UTF-8 proxy layer is present */
|
#define DICT_FLAG_UTF8_ACTIVE (1<<20) /* UTF-8 proxy layer is present */
|
||||||
#define DICT_FLAG_SRC_RHS_IS_FILE \
|
#define DICT_FLAG_SRC_RHS_IS_FILE \
|
||||||
(1<<21) /* Map source RHS is a file */
|
(1<<21) /* Map source RHS is a file */
|
||||||
#define DICT_FLAG_UNB64_ACTIVE (1<<22) /* File decode proxy layer is present */
|
|
||||||
|
|
||||||
#define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST)
|
#define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST)
|
||||||
|
|
||||||
@@ -252,29 +251,15 @@ extern int dict_flags_mask(const char *);
|
|||||||
extern void dict_type_override(DICT *, const char *);
|
extern void dict_type_override(DICT *, const char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrappers for DICT methods. Usage: create an "trivial" wrapper object with
|
* Check and convert UTF-8 keys and values.
|
||||||
* dict_wrapper_alloc(), then for each method that requires special
|
|
||||||
* processing, specify a pointer to function that calls the 'next' wrapper's
|
|
||||||
* method of the same type, with the 'next' wrapper as the first argument
|
|
||||||
* (the 'self' pointer).
|
|
||||||
*/
|
*/
|
||||||
typedef struct DICT_WRAPPER {
|
typedef struct DICT_UTF8_BACKUP {
|
||||||
const char *name; /* for literal constant */
|
const char *(*lookup) (struct DICT *, const char *);
|
||||||
const char *(*lookup) (struct DICT_WRAPPER *, DICT *, const char *);
|
int (*update) (struct DICT *, const char *, const char *);
|
||||||
int (*update) (struct DICT_WRAPPER *, DICT *, const char *, const char *);
|
int (*delete) (struct DICT *, const char *);
|
||||||
int (*delete) (struct DICT_WRAPPER *, DICT *, const char *);
|
} DICT_UTF8_BACKUP;
|
||||||
struct DICT_WRAPPER *next;
|
|
||||||
} DICT_WRAPPER;
|
|
||||||
|
|
||||||
extern void dict_wrapper_prepend(DICT *, DICT_WRAPPER *);
|
extern DICT *dict_utf8_activate(DICT *);
|
||||||
extern DICT_WRAPPER *dict_wrapper_alloc(ssize_t);
|
|
||||||
extern void dict_wrapper_free(DICT_WRAPPER *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Things that build on DICT_WRAPPER.
|
|
||||||
*/
|
|
||||||
extern void dict_utf8_wrapper_activate(DICT *);
|
|
||||||
extern void dict_file_wrapper_activate(DICT *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Driver for interactive or scripted tests.
|
* Driver for interactive or scripted tests.
|
||||||
@@ -327,6 +312,7 @@ extern struct VSTRING *dict_file_to_b64(DICT *, const char *);
|
|||||||
extern struct VSTRING *dict_file_from_b64(DICT *, const char *);
|
extern struct VSTRING *dict_file_from_b64(DICT *, const char *);
|
||||||
extern char *dict_file_get_error(DICT *);
|
extern char *dict_file_get_error(DICT *);
|
||||||
extern void dict_file_purge_buffers(DICT *);
|
extern void dict_file_purge_buffers(DICT *);
|
||||||
|
extern const char *dict_file_lookup(DICT *dict, const char *);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@@ -159,7 +159,7 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
|
|||||||
dict->owner.uid = INT_MAX;
|
dict->owner.uid = INT_MAX;
|
||||||
dict->error = DICT_ERR_NONE;
|
dict->error = DICT_ERR_NONE;
|
||||||
dict->jbuf = 0;
|
dict->jbuf = 0;
|
||||||
dict->wrapper = 0;
|
dict->utf8_backup = 0;
|
||||||
dict->file_buf = 0;
|
dict->file_buf = 0;
|
||||||
dict->file_b64 = 0;
|
dict->file_b64 = 0;
|
||||||
return dict;
|
return dict;
|
||||||
@@ -173,8 +173,8 @@ void dict_free(DICT *dict)
|
|||||||
myfree(dict->name);
|
myfree(dict->name);
|
||||||
if (dict->jbuf)
|
if (dict->jbuf)
|
||||||
myfree((void *) dict->jbuf);
|
myfree((void *) dict->jbuf);
|
||||||
if (dict->wrapper)
|
if (dict->utf8_backup)
|
||||||
dict_wrapper_free(dict->wrapper);
|
myfree((void *) dict->utf8_backup);
|
||||||
if (dict->file_buf)
|
if (dict->file_buf)
|
||||||
vstring_free(dict->file_buf);
|
vstring_free(dict->file_buf);
|
||||||
if (dict->file_b64)
|
if (dict->file_b64)
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
./dict_open: warning: cidr map dict_cidr_file.map, line 3: open dict_cidr_file3: No such file or directory: skipping this rule
|
./dict_open: warning: cidr map dict_cidr_file.map, line 3: open dict_cidr_file3: No such file or directory: skipping this rule
|
||||||
owner=untrusted (uid=USER)
|
owner=untrusted (uid=USER)
|
||||||
> get 1.1.1.1
|
> get 1.1.1.1
|
||||||
1.1.1.1=this-is-file1
|
1.1.1.1=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get 2.2.2.2
|
> get 2.2.2.2
|
||||||
2.2.2.2=this-is-file2
|
2.2.2.2=dGhpcy1pcy1maWxlMgo=
|
||||||
|
|
||||||
> get 3.3.3.3
|
> get 3.3.3.3
|
||||||
3.3.3.3: not found
|
3.3.3.3: not found
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
/* void dict_file_purge_buffers(
|
/* void dict_file_purge_buffers(
|
||||||
/* DICT *dict)
|
/* DICT *dict)
|
||||||
/*
|
/*
|
||||||
/* void dict_file_wrapper_activate(
|
/* const char *dict_file_lookup(
|
||||||
/* DICT *dict)
|
/* DICT *dict)
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* dict_file_to_buf() reads the content of the specified files,
|
/* dict_file_to_buf() reads the content of the specified files,
|
||||||
@@ -48,10 +48,17 @@
|
|||||||
/* it returns a desciption of the problem. Storage is owned
|
/* it returns a desciption of the problem. Storage is owned
|
||||||
/* by the caller.
|
/* by the caller.
|
||||||
/*
|
/*
|
||||||
/* dict_file_wrapper_activate() activates a wrapper that
|
/* dict_file_lookup() wraps the dictionary lookup method and
|
||||||
/* automatically base64-decodes lookup results.
|
/* decodes the base64 lookup result. The dictionary must be
|
||||||
|
/* opened with DICT_FLAG_SRC_RHS_IS_FILE. Sets dict->error to
|
||||||
|
/* DICT_ERR_CONFIG if the content is invalid. Decoding is not
|
||||||
|
/* built into the dict->lookup() method, because that would
|
||||||
|
/* complicate the implementation of map nesting (inline, thash),
|
||||||
|
/* map composition (pipemap, unionmap), and map proxying.
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* In case of error the result value is a null pointer, and
|
/* Panic: interface violation.
|
||||||
|
/*
|
||||||
|
/* In case of error the VSTRING result value is a null pointer, and
|
||||||
/* an error description can be retrieved with dict_file_get_error().
|
/* an error description can be retrieved with dict_file_get_error().
|
||||||
/* The storage is owned by the caller.
|
/* The storage is owned by the caller.
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
@@ -199,56 +206,28 @@ void dict_file_purge_buffers(DICT *dict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dict_file_wrapper_lookup - wrap the lookup method */
|
/* dict_file_lookup - look up and decode dictionary entry */
|
||||||
|
|
||||||
static const char *dict_file_wrapper_lookup(DICT_WRAPPER *wrapper,
|
const char *dict_file_lookup(DICT *dict, const char *key)
|
||||||
DICT *dict, const char *key)
|
|
||||||
{
|
{
|
||||||
DICT_WRAPPER *next_wrapper;
|
const char myname[] = "dict_file_lookup";
|
||||||
const char *res;
|
const char *res;
|
||||||
VSTRING *unb64;
|
VSTRING *unb64;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
next_wrapper = wrapper->next;
|
if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) == 0)
|
||||||
if ((res = next_wrapper->lookup(next_wrapper, dict, key)) != 0) {
|
msg_panic("%s: dictionary opened without DICT_FLAG_SRC_RHS_IS_FILE",
|
||||||
if ((unb64 = dict_file_from_b64(dict, res)) == 0) {
|
myname);
|
||||||
err = dict_file_get_error(dict);
|
if ((res = dict->lookup(dict, key)) == 0)
|
||||||
msg_warn("table %s:%s: key %s: %s",
|
return (0);
|
||||||
dict->type, dict->name, key, err);
|
if ((unb64 = dict_file_from_b64(dict, res)) == 0) {
|
||||||
myfree(err);
|
err = dict_file_get_error(dict);
|
||||||
dict->error = DICT_ERR_CONFIG;
|
msg_warn("table %s:%s: key %s: %s",
|
||||||
res = 0;
|
dict->type, dict->name,
|
||||||
} else {
|
key, err);
|
||||||
res = vstring_str(unb64);
|
myfree(err);
|
||||||
}
|
dict->error = DICT_ERR_CONFIG;
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
return (res);
|
return STR(unb64);
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_file_wrapper_activate - wrap the lookup method */
|
|
||||||
|
|
||||||
void dict_file_wrapper_activate(DICT *dict)
|
|
||||||
{
|
|
||||||
const char myname[] = "dict_file_wrapper_activate";
|
|
||||||
DICT_WRAPPER *wrapper;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanity check.
|
|
||||||
*/
|
|
||||||
if ((dict->flags & DICT_FLAG_UNB64_ACTIVE))
|
|
||||||
msg_panic("%s: %s:%s Base64 decoding support is already activated",
|
|
||||||
myname, dict->type, dict->name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interpose on the lookup method.
|
|
||||||
*/
|
|
||||||
wrapper = dict_wrapper_alloc(sizeof(*wrapper));
|
|
||||||
wrapper->name = "file";
|
|
||||||
wrapper->lookup = dict_file_wrapper_lookup;
|
|
||||||
dict_wrapper_prepend(dict, wrapper);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Leave our mark. See sanity check above.
|
|
||||||
*/
|
|
||||||
dict->flags |= DICT_FLAG_UNB64_ACTIVE;
|
|
||||||
}
|
}
|
||||||
|
@@ -5,10 +5,8 @@ owner=trusted (uid=2147483647)
|
|||||||
foo: error
|
foo: error
|
||||||
owner=trusted (uid=2147483647)
|
owner=trusted (uid=2147483647)
|
||||||
> get file1
|
> get file1
|
||||||
file1=this-is-file1
|
file1=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get file2
|
> get file2
|
||||||
file2=this-is-file2
|
file2=dGhpcy1pcy1maWxlMgo=
|
||||||
|
|
||||||
> get file3
|
> get file3
|
||||||
file3: not found
|
file3: not found
|
||||||
|
@@ -479,16 +479,10 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
|
|||||||
msg_fatal("%s:%s: unable to get exclusive lock: %m",
|
msg_fatal("%s:%s: unable to get exclusive lock: %m",
|
||||||
dict_type, dict_name);
|
dict_type, dict_name);
|
||||||
}
|
}
|
||||||
/* Insert wrapper for UTF-8 syntax checks and casefolding. */
|
/* Last step: insert proxy for UTF-8 syntax checks and casefolding. */
|
||||||
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
|
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
|
||||||
&& DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags))
|
&& DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags))
|
||||||
dict_utf8_wrapper_activate(dict);
|
dict = dict_utf8_activate(dict);
|
||||||
|
|
||||||
/* Insert wrapper for base64 decoding file content. */
|
|
||||||
if ((dict->flags & DICT_FLAG_UNB64_ACTIVE) == 0
|
|
||||||
&& dict->flags & DICT_FLAG_SRC_RHS_IS_FILE)
|
|
||||||
dict_file_wrapper_activate(dict);
|
|
||||||
|
|
||||||
return (dict);
|
return (dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,15 +3,10 @@
|
|||||||
./dict_open: warning: pcre map dict_pcre_file.map, line 6: empty pathname list: >>,<<': skipping this rule
|
./dict_open: warning: pcre map dict_pcre_file.map, line 6: empty pathname list: >>,<<': skipping this rule
|
||||||
owner=untrusted (uid=USER)
|
owner=untrusted (uid=USER)
|
||||||
> get file1
|
> get file1
|
||||||
file1=this-is-file1
|
file1=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get file2
|
> get file2
|
||||||
file2=this-is-file2
|
file2=dGhpcy1pcy1maWxlMgo=
|
||||||
|
|
||||||
> get file3
|
> get file3
|
||||||
file3: not found
|
file3: not found
|
||||||
> get files12
|
> get files12
|
||||||
files12=this-is-file1
|
files12=dGhpcy1pcy1maWxlMQoKdGhpcy1pcy1maWxlMgo=
|
||||||
|
|
||||||
this-is-file2
|
|
||||||
|
|
||||||
|
@@ -166,8 +166,7 @@ DICT *dict_pipe_open(const char *name, int open_flags, int dict_flags)
|
|||||||
DICT_TYPE_PIPE, name,
|
DICT_TYPE_PIPE, name,
|
||||||
DICT_TYPE_PIPE));
|
DICT_TYPE_PIPE));
|
||||||
if ((dict = dict_handle(dict_type_name)) == 0)
|
if ((dict = dict_handle(dict_type_name)) == 0)
|
||||||
dict = dict_open(dict_type_name, open_flags,
|
dict = dict_open(dict_type_name, open_flags, dict_flags);
|
||||||
dict_flags & ~DICT_FLAG_SRC_RHS_IS_FILE);
|
|
||||||
dict_register(dict_type_name, dict);
|
dict_register(dict_type_name, dict);
|
||||||
DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
|
DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
|
||||||
if (cpp == argv->argv)
|
if (cpp == argv->argv)
|
||||||
|
@@ -5,8 +5,6 @@ owner=trusted (uid=2147483647)
|
|||||||
foo: error
|
foo: error
|
||||||
owner=trusted (uid=0)
|
owner=trusted (uid=0)
|
||||||
> get foo
|
> get foo
|
||||||
foo=this-is-file1
|
foo=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get bar
|
> get bar
|
||||||
bar=this-is-file1
|
bar=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
./dict_open: warning: regexp map dict_regexp_file.map, line 3: open dict_regexp_file3: No such file or directory: skipping this rule
|
./dict_open: warning: regexp map dict_regexp_file.map, line 3: open dict_regexp_file3: No such file or directory: skipping this rule
|
||||||
owner=untrusted (uid=USER)
|
owner=untrusted (uid=USER)
|
||||||
> get file1
|
> get file1
|
||||||
file1=this-is-file1
|
file1=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get file2
|
> get file2
|
||||||
file2=this-is-file2
|
file2=dGhpcy1pcy1maWxlMgo=
|
||||||
|
|
||||||
> get file3
|
> get file3
|
||||||
file3: not found
|
file3: not found
|
||||||
|
@@ -5,8 +5,6 @@ owner=trusted (uid=2147483647)
|
|||||||
foo: error
|
foo: error
|
||||||
owner=trusted (uid=2147483647)
|
owner=trusted (uid=2147483647)
|
||||||
> get file1
|
> get file1
|
||||||
file1=this-is-file1
|
file1=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
> get file2
|
> get file2
|
||||||
file2=this-is-file1
|
file2=dGhpcy1pcy1maWxlMQo=
|
||||||
|
|
||||||
|
@@ -179,8 +179,7 @@ DICT *dict_union_open(const char *name, int open_flags, int dict_flags)
|
|||||||
DICT_TYPE_UNION, name,
|
DICT_TYPE_UNION, name,
|
||||||
DICT_TYPE_UNION));
|
DICT_TYPE_UNION));
|
||||||
if ((dict = dict_handle(dict_type_name)) == 0)
|
if ((dict = dict_handle(dict_type_name)) == 0)
|
||||||
dict = dict_open(dict_type_name, open_flags,
|
dict = dict_open(dict_type_name, open_flags, dict_flags);
|
||||||
dict_flags & ~DICT_FLAG_SRC_RHS_IS_FILE);
|
|
||||||
dict_register(dict_type_name, dict);
|
dict_register(dict_type_name, dict);
|
||||||
DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
|
DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
|
||||||
if (cpp == argv->argv)
|
if (cpp == argv->argv)
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <dict.h>
|
/* #include <dict.h>
|
||||||
/*
|
/*
|
||||||
/* void dict_utf8_wrapper_activate(
|
/* DICT *dict_utf8_activate(
|
||||||
/* DICT *dict)
|
/* DICT *dict)
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* dict_utf8_wrapper_activate() wraps a dictionary's lookup/update/delete
|
/* dict_utf8_activate() wraps a dictionary's lookup/update/delete
|
||||||
/* methods with code that enforces UTF-8 checks on keys and
|
/* methods with code that enforces UTF-8 checks on keys and
|
||||||
/* values, and that logs a warning when incorrect UTF-8 is
|
/* values, and that logs a warning when incorrect UTF-8 is
|
||||||
/* encountered.
|
/* encountered. The original dictionary handle becomes invalid.
|
||||||
/*
|
/*
|
||||||
/* The wrapper code enforces a policy that maximizes application
|
/* The wrapper code enforces a policy that maximizes application
|
||||||
/* robustness (it avoids the need for new error-handling code
|
/* robustness (it avoids the need for new error-handling code
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
/* skipped while reporting a non-error status, and lookup
|
/* skipped while reporting a non-error status, and lookup
|
||||||
/* results that contain a non-UTF-8 value are blocked while
|
/* results that contain a non-UTF-8 value are blocked while
|
||||||
/* reporting a configuration error.
|
/* reporting a configuration error.
|
||||||
|
/* BUGS
|
||||||
|
/* dict_utf8_activate() does not nest.
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -131,10 +133,9 @@ static int dict_utf8_check(const char *string, CONST_CHAR_STAR *err)
|
|||||||
|
|
||||||
/* dict_utf8_lookup - UTF-8 lookup method wrapper */
|
/* dict_utf8_lookup - UTF-8 lookup method wrapper */
|
||||||
|
|
||||||
static const char *dict_utf8_lookup(DICT_WRAPPER *wrapper, DICT *dict,
|
static const char *dict_utf8_lookup(DICT *dict, const char *key)
|
||||||
const char *key)
|
|
||||||
{
|
{
|
||||||
DICT_WRAPPER *next_wrapper;
|
DICT_UTF8_BACKUP *backup;
|
||||||
const char *utf8_err;
|
const char *utf8_err;
|
||||||
const char *fold_res;
|
const char *fold_res;
|
||||||
const char *value;
|
const char *value;
|
||||||
@@ -155,8 +156,8 @@ static const char *dict_utf8_lookup(DICT_WRAPPER *wrapper, DICT *dict,
|
|||||||
*/
|
*/
|
||||||
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
||||||
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
||||||
next_wrapper = wrapper->next;
|
backup = dict->utf8_backup;
|
||||||
value = next_wrapper->lookup(next_wrapper, dict, fold_res);
|
value = backup->lookup(dict, fold_res);
|
||||||
dict->flags |= saved_flags;
|
dict->flags |= saved_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -174,10 +175,9 @@ static const char *dict_utf8_lookup(DICT_WRAPPER *wrapper, DICT *dict,
|
|||||||
|
|
||||||
/* dict_utf8_update - UTF-8 update method wrapper */
|
/* dict_utf8_update - UTF-8 update method wrapper */
|
||||||
|
|
||||||
static int dict_utf8_update(DICT_WRAPPER *wrapper, DICT *dict,
|
static int dict_utf8_update(DICT *dict, const char *key, const char *value)
|
||||||
const char *key, const char *value)
|
|
||||||
{
|
{
|
||||||
DICT_WRAPPER *next_wrapper;
|
DICT_UTF8_BACKUP *backup;
|
||||||
const char *utf8_err;
|
const char *utf8_err;
|
||||||
const char *fold_res;
|
const char *fold_res;
|
||||||
int saved_flags;
|
int saved_flags;
|
||||||
@@ -209,8 +209,8 @@ static int dict_utf8_update(DICT_WRAPPER *wrapper, DICT *dict,
|
|||||||
else {
|
else {
|
||||||
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
||||||
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
||||||
next_wrapper = wrapper->next;
|
backup = dict->utf8_backup;
|
||||||
status = next_wrapper->update(next_wrapper, dict, fold_res, value);
|
status = backup->update(dict, fold_res, value);
|
||||||
dict->flags |= saved_flags;
|
dict->flags |= saved_flags;
|
||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
@@ -218,9 +218,9 @@ static int dict_utf8_update(DICT_WRAPPER *wrapper, DICT *dict,
|
|||||||
|
|
||||||
/* dict_utf8_delete - UTF-8 delete method wrapper */
|
/* dict_utf8_delete - UTF-8 delete method wrapper */
|
||||||
|
|
||||||
static int dict_utf8_delete(DICT_WRAPPER *wrapper, DICT *dict, const char *key)
|
static int dict_utf8_delete(DICT *dict, const char *key)
|
||||||
{
|
{
|
||||||
DICT_WRAPPER *next_wrapper;
|
DICT_UTF8_BACKUP *backup;
|
||||||
const char *utf8_err;
|
const char *utf8_err;
|
||||||
const char *fold_res;
|
const char *fold_res;
|
||||||
int saved_flags;
|
int saved_flags;
|
||||||
@@ -242,19 +242,19 @@ static int dict_utf8_delete(DICT_WRAPPER *wrapper, DICT *dict, const char *key)
|
|||||||
else {
|
else {
|
||||||
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
|
||||||
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
dict->flags &= ~DICT_FLAG_FOLD_ANY;
|
||||||
next_wrapper = wrapper->next;
|
backup = dict->utf8_backup;
|
||||||
status = next_wrapper->delete(next_wrapper, dict, fold_res);
|
status = backup->delete(dict, fold_res);
|
||||||
dict->flags |= saved_flags;
|
dict->flags |= saved_flags;
|
||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dict_utf8_wrapper_activate - wrap legacy dict object for UTF-8 processing */
|
/* dict_utf8_activate - wrap a legacy dict object for UTF-8 processing */
|
||||||
|
|
||||||
void dict_utf8_wrapper_activate(DICT *dict)
|
DICT *dict_utf8_activate(DICT *dict)
|
||||||
{
|
{
|
||||||
const char myname[] = "dict_utf8_wrapper_activate";
|
const char myname[] = "dict_utf8_activate";
|
||||||
DICT_WRAPPER *wrapper;
|
DICT_UTF8_BACKUP *backup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check.
|
* Sanity check.
|
||||||
@@ -264,22 +264,37 @@ void dict_utf8_wrapper_activate(DICT *dict)
|
|||||||
if ((dict->flags & DICT_FLAG_UTF8_REQUEST) == 0)
|
if ((dict->flags & DICT_FLAG_UTF8_REQUEST) == 0)
|
||||||
msg_panic("%s: %s:%s does not request Unicode support",
|
msg_panic("%s: %s:%s does not request Unicode support",
|
||||||
myname, dict->type, dict->name);
|
myname, dict->type, dict->name);
|
||||||
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE))
|
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) || dict->utf8_backup != 0)
|
||||||
msg_panic("%s: %s:%s Unicode support is already activated",
|
msg_panic("%s: %s:%s Unicode support is already activated",
|
||||||
myname, dict->type, dict->name);
|
myname, dict->type, dict->name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interpose on the lookup/update/delete methods.
|
* Unlike dict_debug(3) we do not put a proxy dict object in front of the
|
||||||
|
* encapsulated object, because then we would have to bidirectionally
|
||||||
|
* propagate changes in the data members (errors, flags, jbuf, and so on)
|
||||||
|
* between proxy object and encapsulated object.
|
||||||
|
*
|
||||||
|
* Instead we attach ourselves behind the encapsulated dict object, and
|
||||||
|
* redirect some function pointers to ourselves.
|
||||||
*/
|
*/
|
||||||
wrapper = dict_wrapper_alloc(sizeof(*wrapper));
|
backup = dict->utf8_backup = (DICT_UTF8_BACKUP *) mymalloc(sizeof(*backup));
|
||||||
wrapper->name = "utf8";
|
|
||||||
wrapper->lookup = dict_utf8_lookup;
|
/*
|
||||||
wrapper->update = dict_utf8_update;
|
* Interpose on the lookup/update/delete methods. It is a conscious
|
||||||
wrapper->delete = dict_utf8_delete;
|
* decision not to tinker with the iterator or destructor.
|
||||||
dict_wrapper_prepend(dict, wrapper);
|
*/
|
||||||
|
backup->lookup = dict->lookup;
|
||||||
|
backup->update = dict->update;
|
||||||
|
backup->delete = dict->delete;
|
||||||
|
|
||||||
|
dict->lookup = dict_utf8_lookup;
|
||||||
|
dict->update = dict_utf8_update;
|
||||||
|
dict->delete = dict_utf8_delete;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leave our mark. See sanity check above.
|
* Leave our mark. See sanity check above.
|
||||||
*/
|
*/
|
||||||
dict->flags |= DICT_FLAG_UTF8_ACTIVE;
|
dict->flags |= DICT_FLAG_UTF8_ACTIVE;
|
||||||
|
|
||||||
|
return (dict);
|
||||||
}
|
}
|
||||||
|
@@ -1,243 +0,0 @@
|
|||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* dict_wrapper 3
|
|
||||||
/* SUMMARY
|
|
||||||
/* dictionary method wrappers
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* #include <dict.h>
|
|
||||||
/*
|
|
||||||
/* void dict_wrapper_prepend(
|
|
||||||
/* DICT *dict,
|
|
||||||
/* DICT_WRAPPER *wrapper)
|
|
||||||
/*
|
|
||||||
/* DICT_WRAPPER *dict_wrapper_alloc(
|
|
||||||
/* ssize_t size)
|
|
||||||
/*
|
|
||||||
/* void dict_wrapper_free(
|
|
||||||
/* DICT_WRAPPER *wrapper)
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* dict_wrapper_prepend() prepends the specified dictionary
|
|
||||||
/* lookup/update/delete wrappers to a chain that is evaluated
|
|
||||||
/* in reverse order. dict_wrapper_prepend() takes ownership
|
|
||||||
/* of the wrapper.
|
|
||||||
/*
|
|
||||||
/* dict_wrapper_alloc() allocates memory for a dictionary
|
|
||||||
/* wrapper object and initializes all wrapper methods to
|
|
||||||
/* empty (no override).
|
|
||||||
/*
|
|
||||||
/* dict_wrapper_free() destroys a chain of dictionary wrappers.
|
|
||||||
/* LICENSE
|
|
||||||
/* .ad
|
|
||||||
/* .fi
|
|
||||||
/* The Secure Mailer license must be distributed with this software.
|
|
||||||
/* AUTHOR(S)
|
|
||||||
/* 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 <stringops.h>
|
|
||||||
#include <dict.h>
|
|
||||||
#include <mymalloc.h>
|
|
||||||
#include <msg.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The final DICT_WRAPPER is installed first, and also contains the original
|
|
||||||
* DICT's methods.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
DICT_WRAPPER wrapper; /* parent class, must be first */
|
|
||||||
const char *(*saved_lookup) (DICT *, const char *);
|
|
||||||
int (*saved_update) (DICT *, const char *, const char *);
|
|
||||||
int (*saved_delete) (DICT *, const char *);
|
|
||||||
} DICT_FINAL_WRAPPER;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions that override DICT methods, and that call into the head of
|
|
||||||
* the dict wrapper chain.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* dict_wrapper_lookup - DICT method to call into wrapper chain head */
|
|
||||||
|
|
||||||
static const char *dict_wrapper_lookup(DICT *dict, const char *key)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *head_wrapper = dict->wrapper;
|
|
||||||
|
|
||||||
return (head_wrapper->lookup(head_wrapper, dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_wrapper_update - DICT method to call into wrapper chain head */
|
|
||||||
|
|
||||||
static int dict_wrapper_update(DICT *dict, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *head_wrapper = dict->wrapper;
|
|
||||||
|
|
||||||
return (head_wrapper->update(head_wrapper, dict, key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_wrapper_delete - DICT method to call into wrapper chain head */
|
|
||||||
|
|
||||||
static int dict_wrapper_delete(DICT *dict, const char *key)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *head_wrapper = dict->wrapper;
|
|
||||||
|
|
||||||
return (head_wrapper->delete(head_wrapper, dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Empty methods for wrappers that override only some methods. These ensure
|
|
||||||
* that the next wrapper's methods are called with the right 'self' pointer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* empty_wrapper_lookup - wrapper method to call into next wrapper */
|
|
||||||
|
|
||||||
static const char *empty_wrapper_lookup(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *next_wrapper = wrapper->next;
|
|
||||||
|
|
||||||
return (next_wrapper->lookup(next_wrapper, dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* empty_wrapper_update - wrapper method to call into next wrapper */
|
|
||||||
|
|
||||||
static int empty_wrapper_update(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key, const char *value)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *next_wrapper = wrapper->next;
|
|
||||||
|
|
||||||
return (next_wrapper->update(next_wrapper, dict, key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* empty_wrapper_delete - wrapper method to call into next wrapper */
|
|
||||||
|
|
||||||
static int empty_wrapper_delete(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *next_wrapper = wrapper->next;
|
|
||||||
|
|
||||||
return (next_wrapper->delete(next_wrapper, dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrapper methods for the final dict wrapper in the chain. These call into
|
|
||||||
* the saved DICT methods.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* final_wrapper_lookup - wrapper method to call saved DICT method */
|
|
||||||
|
|
||||||
static const char *final_wrapper_lookup(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key)
|
|
||||||
{
|
|
||||||
DICT_FINAL_WRAPPER *final_wrapper = (DICT_FINAL_WRAPPER *) wrapper;
|
|
||||||
|
|
||||||
return (final_wrapper->saved_lookup(dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* final_wrapper_update - wrapper method to call saved DICT method */
|
|
||||||
|
|
||||||
static int final_wrapper_update(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key, const char *value)
|
|
||||||
{
|
|
||||||
DICT_FINAL_WRAPPER *final_wrapper = (DICT_FINAL_WRAPPER *) wrapper;
|
|
||||||
|
|
||||||
return (final_wrapper->saved_update(dict, key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* final_wrapper_delete - wrapper method to call saved DICT method */
|
|
||||||
|
|
||||||
static int final_wrapper_delete(DICT_WRAPPER *wrapper, DICT *dict,
|
|
||||||
const char *key)
|
|
||||||
{
|
|
||||||
DICT_FINAL_WRAPPER *final_wrapper = (DICT_FINAL_WRAPPER *) wrapper;
|
|
||||||
|
|
||||||
return (final_wrapper->saved_delete(dict, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finally, the functions that build the wrapper chain.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* dict_wrapper_activate - wrap a DICT object for additional processing */
|
|
||||||
|
|
||||||
static void dict_wrapper_activate(DICT *dict)
|
|
||||||
{
|
|
||||||
const char myname[] = "dict_wrapper_activate";
|
|
||||||
DICT_FINAL_WRAPPER *final_wrapper;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanity check.
|
|
||||||
*/
|
|
||||||
if (dict->wrapper != 0)
|
|
||||||
msg_panic("%s: %s:%s wrapper support is already activated",
|
|
||||||
myname, dict->type, dict->name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Install the final wrapper object that calls the original DICT's
|
|
||||||
* methods, and redirect DICT's method calls to ourselves. All other
|
|
||||||
* dictionary wrappers will be prepended to a chain that ends in the
|
|
||||||
* final wrapper object.
|
|
||||||
*/
|
|
||||||
final_wrapper = (DICT_FINAL_WRAPPER *) mymalloc(sizeof(*final_wrapper));
|
|
||||||
final_wrapper->wrapper.name = "final";
|
|
||||||
final_wrapper->wrapper.lookup = final_wrapper_lookup;
|
|
||||||
final_wrapper->wrapper.update = final_wrapper_update;
|
|
||||||
final_wrapper->wrapper.delete = final_wrapper_delete;
|
|
||||||
final_wrapper->wrapper.next = 0;
|
|
||||||
dict->wrapper = &final_wrapper->wrapper;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interpose on the DICT's lookup/update/delete methods.
|
|
||||||
*/
|
|
||||||
final_wrapper->saved_lookup = dict->lookup;
|
|
||||||
final_wrapper->saved_update = dict->update;
|
|
||||||
final_wrapper->saved_delete = dict->delete;
|
|
||||||
|
|
||||||
dict->lookup = dict_wrapper_lookup;
|
|
||||||
dict->update = dict_wrapper_update;
|
|
||||||
dict->delete = dict_wrapper_delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_wrapper_alloc - allocate and initialize dictionary wrapper */
|
|
||||||
|
|
||||||
DICT_WRAPPER *dict_wrapper_alloc(ssize_t size)
|
|
||||||
{
|
|
||||||
DICT_WRAPPER *wrapper;
|
|
||||||
|
|
||||||
wrapper = (DICT_WRAPPER *) mymalloc(size);
|
|
||||||
wrapper->lookup = empty_wrapper_lookup;
|
|
||||||
wrapper->update = empty_wrapper_update;
|
|
||||||
wrapper->delete = empty_wrapper_delete;
|
|
||||||
return (wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_wrapper_prepend - prepend dict method overrides */
|
|
||||||
|
|
||||||
void dict_wrapper_prepend(DICT *dict, DICT_WRAPPER *wrapper)
|
|
||||||
{
|
|
||||||
if (dict->wrapper == 0)
|
|
||||||
dict_wrapper_activate(dict);
|
|
||||||
|
|
||||||
wrapper->next = dict->wrapper;
|
|
||||||
dict->wrapper = wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dict_wrapper_free - wrapper destructor */
|
|
||||||
|
|
||||||
void dict_wrapper_free(DICT_WRAPPER *wrapper)
|
|
||||||
{
|
|
||||||
if (wrapper->next)
|
|
||||||
dict_wrapper_free(wrapper->next);
|
|
||||||
myfree((void *) wrapper);
|
|
||||||
}
|
|
Reference in New Issue
Block a user