Commit | Line | Data |
---|---|---|
854bd65f JH |
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 | { | |
9669c6e0 JH |
72 | *errmsg = string_sprintf("json error on open: %.*s\n", |
73 | JSON_ERROR_TEXT_LENGTH, jerr.text); | |
854bd65f JH |
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 */ |