1 
2 #include <switch.h>
3 #include "freeswitch_lua.h"
4 using namespace LUA;
5 
6 extern "C" {
7 	int docall(lua_State * L, int narg, int nresults, int perror, int fatal);
8 };
9 
Session()10 Session::Session():CoreSession()
11 {
12 	cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
13 	hh = mark = 0;
14 }
15 
Session(char * nuuid,CoreSession * a_leg)16 Session::Session(char *nuuid, CoreSession *a_leg):CoreSession(nuuid, a_leg)
17 {
18 	cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
19 	hh = mark = 0;
20 }
21 
Session(switch_core_session_t * new_session)22 Session::Session(switch_core_session_t *new_session):CoreSession(new_session)
23 {
24 	cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
25 	hh = mark = 0;
26 }
27 static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup);
28 
29 
destroy(const char * err)30 void Session::destroy(const char *err)
31 {
32 
33 	if (!allocated) {
34 		return;
35 	}
36 
37 	if (session) {
38 		if (!channel) {
39 			channel = switch_core_session_get_channel(session);
40 		}
41 		switch_channel_set_private(channel, "CoreSession", NULL);
42 		switch_core_event_hook_remove_state_change(session, lua_hanguphook);
43 	}
44 
45 	switch_safe_free(hangup_func_str);
46 	switch_safe_free(hangup_func_arg);
47 	switch_safe_free(cb_function);
48 	switch_safe_free(cb_arg);
49 
50 	unsetInputCallback();
51 
52 	CoreSession::destroy();
53 
54 
55 	if (!zstr(err)) {
56 		lua_pushstring(L, err);
57 		lua_error(L);
58 	}
59 
60 }
61 
62 
~Session()63 Session::~Session()
64 {
65 	destroy();
66 }
67 
begin_allow_threads()68 bool Session::begin_allow_threads()
69 {
70 	do_hangup_hook();
71 	return true;
72 }
73 
end_allow_threads()74 bool Session::end_allow_threads()
75 {
76 	do_hangup_hook();
77 	return true;
78 }
79 
setLUA(lua_State * state)80 void Session::setLUA(lua_State * state)
81 {
82 	L = state;
83 
84 	if (session && allocated && uuid) {
85 		lua_setglobal(L, uuid);
86 		lua_getglobal(L, uuid);
87 	}
88 
89 }
90 
originate(CoreSession * a_leg_session,char * dest,int timeout)91 int Session::originate(CoreSession *a_leg_session, char *dest, int timeout)
92 {
93 	if (zstr(dest)) {
94 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing destination.\n");
95 		return 0;
96 	}
97 
98 	int x = CoreSession::originate(a_leg_session, dest, timeout);
99 
100 	if (x) {
101 		setLUA(L);
102 	}
103 
104 	return x;
105 }
106 
getLUA()107 lua_State *Session::getLUA()
108 {
109 	if (!L) {
110 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
111 	}
112 	return L;
113 }
114 
115 
ready()116 bool Session::ready()
117 {
118 	bool r;
119 
120 	if (!session) {
121 		return false;
122 	}
123 	sanity_check(false);
124 	r = switch_channel_ready(channel) != 0;
125 	do_hangup_hook();
126 
127 	return r;
128 }
129 
check_hangup_hook()130 void Session::check_hangup_hook()
131 {
132 	if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) {
133 		hh++;
134 	}
135 }
136 
do_hangup_hook()137 void Session::do_hangup_hook()
138 {
139 	if (hh && !mark) {
140 		int arg_count = 2;
141 		mark++;
142 
143 		if (!getLUA()) {
144 			return;
145 		}
146 
147 		lua_getglobal(L, (char *) hangup_func_str);
148 		lua_getglobal(L, uuid);
149 
150 		lua_pushstring(L, hook_state == CS_HANGUP ? "hangup" : "transfer");
151 
152 		if (hangup_func_arg) {
153 			lua_getglobal(L, (char *) hangup_func_arg);
154 			arg_count++;
155 		}
156 
157 		docall(L, arg_count, 1, 1, 0);
158 
159 		const char *err = lua_tostring(L, -1);
160 
161 		switch_channel_set_variable(channel, "lua_hangup_hook_return_val", err);
162 
163 		if (!zstr(err)) {
164 
165 			if (!strcasecmp(err, "exit") || !strcasecmp(err, "die")) {
166 				lua_error(L);
167 			} else {
168 				lua_pop(L, 1);
169 			}
170 		} else {
171 			lua_pop(L, 1);
172 		}
173 
174 
175 		if (channel) {
176 			switch_channel_set_private(channel, "CoreSession", NULL);
177 		}
178 
179 		if (session) {
180 			switch_core_event_hook_remove_state_change(session, lua_hanguphook);
181 		}
182 		switch_safe_free(hangup_func_str);
183 
184 	}
185 }
186 
lua_hanguphook(switch_core_session_t * session_hungup)187 static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup)
188 {
189 	switch_channel_t *channel = switch_core_session_get_channel(session_hungup);
190 	Session *coresession = NULL;
191 	switch_channel_state_t state = switch_channel_get_state(channel);
192 
193 	if (session_hungup) {
194 
195 		channel = switch_core_session_get_channel(session_hungup);
196 
197 		if (channel) {
198 			void *vs = switch_channel_get_private(channel, "CoreSession");
199 			if (vs) {
200 				coresession = (Session *) vs;
201 			}
202 		}
203 
204 		if (!(coresession && coresession->hook_state)) {
205 			return SWITCH_STATUS_FALSE;
206 		}
207 
208 		if (coresession && coresession->allocated && (state == CS_HANGUP || state == CS_ROUTING) && coresession->hook_state != state) {
209 			coresession->hook_state = state;
210 			coresession->check_hangup_hook();
211 			switch_core_event_hook_remove_state_change(session_hungup, lua_hanguphook);
212 		}
213 	}
214 
215 	return SWITCH_STATUS_SUCCESS;
216 }
217 
218 
setHangupHook(char * func,char * arg)219 void Session::setHangupHook(char *func, char *arg)
220 {
221 
222 	sanity_check_noreturn;
223 
224 	switch_safe_free(hangup_func_str);
225 	switch_safe_free(hangup_func_arg);
226 
227 	if (func) {
228 		hangup_func_str = strdup(func);
229 		if (!zstr(arg)) {
230 			hangup_func_arg = strdup(arg);
231 		}
232 		switch_channel_set_private(channel, "CoreSession", this);
233 		hook_state = switch_channel_get_state(channel);
234 		switch_core_event_hook_add_state_change(session, lua_hanguphook);
235 	}
236 }
237 
unsetInputCallback(void)238 void Session::unsetInputCallback(void)
239 {
240 	sanity_check_noreturn;
241 	switch_safe_free(cb_function);
242 	switch_safe_free(cb_arg);
243 	args.input_callback = NULL;
244 	ap = NULL;
245 	switch_channel_clear_flag_recursive(channel, CF_QUEUE_TEXT_EVENTS);
246 }
247 
setInputCallback(char * cbfunc,char * funcargs)248 void Session::setInputCallback(char *cbfunc, char *funcargs)
249 {
250 
251 	sanity_check_noreturn;
252 
253 	switch_safe_free(cb_function);
254 	if (cbfunc) {
255 		cb_function = strdup(cbfunc);
256 	}
257 
258 	switch_safe_free(cb_arg);
259 	if (funcargs) {
260 		cb_arg = strdup(funcargs);
261 	}
262 
263 	args.buf = this;
264 	switch_channel_set_private(channel, "CoreSession", this);
265 
266 	args.input_callback = dtmf_callback;
267 	ap = &args;
268 
269 	switch_channel_set_flag_recursive(channel, CF_QUEUE_TEXT_EVENTS);
270 
271 }
272 
run_dtmf_callback(void * input,switch_input_type_t itype)273 switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
274 {
275 	const char *ret;
276 
277 	if (!getLUA()) {
278 		return SWITCH_STATUS_FALSE;;
279 	}
280 
281 	switch (itype) {
282 	case SWITCH_INPUT_TYPE_DTMF:
283 		{
284 			switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
285 			char str[3] = "";
286 			int arg_count = 3;
287 			int r;
288 
289 			lua_getglobal(L, (char *) cb_function);
290 			lua_getglobal(L, uuid);
291 
292 			lua_pushstring(L, "dtmf");
293 
294 			lua_newtable(L);
295 			lua_pushstring(L, "digit");
296 			str[0] = dtmf->digit;
297 			lua_pushstring(L, str);
298 			lua_rawset(L, -3);
299 
300 			lua_pushstring(L, "duration");
301 			lua_pushnumber(L, dtmf->duration);
302 			lua_rawset(L, -3);
303 
304 			if (!zstr(cb_arg)) {
305 				lua_getglobal(L, (char *) cb_arg);
306 				arg_count++;
307 			}
308 
309 			r = docall(L, arg_count, 1, 1, 0);
310 
311 			if (!r) {
312 				ret = lua_tostring(L, -1);
313 				lua_pop(L, 1);
314 			} else {
315 				ret = "SCRIPT_ERROR";
316 			}
317 
318 			return process_callback_result((char *) ret);
319 		}
320 		break;
321 	case SWITCH_INPUT_TYPE_EVENT:
322 		{
323 			switch_event_t *event = (switch_event_t *) input;
324 			int arg_count = 3;
325 
326 
327 			lua_getglobal(L, (char *) cb_function);
328 			lua_getglobal(L, uuid);
329 			lua_pushstring(L, "event");
330 			mod_lua_conjure_event(L, event, "__Input_Event__", 1);
331 			lua_getglobal(L, "__Input_Event__");
332 
333 			if (!zstr(cb_arg)) {
334 				lua_getglobal(L, (char *) cb_arg);
335 				arg_count++;
336 			}
337 
338 			if (!docall(L, arg_count, 1, 1, 0)) {
339 				ret = lua_tostring(L, -1);
340 				lua_pop(L, 1);
341 			} else {
342 				ret = "SCRIPT_ERROR";
343 			}
344 
345 			return process_callback_result((char *) ret);
346 		}
347 		break;
348 	}
349 
350 	return SWITCH_STATUS_SUCCESS;
351 }
352 
353 
Dbh(char * dsn,char * user,char * pass)354 Dbh::Dbh(char *dsn, char *user, char *pass)
355 {
356 	dbh = NULL;
357 	err = NULL;
358 	char *tmp = NULL;
359 
360 	if (!zstr(user) || !zstr(pass)) {
361 		tmp = switch_mprintf("%s%s%s%s%s", dsn,
362 							 zstr(user) ? "" : ":",
363 							 zstr(user) ? "" : user,
364 							 zstr(pass) ? "" : ":",
365 							 zstr(pass) ? "" : pass
366 							 );
367 
368 		dsn = tmp;
369 	}
370 
371 	if (!zstr(dsn) && switch_cache_db_get_db_handle_dsn(&dbh, dsn) == SWITCH_STATUS_SUCCESS) {
372 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "DBH handle %p Connected.\n", (void *) dbh);
373 	} else {
374 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Connection failed.  DBH NOT Connected.\n");
375 	}
376 
377 	switch_safe_free(tmp);
378 
379 }
380 
~Dbh()381 Dbh::~Dbh()
382 {
383 	if (dbh) release();
384 
385 	clear_error();
386 }
387 
clear_error()388 void Dbh::clear_error()
389 {
390 	switch_safe_free(err);
391 }
392 
last_error()393 char *Dbh::last_error()
394 {
395 	return err;
396 }
397 
release()398 bool Dbh::release()
399 {
400   if (dbh) {
401 	  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "DBH handle %p released.\n", (void *) dbh);
402 	  switch_cache_db_release_db_handle(&dbh);
403 	  return true;
404   }
405 
406   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
407   return false;
408 }
409 
connected()410 bool Dbh::connected()
411 {
412 	return dbh ? true : false;
413 }
414 
test_reactive(char * test_sql,char * drop_sql,char * reactive_sql)415 bool Dbh::test_reactive(char *test_sql, char *drop_sql, char *reactive_sql)
416 {
417   if (dbh) {
418     if (!zstr(test_sql) && !zstr(reactive_sql)) {
419       if (switch_cache_db_test_reactive(dbh, test_sql, drop_sql, reactive_sql) == SWITCH_TRUE) {
420         return true;
421       }
422     } else {
423       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing parameters.\n");
424     }
425   } else {
426     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
427   }
428   return false;
429 }
430 
query_callback(void * pArg,int argc,char ** argv,char ** cargv)431 int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
432 {
433   SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
434 	int ret = 0;
435 
436   lua_pushvalue(lua_fun->L, lua_fun->idx); /* get the lua callback function onto the stack */
437 
438   lua_newtable(lua_fun->L); /* push a row (table) */
439 
440   for (int i = 0; i < argc; i++) {
441     lua_pushstring(lua_fun->L, switch_str_nil(cargv[i]));
442     lua_pushstring(lua_fun->L, switch_str_nil(argv[i]));
443     lua_settable(lua_fun->L, -3);
444   }
445 
446   if (docall(lua_fun->L, 1, 1, 1, 0)) {
447 	  return 1;
448   }
449 
450   ret = lua_tonumber(lua_fun->L, -1);
451   lua_pop(lua_fun->L, 1);
452 
453   if (ret != 0) {
454 	  return 1;
455   }
456 
457   return 0; /* 0 to continue with next row */
458 }
459 
query(char * sql,SWIGLUA_FN lua_fun)460 bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
461 {
462   clear_error();
463 
464   if (zstr(sql)) {
465     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing SQL query.\n");
466     return false;
467   }
468 
469   if (dbh) {
470     if (lua_fun.L) {
471       if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, &err) == SWITCH_STATUS_SUCCESS) {
472         return true;
473       }
474     } else { /* if no lua_fun arg is passed from Lua, an empty initialized struct will be sent - see freeswitch.i */
475       if (switch_cache_db_execute_sql(dbh, sql, &err) == SWITCH_STATUS_SUCCESS) {
476         return true;
477       }
478     }
479   } else {
480     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
481   }
482   return false;
483 }
484 
affected_rows()485 int Dbh::affected_rows()
486 {
487   if (dbh) {
488     return switch_cache_db_affected_rows(dbh);
489   }
490 
491   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
492   return 0;
493 }
494 
load_extension(const char * extension)495 int Dbh::load_extension(const char *extension)
496 {
497   if (zstr(extension)) {
498     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing extension name.\n");
499     return 0;
500   }
501 
502   if (dbh) {
503     return switch_cache_db_load_extension(dbh, extension);
504   }
505 
506   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
507   return 0;
508 }
509 
JSON()510 JSON::JSON()
511 {
512 	_encode_empty_table_as_object = true;
513 }
514 
~JSON()515 JSON::~JSON()
516 {
517 }
518 
encode_empty_table_as_object(bool flag)519 void JSON::encode_empty_table_as_object(bool flag)
520 {
521 	_encode_empty_table_as_object = flag;
522 }
523 
return_unformatted_json(bool flag)524 void JSON::return_unformatted_json(bool flag)
525 {
526 	_return_unformatted_json = flag;
527 }
528 
decode(const char * str)529 cJSON *JSON::decode(const char *str)
530 {
531 	cJSON *json = cJSON_Parse(str);
532 	return json;
533 }
534 
535 #define ADDITEM(json, k, v) do { \
536 	if (return_array > 0) { cJSON_AddItemToArray(json, v);} else { cJSON_AddItemToObject(json, k, v); } \
537 } while (0)
538 
LuaTable2cJSON(lua_State * L,int index,cJSON ** json)539 void JSON::LuaTable2cJSON(lua_State *L, int index, cJSON **json)
540 {
541 	int return_array = -1;
542 
543     // Push another reference to the table on top of the stack (so we know
544     // where it is, and this function can work for negative, positive and
545     // pseudo indices
546     lua_pushvalue(L, index);
547     // stack now contains: -1 => table
548     lua_pushnil(L);
549     // stack now contains: -1 => nil; -2 => table
550     while (lua_next(L, -2)) {
551         // stack now contains: -1 => value; -2 => key; -3 => table
552         // copy the key so that lua_tostring does not modify the original
553         lua_pushvalue(L, -2);
554         // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
555 
556         const char *key = lua_tostring(L, -1);
557         // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "key: %s\n", key);
558 
559 		if (return_array < 0) {
560 			if (lua_isnumber(L, -1) && lua_tonumber(L, -1) == 1) {
561 				return_array = 1;
562 				*json = cJSON_CreateArray();
563 			} else {
564 				return_array = 0;
565 				*json = cJSON_CreateObject();
566 			}
567 		}
568 
569 		switch_assert(*json);
570 
571 		if (lua_isnumber(L, -2)) {
572 			ADDITEM(*json, key, cJSON_CreateNumber(lua_tonumber(L, -2)));
573 		} else if (lua_isstring(L, -2)) {
574 			ADDITEM(*json, key, cJSON_CreateString(lua_tostring(L, -2)));
575 		} else if (lua_isboolean(L, -2)) {
576 			ADDITEM(*json, key, cJSON_CreateBool(lua_toboolean(L, -2)));
577 		} else if (lua_isnil(L, -2)) {
578 			ADDITEM(*json, key, cJSON_CreateNull());
579 		} else if (lua_isnone(L, -2)) {
580 			// ADDITEM(*json, key, cJSON_CreateNone());
581 		} else if (lua_istable(L, -2)) {
582 			cJSON *child = NULL;
583 			LuaTable2cJSON(L, -2, &child);
584 			if (child) {
585 				ADDITEM(*json, key, child);
586 			} else { // empty table?
587 				ADDITEM(*json, key, _encode_empty_table_as_object ? cJSON_CreateObject() : cJSON_CreateArray());
588 			}
589 		}
590 
591         // pop value + copy of key, leaving original key
592         lua_pop(L, 2);
593         // stack now contains: -1 => key; -2 => table
594     }
595 
596     // stack now contains: -1 => table (when lua_next returns 0 it pops the key
597     // but does not push anything.)
598     // Pop table
599     lua_pop(L, 1);
600     // Stack is now the same as it was on entry to this function
601 }
602 
encode(SWIGLUA_TABLE lua_table)603 std::string JSON::encode(SWIGLUA_TABLE lua_table)
604 {
605 	lua_State *L = lua_table.L;
606 	cJSON *json = NULL;
607 
608 	luaL_checktype(L, lua_table.idx, LUA_TTABLE);
609 	LuaTable2cJSON(L, -1, &json);
610 
611 	if (!json) {
612 		json = _encode_empty_table_as_object ? cJSON_CreateObject() : cJSON_CreateArray();
613 	}
614 
615 	char *s = _return_unformatted_json ? cJSON_PrintUnformatted(json) : cJSON_Print(json);
616 	std::string result = std::string(s);
617 	free(s);
618 	cJSON_Delete(json);
619 	return result;
620 }
621 
cJSON2LuaTable(lua_State * L,cJSON * json)622 int JSON::cJSON2LuaTable(lua_State *L, cJSON *json) {
623 	cJSON *current = NULL;
624 
625 	if (!json) return 0;
626 
627 	lua_newtable(L);
628 
629 	if (json->type == cJSON_Object) {
630 		for (current = json->child; current; current = current->next) {
631 			// printf("type: %d %s\n", current->type, current->string);
632 			switch (current->type) {
633 				case cJSON_String:
634 					lua_pushstring(L, current->valuestring);
635 					lua_setfield(L, -2, current->string);
636 					break;
637 				case cJSON_Number:
638 					lua_pushnumber(L, current->valuedouble);
639 					lua_setfield(L, -2, current->string);
640 					break;
641 				case cJSON_True:
642 					lua_pushboolean(L, 1);
643 					lua_setfield(L, -2, current->string);
644 					break;
645 				case cJSON_False:
646 					lua_pushboolean(L, 0);
647 					lua_setfield(L, -2, current->string);
648 					break;
649 				case cJSON_Object:
650 					JSON::cJSON2LuaTable(L, current);
651 					lua_setfield(L, -2, current->string);
652 					break;
653 				case cJSON_Array:
654 					JSON::cJSON2LuaTable(L, current);
655 					lua_setfield(L, -2, current->string);
656 					break;
657 				default:
658 					break;
659 			}
660 		}
661 	} else if (json->type == cJSON_Array) {
662 		int i = 1;
663 
664 		for (current = json->child; current; current = current->next) {
665 			// printf("array type: %d %s\n", current->type, current->valuestring);
666 			switch (current->type) {
667 				case cJSON_String:
668 					lua_pushinteger(L, i++);
669 					lua_pushstring(L, current->valuestring);
670 					lua_settable(L, -3);
671 					break;
672 				case cJSON_Number:
673 					lua_pushinteger(L, i++);
674 					lua_pushnumber(L, current->valuedouble);
675 					lua_settable(L, -3);
676 					break;
677 				case cJSON_True:
678 					lua_pushinteger(L, i++);
679 					lua_pushboolean(L, 1);
680 					lua_settable(L, -3);
681 					break;
682 				case cJSON_False:
683 					lua_pushinteger(L, i++);
684 					lua_pushboolean(L, 0);
685 					lua_settable(L, -3);
686 					break;
687 				case cJSON_Object:
688 					lua_pushinteger(L, i++);
689 					JSON::cJSON2LuaTable(L, current);
690 					lua_settable(L, -3);
691 					break;
692 				default:
693 					break;
694 			}
695 		}
696 	}
697 
698 	return 1;
699 }
700 
execute(const char * str)701 cJSON *JSON::execute(const char *str)
702 {
703 	cJSON *cmd = cJSON_Parse(str);
704 	cJSON *reply = NULL;
705 
706 	if (cmd) {
707 		switch_json_api_execute(cmd, NULL, &reply);
708 	}
709 
710 	cJSON_Delete(cmd);
711 
712 	return reply;
713 }
714 
execute(SWIGLUA_TABLE table)715 cJSON *JSON::execute(SWIGLUA_TABLE table)
716 {
717 	lua_State *L = table.L;
718 	cJSON *json = NULL;
719 	cJSON *reply = NULL;
720 
721 	luaL_checktype(L, table.idx, LUA_TTABLE);
722 	LuaTable2cJSON(L, -1, &json);
723 
724 	switch_json_api_execute(json, NULL, &reply);
725 	cJSON_Delete(json);
726 	return reply;
727 }
728 
execute2(const char * str)729 std::string JSON::execute2(const char *str)
730 {
731     cJSON *reply = execute(str);
732     char *s = _return_unformatted_json ? cJSON_PrintUnformatted(reply) : cJSON_Print(reply);
733     std::string result = std::string(s);
734     free(s);
735     cJSON_Delete(reply);
736     return result;
737 }
738 
execute2(SWIGLUA_TABLE table)739 std::string JSON::execute2(SWIGLUA_TABLE table)
740 {
741     cJSON *reply = execute(table);
742     char *s = _return_unformatted_json ? cJSON_PrintUnformatted(reply) : cJSON_Print(reply);
743     std::string result = std::string(s);
744     free(s);
745     cJSON_Delete(reply);
746     return result;
747 }
748