diff options
author | Jeremy Harris <jgh146exb@wizmail.org> | 2019-02-09 16:48:08 +0000 |
---|---|---|
committer | Jeremy Harris <jgh146exb@wizmail.org> | 2019-02-11 00:15:39 +0000 |
commit | ffc92d69bf2618aca35f2c523abde0a76657e3a2 (patch) | |
tree | 07651643a7aa35b4375a081e56c8245c8eefdeef /src | |
parent | b53c265b5c7825d7fb6bb672547c44d080459d71 (diff) |
JSON lookup
(cherry picked from commits 854bd65fa7, 11b31159ac, 19cb5e2f14, 9669c6e06f, 6db8b72c86)
Diffstat (limited to 'src')
-rwxr-xr-x | src/scripts/MakeLinks | 2 | ||||
-rwxr-xr-x | src/scripts/lookups-Makefile | 2 | ||||
-rw-r--r-- | src/src/EDITME | 3 | ||||
-rw-r--r-- | src/src/config.h.defaults | 1 | ||||
-rw-r--r-- | src/src/drtables.c | 7 | ||||
-rw-r--r-- | src/src/exim.c | 3 | ||||
-rw-r--r-- | src/src/lookups/Makefile | 2 | ||||
-rw-r--r-- | src/src/lookups/json.c | 192 | ||||
-rw-r--r-- | src/src/macro_predef.c | 3 |
9 files changed, 212 insertions, 3 deletions
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks index f69bde437..b71736797 100755 --- a/src/scripts/MakeLinks +++ b/src/scripts/MakeLinks @@ -30,7 +30,7 @@ echo ">>> Creating links to source files..." mkdir lookups cd lookups # Makefile is generated -for f in README cdb.c dbmdb.c dnsdb.c dsearch.c ibase.c ldap.h ldap.c \ +for f in README cdb.c dbmdb.c dnsdb.c dsearch.c ibase.c json.c ldap.h ldap.c \ lmdb.c lsearch.c mysql.c redis.c nis.c nisplus.c oracle.c passwd.c \ pgsql.c spf.c sqlite.c testdb.c whoson.c \ lf_functions.h lf_check_file.c lf_quote.c lf_sqlperform.c diff --git a/src/scripts/lookups-Makefile b/src/scripts/lookups-Makefile index db2d184a7..498184ff6 100755 --- a/src/scripts/lookups-Makefile +++ b/src/scripts/lookups-Makefile @@ -160,7 +160,7 @@ exec > "$target" sed -n "1,/$tag_marker/p" < "$input" for name_mod in \ - CDB DBM:dbmdb DNSDB DSEARCH IBASE LSEARCH MYSQL NIS NISPLUS ORACLE \ + CDB DBM:dbmdb DNSDB DSEARCH IBASE JSON LSEARCH MYSQL NIS NISPLUS ORACLE \ PASSWD PGSQL REDIS SQLITE TESTDB WHOSON do emit_module_rule $name_mod diff --git a/src/src/EDITME b/src/src/EDITME index 15360db9a..b2c27dafe 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -309,6 +309,7 @@ LOOKUP_DNSDB=yes # LOOKUP_CDB=yes # LOOKUP_DSEARCH=yes # LOOKUP_IBASE=yes +# LOOKUP_JSON=yes # LOOKUP_LDAP=yes # LOOKUP_MYSQL=yes # LOOKUP_MYSQL_PC=mariadb @@ -376,7 +377,7 @@ PCRE_CONFIG=yes # don't need to set LOOKUP_INCLUDE if the relevant directories are already # specified in INCLUDE. The settings below are just examples; -lpq is for # PostgreSQL, -lgds is for Interbase, -lsqlite3 is for SQLite, -lhiredis -# is for Redis. +# is for Redis, -ljansson for JSON. # # You do not need to use this for any lookup information added via pkg-config. diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 74ec3f4df..55688295d 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -93,6 +93,7 @@ Do not put spaces between # and the 'define'. #define LOOKUP_DNSDB #define LOOKUP_DSEARCH #define LOOKUP_IBASE +#define LOOKUP_JSON #define LOOKUP_LDAP #define LOOKUP_LSEARCH #define LOOKUP_MYSQL diff --git a/src/src/drtables.c b/src/src/drtables.c index 54d03edab..b7024297d 100644 --- a/src/src/drtables.c +++ b/src/src/drtables.c @@ -564,6 +564,9 @@ extern lookup_module_info dsearch_lookup_module_info; #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2 extern lookup_module_info ibase_lookup_module_info; #endif +#if defined(LOOKUP_JSON) +extern lookup_module_info json_lookup_module_info; +#endif #if defined(LOOKUP_LDAP) extern lookup_module_info ldap_lookup_module_info; #endif @@ -649,6 +652,10 @@ init_lookup_list(void) addlookupmodule(NULL, &ldap_lookup_module_info); #endif +#ifdef LOOKUP_JSON + addlookupmodule(NULL, &json_lookup_module_info); +#endif + #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2 addlookupmodule(NULL, &lsearch_lookup_module_info); #endif diff --git a/src/src/exim.c b/src/src/exim.c index d693c9f98..8e700f711 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -930,6 +930,9 @@ fprintf(fp, "Lookups (built-in):"); #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2 fprintf(fp, " ibase"); #endif +#if defined(LOOKUP_JSON) && LOOKUP_JSON!=2 + fprintf(fp, " json"); +#endif #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2 fprintf(fp, " ldap ldapdn ldapm"); #endif diff --git a/src/src/lookups/Makefile b/src/src/lookups/Makefile index 7c9700690..01910d542 100644 --- a/src/src/lookups/Makefile +++ b/src/src/lookups/Makefile @@ -35,6 +35,7 @@ dsearch.o: $(PHDRS) dsearch.c ibase.o: $(PHDRS) ibase.c ldap.o: $(PHDRS) ldap.c lmdb.o: $(PHDRS) lmdb.c +json.o: $(PHDRS) json.c lsearch.o: $(PHDRS) lsearch.c mysql.o: $(PHDRS) mysql.c nis.o: $(PHDRS) nis.c @@ -53,6 +54,7 @@ dbmdb.so: $(PHDRS) dbmdb.c dnsdb.so: $(PHDRS) dnsdb.c dsearch.so: $(PHDRS) dsearch.c ibase.so: $(PHDRS) ibase.c +json.so: $(PHDRS) json.c ldap.so: $(PHDRS) ldap.c lmdb.so: $(PHDRS) lmdb.c lsearch.so: $(PHDRS) lsearch.c diff --git a/src/src/lookups/json.c b/src/src/lookups/json.c new file mode 100644 index 000000000..0b28b731e --- /dev/null +++ b/src/src/lookups/json.c @@ -0,0 +1,192 @@ +/************************************************* +* Exim - an Internet mail transport agent * +*************************************************/ + +/* Copyright (c) Jeremy Harris 2019 */ +/* See the file NOTICE for conditions of use and distribution. */ + +#include "../exim.h" +#include "lf_functions.h" +#include <jansson.h> + + + +/* All use of allocations will be done against the POOL_SEARCH memory, +which is freed once by search_tidyup(). Make the free call a dummy. +This burns some 300kB in handling a 37kB JSON file, for the benefit of +a fast free. The alternative of staying with malloc is nearly as bad, +eyeballing the activity there are 20% the number of free vs. alloc +calls (before the big bunch at the end). */ + +static void * +json_malloc(size_t nbytes) +{ +void * p = store_get((int)nbytes); +/* debug_printf("%s %d: %p\n", __FUNCTION__, (int)nbytes, p); */ +return p; +} +static void +json_free(void * p) +{ +/* debug_printf("%s: %p\n", __FUNCTION__, p); */ +} + +/************************************************* +* Open entry point * +*************************************************/ + +/* See local README for interface description */ + +static void * +json_open(uschar *filename, uschar **errmsg) +{ +FILE * f; + +json_set_alloc_funcs(json_malloc, json_free); + +if (!(f = Ufopen(filename, "rb"))) + { + int save_errno = errno; + *errmsg = string_open_failed(errno, "%s for json search", filename); + errno = save_errno; + return NULL; + } +return f; +} + + + +/************************************************* +* Check entry point * +*************************************************/ + +static BOOL +json_check(void *handle, uschar *filename, int modemask, uid_t *owners, + gid_t *owngroups, uschar **errmsg) +{ +return lf_check_file(fileno((FILE *)handle), filename, S_IFREG, modemask, + owners, owngroups, "json", errmsg) == 0; +} + + + +/************************************************* +* Find entry point for lsearch * +*************************************************/ + +/* See local README for interface description */ + +static int +json_find(void *handle, uschar *filename, const uschar *keystring, int length, + uschar **result, uschar **errmsg, uint *do_cache) +{ +FILE * f = handle; +json_t * j, * j0; +json_error_t jerr; +uschar * key; +int sep = 0; + +length = length; /* Keep picky compilers happy */ +do_cache = do_cache; /* Keep picky compilers happy */ + +rewind(f); +if (!(j = json_loadf(f, 0, &jerr))) + { + *errmsg = string_sprintf("json error on open: %.*s\n", + JSON_ERROR_TEXT_LENGTH, jerr.text); + return FAIL; + } +j0 = j; + +for (int k = 1; (key = string_nextinlist(&keystring, &sep, NULL, 0)); k++) + { + BOOL numeric = TRUE; + for (uschar * s = key; *s; s++) if (!isdigit(*s)) { numeric = FALSE; break; } + + if (!(j = numeric + ? json_array_get(j, (size_t) strtoul(CS key, NULL, 10)) + : json_object_get(j, CCS key) + ) ) + { + DEBUG(D_lookup) debug_printf("%s, for key %d: '%s'\n", + numeric + ? US"bad index, or not json array" + : US"no such key, or not json object", + k, key); + json_decref(j0); + return FAIL; + } + } + +switch (json_typeof(j)) + { + case JSON_STRING: + *result = string_copyn(CUS json_string_value(j), json_string_length(j)); + break; + case JSON_INTEGER: + *result = string_sprintf("%" JSON_INTEGER_FORMAT, json_integer_value(j)); + break; + case JSON_REAL: + *result = string_sprintf("%f", json_real_value(j)); + break; + case JSON_TRUE: *result = US"true"; break; + case JSON_FALSE: *result = US"false"; break; + case JSON_NULL: *result = NULL; break; + default: *result = US json_dumps(j, 0); break; + } +json_decref(j0); +return OK; +} + + + +/************************************************* +* Close entry point * +*************************************************/ + +/* See local README for interface description */ + +static void +json_close(void *handle) +{ +(void)fclose((FILE *)handle); +} + + + +/************************************************* +* Version reporting entry point * +*************************************************/ + +/* See local README for interface description. */ + +#include "../version.h" + +void +json_version_report(FILE *f) +{ +fprintf(f, "Library version: json: Jansonn version %s\n", JANSSON_VERSION); +} + + +static lookup_info json_lookup_info = { + US"json", /* lookup name */ + lookup_absfile, /* uses absolute file name */ + json_open, /* open function */ + json_check, /* check function */ + json_find, /* find function */ + json_close, /* close function */ + NULL, /* no tidy function */ + NULL, /* no quoting function */ + json_version_report /* version reporting */ +}; + + +#ifdef DYNLOOKUP +#define json_lookup_module_info _lookup_module_info +#endif + +static lookup_info *_lookup_list[] = { &json_lookup_info }; +lookup_module_info json_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 }; + +/* End of lookups/json.c */ diff --git a/src/src/macro_predef.c b/src/src/macro_predef.c index 84a33282d..f92671ae2 100644 --- a/src/src/macro_predef.c +++ b/src/src/macro_predef.c @@ -223,6 +223,9 @@ due to conflicts with other common macros. */ builtin_macro_create(US"_HAVE_LOOKUP_IBASE"); #endif #ifdef LOOKUP_LDAP + builtin_macro_create(US"_HAVE_LOOKUP_JSON"); +#endif +#ifdef LOOKUP_LDAP builtin_macro_create(US"_HAVE_LOOKUP_LDAP"); #endif #ifdef EXPERIMENTAL_LMDB |