Bug Summary

File:src/mod/applications/mod_httapi/mod_httapi.c
Location:line 986, column 11
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Raymond Chandler <intralanman@freeswitch.org>
28 *
29 * mod_httapi.c -- HT-TAPI Hypertext Telephony API
30 *
31 */
32#include <switch.h>
33#include <switch_curl.h>
34
35SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)switch_status_t mod_httapi_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
36SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_httapi_shutdown)switch_status_t mod_httapi_shutdown (void);
37SWITCH_MODULE_DEFINITION(mod_httapi, mod_httapi_load, mod_httapi_shutdown, NULL)static const char modname[] = "mod_httapi" ; __attribute__((visibility
("default"))) switch_loadable_module_function_table_t mod_httapi_module_interface
= { 5, mod_httapi_load, mod_httapi_shutdown, ((void*)0), SMODF_NONE
}
;
38
39typedef struct profile_perms_s {
40 switch_byte_t set_params;
41 switch_byte_t set_vars;
42 switch_byte_t get_vars;
43 switch_byte_t extended_data;
44 switch_byte_t execute_apps;
45 switch_byte_t expand_vars;
46 struct {
47 switch_byte_t enabled;
48 switch_byte_t set_context;
49 switch_byte_t set_dp;
50 switch_byte_t set_cid_name;
51 switch_byte_t set_cid_number;
52 switch_byte_t full_originate;
53 } dial;
54 struct {
55 switch_byte_t enabled;
56 switch_byte_t set_profile;
57 } conference;
58} profile_perms_t;
59
60struct client_s;
61
62typedef struct action_binding_s {
63 char *realm;
64 char *input;
65 char *action;
66 char *error_file;
67 char *match_digits;
68 char *strip;
69 struct client_s *client;
70 struct action_binding_s *parent;
71} action_binding_t;
72
73typedef struct client_profile_s {
74 char *name;
75 char *method;
76 char *url;
77 char *cred;
78 char *bind_local;
79 int disable100continue;
80 uint32_t enable_cacert_check;
81 char *ssl_cert_file;
82 char *ssl_key_file;
83 char *ssl_key_password;
84 char *ssl_version;
85 char *ssl_cacert_file;
86 uint32_t enable_ssl_verifyhost;
87 char *cookie_file;
88 switch_hash_t *vars_map;
89 long auth_scheme;
90 int timeout;
91 profile_perms_t perms;
92 char *ua;
93
94 struct {
95 char *use_profile;
96 } conference_params;
97
98 struct {
99 char *context;
100 char *dp;
101 switch_event_t *app_list;
102 int default_allow;
103 } dial_params;
104
105 struct {
106 switch_event_t *expand_var_list;
107 switch_event_t *set_var_list;
108 switch_event_t *get_var_list;
109 switch_event_t *api_list;
110 int default_allow;
111 } var_params;
112
113} client_profile_t;
114
115#define HTTAPI_MAX_API_BYTES1024 * 1024 1024 * 1024
116#define HTTAPI_MAX_FILE_BYTES1024 * 1024 * 100 1024 * 1024 * 100
117
118typedef struct client_s {
119 switch_memory_pool_t *pool;
120 int fd;
121 switch_buffer_t *buffer;
122 switch_size_t bytes;
123 switch_size_t max_bytes;
124 switch_event_t *headers;
125 switch_event_t *params;
126 switch_event_t *one_time_params;
127 client_profile_t *profile;
128 switch_core_session_t *session;
129 switch_channel_t *channel;
130 action_binding_t *matching_action_binding;
131 action_binding_t *no_matching_action_binding;
132 struct {
133 char *action;
134 char *name;
135 char *file;
136 } record;
137
138 int err;
139 long code;
140} client_t;
141
142typedef struct hash_node {
143 switch_hash_t *hash;
144 struct hash_node *next;
145} hash_node_t;
146
147static struct {
148 switch_memory_pool_t *pool;
149 hash_node_t *hash_root;
150 hash_node_t *hash_tail;
151 switch_hash_t *profile_hash;
152 switch_hash_t *request_hash;
153 switch_mutex_t *request_mutex;
154 switch_hash_t *parse_hash;
155 char cache_path[128];
156 int debug;
157 int not_found_expires;
158 int cache_ttl;
159 int abs_cache_ttl;
160 client_profile_t *profile;
161} globals;
162
163
164/* for apr_pstrcat */
165#define DEFAULT_PREBUFFER_SIZE1024 * 64 1024 * 64
166
167struct http_file_source;
168
169struct http_file_context {
170 int samples;
171 switch_file_handle_t fh;
172 char *cache_file;
173 char *cache_file_base;
174 char *meta_file;
175 char *metadata;
176 time_t expires;
177 switch_file_t *lock_fd;
178 switch_memory_pool_t *pool;
179 int del_on_close;
180 char *dest_url;
181 char *ua;
182 switch_event_t *url_params;
183
184 struct {
185 char *ext;
186 } read;
187
188 struct {
189 char *file_name;
190 char *profile_name;
191 char *file;
192 char *method;
193 char *name;
194 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1];
195 } write;
196
197 switch_mutex_t *mutex;
198};
199
200typedef struct http_file_context http_file_context_t;
201typedef switch_status_t (*tag_parse_t)(const char *tag_name, client_t *client, switch_xml_t tag, const char *body);
202
203static void bind_parser(const char *tag_name, tag_parse_t handler)
204{
205 switch_core_hash_insert(globals.parse_hash, tag_name, (void *)(intptr_t)handler)switch_core_hash_insert_destructor(globals.parse_hash, tag_name
, (void *)(intptr_t)handler, ((void*)0))
;
206}
207
208
209#define HTTAPI_SYNTAX"[debug_on|debug_off]" "[debug_on|debug_off]"
210SWITCH_STANDARD_API(httapi_api_function)static switch_status_t httapi_api_function ( const char *cmd,
switch_core_session_t *session, switch_stream_handle_t *stream
)
211{
212 if (session) {
213 return SWITCH_STATUS_FALSE;
214 }
215
216 if (zstr(cmd)_zstr(cmd)) {
217 goto usage;
218 }
219
220 if (!strcasecmp(cmd, "debug_on")) {
221 globals.debug = 1;
222 } else if (!strcasecmp(cmd, "debug_off")) {
223 globals.debug = 0;
224 } else {
225 goto usage;
226 }
227
228 stream->write_function(stream, "OK\n");
229 return SWITCH_STATUS_SUCCESS;
230
231 usage:
232 stream->write_function(stream, "USAGE: %s\n", HTTAPI_SYNTAX"[debug_on|debug_off]");
233 return SWITCH_STATUS_SUCCESS;
234}
235
236static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
237{
238 action_binding_t *action_binding = (action_binding_t *) match->user_data;
239
240 action_binding->client->matching_action_binding = action_binding;
241 action_binding->match_digits = switch_core_strdup(action_binding->client->pool, match->match_digits)switch_core_perform_strdup(action_binding->client->pool
, match->match_digits, "mod_httapi.c", (const char *)__func__
, 241)
;
242
243 return SWITCH_STATUS_SUCCESS;
244}
245
246static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t *match)
247{
248 action_binding_t *action_binding = (action_binding_t *) match->user_data;
249
250 action_binding->client->no_matching_action_binding = action_binding;
251
252 return SWITCH_STATUS_BREAK;
253}
254
255
256static switch_status_t parse_voicemail(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
257{
258 const char *check = switch_xml_attr(tag, "check");
259 const char *auth = switch_xml_attr(tag, "auth-only");
260 const char *profile = switch_xml_attr(tag, "profile");
261 const char *domain = switch_xml_attr(tag, "domain");
262 const char *id = switch_xml_attr_soft(tag, "id");
263 char *ddom = NULL((void*)0);
264 char *str;
265 switch_status_t status;
266
267 if (zstr(profile)_zstr(profile)) profile = "default";
268
269 if (zstr(domain)_zstr(domain)) {
270 if ((ddom = switch_core_get_domain(SWITCH_TRUE))) {
271 domain = ddom;
272 }
273 }
274
275 if (switch_true(check)) {
276 check = "check";
277 } else {
278 check = "";
279 }
280
281 if (switch_true(auth)) {
282 auth = "auth_only";
283 check = "check";
284 } else {
285 auth = "";
286 }
287
288 str = switch_core_session_sprintf(client->session, "%s %s %s %s %s", check, auth, profile, domain, id);
289
290 while(*str == ' ') str++;
291
292 status = switch_core_session_execute_application(client->session, "voicemail", str)switch_core_session_execute_application_get_flags(client->
session, "voicemail", str, ((void*)0))
;
293
294 switch_safe_free(ddom)if (ddom) {free(ddom);ddom=((void*)0);};
295
296 return status;
297}
298
299static switch_status_t parse_break(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
300{
301 return SWITCH_STATUS_FALSE;
302}
303
304
305static void console_log(const char *level_str, const char *msg)
306{
307 switch_log_level_t level = SWITCH_LOG_DEBUG;
308 if (level_str) {
309 level = switch_log_str2level(level_str);
310 if (level == SWITCH_LOG_INVALID) {
311 level = SWITCH_LOG_DEBUG;
312 }
313 }
314 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 314, ((void*)0)
, level, "%s", switch_str_nil(msg)(msg ? msg : ""));
315}
316
317static void console_clean_log(const char *level_str, const char *msg)
318{
319 switch_log_level_t level = SWITCH_LOG_DEBUG;
320 if (level_str) {
321 level = switch_log_str2level(level_str);
322 if (level == SWITCH_LOG_INVALID) {
323 level = SWITCH_LOG_DEBUG;
324 }
325 }
326 switch_log_printf(SWITCH_CHANNEL_LOG_CLEANSWITCH_CHANNEL_ID_LOG_CLEAN, "mod_httapi.c", (const char *)__func__
, 326, ((void*)0)
, level, "%s", switch_str_nil(msg)(msg ? msg : ""));
327}
328
329static switch_status_t parse_get_var(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
330{
331 const char *var = switch_xml_attr(tag, "name");
332 const char *perm = switch_xml_attr(tag, "permanent");
333
334 if (zstr(var)_zstr(var)) {
335 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 335, ((void*)0)
, SWITCH_LOG_ERROR, "Missing name attribute!");
336 return SWITCH_STATUS_SUCCESS;
337 }
338
339
340 if (client->profile->perms.get_vars &&
341 (!client->profile->var_params.get_var_list || switch_event_check_permission_list(client->profile->var_params.get_var_list, var))) {
342 const char *vval = switch_channel_get_variable(client->channel, var)switch_channel_get_variable_dup(client->channel, var, SWITCH_TRUE
, -1)
;
343 if (vval) {
344 switch_event_add_header_string(switch_true(perm) ? client->params : client->one_time_params, SWITCH_STACK_BOTTOM, var, vval);
345 }
346 } else {
347 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 347, ((void*)0)
, SWITCH_LOG_ERROR, "variable %s permission denied!\n", var);
348 return SWITCH_STATUS_FALSE;
349 }
350
351 return SWITCH_STATUS_SUCCESS;
352
353}
354
355static switch_status_t parse_continue(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
356{
357
358 return SWITCH_STATUS_SUCCESS;
359}
360
361static switch_status_t parse_log(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
362{
363 const char *level = switch_xml_attr(tag, "level");
364 const char *clean = switch_xml_attr(tag, "clean");
365
366 if (switch_true(clean)) {
367 console_clean_log(level, body);
368 } else {
369 console_log(level, body);
370 }
371
372 return SWITCH_STATUS_SUCCESS;
373}
374
375static switch_status_t parse_playback(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
376{
377 const char *file = switch_xml_attr(tag, "file");
378 const char *name = switch_xml_attr(tag, "name");
379 const char *error_file = switch_xml_attr(tag, "error-file");
380 const char *action = switch_xml_attr(tag, "action");
381 const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout");
382 const char *input_timeout_ = switch_xml_attr(tag, "input-timeout");
383 const char *terminators = switch_xml_attr(tag, "terminators");
384 const char *tts_engine = NULL((void*)0);
385 const char *tts_voice = NULL((void*)0);
386 char *loops_ = (char *) switch_xml_attr(tag, "loops");
387 int loops = 0;
388 switch_status_t status = SWITCH_STATUS_FALSE;
389 switch_ivr_dmachine_t *dmachine = NULL((void*)0);
390 switch_input_args_t *args = NULL((void*)0), myargs = { 0 }, nullargs = { 0 };
391 long digit_timeout = 1500;
392 long input_timeout = 5000;
393 long tmp;
394 switch_xml_t bind = NULL((void*)0);
395 int submit = 0;
396 int input = 0;
397 int speak = 0, say = 0, pause = 0, play = 0, speech = 0;
398 char *sub_action = NULL((void*)0);
399 action_binding_t *top_action_binding = NULL((void*)0);
400 const char *say_lang = NULL((void*)0);
401 const char *say_type = NULL((void*)0);
402 const char *say_method = NULL((void*)0);
403 const char *say_gender = NULL((void*)0);
404 const char *sp_engine = NULL((void*)0);
405 const char *sp_grammar = NULL((void*)0);
406 const char *text = NULL((void*)0);
407 char *free_string = NULL((void*)0);
408
409 if (!strcasecmp(tag_name, "say")) {
410 say_lang = switch_xml_attr(tag, "language");
411 say_type = switch_xml_attr(tag, "type");
412 say_method = switch_xml_attr(tag, "method");
413 say_gender = switch_xml_attr(tag, "gender");
414 text = switch_xml_attr(tag, "text");
415
416 if (zstr(text)_zstr(text)) {
417 if (!zstr(file)_zstr(file)) {
418 text = file;
419 } else if (!zstr(body)_zstr(body)) {
420 text = body;
421 }
422 }
423
424 if (zstr(say_lang)_zstr(say_lang) || zstr(say_type)_zstr(say_type) || zstr(say_method)_zstr(say_method) || zstr(text)_zstr(text)) {
425 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 425, ((void*)0)
, SWITCH_LOG_ERROR, "speak: missing required attributes or text! (language) (type) (method) \n");
426 return SWITCH_STATUS_FALSE;
427 }
428
429 say = 1;
430
431 } else if (!strcasecmp(tag_name, "speak")) {
432 tts_engine = switch_xml_attr(tag, "engine");
433 tts_voice = switch_xml_attr(tag, "voice");
434 text = switch_xml_attr(tag, "text");
435
436 if (zstr(text)_zstr(text)) {
437 if (!zstr(file)_zstr(file)) {
438 text = file;
439 } else if (!zstr(body)_zstr(body)) {
440 text = body;
441 }
442 }
443
444 if (zstr(tts_engine)_zstr(tts_engine)) {
445 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 445, ((void*)0)
, SWITCH_LOG_ERROR, "speak: missing engine attribute!\n");
446 return SWITCH_STATUS_FALSE;
447 }
448 speak = 1;
449 } else if (!strcasecmp(tag_name, "pause")) {
450 const char *ms_ = switch_xml_attr(tag, "milliseconds");
451 if (!zstr(ms_)_zstr(ms_)) {
452 pause = atoi(ms_);
453 }
454 if (pause <= 0) pause = 1000;
455 } else if (!strcasecmp(tag_name, "playback")) {
456 sp_engine = switch_xml_attr(tag, "asr-engine");
457 sp_grammar = switch_xml_attr(tag, "asr-grammar");
458
459 if (sp_grammar && sp_engine) {
460 speech = 1;
461 } else {
462 play = 1;
463 }
464 } else if (!strcasecmp(tag_name, "vmname")) {
465 const char *id = switch_xml_attr(tag, "id");
466 char *cmd, *resp;
467 switch_stream_handle_t stream = { 0 };
468 char *p;
469
470 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_httapi.c", 470, __PRETTY_FUNCTION__)); memset(stream.data
, 0, 1024); stream.end = stream.data; stream.data_size = 1024
; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
471
472 cmd = switch_mprintf("%s|name_path", id);
473
474 switch_api_execute("vm_prefs", cmd, NULL((void*)0), &stream);
475
476 resp = (char *) stream.data;
477
478 if (!zstr(resp)_zstr(resp)) {
479 if (switch_stristr("://", resp) || switch_file_exists(resp, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) {
480 play = 1;
481 file = free_string = resp;
482 resp = NULL((void*)0);
483 } else {
484 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 484, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid file! [%s]\n", resp);
485 switch_safe_free(resp)if (resp) {free(resp);resp=((void*)0);};
486 return SWITCH_STATUS_FALSE;
487 }
488 } else {
489 switch_safe_free(resp)if (resp) {free(resp);resp=((void*)0);};
490 say_lang = switch_xml_attr(tag, "language");
491 say_gender = switch_xml_attr(tag, "gender");
492 say_type = "name_spelled";
493 say_method = "pronounced";
494 free_string = strdup(id)(__extension__ (__builtin_constant_p (id) && ((size_t
)(const void *)((id) + 1) - (size_t)(const void *)(id) == 1) ?
(((const char *) (id))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (id) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, id, __len); __retval; })) : __strdup
(id)))
;
495 if ((p = strchr(free_string, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(free_string) && ('@') == '\0' ? (char *) __rawmemchr
(free_string, '@') : __builtin_strchr (free_string, '@')))
)) {
496 *p = '\0';
497 }
498 say = 1;
499
500 text = free_string;
501 switch_ivr_play_file(client->session, NULL((void*)0), "voicemail/vm-person.wav", &nullargs);
502
503 }
504
505 switch_safe_free(resp)if (resp) {free(resp);resp=((void*)0);};
506 }
507
508
509 if (zstr(name)_zstr(name)) name = "dialed_digits";
510
511 if (loops_) {
512 loops = atoi(loops_);
513
514 if (loops < 0) {
515 loops = -1;
516 }
517 }
518
519 if (digit_timeout_) {
520 tmp = atol(digit_timeout_);
521
522 if (tmp > 0) {
523 digit_timeout = tmp;
524 } else {
525 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 525, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid digit timeout [%s]\n", digit_timeout_);
526 }
527 }
528
529 if (input_timeout_) {
530 tmp = atol(input_timeout_);
531
532 if (tmp > 0) {
533 input_timeout = tmp;
534 } else {
535 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 535, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid input timeout [%s]\n", input_timeout_);
536 }
537 }
538
539 if ((bind = switch_xml_child(tag, "bind"))) {
540 action_binding_t *action_binding;
541 const char *realm = "default";
542
543
544 input++;
545
546 top_action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding))switch_core_perform_session_alloc(client->session, sizeof(
*action_binding), "mod_httapi.c", (const char *)__func__, 546
)
;
547 top_action_binding->client = client;
548 top_action_binding->action = (char *) action;
549 top_action_binding->error_file = (char *)error_file;
550
551 switch_ivr_dmachine_create(&dmachine, "HTTAPI", NULL((void*)0), digit_timeout, 0,
552 NULL((void*)0), digit_nomatch_action_callback, top_action_binding);
553
554 while(bind) {
555 action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding))switch_core_perform_session_alloc(client->session, sizeof(
*action_binding), "mod_httapi.c", (const char *)__func__, 555
)
;
556 action_binding->realm = (char *) realm;
557 action_binding->input = bind->txt;
558 action_binding->client = client;
559 action_binding->action = (char *) switch_xml_attr(bind, "action");
560 action_binding->strip = (char *) switch_xml_attr(bind, "strip");
561 action_binding->error_file = (char *) error_file;
562 action_binding->parent = top_action_binding;
563
564 switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
565 bind = bind->next;
566 }
567
568 switch_ivr_dmachine_set_realm(dmachine, realm);
569 if (!zstr(terminators)_zstr(terminators)) {
570 switch_ivr_dmachine_set_terminators(dmachine, terminators);
571 }
572
573 myargs.dmachine = dmachine;
574 args = &myargs;
575 }
576
577 if (zstr(file)_zstr(file) && !input) {
578 file = body;
579 }
580
581 if (zstr(file)_zstr(file) && !(speak || say || pause)) {
582 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 582, ((void*)0)
, SWITCH_LOG_ERROR, "missing file attribute!\n");
583 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 583, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
584 return SWITCH_STATUS_FALSE;
585 }
586
587 do {
588 if (speak) {
589 status = switch_ivr_speak_text(client->session, tts_engine, tts_voice, (char *)text, args);
590 } else if (say) {
591 status = switch_ivr_say(client->session, (char *)text, say_lang, say_type, say_method, say_gender, args);
592 } else if (play) {
593 status = switch_ivr_play_file(client->session, NULL((void*)0), file, args);
594 } else if (speech) {
595 char *result = NULL((void*)0);
596
597 status = switch_ivr_play_and_detect_speech(client->session, file, sp_engine, sp_grammar, &result, input_timeout, args);
598
599 if (!zstr(result)_zstr(result)) {
600 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, result);
601 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "detected_speech");
602 submit = 1;
603 break;
604 }
605
606 input_timeout = 0;
607 } else if (pause) {
608 input_timeout = pause;
609 status = SWITCH_STATUS_SUCCESS;
610 }
611
612 if (!switch_channel_ready(client->channel)switch_channel_test_ready(client->channel, SWITCH_TRUE, SWITCH_FALSE
)
) {
613 break;
614 }
615
616 if (!input && !pause) {
617 status = switch_channel_ready(client->channel)switch_channel_test_ready(client->channel, SWITCH_TRUE, SWITCH_FALSE
)
? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
618 submit = 1;
619 break;
620 }
621
622 if (input_timeout && status == SWITCH_STATUS_SUCCESS) {
623 if ((status = switch_ivr_sleep(client->session, input_timeout, SWITCH_TRUE, args)) == SWITCH_STATUS_SUCCESS) {
624 status = (input || !pause) ? SWITCH_STATUS_BREAK : SWITCH_STATUS_SUCCESS;
625 }
626 }
627
628 if (status == SWITCH_STATUS_BREAK) {
629 if (error_file) {
630 switch_ivr_play_file(client->session, NULL((void*)0), error_file, &nullargs);
631 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, "invalid");
632 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "invalid");
633 }
634 status = SWITCH_STATUS_SUCCESS;
635 } else if (status == SWITCH_STATUS_FOUND) {
636 status = SWITCH_STATUS_SUCCESS;
637 submit = 1;
638 break;
639 } else if (status != SWITCH_STATUS_SUCCESS) {
640 break;
641 }
642 } while (loops-- > 0);
643
644
645 if (submit) {
646 if (client->matching_action_binding) {
647 if (client->matching_action_binding->match_digits) {
648
649 if (client->matching_action_binding->strip) {
650 char *pp, *p;
651
652 for(pp = client->matching_action_binding->strip; pp && *pp; pp++) {
653 if ((p = strchr(client->matching_action_binding->match_digits, *pp)(__extension__ (__builtin_constant_p (*pp) && !__builtin_constant_p
(client->matching_action_binding->match_digits) &&
(*pp) == '\0' ? (char *) __rawmemchr (client->matching_action_binding
->match_digits, *pp) : __builtin_strchr (client->matching_action_binding
->match_digits, *pp)))
)) {
654 *p = '\0';
655 }
656 }
657 }
658 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, client->matching_action_binding->match_digits);
659 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "dtmf");
660 }
661
662 if (client->matching_action_binding->action) {
663 sub_action = client->matching_action_binding->action;
664 } else if (client->matching_action_binding->parent && client->matching_action_binding->parent->action) {
665 sub_action = client->matching_action_binding->parent->action;
666 }
667 }
668
669 if (!sub_action && top_action_binding && top_action_binding->action) {
670 sub_action = top_action_binding->action;
671 }
672
673 if (sub_action && client->matching_action_binding && client->matching_action_binding->match_digits) {
674 if (!strncasecmp(sub_action, "dial:", 5)) {
675 char *context = NULL((void*)0);
676 char *dp = NULL((void*)0);
677
678 if (client->profile->perms.dial.set_context) {
679 context = switch_core_session_strdup(client->session, sub_action + 5)switch_core_perform_session_strdup(client->session, sub_action
+ 5, "mod_httapi.c", (const char *)__func__, 679)
;
680
681 if ((dp = strchr(context, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(context) && (':') == '\0' ? (char *) __rawmemchr (context
, ':') : __builtin_strchr (context, ':')))
)) {
682 *dp++ = '\0';
683 if (!client->profile->perms.dial.set_dp) {
684 dp = NULL((void*)0);
685 }
686 }
687 }
688
689 switch_ivr_session_transfer(client->session, client->matching_action_binding->match_digits, dp, context);
690 status = SWITCH_STATUS_FALSE;
691
692 } else {
693 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", sub_action);
694 }
695 }
696 }
697
698 if (dmachine) {
699 switch_ivr_dmachine_destroy(&dmachine);
700 }
701
702 switch_safe_free(free_string)if (free_string) {free(free_string);free_string=((void*)0);};
703
704 return status;
705}
706
707static switch_status_t parse_conference(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
708{
709 char *str;
710 char *dup, *p;
711 const char *profile_name = switch_xml_attr(tag, "profile");
712
713 if (!client->profile->perms.conference.enabled) {
714 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 714, ((void*)0)
, SWITCH_LOG_ERROR, "Permission Denied!\n");
715 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 715, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
716 return SWITCH_STATUS_FALSE;
717 }
718
719 dup = switch_core_session_strdup(client->session, body)switch_core_perform_session_strdup(client->session, body, "mod_httapi.c"
, (const char *)__func__, 719)
;
720
721 if ((p = strchr(dup, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup) && ('@') == '\0' ? (char *) __rawmemchr (dup, '@'
) : __builtin_strchr (dup, '@')))
)) {
722 *p = '\0';
723 }
724
725 if (zstr(profile_name)_zstr(profile_name) || !client->profile->perms.conference.set_profile) {
726 profile_name = client->profile->conference_params.use_profile;
727 }
728
729 str = switch_core_session_sprintf(client->session, "%s@%s", dup, profile_name);
730 switch_core_session_execute_application(client->session, "conference", str)switch_core_session_execute_application_get_flags(client->
session, "conference", str, ((void*)0))
;
731
732 return SWITCH_STATUS_SUCCESS;
733}
734
735static switch_status_t parse_dial(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
736{
737 const char *context = NULL((void*)0);
738 const char *dp = NULL((void*)0);
739 const char *cid_name = NULL((void*)0);
740 const char *cid_number = NULL((void*)0);
741
742 if (!client->profile->perms.dial.enabled) {
743 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 743, ((void*)0)
, SWITCH_LOG_ERROR, "Permission Denied!\n");
744 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 744, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
745 return SWITCH_STATUS_FALSE;
746 }
747
748 if (client->profile->perms.dial.set_context) {
749 context = switch_xml_attr(tag, "context");
750 }
751
752 if (client->profile->perms.dial.set_dp) {
753 dp = switch_xml_attr(tag, "dialplan");
754 }
755
756 if (client->profile->perms.dial.set_cid_name) {
757 cid_name = switch_xml_attr(tag, "caller-id-name");
758 }
759
760 if (client->profile->perms.dial.set_cid_number) {
761 cid_number = switch_xml_attr(tag, "caller-id-number");
762 }
763
764 if (client->profile->perms.dial.full_originate && strchr(body, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p
(body) && ('/') == '\0' ? (char *) __rawmemchr (body
, '/') : __builtin_strchr (body, '/')))
) {
765 char *str;
766
767 if (!cid_name) {
768 cid_name = switch_channel_get_variable(client->channel, "caller_id_name")switch_channel_get_variable_dup(client->channel, "caller_id_name"
, SWITCH_TRUE, -1)
;
769 }
770 if (!cid_number) {
771 cid_number = switch_channel_get_variable(client->channel, "caller_id_number")switch_channel_get_variable_dup(client->channel, "caller_id_number"
, SWITCH_TRUE, -1)
;
772 }
773
774 str = switch_core_session_sprintf(client->session,
775 "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s", cid_name, cid_number, body);
776
777 switch_core_session_execute_application(client->session, "bridge", str)switch_core_session_execute_application_get_flags(client->
session, "bridge", str, ((void*)0))
;
778 } else {
779 if (!zstr(cid_name)_zstr(cid_name)) {
780 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 780, ((void*)0)
, SWITCH_LOG_INFO, "Changing Caller-ID Name to: %s\n", cid_name);
781 switch_channel_set_variable(client->channel, "effective_caller_id_name", cid_name)switch_channel_set_variable_var_check(client->channel, "effective_caller_id_name"
, cid_name, SWITCH_TRUE)
;
782 }
783 if (!zstr(cid_number)_zstr(cid_number)) {
784 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 784, ((void*)0)
, SWITCH_LOG_INFO, "Changing Caller-ID Number to: %s\n", cid_number);
785 switch_channel_set_variable(client->channel, "effective_caller_id_number", cid_number)switch_channel_set_variable_var_check(client->channel, "effective_caller_id_number"
, cid_number, SWITCH_TRUE)
;
786 }
787 switch_ivr_session_transfer(client->session, body, dp, context);
788 }
789
790 return SWITCH_STATUS_SUCCESS;
791}
792
793static switch_status_t parse_sms(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
794{
795 switch_event_t *event;
796 const char *from_proto = "httapi";
797 const char *to_proto = "sip";
798 const char *to = switch_xml_attr(tag, "to");
799
800 if (to && switch_event_create(&event, SWITCH_EVENT_MESSAGE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 800, &event, SWITCH_EVENT_MESSAGE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
801 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", from_proto);
802 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", to_proto);
803
804 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", switch_channel_get_variable(client->channel, "caller_id_number")switch_channel_get_variable_dup(client->channel, "caller_id_number"
, SWITCH_TRUE, -1)
);
805 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to);
806 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
807
808 if (body) {
809 switch_event_add_body(event, "%s", body);
810 }
811
812 switch_core_chat_send(to_proto, event);
813 } else {
814 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 814, ((void*)0)
, SWITCH_LOG_ERROR, "Missing 'to' Attribute!\n");
815 return SWITCH_STATUS_FALSE;
816 }
817
818 return SWITCH_STATUS_SUCCESS;
819}
820
821static int check_app_perm(client_t *client, const char *app_name)
822{
823 if (!client->profile->perms.execute_apps) {
824 return 0;
825 }
826
827 return switch_event_check_permission_list(client->profile->dial_params.app_list, app_name);
828}
829
830static switch_status_t parse_execute(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
831{
832 const char *app_name = switch_xml_attr(tag, "application");
833 const char *data = switch_xml_attr(tag, "data");
834
835 if (zstr(data)_zstr(data)) data = body;
836
837 if (zstr(app_name)_zstr(app_name)) {
838 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 838, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid app\n");
839 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 839, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
840 return SWITCH_STATUS_FALSE;
841 }
842
843 if (!check_app_perm(client, app_name)) {
844 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 844, ((void*)0)
, SWITCH_LOG_ERROR, "Permission Denied!\n");
845 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 845, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
846 return SWITCH_STATUS_FALSE;
847 }
848
849 if (!client->profile->perms.expand_vars) {
850 const char *p;
851
852 for(p = data; p && *p; p++) {
853 if (*p == '$') {
854 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 854, ((void*)0)
, SWITCH_LOG_ERROR, "Expand Variables: Permission Denied!\n");
855 switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 855, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
856 return SWITCH_STATUS_FALSE;
857 }
858 }
859 }
860
861 switch_core_session_execute_application(client->session, app_name, data)switch_core_session_execute_application_get_flags(client->
session, app_name, data, ((void*)0))
;
862
863 return SWITCH_STATUS_SUCCESS;
864}
865
866static switch_status_t parse_hangup(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
867{
868 const char *cause_str = switch_xml_attr(tag, "cause");
869 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
870
871 if (zstr(cause_str)_zstr(cause_str)) {
872 cause_str = body;
873 }
874
875 if (!zstr(cause_str)_zstr(cause_str)) {
876 cause = switch_channel_str2cause(cause_str);
877 }
878
879 switch_channel_hangup(client->channel, cause)switch_channel_perform_hangup(client->channel, "mod_httapi.c"
, (const char *)__func__, 879, cause)
;
880
881 return SWITCH_STATUS_FALSE;
882}
883
884static switch_status_t parse_answer(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
885{
886
887 if (!strcasecmp(tag_name, "answer")) {
888 const char *conf = switch_xml_attr(tag, "is-conference");
889
890 if (conf && switch_true(conf)) {
891 switch_channel_set_flag(client->channel, CF_CONFERENCE)switch_channel_set_flag_value(client->channel, CF_CONFERENCE
, 1)
;
892 }
893
894 switch_channel_answer(client->channel)switch_channel_perform_answer(client->channel, "mod_httapi.c"
, (const char *)__func__, 894)
;
895 } else if (!strcasecmp(tag_name, "preAnswer")) {
896 switch_channel_pre_answer(client->channel)switch_channel_perform_pre_answer(client->channel, "mod_httapi.c"
, (const char *)__func__, 896)
;
897 } else if (!strcasecmp(tag_name, "ringReady")) {
898 switch_channel_ring_ready(client->channel)switch_channel_perform_ring_ready_value(client->channel, SWITCH_RING_READY_RINGING
, "mod_httapi.c", (const char *)__func__, 898)
;
899 }
900
901 return SWITCH_STATUS_FALSE;
902}
903
904static switch_status_t parse_record_call(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
905{
906 const char *limit_ = switch_xml_attr(tag, "limit");
907 const char *name = switch_xml_attr(tag, "name");
908 const char *action = switch_xml_attr(tag, "action");
909 const char *record_file;
910
911 int limit = 0;
912
913 if (client->record.file) {
914 return SWITCH_STATUS_SUCCESS;
915 }
916
917 if (zstr(name)_zstr(name)) name = "recorded_file";
918
919 if (!strncasecmp(name, "http://", 7)) {
920 record_file = name;
921 } else {
922 client->record.action = (char *) action;
923 client->record.name = (char *)name;
924 client->record.file = switch_core_session_sprintf(client->session, "%s%s%s.wav",
925 SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR"/", switch_core_session_get_uuid(client->session));
926 record_file = client->record.file;
927 }
928
929 if (limit_) {
930 limit = atoi(limit_);
931 if (limit < 0) limit = 0;
932 }
933
934
935 switch_ivr_record_session(client->session, (char *)record_file, limit, NULL((void*)0));
936
937 return SWITCH_STATUS_SUCCESS;
938}
939
940static switch_status_t parse_record(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
941{
942 const char *file = switch_xml_attr(tag, "file");
943 const char *name = switch_xml_attr(tag, "name");
944 const char *error_file = switch_xml_attr(tag, "error-file");
945 const char *beep_file = switch_xml_attr(tag, "beep-file");
946 const char *action = switch_xml_attr(tag, "action");
947 const char *sub_action = NULL((void*)0);
948 const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout");
949 const char *terminators = switch_xml_attr(tag, "terminators");
950 char *loops_ = (char *) switch_xml_attr(tag, "loops");
951 int loops = 0;
952 switch_status_t status = SWITCH_STATUS_SUCCESS;
953 switch_ivr_dmachine_t *dmachine = NULL((void*)0);
954 switch_input_args_t *args = NULL((void*)0), myargs = { 0 };
955 long digit_timeout = 1500;
956 long tmp;
957 int thresh = 200;
958 int silence_hits = 2;
959 int record_limit = 0;
960 char *tmp_record_path = NULL((void*)0);
961 const char *v;
962 int rtmp;
963 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1];
964 char *fname = NULL((void*)0);
965 char *p, *ext = "wav";
966 switch_xml_t bind;
967 action_binding_t *top_action_binding = NULL((void*)0);
968 int http = 0;
969
970 switch_uuid_str(uuid_str, sizeof(uuid_str));
971
972 if (zstr(name)_zstr(name)) name = "attached_file";
1
Taking false branch
973
974 if (zstr(file)_zstr(file)) {
2
Taking false branch
975 return SWITCH_STATUS_FALSE;
976 }
977
978 fname = switch_core_strdup(client->pool, file)switch_core_perform_strdup(client->pool, file, "mod_httapi.c"
, (const char *)__func__, 978)
;
3
Value assigned to 'fname'
979
980 for(p = fname; p && *p; p++) {
4
Assuming pointer value is null
981 if (*p == '/' || *p == '\\' || *p == '`') {
982 *p = '_';
983 }
984 }
985
986 if ((p = strrchr(fname, '.'))) {
5
Null pointer passed as an argument to a 'nonnull' parameter
987 *p++ = '\0';
988 ext = p;
989 }
990
991 for(p = fname; p && *p; p++) {
992 if (*p == '.') {
993 *p = '_';
994 }
995 }
996
997 if (!strncasecmp(fname, "http://", 7)) {
998 tmp_record_path = fname;
999 http = 1;
1000 } else {
1001 tmp_record_path = switch_core_sprintf(client->pool, "%s%s%s_%s.%s",
1002 SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR"/", uuid_str, fname, ext);
1003 }
1004
1005 if ((v = switch_xml_attr(tag, "limit"))) {
1006 if ((rtmp = atoi(v)) > -1) {
1007 record_limit = rtmp;
1008 }
1009 }
1010
1011 if ((v = switch_xml_attr(tag, "silence-hits"))) {
1012 if ((rtmp = atoi(v)) > -1) {
1013 silence_hits = rtmp;
1014 }
1015 }
1016
1017 if ((v = switch_xml_attr(tag, "threshold"))) {
1018 if ((rtmp = atoi(v)) > -1) {
1019 thresh = rtmp;
1020 }
1021 }
1022
1023 if (loops_) {
1024 loops = atoi(loops_);
1025
1026 if (loops < 0) {
1027 loops = -1;
1028 }
1029 }
1030
1031 if (digit_timeout_) {
1032 tmp = atol(digit_timeout_);
1033
1034 if (tmp > 0) {
1035 digit_timeout = tmp;
1036 } else {
1037 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1037, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid digit timeout [%s]\n", digit_timeout_);
1038 }
1039 }
1040
1041 if ((bind = switch_xml_child(tag, "bind"))) {
1042 action_binding_t *action_binding;
1043 const char *realm = "default";
1044
1045 top_action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding))switch_core_perform_session_alloc(client->session, sizeof(
*action_binding), "mod_httapi.c", (const char *)__func__, 1045
)
;
1046 top_action_binding->client = client;
1047 top_action_binding->action = (char *) action;
1048 top_action_binding->error_file = (char *)error_file;
1049
1050 switch_ivr_dmachine_create(&dmachine, "HTTAPI", NULL((void*)0), digit_timeout, 0,
1051 NULL((void*)0), digit_nomatch_action_callback, top_action_binding);
1052
1053 while(bind) {
1054 action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding))switch_core_perform_session_alloc(client->session, sizeof(
*action_binding), "mod_httapi.c", (const char *)__func__, 1054
)
;
1055 action_binding->realm = (char *) realm;
1056 action_binding->input = bind->txt;
1057 action_binding->client = client;
1058 action_binding->action = (char *) switch_xml_attr(bind, "action");
1059 action_binding->error_file = (char *) error_file;
1060 action_binding->parent = top_action_binding;
1061
1062 switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
1063 bind = bind->next;
1064 }
1065
1066 switch_ivr_dmachine_set_realm(dmachine, realm);
1067 if (!zstr(terminators)_zstr(terminators)) {
1068 switch_ivr_dmachine_set_terminators(dmachine, terminators);
1069 }
1070
1071 myargs.dmachine = dmachine;
1072 args = &myargs;
1073 }
1074
1075 if (beep_file) {
1076 status = switch_ivr_play_file(client->session, NULL((void*)0), beep_file, args);
1077 }
1078
1079 if (!switch_channel_ready(client->channel)switch_channel_test_ready(client->channel, SWITCH_TRUE, SWITCH_FALSE
)
) {
1080 goto end;
1081 }
1082
1083 if (status == SWITCH_STATUS_SUCCESS) {
1084 switch_file_handle_t fh = { 0 };
1085 fh.thresh = thresh;
1086 fh.silence_hits = silence_hits;
1087
1088 status = switch_ivr_record_file(client->session, &fh, tmp_record_path, args, record_limit);
1089 }
1090
1091 if (switch_channel_ready(client->channel)switch_channel_test_ready(client->channel, SWITCH_TRUE, SWITCH_FALSE
)
) {
1092 status = SWITCH_STATUS_SUCCESS;
1093 }
1094
1095 if (client->matching_action_binding) {
1096 if (client->matching_action_binding->action) {
1097 sub_action = client->matching_action_binding->action;
1098 } else if (client->matching_action_binding->parent && client->matching_action_binding->parent->action) {
1099 sub_action = client->matching_action_binding->parent->action;
1100 }
1101 }
1102
1103 if (!sub_action && top_action_binding && top_action_binding->action) {
1104 sub_action = top_action_binding->action;
1105 }
1106
1107 if (sub_action) {
1108 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", sub_action);
1109 }
1110
1111 if (!http && !zstr(tmp_record_path)_zstr(tmp_record_path) && switch_file_exists(tmp_record_path, client->pool) == SWITCH_STATUS_SUCCESS) {
1112 char *key = switch_core_sprintf(client->pool, "attach_file:%s:%s.%s", name, fname, ext);
1113 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, key, tmp_record_path);
1114 }
1115
1116 end:
1117
1118 if (dmachine) {
1119 switch_ivr_dmachine_destroy(&dmachine);
1120 }
1121
1122 return status;
1123}
1124
1125static switch_status_t parse_common(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
1126{
1127 const char *action = switch_xml_attr(tag, "action");
1128 const char *tmp_action = switch_xml_attr(tag, "temp-action");
1129
1130 if (action) {
1131 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", action);
1132 }
1133
1134 if (tmp_action) {
1135 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", tmp_action);
1136 }
1137
1138 return SWITCH_STATUS_SUCCESS;
1139}
1140
1141static switch_status_t parse_xml(client_t *client)
1142{
1143 switch_status_t status = SWITCH_STATUS_FALSE;
1144 const void *bdata;
1145 switch_size_t len;
1146 int runs = 0;
1147
1148 if ((len = switch_buffer_peek_zerocopy(client->buffer, &bdata)) && switch_buffer_len(client->buffer) > len) {
1149 switch_xml_t xml, tag, category;
1150
1151 if (globals.debug) {
1152 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1152, ((void*)0)
, SWITCH_LOG_CRIT, "Debugging Return Data:\n%s\n", (char *)bdata);
1153 }
1154
1155 if ((xml = switch_xml_parse_str((char *)bdata, len))) {
1156
1157 if (client->profile->perms.set_params) {
1158 if ((category = switch_xml_child(xml, "params"))) {
1159 tag = category->child;
1160
1161 while(tag) {
1162 if (!zstr(tag->name)_zstr(tag->name)) {
1163 char *val = tag->txt;
1164 if (zstr(val)_zstr(val)) {
1165 val = NULL((void*)0);
1166 }
1167 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, tag->name, val);
1168 }
1169 tag = tag->ordered;
1170 }
1171 }
1172 }
1173
1174 if (client->profile->perms.set_vars) {
1175 if ((category = switch_xml_child(xml, "variables"))) {
1176 tag = category->child;
1177
1178 while(tag) {
1179 if (!zstr(tag->name)_zstr(tag->name)) {
1180 char *val = tag->txt;
1181 if (zstr(val)_zstr(val)) {
1182 val = NULL((void*)0);
1183 }
1184
1185 if (client->profile->perms.set_vars &&
1186 (!client->profile->var_params.set_var_list ||
1187 switch_event_check_permission_list(client->profile->var_params.set_var_list, tag->name))) {
1188 switch_channel_set_variable(client->channel, tag->name, val)switch_channel_set_variable_var_check(client->channel, tag
->name, val, SWITCH_TRUE)
;
1189 } else {
1190 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1190, ((void*)0)
, SWITCH_LOG_ERROR, "variable %s permission denied!\n", tag->name);
1191 }
1192 }
1193 tag = tag->ordered;
1194 }
1195 }
1196 }
1197
1198 if ((category = switch_xml_child(xml, "work"))) {
1199
1200 tag = category->child;
1201 status = SWITCH_STATUS_SUCCESS;
1202
1203 while(status == SWITCH_STATUS_SUCCESS && tag) {
1204 if (!zstr(tag->name)_zstr(tag->name)) {
1205 tag_parse_t handler;
1206
1207 if ((handler = (tag_parse_t)(intptr_t) switch_core_hash_find(globals.parse_hash, tag->name))) {
1208 char *expanded = tag->txt;
1209 switch_event_t *templ_data;
1210
1211 if (tag->txt && client->profile->perms.expand_vars) {
1212 switch_channel_get_variables(client->channel, &templ_data);
1213 switch_event_merge(templ_data, client->params);
1214 expanded = switch_event_expand_headers_check(templ_data, tag->txt,
1215 client->profile->var_params.expand_var_list,
1216 client->profile->var_params.api_list, 0);
1217 switch_event_destroy(&templ_data);
1218 }
1219
1220 runs++;
1221 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1221, ((void*)0)
, SWITCH_LOG_DEBUG, "Process Tag: [%s]\n", tag->name);
1222
1223 parse_common(tag->name, client, tag, expanded);
1224 status = handler(tag->name, client, tag, expanded);
1225
1226 if (expanded && expanded != tag->txt) {
1227 free(expanded);
1228 }
1229
1230 } else {
1231 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1231, ((void*)0)
, SWITCH_LOG_WARNING, "Unsupported Tag: [%s]\n", tag->name);
1232 status = SWITCH_STATUS_FALSE;
1233 }
1234
1235 }
1236 tag = tag->ordered;
1237 }
1238 }
1239
1240 if (!runs) {
1241 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1241, ((void*)0)
, SWITCH_LOG_WARNING, "No instructions found in result!\n");
1242 status = SWITCH_STATUS_FALSE;
1243 }
1244
1245
1246 switch_xml_free(xml);
1247 }
1248 }
1249
1250 return status;
1251}
1252
1253
1254static size_t get_header_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
1255{
1256 size_t realsize = (size * nmemb);
1257 char *val, *header = NULL((void*)0);
1258 client_t *client = userdata;
1259
1260 /* validate length... Apache and IIS won't send a header larger than 16 KB */
1261 if (realsize == 0 || realsize > 1024 * 16) {
1262 return realsize;
1263 }
1264
1265 /* get the header, adding NULL terminator if there isn't one */
1266 switch_zmalloc(header, realsize + 1)(void)((((header = calloc(1, (realsize + 1)))) ? (void) (0) :
__assert_fail ("(header = calloc(1, (realsize + 1)))", "mod_httapi.c"
, 1266, __PRETTY_FUNCTION__)),header)
;
1267 strncpy(header, (char *)ptr, realsize)__builtin_strncpy (header, (char *)ptr, realsize);
1268
1269 if ((val = strchr(header, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(header) && (':') == '\0' ? (char *) __rawmemchr (header
, ':') : __builtin_strchr (header, ':')))
)) {
1270 char *cr;
1271 *val++ = '\0';
1272 while(*val == ' ') val++;
1273
1274 if ((cr = strchr(val, '\r')(__extension__ (__builtin_constant_p ('\r') && !__builtin_constant_p
(val) && ('\r') == '\0' ? (char *) __rawmemchr (val,
'\r') : __builtin_strchr (val, '\r')))
) || (cr = strchr(val, '\r')(__extension__ (__builtin_constant_p ('\r') && !__builtin_constant_p
(val) && ('\r') == '\0' ? (char *) __rawmemchr (val,
'\r') : __builtin_strchr (val, '\r')))
)) {
1275 *cr = '\0';
1276 }
1277
1278 switch_event_add_header_string(client->headers, SWITCH_STACK_BOTTOM, header, val);
1279 }
1280
1281 switch_safe_free(header)if (header) {free(header);header=((void*)0);};
1282 return realsize;
1283}
1284
1285
1286static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
1287{
1288 register unsigned int realsize = (unsigned int) (size * nmemb);
1289 client_t *client = data;
1290 char *zero = "\0";
1291
1292 client->bytes += realsize;
1293
1294 if (client->bytes > client->max_bytes - 1) {
1295 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1295, ((void*)0)
, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) client->bytes);
1296 client->err = 1;
1297 return 0;
1298 }
1299
1300 switch_buffer_write(client->buffer, ptr, realsize);
1301 switch_buffer_write(client->buffer, zero, 1);
1302
1303 return realsize;
1304}
1305
1306static void client_destroy(client_t **client)
1307{
1308 if (client && *client) {
1309 switch_memory_pool_t *pool;
1310
1311 switch_event_destroy(&(*client)->headers);
1312 switch_event_destroy(&(*client)->params);
1313 switch_event_destroy(&(*client)->one_time_params);
1314 switch_buffer_destroy(&(*client)->buffer);
1315
1316 pool = (*client)->pool;
1317 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_httapi.c"
, (const char *)__func__, 1317)
;
1318 }
1319}
1320
1321static void client_reset(client_t *client)
1322{
1323 if (client->headers) {
1324 switch_event_destroy(&client->headers);
1325 }
1326
1327 switch_event_destroy(&client->one_time_params);
1328 switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1328, &client->one_time_params
, SWITCH_EVENT_CLONE, ((void*)0))
;
1329 client->one_time_params->flags |= EF_UNIQ_HEADERS;
1330
1331 switch_event_create(&client->headers, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1331, &client->headers, SWITCH_EVENT_CLONE
, ((void*)0))
;
1332
1333
1334 switch_buffer_zero(client->buffer);
1335
1336 client->code = 0;
1337 client->err = 0;
1338 client->matching_action_binding = NULL((void*)0);
1339 client->no_matching_action_binding = NULL((void*)0);
1340}
1341
1342static client_t *client_create(switch_core_session_t *session, const char *profile_name, switch_event_t **params)
1343{
1344 client_t *client;
1345 switch_memory_pool_t *pool;
1346 client_profile_t *profile;
1347
1348 if (zstr(profile_name)_zstr(profile_name)) {
1349 profile_name = "default";
1350 }
1351
1352 profile = (client_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name);
1353
1354 if (!profile) {
1355 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1355, ((void*)0)
, SWITCH_LOG_ERROR, "Cannot find profile [%s]\n", profile_name);
1356 return NULL((void*)0);
1357 }
1358
1359 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_httapi.c"
, (const char *)__func__, 1359)
;
1360 client = switch_core_alloc(pool, sizeof(*client))switch_core_perform_alloc(pool, sizeof(*client), "mod_httapi.c"
, (const char *)__func__, 1360)
;
1361 client->pool = pool;
1362
1363 switch_event_create(&client->headers, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1363, &client->headers, SWITCH_EVENT_CLONE
, ((void*)0))
;
1364
1365 if (session) {
1366 client->session = session;
1367 client->channel = switch_core_session_get_channel(session);
1368 }
1369
1370
1371 client->profile = profile;
1372
1373 client->max_bytes = HTTAPI_MAX_API_BYTES1024 * 1024;
1374
1375 switch_buffer_create_dynamic(&client->buffer, 1024, 1024, 0);
1376
1377 if (params && *params) {
1378 client->params = *params;
1379 *params = NULL((void*)0);
1380 } else {
1381 switch_event_create(&client->params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1381, &client->params, SWITCH_EVENT_CLONE
, ((void*)0))
;
1382 client->params->flags |= EF_UNIQ_HEADERS;
1383 }
1384
1385 switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1385, &client->one_time_params
, SWITCH_EVENT_CLONE, ((void*)0))
;
1386 client->one_time_params->flags |= EF_UNIQ_HEADERS;
1387
1388 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "hostname", switch_core_get_switchname());
1389
1390 return client;
1391}
1392
1393
1394static void cleanup_attachments(client_t *client)
1395{
1396 switch_event_header_t *hp;
1397
1398 for (hp = client->params->headers; hp; hp = hp->next) {
1399 if (!strncasecmp(hp->name, "attach_file:", 12)) {
1400 if (switch_file_exists(hp->value, client->pool) == SWITCH_STATUS_SUCCESS) {
1401 unlink(hp->value);
1402 }
1403 }
1404 }
1405}
1406
1407size_t put_file_read( void *ptr, size_t size, size_t nmemb, void *userdata)
1408{
1409 return fread(ptr, size, nmemb, (FILE *) userdata);
1410}
1411
1412static switch_status_t httapi_sync(client_t *client)
1413
1414{
1415 switch_CURL *curl_handle = NULL((void*)0);
1416 char *data = NULL((void*)0);
1417 switch_curl_slist_t *headers = NULL((void*)0);
1418 char *url = NULL((void*)0);
1419 char *dynamic_url = NULL((void*)0), *use_url = NULL((void*)0);
1420 const char *session_id = NULL((void*)0);
1421 switch_status_t status = SWITCH_STATUS_FALSE;
1422 int get_style_method = 0;
1423 char *method = NULL((void*)0);
1424 struct curl_httppost *formpost=NULL((void*)0);
1425 switch_event_t *save_params = NULL((void*)0);
1426 const char *put_file;
1427 FILE *fd = NULL((void*)0);
1428 char *creds, *dup_creds = NULL((void*)0), *ua = NULL((void*)0);
1429
1430
1431 if (client->one_time_params && client->one_time_params->headers) {
1432 save_params = client->params;
1433 switch_event_dup(&client->params, save_params);
1434 switch_event_merge(client->params, client->one_time_params);
1435 switch_event_destroy(&client->one_time_params);
1436 switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1436, &client->one_time_params
, SWITCH_EVENT_CLONE, ((void*)0))
;
1437 client->one_time_params->flags |= EF_UNIQ_HEADERS;
1438 }
1439
1440
1441 ua = switch_event_get_header(client->params, "user_agent")switch_event_get_header_idx(client->params, "user_agent", -
1)
;
1442
1443 if (zstr(ua)_zstr(ua)) {
1444 ua = client->profile->ua;
1445 }
1446
1447 if (!(session_id = switch_event_get_header(client->params, "HTTAPI_SESSION_ID")switch_event_get_header_idx(client->params, "HTTAPI_SESSION_ID"
, -1)
)) {
1448 if (client->channel && !(session_id = switch_channel_get_variable(client->channel, "HTTAPI_SESSION_ID")switch_channel_get_variable_dup(client->channel, "HTTAPI_SESSION_ID"
, SWITCH_TRUE, -1)
)) {
1449 session_id = switch_core_session_get_uuid(client->session);
1450 }
1451 }
1452
1453 if (client->code || client->err) {
1454 client_reset(client);
1455 }
1456
1457
1458 if (!(method = switch_event_get_header(client->params, "method")switch_event_get_header_idx(client->params, "method", -1))) {
1459 method = client->profile->method;
1460 }
1461
1462 if (!(url = switch_event_get_header(client->params, "url")switch_event_get_header_idx(client->params, "url", -1))) {
1463 url = client->profile->url;
1464 switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", url);
1465 }
1466
1467 get_style_method = method ? strcasecmp(method, "post") : 1;
1468
1469 switch_event_add_header_string(client->params, SWITCH_STACK_TOP, "session_id", session_id);
1470
1471 dynamic_url = switch_event_expand_headers(client->params, url)switch_event_expand_headers_check(client->params, url, ((void
*)0), ((void*)0), 0)
;
1472
1473 if ((put_file = switch_event_get_header(client->params, "put_file")switch_event_get_header_idx(client->params, "put_file", -1
)
)) {
1474 if (!(fd = fopen(put_file, "rb"))) {
1475 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1475, ((void*)0)
, SWITCH_LOG_CRIT, "Can't open [%s]\n", put_file);
1476 put_file = NULL((void*)0);
1477 }
1478 }
1479
1480 if (!put_file) {
1481 switch_curl_process_form_post_params(client->params, curl_handle, &formpost);
1482 }
1483
1484 if (formpost) {
1485 get_style_method = 1;
1486 } else {
1487 data = switch_event_build_param_string(client->params, NULL((void*)0), client->profile->vars_map);
1488 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_httapi.c",
1488, __PRETTY_FUNCTION__))
;
1489
1490 if (get_style_method) {
1491 char *tmp = switch_mprintf("%s%c%s", dynamic_url, strchr(dynamic_url, '?')(__extension__ (__builtin_constant_p ('?') && !__builtin_constant_p
(dynamic_url) && ('?') == '\0' ? (char *) __rawmemchr
(dynamic_url, '?') : __builtin_strchr (dynamic_url, '?')))
!= NULL((void*)0) ? '&' : '?', data);
1492
1493 if (dynamic_url != url) {
1494 free(dynamic_url);
1495 }
1496
1497 dynamic_url = tmp;
1498 }
1499 }
1500
1501
1502 if ((use_url = strchr(dynamic_url, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dynamic_url) && ('@') == '\0' ? (char *) __rawmemchr
(dynamic_url, '@') : __builtin_strchr (dynamic_url, '@')))
)) {
1503 char *r, *q, *p = strstr(dynamic_url, "://");
1504 use_url++;
1505
1506 if (p) {
1507 dup_creds = strdup(p+3)(__extension__ (__builtin_constant_p (p+3) && ((size_t
)(const void *)((p+3) + 1) - (size_t)(const void *)(p+3) == 1
) ? (((const char *) (p+3))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (p+3) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, p+3, __len); __retval
; })) : __strdup (p+3)))
;
1508
1509 if ((q = strchr(dup_creds, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup_creds) && ('@') == '\0' ? (char *) __rawmemchr (
dup_creds, '@') : __builtin_strchr (dup_creds, '@')))
)) *q = '\0';
1510
1511 q = strdup(url)(__extension__ (__builtin_constant_p (url) && ((size_t
)(const void *)((url) + 1) - (size_t)(const void *)(url) == 1
) ? (((const char *) (url))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (url) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, url, __len); __retval
; })) : __strdup (url)))
;
1512
1513 if (q) {
1514 r = strchr(q, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(q) && ('@') == '\0' ? (char *) __rawmemchr (q, '@')
: __builtin_strchr (q, '@')))
;
1515
1516 if (r) {
1517 r++;
1518
1519 if ((p = strstr(q, "://"))) {
1520 *(p+3) = '\0';
1521 }
1522
1523 p = switch_mprintf("%s%s", q, r);
1524 if (p) {
1525 free(dynamic_url);
1526 dynamic_url = p;
1527 }
1528 }
1529 free(q);
1530 }
1531 }
1532 }
1533
1534
1535 if ((use_url = strchr(dynamic_url, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dynamic_url) && ('@') == '\0' ? (char *) __rawmemchr
(dynamic_url, '@') : __builtin_strchr (dynamic_url, '@')))
)) {
1536 char *q, *p = strstr(dynamic_url, "://");
1537 use_url++;
1538
1539 dup_creds = strdup(p+3)(__extension__ (__builtin_constant_p (p+3) && ((size_t
)(const void *)((p+3) + 1) - (size_t)(const void *)(p+3) == 1
) ? (((const char *) (p+3))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (p+3) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, p+3, __len); __retval
; })) : __strdup (p+3)))
;
1540 *p = '\0';
1541
1542 if ((q = strchr(dup_creds, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup_creds) && ('@') == '\0' ? (char *) __rawmemchr (
dup_creds, '@') : __builtin_strchr (dup_creds, '@')))
)) *q = '\0';
1543
1544 creds = dup_creds;
1545
1546 p = switch_mprintf("%s%s", p, use_url);
1547 free(dynamic_url);
1548 dynamic_url = p;
1549 } else {
1550 creds = client->profile->cred;
1551 }
1552
1553 curl_handle = switch_curl_easy_init();
1554
1555 if (session_id) {
1556 char *hval = switch_mprintf("HTTAPI_SESSION_ID=%s", session_id);
1557 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIE, hval)curl_easy_setopt(curl_handle,CURLOPT_COOKIE,hval);
1558 free(hval);
1559 }
1560
1561 if (!strncasecmp(dynamic_url, "https", 5)) {
1562 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
1563 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
1564 }
1565
1566
1567 if (!zstr(creds)_zstr(creds)) {
1568 switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, client->profile->auth_scheme)curl_easy_setopt(curl_handle,CURLOPT_HTTPAUTH,client->profile
->auth_scheme)
;
1569 switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, creds)curl_easy_setopt(curl_handle,CURLOPT_USERPWD,creds);
1570 }
1571
1572 if (client->profile->disable100continue) {
1573 headers = switch_curl_slist_append(headers, "Expect:");
1574 }
1575
1576 if (client->profile->enable_cacert_check) {
1577 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,(!0));
1578 }
1579
1580 switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers)curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER,headers);
1581
1582 if (!zstr(method)_zstr(method)) {
1583 switch_curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, method)curl_easy_setopt(curl_handle,CURLOPT_CUSTOMREQUEST,method);
1584 }
1585
1586 if (put_file) {
1587 curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L)curl_easy_setopt(curl_handle,CURLOPT_UPLOAD,1L);
1588 curl_easy_setopt(curl_handle, CURLOPT_READDATA, fd)curl_easy_setopt(curl_handle,CURLOPT_READDATA,fd);
1589 curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, put_file_read)curl_easy_setopt(curl_handle,CURLOPT_READFUNCTION,put_file_read
)
;
1590
1591 } else if (formpost) {
1592 curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, formpost)curl_easy_setopt(curl_handle,CURLOPT_HTTPPOST,formpost);
1593 } else {
1594 switch_curl_easy_setopt(curl_handle, CURLOPT_POST, !get_style_method)curl_easy_setopt(curl_handle,CURLOPT_POST,!get_style_method);
1595 }
1596
1597 switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1)curl_easy_setopt(curl_handle,CURLOPT_FOLLOWLOCATION,1);
1598 switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10)curl_easy_setopt(curl_handle,CURLOPT_MAXREDIRS,10);
1599
1600 if (!get_style_method && !formpost) {
1601 switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data)curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,data);
1602 }
1603
1604 switch_curl_easy_setopt(curl_handle, CURLOPT_URL, dynamic_url)curl_easy_setopt(curl_handle,CURLOPT_URL,dynamic_url);
1605 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback)curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,file_callback
)
;
1606 switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback)curl_easy_setopt(curl_handle,CURLOPT_HEADERFUNCTION,get_header_callback
)
;
1607 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client)curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *) client
)
;
1608 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client)curl_easy_setopt(curl_handle,CURLOPT_HEADERDATA,(void *) client
)
;
1609 switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua)curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,ua);
1610 switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1)curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL,1);
1611
1612 if (client->profile->timeout) {
1613 switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout)curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,client->profile
->timeout)
;
1614 }
1615
1616 if (client->profile->ssl_cert_file) {
1617 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, client->profile->ssl_cert_file)curl_easy_setopt(curl_handle,CURLOPT_SSLCERT,client->profile
->ssl_cert_file)
;
1618 }
1619
1620 if (client->profile->ssl_key_file) {
1621 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, client->profile->ssl_key_file)curl_easy_setopt(curl_handle,CURLOPT_SSLKEY,client->profile
->ssl_key_file)
;
1622 }
1623
1624 if (client->profile->ssl_key_password) {
1625 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, client->profile->ssl_key_password)curl_easy_setopt(curl_handle,CURLOPT_KEYPASSWD,client->profile
->ssl_key_password)
;
1626 }
1627
1628 if (client->profile->ssl_version) {
1629 if (!strcasecmp(client->profile->ssl_version, "SSLv3")) {
1630 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_SSLv3
)
;
1631#ifdef CURL_SSLVERSION_TLSv1_1
1632 } else if (!strcasecmp(client->profile->ssl_version, "TLSv1.1")) {
1633 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1_1
)
;
1634#endif
1635#ifdef CURL_SSLVERSION_TLSv1_2
1636 } else if (!strcasecmp(client->profile->ssl_version, "TLSv1.2")) {
1637 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1_2
)
;
1638#endif
1639 }
1640 } else {
1641 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1
)
;
1642 }
1643
1644
1645 if (client->profile->ssl_cacert_file) {
1646 switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, client->profile->ssl_cacert_file)curl_easy_setopt(curl_handle,CURLOPT_CAINFO,client->profile
->ssl_cacert_file)
;
1647 }
1648
1649 if (client->profile->enable_ssl_verifyhost) {
1650 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,2);
1651 }
1652
1653 if (client->profile->cookie_file) {
1654 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, client->profile->cookie_file)curl_easy_setopt(curl_handle,CURLOPT_COOKIEJAR,client->profile
->cookie_file)
;
1655 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, client->profile->cookie_file)curl_easy_setopt(curl_handle,CURLOPT_COOKIEFILE,client->profile
->cookie_file)
;
1656 } else {
1657 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIE, "")curl_easy_setopt(curl_handle,CURLOPT_COOKIE,"");
1658 }
1659
1660 if (client->profile->bind_local) {
1661 curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local)curl_easy_setopt(curl_handle,CURLOPT_INTERFACE,client->profile
->bind_local)
;
1662 }
1663
1664
1665 switch_curl_easy_perform(curl_handle);
1666 switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &client->code);
1667 switch_curl_easy_cleanup(curl_handle);
1668 switch_curl_slist_free_all(headers);
1669
1670 if (formpost) {
1671 curl_formfree(formpost);
1672 }
1673
1674 if (client->err) {
1675 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1675, ((void*)0)
, SWITCH_LOG_ERROR, "Error encountered! [%s]\ndata: [%s]\n", client->profile->url, data);
1676 status = SWITCH_STATUS_FALSE;
1677 } else {
1678 status = SWITCH_STATUS_SUCCESS;
1679 }
1680
1681 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1682 switch_safe_free(dup_creds)if (dup_creds) {free(dup_creds);dup_creds=((void*)0);};
1683
1684 if (dynamic_url != url) {
1685 switch_safe_free(dynamic_url)if (dynamic_url) {free(dynamic_url);dynamic_url=((void*)0);};
1686 }
1687
1688 cleanup_attachments(client);
1689
1690 if (save_params) {
1691 switch_event_destroy(&client->params);
1692 client->params = save_params;
1693 save_params = NULL((void*)0);
1694 }
1695
1696 if (fd) {
1697 fclose(fd);
1698 }
1699
1700 return status;
1701}
1702
1703#define ENABLE_PARAM_VALUE"enabled" "enabled"
1704static switch_status_t do_config(void)
1705{
1706 char *cf = "httapi.conf";
1707 switch_xml_t cfg, xml, profiles_tag, profile_tag, param, settings, tag;
1708 client_profile_t *profile = NULL((void*)0);
1709 int x = 0;
1710 int need_vars_map = 0;
1711 switch_hash_t *vars_map = NULL((void*)0);
1712
1713 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL((void*)0)))) {
1714 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1714, ((void*)0)
, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
1715 return SWITCH_STATUS_TERM;
1716 }
1717
1718 if ((settings = switch_xml_child(cfg, "settings"))) {
1719 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
1720 char *var = (char *) switch_xml_attr_soft(param, "name");
1721 char *val = (char *) switch_xml_attr_soft(param, "value");
1722
1723 if (!strcasecmp(var, "debug")) {
1724 globals.debug = switch_true(val);
1725 } else if (!strcasecmp(var, "file-cache-ttl")) {
1726 int tmp = atoi(val);
1727
1728 if (tmp > -1) {
1729 globals.cache_ttl = tmp;
1730 } else {
1731 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1731, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid value [%s]for file-cache-ttl\n", val);
1732 }
1733 } else if (!strcasecmp(var, "abs-file-cache-ttl")) {
1734 int tmp = atoi(val);
1735
1736 if (tmp > -1) {
1737 globals.abs_cache_ttl = tmp;
1738 } else {
1739 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1739, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid value [%s]for file-cache-ttl\n", val);
1740 }
1741
1742 } else if (!strcasecmp(var, "file-not-found-expires")) {
1743 globals.not_found_expires = atoi(val);
1744
1745 if (globals.not_found_expires < 0) {
1746 globals.not_found_expires = -1;
1747 }
1748 }
1749 }
1750 }
1751
1752 if (!(profiles_tag = switch_xml_child(cfg, "profiles"))) {
1753 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1753, ((void*)0)
, SWITCH_LOG_ERROR, "Missing <profiles> tag!\n");
1754 goto done;
1755 }
1756
1757 for (profile_tag = switch_xml_child(profiles_tag, "profile"); profile_tag; profile_tag = profile_tag->next) {
1758 char *bname = (char *) switch_xml_attr_soft(profile_tag, "name");
1759 char *url = NULL((void*)0);
1760 char *bind_local = NULL((void*)0);
1761 char *bind_cred = NULL((void*)0);
1762 char *method = NULL((void*)0);
1763 int disable100continue = 1;
1764 int timeout = 0;
1765 uint32_t enable_cacert_check = 0;
1766 char *ssl_cert_file = NULL((void*)0);
1767 char *ssl_key_file = NULL((void*)0);
1768 char *ssl_key_password = NULL((void*)0);
1769 char *ssl_version = NULL((void*)0);
1770 char *ssl_cacert_file = NULL((void*)0);
1771 uint32_t enable_ssl_verifyhost = 0;
1772 char *cookie_file = NULL((void*)0);
1773 char *ua = "mod_httapi/1.0";
1774 hash_node_t *hash_node;
1775 long auth_scheme = CURLAUTH_BASIC(((unsigned long)1)<<0);
1776 need_vars_map = 0;
1777 vars_map = NULL((void*)0);
1778
1779 if (zstr(bname)_zstr(bname)) {
1780 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1780, ((void*)0)
, SWITCH_LOG_ERROR, "profile tag missing name field!\n");
1781 continue;
1782 }
1783
1784 if (switch_core_hash_find(globals.profile_hash, bname)) {
1785 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1785, ((void*)0)
, SWITCH_LOG_ERROR, "Profile %s already exists\n", (char *)bname);
1786 continue;
1787 }
1788
1789 if ((tag = switch_xml_child(profile_tag, "params"))) {
1790 for (param = switch_xml_child(tag, "param"); param; param = param->next) {
1791 char *var = (char *) switch_xml_attr_soft(param, "name");
1792 char *val = (char *) switch_xml_attr_soft(param, "value");
1793
1794 if (!strcasecmp(var, "gateway-url")) {
1795 if (val) {
1796 url = val;
1797 }
1798 } else if (!strcasecmp(var, "user-agent")) {
1799 ua = val;
1800 } else if (!strcasecmp(var, "gateway-credentials")) {
1801 bind_cred = val;
1802 } else if (!strcasecmp(var, "auth-scheme")) {
1803 if (*val == '=') {
1804 auth_scheme = 0;
1805 val++;
1806 }
1807
1808 if (!strcasecmp(val, "basic")) {
1809 auth_scheme |= CURLAUTH_BASIC(((unsigned long)1)<<0);
1810 } else if (!strcasecmp(val, "digest")) {
1811 auth_scheme |= CURLAUTH_DIGEST(((unsigned long)1)<<1);
1812 } else if (!strcasecmp(val, "NTLM")) {
1813 auth_scheme |= CURLAUTH_NTLM(((unsigned long)1)<<3);
1814 } else if (!strcasecmp(val, "GSS-NEGOTIATE")) {
1815 auth_scheme |= CURLAUTH_GSSNEGOTIATE(((unsigned long)1)<<2);
1816 } else if (!strcasecmp(val, "any")) {
1817 auth_scheme = (long)CURLAUTH_ANY(~(((unsigned long)1)<<4));
1818 }
1819 } else if (!strcasecmp(var, "disable-100-continue") && !switch_true(val)) {
1820 disable100continue = 0;
1821 } else if (!strcasecmp(var, "method")) {
1822 method = val;
1823 } else if (!strcasecmp(var, "timeout")) {
1824 int tmp = atoi(val);
1825 if (tmp >= 0) {
1826 timeout = tmp;
1827 } else {
1828 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1828, ((void*)0)
, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
1829 }
1830 } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
1831 enable_cacert_check = 1;
1832 } else if (!strcasecmp(var, "ssl-cert-path")) {
1833 ssl_cert_file = val;
1834 } else if (!strcasecmp(var, "ssl-key-path")) {
1835 ssl_key_file = val;
1836 } else if (!strcasecmp(var, "ssl-key-password")) {
1837 ssl_key_password = val;
1838 } else if (!strcasecmp(var, "ssl-version")) {
1839 ssl_version = val;
1840 } else if (!strcasecmp(var, "ssl-cacert-file")) {
1841 ssl_cacert_file = val;
1842 } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) {
1843 enable_ssl_verifyhost = 1;
1844 } else if (!strcasecmp(var, "cookie-file")) {
1845 cookie_file = val;
1846 } else if (!strcasecmp(var, "enable-post-var")) {
1847 if (!vars_map && need_vars_map == 0) {
1848 if (switch_core_hash_init(&vars_map)switch_core_hash_init_case(&vars_map, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
1849 need_vars_map = -1;
1850 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1850, ((void*)0)
, SWITCH_LOG_WARNING, "Can't init params hash!\n");
1851 continue;
1852 }
1853 need_vars_map = 1;
1854 }
1855
1856 if (vars_map && val) {
1857 if (switch_core_hash_insert(vars_map, val, ENABLE_PARAM_VALUE)switch_core_hash_insert_destructor(vars_map, val, "enabled", (
(void*)0))
!= SWITCH_STATUS_SUCCESS) {
1858 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1858, ((void*)0)
, SWITCH_LOG_WARNING, "Can't add %s to params hash!\n", val);
1859 }
1860 }
1861 } else if (!strcasecmp(var, "bind-local")) {
1862 bind_local = val;
1863 }
1864 }
1865 }
1866
1867 if (!url) {
1868 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 1868, ((void*)0)
, SWITCH_LOG_ERROR, "Profile has no url!\n");
1869 if (vars_map)
1870 switch_core_hash_destroy(&vars_map);
1871 continue;
1872 }
1873
1874 if (!(profile = switch_core_alloc(globals.pool, sizeof(*profile))switch_core_perform_alloc(globals.pool, sizeof(*profile), "mod_httapi.c"
, (const char *)__func__, 1874)
)) {
1875 if (vars_map)
1876 switch_core_hash_destroy(&vars_map);
1877 goto done;
1878 }
1879 memset(profile, 0, sizeof(*profile));
1880
1881
1882 /* Defaults */
1883 profile->ua = ua;
1884 profile->conference_params.use_profile = "default";
1885 profile->perms.set_params = 1;
1886 profile->perms.conference.enabled = 1;
1887 profile->perms.dial.enabled = 1;
1888
1889
1890 if ((tag = switch_xml_child(profile_tag, "conference"))) {
1891 for (param = switch_xml_child(tag, "param"); param; param = param->next) {
1892 char *var = (char *) switch_xml_attr_soft(param, "name");
1893 char *val = (char *) switch_xml_attr_soft(param, "value");
1894
1895 if (!strcasecmp(var, "default-profile")) {
1896 profile->conference_params.use_profile = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_httapi.c",
(const char *)__func__, 1896)
;
1897 }
1898 }
1899 }
1900
1901 if ((tag = switch_xml_child(profile_tag, "dial"))) {
1902 for (param = switch_xml_child(tag, "param"); param; param = param->next) {
1903 char *var = (char *) switch_xml_attr_soft(param, "name");
1904 char *val = (char *) switch_xml_attr_soft(param, "value");
1905
1906 if (!strcasecmp(var, "context")) {
1907 profile->dial_params.context = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_httapi.c",
(const char *)__func__, 1907)
;
1908 } else if (!strcasecmp(var, "dialplan")) {
1909 profile->dial_params.dp = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_httapi.c",
(const char *)__func__, 1909)
;
1910 }
1911 }
1912 }
1913
1914 if ((tag = switch_xml_child(profile_tag, "permissions"))) {
1915 for (param = switch_xml_child(tag, "permission"); param; param = param->next) {
1916 char *var = (char *) switch_xml_attr_soft(param, "name");
1917 char *val = (char *) switch_xml_attr_soft(param, "value");
1918
1919 if (!strcasecmp(var, "all")) {
1920 switch_byte_t all = switch_true_byte(val);
1921 memset(&profile->perms, all, sizeof(profile->perms));
1922 } else if (!strcasecmp(var, "none")) {
1923 switch_byte_t none = switch_true_byte(val);
1924 memset(&profile->perms, none, sizeof(profile->perms));
1925 } else if (!strcasecmp(var, "set-params")) {
1926 profile->perms.set_params = switch_true_byte(val);
1927 } else if (!strcasecmp(var, "set-vars")) {
1928 profile->perms.set_vars = switch_true_byte(val);
1929
1930 if (profile->perms.set_vars) {
1931 switch_xml_t x_list, x_var;
1932 if ((x_list = switch_xml_child(param, "variable-list"))) {
1933 char *var = (char *) switch_xml_attr_soft(param, "default");
1934
1935 profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
1936 switch_event_create(&profile->var_params.set_var_list, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1936, &profile->var_params
.set_var_list, SWITCH_EVENT_CLONE, ((void*)0))
;
1937 profile->var_params.set_var_list->flags |= EF_UNIQ_HEADERS;
1938 if (profile->var_params.default_allow) {
1939 profile->var_params.set_var_list->flags |= EF_DEFAULT_ALLOW;
1940 }
1941
1942
1943 for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
1944 const char *name = switch_xml_attr(x_var, "name");
1945 const char *type = switch_xml_attr(x_var, "type");
1946
1947 if (zstr(type)_zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
1948
1949 if (name) {
1950 switch_event_add_header_string(profile->var_params.set_var_list, SWITCH_STACK_BOTTOM, name, type);
1951 }
1952 }
1953 }
1954 }
1955 } else if (!strcasecmp(var, "get-vars")) {
1956 profile->perms.get_vars = switch_true_byte(val);
1957
1958 if (profile->perms.get_vars) {
1959 switch_xml_t x_list, x_var;
1960 if ((x_list = switch_xml_child(param, "variable-list"))) {
1961 char *var = (char *) switch_xml_attr_soft(param, "default");
1962
1963 profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
1964 switch_event_create(&profile->var_params.get_var_list, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1964, &profile->var_params
.get_var_list, SWITCH_EVENT_CLONE, ((void*)0))
;
1965 profile->var_params.get_var_list->flags |= EF_UNIQ_HEADERS;
1966 if (profile->var_params.default_allow) {
1967 profile->var_params.get_var_list->flags |= EF_DEFAULT_ALLOW;
1968 }
1969
1970
1971 for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
1972 const char *name = switch_xml_attr(x_var, "name");
1973 const char *type = switch_xml_attr(x_var, "type");
1974
1975 if (zstr(type)_zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
1976
1977 if (name) {
1978 switch_event_add_header_string(profile->var_params.get_var_list, SWITCH_STACK_BOTTOM, name, type);
1979 }
1980 }
1981 }
1982 }
1983 } else if (!strcasecmp(var, "extended-data")) {
1984 profile->perms.extended_data = switch_true_byte(val);
1985 } else if (!strcasecmp(var, "execute-apps")) {
1986 profile->perms.execute_apps = switch_true_byte(val);
1987
1988 if (profile->perms.execute_apps) {
1989 switch_xml_t x_list, x_app;
1990 if ((x_list = switch_xml_child(param, "application-list"))) {
1991 char *var = (char *) switch_xml_attr_soft(param, "default");
1992
1993 profile->dial_params.default_allow = (var && !strcasecmp(var, "allow"));
1994 switch_event_create(&profile->dial_params.app_list, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 1994, &profile->dial_params
.app_list, SWITCH_EVENT_CLONE, ((void*)0))
;
1995 profile->dial_params.app_list->flags |= EF_UNIQ_HEADERS;
1996 if (profile->dial_params.default_allow) {
1997 profile->dial_params.app_list->flags |= EF_DEFAULT_ALLOW;
1998 }
1999
2000
2001 for (x_app = switch_xml_child(x_list, "application"); x_app; x_app = x_app->next) {
2002 const char *name = switch_xml_attr(x_app, "name");
2003 const char *type = switch_xml_attr(x_app, "type");
2004
2005 if (zstr(type)_zstr(type)) type = profile->dial_params.default_allow ? "deny" : "allow";
2006
2007 if (name) {
2008 switch_event_add_header_string(profile->dial_params.app_list, SWITCH_STACK_BOTTOM, name, type);
2009 }
2010 }
2011 }
2012 }
2013
2014 } else if (!strcasecmp(var, "expand-vars")) {
2015 profile->perms.expand_vars = switch_true_byte(val);
2016
2017 if (profile->perms.expand_vars) {
2018 switch_xml_t x_list, x_var, x_api;
2019 if ((x_list = switch_xml_child(param, "variable-list"))) {
2020 char *var = (char *) switch_xml_attr_soft(param, "default");
2021
2022 profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
2023 switch_event_create(&profile->var_params.expand_var_list, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 2023, &profile->var_params
.expand_var_list, SWITCH_EVENT_CLONE, ((void*)0))
;
2024 profile->var_params.expand_var_list->flags |= EF_UNIQ_HEADERS;
2025 if (profile->var_params.default_allow) {
2026 profile->var_params.expand_var_list->flags |= EF_DEFAULT_ALLOW;
2027 }
2028
2029
2030 for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
2031 const char *name = switch_xml_attr(x_var, "name");
2032 const char *type = switch_xml_attr(x_var, "type");
2033
2034 if (zstr(type)_zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
2035
2036 if (name) {
2037 switch_event_add_header_string(profile->var_params.expand_var_list, SWITCH_STACK_BOTTOM, name, type);
2038 }
2039 }
2040 }
2041
2042 if ((x_list = switch_xml_child(param, "api-list"))) {
2043 char *api = (char *) switch_xml_attr_soft(param, "default");
2044
2045 profile->var_params.default_allow = (api && !strcasecmp(api, "allow"));
2046 switch_event_create(&profile->var_params.api_list, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 2046, &profile->var_params
.api_list, SWITCH_EVENT_CLONE, ((void*)0))
;
2047 profile->var_params.api_list->flags |= EF_UNIQ_HEADERS;
2048 if (profile->var_params.default_allow) {
2049 profile->var_params.api_list->flags |= EF_DEFAULT_ALLOW;
2050 }
2051
2052
2053 for (x_api = switch_xml_child(x_list, "api"); x_api; x_api = x_api->next) {
2054 const char *name = switch_xml_attr(x_api, "name");
2055 const char *type = switch_xml_attr(x_api, "type");
2056
2057 if (zstr(type)_zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
2058
2059 if (name) {
2060 switch_event_add_header_string(profile->var_params.api_list, SWITCH_STACK_BOTTOM, name, type);
2061 }
2062 }
2063 }
2064 }
2065
2066 } else if (!strcasecmp(var, "dial")) {
2067 profile->perms.dial.enabled = switch_true_byte(val);
2068 } else if (!strcasecmp(var, "dial-set-context")) {
2069 if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE;
2070 profile->perms.dial.set_context = switch_true_byte(val);
2071 } else if (!strcasecmp(var, "dial-set-dialplan")) {
2072 if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE;
2073 profile->perms.dial.set_dp = switch_true_byte(val);
2074 } else if (!strcasecmp(var, "dial-set-cid-name")) {
2075 if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE;
2076 profile->perms.dial.set_cid_name = switch_true_byte(val);
2077 } else if (!strcasecmp(var, "dial-set-cid-number")) {
2078 if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE;
2079 profile->perms.dial.set_cid_number = switch_true_byte(val);
2080 } else if (!strcasecmp(var, "dial-full-originate")) {
2081 if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE;
2082 profile->perms.dial.full_originate = switch_true_byte(val);
2083 } else if (!strcasecmp(var, "conference")) {
2084 profile->perms.conference.enabled = switch_true_byte(val);
2085 } else if (!strcasecmp(var, "conference-set-profile")) {
2086 if (switch_true(val)) profile->perms.conference.enabled = SWITCH_TRUE;
2087 profile->perms.conference.set_profile = switch_true_byte(val);
2088 }
2089
2090 }
2091 }
2092
2093
2094
2095 profile->auth_scheme = auth_scheme;
2096 profile->timeout = timeout;
2097 profile->url = switch_core_strdup(globals.pool, url)switch_core_perform_strdup(globals.pool, url, "mod_httapi.c",
(const char *)__func__, 2097)
;
2098 switch_assert(profile->url)((profile->url) ? (void) (0) : __assert_fail ("profile->url"
, "mod_httapi.c", 2098, __PRETTY_FUNCTION__))
;
2099
2100 if (bind_local != NULL((void*)0)) {
2101 profile->bind_local = switch_core_strdup(globals.pool, bind_local)switch_core_perform_strdup(globals.pool, bind_local, "mod_httapi.c"
, (const char *)__func__, 2101)
;
2102 }
2103 if (method != NULL((void*)0)) {
2104 profile->method = switch_core_strdup(globals.pool, method)switch_core_perform_strdup(globals.pool, method, "mod_httapi.c"
, (const char *)__func__, 2104)
;
2105 } else {
2106 profile->method = NULL((void*)0);
2107 }
2108
2109 if (bind_cred) {
2110 profile->cred = switch_core_strdup(globals.pool, bind_cred)switch_core_perform_strdup(globals.pool, bind_cred, "mod_httapi.c"
, (const char *)__func__, 2110)
;
2111 }
2112
2113 profile->disable100continue = disable100continue;
2114 profile->enable_cacert_check = enable_cacert_check;
2115
2116 if (ssl_cert_file) {
2117 profile->ssl_cert_file = switch_core_strdup(globals.pool, ssl_cert_file)switch_core_perform_strdup(globals.pool, ssl_cert_file, "mod_httapi.c"
, (const char *)__func__, 2117)
;
2118 }
2119
2120 if (ssl_key_file) {
2121 profile->ssl_key_file = switch_core_strdup(globals.pool, ssl_key_file)switch_core_perform_strdup(globals.pool, ssl_key_file, "mod_httapi.c"
, (const char *)__func__, 2121)
;
2122 }
2123
2124 if (ssl_key_password) {
2125 profile->ssl_key_password = switch_core_strdup(globals.pool, ssl_key_password)switch_core_perform_strdup(globals.pool, ssl_key_password, "mod_httapi.c"
, (const char *)__func__, 2125)
;
2126 }
2127
2128 if (ssl_version) {
2129 profile->ssl_version = switch_core_strdup(globals.pool, ssl_version)switch_core_perform_strdup(globals.pool, ssl_version, "mod_httapi.c"
, (const char *)__func__, 2129)
;
2130 }
2131
2132 if (ssl_cacert_file) {
2133 profile->ssl_cacert_file = switch_core_strdup(globals.pool, ssl_cacert_file)switch_core_perform_strdup(globals.pool, ssl_cacert_file, "mod_httapi.c"
, (const char *)__func__, 2133)
;
2134 }
2135
2136 profile->enable_ssl_verifyhost = enable_ssl_verifyhost;
2137
2138 if (cookie_file) {
2139 profile->cookie_file = switch_core_strdup(globals.pool, cookie_file)switch_core_perform_strdup(globals.pool, cookie_file, "mod_httapi.c"
, (const char *)__func__, 2139)
;
2140 }
2141
2142 profile->vars_map = vars_map;
2143
2144 if (vars_map) {
2145 switch_zmalloc(hash_node, sizeof(hash_node_t))(void)((((hash_node = calloc(1, (sizeof(hash_node_t))))) ? (void
) (0) : __assert_fail ("(hash_node = calloc(1, (sizeof(hash_node_t))))"
, "mod_httapi.c", 2145, __PRETTY_FUNCTION__)),hash_node)
;
2146 hash_node->hash = vars_map;
2147 hash_node->next = NULL((void*)0);
2148
2149 if (!globals.hash_root) {
2150 globals.hash_root = hash_node;
2151 globals.hash_tail = globals.hash_root;
2152 }
2153
2154 else {
2155 globals.hash_tail->next = hash_node;
2156 globals.hash_tail = globals.hash_tail->next;
2157 }
2158
2159 }
2160
2161 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2161, ((void*)0)
, SWITCH_LOG_NOTICE, "Profile [%s] JSON Function [%s]\n",
2162 zstr(bname)_zstr(bname) ? "N/A" : bname, profile->url);
2163
2164 profile->name = switch_core_strdup(globals.pool, bname)switch_core_perform_strdup(globals.pool, bname, "mod_httapi.c"
, (const char *)__func__, 2164)
;
2165
2166 if (!globals.profile) globals.profile = profile;
2167
2168 switch_core_hash_insert(globals.profile_hash, bname, profile)switch_core_hash_insert_destructor(globals.profile_hash, bname
, profile, ((void*)0))
;
2169
2170 x++;
2171 profile = NULL((void*)0);
2172 }
2173
2174 done:
2175
2176 switch_xml_free(xml);
2177
2178 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
2179}
2180
2181static switch_status_t my_on_reporting(switch_core_session_t *session)
2182{
2183 switch_channel_t *channel = switch_core_session_get_channel(session);
2184 switch_status_t status = SWITCH_STATUS_SUCCESS;
2185 client_t *client;
2186 const char *var;
2187
2188 if (!(client = (client_t *) switch_channel_get_private(channel, "_HTTAPI_CLIENT_"))) {
2189 return status;
2190 }
2191
2192 switch_channel_set_private(channel, "_HTTAPI_CLIENT_", NULL((void*)0));
2193
2194 if (client->profile->perms.extended_data) {
2195 switch_channel_event_set_extended_data(channel, client->one_time_params);
2196 }
2197
2198 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "exiting", "true");
2199
2200 if (client->record.file) {
2201 char *key = switch_core_sprintf(client->pool, "attach_file:%s:%s.wav", client->record.name, switch_core_session_get_uuid(session));
2202 switch_ivr_stop_record_session(client->session, client->record.file);
2203 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, key, client->record.file);
2204 }
2205
2206 var = switch_event_get_header(client->params, "url")switch_event_get_header_idx(client->params, "url", -1);
2207
2208 if (client->record.action) {
2209 if (strcmp(var, client->record.action)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(var) && __builtin_constant_p (client->record.action
) && (__s1_len = __builtin_strlen (var), __s2_len = __builtin_strlen
(client->record.action), (!((size_t)(const void *)((var) +
1) - (size_t)(const void *)(var) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((client->record.action) + 1) - (
size_t)(const void *)(client->record.action) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (var, client->record.action)
: (__builtin_constant_p (var) && ((size_t)(const void
*)((var) + 1) - (size_t)(const void *)(var) == 1) &&
(__s1_len = __builtin_strlen (var), __s1_len < 4) ? (__builtin_constant_p
(client->record.action) && ((size_t)(const void *
)((client->record.action) + 1) - (size_t)(const void *)(client
->record.action) == 1) ? __builtin_strcmp (var, client->
record.action) : (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (client->record.action
); int __result = (((const unsigned char *) (const char *) (var
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (var)
)[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (var)
)[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (var))[
3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (client
->record.action) && ((size_t)(const void *)((client
->record.action) + 1) - (size_t)(const void *)(client->
record.action) == 1) && (__s2_len = __builtin_strlen (
client->record.action), __s2_len < 4) ? (__builtin_constant_p
(var) && ((size_t)(const void *)((var) + 1) - (size_t
)(const void *)(var) == 1) ? __builtin_strcmp (var, client->
record.action) : (- (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (var); int __result
= (((const unsigned char *) (const char *) (client->record
.action))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
client->record.action))[1] - __s2[1]); if (__s2_len > 1
&& __result == 0) { __result = (((const unsigned char
*) (const char *) (client->record.action))[2] - __s2[2]);
if (__s2_len > 2 && __result == 0) __result = (((
const unsigned char *) (const char *) (client->record.action
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (var
, client->record.action)))); })
) {
2210 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", client->record.action);
2211 httapi_sync(client);
2212 if (client->profile->perms.extended_data) {
2213 switch_channel_event_set_extended_data(channel, client->one_time_params);
2214 }
2215 switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "exiting", "true");
2216 }
2217 }
2218
2219 httapi_sync(client);
2220
2221 client_destroy(&client);
2222
2223 return status;
2224}
2225
2226static switch_state_handler_table_t state_handlers = {
2227 /*.on_init */ NULL((void*)0),
2228 /*.on_routing */ NULL((void*)0),
2229 /*.on_execute */ NULL((void*)0),
2230 /*.on_hangup */ NULL((void*)0),
2231 /*.on_exchange_media */ NULL((void*)0),
2232 /*.on_soft_execute */ NULL((void*)0),
2233 /*.on_consume_media */ NULL((void*)0),
2234 /*.on_hibernate */ NULL((void*)0),
2235 /*.on_reset */ NULL((void*)0),
2236 /*.on_park */ NULL((void*)0),
2237 /*.on_reporting */ my_on_reporting,
2238 /*.on_destroy */ NULL((void*)0),
2239 SSH_FLAG_STICKY
2240};
2241
2242
2243SWITCH_STANDARD_APP(httapi_function)static void httapi_function (switch_core_session_t *session, const
char *data)
2244{
2245 switch_channel_t *channel = switch_core_session_get_channel(session);
2246 char *parsed = NULL((void*)0);
2247 const char *profile_name = NULL((void*)0), *url = NULL((void*)0);
2248 client_t *client;
2249 switch_event_t *params = NULL((void*)0);
2250 uint32_t loops = 0, all_extended = 0;
2251 switch_caller_profile_t *caller_profile;
2252
2253 if (!zstr(data)_zstr(data)) {
2254 switch_event_create_brackets((char *)data, '{', '}', ',', &params, &parsed, SWITCH_TRUE);
2255
2256 if (params) {
2257 url = parsed;
2258 } else {
2259 url = data;
2260 }
2261
2262 if (!zstr(url)_zstr(url) && switch_stristr("://", url)) {
2263 if (!params) {
2264 switch_event_create(&params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 2264, &params, SWITCH_EVENT_CLONE
, ((void*)0))
;
2265 params->flags |= EF_UNIQ_HEADERS;
2266 }
2267 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "url", url);
2268 }
2269 }
2270
2271 if ((client = (client_t *) switch_channel_get_private(channel, "_HTTAPI_CLIENT_"))) {
2272 if (params) {
2273 switch_event_merge(client->params, params);
2274 switch_event_destroy(&params);
2275 }
2276 } else {
2277 if (params) {
2278 profile_name = switch_event_get_header(params, "httapi_profile")switch_event_get_header_idx(params, "httapi_profile", -1);
2279 }
2280
2281 if (zstr(profile_name)_zstr(profile_name) && !(profile_name = switch_channel_get_variable(channel, "httapi_profile")switch_channel_get_variable_dup(channel, "httapi_profile", SWITCH_TRUE
, -1)
)) {
2282 profile_name = "default";
2283 }
2284
2285 if ((client = client_create(session, profile_name, &params))) {
2286 switch_channel_set_private(channel, "_HTTAPI_CLIENT_", client);
2287 switch_channel_add_state_handler(channel, &state_handlers);
2288 } else {
2289 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2289, ((void*)0)
, SWITCH_LOG_ERROR, "Cannot find suitable profile\n");
2290 switch_event_destroy(&params);
2291 return;
2292 }
2293 }
2294
2295 if (client->profile->perms.extended_data) {
2296 all_extended = switch_true(switch_event_get_header(client->params, "full_channel_data_on_every_req")switch_event_get_header_idx(client->params, "full_channel_data_on_every_req"
, -1)
);
2297 }
2298
2299 if ((caller_profile = switch_channel_get_caller_profile(channel))) {
2300 switch_caller_profile_event_set_data(caller_profile, "Caller", client->params);
2301 }
2302
2303 while(switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
2304 switch_status_t status = SWITCH_STATUS_FALSE;
2305
2306 if (client->profile->perms.extended_data && (!loops++ || all_extended)) {
2307 switch_channel_event_set_extended_data(channel, client->one_time_params);
2308 }
2309
2310 if ((status = httapi_sync(client)) == SWITCH_STATUS_SUCCESS) {
2311 if (client->code == 200) {
2312 const char *ct = switch_event_get_header(client->headers, "content-type")switch_event_get_header_idx(client->headers, "content-type"
, -1)
;
2313
2314 if (switch_stristr("text/xml", ct)) {
2315 status = parse_xml(client);
2316 } else {
2317 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2317, ((void*)0)
, SWITCH_LOG_ERROR, "Received unsupported content-type %s\n", ct);
2318 break;
2319 }
2320 } else {
2321 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2321, ((void*)0)
, SWITCH_LOG_ERROR, "Received HTTP response: %ld.\n", client->code);
2322 break;
2323 }
2324 } else {
2325 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2325, ((void*)0)
, SWITCH_LOG_ERROR, "Error %d!\n", client->err);
2326 }
2327
2328 if (status == SWITCH_STATUS_TERM) {
2329 httapi_sync(client);
2330 }
2331
2332 if (status != SWITCH_STATUS_SUCCESS) {
2333 break;
2334 }
2335 }
2336
2337
2338 switch_safe_free(parsed)if (parsed) {free(parsed);parsed=((void*)0);};
2339
2340}
2341
2342
2343/* HTTP FILE INTERFACE */
2344
2345static const char *find_ext(const char *in)
2346{
2347 const char *p = in + (strlen(in) - 1);
2348
2349 while(p >= in && *p) {
2350 if (*p == '/') return NULL((void*)0);
2351 if (*p == '.') return (p+1);
2352 p--;
2353 }
2354
2355 return NULL((void*)0);
2356}
2357
2358static char *load_cache_data(http_file_context_t *context, const char *url)
2359{
2360 const char *ext = NULL((void*)0);
2361 char *dext = NULL((void*)0), *p;
2362 char digest[SWITCH_MD5_DIGEST_STRING_SIZE33] = { 0 };
2363 char meta_buffer[1024] = "";
2364 int fd;
2365 switch_ssize_t bytes;
2366
2367 switch_md5_string(digest, (void *) url, strlen(url));
2368
2369 if (context->url_params) {
2370 ext = switch_event_get_header(context->url_params, "ext")switch_event_get_header_idx(context->url_params, "ext", -1
)
;
2371 }
2372
2373 if (zstr(ext)_zstr(ext)) {
2374 ext = find_ext(url);
2375 }
2376
2377 if (ext && (p = strchr(ext, '?')(__extension__ (__builtin_constant_p ('?') && !__builtin_constant_p
(ext) && ('?') == '\0' ? (char *) __rawmemchr (ext, '?'
) : __builtin_strchr (ext, '?')))
)) {
2378 dext = strdup(ext)(__extension__ (__builtin_constant_p (ext) && ((size_t
)(const void *)((ext) + 1) - (size_t)(const void *)(ext) == 1
) ? (((const char *) (ext))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (ext) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, ext, __len); __retval
; })) : __strdup (ext)))
;
2379 if ((p = strchr(dext, '?')(__extension__ (__builtin_constant_p ('?') && !__builtin_constant_p
(dext) && ('?') == '\0' ? (char *) __rawmemchr (dext
, '?') : __builtin_strchr (dext, '?')))
)) {
2380 *p = '\0';
2381 ext = dext;
2382 } else switch_safe_free(dext)if (dext) {free(dext);dext=((void*)0);};
2383 }
2384
2385 context->cache_file_base = switch_core_sprintf(context->pool, "%s%s%s", globals.cache_path, SWITCH_PATH_SEPARATOR"/", digest);
2386 context->meta_file = switch_core_sprintf(context->pool, "%s%s%s.meta", globals.cache_path, SWITCH_PATH_SEPARATOR"/", digest);
2387
2388 if (switch_file_exists(context->meta_file, context->pool) == SWITCH_STATUS_SUCCESS && ((fd = open(context->meta_file, O_RDONLY00, 0)) > -1)) {
2389 if ((bytes = read(fd, meta_buffer, sizeof(meta_buffer))) > 0) {
2390 char *p;
2391
2392 if ((p = strchr(meta_buffer, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(meta_buffer) && (':') == '\0' ? (char *) __rawmemchr
(meta_buffer, ':') : __builtin_strchr (meta_buffer, ':')))
)) {
2393 *p++ = '\0';
2394 if (context->expires != 1) {
2395 context->expires = (time_t) atol(meta_buffer);
2396 }
2397 context->metadata = switch_core_strdup(context->pool, p)switch_core_perform_strdup(context->pool, p, "mod_httapi.c"
, (const char *)__func__, 2397)
;
2398 }
2399
2400 if ((p = strrchr(context->metadata, ':'))) {
2401 p++;
2402 if (!zstr(p)_zstr(p)) {
2403 ext = p;
2404 }
2405 }
2406
2407 }
2408 close(fd);
2409 }
2410
2411 context->cache_file = switch_core_sprintf(context->pool, "%s%s%s%s%s", globals.cache_path, SWITCH_PATH_SEPARATOR"/", digest, ext ? "." : "", ext ? ext : "");
2412 switch_safe_free(dext)if (dext) {free(dext);dext=((void*)0);};
2413
2414 return context->cache_file;
2415}
2416
2417static size_t save_file_callback(void *ptr, size_t size, size_t nmemb, void *data)
2418{
2419 register unsigned int realsize = (unsigned int) (size * nmemb);
2420 client_t *client = data;
2421 int x;
2422
2423 client->bytes += realsize;
2424
2425
2426
2427 if (client->bytes > client->max_bytes) {
2428 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2428, ((void*)0)
, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) client->bytes);
2429 client->err = 1;
2430 return 0;
2431 }
2432
2433 x = write(client->fd, ptr, realsize);
2434
2435 if (x != (int) realsize) {
2436 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2436, ((void*)0)
, SWITCH_LOG_ERROR, "Short write! %d out of %d\n", x, realsize);
2437 }
2438 return x;
2439}
2440
2441
2442
2443static switch_status_t fetch_cache_data(http_file_context_t *context, const char *url, switch_event_t **headers, const char *save_path)
2444{
2445 switch_CURL *curl_handle = NULL((void*)0);
2446 client_t *client = NULL((void*)0);
2447 long code;
2448 switch_status_t status = SWITCH_STATUS_FALSE;
2449 char *dup_creds = NULL((void*)0), *dynamic_url = NULL((void*)0), *use_url;
2450 char *ua = NULL((void*)0);
2451 const char *profile_name = NULL((void*)0);
2452
2453
2454 if (context->url_params) {
2455 profile_name = switch_event_get_header(context->url_params, "profile_name")switch_event_get_header_idx(context->url_params, "profile_name"
, -1)
;
2456 }
2457
2458 if (zstr(profile_name)_zstr(profile_name)) {
2459 if (globals.profile) profile_name = globals.profile->name;
2460 }
2461
2462 if (zstr(profile_name)_zstr(profile_name)) {
2463 profile_name = "default";
2464 }
2465
2466 if (!(client = client_create(NULL((void*)0), profile_name, NULL((void*)0)))) {
2467 return SWITCH_STATUS_FALSE;
2468 }
2469
2470
2471 if (save_path) {
2472 if ((client->fd = open(save_path, O_CREAT0100 | O_RDWR02 | O_TRUNC01000, S_IRUSR0400 | S_IWUSR0200)) < 0) {
2473 return SWITCH_STATUS_FALSE;
2474 }
2475 }
2476
2477 if (context->url_params) {
2478 ua = switch_event_get_header(context->url_params, "user_agent")switch_event_get_header_idx(context->url_params, "user_agent"
, -1)
;
2479 }
2480
2481 if (zstr(ua)_zstr(ua)) {
2482 ua = "mod_httapi/1.0";
2483 }
2484
2485 if ((use_url = strchr(url, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(url) && ('@') == '\0' ? (char *) __rawmemchr (url, '@'
) : __builtin_strchr (url, '@')))
)) {
2486 char *r, *q, *p = strstr(url, "://");
2487 use_url++;
2488
2489 dup_creds = strdup(p+3)(__extension__ (__builtin_constant_p (p+3) && ((size_t
)(const void *)((p+3) + 1) - (size_t)(const void *)(p+3) == 1
) ? (((const char *) (p+3))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (p+3) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, p+3, __len); __retval
; })) : __strdup (p+3)))
;
2490
2491 if ((q = strchr(dup_creds, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(dup_creds) && ('@') == '\0' ? (char *) __rawmemchr (
dup_creds, '@') : __builtin_strchr (dup_creds, '@')))
)) *q = '\0';
2492
2493 q = strdup(url)(__extension__ (__builtin_constant_p (url) && ((size_t
)(const void *)((url) + 1) - (size_t)(const void *)(url) == 1
) ? (((const char *) (url))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (url) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, url, __len); __retval
; })) : __strdup (url)))
;
2494 r = strchr(q, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(q) && ('@') == '\0' ? (char *) __rawmemchr (q, '@')
: __builtin_strchr (q, '@')))
;
2495 r++;
2496
2497 if ((p = strstr(q, "://"))) {
2498 *(p+3) = '\0';
2499 }
2500
2501 p = switch_mprintf("%s%s", q, r);
2502 dynamic_url = p;
2503 free(q);
2504 url = dynamic_url;
2505 }
2506
2507 curl_handle = switch_curl_easy_init();
2508
2509 switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1)curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL,1);
2510 switch_curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1)curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS,1);
2511
2512 if (!strncasecmp(url, "https", 5)) {
2513 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
2514 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
2515 }
2516
2517 client->max_bytes = HTTAPI_MAX_FILE_BYTES1024 * 1024 * 100;
2518
2519 switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1)curl_easy_setopt(curl_handle,CURLOPT_FOLLOWLOCATION,1);
2520 switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10)curl_easy_setopt(curl_handle,CURLOPT_MAXREDIRS,10);
2521 switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url)curl_easy_setopt(curl_handle,CURLOPT_URL,url);
2522
2523 if (client->profile->timeout) {
2524 switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout)curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,client->profile
->timeout)
;
2525 }
2526
2527 if (client->profile->ssl_cert_file) {
2528 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, client->profile->ssl_cert_file)curl_easy_setopt(curl_handle,CURLOPT_SSLCERT,client->profile
->ssl_cert_file)
;
2529 }
2530
2531 if (client->profile->ssl_key_file) {
2532 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, client->profile->ssl_key_file)curl_easy_setopt(curl_handle,CURLOPT_SSLKEY,client->profile
->ssl_key_file)
;
2533 }
2534
2535 if (client->profile->ssl_key_password) {
2536 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, client->profile->ssl_key_password)curl_easy_setopt(curl_handle,CURLOPT_KEYPASSWD,client->profile
->ssl_key_password)
;
2537 }
2538
2539 if (client->profile->ssl_version) {
2540 if (!strcasecmp(client->profile->ssl_version, "SSLv3")) {
2541 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_SSLv3
)
;
2542#ifdef CURL_SSLVERSION_TLSv1_1
2543 } else if (!strcasecmp(client->profile->ssl_version, "TLSv1.1")) {
2544 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1_1
)
;
2545#endif
2546#ifdef CURL_SSLVERSION_TLSv1_2
2547 } else if (!strcasecmp(client->profile->ssl_version, "TLSv1.2")) {
2548 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1_2
)
;
2549#endif
2550 }
2551 } else {
2552 switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1)curl_easy_setopt(curl_handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1
)
;
2553 }
2554
2555 if (client->profile->ssl_cacert_file) {
2556 switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, client->profile->ssl_cacert_file)curl_easy_setopt(curl_handle,CURLOPT_CAINFO,client->profile
->ssl_cacert_file)
;
2557 }
2558
2559 if (client->profile->enable_ssl_verifyhost) {
2560 switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2)curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,2);
2561 }
2562
2563 if (client->profile->cookie_file) {
2564 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, client->profile->cookie_file)curl_easy_setopt(curl_handle,CURLOPT_COOKIEJAR,client->profile
->cookie_file)
;
2565 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, client->profile->cookie_file)curl_easy_setopt(curl_handle,CURLOPT_COOKIEFILE,client->profile
->cookie_file)
;
2566 } else {
2567 switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIE, "")curl_easy_setopt(curl_handle,CURLOPT_COOKIE,"");
2568 }
2569
2570 if (client->profile->bind_local) {
2571 curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local)curl_easy_setopt(curl_handle,CURLOPT_INTERFACE,client->profile
->bind_local)
;
2572 }
2573
2574 if (save_path) {
2575 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, save_file_callback)curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,save_file_callback
)
;
2576 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client)curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *) client
)
;
2577 } else {
2578 switch_curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1)curl_easy_setopt(curl_handle,CURLOPT_HEADER,1);
2579 switch_curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1)curl_easy_setopt(curl_handle,CURLOPT_NOBODY,1);
2580 }
2581
2582 if (headers) {
2583 switch_event_create(&client->headers, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 2583, &client->headers, SWITCH_EVENT_CLONE
, ((void*)0))
;
2584 if (save_path) {
2585 switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback)curl_easy_setopt(curl_handle,CURLOPT_HEADERFUNCTION,get_header_callback
)
;
2586 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client)curl_easy_setopt(curl_handle,CURLOPT_HEADERDATA,(void *) client
)
;
2587 } else {
2588 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, get_header_callback)curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,get_header_callback
)
;
2589 switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client)curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *) client
)
;
2590 }
2591 }
2592
2593 if (!zstr(dup_creds)_zstr(dup_creds)) {
2594 switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC)curl_easy_setopt(curl_handle,CURLOPT_HTTPAUTH,(((unsigned long
)1)<<0))
;
2595 switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, dup_creds)curl_easy_setopt(curl_handle,CURLOPT_USERPWD,dup_creds);
2596 }
2597
2598 switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua)curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,ua);
2599 switch_curl_easy_perform(curl_handle);
2600 switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
2601 switch_curl_easy_cleanup(curl_handle);
2602
2603 if (client->fd > -1) {
2604 close(client->fd);
2605 }
2606
2607 if (headers && client->headers) {
2608 switch_event_add_header(client->headers, SWITCH_STACK_BOTTOM, "http-response-code", "%ld", code);
2609 *headers = client->headers;
2610 client->headers = NULL((void*)0);
2611 }
2612
2613 switch(code) {
2614 case 200:
2615 if (save_path) {
2616 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2616, ((void*)0)
, SWITCH_LOG_DEBUG, "caching: url:%s to %s (%" SWITCH_SIZE_T_FMT"ld" " bytes)\n", url, save_path, client->bytes);
2617 }
2618 status = SWITCH_STATUS_SUCCESS;
2619 break;
2620
2621 case 404:
2622 status = SWITCH_STATUS_NOTFOUND;
2623 break;
2624
2625 default:
2626 status = SWITCH_STATUS_FALSE;
2627 break;
2628 }
2629
2630 switch_safe_free(dynamic_url)if (dynamic_url) {free(dynamic_url);dynamic_url=((void*)0);};
2631 switch_safe_free(dup_creds)if (dup_creds) {free(dup_creds);dup_creds=((void*)0);};
2632 client_destroy(&client);
2633
2634 return status;
2635}
2636
2637static switch_status_t write_meta_file(http_file_context_t *context, const char *data, switch_event_t *headers)
2638{
2639 int fd;
2640 switch_status_t status = SWITCH_STATUS_SUCCESS;
2641 char write_data[1024];
2642
2643 if ((fd = open(context->meta_file, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000, S_IRUSR0400 | S_IWUSR0200)) < 0) {
2644 return SWITCH_STATUS_FALSE;
2645 }
2646
2647 if (!zstr(data)_zstr(data)) {
2648 int ttl = globals.cache_ttl, abs_cache_ttl = globals.abs_cache_ttl;
2649 const char *cc;
2650 const char *p;
2651 int x;
2652
2653 if (context->url_params) {
2654 if ((cc = switch_event_get_header(context->url_params, "abs_cache_control")switch_event_get_header_idx(context->url_params, "abs_cache_control"
, -1)
)) {
2655 x = atoi(cc);
2656
2657 if (x > 0) {
2658 abs_cache_ttl = x;
2659 }
2660 } else if ((cc = switch_event_get_header(context->url_params, "cache_control")switch_event_get_header_idx(context->url_params, "cache_control"
, -1)
)) {
2661 x = atoi(cc);
2662
2663 if (x > 0) {
2664 ttl = x;
2665 }
2666 }
2667 }
2668
2669 if (abs_cache_ttl) {
2670 ttl = abs_cache_ttl;
2671 } else if (headers && (cc = switch_event_get_header(headers, "Cache-Control")switch_event_get_header_idx(headers, "Cache-Control", -1))) {
2672 if ((p = switch_stristr("max-age=", cc))) {
2673 p += 8;
2674
2675 if (!zstr(p)_zstr(p)) {
2676 x = atoi(p);
2677
2678 if (x < ttl) {
2679 ttl = x;
2680 }
2681 }
2682 }
2683
2684 if (switch_stristr("no-cache", cc) || switch_stristr("no-store", cc)) {
2685 context->del_on_close = 1;
2686 }
2687 }
2688
2689 switch_snprintf(write_data, sizeof(write_data),
2690 "%" TIME_T_FMT"ld" ":%s",
2691 switch_epoch_time_now(NULL((void*)0)) + ttl,
2692 data);
2693
2694
2695 status = write(fd, write_data, (int)strlen(write_data) + 1) > 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
2696 }
2697
2698 close(fd);
2699
2700 return status;
2701}
2702
2703
2704static switch_status_t lock_file(http_file_context_t *context, switch_bool_t lock)
2705{
2706
2707 switch_status_t status = SWITCH_STATUS_SUCCESS;
2708 http_file_context_t *xcontext = NULL((void*)0);
2709
2710 if (lock) {
2711 switch_mutex_lock(globals.request_mutex);
2712 if (!(xcontext = switch_core_hash_find(globals.request_hash, context->dest_url))) {
2713 switch_core_hash_insert(globals.request_hash, context->dest_url, context)switch_core_hash_insert_destructor(globals.request_hash, context
->dest_url, context, ((void*)0))
;
2714 xcontext = context;
2715 }
2716 switch_mutex_lock(context->mutex);
2717 switch_mutex_unlock(globals.request_mutex);
2718
2719 if (context != xcontext) {
2720 switch_mutex_lock(xcontext->mutex);
2721 switch_mutex_unlock(xcontext->mutex);
2722 }
2723
2724 } else {
2725 switch_mutex_lock(globals.request_mutex);
2726 if ((xcontext = switch_core_hash_find(globals.request_hash, context->dest_url)) && xcontext == context) {
2727 switch_core_hash_delete(globals.request_hash, context->dest_url);
2728 }
2729 switch_mutex_unlock(context->mutex);
2730 switch_mutex_unlock(globals.request_mutex);
2731 }
2732
2733 return status;
2734}
2735
2736
2737static switch_status_t locate_url_file(http_file_context_t *context, const char *url)
2738{
2739 switch_event_t *headers = NULL((void*)0);
2740 int unreachable = 0;
2741 switch_status_t status = SWITCH_STATUS_FALSE;
2742 time_t now = switch_epoch_time_now(NULL((void*)0));
2743 char *metadata;
2744 const char *ext = NULL((void*)0);
2745
2746 load_cache_data(context, url);
2747
2748 if (context->expires > 1 && now < context->expires) {
2749 return SWITCH_STATUS_SUCCESS;
2750 }
2751
2752 if (context->url_params) {
2753 ext = switch_event_get_header(context->url_params, "ext")switch_event_get_header_idx(context->url_params, "ext", -1
)
;
2754 }
2755
2756 if (zstr(ext)_zstr(ext)) {
2757 ext = find_ext(context->cache_file);
2758 }
2759
2760 if (!context->url_params || !switch_true(switch_event_get_header(context->url_params, "nohead")switch_event_get_header_idx(context->url_params, "nohead",
-1)
)) {
2761 const char *ct = NULL((void*)0);
2762 const char *newext = NULL((void*)0);
2763
2764 if ((status = fetch_cache_data(context, url, &headers, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) {
2765 if (status == SWITCH_STATUS_NOTFOUND) {
2766 unreachable = 2;
2767 if (now - context->expires < globals.not_found_expires) {
2768 switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end;
2769 }
2770 } else {
2771 unreachable = 1;
2772 }
2773 }
2774
2775 if (zstr(ext)_zstr(ext) && headers && (ct = switch_event_get_header(headers, "content-type")switch_event_get_header_idx(headers, "content-type", -1))) {
2776 if (switch_strcasecmp_any(ct, "audio/mpeg", "audio/x-mpeg", "audio/mp3", "audio/x-mp3", "audio/mpeg3",
2777 "audio/x-mpeg3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio", NULL((void*)0))) {
2778 newext = "mp3";
2779 } else if (switch_strcasecmp_any(ct, "audio/x-wav", "audio/x-wave", "audio/wav", "audio/wave", NULL((void*)0))) {
2780 newext = "wav";
2781 }
2782 }
2783
2784 if (newext) {
2785 ext = newext;
2786 context->cache_file = switch_core_sprintf(context->pool, "%s.%s", context->cache_file, newext);
2787 }
2788
2789
2790 if (switch_file_exists(context->cache_file, context->pool) != SWITCH_STATUS_SUCCESS && unreachable) {
2791 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2791, ((void*)0)
, SWITCH_LOG_ERROR, "File at url [%s] is unreachable!\n", url);
2792 status = SWITCH_STATUS_NOTFOUND;
2793 goto end;
2794 }
2795
2796 if (!unreachable && !zstr(context->metadata)_zstr(context->metadata)) {
2797 metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s:%s",
2798 url,
2799 switch_event_get_header_nil(headers, "last-modified")(switch_event_get_header_idx(headers, "last-modified", -1) ? switch_event_get_header_idx
(headers, "last-modified", -1) : "")
,
2800 switch_event_get_header_nil(headers, "etag")(switch_event_get_header_idx(headers, "etag", -1) ? switch_event_get_header_idx
(headers, "etag", -1) : "")
,
2801 switch_event_get_header_nil(headers, "content-length")(switch_event_get_header_idx(headers, "content-length", -1) ?
switch_event_get_header_idx(headers, "content-length", -1) :
"")
,
2802 ext
2803 );
2804
2805 if (!strcmp(metadata, context->metadata)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(metadata) && __builtin_constant_p (context->metadata
) && (__s1_len = __builtin_strlen (metadata), __s2_len
= __builtin_strlen (context->metadata), (!((size_t)(const
void *)((metadata) + 1) - (size_t)(const void *)(metadata) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((context->metadata) + 1) - (size_t)(const void *)(context
->metadata) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(metadata, context->metadata) : (__builtin_constant_p (metadata
) && ((size_t)(const void *)((metadata) + 1) - (size_t
)(const void *)(metadata) == 1) && (__s1_len = __builtin_strlen
(metadata), __s1_len < 4) ? (__builtin_constant_p (context
->metadata) && ((size_t)(const void *)((context->
metadata) + 1) - (size_t)(const void *)(context->metadata)
== 1) ? __builtin_strcmp (metadata, context->metadata) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (context->metadata); int __result = (((
const unsigned char *) (const char *) (metadata))[0] - __s2[0
]); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (metadata))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (metadata))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (metadata))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p (context->
metadata) && ((size_t)(const void *)((context->metadata
) + 1) - (size_t)(const void *)(context->metadata) == 1) &&
(__s2_len = __builtin_strlen (context->metadata), __s2_len
< 4) ? (__builtin_constant_p (metadata) && ((size_t
)(const void *)((metadata) + 1) - (size_t)(const void *)(metadata
) == 1) ? __builtin_strcmp (metadata, context->metadata) :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (metadata); int __result = (((const unsigned
char *) (const char *) (context->metadata))[0] - __s2[0])
; if (__s2_len > 0 && __result == 0) { __result = (
((const unsigned char *) (const char *) (context->metadata
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (context
->metadata))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (context->metadata))[3] - __s2[3]); } } __result; })))
) : __builtin_strcmp (metadata, context->metadata)))); })
) {
2806 write_meta_file(context, metadata, headers);
2807 switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end;
2808 }
2809 }
2810
2811 switch_event_destroy(&headers);
2812 }
2813
2814
2815 if ((status = fetch_cache_data(context, url, &headers, context->cache_file)) != SWITCH_STATUS_SUCCESS) {
2816 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2816, ((void*)0)
, SWITCH_LOG_ERROR, "Error checking file cache (check permissions)\n");
2817 goto end;
2818 }
2819
2820
2821 metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s:%s",
2822 url,
2823 switch_event_get_header_nil(headers, "last-modified")(switch_event_get_header_idx(headers, "last-modified", -1) ? switch_event_get_header_idx
(headers, "last-modified", -1) : "")
,
2824 switch_event_get_header_nil(headers, "etag")(switch_event_get_header_idx(headers, "etag", -1) ? switch_event_get_header_idx
(headers, "etag", -1) : "")
,
2825 switch_event_get_header_nil(headers, "content-length")(switch_event_get_header_idx(headers, "content-length", -1) ?
switch_event_get_header_idx(headers, "content-length", -1) :
"")
,
2826 ext
2827 );
2828
2829 write_meta_file(context, metadata, headers);
2830
2831 if (switch_file_exists(context->cache_file, context->pool) == SWITCH_STATUS_SUCCESS) {
2832 status = SWITCH_STATUS_SUCCESS;
2833 }
2834
2835 end:
2836
2837 if (status != SWITCH_STATUS_SUCCESS) {
2838 unlink(context->meta_file);
2839 unlink(context->cache_file);
2840 }
2841
2842 switch_event_destroy(&headers);
2843
2844 return status;
2845}
2846
2847
2848static switch_status_t http_file_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
2849{
2850 http_file_context_t *context = handle->private_info;
2851
2852 if (!handle->seekable) {
2853 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2853, ((void*)0)
, SWITCH_LOG_WARNING, "File is not seekable\n");
2854 return SWITCH_STATUS_NOTIMPL;
2855 }
2856
2857 return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
2858}
2859
2860static switch_status_t file_open(switch_file_handle_t *handle, const char *path, int is_https)
2861{
2862 http_file_context_t *context;
2863 char *parsed = NULL((void*)0), *pdup = NULL((void*)0);
2864 const char *pa = NULL((void*)0);
2865 switch_status_t status;
2866
2867 if (!strncmp(path, "http://", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(path) && strlen (path) < ((size_t) (7))) || (__builtin_constant_p
("http://") && strlen ("http://") < ((size_t) (7)
))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(path) && __builtin_constant_p ("http://") &&
(__s1_len = __builtin_strlen (path), __s2_len = __builtin_strlen
("http://"), (!((size_t)(const void *)((path) + 1) - (size_t
)(const void *)(path) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("http://") + 1) - (size_t)(const void
*)("http://") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(path, "http://") : (__builtin_constant_p (path) && (
(size_t)(const void *)((path) + 1) - (size_t)(const void *)(path
) == 1) && (__s1_len = __builtin_strlen (path), __s1_len
< 4) ? (__builtin_constant_p ("http://") && ((size_t
)(const void *)(("http://") + 1) - (size_t)(const void *)("http://"
) == 1) ? __builtin_strcmp (path, "http://") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("http://"); int __result = (((const unsigned char *
) (const char *) (path))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (path))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (path))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (path))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("http://") && ((size_t)(const void *)(("http://") +
1) - (size_t)(const void *)("http://") == 1) && (__s2_len
= __builtin_strlen ("http://"), __s2_len < 4) ? (__builtin_constant_p
(path) && ((size_t)(const void *)((path) + 1) - (size_t
)(const void *)(path) == 1) ? __builtin_strcmp (path, "http://"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (path); int __result = (((const unsigned
char *) (const char *) ("http://"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("http://"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("http://"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("http://"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (path, "http://")))); }) : strncmp
(path, "http://", 7)))
) {
2868 pa = path + 7;
2869 } else if (!strncmp(path, "https://", 8)(__extension__ (__builtin_constant_p (8) && ((__builtin_constant_p
(path) && strlen (path) < ((size_t) (8))) || (__builtin_constant_p
("https://") && strlen ("https://") < ((size_t) (
8)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(path) && __builtin_constant_p ("https://") &&
(__s1_len = __builtin_strlen (path), __s2_len = __builtin_strlen
("https://"), (!((size_t)(const void *)((path) + 1) - (size_t
)(const void *)(path) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("https://") + 1) - (size_t)(const void
*)("https://") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(path, "https://") : (__builtin_constant_p (path) &&
((size_t)(const void *)((path) + 1) - (size_t)(const void *)
(path) == 1) && (__s1_len = __builtin_strlen (path), __s1_len
< 4) ? (__builtin_constant_p ("https://") && ((size_t
)(const void *)(("https://") + 1) - (size_t)(const void *)("https://"
) == 1) ? __builtin_strcmp (path, "https://") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("https://"); int __result = (((const unsigned char *
) (const char *) (path))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (path))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (path))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (path))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("https://") && ((size_t)(const void *)(("https://")
+ 1) - (size_t)(const void *)("https://") == 1) && (
__s2_len = __builtin_strlen ("https://"), __s2_len < 4) ? (
__builtin_constant_p (path) && ((size_t)(const void *
)((path) + 1) - (size_t)(const void *)(path) == 1) ? __builtin_strcmp
(path, "https://") : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (path); int __result
= (((const unsigned char *) (const char *) ("https://"))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("https://"))[1] -
__s2[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("https://"))[2] -
__s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) ("https://"))[3] -
__s2[3]); } } __result; })))) : __builtin_strcmp (path, "https://"
)))); }) : strncmp (path, "https://", 8)))
) {
2870 pa = path + 8;
2871 is_https = 1;
2872 } else {
2873 pa = path;
2874 }
2875
2876 context = switch_core_alloc(handle->memory_pool, sizeof(*context))switch_core_perform_alloc(handle->memory_pool, sizeof(*context
), "mod_httapi.c", (const char *)__func__, 2876)
;
2877 context->pool = handle->memory_pool;
2878 switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED0x1, handle->memory_pool);
2879
2880 pdup = switch_core_strdup(context->pool, pa)switch_core_perform_strdup(context->pool, pa, "mod_httapi.c"
, (const char *)__func__, 2880)
;
2881
2882 switch_event_create_brackets(pdup, '(', ')', ',', &context->url_params, &parsed, SWITCH_FALSE);
2883
2884 if (context->url_params) {
2885 const char *var;
2886 context->ua = switch_event_get_header(context->url_params, "ua")switch_event_get_header_idx(context->url_params, "ua", -1);
2887
2888 if ((var = switch_event_get_header(context->url_params, "cache")switch_event_get_header_idx(context->url_params, "cache", -
1)
) && !switch_true(var)) {
2889 context->expires = 1;
2890 }
2891 }
2892
2893 if (parsed) pa = parsed;
2894
2895 if (is_https) {
2896 context->dest_url = switch_core_sprintf(context->pool, "https://%s", pa);
2897 } else {
2898 context->dest_url = switch_core_sprintf(context->pool, "http://%s", pa);
2899 }
2900
2901 if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)((handle)->flags & SWITCH_FILE_FLAG_WRITE)) {
2902 char *ext;
2903
2904 context->fh.channels = handle->channels;
2905 context->fh.native_rate = handle->native_rate;
2906 context->fh.samples = handle->samples;
2907 context->fh.samplerate = handle->samplerate;
2908 context->fh.prefix = handle->prefix;
2909
2910
2911 if (context->url_params) {
2912 context->write.file_name = switch_event_get_header(context->url_params, "file")switch_event_get_header_idx(context->url_params, "file", -
1)
;
2913 context->write.profile_name = switch_event_get_header(context->url_params, "profile")switch_event_get_header_idx(context->url_params, "profile"
, -1)
;
2914 context->write.method = switch_event_get_header(context->url_params, "method")switch_event_get_header_idx(context->url_params, "method",
-1)
;
2915 context->write.name = switch_event_get_header(context->url_params, "name")switch_event_get_header_idx(context->url_params, "name", -
1)
;
2916 }
2917
2918 if (!context->write.file_name) {
2919 char *p;
2920 if ((p = strrchr(context->dest_url, '/'))) {
2921 p++;
2922 context->write.file_name = switch_core_strdup(context->pool, p)switch_core_perform_strdup(context->pool, p, "mod_httapi.c"
, (const char *)__func__, 2922)
;
2923 }
2924 }
2925
2926 if (!context->write.file_name) {
2927 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2927, ((void*)0)
, SWITCH_LOG_ERROR, "No file name specified.\n");
2928 return SWITCH_STATUS_GENERR;
2929 }
2930
2931 if ((ext = strrchr(context->write.file_name, '.'))) {
2932 ext++;
2933 } else {
2934 ext = "wav";
2935 }
2936
2937 if (!context->write.profile_name) context->write.profile_name = "default";
2938 if (!context->write.method) context->write.method = !strcasecmp(ext, "cgi") ? "post" : "put";
2939 if (!context->write.name) context->write.name = "recorded_file";
2940
2941 switch_uuid_str(context->write.uuid_str, sizeof(context->write.uuid_str));
2942
2943 context->write.file = switch_core_sprintf(context->pool, "%s%s%s_%s",
2944 SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR"/", context->write.uuid_str, context->write.file_name);
2945
2946
2947 if (switch_core_file_open(&context->fh, context->write.file, handle->channels, handle->samplerate, handle->flags, NULL)switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2947, &context->fh, context->write.file, handle->
channels, handle->samplerate, handle->flags, ((void*)0)
)
!= SWITCH_STATUS_SUCCESS) {
2948 return SWITCH_STATUS_GENERR;
2949 }
2950
2951 } else {
2952
2953 if (context->url_params) {
2954 context->read.ext = switch_event_get_header(context->url_params, "ext")switch_event_get_header_idx(context->url_params, "ext", -1
)
;
2955 }
2956
2957 lock_file(context, SWITCH_TRUE);
2958
2959 if ((status = locate_url_file(context, context->dest_url)) != SWITCH_STATUS_SUCCESS) {
2960 return status;
2961 }
2962
2963 lock_file(context, SWITCH_FALSE);
2964
2965 if ((status = switch_core_file_open(&context->fh,switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2969, &context->fh, context->cache_file, handle->
channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT
, ((void*)0))
2966 context->cache_file,switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2969, &context->fh, context->cache_file, handle->
channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT
, ((void*)0))
2967 handle->channels,switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2969, &context->fh, context->cache_file, handle->
channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT
, ((void*)0))
2968 handle->samplerate,switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2969, &context->fh, context->cache_file, handle->
channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT
, ((void*)0))
2969 SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)switch_core_perform_file_open("mod_httapi.c", (const char *)__func__
, 2969, &context->fh, context->cache_file, handle->
channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT
, ((void*)0))
) != SWITCH_STATUS_SUCCESS) {
2970 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 2970, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid cache file %s opening url %s Discarding file.\n", context->cache_file, path);
2971 unlink(context->cache_file);
2972 unlink(context->meta_file);
2973 return status;
2974 }
2975 }
2976
2977 handle->private_info = context;
2978 handle->samples = context->fh.samples;
2979 handle->format = context->fh.format;
2980 handle->sections = context->fh.sections;
2981 handle->seekable = context->fh.seekable;
2982 handle->speed = context->fh.speed;
2983 handle->interval = context->fh.interval;
2984 handle->channels = context->fh.real_channels;
2985 handle->flags |= SWITCH_FILE_NOMUX;
2986
2987 if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)(((&context->fh))->flags & SWITCH_FILE_NATIVE)) {
2988 switch_set_flag(handle, SWITCH_FILE_NATIVE)(handle)->flags |= (SWITCH_FILE_NATIVE);
2989 } else {
2990 switch_clear_flag(handle, SWITCH_FILE_NATIVE)(handle)->flags &= ~(SWITCH_FILE_NATIVE);
2991 }
2992
2993 return SWITCH_STATUS_SUCCESS;
2994}
2995
2996static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path) {
2997 return file_open(handle, path, 0);
2998}
2999
3000static switch_status_t https_file_file_open(switch_file_handle_t *handle, const char *path) {
3001 return file_open(handle, path, 1);
3002}
3003
3004static switch_status_t http_file_file_close(switch_file_handle_t *handle)
3005{
3006 http_file_context_t *context = handle->private_info;
3007
3008 switch_mutex_lock(context->mutex);
3009 switch_mutex_unlock(context->mutex);
3010
3011 if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)(((&context->fh))->flags & SWITCH_FILE_OPEN)) {
3012 switch_core_file_close(&context->fh);
3013 }
3014
3015 if (context->write.file) {
3016 client_t *client;
3017 switch_event_t *params;
3018 char *key;
3019
3020 switch_event_create(&params, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("mod_httapi.c", (const char
* )(const char *)__func__, 3020, &params, SWITCH_EVENT_CLONE
, ((void*)0))
;
3021 params->flags |= EF_UNIQ_HEADERS;
3022
3023 if (!strcasecmp(context->write.method, "put")) {
3024 switch_event_add_header(params, SWITCH_STACK_BOTTOM, "put_file", "%s", context->write.file);
3025 } else {
3026 key = switch_core_sprintf(context->pool, "attach_file:%s:%s", context->write.name, context->write.file_name);
3027 switch_event_add_header(params, SWITCH_STACK_BOTTOM, key, "%s", context->write.file);
3028 }
3029
3030 switch_event_add_header(params, SWITCH_STACK_BOTTOM, "url", "%s", context->dest_url);
3031 switch_event_add_header(params, SWITCH_STACK_BOTTOM, "file_driver", "true");
3032 switch_event_add_header(params, SWITCH_STACK_BOTTOM, "HTTAPI_SESSION_ID", "%s", context->write.uuid_str);
3033
3034 if ((client = client_create(NULL((void*)0), context->write.profile_name, &params))) {
3035 httapi_sync(client);
3036 client_destroy(&client);
3037 } else {
3038 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_httapi.c", (const char *)__func__
, 3038, ((void*)0)
, SWITCH_LOG_ERROR, "Cannot find suitable profile\n");
3039 switch_event_destroy(&params);
3040 }
3041
3042 unlink(context->write.file);
3043 return SWITCH_STATUS_SUCCESS;
3044 }
3045
3046
3047 if (context->del_on_close) {
3048 if (context->cache_file) {
3049 unlink(context->cache_file);
3050 unlink(context->meta_file);
3051 }
3052 }
3053
3054 if (context->url_params) {
3055 switch_event_destroy(&context->url_params);
3056 }
3057
3058 return SWITCH_STATUS_SUCCESS;
3059}
3060
3061
3062static switch_status_t http_file_write(switch_file_handle_t *handle, void *data, size_t *len)
3063{
3064 http_file_context_t *context = handle->private_info;
3065
3066 return switch_core_file_write(&context->fh, data, len);
3067}
3068
3069static switch_status_t http_file_file_read(switch_file_handle_t *handle, void *data, size_t *len)
3070{
3071 http_file_context_t *context = handle->private_info;
3072 switch_status_t status;
3073
3074 if (context->samples > 0) {
3075 if (*len > (size_t) context->samples) {
3076 *len = context->samples;
3077 }
3078
3079 context->samples -= (int)*len;
3080 memset(data, 255, *len *2);
3081 status = SWITCH_STATUS_SUCCESS;
3082 } else {
3083 status = switch_core_file_read(&context->fh, data, len);
3084 }
3085
3086 return status;
3087}
3088
3089/* Registration */
3090
3091static char *http_file_supported_formats[SWITCH_MAX_CODECS50] = { 0 };
3092static char *https_file_supported_formats[SWITCH_MAX_CODECS50] = { 0 };
3093
3094
3095/* /HTTP FILE INTERFACE */
3096
3097SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)switch_status_t mod_httapi_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
3098{
3099 switch_api_interface_t *httapi_api_interface;
3100 switch_application_interface_t *app_interface;
3101 switch_file_interface_t *http_file_interface;
3102 switch_file_interface_t *https_file_interface;
3103
3104 /* connect my internal structure to the blank pointer passed to me */
3105 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
3106
3107 memset(&globals, 0, sizeof(globals));
3108 globals.pool = pool;
3109 globals.hash_root = NULL((void*)0);
3110 globals.hash_tail = NULL((void*)0);
3111 globals.cache_ttl = 300;
3112 globals.not_found_expires = 300;
3113
3114 switch_mutex_init(&globals.request_mutex, SWITCH_MUTEX_NESTED0x1, pool);
3115
3116 http_file_supported_formats[0] = "http";
3117
3118 http_file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
3119 http_file_interface->interface_name = modname;
3120 http_file_interface->extens = http_file_supported_formats;
3121 http_file_interface->file_open = http_file_file_open;
3122 http_file_interface->file_close = http_file_file_close;
3123 http_file_interface->file_read = http_file_file_read;
3124 http_file_interface->file_write = http_file_write;
3125 http_file_interface->file_seek = http_file_file_seek;
3126
3127 https_file_supported_formats[0] = "https";
3128
3129 https_file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
3130 https_file_interface->interface_name = modname;
3131 https_file_interface->extens = https_file_supported_formats;
3132 https_file_interface->file_open = https_file_file_open;
3133 https_file_interface->file_close = http_file_file_close;
3134 https_file_interface->file_read = http_file_file_read;
3135 https_file_interface->file_write = http_file_write;
3136 https_file_interface->file_seek = http_file_file_seek;
3137
3138 switch_snprintf(globals.cache_path, sizeof(globals.cache_path), "%s%shttp_file_cache", SWITCH_GLOBAL_dirs.storage_dir, SWITCH_PATH_SEPARATOR"/");
3139 switch_dir_make_recursive(globals.cache_path, SWITCH_DEFAULT_DIR_PERMS0x0400 | 0x0200 | 0x0100 | 0x0040 | 0x0010, pool);
3140
3141
3142 switch_core_hash_init(&globals.profile_hash)switch_core_hash_init_case(&globals.profile_hash, SWITCH_TRUE
)
;
3143 switch_core_hash_init(&globals.request_hash)switch_core_hash_init_case(&globals.request_hash, SWITCH_TRUE
)
;
3144 switch_core_hash_init_case(&globals.parse_hash, SWITCH_FALSE);
3145
3146 bind_parser("execute", parse_execute);
3147 bind_parser("sms", parse_sms);
3148 bind_parser("dial", parse_dial);
3149 bind_parser("pause", parse_playback);
3150 bind_parser("answer", parse_answer);
3151 bind_parser("preAnswer", parse_answer);
3152 bind_parser("ringReady", parse_answer);
3153 bind_parser("hangup", parse_hangup);
3154 bind_parser("record", parse_record);
3155 bind_parser("recordCall", parse_record_call);
3156 bind_parser("playback", parse_playback);
3157 bind_parser("vmName", parse_playback);
3158 bind_parser("speak", parse_playback);
3159 bind_parser("say", parse_playback);
3160 bind_parser("conference", parse_conference);
3161 bind_parser("break", parse_break);
3162 bind_parser("log", parse_log);
3163 bind_parser("continue", parse_continue);
3164 bind_parser("getVariable", parse_get_var);
3165 bind_parser("voicemail", parse_voicemail);
3166
3167 if (do_config() != SWITCH_STATUS_SUCCESS) {
3168 return SWITCH_STATUS_FALSE;
3169 }
3170
3171 SWITCH_ADD_API(httapi_api_interface, "httapi",for (;;) { httapi_api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); httapi_api_interface
->interface_name = "httapi"; httapi_api_interface->desc
= "HT-TAPI Hypertext Telephony API"; httapi_api_interface->
function = httapi_api_function; httapi_api_interface->syntax
= "[debug_on|debug_off]"; break; }
3172 "HT-TAPI Hypertext Telephony API", httapi_api_function, HTTAPI_SYNTAX)for (;;) { httapi_api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); httapi_api_interface
->interface_name = "httapi"; httapi_api_interface->desc
= "HT-TAPI Hypertext Telephony API"; httapi_api_interface->
function = httapi_api_function; httapi_api_interface->syntax
= "[debug_on|debug_off]"; break; }
;
3173
3174 SWITCH_ADD_APP(app_interface, "httapi",for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "httapi"; app_interface
->application_function = httapi_function; app_interface->
short_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->long_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->syntax = "{<param1>=<val1>}"; app_interface->
flags = SAF_SUPPORT_NOMEDIA; break; }
3175 "HT-TAPI Hypertext Telephony API",for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "httapi"; app_interface
->application_function = httapi_function; app_interface->
short_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->long_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->syntax = "{<param1>=<val1>}"; app_interface->
flags = SAF_SUPPORT_NOMEDIA; break; }
3176 "HT-TAPI Hypertext Telephony API", httapi_function, "{<param1>=<val1>}", SAF_SUPPORT_NOMEDIA)for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "httapi"; app_interface
->application_function = httapi_function; app_interface->
short_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->long_desc = "HT-TAPI Hypertext Telephony API"; app_interface
->syntax = "{<param1>=<val1>}"; app_interface->
flags = SAF_SUPPORT_NOMEDIA; break; }
;
3177
3178
3179
3180 switch_console_set_complete("add httapi debug_on");
3181 switch_console_set_complete("add httapi debug_off");
3182
3183 /* indicate that the module should continue to be loaded */
3184 return SWITCH_STATUS_SUCCESS;
3185}
3186
3187SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_httapi_shutdown)switch_status_t mod_httapi_shutdown (void)
3188{
3189 hash_node_t *ptr = NULL((void*)0);
3190 client_profile_t *profile;
3191 switch_hash_index_t *hi;
3192 void *val;
3193 const void *vvar;
3194
3195 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
3196 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
3197 profile = (client_profile_t *) val;
3198 switch_event_destroy(&profile->dial_params.app_list);
3199 switch_event_destroy(&profile->var_params.expand_var_list);
3200 switch_event_destroy(&profile->var_params.set_var_list);
3201 switch_event_destroy(&profile->var_params.get_var_list);
3202 }
3203
3204
3205 switch_core_hash_destroy(&globals.profile_hash);
3206 switch_core_hash_destroy(&globals.parse_hash);
3207
3208 while (globals.hash_root) {
3209 ptr = globals.hash_root;
3210 switch_core_hash_destroy(&ptr->hash);
3211 globals.hash_root = ptr->next;
3212 switch_safe_free(ptr)if (ptr) {free(ptr);ptr=((void*)0);};
3213 }
3214
3215 return SWITCH_STATUS_SUCCESS;
3216}
3217
3218/* For Emacs:
3219 * Local Variables:
3220 * mode:c
3221 * indent-tabs-mode:t
3222 * tab-width:4
3223 * c-basic-offset:4
3224 * End:
3225 * For VIM:
3226 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3227 */
3228
3229