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 |
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 | ||||
74 | SWITCH_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); | |||
75 | SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)switch_status_t mod_xml_rpc_shutdown (void); | |||
76 | SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)switch_status_t mod_xml_rpc_runtime (void); | |||
77 | SWITCH_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 | ||||
79 | static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len); | |||
80 | ||||
81 | static 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 | ||||
95 | SWITCH_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 ); | |||
96 | SWITCH_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); | |||
97 | SWITCH_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); | |||
98 | SWITCH_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 | ||||
100 | static 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 | ||||
161 | SWITCH_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 | ||||
174 | static 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 | ||||
182 | static 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 | ||||
242 | static 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(¶ms, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_xml_rpc.c", (const char * )(const char *)__func__, 264, ¶ms, 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(¶ms); | |||
271 | return FALSE0; | |||
272 | } | |||
273 | ||||
274 | switch_event_destroy(¶ms); | |||
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 | ||||
315 | static 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 | ||||
390 | static 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 | ||||
553 | void 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 | ||||
560 | void 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 | ||||
570 | abyss_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++) { | |||
| ||||
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; | |||
597 | if (strncasecmp(upgrade, "websocket", 9) || strncasecmp(proto, "websocket", 9)) return FALSE0; | |||
598 | ||||
599 | wsh = ws_init(r); | |||
600 | if (!wsh) { | |||
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; | |||
607 | ||||
608 | if (ret != 0) { | |||
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) { | |||
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) { | |||
619 | int bytes = ws_read_frame(wsh, &opcode, &data); | |||
620 | ||||
621 | if (bytes < 0) { | |||
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) { | |||
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; | |||
637 | if (!strncasecmp(data, "event ", 6)) { | |||
638 | switch_event_types_t type; | |||
639 | char *subclass; | |||
640 | ||||
641 | if (node_count == MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL - 1) { | |||
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++; | |||
647 | if (!strncasecmp(p, "json ", 5)) { | |||
| ||||
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 | ||||
699 | abyss_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 | ||||
774 | static 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 | ||||
789 | static 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 | ||||
804 | abyss_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 | ||||
1083 | static 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 | ||||
1138 | static 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 | ||||
1193 | SWITCH_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 | ||||
1253 | void 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 */ | |||
1268 | SWITCH_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 | */ |