mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	(closes issue #6019)
Reported by: ssokol
 Patches: 
       20080304__bug6019.diff.txt uploaded by Corydon76 (license 14)
 Tested by: putnopvut
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@107231 65c4cc65-6c06-0410-ace0-fbb531ad65f3
			
			
This commit is contained in:
		| @@ -839,6 +839,11 @@ int pbx_set_autofallthrough(int newval); | ||||
|   the old linear-search algorithm.  Returns previous value. */ | ||||
| int pbx_set_extenpatternmatchnew(int newval); | ||||
|  | ||||
| /*! Set "overrideswitch" field.  If set and of nonzero length, all contexts | ||||
|  * will be tried directly through the named switch prior to any other | ||||
|  * matching within that context. */ | ||||
| void pbx_set_overrideswitch(const char *newval); | ||||
|  | ||||
| /*! | ||||
|  * \note This function will handle locking the channel as needed. | ||||
|  */ | ||||
|   | ||||
							
								
								
									
										94
									
								
								main/pbx.c
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								main/pbx.c
									
									
									
									
									
								
							| @@ -123,6 +123,8 @@ AST_APP_OPTIONS(waitexten_opts, { | ||||
| struct ast_context; | ||||
| struct ast_app; | ||||
|  | ||||
| AST_THREADSTORAGE(switch_data); | ||||
|  | ||||
| /*! | ||||
|    \brief ast_exten: An extension | ||||
| 	The dialplan is saved as a linked list with each context | ||||
| @@ -166,7 +168,6 @@ struct ast_sw { | ||||
| 	char *data;				/*!< Data load */ | ||||
| 	int eval; | ||||
| 	AST_LIST_ENTRY(ast_sw) list; | ||||
| 	char *tmpdata; | ||||
| 	char stuff[0]; | ||||
| }; | ||||
|  | ||||
| @@ -413,6 +414,7 @@ static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE; | ||||
|  | ||||
| static int autofallthrough = 1; | ||||
| static int extenpatternmatchnew = 0; | ||||
| static char *overrideswitch = NULL; | ||||
|  | ||||
| /*! \brief Subscription for device state change events */ | ||||
| static struct ast_event_sub *device_state_sub; | ||||
| @@ -1644,6 +1646,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, | ||||
| 	struct ast_sw *sw = NULL; | ||||
| 	struct ast_exten pattern = {NULL, }; | ||||
| 	struct scoreboard score = {0, }; | ||||
| 	struct ast_str *tmpdata = NULL; | ||||
|  | ||||
| 	pattern.label = label; | ||||
| 	pattern.priority = priority; | ||||
| @@ -1707,6 +1710,65 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, | ||||
| 	log_match_char_tree(tmp->pattern_tree, "::  "); | ||||
| #endif | ||||
|  | ||||
| 	do { | ||||
| 		if (!ast_strlen_zero(overrideswitch)) { | ||||
| 			char *osw = ast_strdupa(overrideswitch), *name; | ||||
| 			struct ast_switch *asw; | ||||
| 			ast_switch_f *aswf = NULL; | ||||
| 			char *datap; | ||||
| 			int eval = 0; | ||||
|  | ||||
| 			name = strsep(&osw, "/"); | ||||
| 			asw = pbx_findswitch(name); | ||||
|  | ||||
| 			if (!asw) { | ||||
| 				ast_log(LOG_WARNING, "No such switch '%s'\n", name); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (osw && strchr(osw, '$')) { | ||||
| 				eval = 1; | ||||
| 			} | ||||
|  | ||||
| 			if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { | ||||
| 				ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); | ||||
| 				break; | ||||
| 			} else if (eval) { | ||||
| 				/* Substitute variables now */ | ||||
| 				pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); | ||||
| 				datap = tmpdata->str; | ||||
| 			} else { | ||||
| 				datap = osw; | ||||
| 			} | ||||
|  | ||||
| 			/* equivalent of extension_match_core() at the switch level */ | ||||
| 			if (action == E_CANMATCH) | ||||
| 				aswf = asw->canmatch; | ||||
| 			else if (action == E_MATCHMORE) | ||||
| 				aswf = asw->matchmore; | ||||
| 			else /* action == E_MATCH */ | ||||
| 				aswf = asw->exists; | ||||
| 			if (!aswf) { | ||||
| 				res = 0; | ||||
| 			} else { | ||||
| 				if (chan) { | ||||
| 					ast_autoservice_start(chan); | ||||
| 				} | ||||
| 				res = aswf(chan, context, exten, priority, callerid, datap); | ||||
| 				if (chan) { | ||||
| 					ast_autoservice_stop(chan); | ||||
| 				} | ||||
| 			} | ||||
| 			if (res) {	/* Got a match */ | ||||
| 				q->swo = asw; | ||||
| 				q->data = datap; | ||||
| 				q->foundcontext = context; | ||||
| 				/* XXX keep status = STATUS_NO_CONTEXT ? */ | ||||
| 				return NULL; | ||||
| 			} | ||||
| 		} | ||||
| 	} while (0); | ||||
|  | ||||
| 	if (extenpatternmatchnew) { | ||||
| 		new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid); | ||||
| 		eroot = score.exten; | ||||
| @@ -1828,8 +1890,13 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, | ||||
| 		} | ||||
| 		/* Substitute variables now */ | ||||
| 		 | ||||
| 		if (sw->eval) | ||||
| 			pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1); | ||||
| 		if (sw->eval) { | ||||
| 			if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { | ||||
| 				ast_log(LOG_WARNING, "Can't evaluate switch?!"); | ||||
| 				continue; | ||||
| 			} | ||||
| 			pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); | ||||
| 		} | ||||
|  | ||||
| 		/* equivalent of extension_match_core() at the switch level */ | ||||
| 		if (action == E_CANMATCH) | ||||
| @@ -1838,7 +1905,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, | ||||
| 			aswf = asw->matchmore; | ||||
| 		else /* action == E_MATCH */ | ||||
| 			aswf = asw->exists; | ||||
| 		datap = sw->eval ? sw->tmpdata : sw->data; | ||||
| 		datap = sw->eval ? tmpdata->str : sw->data; | ||||
| 		if (!aswf) | ||||
| 			res = 0; | ||||
| 		else { | ||||
| @@ -3618,6 +3685,18 @@ int pbx_set_extenpatternmatchnew(int newval) | ||||
| 	return oldval; | ||||
| } | ||||
|  | ||||
| void pbx_set_overrideswitch(const char *newval) | ||||
| { | ||||
| 	if (overrideswitch) { | ||||
| 		ast_free(overrideswitch); | ||||
| 	} | ||||
| 	if (!ast_strlen_zero(newval)) { | ||||
| 		overrideswitch = ast_strdup(newval); | ||||
| 	} else { | ||||
| 		overrideswitch = NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \brief lookup for a context with a given name, | ||||
|  * \retval with conlock held if found. | ||||
| @@ -5781,11 +5860,6 @@ int ast_context_add_switch2(struct ast_context *con, const char *value, | ||||
| 	if (data) | ||||
| 		length += strlen(data); | ||||
| 	length++; | ||||
| 	if (eval) { | ||||
| 		/* Create buffer for evaluation of variables */ | ||||
| 		length += SWITCH_DATA_LENGTH; | ||||
| 		length++; | ||||
| 	} | ||||
|  | ||||
| 	/* allocate new sw structure ... */ | ||||
| 	if (!(new_sw = ast_calloc(1, length))) | ||||
| @@ -5803,8 +5877,6 @@ int ast_context_add_switch2(struct ast_context *con, const char *value, | ||||
| 		strcpy(new_sw->data, ""); | ||||
| 		p++; | ||||
| 	} | ||||
| 	if (eval) | ||||
| 		new_sw->tmpdata = p; | ||||
| 	new_sw->eval	  = eval; | ||||
| 	new_sw->registrar = registrar; | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,7 @@ static int write_protect_config = 1; | ||||
| static int autofallthrough_config = 1; | ||||
| static int clearglobalvars_config = 0; | ||||
| static int extenpatternmatchnew_config = 0; | ||||
| static char *overrideswitch_config = NULL; | ||||
|  | ||||
| AST_MUTEX_DEFINE_STATIC(save_dialplan_lock); | ||||
|  | ||||
| @@ -701,7 +702,7 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a) | ||||
|  */ | ||||
| static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	char filename[256]; | ||||
| 	char filename[256], overrideswitch[256] = ""; | ||||
| 	struct ast_context *c; | ||||
| 	struct ast_config *cfg; | ||||
| 	struct ast_variable *v; | ||||
| @@ -781,11 +782,15 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a | ||||
| 	} | ||||
|  | ||||
| 	/* fireout general info */ | ||||
| 	fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\nextenpatternmatchnew=%s\n\n", | ||||
| 	if (overrideswitch_config) { | ||||
| 		snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config); | ||||
| 	} | ||||
| 	fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n", | ||||
| 		static_config ? "yes" : "no", | ||||
| 		write_protect_config ? "yes" : "no", | ||||
|                 autofallthrough_config ? "yes" : "no", | ||||
| 				clearglobalvars_config ? "yes" : "no", | ||||
| 				overrideswitch_config ? overrideswitch : "", | ||||
| 				extenpatternmatchnew_config ? "yes" : "no"); | ||||
|  | ||||
| 	if ((v = ast_variable_browse(cfg, "globals"))) { | ||||
| @@ -1353,6 +1358,9 @@ static int unload_module(void) | ||||
| { | ||||
| 	if (static_config && !write_protect_config) | ||||
| 		ast_cli_unregister(&cli_dialplan_save); | ||||
| 	if (overrideswitch_config) { | ||||
| 		ast_free(overrideswitch_config); | ||||
| 	} | ||||
| 	ast_cli_unregister_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry)); | ||||
| 	ast_context_destroy(NULL, registrar); | ||||
| 	return 0; | ||||
| @@ -1369,7 +1377,7 @@ static int pbx_load_config(const char *config_file) | ||||
| 	struct ast_variable *v; | ||||
| 	const char *cxt; | ||||
| 	const char *aft; | ||||
| 	const char *newpm; | ||||
| 	const char *newpm, *ovsw; | ||||
| 	struct ast_flags config_flags = { 0 }; | ||||
| 	cfg = ast_config_load(config_file, config_flags); | ||||
| 	if (!cfg) | ||||
| @@ -1383,7 +1391,16 @@ static int pbx_load_config(const char *config_file) | ||||
| 	if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew"))) | ||||
| 		extenpatternmatchnew_config = ast_true(newpm); | ||||
| 	clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars")); | ||||
| 	 | ||||
| 	if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) { | ||||
| 		if (overrideswitch_config) { | ||||
| 			ast_free(overrideswitch_config); | ||||
| 		} | ||||
| 		if (!ast_strlen_zero(ovsw)) { | ||||
| 			overrideswitch_config = ast_strdup(ovsw); | ||||
| 		} else { | ||||
| 			overrideswitch_config = NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))  | ||||
| 		ast_copy_string(userscontext, cxt, sizeof(userscontext)); | ||||
| @@ -1640,6 +1657,7 @@ static int pbx_load_module(void) | ||||
| 	for (con = NULL; (con = ast_walk_contexts(con));) | ||||
| 		ast_context_verify_includes(con); | ||||
|  | ||||
| 	pbx_set_overrideswitch(overrideswitch_config); | ||||
| 	pbx_set_autofallthrough(autofallthrough_config); | ||||
| 	pbx_set_extenpatternmatchnew(extenpatternmatchnew_config); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user