<configuration name="httapi.conf" description="HT-TAPI Hypertext Telephony API">
<settings>
- <!-- print xml on the console -->
+ <!-- print xml on the consol -->
<param name="debug" value="true"/>
- <!-- time to keep audio files when discovered they were deleted from the http server -->
+ <!-- time to keep audio files when discoverd they were deleted from the http server -->
<param name="file-not-found-expires" value="300"/>
<!-- how often to re-check the server to make sure the remote file has not changed -->
<param name="file-cache-ttl" value="300"/>
<permission name="set-params" value="true"/>
<permission name="set-vars" value="false"/>
<permission name="extended-data" value="false"/>
- <permission name="execute-apps" value="false"/>
+ <permission name="execute-apps" value="true">
+ <!-- default to "deny" or "allow" -->
+ <application-list default="deny">
+ <!-- type attr can be "deny" or "allow" nothing defaults to opposite of the list default so allow in this case -->
+ <application name="info"/>
+ <application name="hangup"/>
+ </application-list>
+ </permission>
<permission name="expand-vars-in-tag-body" value="false"/>
<permission name="dial" value="true"/>
<permission name="dial-set-context" value="false"/>
switch_byte_t set_vars;
switch_byte_t extended_data;
switch_byte_t execute_apps;
- switch_byte_t expand_vars_in_tag_body;
+ switch_byte_t expand_vars;
struct {
switch_byte_t enabled;
switch_byte_t set_context;
struct {
char *context;
char *dp;
+ switch_event_t *app_list;
+ int default_allow;
} dial_params;
} client_profile_t;
return SWITCH_STATUS_SUCCESS;
}
+static int check_app_perm(client_t *client, const char *app_name)
+{
+ const char *v;
+ int r = 0;
+
+ if (!client->profile->perms.execute_apps) {
+ return 0;
+ }
+
+ if (!client->profile->dial_params.app_list) {
+ return 1;
+ }
+
+ if ((v = switch_event_get_header(client->profile->dial_params.app_list, app_name))) {
+ if (*v == 'd') {
+ r = 0;
+ } else {
+ r = 1;
+ }
+ } else {
+ r = client->profile->dial_params.default_allow;
+ }
+
+
+ return r;
+}
+
static switch_status_t parse_execute(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
{
const char *app_name = switch_xml_attr(tag, "application");
+ const char *data = switch_xml_attr(tag, "data");
- if (!client->profile->perms.execute_apps) {
+ if (zstr(data)) data = body;
+
+ if (!check_app_perm(client, app_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Permission Denied!\n");
switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
} else {
- switch_core_session_execute_application(client->session, app_name, body);
+ if (!client->profile->perms.expand_vars) {
+ const char *p;
+
+ for(p = data; p && *p; p++) {
+ if (*p == '$') {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Expand Variables: Permission Denied!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+ }
+
+ switch_core_session_execute_application(client->session, app_name, data);
}
return SWITCH_STATUS_SUCCESS;
char *expanded = tag->txt;
switch_event_t *templ_data;
- if (tag->txt && client->profile->perms.expand_vars_in_tag_body) {
+ if (tag->txt && client->profile->perms.expand_vars) {
switch_channel_get_variables(client->channel, &templ_data);
switch_event_merge(templ_data, client->params);
expanded = switch_event_expand_headers(templ_data, tag->txt);
profile->perms.extended_data = switch_true(val);
} else if (!strcasecmp(var, "execute-apps")) {
profile->perms.execute_apps = switch_true(val);
- } else if (!strcasecmp(var, "expand-vars-in-tag-body")) {
- profile->perms.expand_vars_in_tag_body = switch_true(val);
+
+ if (profile->perms.execute_apps) {
+ switch_xml_t x_list, x_app;
+ if ((x_list = switch_xml_child(param, "application-list"))) {
+ char *var = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->dial_params.default_allow = (var && !strcasecmp(var, "allow"));
+ switch_event_create(&profile->dial_params.app_list, SWITCH_EVENT_CLONE);
+ profile->dial_params.app_list->flags |= EF_UNIQ_HEADERS;
+
+ for (x_app = switch_xml_child(x_list, "application"); x_app; x_app = x_app->next) {
+ const char *name = switch_xml_attr(x_app, "name");
+ const char *type = switch_xml_attr(x_app, "type");
+
+ if (zstr(type)) type = profile->dial_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->dial_params.app_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+ }
+
+ } else if (!strcasecmp(var, "expand-vars")) {
+ profile->perms.expand_vars = switch_true(val);
} else if (!strcasecmp(var, "dial")) {
profile->perms.dial.enabled = switch_true(val);
} else if (!strcasecmp(var, "dial-set-context")) {
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_httapi_shutdown)
{
hash_node_t *ptr = NULL;
+ client_profile_t *profile;
+ switch_hash_index_t *hi;
+ void *val;
+ const void *vvar;
+
+ for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &val);
+ profile = (client_profile_t *) val;
+ switch_event_destroy(&profile->dial_params.app_list);
+ }
+
switch_core_hash_destroy(&globals.profile_hash);
switch_core_hash_destroy(&globals.parse_hash);