コード例 #1
0
ファイル: mod_translate.c プロジェクト: PauloFer1/FreeSWITCH
static void translate_number(char *number, char *profile, char **translated, switch_core_session_t *session, switch_event_t *event)
{
	translate_rule_t *hi = NULL;
	translate_rule_t *rule = NULL;
	switch_regex_t *re = NULL;
	int proceed = 0, ovector[30];
	char *substituted = NULL;
	uint32_t len = 0;

	if (!profile) {
		profile = "US";
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "translating [%s] against [%s] profile\n", number, profile);

	hi = switch_core_hash_find_rdlock(globals.translate_profiles, (const char *)profile, globals.profile_hash_rwlock);
	if (!hi) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "can't find key for profile matching [%s]\n", profile);
		return;
	}

	for (rule = hi; rule; rule = rule->next) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s =~ /%s/\n", number, rule->regex);
		if ((proceed = switch_regex_perform(number, rule->regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s matched %s, replacing with %s\n", number, rule->regex, rule->replace);
			if (!(substituted = malloc(len))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
				switch_regex_safe_free(re);
				goto end;
			}
			memset(substituted, 0, len);

			switch_perform_substitution(re, proceed, rule->replace, number, substituted, len, ovector);

			if ((switch_string_var_check_const(substituted) || switch_string_has_escaped_data(substituted))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "perform variable expansion\n");
				if (session) {
					substituted = switch_channel_expand_variables(switch_core_session_get_channel(session), substituted);
				} else if (event) {
					substituted = switch_event_expand_headers(event, substituted);
				}
			}

			break;
		}
	}

 end:
	*translated = substituted ? substituted : NULL;
}
コード例 #2
0
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results)
{
	char *str = ldns_rr2str(naptr);
	char *argv[11] = { 0 };
	int i, argc;
	char *pack[4] = { 0 };
	int packc;

	char *p;
	int order = 10;
	int preference = 100;
	char *service = NULL;
	char *packstr;

	char *regex, *replace;
	
	if (zstr(str)) {
		if (str != NULL) {
			/* In this case ldns_rr2str returned a malloc'd null terminated string */
			switch_safe_free(str);
		}
		return;
	}

	for (p = str; p && *p; p++) {
		if (*p == '\t') *p = ' ';
		if (*p == ' ' && *(p+1) == '.') *p = '\0';
	}


	argc = switch_split(str, ' ', argv);

	for (i = 0; i < argc; i++) {
		if (i > 0) {
			strip_quotes(argv[i]);
		}
	}

	service = argv[7];
	packstr = argv[8];

	if (zstr(service) || zstr(packstr)) {
		goto end;
	}
	
	if (!zstr(argv[4])) {
		order = atoi(argv[4]);
	}

	if (!zstr(argv[5])) {
		preference = atoi(argv[5]);
	}


	if ((packc = switch_split(packstr, '!', pack))) {
		regex = pack[1];
		replace = pack[2];
	} else {
		goto end;
	}
	
	for (p = replace; p && *p; p++) {
		if (*p == '\\') {
			*p = '$';
		}
	}

	if (service && regex && replace) {
		switch_regex_t *re = NULL, *re2 = NULL;
		int proceed = 0, ovector[30];
		char *substituted = NULL;
		char *substituted_2 = NULL;
		char *orig_uri;
		char *uri_expanded = NULL;
		enum_route_t *route;
		int supported = 0;
		uint32_t len = 0;

		if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
			if (strchr(regex, '(')) {
				len = (uint32_t) (strlen(number) + strlen(replace) + 10) * proceed;
				if (!(substituted = malloc(len))) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
					switch_regex_safe_free(re);
					goto end;
				}
				memset(substituted, 0, len);

				switch_perform_substitution(re, proceed, replace, number, substituted, len, ovector);
				orig_uri = substituted;
			} else {
				orig_uri = replace;
			}
			
			switch_mutex_lock(MUTEX);
			for (route = globals.route_order; route; route = route->next) {
				char *uri = orig_uri;
				
				if (strcasecmp(service, route->service)) {
					continue;
				}

				if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
					switch_event_t *event = NULL;

					if (strchr(route->regex, '(')) {
						len = (uint32_t) (strlen(uri) + strlen(route->replace) + 10) * proceed;
						if (!(substituted_2 = malloc(len))) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
							switch_safe_free(substituted);
							switch_regex_safe_free(re);
							switch_regex_safe_free(re2);
							switch_mutex_unlock(MUTEX);
							goto end;
						}
						memset(substituted_2, 0, len);

						switch_perform_substitution(re2, proceed, route->replace, uri, substituted_2, len, ovector);
						uri = substituted_2;
					} else {
						uri = route->replace;
					}
					switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
					uri_expanded = switch_event_expand_headers(event, uri);
					switch_event_destroy(&event);

					if (uri_expanded == uri) {
						uri_expanded = NULL;
					} else {
						uri = uri_expanded;
					}

					supported++;
					add_result(results, order, preference, service, uri, supported);
					
				}
				switch_safe_free(uri_expanded);
				switch_safe_free(substituted_2);
				switch_regex_safe_free(re2);
			}
			switch_mutex_unlock(MUTEX);			

			if (!supported) {
				add_result(results, order, preference, service, orig_uri, 0);
			}

			switch_safe_free(substituted);
			switch_regex_safe_free(re);
		}
	}

 end:

	switch_safe_free(str);
	
	return;
}
コード例 #3
0
ファイル: switch_ivr_menu.c プロジェクト: hsaid/FreeSWITCH
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
{
	int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1;
	char *greeting_sound = NULL, *aptr = NULL;
	char arg[512];
	switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE;
	switch_ivr_menu_action_t *ap;
	switch_ivr_menu_t *menu;
	switch_channel_t *channel;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (++stack->stack_count > 12) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!session || !stack || zstr(name)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	channel = switch_core_session_get_channel(session);

	if (!(menu = switch_ivr_menu_find(stack, name))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
		switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
		switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name);
	switch_channel_set_variable(channel, "ivr_menu_status", "success");

	for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) {
		if (!switch_channel_ready(channel)) {
			break;
		}
		if (errs == menu->max_failures) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "failure");
			break;
		}
		if (timeouts == menu->max_timeouts) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "timeout");
			break;
		}

		if (reps > 0 && menu->short_greeting_sound) {
			greeting_sound = menu->short_greeting_sound;
		} else {
			greeting_sound = menu->greeting_sound;
		}

		match = 0;
		aptr = NULL;

		memset(arg, 0, sizeof(arg));

		memset(menu->buf, 0, menu->inlen + 1);

		if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') {
			timeouts++;
			continue;
		}

		if (*menu->buf != '\0') {

			for (ap = menu->actions; ap; ap = ap->next) {
				int ok = 0;
				char substituted[1024];
				char *use_arg = ap->arg;

				if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
					switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
					switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
				}

				if (ap->re) {
					switch_regex_t *re = NULL;
					int ovector[30];

					if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector);
						use_arg = substituted;
					}
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok);

					switch_regex_safe_free(re);
				} else {
					ok = !strcmp(menu->buf, ap->bind);
				}

				if (ok) {
					match++;
					errs = 0;
					if (ap->function) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg);
						todo = ap->function(menu, use_arg, arg, sizeof(arg), obj);
						aptr = arg;
					} else {
						todo = ap->ivr_action;
						aptr = use_arg;
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr);
					}

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo);

					switch (todo) {
					case SWITCH_IVR_ACTION_DIE:
						status = SWITCH_STATUS_FALSE;
						break;
					case SWITCH_IVR_ACTION_PLAYSOUND:
						status = switch_ivr_play_file(session, NULL, aptr, NULL);
						break;
					case SWITCH_IVR_ACTION_EXECMENU:
						if (!strcmp(aptr, menu->name)) {
							status = SWITCH_STATUS_SUCCESS;
						} else {
							reps = -1;
							status = switch_ivr_menu_execute(session, stack, aptr, obj);
						}
						break;
					case SWITCH_IVR_ACTION_EXECAPP:
						{
							switch_application_interface_t *application_interface;
							char *app_name;
							char *app_arg = NULL;

							status = SWITCH_STATUS_FALSE;

							if (!zstr(aptr)) {
								app_name = switch_core_session_strdup(session, aptr);
								if ((app_arg = strchr(app_name, ' '))) {
									*app_arg++ = '\0';
								}

								if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
									switch_core_session_exec(session, application_interface, app_arg);
									UNPROTECT_INTERFACE(application_interface);
									status = SWITCH_STATUS_SUCCESS;
								}
							}
						}
						break;
					case SWITCH_IVR_ACTION_BACK:
						running = 0;
						status = SWITCH_STATUS_SUCCESS;
						break;
					case SWITCH_IVR_ACTION_TOMAIN:
						switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
						status = SWITCH_STATUS_BREAK;
						break;
					case SWITCH_IVR_ACTION_NOOP:
						status = SWITCH_STATUS_SUCCESS;
						break;
					default:
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n");
						break;
					}
				}
			}

			if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) {	/* top level */
				if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) {	/* catch the fallback and recover */
					switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
					status = SWITCH_STATUS_SUCCESS;
					running = 1;
					continue;
				}
			}
		}
		if (!match) {
			if (*menu->buf) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name,
								  menu->buf);
				if (menu->invalid_sound) {
					play_and_collect(session, menu, menu->invalid_sound, 0);
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name);
			}
			errs++;

			/* breaks are ok too */
			if (SWITCH_STATUS_IS_BREAK(status)) {
				status = SWITCH_STATUS_SUCCESS;
			}
		}
	}

	if (stack->stack_count == 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound);
		if (!zstr(menu->exit_sound)) {
			status = play_and_collect(session, menu, menu->exit_sound, 0);
		}
	}

  end:

	stack->stack_count--;

	return status;
}
コード例 #4
0
SWITCH_DECLARE(int) switch_regex_perform(const char *field, const char *expression, switch_regex_t **new_re, int *ovector, uint32_t olen)
{
	const char *error = NULL;
	int erroffset = 0;
	pcre *re = NULL;
	int match_count = 0;
	char *tmp = NULL;
	uint32_t flags = 0;
	char abuf[256] = "";

	if (!(field && expression)) {
		return 0;
	}

	if (*expression == '_') {
		if (switch_ast2regex(expression + 1, abuf, sizeof(abuf))) {
			expression = abuf;
		}
	}

	if (*expression == '/') {
		char *opts = NULL;
		tmp = strdup(expression + 1);
		assert(tmp);
		if ((opts = strrchr(tmp, '/'))) {
			*opts++ = '\0';
		} else {
			goto end;
		}
		expression = tmp;
		if (opts) {
			if (strchr(opts, 'i')) {
				flags |= PCRE_CASELESS;
			}
			if (strchr(opts, 's')) {
				flags |= PCRE_DOTALL;
			}
		}
	}

	re = pcre_compile(expression,	/* the pattern */
					  flags,	/* default options */
					  &error,	/* for error message */
					  &erroffset,	/* for error offset */
					  NULL);	/* use default character tables */
	if (error) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s][%s]\n", erroffset, error, expression);
		switch_regex_safe_free(re);
		goto end;
	}

	match_count = pcre_exec(re,	/* result of pcre_compile() */
							NULL,	/* we didn't study the pattern */
							field,	/* the subject string */
							(int) strlen(field),	/* the length of the subject string */
							0,	/* start at offset 0 in the subject */
							0,	/* default options */
							ovector,	/* vector of integers for substring information */
							olen);	/* number of elements (NOT size in bytes) */


	if (match_count <= 0) {
		switch_regex_safe_free(re);
		match_count = 0;
	}

	*new_re = (switch_regex_t *) re;

  end:
	switch_safe_free(tmp);
	return match_count;
}
コード例 #5
0
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, 
					   switch_caller_extension_t **extension, const char *exten_name, int recur)
{
	switch_xml_t xcond, xaction, xexpression, xregex;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	int proceed = 0, save_proceed = 0;
	char *expression_expanded = NULL, *field_expanded = NULL;
	switch_regex_t *re = NULL, *save_re = NULL;
	int offset = 0;
	const char *tmp, *tzoff = NULL, *tzname = NULL, *req_nesta = NULL;
	char nbuf[128] = "";
	int req_nest = 1;
	char space[MAX_RECUR_SPACE] = "";
	const char *orig_exten_name = exten_name;

	check_tz();

	if (!exten_name) {
		exten_name = "_anon_";
	}

	if (!orig_exten_name) {
		orig_exten_name = "_anon_";
	}


	if (recur) {
		int i, j = 0, k = 0;

		if (recur > MAX_RECUR) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Recursion LIMIT!\n");
			return 0;
		}

		switch_snprintf(nbuf, sizeof(nbuf), "%s_recur_%d", exten_name, recur);
		exten_name = nbuf;
		
		space[j++] = '|';

		for (i = 0; i < recur; i++) {
			for (k = 0; k < RECUR_SPACE; k++) {
				if (i == recur-1 && k == RECUR_SPACE-1) {
					space[j++] = ' ';
				} else {
					space[j++] = '-';
				}
			}
		}
		
		if ((req_nesta = switch_xml_attr(xexten, "require-nested"))) {
			req_nest = switch_true(req_nesta);
		}

		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, 
						  "%sDialplan: Processing recursive conditions level:%d [%s] require-nested=%s\n", space,
						  recur, exten_name, req_nest ? "TRUE" : "FALSE");

	} else {
		if ((tmp = switch_xml_attr(xexten, "name"))) {
			exten_name = tmp;
		}
	}


	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
		char *field = NULL;
		char *do_break_a = NULL;
		char *expression = NULL, *save_expression = NULL, *save_field_data = NULL;
		char *regex_rule = NULL;
		const char *field_data = NULL;
		int ovector[30];
		switch_bool_t anti_action = SWITCH_TRUE;
		break_t do_break_i = BREAK_ON_FALSE;
		int time_match;

		check_tz();
		time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname);

		switch_safe_free(field_expanded);
		switch_safe_free(expression_expanded);

		field = (char *) switch_xml_attr(xcond, "field");


		if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
			if (!strcasecmp(do_break_a, "on-true")) {
				do_break_i = BREAK_ON_TRUE;
			} else if (!strcasecmp(do_break_a, "on-false")) {
				do_break_i = BREAK_ON_FALSE;
			} else if (!strcasecmp(do_break_a, "always")) {
				do_break_i = BREAK_ALWAYS;
			} else if (!strcasecmp(do_break_a, "never")) {
				do_break_i = BREAK_NEVER;
			} else {
				do_break_a = NULL;
			}
		}


		if (switch_xml_child(xcond, "condition")) {
			if (!(proceed = parse_exten(session, caller_profile, xcond, extension, orig_exten_name, recur + 1))) {
				if (do_break_i == BREAK_NEVER) {
					continue;
				}
				goto done;
			}
		}
		
		if (time_match == 1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "%sDialplan: %s Date/Time Match (PASS) [%s] break=%s\n", space,
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
			anti_action = SWITCH_FALSE;
			proceed = 1;
		} else if (time_match == 0) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "%sDialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n", space,
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
		}
		
		
		if ((regex_rule = (char *) switch_xml_attr(xcond, "regex"))) {
			int all = !strcasecmp(regex_rule, "all");
			int xor = !strcasecmp(regex_rule, "xor");
			int pass = 0;
			int fail = 0;
			int total = 0;

			switch_channel_del_variable_prefix(channel, "DP_REGEX_MATCH");

			for (xregex = switch_xml_child(xcond, "regex"); xregex; xregex = xregex->next) {
				check_tz();
				time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL, tzname);
				
				if (time_match == 1) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Date/Time Match (PASS) [%s]\n", space,
									  switch_channel_get_name(channel), exten_name);
					anti_action = SWITCH_FALSE;
				} else if (time_match == 0) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Date/TimeMatch (FAIL) [%s]\n", space,
									  switch_channel_get_name(channel), exten_name);
				}


				if ((xexpression = switch_xml_child(xregex, "expression"))) {
					expression = switch_str_nil(xexpression->txt);
				} else {
					expression = (char *) switch_xml_attr_soft(xregex, "expression");
				}
				
				if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
					expression_expanded = NULL;
				} else {
					expression = expression_expanded;
				}
				
				total++;
				
				field = (char *) switch_xml_attr(xregex, "field");
				
				if (field) {
					if (strchr(field, '$')) {
						if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
							field_expanded = NULL;
							field_data = field;
						} else {
							field_data = field_expanded;
						}
					} else {
						field_data = switch_caller_get_field_by_name(caller_profile, field);
					}
					if (!field_data) {
						field_data = "";
					}
					
					if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
										  "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n", space,
										  switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
						pass++;
						if (!all && !xor) break;
					} else {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
										  "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n", space,
										  switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
						fail++;
						if (all && !xor) break;
					}
				} else if (time_match == -1) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Absolute Condition [%s] match=%s\n", space,
									  switch_channel_get_name(channel), exten_name, all ? "all" : "any");
					pass++;
					proceed = 1;
					if (!all && !xor) break;
				} else if (time_match == 1) {
					pass++;
					proceed = 1;
					if (!all && !xor) break;
				}
				
				if (field && strchr(expression, '(')) {
					char var[256];
					switch_snprintf(var, sizeof(var), "DP_REGEX_MATCH_%d", total);

					switch_channel_set_variable(channel, var, NULL);
					switch_capture_regex(re, proceed, field_data, ovector, var, switch_regex_set_var_callback, session);
					
					switch_safe_free(save_expression);
					switch_safe_free(save_field_data);
					switch_regex_safe_free(save_re);
					
					
					save_expression = strdup(expression);
					save_field_data = strdup(field_data);
					save_re = re;
					save_proceed = proceed;
					
					re = NULL;
				}

				switch_regex_safe_free(re);

				switch_safe_free(field_expanded);
				switch_safe_free(expression_expanded);
				
			}

			if (xor) {
				if (pass == 1) {
					anti_action = SWITCH_FALSE;
				}
			} else {
				if ((all && !fail) || (!all && pass)) {
					anti_action = SWITCH_FALSE; 
				}
			}

			switch_safe_free(field_expanded);
			switch_safe_free(expression_expanded);
			
		} else {
			if ((xexpression = switch_xml_child(xcond, "expression"))) {
				expression = switch_str_nil(xexpression->txt);
			} else {
				expression = (char *) switch_xml_attr_soft(xcond, "expression");
			}

			if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
				expression_expanded = NULL;
			} else {
				expression = expression_expanded;
			}
			
			if (field) {
				if (strchr(field, '$')) {
					if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
						field_expanded = NULL;
						field_data = field;
					} else {
						field_data = field_expanded;
					}
				} else {
					field_data = switch_caller_get_field_by_name(caller_profile, field);
				}
				if (!field_data) {
					field_data = "";
				}

				if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", space,
									  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
					anti_action = SWITCH_FALSE;
				} else {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", space,
									  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
				}
			} else if (time_match == -1) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "%sDialplan: %s Absolute Condition [%s]\n", space,
								  switch_channel_get_name(channel), exten_name);
				anti_action = SWITCH_FALSE;
				proceed = 1;
			}

		}

		if (save_re) {
			re = save_re;
			save_re = NULL;
			
			expression = expression_expanded = save_expression;
			save_expression = NULL;
			field_data = field_expanded = save_field_data;
			field = (char *) field_data;
			save_field_data = NULL;
			proceed = save_proceed;
		}


		if (anti_action) {
			for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
				const char *application = switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				const char *data;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}

				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s ANTI-Action %s(%s) %s\n", space,
									  switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, data);
					}
				}
				proceed = 1;
			}
		} else {
			if (field && strchr(expression, '(')) {
				switch_channel_set_variable(channel, "DP_MATCH", NULL);
				switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_var_callback, session);
			}

			for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
				char *application = (char *) switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				char *data = NULL;
				char *substituted = NULL;
				uint32_t len = 0;
				char *app_data = NULL;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (field && strchr(expression, '(')) {
					len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
					if (!(substituted = malloc(len))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
					memset(substituted, 0, len);
					switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
					app_data = substituted;
				} else {
					app_data = data;
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}
				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Action %s(%s) %s\n", space,
									  switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, app_data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, app_data);
					}
				}
				switch_safe_free(substituted);
			}
		}
		switch_regex_safe_free(re);

		if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
			 (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
			break;
		}
	}

  done:
	switch_regex_safe_free(re);
	switch_safe_free(field_expanded);
	switch_safe_free(expression_expanded);

	if (!req_nest) proceed = 1;

	return proceed;
}
コード例 #6
0
ファイル: mod_sms.c プロジェクト: DastanIqbal/FreeSWITCH
static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_t **extension)
{
	switch_xml_t xcond, xaction, xexpression;
	char *exten_name = (char *) switch_xml_attr(xexten, "name");
	int proceed = 0;
	char *expression_expanded = NULL, *field_expanded = NULL;
	switch_regex_t *re = NULL;
	const char *to = switch_event_get_header(event, "to");
	const char *tzoff = NULL, *tzname = NULL;
	int offset = 0;

	check_tz();

	if (!to) {
		to = "nobody";
	}

	if (!exten_name) {
		exten_name = "_anon_";
	}

	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
		char *field = NULL;
		char *do_break_a = NULL;
		char *expression = NULL;
		const char *field_data = NULL;
		int ovector[30];
		switch_bool_t anti_action = SWITCH_TRUE;
		break_t do_break_i = BREAK_ON_FALSE;
		int time_match;

		check_tz();
		time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname);

		switch_safe_free(field_expanded);
		switch_safe_free(expression_expanded);

		if (switch_xml_child(xcond, "condition")) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n");
			proceed = 1;
			goto done;
		}

		field = (char *) switch_xml_attr(xcond, "field");

		if ((xexpression = switch_xml_child(xcond, "expression"))) {
			expression = switch_str_nil(xexpression->txt);
		} else {
			expression = (char *) switch_xml_attr_soft(xcond, "expression");
		}

		if ((expression_expanded = switch_event_expand_headers(event, expression)) == expression) {
			expression_expanded = NULL;
		} else {
			expression = expression_expanded;
		}

		if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
			if (!strcasecmp(do_break_a, "on-true")) {
				do_break_i = BREAK_ON_TRUE;
			} else if (!strcasecmp(do_break_a, "on-false")) {
				do_break_i = BREAK_ON_FALSE;
			} else if (!strcasecmp(do_break_a, "always")) {
				do_break_i = BREAK_ALWAYS;
			} else if (!strcasecmp(do_break_a, "never")) {
				do_break_i = BREAK_NEVER;
			} else {
				do_break_a = NULL;
			}
		}

		if (time_match == 1) {
			switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
							  "Chatplan: %s Date/Time Match (PASS) [%s] break=%s\n",
							  to, exten_name, do_break_a ? do_break_a : "on-false");
			anti_action = SWITCH_FALSE;
		} else if (time_match == 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
							  "Chatplan: %s Date/Time Match (FAIL) [%s] break=%s\n",
							  to, exten_name, do_break_a ? do_break_a : "on-false");
		}

		if (field) {
			if (strchr(field, '$')) {
				if ((field_expanded = switch_event_expand_headers(event, field)) == field) {
					field_expanded = NULL;
					field_data = field;
				} else {
					field_data = field_expanded;
				}
			} else {
				field_data = switch_event_get_header(event, field);
			}
			if (!field_data) {
				field_data = "";
			}

			if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
				switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
								  "Chatplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
								  to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
				anti_action = SWITCH_FALSE;
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
								  "Chatplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
								  to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
			}
		} else if (time_match == -1) {
			switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
							  "Chatplan: %s Absolute Condition [%s]\n", to, exten_name);
			anti_action = SWITCH_FALSE;
		}

		if (anti_action) {
			for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
				const char *application = switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				const char *data;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (!*extension) {
					if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
						abort();
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}

				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
							"Chatplan: %s ANTI-Action %s(%s) %s\n", to, application, data, xinline ? "INLINE" : "");

					if (xinline) {
						switch_core_execute_chat_app(event, application, data);
					} else {
						switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(data) ? "__undef" : data);
					}
				}
				proceed = 1;
			}
		} else {
			if (field && strchr(expression, '(')) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DP_MATCH", NULL);
				switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_event_header_callback, event);
			}

			for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
				char *application = (char *) switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				char *data = NULL;
				char *substituted = NULL;
				uint32_t len = 0;
				char *app_data = NULL;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (field && strchr(expression, '(')) {
					len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
					if (!(substituted = (char *) malloc(len))) {
						abort();
					}
					memset(substituted, 0, len);
					switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
					app_data = substituted;
				} else {
					app_data = data;
				}

				if (!*extension) {
					if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
						abort();
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}
				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
							"Chatplan: %s Action %s(%s) %s\n", to, application, app_data, xinline ? "INLINE" : "");

					if (xinline) {
						switch_core_execute_chat_app(event, application, app_data);
					} else {
						switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(app_data) ? "__undef" : app_data);
					}
				}
				switch_safe_free(substituted);
			}
		}
		switch_regex_safe_free(re);

		if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
			 (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
			break;
		}
	}

  done:
	switch_regex_safe_free(re);
	switch_safe_free(field_expanded);
	switch_safe_free(expression_expanded);
	return proceed;
}
コード例 #7
0
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
{
	switch_xml_t xcond, xaction, xexpression;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	char *exten_name = (char *) switch_xml_attr(xexten, "name");
	int proceed = 0;
	char *expression_expanded = NULL, *field_expanded = NULL;
	switch_regex_t *re = NULL;

	if (!exten_name) {
		exten_name = "_anon_";
	}

	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
		char *field = NULL;
		char *do_break_a = NULL;
		char *expression = NULL;
		const char *field_data = NULL;
		int ovector[30];
		switch_bool_t anti_action = SWITCH_TRUE;
		break_t do_break_i = BREAK_ON_FALSE;

		int time_match = switch_xml_std_datetime_check(xcond);

		switch_safe_free(field_expanded);
		switch_safe_free(expression_expanded);

		if (switch_xml_child(xcond, "condition")) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n");
			proceed = 1;
			goto done;
		}

		field = (char *) switch_xml_attr(xcond, "field");

		if ((xexpression = switch_xml_child(xcond, "expression"))) {
			expression = switch_str_nil(xexpression->txt);
		} else {
			expression = (char *) switch_xml_attr_soft(xcond, "expression");
		}

		if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
			expression_expanded = NULL;
		} else {
			expression = expression_expanded;
		}

		if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
			if (!strcasecmp(do_break_a, "on-true")) {
				do_break_i = BREAK_ON_TRUE;
			} else if (!strcasecmp(do_break_a, "on-false")) {
				do_break_i = BREAK_ON_FALSE;
			} else if (!strcasecmp(do_break_a, "always")) {
				do_break_i = BREAK_ALWAYS;
			} else if (!strcasecmp(do_break_a, "never")) {
				do_break_i = BREAK_NEVER;
			} else {
				do_break_a = NULL;
			}
		}

		if (time_match == 1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Date/Time Match (PASS) [%s] break=%s\n",
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
			anti_action = SWITCH_FALSE;
		} else if (time_match == 0) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Date/Time Match (FAIL) [%s] break=%s\n",
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
		}

		if (field) {
			if (strchr(field, '$')) {
				if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
					field_expanded = NULL;
					field_data = field;
				} else {
					field_data = field_expanded;
				}
			} else {
				field_data = switch_caller_get_field_by_name(caller_profile, field);
			}
			if (!field_data) {
				field_data = "";
			}

			if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
								  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
				anti_action = SWITCH_FALSE;
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
								  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
			}
		} else if (time_match == -1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name);
			anti_action = SWITCH_FALSE;
		}

		if (anti_action) {
			for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
				const char *application = switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				const char *data;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}

				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							"Dialplan: %s ANTI-Action %s(%s) %s\n", switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, data);
					}
				}
				proceed = 1;
			}
		} else {
			for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
				char *application = (char *) switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				char *data = NULL;
				char *substituted = NULL;
				uint32_t len = 0;
				char *app_data = NULL;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (field && strchr(expression, '(')) {
					len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
					if (!(substituted = malloc(len))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
					memset(substituted, 0, len);
					switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
					app_data = substituted;
				} else {
					app_data = data;
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}
				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							"Dialplan: %s Action %s(%s) %s\n", switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, app_data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, app_data);
					}
				}
				switch_safe_free(substituted);
			}
		}
		switch_regex_safe_free(re);

		if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
			 (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
			break;
		}
	}

  done:
	switch_regex_safe_free(re);
	switch_safe_free(field_expanded);
	switch_safe_free(expression_expanded);
	return proceed;
}