kazoo: fixed crash when json body is NULL
[kamailio] / src / modules / kazoo / kz_json.c
1 /*
2  * $Id$
3  *
4  * Kazoo module interface
5  *
6  * Copyright (C) 2010-2014 2600Hz
7  *
8  * This file is part of Kamailio, a free SIP server.
9  *
10  * Kamailio is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * Kamailio is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * History:
25  * --------
26  * 2014-08  first version (2600hz)
27  */
28
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "../../core/mod_fix.h"
33 #include "../../core/lvalue.h"
34
35 #include "kz_json.h"
36 #include "const.h"
37 #include "../../core/pvar.h"
38 #include "../../core/usr_avp.h"
39
40
41
42 static str kz_pv_str_empty = {"", 0};
43
44 enum json_type kz_json_get_type(struct json_object *jso)
45 {
46   return json_object_get_type(jso);
47 }
48
49 typedef str* json_key;
50 typedef json_key* json_keys;
51
52 json_keys kz_str_split(char* a_str, const char a_delim, int* c)
53 {
54         json_keys result = 0;
55     int count     = 0;
56     char* tmp        = a_str;
57     char* last_comma = 0;
58     char delim[2];
59     delim[0] = a_delim;
60     delim[1] = 0;
61     int len = 0;
62
63     /* Count how many elements will be extracted. */
64     while (*tmp)
65     {
66         if (a_delim == *tmp)
67         {
68             count++;
69             last_comma = tmp;
70         }
71         tmp++;
72     }
73
74     /* Add space for trailing token. */
75     count += last_comma < (a_str + strlen(a_str) - 1);
76
77     /* Add space for terminating null string so caller
78        knows where the list of returned strings ends. */
79 //    count++;
80     *c = count;
81     LM_DBG("COUNT %d\n", count);
82
83     result = pkg_malloc(sizeof(json_key) * count);
84     memset(result, 0, sizeof(json_key) * count);
85
86     if (result)
87     {
88         int idx  = 0;
89         char* token = strtok(a_str, delim);
90
91         while (token)
92         {
93             LM_DBG("TOKEN %d : %s\n", idx, token);
94
95             assert(idx < count);
96
97             result[idx] = pkg_malloc(sizeof(str));
98             len = strlen(token);
99
100             result[idx]->len = len;
101                         result[idx]->s = pkg_malloc((len + 1) * sizeof(char));
102                         strncpy(result[idx]->s, token, len);
103                         result[idx]->s[len] = '\0';
104
105                 int i = 0;
106                 while(i < len) {
107                         if(result[idx]->s[i] == kz_json_escape_char)
108                                 result[idx]->s[i] = '.';
109                         i++;
110                 }
111                 LM_DBG("TOKEN2 %d : %s\n", idx, result[idx]->s);
112             token = strtok(0, delim);
113             idx++;
114         }
115         assert(idx == count);
116     }
117
118     return result;
119 }
120
121 struct json_object * kz_json_get_field_object(str* json, str* field)
122 {
123   json_keys keys;
124   json_key key;
125   char* dup;
126   char f1[250], f2[250];//, f3[25];
127   int i, parts;
128
129   dup = pkg_malloc(json->len+1);
130   memcpy(dup, json->s, json->len);
131   dup[json->len] = '\0';
132   struct json_object *j = json_tokener_parse(dup);
133   pkg_free(dup);
134
135   if (j==NULL) {
136           LM_ERR("empty or invalid JSON\n");
137           return NULL;
138   }
139
140   struct json_object *jtree = NULL;
141   struct json_object *ret = NULL;
142
143   LM_DBG("getting json %.*s\n", field->len, field->s);
144
145   dup = pkg_malloc(field->len+1);
146   memcpy(dup, field->s, field->len);
147   dup[field->len] = '\0';
148   keys = kz_str_split(dup, '.', &parts);
149   pkg_free(dup);
150
151     if (keys)
152     {
153         jtree = j;
154         for (i = 0; i < parts; i++)
155         {
156                 key = keys[i];
157                 LM_DBG("TOKEN %d , %p, %p : %s\n", i, keys[i], key->s, key->s);
158
159                 if(jtree != NULL) {
160                                 //str field1 = str_init(token);
161                                 // check for idx []
162                                 int sresult = sscanf(key->s, "%[^[][%[^]]]", f1, f2); //, f3);
163                                 LM_DBG("CHECK IDX %d - %s , %s, %s\n", sresult, key->s, f1, (sresult > 1? f2 : "(null)"));
164
165                                 jtree = kz_json_get_object(jtree, f1);
166                                 if(jtree != NULL) {
167                                         char *value = (char*)json_object_get_string(jtree);
168                                         LM_DBG("JTREE OK %s\n", value);
169                                 }
170                                 if(jtree != NULL && sresult > 1 && json_object_is_type(jtree, json_type_array)) {
171                                         int idx = atoi(f2);
172                                         jtree = json_object_array_get_idx(jtree, idx);
173                                         if(jtree != NULL) {
174                                                 char *value = (char*)json_object_get_string(jtree);
175                                                 LM_DBG("JTREE IDX OK %s\n", value);
176                                         }
177                                 }
178                 }
179         }
180
181         for(i = 0;i < parts; i++) {
182             LM_DBG("FREE %d\n", i);
183             pkg_free(keys[i]->s);
184             pkg_free(keys[i]);
185         }
186
187         pkg_free(keys);
188     }
189
190
191
192         if(jtree != NULL)
193                 ret = json_object_get(jtree);
194
195         json_object_put(j);
196
197         return ret;
198 }
199
200 int kz_json_get_count(str* json, str* field, pv_value_p dst_val)
201 {
202
203   struct json_object *jtree = kz_json_get_field_object(json, field);
204
205
206         dst_val->flags = PV_TYPE_INT | PV_VAL_INT;
207     dst_val->rs = kz_pv_str_empty;
208     dst_val->ri = 0;
209         if(jtree != NULL) {
210                 if(json_object_is_type(jtree, json_type_array)) {
211                         dst_val->ri = json_object_array_length(jtree);
212                 }
213         json_object_put(jtree);
214         }
215         return 1;
216 }
217
218
219 int kz_json_get_field_ex(str* json, str* field, pv_value_p dst_val)
220 {
221
222   struct json_object *jtree = kz_json_get_field_object(json, field);
223
224
225         if(jtree != NULL) {
226                 char *value = (char*)json_object_get_string(jtree);
227                 int len = strlen(value);
228                 dst_val->rs.s = pkg_malloc(len+1);
229                 memcpy(dst_val->rs.s, value, len);
230                 dst_val->rs.s[len] = '\0';
231                 dst_val->rs.len = len;
232                 dst_val->flags = PV_VAL_STR | PV_VAL_PKG;
233         dst_val->ri = 0;
234         json_object_put(jtree);
235         } else {
236                 dst_val->flags = PV_VAL_NULL;
237         dst_val->rs = kz_pv_str_empty;
238         dst_val->ri = 0;
239         }
240         return 1;
241 }
242
243
244 int kz_json_get_field(struct sip_msg* msg, char* json, char* field, char* dst)
245 {
246   str json_s;
247   str field_s;
248   pv_spec_t *dst_pv;
249   pv_value_t dst_val;
250
251         if (fixup_get_svalue(msg, (gparam_p)json, &json_s) != 0) {
252                 LM_ERR("cannot get json string value\n");
253                 return -1;
254         }
255
256         if (fixup_get_svalue(msg, (gparam_p)field, &field_s) != 0) {
257                 LM_ERR("cannot get field string value\n");
258                 return -1;
259         }
260
261         if(kz_json_get_field_ex(&json_s, &field_s, &dst_val) != 1)
262                 return -1;
263
264         dst_pv = (pv_spec_t *)dst;
265         dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
266         if(dst_val.flags & PV_VAL_PKG)
267                 pkg_free(dst_val.rs.s);
268         else if(dst_val.flags & PV_VAL_SHM)
269                 shm_free(dst_val.rs.s);
270
271         return 1;
272 }
273
274 struct json_object* kz_json_parse(const char *str)
275 {
276     struct json_tokener* tok;
277     struct json_object* obj;
278
279     if (str == NULL || str[0] == 0) {
280       LM_ERR("Error parsing json: empty string\n");
281       return NULL;
282     }
283
284     tok = json_tokener_new();
285     if (!tok) {
286       LM_ERR("Error parsing json: could not allocate tokener\n");
287       return NULL;
288     }
289
290     obj = json_tokener_parse_ex(tok, str, -1);
291     if(tok->err != json_tokener_success) {        
292       LM_ERR("Error parsing json: %s\n", json_tokener_error_desc(tok->err));
293       LM_ERR("%s\n", str);
294       if (obj != NULL)
295            json_object_put(obj);
296       obj = NULL;
297     }
298
299     json_tokener_free(tok);
300     return obj;
301 }
302
303 struct json_object* kz_json_get_object(struct json_object* jso, const char *key)
304 {
305         struct json_object *result = NULL;
306         json_object_object_get_ex(jso, key, &result);
307         return result;
308 }
309
310 int kz_json_get_keys(struct sip_msg* msg, char* json, char* field, char* dst)
311 {
312   str json_s;
313   str field_s;
314   int_str keys_avp_name;
315   unsigned short keys_avp_type;
316   pv_spec_t *avp_spec;
317
318         if (fixup_get_svalue(msg, (gparam_p)json, &json_s) != 0) {
319                 LM_ERR("cannot get json string value\n");
320                 return -1;
321         }
322
323         if (fixup_get_svalue(msg, (gparam_p)field, &field_s) != 0) {
324                 LM_ERR("cannot get field string value\n");
325                 return -1;
326         }
327
328         if(dst == NULL){
329                 LM_ERR("avp spec is null\n");
330                 return -1;
331         }
332
333         avp_spec = (pv_spec_t *)dst;
334
335         if(avp_spec->type != PVT_AVP) {
336                 LM_ERR("invalid avp spec\n");
337                 return -1;
338         }
339
340         if(pv_get_avp_name(0, &avp_spec->pvp, &keys_avp_name, &keys_avp_type)!=0)
341         {
342                 LM_ERR("invalid AVP definition\n");
343                 return -1;
344         }
345
346         struct json_object *jtree = kz_json_get_field_object(&json_s, &field_s);
347
348         if(jtree != NULL) {
349                 json_foreach_key(jtree, k) {
350                         LM_DBG("ITERATING KEY %s\n", k);
351                         int_str v1;
352                         v1.s.s = k;
353                         v1.s.len = strlen(k);
354                         if (add_avp(AVP_VAL_STR|keys_avp_type, keys_avp_name, v1) < 0) {
355                                 LM_ERR("failed to create AVP\n");
356                             json_object_put(jtree);
357                                 return -1;
358                         }
359                 }
360             json_object_put(jtree);
361         }
362
363         return 1;
364 }
365