013013ae808aac535fdaa81b0432093456e12f80
[exim.git] / src / src / lookups / json.c
1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
4
5 /* Copyright (c) Jeremy Harris 2019 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 #include "../exim.h"
9 #include "lf_functions.h"
10 #include <jansson.h>
11
12
13
14 /*************************************************
15 * Open entry point *
16 *************************************************/
17
18 /* See local README for interface description */
19
20 static void *
21 json_open(uschar *filename, uschar **errmsg)
22 {
23 FILE *f = Ufopen(filename, "rb");
24 if (f == NULL)
25 {
26 int save_errno = errno;
27 *errmsg = string_open_failed(errno, "%s for json search", filename);
28 errno = save_errno;
29 return NULL;
30 }
31 return f;
32 }
33
34
35
36 /*************************************************
37 * Check entry point *
38 *************************************************/
39
40 static BOOL
41 json_check(void *handle, uschar *filename, int modemask, uid_t *owners,
42 gid_t *owngroups, uschar **errmsg)
43 {
44 return lf_check_file(fileno((FILE *)handle), filename, S_IFREG, modemask,
45 owners, owngroups, "json", errmsg) == 0;
46 }
47
48
49
50 /*************************************************
51 * Find entry point for lsearch *
52 *************************************************/
53
54 /* See local README for interface description */
55
56 static int
57 json_find(void *handle, uschar *filename, const uschar *keystring, int length,
58 uschar **result, uschar **errmsg, uint *do_cache)
59 {
60 FILE * f = handle;
61 json_t * j, * j0;
62 json_error_t jerr;
63 uschar * key;
64 int sep = 0;
65
66 length = length; /* Keep picky compilers happy */
67 do_cache = do_cache; /* Keep picky compilers happy */
68
69 rewind(f);
70 if (!(j = json_loadf(f, 0, &jerr)))
71 {
72 enum json_error_code je = json_error_code(&jerr);
73 *errmsg = string_sprintf("json err %d on open", je);
74 return FAIL;
75 }
76 j0 = j;
77
78 for (int k = 1; (key = string_nextinlist(&keystring, &sep, NULL, 0)); k++)
79 {
80 BOOL numeric = TRUE;
81 for (uschar * s = key; *s; s++) if (!isdigit(*s)) { numeric = FALSE; break; }
82
83 if (!(j = numeric
84 ? json_array_get(j, (size_t) strtoul(CS key, NULL, 10))
85 : json_object_get(j, CCS key)
86 ) )
87 {
88 DEBUG(D_lookup) debug_printf("%s, for key %d: '%s'\n",
89 numeric
90 ? US"bad index, or not json array"
91 : US"no such key, or not json object",
92 k, key);
93 json_decref(j0);
94 return FAIL;
95 }
96 }
97
98 switch (json_typeof(j))
99 {
100 case JSON_STRING:
101 *result = string_copyn(CUS json_string_value(j), json_string_length(j));
102 break;
103 case JSON_INTEGER:
104 *result = string_sprintf("%" JSON_INTEGER_FORMAT, json_integer_value(j));
105 break;
106 case JSON_REAL:
107 *result = string_sprintf("%f", json_real_value(j));
108 break;
109 case JSON_TRUE: *result = US"true"; break;
110 case JSON_FALSE: *result = US"false"; break;
111 case JSON_NULL: *result = NULL; break;
112 default: *result = US json_dumps(j, 0); break;
113 }
114 json_decref(j0);
115 return OK;
116 }
117
118
119
120 /*************************************************
121 * Close entry point *
122 *************************************************/
123
124 /* See local README for interface description */
125
126 static void
127 json_close(void *handle)
128 {
129 (void)fclose((FILE *)handle);
130 }
131
132
133
134 /*************************************************
135 * Version reporting entry point *
136 *************************************************/
137
138 /* See local README for interface description. */
139
140 #include "../version.h"
141
142 void
143 json_version_report(FILE *f)
144 {
145 fprintf(f, "Library version: json: Jansonn version %s\n", JANSSON_VERSION);
146 }
147
148
149 static lookup_info json_lookup_info = {
150 US"json", /* lookup name */
151 lookup_absfile, /* uses absolute file name */
152 json_open, /* open function */
153 json_check, /* check function */
154 json_find, /* find function */
155 json_close, /* close function */
156 NULL, /* no tidy function */
157 NULL, /* no quoting function */
158 json_version_report /* version reporting */
159 };
160
161
162 #ifdef DYNLOOKUP
163 #define json_lookup_module_info _lookup_module_info
164 #endif
165
166 static lookup_info *_lookup_list[] = { &json_lookup_info };
167 lookup_module_info json_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
168
169 /* End of lookups/json.c */