Bug Summary

File:src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
Location:line 647, 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 * John Wehle <john@feith.com>
28 * Garmt Boekholt <garmt@cimico.com>
29 * Seven Du <dujinfang@gmail.com>
30 *
31 * mod_xml_rpc.c -- XML RPC
32 *
33 * embedded webserver for FS
34 * exposes fs api to web (and ajax, javascript, ...)
35 * supports GET/POST requests (as defined below)
36 * and similar XMLRPC format /RPC2 freeswitch.api and management.api
37 *
38 * usage:
39 * (1) http:/host:port/[txt|web|xml]api/fsapicommand[?arg[ arg]*][ &key=value[+&key=value]*]
40 * e.g. http:/host:port/api/show?calls &refresh=5+&weather=nice
41 * (2) http:/host:port/filepath - serves files from conf/htdocs
42 *
43 * NB:
44 * ad (1) - key/value pairs are propagated as event headers
45 * - if &key=value is "&refresh=xx" - special feature: automatic refresh after xx sec (triggered by browser)
46 * note that refresh works only
47 * IF response content-type: text/html (i.e. "webapi" or "api")
48 * AND fs api command created an event header HTTP-REFRESH before the first write_stream
49 * NOTE if "api", fs api command has to overwrite content-type to be text/html i.s.o. text/plain (default)
50 *
51 * - if api format is "api" mod_xml_rpc will automatically assume plain/text (so webunaware fs commands are rendered apropriately)
52 * - xmlapi doesn't seem to be used, however if a fs api command renders xml, you can set the format type to xml
53 * txtapi-text/plain or webapi-text/html surround xml with <pre> xml <pre/>
54 * - typically fs api command arguments are encoded with UrlPathEncode (spaces -> %20), and k/v pairs are urlencoded (space -> +)
55 *
56 * ad (2) ms ie may show extra empty lines when serving large txt files as ie has problems rendering content-type "plain/text"
57 *
58 */
59#include <switch.h>
60#ifdef _MSC_VER
61#pragma warning(disable:4142)
62#endif
63
64#include <xmlrpc-c/base.h>
65#include <xmlrpc-c/abyss.h>
66#include <xmlrpc-c/server.h>
67#include <xmlrpc-c/server_abyss.h>
68#include <xmlrpc-c/base64_int.h>
69#include <../lib/abyss/src/token.h>
70#include <../lib/abyss/src/http.h>
71#include <../lib/abyss/src/session.h>
72#include "ws.h"
73
74SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)switch_status_t mod_xml_rpc_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
75SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)switch_status_t mod_xml_rpc_shutdown (void);
76SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)switch_status_t mod_xml_rpc_runtime (void);
77SWITCH_MODULE_DEFINITION(mod_xml_rpc, mod_xml_rpc_load, mod_xml_rpc_shutdown, mod_xml_rpc_runtime)static const char modname[] = "mod_xml_rpc" ; __attribute__((
visibility("default"))) switch_loadable_module_function_table_t
mod_xml_rpc_module_interface = { 5, mod_xml_rpc_load, mod_xml_rpc_shutdown
, mod_xml_rpc_runtime, SMODF_NONE }
;
78
79static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len);
80
81static struct {
82 uint16_t port;
83 uint8_t running;
84 char *realm;
85 char *user;
86 char *pass;
87 char *default_domain;
88 switch_bool_t virtual_host;
89 TServer abyssServer;
90 xmlrpc_registry *registryP;
91 switch_bool_t enable_websocket;
92 char *commands_to_log;
93} globals;
94
95SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_realm, globals.realm)static void set_global_realm(const char *string) { if (!string
) return; if (globals.realm) {free(globals.realm); globals.realm
= ((void*)0);}globals.realm = (__extension__ (__builtin_constant_p
(string) && ((size_t)(const void *)((string) + 1) - (
size_t)(const void *)(string) == 1) ? (((const char *) (string
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (string) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, string, __len); __retval; })) : __strdup
(string)));} static void set_global_realm(const char *string
)
;
96SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_user, globals.user)static void set_global_user(const char *string) { if (!string
) return; if (globals.user) {free(globals.user); globals.user
= ((void*)0);}globals.user = (__extension__ (__builtin_constant_p
(string) && ((size_t)(const void *)((string) + 1) - (
size_t)(const void *)(string) == 1) ? (((const char *) (string
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (string) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, string, __len); __retval; })) : __strdup
(string)));} static void set_global_user(const char *string)
;
97SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_pass, globals.pass)static void set_global_pass(const char *string) { if (!string
) return; if (globals.pass) {free(globals.pass); globals.pass
= ((void*)0);}globals.pass = (__extension__ (__builtin_constant_p
(string) && ((size_t)(const void *)((string) + 1) - (
size_t)(const void *)(string) == 1) ? (((const char *) (string
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (string) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, string, __len); __retval; })) : __strdup
(string)));} static void set_global_pass(const char *string)
;
98SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_default_domain, globals.default_domain)static void set_global_default_domain(const char *string) { if
(!string) return; if (globals.default_domain) {free(globals.
default_domain); globals.default_domain = ((void*)0);}globals
.default_domain = (__extension__ (__builtin_constant_p (string
) && ((size_t)(const void *)((string) + 1) - (size_t)
(const void *)(string) == 1) ? (((const char *) (string))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (string) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, string, __len); __retval; })) : __strdup (string)));} static
void set_global_default_domain(const char *string)
;
99
100static switch_status_t do_config(void)
101{
102 char *cf = "xml_rpc.conf";
103 switch_xml_t cfg, xml, settings, param;
104 char *realm, *user, *pass, *default_domain;
105
106 default_domain = realm = user = pass = NULL((void*)0);
107 globals.commands_to_log = NULL((void*)0);
108
109 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL((void*)0)))) {
110 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 110, ((void*)0)
, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
111 return SWITCH_STATUS_TERM;
112 }
113
114 globals.virtual_host = SWITCH_TRUE;
115
116 if ((settings = switch_xml_child(cfg, "settings"))) {
117 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
118 char *var = (char *) switch_xml_attr_soft(param, "name");
119 char *val = (char *) switch_xml_attr_soft(param, "value");
120
121 if (!zstr(var)_zstr(var) && !zstr(val)_zstr(val)) {
122 if (!strcasecmp(var, "auth-realm")) {
123 realm = val;
124 } else if (!strcasecmp(var, "auth-user")) {
125 user = val;
126 } else if (!strcasecmp(var, "auth-pass")) {
127 pass = val;
128 } else if (!strcasecmp(var, "http-port")) {
129 globals.port = (uint16_t) atoi(val);
130 } else if (!strcasecmp(var, "default-domain")) {
131 default_domain = val;
132 } else if (!strcasecmp(var, "virtual-host")) {
133 globals.virtual_host = switch_true(val);
134 } else if (!strcasecmp(var, "enable-websocket")) {
135 globals.enable_websocket = switch_true(val);
136 } else if (!strcasecmp(var, "commands-to-log")) {
137 globals.commands_to_log = val;
138 }
139 }
140 }
141 }
142
143 if (!globals.port) {
144 globals.port = 8080;
145 }
146 if (realm) {
147 set_global_realm(realm);
148 if (user && pass) {
149 set_global_user(user);
150 set_global_pass(pass);
151 }
152 }
153 if (default_domain) {
154 set_global_default_domain(default_domain);
155 }
156 switch_xml_free(xml);
157
158 return SWITCH_STATUS_SUCCESS;
159}
160
161SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)switch_status_t mod_xml_rpc_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
162{
163 /* connect my internal structure to the blank pointer passed to me */
164 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
165
166 memset(&globals, 0, sizeof(globals));
167
168 do_config();
169
170 /* indicate that the module should continue to be loaded */
171 return SWITCH_STATUS_SUCCESS;
172}
173
174static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)
175{
176 TSession *r = (TSession *) handle->data;
177
178 return HTTPWrite(r, (char *) data, (uint32_t) datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
179
180}
181
182static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...)
183{
184 TSession *r = (TSession *) handle->data;
185 int ret = 1;
186 char *data;
187 switch_event_t *evnt = handle->param_event;
188 va_list ap;
189
190 va_start(ap, fmt)__builtin_va_start(ap, fmt);
191 ret = switch_vasprintf(&data, fmt, ap);
192 va_end(ap)__builtin_va_end(ap);
193
194 if (data) {
195 /* Stream Content-Type (http header) to the xmlrpc (web) client, if fs api command did not do it yet. */
196 /* If (Content-Type in event) then the header was already replied. */
197 /* If fs api command is not "web aware", this will set the Content-Type to "text/plain". */
198 const char *http_refresh = NULL((void*)0);
199 const char *ct = NULL((void*)0);
200 const char *refresh = NULL((void*)0);
201 if (evnt && !(ct = switch_event_get_header(evnt, "Content-Type")switch_event_get_header_idx(evnt, "Content-Type", -1))){
202 const char *val = switch_stristr("Content-Type", data);
203 if (!val) {
204 val = "Content-Type: text/plain\r\n\r\n";
205 ret = HTTPWrite(r, val, (uint32_t) strlen(val));
206 }
207 /* flag to prevent running this more than once per http reply */
208 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", strstr(val,":")+2);
209 ct = switch_event_get_header(evnt, "Content-Type")switch_event_get_header_idx(evnt, "Content-Type", -1);
210 }
211
212 if (ret) {
213 ret = HTTPWrite(r, data, (uint32_t) strlen(data));
214 }
215 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
216
217 /* e.g. "http://www.cluecon.fs/api/show?calls &refresh=5" */
218 /* fs api command can set event header "HTTP-REFRESH" so that the web page will automagically refresh, if */
219 /* "refresh=xxx" was part of the http query kv pairs */
220 if (ret && ct && *ct && (http_refresh = switch_event_get_header(evnt, "HTTP-REFRESH")switch_event_get_header_idx(evnt, "HTTP-REFRESH", -1))
221 && (refresh = switch_event_get_header(evnt, "refresh")switch_event_get_header_idx(evnt, "refresh", -1))
222 && !strstr("text/html", ct)
223 && (atoi(refresh) > 0 )) {
224 const char *query = switch_event_get_header(evnt, "HTTP-QUERY")switch_event_get_header_idx(evnt, "HTTP-QUERY", -1);
225 const char *uri = switch_event_get_header(evnt, "HTTP-URI")switch_event_get_header_idx(evnt, "HTTP-URI", -1);
226 if (uri && query && *uri && *query) {
227 char *buf = switch_mprintf("<META HTTP-EQUIV=REFRESH CONTENT=\"%s; URL=%s?%s\">\n", refresh, uri, query);
228 ret = HTTPWrite(r, buf, (uint32_t) strlen(buf));
229 switch_safe_free(buf)if (buf) {free(buf);buf=((void*)0);};
230 }
231 }
232
233 /* only one refresh meta header per reply */
234 if (http_refresh) {
235 switch_event_del_header(evnt, "HTTP-REFRESH")switch_event_del_header_val(evnt, "HTTP-REFRESH", ((void*)0));
236 }
237 }
238
239 return ret ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
240}
241
242static abyss_bool user_attributes(const char *user, const char *domain_name,
243 const char **ppasswd, const char **pvm_passwd, const char **palias, const char **pallowed_commands)
244{
245 const char *passwd;
246 const char *vm_passwd;
247 const char *alias;
248 const char *allowed_commands;
249 switch_event_t *params;
250 switch_xml_t x_user, x_params, x_param;
251
252 passwd = NULL((void*)0);
253 vm_passwd = NULL((void*)0);
254 alias = NULL((void*)0);
255 allowed_commands = NULL((void*)0);
256
257 if (ppasswd) *ppasswd = NULL((void*)0);
258 if (pvm_passwd) *pvm_passwd = NULL((void*)0);
259 if (palias) *palias = NULL((void*)0);
260 if (pallowed_commands) *pallowed_commands = NULL((void*)0);
261
262 params = NULL((void*)0);
263
264 switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_xml_rpc.c", (const
char * )(const char *)__func__, 264, &params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
265 switch_assert(params)((params) ? (void) (0) : __assert_fail ("params", "mod_xml_rpc.c"
, 265, __PRETTY_FUNCTION__))
;
266 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "number_alias", "check");
267
268
269 if (switch_xml_locate_user_merged("id", user, domain_name, NULL((void*)0), &x_user, params) != SWITCH_STATUS_SUCCESS) {
270 switch_event_destroy(&params);
271 return FALSE0;
272 }
273
274 switch_event_destroy(&params);
275 alias = switch_xml_attr(x_user, "number-alias");
276
277 if ((x_params = switch_xml_child(x_user, "params"))) {
278 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
279 const char *var = switch_xml_attr_soft(x_param, "name");
280 const char *val = switch_xml_attr_soft(x_param, "value");
281
282 if (!strcasecmp(var, "password")) {
283 passwd = val;
284 } else if (!strcasecmp(var, "vm-password")) {
285 vm_passwd = val;
286 } else if (!strcasecmp(var, "http-allowed-api")) {
287 allowed_commands = val;
288 }
289 }
290 }
291
292 if (ppasswd && passwd) {
293 *ppasswd = strdup(passwd)(__extension__ (__builtin_constant_p (passwd) && ((size_t
)(const void *)((passwd) + 1) - (size_t)(const void *)(passwd
) == 1) ? (((const char *) (passwd))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (passwd)
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, passwd, __len
); __retval; })) : __strdup (passwd)))
;
294 }
295
296 if (pvm_passwd && vm_passwd) {
297 *pvm_passwd = strdup(vm_passwd)(__extension__ (__builtin_constant_p (vm_passwd) && (
(size_t)(const void *)((vm_passwd) + 1) - (size_t)(const void
*)(vm_passwd) == 1) ? (((const char *) (vm_passwd))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (vm_passwd) + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, vm_passwd, __len); __retval; })) : __strdup (vm_passwd
)))
;
298 }
299
300 if (palias && alias) {
301 *palias = strdup(alias)(__extension__ (__builtin_constant_p (alias) && ((size_t
)(const void *)((alias) + 1) - (size_t)(const void *)(alias) ==
1) ? (((const char *) (alias))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (alias) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, alias, __len
); __retval; })) : __strdup (alias)))
;
302 }
303
304 if (pallowed_commands && allowed_commands) {
305 *pallowed_commands = strdup(allowed_commands)(__extension__ (__builtin_constant_p (allowed_commands) &&
((size_t)(const void *)((allowed_commands) + 1) - (size_t)(const
void *)(allowed_commands) == 1) ? (((const char *) (allowed_commands
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (allowed_commands) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, allowed_commands, __len); __retval
; })) : __strdup (allowed_commands)))
;
306 }
307
308 if (x_user) {
309 switch_xml_free(x_user);
310 }
311
312 return TRUE(!0);
313}
314
315static abyss_bool is_authorized(const TSession * r, const char *command)
316{
317 char *user = NULL((void*)0), *domain_name = NULL((void*)0);
318 char *allowed_commands = NULL((void*)0);
319 char *dp;
320 char *dup = NULL((void*)0);
321 char *argv[256] = { 0 };
322 int argc = 0, i = 0, ok = 0;
323 unsigned int err = 403;
324
325 if (!r) {
326 return FALSE0;
327 }
328
329 if (zstr(globals.realm)_zstr(globals.realm) && zstr(globals.user)_zstr(globals.user)) {
330 return TRUE(!0);
331 }
332
333 if (!r->requestInfo.user) {
334 return FALSE0;
335 }
336
337 user = strdup(r->requestInfo.user)(__extension__ (__builtin_constant_p (r->requestInfo.user)
&& ((size_t)(const void *)((r->requestInfo.user) +
1) - (size_t)(const void *)(r->requestInfo.user) == 1) ? (
((const char *) (r->requestInfo.user))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
r->requestInfo.user) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, r->requestInfo.user, __len); __retval; })) : __strdup
(r->requestInfo.user)))
;
338
339 if ((dp = strchr(user, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(user) && ('@') == '\0' ? (char *) __rawmemchr (user
, '@') : __builtin_strchr (user, '@')))
)) {
340 *dp++ = '\0';
341 domain_name = dp;
342 }
343
344 if (!zstr(globals.realm)_zstr(globals.realm) && !zstr(globals.user)_zstr(globals.user) && !strcmp(user, globals.user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(user) && __builtin_constant_p (globals.user) &&
(__s1_len = __builtin_strlen (user), __s2_len = __builtin_strlen
(globals.user), (!((size_t)(const void *)((user) + 1) - (size_t
)(const void *)(user) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((globals.user) + 1) - (size_t)(const
void *)(globals.user) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(user, globals.user) : (__builtin_constant_p (user) &&
((size_t)(const void *)((user) + 1) - (size_t)(const void *)
(user) == 1) && (__s1_len = __builtin_strlen (user), __s1_len
< 4) ? (__builtin_constant_p (globals.user) && ((
size_t)(const void *)((globals.user) + 1) - (size_t)(const void
*)(globals.user) == 1) ? __builtin_strcmp (user, globals.user
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (globals.user); int __result = (((const
unsigned char *) (const char *) (user))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (user))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (user))[2] - __s2[2]); if (__s1_len > 2
&& __result == 0) __result = (((const unsigned char *
) (const char *) (user))[3] - __s2[3]); } } __result; }))) : (
__builtin_constant_p (globals.user) && ((size_t)(const
void *)((globals.user) + 1) - (size_t)(const void *)(globals
.user) == 1) && (__s2_len = __builtin_strlen (globals
.user), __s2_len < 4) ? (__builtin_constant_p (user) &&
((size_t)(const void *)((user) + 1) - (size_t)(const void *)
(user) == 1) ? __builtin_strcmp (user, globals.user) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (user); int __result = (((const unsigned char *) (const
char *) (globals.user))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (globals.user))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (globals.user))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (globals.user))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(user, globals.user)))); })
) {
345 ok = 1;
346 goto end;
347 }
348
349 if (zstr(user)_zstr(user) || zstr(domain_name)_zstr(domain_name)) {
350 goto end;
351 }
352
353
354 err = 686;
355
356 if (!user_attributes(user, domain_name, NULL((void*)0), NULL((void*)0), NULL((void*)0), &allowed_commands)) {
357 goto end;
358 }
359
360 switch_safe_free(user)if (user) {free(user);user=((void*)0);};
361
362 if (!allowed_commands) {
363 goto end;
364 }
365
366 if ((dup = allowed_commands)) {
367 argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
368
369 for (i = 0; i < argc && argv[i]; i++) {
370 if (!strcasecmp(argv[i], command) || !strcasecmp(argv[i], "any")) {
371 ok = 1;
372 break;
373 }
374 }
375 }
376
377 end:
378
379 switch_safe_free(user)if (user) {free(user);user=((void*)0);};
380 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
381
382 if (!ok) {
383 ResponseStatus(r, (xmlrpc_uint16_t)err);
384 }
385
386
387 return ok ? TRUE(!0) : FALSE0;
388}
389
390static abyss_bool http_directory_auth(TSession *r, char *domain_name)
391{
392 char *p = NULL((void*)0);
393 char *x = NULL((void*)0);
394 char z[256] = "", t[80] = "";
395 char user[512] = "" ;
396 char *pass = NULL((void*)0);
397 const char *mypass1 = NULL((void*)0), *mypass2 = NULL((void*)0);
398 const char *box = NULL((void*)0);
399 int at = 0;
400 char *dp = NULL((void*)0);
401 abyss_bool rval = FALSE0;
402 char *dup_domain = NULL((void*)0);
403
404 p = RequestHeaderValue(r, "authorization");
405
406 if (p) {
407 NextToken((const char **const) &p);
408 x = GetToken(&p);
409 if (x) {
410 if (!strcasecmp(x, "basic")) {
411 NextToken((const char **const) &p);
412 switch_b64_decode(p, user, sizeof(user));
413 if ((pass = strchr(user, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(user) && (':') == '\0' ? (char *) __rawmemchr (user
, ':') : __builtin_strchr (user, ':')))
)) {
414 *pass++ = '\0';
415 }
416
417 if ((dp = strchr(user, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(user) && ('@') == '\0' ? (char *) __rawmemchr (user
, '@') : __builtin_strchr (user, '@')))
)) {
418 *dp++ = '\0';
419 domain_name = dp;
420 at++;
421 }
422
423 if (!domain_name) {
424 if (globals.virtual_host) {
425 if ((domain_name = (char *) r->requestInfo.host)) {
426 if (!strncasecmp(domain_name, "www.", 3)) {
427 domain_name += 4;
428 }
429 }
430 }
431 if (!domain_name) {
432 if (globals.default_domain) {
433 domain_name = globals.default_domain;
434 } else {
435 if ((dup_domain = switch_core_get_domain(SWITCH_TRUE))) {
436 domain_name = dup_domain;
437 }
438 }
439 }
440 }
441
442 if (zstr(user)_zstr(user) || zstr(domain_name)_zstr(domain_name)) {
443 goto fail;
444 }
445
446 if (!zstr(globals.realm)_zstr(globals.realm) && !zstr(globals.user)_zstr(globals.user) && !zstr(globals.pass)_zstr(globals.pass)) {
447 if (at) {
448 switch_snprintf(z, sizeof(z), "%s@%s:%s", globals.user, globals.realm, globals.pass);
449 } else {
450 switch_snprintf(z, sizeof(z), "%s:%s", globals.user, globals.pass);
451 }
452 xmlrpc_base64Encode(z, t);
453
454 if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p) && __builtin_constant_p (t) && (__s1_len
= __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!(
(size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >=
4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) &&
((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p)
== 1) && (__s1_len = __builtin_strlen (p), __s1_len <
4) ? (__builtin_constant_p (t) && ((size_t)(const void
*)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp
(p, t) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (t); int __result = (((const
unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (p))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(t) && ((size_t)(const void *)((t) + 1) - (size_t)(const
void *)(t) == 1) && (__s2_len = __builtin_strlen (t)
, __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t
)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp
(p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (p); int __result = (((const
unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (t))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(p, t)))); })
) {
455 goto authed;
456 }
457 }
458
459 if (!user_attributes(user, domain_name, &mypass1, &mypass2, &box, NULL((void*)0))) {
460 goto fail;
461 }
462
463
464 if (!zstr(mypass2)_zstr(mypass2) && !strcasecmp(mypass2, "user-choose")) {
465 switch_safe_free(mypass2)if (mypass2) {free(mypass2);mypass2=((void*)0);};
466 }
467
468 if (!mypass1) {
469 goto authed;
470 } else {
471 if (at) {
472 switch_snprintf(z, sizeof(z), "%s@%s:%s", user, domain_name, mypass1);
473 } else {
474 switch_snprintf(z, sizeof(z), "%s:%s", user, mypass1);
475 }
476 xmlrpc_base64Encode(z, t);
477
478 if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p) && __builtin_constant_p (t) && (__s1_len
= __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!(
(size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >=
4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) &&
((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p)
== 1) && (__s1_len = __builtin_strlen (p), __s1_len <
4) ? (__builtin_constant_p (t) && ((size_t)(const void
*)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp
(p, t) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (t); int __result = (((const
unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (p))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(t) && ((size_t)(const void *)((t) + 1) - (size_t)(const
void *)(t) == 1) && (__s2_len = __builtin_strlen (t)
, __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t
)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp
(p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (p); int __result = (((const
unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (t))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(p, t)))); })
) {
479 goto authed;
480 }
481
482 if (mypass2) {
483 if (at) {
484 switch_snprintf(z, sizeof(z), "%s@%s:%s", user, domain_name, mypass2);
485 } else {
486 switch_snprintf(z, sizeof(z), "%s:%s", user, mypass2);
487 }
488 xmlrpc_base64Encode(z, t);
489
490 if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p) && __builtin_constant_p (t) && (__s1_len
= __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!(
(size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >=
4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) &&
((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p)
== 1) && (__s1_len = __builtin_strlen (p), __s1_len <
4) ? (__builtin_constant_p (t) && ((size_t)(const void
*)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp
(p, t) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (t); int __result = (((const
unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (p))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(t) && ((size_t)(const void *)((t) + 1) - (size_t)(const
void *)(t) == 1) && (__s2_len = __builtin_strlen (t)
, __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t
)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp
(p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (p); int __result = (((const
unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (t))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(p, t)))); })
) {
491 goto authed;
492 }
493 }
494
495 if (box) {
496 if (at) {
497 switch_snprintf(z, sizeof(z), "%s@%s:%s", box, domain_name, mypass1);
498 } else {
499 switch_snprintf(z, sizeof(z), "%s:%s", box, mypass1);
500 }
501 xmlrpc_base64Encode(z, t);
502
503 if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p) && __builtin_constant_p (t) && (__s1_len
= __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!(
(size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >=
4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) &&
((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p)
== 1) && (__s1_len = __builtin_strlen (p), __s1_len <
4) ? (__builtin_constant_p (t) && ((size_t)(const void
*)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp
(p, t) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (t); int __result = (((const
unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (p))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(t) && ((size_t)(const void *)((t) + 1) - (size_t)(const
void *)(t) == 1) && (__s2_len = __builtin_strlen (t)
, __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t
)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp
(p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (p); int __result = (((const
unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (t))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(p, t)))); })
) {
504 goto authed;
505 }
506
507 if (mypass2) {
508 if (at) {
509 switch_snprintf(z, sizeof(z), "%s@%s:%s", box, domain_name, mypass2);
510 } else {
511 switch_snprintf(z, sizeof(z), "%s:%s", box, mypass2);
512 }
513
514 xmlrpc_base64Encode(z, t);
515
516 if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(p) && __builtin_constant_p (t) && (__s1_len
= __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!(
(size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >=
4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) &&
((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p)
== 1) && (__s1_len = __builtin_strlen (p), __s1_len <
4) ? (__builtin_constant_p (t) && ((size_t)(const void
*)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp
(p, t) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (t); int __result = (((const
unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (p))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(t) && ((size_t)(const void *)((t) + 1) - (size_t)(const
void *)(t) == 1) && (__s2_len = __builtin_strlen (t)
, __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t
)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp
(p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (p); int __result = (((const
unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (t))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(p, t)))); })
) {
517 goto authed;
518 }
519 }
520 }
521 }
522 goto fail;
523
524 authed:
525
526 switch_snprintf(z, sizeof(z), "%s@%s", (box ? box : user), domain_name);
527 r->requestInfo.user = strdup(z)(__extension__ (__builtin_constant_p (z) && ((size_t)
(const void *)((z) + 1) - (size_t)(const void *)(z) == 1) ? (
((const char *) (z))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen (z) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, z, __len); __retval; })) : __strdup
(z)))
;
528
529 ResponseAddField(r, "freeswitch-user", (box ? box : user));
530 ResponseAddField(r, "freeswitch-domain", domain_name);
531 rval = TRUE(!0);
532 goto done;
533 }
534 }
535 }
536
537 fail:
538
539 switch_snprintf(z, sizeof(z), "Basic realm=\"%s\"", domain_name ? domain_name : globals.realm);
540 ResponseAddField(r, "WWW-Authenticate", z);
541 ResponseStatus(r, 401);
542
543 done:
544
545 switch_safe_free(mypass1)if (mypass1) {free(mypass1);mypass1=((void*)0);};
546 switch_safe_free(mypass2)if (mypass2) {free(mypass2);mypass2=((void*)0);};
547 switch_safe_free(box)if (box) {free(box);box=((void*)0);};
548 switch_safe_free(dup_domain)if (dup_domain) {free(dup_domain);dup_domain=((void*)0);};
549
550 return rval;
551}
552
553void stop_hook_event_handler(switch_event_t *event) {
554 wsh_t *wsh = (wsh_t *)event->bind_user_data;
555
556 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 556, ((void*)0)
, SWITCH_LOG_NOTICE, "got websocket::stophook, closing\n");
557 wsh->down++;
558}
559
560void event_handler(switch_event_t *event) {
561 char *json;
562 wsh_t *wsh = (wsh_t *)event->bind_user_data;
563 switch_event_serialize_json(event, &json);
564 ws_write_frame(wsh, WSOC_TEXT, json, strlen(json));
565 free(json);
566}
567
568#define MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL SWITCH_EVENT_ALL
569
570abyss_bool websocket_hook(TSession *r)
571{
572 wsh_t *wsh;
573 int ret;
574 int i;
575 ws_opcode_t opcode;
576 uint8_t *data;
577 switch_event_node_t *nodes[MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL];
578 int node_count = 0;
579 char *p;
580 char *key = NULL((void*)0);
581 char *version = NULL((void*)0);
582 char *proto = NULL((void*)0);
583 char *upgrade = NULL((void*)0);
584
585 for (i = 0; i < r->requestHeaderFields.size; i++) {
1
Loop condition is false. Execution continues on line 591
586 TTableItem * const item = &r->requestHeaderFields.item[i];
587
588 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 588, ((void*)0)
, SWITCH_LOG_INFO, "headers %s: %s\n", item->name, item->value);
589 }
590
591 key = RequestHeaderValue(r, "sec-websocket-key");
592 version = RequestHeaderValue(r, "sec-websocket-version");
593 proto = RequestHeaderValue(r, "sec-websocket-protocol");
594 upgrade = RequestHeaderValue(r, "upgrade");
595
596 if (!key || !version || !proto || !upgrade) return FALSE0;
2
Assuming 'key' is non-null
3
Assuming 'version' is non-null
4
Assuming 'proto' is non-null
5
Assuming 'upgrade' is non-null
6
Taking false branch
597 if (strncasecmp(upgrade, "websocket", 9) || strncasecmp(proto, "websocket", 9)) return FALSE0;
7
Taking false branch
598
599 wsh = ws_init(r);
600 if (!wsh) {
8
Assuming 'wsh' is non-null
9
Taking false branch
601 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 601, ((void*)0)
, SWITCH_LOG_ERROR, "websocket memory error\n");
602 return FALSE0;
603 }
604
605 ret = ws_handshake_kvp(wsh, key, version, proto);
606 if (ret < 0) wsh->down = 1;
10
Assuming 'ret' is >= 0
11
Taking false branch
607
608 if (ret != 0) {
12
Assuming 'ret' is equal to 0
13
Taking false branch
609 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 609, ((void*)0)
, SWITCH_LOG_ERROR, "handshake error %d\n", ret);
610 return FALSE0;
611 }
612
613 if (switch_event_bind_removable("websocket", SWITCH_EVENT_CUSTOM, "websocket::stophook", stop_hook_event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) {
14
Taking false branch
614 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 614, ((void*)0)
, SWITCH_LOG_ERROR, "Can't bind!\n");
615 node_count--;
616 }
617
618 while (!wsh->down) {
15
Loop condition is true. Entering loop body
619 int bytes = ws_read_frame(wsh, &opcode, &data);
620
621 if (bytes < 0) {
16
Assuming 'bytes' is >= 0
17
Taking false branch
622 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 622, ((void*)0)
, SWITCH_LOG_INFO, "%d %s\n", opcode, (char *)data);
623 switch_yield(100000)switch_sleep(100000);;
624 continue;
625 }
626
627 switch (opcode) {
18
Control jumps to 'case WSOC_TEXT:' at line 634
628 case WSOC_CLOSE:
629 ws_close(wsh, 1000);
630 break;
631 case WSOC_CONTINUATION:
632 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 632, ((void*)0)
, SWITCH_LOG_ERROR, "continue\n");
633 continue;
634 case WSOC_TEXT:
635 p = data;
636 if (!p) continue;
19
Assuming 'p' is non-null
20
Taking false branch
637 if (!strncasecmp(data, "event ", 6)) {
21
Taking true branch
638 switch_event_types_t type;
639 char *subclass;
640
641 if (node_count == MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL - 1) {
22
Taking false branch
642 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 642, ((void*)0)
, SWITCH_LOG_ERROR, "cannot subscribe more than %d events\n", node_count);
643 continue;
644 }
645 p += 6;
646 if (p = strchr(p, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(p) && (' ') == '\0' ? (char *) __rawmemchr (p, ' ')
: __builtin_strchr (p, ' ')))
) p++;
23
Value assigned to 'p'
24
Assuming 'p' is null
25
Assuming pointer value is null
26
Taking false branch
647 if (!strncasecmp(p, "json ", 5)) {
27
Null pointer passed as an argument to a 'nonnull' parameter
648 p += 5;
649 } else if (!strncasecmp(p, "xml ", 4)) {
650 p += 4;
651 } else if (!strncasecmp(p, "plain ", 6)) {
652 p += 6;
653 }
654 if (!*p) {
655 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 655, ((void*)0)
, SWITCH_LOG_WARNING, "missing event type in [%s]\n", data);
656 break;
657 } else {
658 }
659 if (subclass = strchr(p, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(p) && (' ') == '\0' ? (char *) __rawmemchr (p, ' ')
: __builtin_strchr (p, ' ')))
) {
660 *subclass++ = '\0';
661 if (!*subclass) {
662 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 662, ((void*)0)
, SWITCH_LOG_ERROR, "missing subclass\n");
663 continue;
664 }
665 } else {
666 subclass = SWITCH_EVENT_SUBCLASS_ANY((void*)0);
667 }
668
669 if (switch_name_event(p, &type) != SWITCH_STATUS_SUCCESS) {
670 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 670, ((void*)0)
, SWITCH_LOG_ERROR, "Unknown event %s\n", p);
671 continue;
672 }
673
674 if (switch_event_bind_removable("websocket", type, subclass, event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) {
675 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 675, ((void*)0)
, SWITCH_LOG_ERROR, "Can't bind!\n");
676 node_count--;
677 continue;
678 } else {
679 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 679, ((void*)0)
, SWITCH_LOG_INFO, "Bind %s\n", data);
680 }
681
682 }
683 break;
684 default:
685 break;
686 }
687 }
688
689 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 689, ((void*)0)
, SWITCH_LOG_ERROR, "wsh->down = %d, node_count = %d\n", wsh->down, node_count);
690
691 switch_yield(2000)switch_sleep(2000);;
692 while (--node_count >= 0) switch_event_unbind(&nodes[node_count]);
693
694 switch_safe_free(wsh)if (wsh) {free(wsh);wsh=((void*)0);};
695
696 return FALSE0;
697}
698
699abyss_bool auth_hook(TSession * r)
700{
701 char *domain_name, *e;
702 abyss_bool ret = FALSE0;
703
704 if (globals.enable_websocket && !strncmp(r->requestInfo.uri, "/socket", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(r->requestInfo.uri) && strlen (r->requestInfo
.uri) < ((size_t) (7))) || (__builtin_constant_p ("/socket"
) && strlen ("/socket") < ((size_t) (7)))) ? __extension__
({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo
.uri) && __builtin_constant_p ("/socket") && (
__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len
= __builtin_strlen ("/socket"), (!((size_t)(const void *)((r
->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo
.uri) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(("/socket") + 1) - (size_t)(const void *)("/socket")
== 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo
.uri, "/socket") : (__builtin_constant_p (r->requestInfo.uri
) && ((size_t)(const void *)((r->requestInfo.uri) +
1) - (size_t)(const void *)(r->requestInfo.uri) == 1) &&
(__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len
< 4) ? (__builtin_constant_p ("/socket") && ((size_t
)(const void *)(("/socket") + 1) - (size_t)(const void *)("/socket"
) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/socket")
: (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("/socket"); int __result = (((const unsigned
char *) (const char *) (r->requestInfo.uri))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (r->requestInfo.
uri))[1] - __s2[1]); if (__s1_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (r->
requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (r->requestInfo.uri))[3] - __s2[3]); } } __result; }))
) : (__builtin_constant_p ("/socket") && ((size_t)(const
void *)(("/socket") + 1) - (size_t)(const void *)("/socket")
== 1) && (__s2_len = __builtin_strlen ("/socket"), __s2_len
< 4) ? (__builtin_constant_p (r->requestInfo.uri) &&
((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t
)(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp
(r->requestInfo.uri, "/socket") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(r->requestInfo.uri); int __result = (((const unsigned char
*) (const char *) ("/socket"))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/socket"))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/socket"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ("/socket"))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp (r->requestInfo.uri, "/socket"))))
; }) : strncmp (r->requestInfo.uri, "/socket", 7)))
) {
705 // Chrome has no Authorization support yet
706 // https://code.google.com/p/chromium/issues/detail?id=123862
707 return websocket_hook(r);
708 }
709
710 if (!strncmp(r->requestInfo.uri, "/portal", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
(r->requestInfo.uri) && strlen (r->requestInfo
.uri) < ((size_t) (7))) || (__builtin_constant_p ("/portal"
) && strlen ("/portal") < ((size_t) (7)))) ? __extension__
({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo
.uri) && __builtin_constant_p ("/portal") && (
__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len
= __builtin_strlen ("/portal"), (!((size_t)(const void *)((r
->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo
.uri) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(("/portal") + 1) - (size_t)(const void *)("/portal")
== 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo
.uri, "/portal") : (__builtin_constant_p (r->requestInfo.uri
) && ((size_t)(const void *)((r->requestInfo.uri) +
1) - (size_t)(const void *)(r->requestInfo.uri) == 1) &&
(__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len
< 4) ? (__builtin_constant_p ("/portal") && ((size_t
)(const void *)(("/portal") + 1) - (size_t)(const void *)("/portal"
) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/portal")
: (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("/portal"); int __result = (((const unsigned
char *) (const char *) (r->requestInfo.uri))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (r->requestInfo.
uri))[1] - __s2[1]); if (__s1_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (r->
requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (r->requestInfo.uri))[3] - __s2[3]); } } __result; }))
) : (__builtin_constant_p ("/portal") && ((size_t)(const
void *)(("/portal") + 1) - (size_t)(const void *)("/portal")
== 1) && (__s2_len = __builtin_strlen ("/portal"), __s2_len
< 4) ? (__builtin_constant_p (r->requestInfo.uri) &&
((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t
)(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp
(r->requestInfo.uri, "/portal") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(r->requestInfo.uri); int __result = (((const unsigned char
*) (const char *) ("/portal"))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/portal"))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/portal"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ("/portal"))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp (r->requestInfo.uri, "/portal"))))
; }) : strncmp (r->requestInfo.uri, "/portal", 7)))
&& strlen(r->requestInfo.uri) <= 8) {
711 ResponseAddField(r, "Location", "/portal/index.html");
712 ResponseStatus(r, 302);
713 return TRUE(!0);
714 }
715
716 if (!strncmp(r->requestInfo.uri, "/domains/", 9)(__extension__ (__builtin_constant_p (9) && ((__builtin_constant_p
(r->requestInfo.uri) && strlen (r->requestInfo
.uri) < ((size_t) (9))) || (__builtin_constant_p ("/domains/"
) && strlen ("/domains/") < ((size_t) (9)))) ? __extension__
({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo
.uri) && __builtin_constant_p ("/domains/") &&
(__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len
= __builtin_strlen ("/domains/"), (!((size_t)(const void *)(
(r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo
.uri) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo
.uri, "/domains/") : (__builtin_constant_p (r->requestInfo
.uri) && ((size_t)(const void *)((r->requestInfo.uri
) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) &&
(__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len
< 4) ? (__builtin_constant_p ("/domains/") && ((size_t
)(const void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/"
) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/domains/"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("/domains/"); int __result = (((const
unsigned char *) (const char *) (r->requestInfo.uri))[0] -
__s2[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (r->requestInfo
.uri))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
r->requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (r->requestInfo.uri))[3] - __s2[3]); } } __result; }))
) : (__builtin_constant_p ("/domains/") && ((size_t)(
const void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/"
) == 1) && (__s2_len = __builtin_strlen ("/domains/")
, __s2_len < 4) ? (__builtin_constant_p (r->requestInfo
.uri) && ((size_t)(const void *)((r->requestInfo.uri
) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) ?
__builtin_strcmp (r->requestInfo.uri, "/domains/") : (- (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (r->requestInfo.uri); int __result = ((
(const unsigned char *) (const char *) ("/domains/"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("/domains/"))[1]
- __s2[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("/domains/"))[2]
- __s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) ("/domains/"))[3]
- __s2[3]); } } __result; })))) : __builtin_strcmp (r->requestInfo
.uri, "/domains/")))); }) : strncmp (r->requestInfo.uri, "/domains/"
, 9)))
) {
717 domain_name = strdup(r->requestInfo.uri + 9)(__extension__ (__builtin_constant_p (r->requestInfo.uri +
9) && ((size_t)(const void *)((r->requestInfo.uri
+ 9) + 1) - (size_t)(const void *)(r->requestInfo.uri + 9
) == 1) ? (((const char *) (r->requestInfo.uri + 9))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (r->requestInfo.uri + 9) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, r->requestInfo.uri + 9, __len)
; __retval; })) : __strdup (r->requestInfo.uri + 9)))
;
718 switch_assert(domain_name)((domain_name) ? (void) (0) : __assert_fail ("domain_name", "mod_xml_rpc.c"
, 718, __PRETTY_FUNCTION__))
;
719
720 if ((e = strchr(domain_name, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p
(domain_name) && ('/') == '\0' ? (char *) __rawmemchr
(domain_name, '/') : __builtin_strchr (domain_name, '/')))
)) {
721 *e++ = '\0';
722 }
723
724 if (!strcmp(domain_name, "this")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(domain_name) && __builtin_constant_p ("this") &&
(__s1_len = __builtin_strlen (domain_name), __s2_len = __builtin_strlen
("this"), (!((size_t)(const void *)((domain_name) + 1) - (size_t
)(const void *)(domain_name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("this") + 1) - (size_t)(const void
*)("this") == 1) || __s2_len >= 4)) ? __builtin_strcmp (domain_name
, "this") : (__builtin_constant_p (domain_name) && ((
size_t)(const void *)((domain_name) + 1) - (size_t)(const void
*)(domain_name) == 1) && (__s1_len = __builtin_strlen
(domain_name), __s1_len < 4) ? (__builtin_constant_p ("this"
) && ((size_t)(const void *)(("this") + 1) - (size_t)
(const void *)("this") == 1) ? __builtin_strcmp (domain_name,
"this") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("this"); int __result = (((
const unsigned char *) (const char *) (domain_name))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (domain_name))[1]
- __s2[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (domain_name))[2]
- __s2[2]); if (__s1_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (domain_name))[3]
- __s2[3]); } } __result; }))) : (__builtin_constant_p ("this"
) && ((size_t)(const void *)(("this") + 1) - (size_t)
(const void *)("this") == 1) && (__s2_len = __builtin_strlen
("this"), __s2_len < 4) ? (__builtin_constant_p (domain_name
) && ((size_t)(const void *)((domain_name) + 1) - (size_t
)(const void *)(domain_name) == 1) ? __builtin_strcmp (domain_name
, "this") : (- (__extension__ ({ const unsigned char *__s2 = (
const unsigned char *) (const char *) (domain_name); int __result
= (((const unsigned char *) (const char *) ("this"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("this"))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("this"))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ("this"))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp (domain_name, "this"
)))); })
) {
725 free(domain_name);
726 domain_name = strdup(r->requestInfo.host)(__extension__ (__builtin_constant_p (r->requestInfo.host)
&& ((size_t)(const void *)((r->requestInfo.host) +
1) - (size_t)(const void *)(r->requestInfo.host) == 1) ? (
((const char *) (r->requestInfo.host))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
r->requestInfo.host) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, r->requestInfo.host, __len); __retval; })) : __strdup
(r->requestInfo.host)))
;
727 }
728
729 ret = !http_directory_auth(r, domain_name);
730
731 free(domain_name);
732 } else {
733 char tmp[512];
734 const char *list[2] = { "index.html", "index.txt" };
735 int x;
736
737 if (!strncmp(r->requestInfo.uri, "/pub", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
(r->requestInfo.uri) && strlen (r->requestInfo
.uri) < ((size_t) (4))) || (__builtin_constant_p ("/pub") &&
strlen ("/pub") < ((size_t) (4)))) ? __extension__ ({ size_t
__s1_len, __s2_len; (__builtin_constant_p (r->requestInfo
.uri) && __builtin_constant_p ("/pub") && (__s1_len
= __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen
("/pub"), (!((size_t)(const void *)((r->requestInfo.uri) +
1) - (size_t)(const void *)(r->requestInfo.uri) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)(("/pub") + 1) -
(size_t)(const void *)("/pub") == 1) || __s2_len >= 4)) ?
__builtin_strcmp (r->requestInfo.uri, "/pub") : (__builtin_constant_p
(r->requestInfo.uri) && ((size_t)(const void *)((
r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo
.uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo
.uri), __s1_len < 4) ? (__builtin_constant_p ("/pub") &&
((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *
)("/pub") == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("/pub"); int __result = (((const unsigned
char *) (const char *) (r->requestInfo.uri))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (r->requestInfo.
uri))[1] - __s2[1]); if (__s1_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (r->
requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (r->requestInfo.uri))[3] - __s2[3]); } } __result; }))
) : (__builtin_constant_p ("/pub") && ((size_t)(const
void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1)
&& (__s2_len = __builtin_strlen ("/pub"), __s2_len <
4) ? (__builtin_constant_p (r->requestInfo.uri) &&
((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t
)(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp
(r->requestInfo.uri, "/pub") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(r->requestInfo.uri); int __result = (((const unsigned char
*) (const char *) ("/pub"))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/pub"))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/pub"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ("/pub"))[3] - __s2[3]); } } __result; }))
)) : __builtin_strcmp (r->requestInfo.uri, "/pub")))); }) :
strncmp (r->requestInfo.uri, "/pub", 4)))
) {
738 char *p = (char *) r->requestInfo.uri;
739 char *new_uri = p + 4;
740 if (!new_uri) {
741 new_uri = "/";
742 }
743
744 switch_snprintf(tmp, sizeof(tmp), "%s%s", SWITCH_GLOBAL_dirs.htdocs_dir, new_uri);
745
746 if (switch_directory_exists(tmp, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) {
747 for (x = 0; x < 2; x++) {
748 switch_snprintf(tmp, sizeof(tmp), "%s%s%s%s",
749 SWITCH_GLOBAL_dirs.htdocs_dir, new_uri, end_of(new_uri)*(*new_uri == '\0' ? new_uri : new_uri + strlen(new_uri) - 1) == *SWITCH_PATH_SEPARATOR"/" ? "" : SWITCH_PATH_SEPARATOR"/", list[x]
750 );
751
752 if (switch_file_exists(tmp, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) {
753 switch_snprintf(tmp, sizeof(tmp), "%s%s%s", new_uri, end_of(new_uri)*(*new_uri == '\0' ? new_uri : new_uri + strlen(new_uri) - 1) == '/' ? "" : "/", list[x]
754 );
755 new_uri = tmp;
756 break;
757 }
758 }
759 }
760
761 r->requestInfo.uri = strdup(new_uri)(__extension__ (__builtin_constant_p (new_uri) && ((size_t
)(const void *)((new_uri) + 1) - (size_t)(const void *)(new_uri
) == 1) ? (((const char *) (new_uri))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (new_uri
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, new_uri
, __len); __retval; })) : __strdup (new_uri)))
;
762 free(p);
763
764 } else {
765 if (globals.realm && strncmp(r->requestInfo.uri, "/pub", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
(r->requestInfo.uri) && strlen (r->requestInfo
.uri) < ((size_t) (4))) || (__builtin_constant_p ("/pub") &&
strlen ("/pub") < ((size_t) (4)))) ? __extension__ ({ size_t
__s1_len, __s2_len; (__builtin_constant_p (r->requestInfo
.uri) && __builtin_constant_p ("/pub") && (__s1_len
= __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen
("/pub"), (!((size_t)(const void *)((r->requestInfo.uri) +
1) - (size_t)(const void *)(r->requestInfo.uri) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)(("/pub") + 1) -
(size_t)(const void *)("/pub") == 1) || __s2_len >= 4)) ?
__builtin_strcmp (r->requestInfo.uri, "/pub") : (__builtin_constant_p
(r->requestInfo.uri) && ((size_t)(const void *)((
r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo
.uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo
.uri), __s1_len < 4) ? (__builtin_constant_p ("/pub") &&
((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *
)("/pub") == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("/pub"); int __result = (((const unsigned
char *) (const char *) (r->requestInfo.uri))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (r->requestInfo.
uri))[1] - __s2[1]); if (__s1_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) (r->
requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (r->requestInfo.uri))[3] - __s2[3]); } } __result; }))
) : (__builtin_constant_p ("/pub") && ((size_t)(const
void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1)
&& (__s2_len = __builtin_strlen ("/pub"), __s2_len <
4) ? (__builtin_constant_p (r->requestInfo.uri) &&
((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t
)(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp
(r->requestInfo.uri, "/pub") : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(r->requestInfo.uri); int __result = (((const unsigned char
*) (const char *) ("/pub"))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/pub"))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ("/pub"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ("/pub"))[3] - __s2[3]); } } __result; }))
)) : __builtin_strcmp (r->requestInfo.uri, "/pub")))); }) :
strncmp (r->requestInfo.uri, "/pub", 4)))
) {
766 ret = !http_directory_auth(r, NULL((void*)0));
767 }
768 }
769 }
770 return ret;
771}
772
773
774static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len)
775{
776 if (s->chunkedwrite && s->chunkedwritemode) {
777 char t[16];
778
779 if (ConnWrite(s->connP, t, sprintf(t, "%x" CRLF"\r\n", len)))
780 if (ConnWrite(s->connP, buffer, len))
781 return ConnWrite(s->connP, CRLF"\r\n", 2);
782
783 return FALSE0;
784 }
785
786 return ConnWrite(s->connP, buffer, len);
787}
788
789static abyss_bool HTTPWriteEnd(TSession * s)
790{
791 if (!s->chunkedwritemode)
792 return TRUE(!0);
793
794 if (s->chunkedwrite) {
795 /* May be one day trailer dumping will be added */
796 s->chunkedwritemode = FALSE0;
797 return ConnWrite(s->connP, "0" CRLF"\r\n" CRLF"\r\n", 5);
798 }
799
800 s->requestInfo.keepalive = FALSE0;
801 return TRUE(!0);
802}
803
804abyss_bool handler_hook(TSession * r)
805{
806 switch_stream_handle_t stream = { 0 };
807 char *command;
808 char *full_command;
809 int i;
810 char *fs_user = NULL((void*)0), *fs_domain = NULL((void*)0);
811 char *path_info = NULL((void*)0);
812 abyss_bool ret = TRUE(!0);
813 int html = 0, text = 0, xml = 0, api = 0;
814 const char *api_str;
815 const char *uri = 0;
816 TRequestInfo *info = 0;
817 switch_event_t *evnt = 0; /* shortcut to stream.param_event */
818 char v[256] = "";
819
820 if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) {
821 return FALSE0;
822 }
823
824 stream.data = r;
825 stream.write_function = http_stream_write;
826 stream.raw_write_function = http_stream_raw_write;
827
828 if ((command = strstr(uri, "/api/"))) {
829 command += 5;
830 api++;
831 } else if ((command = strstr(uri, "/webapi/"))) {
832 command += 8;
833 html++;
834 } else if ((command = strstr(uri, "/txtapi/"))) {
835 command += 8;
836 text++;
837 } else if ((command = strstr(uri, "/xmlapi/"))) {
838 command += 8;
839 xml++;
840 } else {
841 return FALSE0; /* 404 */
842 }
843
844 if ((path_info = strchr(command, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p
(command) && ('/') == '\0' ? (char *) __rawmemchr (command
, '/') : __builtin_strchr (command, '/')))
)) {
845 *path_info++ = '\0';
846 }
847
848 for (i = 0; i < r->responseHeaderFields.size; i++) {
849 TTableItem *ti = &r->responseHeaderFields.item[i];
850 if (!strcasecmp(ti->name, "freeswitch-user")) {
851 fs_user = ti->value;
852 } else if (!strcasecmp(ti->name, "freeswitch-domain")) {
853 fs_domain = ti->value;
854 }
855 }
856
857 if (!is_authorized(r, command)) {
858 ret = TRUE(!0);
859 goto end;
860 }
861
862/* auth: */
863
864 if (switch_event_create(&stream.param_event, SWITCH_EVENT_API)switch_event_create_subclass_detailed("mod_xml_rpc.c", (const
char * )(const char *)__func__, 864, &stream.param_event
, SWITCH_EVENT_API, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
865 const char *const content_length = RequestHeaderValue(r, "content-length");
866 evnt = stream.param_event;
867
868 if (html) {
869 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html");
870 } else if (text) {
871 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain");
872 } else if (xml) {
873 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml");
874 }
875 if (api) {
876 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api");
877 }
878 if (fs_user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
879 if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
880 if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);
881
882 if (info->host) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host);
883 if (info->from) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from);
884 if (info->useragent) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent);
885 if (info->referer) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer);
886 if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline);
887 if (info->user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user);
888 if (info->port) switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port);
889
890 {
891 char *q, *qd;
892 char *next;
893 char *query = (char *) info->query;
894 char *name, *val;
895 char qbuf[8192] = "";
896
897 /* first finish reading from the socket if post method was used*/
898 if (info->method == m_post && content_length) {
899 int len = atoi(content_length);
900 int qlen = 0;
901
902 if (len > 0) {
903 int succeeded = TRUE(!0);
904 char *qp = qbuf;
905 char *readError;
906
907 do {
908 int blen = r->connP->buffersize - r->connP->bufferpos;
909
910 if ((qlen + blen) > len) {
911 blen = len - qlen;
912 }
913
914 qlen += blen;
915
916 if (qlen > sizeof(qbuf)) {
917 break;
918 }
919
920 memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen);
921 qp += blen;
922
923 if (qlen >= len) {
924 break;
925 }
926
927 ConnRead(r->connP, 2000, NULL((void*)0), NULL((void*)0), &readError);
928 if (readError) {
929 succeeded = FALSE0;
930 free(readError);
931 }
932
933 } while (succeeded);
934
935 query = qbuf;
936 }
937 }
938
939 /* parse query and add kv-pairs as event headers */
940 /* a kv pair starts with '&', '+' or \0 mark the end */
941 if (query) {
942 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);
943 qd = strdup(query)(__extension__ (__builtin_constant_p (query) && ((size_t
)(const void *)((query) + 1) - (size_t)(const void *)(query) ==
1) ? (((const char *) (query))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (query) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, query, __len
); __retval; })) : __strdup (query)))
;
944 } else {
945 qd = strdup(uri)(__extension__ (__builtin_constant_p (uri) && ((size_t
)(const void *)((uri) + 1) - (size_t)(const void *)(uri) == 1
) ? (((const char *) (uri))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (uri) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, uri, __len); __retval
; })) : __strdup (uri)))
;
946 }
947
948 switch_assert(qd != NULL)((qd != ((void*)0)) ? (void) (0) : __assert_fail ("qd != ((void*)0)"
, "mod_xml_rpc.c", 948, __PRETTY_FUNCTION__))
;
949
950 q = qd;
951 next = q;
952
953 do {
954 char *p;
955
956 if (next = strchr(next, '&')(__extension__ (__builtin_constant_p ('&') && !__builtin_constant_p
(next) && ('&') == '\0' ? (char *) __rawmemchr (
next, '&') : __builtin_strchr (next, '&')))
) {
957 if (!query) {
958 /* pass kv pairs from uri to query */
959 /* "?" is absent in url so parse uri */
960 *((char *)uri + (next - q - 1)) = '\0';
961 query = next;
962 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next);
963 /* and strip uri */
964 /* the start of first kv pair marks the end of uri */
965 /* to prevent kv-pairs confusing fs api commands */
966 /* that have arguments separated by space */
967 }
968 *next++ = '\0';
969 }
970
971 for (p = q; p && *p; p++) {
972 if (*p == '+') {
973 *p = ' ';
974 }
975 }
976 /* hmmm, get method requests are already decoded ... */
977 switch_url_decode(q);
978
979 name = q;
980 if ((val = strchr(name, '=')(__extension__ (__builtin_constant_p ('=') && !__builtin_constant_p
(name) && ('=') == '\0' ? (char *) __rawmemchr (name
, '=') : __builtin_strchr (name, '=')))
)) {
981 *val++ = '\0';
982 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val);
983 }
984 q = next;
985 } while (q != NULL((void*)0));
986
987 free(qd);
988 }
989 }
990
991 switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri);
992
993 /* We made it this far, always OK */
994 if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) {
995 return TRUE(!0);
996 }
997
998 ResponseAddField(r, "Connection", "close");
999
1000 /* generation of the date field */
1001 if (evnt)
1002 {
1003 ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT")switch_event_get_header_idx(evnt, "Event-Date-GMT", -1));
1004 }
1005 else {
1006 const char *dateValue;
1007
1008 DateToString(r->date, &dateValue);
1009 if (dateValue) {
1010 ResponseAddField(r, "Date", dateValue);
1011 free((void *)dateValue);
1012 }
1013 }
1014
1015 /* Generation of the server field */
1016 switch_snprintf(v, sizeof(v), "FreeSWITCH-%s-mod_xml_rpc", switch_version_full());
1017 ResponseAddField(r, "Server", v);
1018
1019 if (html) {
1020 ResponseAddField(r, "Content-Type", "text/html");
1021 } else if (text) {
1022 ResponseAddField(r, "Content-Type", "text/plain");
1023 } else if (xml) {
1024 ResponseAddField(r, "Content-Type", "text/xml");
1025 }
1026
1027 for (i = 0; i < r->responseHeaderFields.size; i++) {
1028 TTableItem *ti = &r->responseHeaderFields.item[i];
1029 char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value);
1030 if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) {
1031 switch_safe_free(header)if (header) {free(header);header=((void*)0);};
1032 return TRUE(!0);
1033 }
1034 switch_safe_free(header)if (header) {free(header);header=((void*)0);};
1035 }
1036
1037 /* send end http header */
1038 if (html||text||xml) {
1039 if (!ConnWrite(r->connP, CRLF"\r\n", 2)) {
1040 return TRUE(!0);
1041 }
1042 }
1043 else {
1044 /* content-type and end of http header will be streamed by fs api or http_stream_write */
1045 }
1046
1047 if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) {
1048 command = "bgapi";
1049 api_str = "unload mod_xml_rpc";
1050 } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) {
1051 command = "bgapi";
1052 api_str = "reload mod_xml_rpc";
1053 } else {
1054 api_str = info->query;
1055 }
1056
1057 /* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands */
1058
1059 /* execute actual fs api command */
1060 /* fs api command will write to stream, calling http_stream_write / http_stream_raw_write */
1061 /* switch_api_execute will stream INVALID COMMAND before it fails */
1062 switch_api_execute(command, api_str, NULL((void*)0), &stream);
1063
1064 if (globals.commands_to_log != NULL((void*)0)) {
1065 full_command = switch_mprintf("%s%s%s", command, (api_str==NULL((void*)0) ? "" : " "), api_str);
1066
1067 if (switch_regex_match(full_command, globals.commands_to_log) == SWITCH_STATUS_SUCCESS) {
1068 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1068, ((void*)0)
, SWITCH_LOG_INFO, "Executed HTTP request command: [%s].\n", full_command);
1069 }
1070
1071 switch_safe_free(full_command)if (full_command) {free(full_command);full_command=((void*)0)
;}
;
1072 }
1073
1074 r->responseStarted = TRUE(!0);
1075 ResponseStatus(r, 200); /* we don't want an assertion failure */
1076 r->requestInfo.keepalive = 0;
1077
1078 end:
1079
1080 return ret;
1081}
1082
1083static xmlrpc_value *freeswitch_api(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void *const userData, void *const callInfo)
1084{
1085 char *command = NULL((void*)0), *arg = NULL((void*)0);
1086 switch_stream_handle_t stream = { 0 };
1087 xmlrpc_value *val = NULL((void*)0);
1088 switch_bool_t freed = 0;
1089
1090
1091 /* Parse our argument array. */
1092 xmlrpc_decompose_value(envP, paramArrayP, "(ss)", &command, &arg);
1093
1094 if (envP->fault_occurred) {
1095 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1095, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid Request!\n");
1096 return NULL((void*)0);
1097 }
1098
1099 if (!is_authorized((const TSession *) callInfo, command)) {
1100 val = xmlrpc_build_value(envP, "s", "UNAUTHORIZED!");
1101 goto end;
1102 }
1103
1104 if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", arg)) {
1105 switch_safe_free(command)if (command) {free(command);command=((void*)0);};
1106 switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);};
1107 freed = 1;
1108 command = "bgapi";
1109 arg = "unload mod_xml_rpc";
1110 } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", arg)) {
1111 switch_safe_free(command)if (command) {free(command);command=((void*)0);};
1112 switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);};
1113 freed = 1;
1114 command = "bgapi";
1115 arg = "reload mod_xml_rpc";
1116 }
1117
1118 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_xml_rpc.c", 1118, __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
;
1119 if (switch_api_execute(command, arg, NULL((void*)0), &stream) == SWITCH_STATUS_SUCCESS) {
1120 /* Return our result. */
1121 val = xmlrpc_build_value(envP, "s", stream.data);
1122 free(stream.data);
1123 } else {
1124 val = xmlrpc_build_value(envP, "s", "ERROR!");
1125 }
1126
1127 end:
1128
1129 /* xmlrpc-c requires us to free memory it malloced from xmlrpc_decompose_value */
1130 if (!freed) {
1131 switch_safe_free(command)if (command) {free(command);command=((void*)0);};
1132 switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);};
1133 }
1134
1135 return val;
1136}
1137
1138static xmlrpc_value *freeswitch_man(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void *const userData)
1139{
1140 char *oid = NULL((void*)0), *relative_oid, *s_action = NULL((void*)0), *data = NULL((void*)0);
1141 char buf[SWITCH_MAX_MANAGEMENT_BUFFER_LEN1024 * 8] = "";
1142 switch_management_action_t action = SMA_NONE;
1143 xmlrpc_value *val = NULL((void*)0);
1144
1145 /* Parse our argument array. */
1146 xmlrpc_decompose_value(envP, paramArrayP, "(sss)", &oid, &s_action, &data);
1147 if (envP->fault_occurred) {
1148 return NULL((void*)0);
1149 }
1150
1151 if (!strncasecmp(oid, FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880", strlen(FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880"))) {
1152 relative_oid = oid + strlen(FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880");
1153 } else {
1154 relative_oid = oid;
1155 }
1156
1157 if (!zstr(data)_zstr(data)) {
1158 switch_copy_string(buf, data, sizeof(buf));
1159 }
1160
1161 if (!strcasecmp(s_action, "get")) {
1162 action = SMA_GET;
1163 } else if (!strcasecmp(s_action, "set")) {
1164 action = SMA_SET;
1165 }
1166
1167 if (action) {
1168 if (switch_core_management_exec(relative_oid, action, buf, sizeof(buf)) == SWITCH_STATUS_SUCCESS) {
1169 if (action == SMA_SET) {
1170 if (*buf != '\0') {
1171 switch_snprintf(buf, sizeof(buf), "OK\n");
1172 }
1173 }
1174 } else {
1175 if (*buf != '\0') {
1176 switch_snprintf(buf, sizeof(buf), "ERROR\n");
1177 }
1178 }
1179 } else {
1180 switch_snprintf(buf, sizeof(buf), "Invalid Action %s\n", s_action);
1181 }
1182
1183 /* Return our result. */
1184 val = xmlrpc_build_value(envP, "s", buf);
1185
1186 /* xmlrpc-c requires us to free memory it malloced from xmlrpc_decompose_value */
1187 switch_safe_free(oid)if (oid) {free(oid);oid=((void*)0);};
1188 switch_safe_free(s_action)if (s_action) {free(s_action);s_action=((void*)0);};
1189 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1190 return val;
1191}
1192
1193SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)switch_status_t mod_xml_rpc_runtime (void)
1194{
1195 xmlrpc_env env;
1196 char logfile[512];
1197 switch_hash_index_t *hi;
1198 const void *var;
1199 void *val;
1200
1201 globals.running = 1;
1202
1203 xmlrpc_env_init(&env);
1204
1205 globals.registryP = xmlrpc_registry_new(&env);
1206
1207 /* TODO why twice and why add_method for freeswitch.api and add_method2 for freeswitch.management ? */
1208 xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch.api", &freeswitch_api, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1209 xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch_api", &freeswitch_api, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1210 xmlrpc_registry_add_method(&env, globals.registryP, NULL((void*)0), "freeswitch.management", &freeswitch_man, NULL((void*)0));
1211 xmlrpc_registry_add_method(&env, globals.registryP, NULL((void*)0), "freeswitch_management", &freeswitch_man, NULL((void*)0));
1212
1213 MIMETypeInit();
1214
1215 for (hi = switch_core_mime_index(); hi; hi = switch_core_hash_next(&hi)) {
1216 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
1217 if (var && val) {
1218 MIMETypeAdd((char *) val, (char *) var);
1219 }
1220 }
1221
1222 switch_snprintf(logfile, sizeof(logfile), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", "freeswitch_http.log");
1223 ServerCreate(&globals.abyssServer, "XmlRpcServer", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, logfile);
1224
1225 xmlrpc_server_abyss_set_handler(&env, &globals.abyssServer, "/RPC2", globals.registryP);
1226
1227 xmlrpc_env_clean(&env);
1228
1229 if (ServerInit(&globals.abyssServer) != TRUE(!0)) {
1230 globals.running = 0;
1231 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1231, ((void*)0)
, SWITCH_LOG_ERROR, "Failed to start HTTP Port %d\n", globals.port);
1232 xmlrpc_registry_free(globals.registryP);
1233 MIMETypeTerm();
1234
1235 return SWITCH_STATUS_TERM;
1236 }
1237
1238 ServerAddHandler(&globals.abyssServer, handler_hook);
1239 ServerAddHandler(&globals.abyssServer, auth_hook);
1240 ServerSetKeepaliveTimeout(&globals.abyssServer, 5);
1241
1242 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1242, ((void*)0)
, SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]%s\n",
1243 globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, globals.enable_websocket ? " with websocket." : "");
1244 ServerRun(&globals.abyssServer);
1245
1246 switch_yield(1000000)switch_sleep(1000000);;
1247
1248 globals.running = 0;
1249
1250 return SWITCH_STATUS_TERM;
1251}
1252
1253void stop_all_websockets()
1254{
1255 switch_event_t *event;
1256 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "websocket::stophook")switch_event_create_subclass_detailed("mod_xml_rpc.c", (const
char * )(const char *)__func__, 1256, &event, SWITCH_EVENT_CUSTOM
, "websocket::stophook")
!= SWITCH_STATUS_SUCCESS) {
1257 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1257, ((void*)0)
,SWITCH_LOG_ERROR, "Failed to create event!\n");
1258 }
1259 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "stop", "now");
1260 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1260, ((void*)0)
, SWITCH_LOG_NOTICE, "stopping all websockets ...\n");
1261 if (switch_event_fire(&event)switch_event_fire_detailed("mod_xml_rpc.c", (const char * )(const
char *)__func__, 1261, &event, ((void*)0))
!= SWITCH_STATUS_SUCCESS) {
1262 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__
, 1262, ((void*)0)
,SWITCH_LOG_ERROR, "Failed to fire the event!\n");
1263 switch_event_destroy(&event);
1264 }
1265}
1266
1267/* upon module unload */
1268SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)switch_status_t mod_xml_rpc_shutdown (void)
1269{
1270
1271 /* Cann't find a way to stop the websockets, use this for a workaround before finding the real one that works */
1272 stop_all_websockets();
1273
1274 /* this makes the worker thread (ServerRun) stop */
1275 ServerTerminate(&globals.abyssServer);
1276
1277 do {
1278 switch_yield(100000)switch_sleep(100000);;
1279 } while (globals.running);
1280
1281 ServerFree(&globals.abyssServer);
1282 xmlrpc_registry_free(globals.registryP);
1283 MIMETypeTerm();
1284
1285 switch_safe_free(globals.realm)if (globals.realm) {free(globals.realm);globals.realm=((void*
)0);}
;
1286 switch_safe_free(globals.user)if (globals.user) {free(globals.user);globals.user=((void*)0)
;}
;
1287 switch_safe_free(globals.pass)if (globals.pass) {free(globals.pass);globals.pass=((void*)0)
;}
;
1288 switch_safe_free(globals.default_domain)if (globals.default_domain) {free(globals.default_domain);globals
.default_domain=((void*)0);}
;
1289
1290 return SWITCH_STATUS_SUCCESS;
1291}
1292
1293/* For Emacs:
1294 * Local Variables:
1295 * mode:c
1296 * indent-tabs-mode:t
1297 * tab-width:4
1298 * c-basic-offset:4
1299 * End:
1300 * For VIM:
1301 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1302 */