2 * Copyright (C) 2013 Flowroute LLC (flowroute.com)
4 * This file is part of Kamailio, a free SIP server.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "../../core/mod_fix.h"
28 #include "../../core/lvalue.h"
30 #include "jansson_path.h"
31 #include "jansson_funcs.h"
32 #include "jansson_utils.h"
34 int janssonmod_get_helper(sip_msg_t* msg, str *path_s, str *src_s, pv_spec_t *dst_pv)
39 json_error_t parsing_error;
41 json = json_loads(src_s->s, JSON_REJECT_DUPLICATES, &parsing_error);
44 ERR("failed to parse json: %.*s\n", src_s->len, src_s->s);
45 ERR("json error at line %d, col %d: %s\n",
46 parsing_error.line, parsing_error.column, parsing_error.text);
50 char* path = path_s->s;
52 json_t* v = json_path_get(json, path);
59 if(jansson_to_val(&dst_val, &freeme, v)<0) goto fail;
61 dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
75 int janssonmod_get(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
80 if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
81 ERR("cannot get json string value\n");
85 if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
86 ERR("cannot get path string value\n");
90 return janssonmod_get_helper(msg, &path_s, &src_s, (pv_spec_t *)dst);
93 #define STR_EQ_STATIC(a,b) ((a.len == sizeof(b)-1) && (strncmp(a.s, b, sizeof(b)-1)==0))
95 int janssonmod_set(unsigned int append, struct sip_msg* msg, char* type_in,
96 char* path_in, char* value_in, char* result_in)
102 pv_spec_t* result_pv;
103 pv_value_t result_val;
105 if (fixup_get_svalue(msg, (gparam_p)type_in, &type_s) != 0){
106 ERR("cannot get type string value\n");
110 if (fixup_get_svalue(msg, (gparam_p)value_in, &value_s) != 0){
111 ERR("cannot get value string\n");
115 if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0){
116 ERR("cannot get path string value\n");
120 result_pv = (pv_spec_t *)result_in;
122 if(pv_get_spec_value(msg, result_pv, &result_val)!=0
123 || result_val.flags != PV_VAL_STR) {
124 result_val.flags = PV_VAL_STR;
125 result_val.rs.s = "{}";
126 result_val.rs.len = strlen("{}");
130 ALERT("type is: %.*s\n", type_s.len, type_s.s);
131 ALERT("path is: %.*s\n", path_s.len, path_s.s);
132 ALERT("value is: %.*s\n", value_s.len, value_s.s);
133 ALERT("result is: %.*s\n", result_val.rs.len, result_val.rs.s);
136 char* result = result_val.rs.s;
138 json_t* result_json = NULL;
139 json_t* value = NULL;
141 json_error_t parsing_error = {0};
145 if(STR_EQ_STATIC(type_s, "object") || STR_EQ_STATIC(type_s, "obj")){
146 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
147 if(value && !json_is_object(value)) {
148 ERR("value to add is not an object - \"%s\"\n", path_s.s);
152 }else if(STR_EQ_STATIC(type_s, "array")) {
153 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
154 if(value && !json_is_array(value)) {
155 ERR("value to add is not an array - \"%s\"\n", path_s.s);
159 }else if(STR_EQ_STATIC(type_s, "string")
160 || STR_EQ_STATIC(type_s, "str")) {
161 value = json_string(value_s.s);
162 if(!value || !json_is_string(value)) {
163 ERR("value to add is not a string - \"%s\"\n", path_s.s);
167 }else if(STR_EQ_STATIC(type_s, "integer")
168 || STR_EQ_STATIC(type_s, "int")) {
169 long long i = strtoll(value_s.s, &endptr, 10);
170 if(*endptr != '\0') {
171 ERR("parsing int failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
174 value = json_integer(i);
175 if(!value || !json_is_integer(value)) {
176 ERR("value to add is not an integer \"%s\"\n", path_s.s);
180 }else if(STR_EQ_STATIC(type_s, "real")) {
181 double d = strtod(value_s.s, &endptr);
182 if(*endptr != '\0') {
183 ERR("parsing real failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
186 value = json_real(d);
187 if(!value || !json_is_real(value)) {
188 ERR("value to add is not a real \"%s\"\n", path_s.s);
192 }else if(STR_EQ_STATIC(type_s, "true")) {
195 }else if(STR_EQ_STATIC(type_s, "false")) {
196 value = json_false();
198 }else if(STR_EQ_STATIC(type_s, "null")) {
202 ERR("unrecognized input type\n");
207 ERR("parsing failed for \"%s\"\n", value_s.s);
208 ERR("value error at line %d: %s\n",
209 parsing_error.line, parsing_error.text);
213 char* path = path_s.s;
215 result_json = json_loads(result, JSON_REJECT_DUPLICATES, &parsing_error);
218 ERR("result has json error at line %d: %s\n",
219 parsing_error.line, parsing_error.text);
223 if(json_path_set(result_json, path, value, append)<0) {
227 if(jansson_to_val(&result_val, &freeme, result_json)<0) goto fail;
229 result_pv->setf(msg, &result_pv->pvp, (int)EQ_T, &result_val);
231 if(freeme) free(freeme);
232 json_decref(result_json);
236 if(freeme) free(freeme);
237 json_decref(result_json);
241 int janssonmod_array_size(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
248 if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
249 ERR("cannot get json string value\n");
253 if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
254 ERR("cannot get path string value\n");
258 dst_pv = (pv_spec_t *)dst;
261 json_error_t parsing_error;
263 json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
266 ERR("json error at line %d: %s\n",
267 parsing_error.line, parsing_error.text);
271 char* path = path_s.s;
273 json_t* v = json_path_get(json, path);
275 ERR("failed to find %s in json\n", path);
279 if(!json_is_array(v)) {
280 ERR("value at %s is not an array\n", path);
284 int size = json_array_size(v);
286 dst_val.flags = PV_TYPE_INT|PV_VAL_INT;
288 dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);