示例#1
0
static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
{
	struct ast_exten *e;
	struct ast_include *i;
	struct ast_context *c2;

	for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
		if (ast_extension_match(ast_get_extension_name(e), exten)) {
			int needmatch = ast_get_extension_matchcid(e);
			if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
				(!needmatch)) {
				/* This is the matching extension we want */
				struct ast_exten *p;
				for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
					if (priority != ast_get_extension_priority(p))
						continue;
					return p;
				}
			}
		}
	}

	/* No match; run through includes */
	for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
		for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
			if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
				e = find_matching_priority(c2, exten, priority, callerid);
				if (e)
					return e;
			}
		}
	}
	return NULL;
}
示例#2
0
static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
	LOOPBACK_COMMON;
	res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
	if (newpattern && !ast_extension_match(newpattern, exten))
		res = 0;
	return res;
}
static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
	LOOPBACK_COMMON;
	res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
	/* XXX hmmm... res is overridden ? */
	if (newpattern && !ast_extension_match(newpattern, exten))
		res = -1;
	return res;
}
示例#4
0
int misdn_cfg_is_msn_valid (int port, char* msn)
{
	int re = 0;
	struct msn_list *iter;

	if (!misdn_cfg_is_port_valid(port)) {
		ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
		return 0;
	}

	misdn_cfg_lock();
	if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
		iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
	else
		iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
	for (; iter; iter = iter->next) 
		if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
			re = 1;
			break;
		}
	misdn_cfg_unlock();

	return re;
}
示例#5
0
/*! \brief
 * the string is 'prefix:data' or prefix:fmt:data'
 * with ':' being invalid in strings.
 */
static int do_say(say_args_t *a, const char *s, const char *options, int depth)
{
	struct ast_variable *v;
	char *lang, *x, *rule = NULL;
	int ret = 0;   
	struct varshead head = { .first = NULL, .last = NULL };
	struct ast_var_t *n;

	ast_debug(2, "string <%s> depth <%d>\n", s, depth);
	if (depth++ > 10) {
		ast_log(LOG_WARNING, "recursion too deep, exiting\n");
		return -1;
	} else if (!say_cfg) {
		ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);
		return -1;
	}

	/* scan languages same as in file.c */
	if (a->language == NULL)
		a->language = "en";     /* default */
	ast_debug(2, "try <%s> in <%s>\n", s, a->language);
	lang = ast_strdupa(a->language);
	for (;;) {
		for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {
			if (ast_extension_match(v->name, s)) {
				rule = ast_strdupa(v->value);
				break;
			}
		}
		if (rule)
			break;
		if ( (x = strchr(lang, '_')) )
			*x = '\0';      /* try without suffix */
		else if (strcmp(lang, "en"))
			lang = "en";    /* last resort, try 'en' if not done yet */
		else
			break;
	}
	if (!rule)
		return 0;

	/* skip up to two prefixes to get the value */
	if ( (x = strchr(s, ':')) )
		s = x + 1;
	if ( (x = strchr(s, ':')) )
		s = x + 1;
	ast_debug(2, "value is <%s>\n", s);
	n = ast_var_assign("SAY", s);
	if (!n) {
		ast_log(LOG_ERROR, "Memory allocation error in do_say\n");
		return -1;
	}
	AST_LIST_INSERT_HEAD(&head, n, entries);

	/* scan the body, one piece at a time */
	while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */
		char fn[128];
		const char *p, *fmt, *data; /* format and data pointers */

		/* prepare a decent file name */
		x = ast_skip_blanks(x);
		ast_trim_blanks(x);

		/* replace variables */
		pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
		ast_debug(2, "doing [%s]\n", fn);

		/* locate prefix and data, if any */
		fmt = strchr(fn, ':');
		if (!fmt || fmt == fn)	{	/* regular filename */
			ret = s_streamwait3(a, fn);
			continue;
		}
		fmt++;
		data = strchr(fmt, ':');	/* colon before data */
		if (!data || data == fmt) {	/* simple prefix-fmt */
			ret = do_say(a, fn, options, depth);
			continue;
		}
		/* prefix:fmt:data */
		for (p = fmt; p < data && ret <= 0; p++) {
			char fn2[sizeof(fn)];
			if (*p == ' ' || *p == '\t')	/* skip blanks */
				continue;
			if (*p == '\'') {/* file name - we trim them */
				char *y;
				strcpy(fn2, ast_skip_blanks(p+1));	/* make a full copy */
				y = strchr(fn2, '\'');
				if (!y) {
					p = data;	/* invalid. prepare to end */
					break;
				}
				*y = '\0';
				ast_trim_blanks(fn2);
				p = strchr(p+1, '\'');
				ret = s_streamwait3(a, fn2);
			} else {
				int l = fmt-fn;
				strcpy(fn2, fn); /* copy everything */
				/* after prefix, append the format */
				fn2[l++] = *p;
				strcpy(fn2 + l, data);
				ret = do_say(a, fn2, options, depth);
			}
			
			if (ret) {
				break;
			}
		}
	}
	ast_var_delete(n);
	return ret;
}
示例#6
0
/*!
 * \brief Locate an extensions and optionally push the matching function on the
 * stack
 *
 * \param L the lua_State to use
 * \param context the context to look in
 * \param exten the extension to look up
 * \param priority the priority to check, '1' is the only valid priority
 * \param func the calling func, used to adjust matching behavior between,
 * match, canmatch, and matchmore
 * \param push_func whether or not to push the lua function for the given
 * extension onto the stack
 */
static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
{
	int context_table, context_order_table, i;

	ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
	if (priority != 1)
		return 0;

	/* load the 'extensions' table */
	lua_getglobal(L, "extensions");
	if (lua_isnil(L, -1)) {
		ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
		lua_pop(L, 1);
		return 0;
	}

	/* load the given context */
	lua_getfield(L, -1, context);
	if (lua_isnil(L, -1)) {
		lua_pop(L, 2);
		return 0;
	}

	/* remove the extensions table */
	lua_remove(L, -2);

	context_table = lua_gettop(L);

	/* load the extensions order table for this context */
	lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
	lua_getfield(L, -1, context);

	lua_remove(L, -2);  /* remove the extensions order table */

	context_order_table = lua_gettop(L);
	
	/* step through the extensions looking for a match */
	for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
		int e_index_copy, match = 0;
		const char *e;

		lua_pushinteger(L, i);
		lua_gettable(L, context_order_table);
		lua_gettop(L);

		/* copy the key at the top of the stack for use later */
		lua_pushvalue(L, -1);
		e_index_copy = lua_gettop(L);

		if (!(e = lua_tostring(L, e_index_copy))) {
			lua_pop(L, 2);
			continue;
		}

		/* make sure this is not the 'include' extension */
		if (!strcasecmp(e, "include")) {
			lua_pop(L, 2);
			continue;
		}

		if (func == &matchmore)
			match = ast_extension_close(e, exten, E_MATCHMORE);
		else if (func == &canmatch)
			match = ast_extension_close(e, exten, E_CANMATCH);
		else
			match = ast_extension_match(e, exten);

		/* the extension matching functions return 0 on fail, 1 on
		 * match, 2 on earlymatch */

		if (!match) {
			/* pop the copy and the extension */
			lua_pop(L, 2);
			continue;	/* keep trying */
		}

		if (func == &matchmore && match == 2) {
			/* We match an extension ending in '!'. The decision in
			 * this case is final and counts as no match. */
			lua_pop(L, 4);
			return 0;
		}

		/* remove the context table, the context order table, the
		 * extension, and the extension copy (or replace the extension
		 * with the corresponding function) */
		if (push_func) {
			lua_pop(L, 1);  /* pop the copy */
			lua_gettable(L, context_table);
			lua_insert(L, -3);
			lua_pop(L, 2);
		} else {
			lua_pop(L, 4);
		}

		return 1;
	}

	/* load the includes for this context */
	lua_getfield(L, context_table, "include");
	if (lua_isnil(L, -1)) {
		lua_pop(L, 3);
		return 0;
	}

	/* remove the context and the order table*/
	lua_remove(L, context_order_table);
	lua_remove(L, context_table);

	/* Now try any includes we have in this context */
	for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
		const char *c = lua_tostring(L, -1);
		if (!c)
			continue;

		if (lua_find_extension(L, c, exten, priority, func, push_func)) {
			/* remove the value, the key, and the includes table
			 * from the stack.  Leave the function behind if
			 * necessary */

			if (push_func)
				lua_insert(L, -4);

			lua_pop(L, 3);
			return 1;
		}
	}

	/* pop the includes table */
	lua_pop(L, 1);
	return 0;
}
/*!
 * \brief Locate an extensions and optionally push the matching function on the
 * stack
 *
 * \param L the lua_State to use
 * \param context the context to look in
 * \param exten the extension to look up
 * \param priority the priority to check, '1' is the only valid priority
 * \param func the calling func, used to adjust matching behavior between,
 * match, canmatch, and matchmore
 * \param push_func whether or not to push the lua function for the given
 * extension onto the stack
 */
static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
{
	int context_table, context_order_table, i;

	ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
	if (priority != 1)
		return 0;

	/* load the 'extensions' table */
	lua_getglobal(L, "extensions");
	if (lua_isnil(L, -1)) {
		ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
		lua_pop(L, 1);
		return 0;
	}

	/* load the given context */
	lua_getfield(L, -1, context);
	if (lua_isnil(L, -1)) {
		lua_pop(L, 2);
		return 0;
	}

	/* remove the extensions table */
	lua_remove(L, -2);

	context_table = lua_gettop(L);

	/* load the extensions order table for this context */
	lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
	lua_getfield(L, -1, context);

	lua_remove(L, -2);  /* remove the extensions order table */

	context_order_table = lua_gettop(L);

	/* step through the extensions looking for a match */
#if LUA_VERSION_NUM < 502
	for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
#else
	for (i = 1; i < lua_rawlen(L, context_order_table) + 1; i++) {
#endif
		int e_index_copy, match = 0;
		const char *e;

		lua_pushinteger(L, i);
		lua_gettable(L, context_order_table);
		lua_gettop(L);

		/* copy the key at the top of the stack for use later */
		lua_pushvalue(L, -1);
		e_index_copy = lua_gettop(L);

		if (!(e = lua_tostring(L, e_index_copy))) {
			lua_pop(L, 2);
			continue;
		}

		/* make sure this is not the 'include' extension */
		if (!strcasecmp(e, "include")) {
			lua_pop(L, 2);
			continue;
		}

		if (func == &matchmore)
			match = ast_extension_close(e, exten, E_MATCHMORE);
		else if (func == &canmatch)
			match = ast_extension_close(e, exten, E_CANMATCH);
		else
			match = ast_extension_match(e, exten);

		/* the extension matching functions return 0 on fail, 1 on
		 * match, 2 on earlymatch */

		if (!match) {
			/* pop the copy and the extension */
			lua_pop(L, 2);
			continue;	/* keep trying */
		}

		if (func == &matchmore && match == 2) {
			/* We match an extension ending in '!'. The decision in
			 * this case is final and counts as no match. */
			lua_pop(L, 4);
			return 0;
		}

		/* remove the context table, the context order table, the
		 * extension, and the extension copy (or replace the extension
		 * with the corresponding function) */
		if (push_func) {
			lua_pop(L, 1);  /* pop the copy */
			lua_gettable(L, context_table);
			lua_insert(L, -3);
			lua_pop(L, 2);
		} else {
			lua_pop(L, 4);
		}

		return 1;
	}

	/* load the includes for this context */
	lua_getfield(L, context_table, "include");
	if (lua_isnil(L, -1)) {
		lua_pop(L, 3);
		return 0;
	}

	/* remove the context and the order table*/
	lua_remove(L, context_order_table);
	lua_remove(L, context_table);

	/* Now try any includes we have in this context */
	for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
		const char *c = lua_tostring(L, -1);
		if (!c)
			continue;

		if (lua_find_extension(L, c, exten, priority, func, push_func)) {
			/* remove the value, the key, and the includes table
			 * from the stack.  Leave the function behind if
			 * necessary */

			if (push_func)
				lua_insert(L, -4);

			lua_pop(L, 3);
			return 1;
		}
	}

	/* pop the includes table */
	lua_pop(L, 1);
	return 0;
}

static struct ast_switch lua_switch = {
        .name		= "Lua",
        .description	= "Lua PBX Switch",
        .exists		= exists,
        .canmatch	= canmatch,
        .exec		= exec,
        .matchmore	= matchmore,
};


static int load_or_reload_lua_stuff(void)
{
	int res = AST_MODULE_LOAD_SUCCESS;

	lua_State *L = luaL_newstate();
	if (!L) {
		ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
		return AST_MODULE_LOAD_DECLINE;
	}

	if (lua_reload_extensions(L)) {
		const char *error = lua_tostring(L, -1);
		ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
		res = AST_MODULE_LOAD_DECLINE;
	}

	lua_close(L);
	return res;
}

static int unload_module(void)
{
	ast_context_destroy(NULL, registrar);
	ast_unregister_switch(&lua_switch);
	lua_free_extensions();
	return 0;
}